mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-01 17:01:56 +01:00
Add configurable fix for TNT cannnons.
This attempts to revert cannoning mechanics to pre-1.8 behavior. A huge thanks to TheIceAP who championed almost every fix in this patch. Another shoutout to Jebediah Smith from SportBukkit for the velocity update patch which mostly fixes the client issue of TNT moving in water.
This commit is contained in:
parent
7d15ab73ad
commit
55b9d1c093
2 changed files with 352 additions and 2 deletions
350
Spigot-Server-Patches/Configurable-TNT-cannon-fix.patch
Normal file
350
Spigot-Server-Patches/Configurable-TNT-cannon-fix.patch
Normal file
|
@ -0,0 +1,350 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Iceee <andrew@opticgaming.tv>
|
||||
Date: Thu, 4 Jun 2015 13:55:02 -0700
|
||||
Subject: [PATCH] Configurable TNT cannon fix
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockDiodeAbstract extends BlockDirectional {
|
||||
} else {
|
||||
this.b(world, blockposition, iblockdata, 0);
|
||||
world.setAir(blockposition);
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this);
|
||||
+ return;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i = aenumdirection.length;
|
||||
|
||||
@@ -0,0 +0,0 @@ public abstract class BlockDiodeAbstract extends BlockDirectional {
|
||||
|
||||
public void postBreak(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
if (this.N) {
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this);
|
||||
+ return;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i = aenumdirection.length;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
|
||||
public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
if (this.isOn) {
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this);
|
||||
+ return;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i = aenumdirection.length;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneTorch extends BlockTorch {
|
||||
|
||||
public void remove(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
if (this.isOn) {
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this);
|
||||
+ return;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i = aenumdirection.length;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneWire.java b/src/main/java/net/minecraft/server/BlockRedstoneWire.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockRedstoneWire.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockRedstoneWire.java
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block {
|
||||
}
|
||||
|
||||
this.R.add(blockposition);
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ this.R.add(blockposition.shift(EnumDirection.WEST));
|
||||
+ this.R.add(blockposition.shift(EnumDirection.EAST));
|
||||
+ this.R.add(blockposition.shift(EnumDirection.DOWN));
|
||||
+ this.R.add(blockposition.shift(EnumDirection.UP));
|
||||
+ this.R.add(blockposition.shift(EnumDirection.NORTH));
|
||||
+ this.R.add(blockposition.shift(EnumDirection.SOUTH));
|
||||
+ return iblockdata;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i1 = aenumdirection.length;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class BlockRedstoneWire extends Block {
|
||||
private void e(World world, BlockPosition blockposition) {
|
||||
if (world.getType(blockposition).getBlock() == this) {
|
||||
world.applyPhysics(blockposition, this);
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ if (world.paperSpigotConfig.fixCannons) {
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.WEST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.EAST), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.NORTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.SOUTH), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.DOWN), this);
|
||||
+ world.applyPhysics(blockposition.shift(EnumDirection.UP), this);
|
||||
+ return;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
EnumDirection[] aenumdirection = EnumDirection.values();
|
||||
int i = aenumdirection.length;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockTNT.java b/src/main/java/net/minecraft/server/BlockTNT.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockTNT.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockTNT.java
|
||||
@@ -0,0 +0,0 @@ public class BlockTNT extends Block {
|
||||
public void wasExploded(World world, BlockPosition blockposition, Explosion explosion) {
|
||||
if (!world.isClientSide) {
|
||||
org.bukkit.Location loc = explosion.source instanceof EntityTNTPrimed ? ((EntityTNTPrimed) explosion.source).sourceLoc : new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()); // PaperSpigot
|
||||
- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(loc, world, (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.5F), (double) ((float) blockposition.getZ() + 0.5F), explosion.c()); // PaperSpigot - add loc
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ double y = blockposition.getY();
|
||||
+ if (!world.paperSpigotConfig.fixCannons) y += 0.5;
|
||||
+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(loc, world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), explosion.c()); // PaperSpigot - add loc
|
||||
+ // PaperSpigot end
|
||||
|
||||
entitytntprimed.fuseTicks = world.random.nextInt(entitytntprimed.fuseTicks / 4) + entitytntprimed.fuseTicks / 8;
|
||||
world.addEntity(entitytntprimed);
|
||||
@@ -0,0 +0,0 @@ public class BlockTNT extends Block {
|
||||
if (!world.isClientSide) {
|
||||
if (((Boolean) iblockdata.get(BlockTNT.EXPLODE)).booleanValue()) {
|
||||
org.bukkit.Location loc = new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()); // PaperSpigot
|
||||
- EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(loc, world, (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.5F), (double) ((float) blockposition.getZ() + 0.5F), entityliving); // PaperSpigot - add loc
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ double y = blockposition.getY();
|
||||
+ if (!world.paperSpigotConfig.fixCannons) y += 0.5;
|
||||
+ EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(loc, world, (double) ((float) blockposition.getX() + 0.5F), y, (double) ((float) blockposition.getZ() + 0.5F), entityliving); // PaperSpigot - add loc
|
||||
+ // PaperSpigot end
|
||||
|
||||
world.addEntity(entitytntprimed);
|
||||
world.makeSound(entitytntprimed, "game.tnt.primed", 1.0F, 1.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/DispenserRegistry.java b/src/main/java/net/minecraft/server/DispenserRegistry.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/DispenserRegistry.java
|
||||
+++ b/src/main/java/net/minecraft/server/DispenserRegistry.java
|
||||
@@ -0,0 +0,0 @@ public class DispenserRegistry {
|
||||
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ());
|
||||
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
|
||||
|
||||
- BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX() + 0.5, blockposition.getY() + 0.5, blockposition.getZ() + 0.5));
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ double y = blockposition.getY();
|
||||
+ if (!world.paperSpigotConfig.fixCannons) y += 0.5;
|
||||
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX() + 0.5, y, blockposition.getZ() + 0.5));
|
||||
+ // PaperSpigot end
|
||||
if (!BlockDispenser.eventFired) {
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityFallingBlock.java b/src/main/java/net/minecraft/server/EntityFallingBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java
|
||||
@@ -0,0 +0,0 @@ public class EntityFallingBlock extends Entity {
|
||||
public IBlockData getBlock() {
|
||||
return this.block;
|
||||
}
|
||||
+
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ @Override
|
||||
+ public double f(double d0, double d1, double d2) {
|
||||
+ if (!world.paperSpigotConfig.fixCannons) return super.f(d0, d1, d2);
|
||||
+
|
||||
+ double d3 = this.locX - d0;
|
||||
+ double d4 = this.locY + this.getHeadHeight() - d1;
|
||||
+ double d5 = this.locZ - d2;
|
||||
+
|
||||
+ return (double) MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float getHeadHeight() {
|
||||
+ return world.paperSpigotConfig.fixCannons ? this.length / 2 : super.getHeadHeight();
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTNTPrimed.java b/src/main/java/net/minecraft/server/EntityTNTPrimed.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTNTPrimed.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTNTPrimed.java
|
||||
@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity {
|
||||
this.lastY = d1;
|
||||
this.lastZ = d2;
|
||||
this.source = entityliving;
|
||||
+ if (world.paperSpigotConfig.fixCannons) this.motX = this.motZ = 0.0F; // PaperSpigot - Fix cannons
|
||||
}
|
||||
|
||||
protected void h() {}
|
||||
@@ -0,0 +0,0 @@ public class EntityTNTPrimed extends Entity {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ @Override
|
||||
+ public double f(double d0, double d1, double d2) {
|
||||
+ if (!world.paperSpigotConfig.fixCannons) return super.f(d0, d1, d2);
|
||||
+
|
||||
+ double d3 = this.locX - d0;
|
||||
+ double d4 = this.locY + this.getHeadHeight() - d1;
|
||||
+ double d5 = this.locZ - d2;
|
||||
+
|
||||
+ return (double) MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean aL() {
|
||||
+ return !world.paperSpigotConfig.fixCannons && super.aL();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
public float getHeadHeight() {
|
||||
- return 0.0F;
|
||||
+ return world.paperSpigotConfig.fixCannons ? this.length / 2 : 0.0F;
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Author: Jedediah Smith <jedediah@silencegreys.com>
|
||||
+ */
|
||||
+ @Override
|
||||
+ public boolean W() {
|
||||
+ if (!world.paperSpigotConfig.fixCannons) return super.W();
|
||||
+
|
||||
+ // Preserve velocity while calling the super method
|
||||
+ double oldMotX = this.motX;
|
||||
+ double oldMotY = this.motY;
|
||||
+ double oldMotZ = this.motZ;
|
||||
+
|
||||
+ super.W();
|
||||
+
|
||||
+ this.motX = oldMotX;
|
||||
+ this.motY = oldMotY;
|
||||
+ this.motZ = oldMotZ;
|
||||
+
|
||||
+ if (this.inWater) {
|
||||
+ // Send position and velocity updates to nearby players on every tick while the TNT is in water.
|
||||
+ // This does pretty well at keeping their clients in sync with the server.
|
||||
+ EntityTrackerEntry ete = ((WorldServer) this.getWorld()).getTracker().trackedEntities.get(this.getId());
|
||||
+ if (ete != null) {
|
||||
+ PacketPlayOutEntityVelocity velocityPacket = new PacketPlayOutEntityVelocity(this);
|
||||
+ PacketPlayOutEntityTeleport positionPacket = new PacketPlayOutEntityTeleport(this);
|
||||
+
|
||||
+ for (EntityPlayer viewer : ete.trackedPlayers) {
|
||||
+ if ((viewer.locX - this.locX) * (viewer.locY - this.locY) * (viewer.locZ - this.locZ) < 16 * 16) {
|
||||
+ viewer.playerConnection.sendPacket(velocityPacket);
|
||||
+ viewer.playerConnection.sendPacket(positionPacket);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return this.inWater;
|
||||
+ }
|
||||
+ // PaperSpigot end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/Explosion.java
|
||||
+++ b/src/main/java/net/minecraft/server/Explosion.java
|
||||
@@ -0,0 +0,0 @@ public class Explosion {
|
||||
// CraftBukkit end
|
||||
double d14 = EnchantmentProtection.a(entity, d13);
|
||||
|
||||
+ // PaperSpigot start - Fix cannons
|
||||
+ /*
|
||||
entity.motX += d8 * d14;
|
||||
entity.motY += d9 * d14;
|
||||
entity.motZ += d10 * d14;
|
||||
+ */
|
||||
+ // This impulse method sets the dirty flag, so clients will get an immediate velocity update
|
||||
+ entity.g(d8 * d14, d9 * d14, d10 * d14);
|
||||
+ // PaperSpigot end
|
||||
+
|
||||
if (entity instanceof EntityHuman && !((EntityHuman) entity).abilities.isInvulnerable) {
|
||||
this.k.put((EntityHuman) entity, new Vec3D(d8 * d13, d9 * d13, d10 * d13));
|
||||
}
|
||||
diff --git a/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java b/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperSpigotWorldConfig
|
||||
generateVillage = getBoolean( "generator-settings.village", true );
|
||||
generateFlatBedrock = getBoolean( "generator-settings.flat-bedrock", false );
|
||||
}
|
||||
+
|
||||
+ public boolean fixCannons;
|
||||
+ private void fixCannons()
|
||||
+ {
|
||||
+ // TODO: Remove migrations after most users have upgraded.
|
||||
+ if ( PaperSpigotConfig.version < 9 )
|
||||
+ {
|
||||
+ // Migrate default value
|
||||
+
|
||||
+ boolean value = config.getBoolean( "world-settings.default.fix-cannons", false );
|
||||
+ if ( !value ) value = config.getBoolean( "world-settings.default.tnt-gameplay.fix-directional-bias", false );
|
||||
+ if ( !value ) value = !config.getBoolean( "world-settings.default.tnt-gameplay.moves-in-water", true );
|
||||
+ if ( !value ) value = config.getBoolean( "world-settings.default.tnt-gameplay.legacy-explosion-height", false );
|
||||
+ if ( value ) config.set( "world-settings.default.fix-cannons", true );
|
||||
+
|
||||
+ if ( config.contains( "world-settings.default.tnt-gameplay" ) )
|
||||
+ {
|
||||
+ config.getDefaults().set( "world-settings.default.tnt-gameplay", null);
|
||||
+ config.set( "world-settings.default.tnt-gameplay", null );
|
||||
+ }
|
||||
+
|
||||
+ // Migrate world setting
|
||||
+
|
||||
+ value = config.getBoolean( "world-settings." + worldName + ".fix-cannons", false );
|
||||
+ if ( !value ) value = config.getBoolean( "world-settings." + worldName + ".tnt-gameplay.fix-directional-bias", false );
|
||||
+ if ( !value ) value = !config.getBoolean( "world-settings." + worldName + ".tnt-gameplay.moves-in-water", true );
|
||||
+ if ( !value ) value = config.getBoolean( "world-settings." + worldName + ".tnt-gameplay.legacy-explosion-height", false );
|
||||
+ if ( value ) config.set( "world-settings." + worldName + ".fix-cannons", true );
|
||||
+
|
||||
+ if ( config.contains( "world-settings." + worldName + ".tnt-gameplay" ) )
|
||||
+ {
|
||||
+ config.getDefaults().set( "world-settings." + worldName + ".tnt-gameplay", null);
|
||||
+ config.set( "world-settings." + worldName + ".tnt-gameplay", null );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ fixCannons = getBoolean( "fix-cannons", false );
|
||||
+ log( "Fix TNT cannons: " + fixCannons);
|
||||
+ }
|
||||
}
|
||||
--
|
||||
1.9.5.msysgit.1
|
||||
|
|
@ -147,8 +147,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+
|
||||
+ commands = new HashMap<String, Command>();
|
||||
+
|
||||
+ version = getInt( "config-version", 8 );
|
||||
+ set( "config-version", 8 );
|
||||
+ version = getInt( "config-version", 9 );
|
||||
+ set( "config-version", 9 );
|
||||
+ readConfig( PaperSpigotConfig.class, null );
|
||||
+ }
|
||||
+
|
||||
|
|
Loading…
Reference in a new issue