papermc/Spigot-Server-Patches/0054-Configurable-TNT-cannon-fix.patch
Byteflux e82e438855 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.
2015-06-04 14:25:07 -07:00

350 lines
18 KiB
Diff

From 0f429d02717e024c12d5648f37da385520aef72c 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 ee49839..eaf9154 100644
--- a/src/main/java/net/minecraft/server/BlockDiodeAbstract.java
+++ b/src/main/java/net/minecraft/server/BlockDiodeAbstract.java
@@ -72,6 +72,17 @@ 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;
@@ -169,6 +180,17 @@ 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 6a7e7b3..78c6d19 100644
--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
@@ -52,6 +52,17 @@ 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;
@@ -66,6 +77,17 @@ 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 ea87aa5..3e3848e 100644
--- a/src/main/java/net/minecraft/server/BlockRedstoneWire.java
+++ b/src/main/java/net/minecraft/server/BlockRedstoneWire.java
@@ -142,6 +142,17 @@ 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;
@@ -158,6 +169,17 @@ 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 3a0bc4b..a901742 100644
--- a/src/main/java/net/minecraft/server/BlockTNT.java
+++ b/src/main/java/net/minecraft/server/BlockTNT.java
@@ -30,7 +30,11 @@ 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);
@@ -45,7 +49,11 @@ 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 f3858d1..d8e1609 100644
--- a/src/main/java/net/minecraft/server/DispenserRegistry.java
+++ b/src/main/java/net/minecraft/server/DispenserRegistry.java
@@ -519,7 +519,11 @@ 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 a0452ac..8a3fd44 100644
--- a/src/main/java/net/minecraft/server/EntityFallingBlock.java
+++ b/src/main/java/net/minecraft/server/EntityFallingBlock.java
@@ -291,4 +291,22 @@ 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 db33c98..5290767 100644
--- a/src/main/java/net/minecraft/server/EntityTNTPrimed.java
+++ b/src/main/java/net/minecraft/server/EntityTNTPrimed.java
@@ -36,6 +36,7 @@ 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() {}
@@ -156,7 +157,64 @@ 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 fdf886a..a3df604 100644
--- a/src/main/java/net/minecraft/server/Explosion.java
+++ b/src/main/java/net/minecraft/server/Explosion.java
@@ -142,9 +142,16 @@ 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 8338cc6..793f043 100644
--- a/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java
+++ b/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java
@@ -299,4 +299,43 @@ 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