From df69ea8814a446502a0d096f542cbbb6879c80cd Mon Sep 17 00:00:00 2001 From: Travis Watkins Date: Wed, 14 Nov 2012 19:52:40 -0600 Subject: [PATCH] Rework skull dropping. Fixes BUKKIT-2930 and BUKKIT-2820 Skulls need their tile entity in order to create an item correctly when broken unlike every other block. Instead of sprinkling special cases all over the code just override dropNaturally for skulls to read from their tile entity and make sure everything that wants to drop them calls this method before removing the block. There is only one case where this wasn't already true so we end up with much less special casing. --- .../java/net/minecraft/server/BlockSkull.java | 19 ++++++++++++++++--- .../java/net/minecraft/server/Explosion.java | 11 +++-------- .../minecraft/server/ItemInWorldManager.java | 6 ++++-- .../org/bukkit/craftbukkit/CraftWorld.java | 6 +----- .../bukkit/craftbukkit/block/CraftBlock.java | 4 ---- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/main/java/net/minecraft/server/BlockSkull.java b/src/main/java/net/minecraft/server/BlockSkull.java index 968bd9416d..d5fd3ad3d3 100644 --- a/src/main/java/net/minecraft/server/BlockSkull.java +++ b/src/main/java/net/minecraft/server/BlockSkull.java @@ -78,8 +78,21 @@ public class BlockSkull extends BlockContainer { return i; } - // CraftBukkit - drop the item like every other block - // public void dropNaturally(World world, int i, int j, int k, int l, float f, int i1) {} + // CraftBukkit start - special case dropping so we can get info from the tile entity + public void dropNaturally(World world, int i, int j, int k, int l, float f, int i1) { + if (world.random.nextFloat() < f) { + ItemStack itemstack = new ItemStack(Item.SKULL.id, 1, this.getDropData(world, i, j, k)); + TileEntitySkull tileentityskull = (TileEntitySkull) world.getTileEntity(i, j, k); + + if (tileentityskull.getSkullType() == 3 && tileentityskull.getExtraType() != null && tileentityskull.getExtraType().length() > 0) { + itemstack.setTag(new NBTTagCompound()); + itemstack.getTag().setString("SkullOwner", tileentityskull.getExtraType()); + } + + this.b(world, i, j, k, itemstack); + } + } + // CraftBukkit end public void a(World world, int i, int j, int k, int l, EntityHuman entityhuman) { if (entityhuman.abilities.canInstantlyBuild) { @@ -92,7 +105,7 @@ public class BlockSkull extends BlockContainer { public void remove(World world, int i, int j, int k, int l, int i1) { if (!world.isStatic) { - /* CraftBukkit start - don't special code dropping the item + /* CraftBukkit start - drop item in code above, not here if ((i1 & 8) == 0) { ItemStack itemstack = new ItemStack(Item.SKULL.id, 1, this.getDropData(world, i, j, k)); TileEntitySkull tileentityskull = (TileEntitySkull) world.getTileEntity(i, j, k); diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java index c91c95990f..fae57de185 100644 --- a/src/main/java/net/minecraft/server/Explosion.java +++ b/src/main/java/net/minecraft/server/Explosion.java @@ -264,18 +264,13 @@ public class Explosion { // CraftBukkit - stop explosions from putting out fire if (l > 0 && l != Block.FIRE.id) { - // CraftBukkit start - special case skulls, add yield - int data = this.world.getData(i, j, k); - if (l == Block.SKULL.id) { - data = Block.SKULL.getDropData(this.world, i, j, k); - } - Block block = Block.byId[l]; if (block.a(this)) { - block.dropNaturally(this.world, i, j, k, data, event.getYield(), 0); + // CraftBukkit + block.dropNaturally(this.world, i, j, k, this.world.getData(i, j, k), event.getYield(), 0); } - // CraftBukkit end + if (this.world.setRawTypeIdAndData(i, j, k, 0, 0, this.world.isStatic)) { this.world.applyPhysics(i, j, k, 0); } diff --git a/src/main/java/net/minecraft/server/ItemInWorldManager.java b/src/main/java/net/minecraft/server/ItemInWorldManager.java index 389a3ed938..771c05f0e2 100644 --- a/src/main/java/net/minecraft/server/ItemInWorldManager.java +++ b/src/main/java/net/minecraft/server/ItemInWorldManager.java @@ -290,9 +290,11 @@ public class ItemInWorldManager { int l = this.world.getTypeId(i, j, k); if (Block.byId[l] == null) return false; // CraftBukkit - a plugin set block to air without cancelling int i1 = this.world.getData(i, j, k); + // CraftBukkit start - special case skulls, their item data comes from a tile entity - if (l == Block.SKULL.id) { - i1 = Block.SKULL.getDropData(world, i, j, k); + if (l == Block.SKULL.id && !this.isCreative()) { + Block.SKULL.dropNaturally(world, i, j, k, i1, 1.0F, 0); + return this.d(i, j, k); } // CraftBukkit end diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 88245a1531..79ae6d1b61 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1084,11 +1084,7 @@ public class CraftWorld implements World { int blockY = block.getY(); int blockZ = block.getZ(); // following code is lifted from Explosion.a(boolean), and modified - int data = block.getData(); - if (blockId == net.minecraft.server.Block.SKULL.id) { - data = net.minecraft.server.Block.SKULL.getDropData(this.world, blockX, blockY, blockZ); - } - net.minecraft.server.Block.byId[blockId].dropNaturally(this.world, blockX, blockY, blockZ, data, yield, 0); + net.minecraft.server.Block.byId[blockId].dropNaturally(this.world, blockX, blockY, blockZ, block.getData(), yield, 0); block.setType(org.bukkit.Material.AIR); // not sure what this does, seems to have something to do with the 'base' material of a block. // For example, WOODEN_STAIRS does something with WOOD in this method diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java index b1eb4fc6ac..7f7a7fc5e8 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -348,10 +348,6 @@ public class CraftBlock implements Block { boolean result = false; if (block != null) { - if (block.id == net.minecraft.server.Block.SKULL.id) { - data = (byte) block.getDropData(chunk.getHandle().world, x, y, z); - } - block.dropNaturally(chunk.getHandle().world, x, y, z, data, 1.0F, 0); result = true; }