From 767528115e544b31e07f83d349f1ce60d0427cc0 Mon Sep 17 00:00:00 2001 From: alexbegt Date: Fri, 26 May 2017 20:58:28 -0400 Subject: [PATCH] Fix chests crashing users when it goes to sync the top stacks to the client for rendering due to a nbt overflow. (Switched to getNBTShareTag that was added to forge and is used by Refined Storage for it's Storage Blocks) Closes #91 --- build.gradle | 6 +- .../java/cpw/mods/ironchest/CommonProxy.java | 5 + .../mods/ironchest/ContainerIronChest.java | 2 +- .../java/cpw/mods/ironchest/IronChest.java | 14 +- .../mods/ironchest/TileEntityIronChest.java | 129 ++++++------------ .../mods/ironchest/client/ClientProxy.java | 7 + .../network/MessageCrystalChestSync.java | 118 ++++++++++++++++ 7 files changed, 191 insertions(+), 90 deletions(-) create mode 100644 src/main/java/cpw/mods/ironchest/network/MessageCrystalChestSync.java diff --git a/build.gradle b/build.gradle index dc6a0f9..d0852f9 100755 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,7 @@ repositories { } dependencies { - deobfCompile "mezz.jei:jei_1.10.2:3.7.6.232" + deobfCompile "mezz.jei:jei_1.10.2:3.14.7.+" } // This is our group. I'm cpw.mods @@ -43,8 +43,8 @@ archivesBaseName = "ironchest" // Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here minecraft { - version = "1.10.2-12.18.1.2014" - mappings = "snapshot_20160715" + version = "1.10.2-12.18.3.2297" + mappings = "snapshot_20161116" runDir = "run" } diff --git a/src/main/java/cpw/mods/ironchest/CommonProxy.java b/src/main/java/cpw/mods/ironchest/CommonProxy.java index 505be12..638b128 100755 --- a/src/main/java/cpw/mods/ironchest/CommonProxy.java +++ b/src/main/java/cpw/mods/ironchest/CommonProxy.java @@ -28,6 +28,11 @@ public class CommonProxy implements IGuiHandler return null; } + public World getClientWorld() + { + return null; + } + @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { diff --git a/src/main/java/cpw/mods/ironchest/ContainerIronChest.java b/src/main/java/cpw/mods/ironchest/ContainerIronChest.java index b69fea3..3b23cc5 100755 --- a/src/main/java/cpw/mods/ironchest/ContainerIronChest.java +++ b/src/main/java/cpw/mods/ironchest/ContainerIronChest.java @@ -37,7 +37,7 @@ public class ContainerIronChest extends Container @Override public boolean canInteractWith(EntityPlayer player) { - return this.chest.isUseableByPlayer(player); + return this.chest.isUsableByPlayer(player); } @Override diff --git a/src/main/java/cpw/mods/ironchest/IronChest.java b/src/main/java/cpw/mods/ironchest/IronChest.java index d726e37..1633f0a 100755 --- a/src/main/java/cpw/mods/ironchest/IronChest.java +++ b/src/main/java/cpw/mods/ironchest/IronChest.java @@ -12,14 +12,18 @@ package cpw.mods.ironchest; import java.util.Properties; +import cpw.mods.ironchest.network.MessageCrystalChestSync; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.Mod.Instance; import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.relauncher.Side; @Mod(modid = IronChest.MOD_ID, name = "Iron Chests", dependencies = "required-after:Forge@[12.17.0.1909,)", acceptedMinecraftVersions = "[1.9.4, 1.11)") public class IronChest @@ -35,6 +39,8 @@ public class IronChest public static BlockIronChest ironChestBlock; public static ItemIronChest ironChestItemBlock; + public static final SimpleNetworkWrapper packetHandler = NetworkRegistry.INSTANCE.newSimpleChannel(MOD_ID); + @EventHandler public void preInit(FMLPreInitializationEvent event) { @@ -46,7 +52,6 @@ public class IronChest String minor = properties.getProperty("IronChest.build.minor.number"); String rev = properties.getProperty("IronChest.build.revision.number"); String build = properties.getProperty("IronChest.build.number"); - // String mcversion = properties.getProperty("IronChest.build.mcversion"); event.getModMetadata().version = String.format("%s.%s.%s build %s", major, minor, rev, build); } @@ -65,4 +70,11 @@ public class IronChest proxy.registerRenderInformation(); MinecraftForge.EVENT_BUS.register(new OcelotsSitOnChestsHandler()); } + + @EventHandler + public void init(FMLInitializationEvent event) + { + int messageId = 0; + packetHandler.registerMessage(MessageCrystalChestSync.Handler.class, MessageCrystalChestSync.class, messageId++, Side.CLIENT); + } } diff --git a/src/main/java/cpw/mods/ironchest/TileEntityIronChest.java b/src/main/java/cpw/mods/ironchest/TileEntityIronChest.java index 4c913b1..76e6a0a 100755 --- a/src/main/java/cpw/mods/ironchest/TileEntityIronChest.java +++ b/src/main/java/cpw/mods/ironchest/TileEntityIronChest.java @@ -15,6 +15,7 @@ import java.util.Comparator; import javax.annotation.Nullable; +import cpw.mods.ironchest.network.MessageCrystalChestSync; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -34,6 +35,7 @@ import net.minecraft.util.ITickable; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint; public class TileEntityIronChest extends TileEntityLockableLoot implements ITickable, IInventory { @@ -114,7 +116,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick if (this.hasWorldObj()) { - IBlockState state = this.worldObj.getBlockState(this.pos); + IBlockState state = this.world.getBlockState(this.pos); if (state.getBlock() == IronChest.ironChestBlock) { @@ -145,7 +147,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick protected void sortTopStacks() { - if (!this.getType().isTransparent() || (this.worldObj != null && this.worldObj.isRemote)) + if (!this.getType().isTransparent() || (this.world != null && this.world.isRemote)) { return; } @@ -194,11 +196,11 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick this.topStacks[i] = null; } - if (this.worldObj != null) + if (this.world != null) { - IBlockState iblockstate = this.worldObj.getBlockState(this.pos); + IBlockState iblockstate = this.world.getBlockState(this.pos); - this.worldObj.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3); + this.world.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3); } return; @@ -247,12 +249,14 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick this.topStacks[i] = null; } - if (this.worldObj != null) + if (this.world != null) { - IBlockState iblockstate = this.worldObj.getBlockState(this.pos); + IBlockState iblockstate = this.world.getBlockState(this.pos); - this.worldObj.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3); + this.world.notifyBlockUpdate(this.pos, iblockstate, iblockstate, 3); } + + sendTopStacksPacket(); } @Override @@ -380,14 +384,14 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick } @Override - public boolean isUseableByPlayer(EntityPlayer player) + public boolean isUsableByPlayer(EntityPlayer player) { - if (this.worldObj == null) + if (this.world == null) { return true; } - if (this.worldObj.getTileEntity(this.pos) != this) + if (this.world.getTileEntity(this.pos) != this) { return false; } @@ -400,7 +404,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick { // Resynchronizes clients with the server state //@formatter:off - if (this.worldObj != null && !this.worldObj.isRemote && this.numPlayersUsing != 0 && (this.ticksSinceSync + this.pos.getX() + this.pos.getY() + this.pos.getZ()) % 200 == 0) + if (this.world != null && !this.world.isRemote && this.numPlayersUsing != 0 && (this.ticksSinceSync + this.pos.getX() + this.pos.getY() + this.pos.getZ()) % 200 == 0) //@formatter:on { this.numPlayersUsing = 0; @@ -408,7 +412,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick float f = 5.0F; //@formatter:off - for (EntityPlayer player : this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(this.pos.getX() - f, this.pos.getY() - f, this.pos.getZ() - f, this.pos.getX() + 1 + f, this.pos.getY() + 1 + f, this.pos.getZ() + 1 + f))) + for (EntityPlayer player : this.world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(this.pos.getX() - f, this.pos.getY() - f, this.pos.getZ() - f, this.pos.getX() + 1 + f, this.pos.getY() + 1 + f, this.pos.getZ() + 1 + f))) //@formatter:on { if (player.openContainer instanceof ContainerIronChest) @@ -418,12 +422,12 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick } } - if (this.worldObj != null && !this.worldObj.isRemote && this.ticksSinceSync < 0) + if (this.world != null && !this.world.isRemote && this.ticksSinceSync < 0) { - this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 3, ((this.numPlayersUsing << 3) & 0xF8) | (this.facing.ordinal() & 0x7)); + this.world.addBlockEvent(this.pos, IronChest.ironChestBlock, 3, ((this.numPlayersUsing << 3) & 0xF8) | (this.facing.ordinal() & 0x7)); } - if (!this.worldObj.isRemote && this.inventoryTouched) + if (!this.world.isRemote && this.inventoryTouched) { this.inventoryTouched = false; @@ -442,7 +446,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick double y = this.pos.getY() + 0.5D; double z = this.pos.getZ() + 0.5D; - this.worldObj.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F); + this.world.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, this.world.rand.nextFloat() * 0.1F + 0.9F); } if (this.numPlayersUsing == 0 && this.lidAngle > 0.0F || this.numPlayersUsing > 0 && this.lidAngle < 1.0F) @@ -471,7 +475,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick double y = this.pos.getY() + 0.5D; double z = this.pos.getZ() + 0.5D; - this.worldObj.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F); + this.world.playSound(null, x, y, z, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, this.world.rand.nextFloat() * 0.1F + 0.9F); } if (this.lidAngle < 0.0F) @@ -506,7 +510,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick { if (!player.isSpectator()) { - if (this.worldObj == null) + if (this.world == null) { return; } @@ -518,9 +522,9 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick ++this.numPlayersUsing; - this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing); - this.worldObj.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock); - this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock); + this.world.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing); + this.world.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock); + this.world.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock); } } @@ -529,16 +533,16 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick { if (!player.isSpectator()) { - if (this.worldObj == null) + if (this.world == null) { return; } --this.numPlayersUsing; - this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing); - this.worldObj.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock); - this.worldObj.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock); + this.world.addBlockEvent(this.pos, IronChest.ironChestBlock, 1, this.numPlayersUsing); + this.world.notifyNeighborsOfStateChange(this.pos, IronChest.ironChestBlock); + this.world.notifyNeighborsOfStateChange(this.pos.down(), IronChest.ironChestBlock); } } @@ -559,29 +563,6 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick compound.setByte("facing", (byte) this.facing.ordinal()); - ItemStack[] stacks = this.buildItemStackDataList(); - - if (stacks != null) - { - NBTTagList itemList = new NBTTagList(); - - for (int slot = 0; slot < stacks.length; slot++) - { - if (stacks[slot] != null) - { - NBTTagCompound item = new NBTTagCompound(); - - item.setByte("Slot", (byte) slot); - - stacks[slot].writeToNBT(item); - - itemList.appendTag(item); - } - } - - compound.setTag("stacks", itemList); - } - return new SPacketUpdateTileEntity(this.pos, 0, compound); } @@ -593,41 +574,6 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick NBTTagCompound compound = pkt.getNbtCompound(); this.facing = EnumFacing.VALUES[compound.getByte("facing")]; - - NBTTagList itemList = compound.getTagList("stacks", Constants.NBT.TAG_COMPOUND); - - ItemStack[] stacks = new ItemStack[this.topStacks.length]; - - for (int item = 0; item < stacks.length; item++) - { - NBTTagCompound itemStack = itemList.getCompoundTagAt(item); - - int slot = itemStack.getByte("Slot") & 255; - - if (slot >= 0 && slot < stacks.length) - { - stacks[slot] = ItemStack.loadItemStackFromNBT(itemStack); - } - } - - if (this.getType().isTransparent() && stacks != null) - { - int pos = 0; - - for (int i = 0; i < this.topStacks.length; i++) - { - if (stacks[pos] != null) - { - this.topStacks[i] = stacks[pos]; - } - else - { - this.topStacks[i] = null; - } - - pos++; - } - } } } @@ -678,7 +624,7 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick { this.setFacing(this.facing.rotateY()); - this.worldObj.addBlockEvent(this.pos, IronChest.ironChestBlock, 2, this.facing.ordinal()); + this.world.addBlockEvent(this.pos, IronChest.ironChestBlock, 2, this.facing.ordinal()); } public void wasPlaced(EntityLivingBase entityliving, ItemStack stack) @@ -742,4 +688,17 @@ public class TileEntityIronChest extends TileEntityLockableLoot implements ITick { return this.writeToNBT(new NBTTagCompound()); } + + protected void sendTopStacksPacket() + { + ItemStack[] stacks = this.buildItemStackDataList(); + //@formatter:off + IronChest.packetHandler.sendToAllAround(new MessageCrystalChestSync(this, stacks), new TargetPoint(world.provider.getDimension(), getPos().getX(), getPos().getY(), getPos().getZ(), 32)); + //@formatter:on + } + + public void receiveMessageFromServer(ItemStack[] topStacks) + { + this.topStacks = topStacks; + } } diff --git a/src/main/java/cpw/mods/ironchest/client/ClientProxy.java b/src/main/java/cpw/mods/ironchest/client/ClientProxy.java index 9637c34..76601d1 100755 --- a/src/main/java/cpw/mods/ironchest/client/ClientProxy.java +++ b/src/main/java/cpw/mods/ironchest/client/ClientProxy.java @@ -15,6 +15,7 @@ import cpw.mods.ironchest.CommonProxy; import cpw.mods.ironchest.IronChest; import cpw.mods.ironchest.IronChestType; import cpw.mods.ironchest.TileEntityIronChest; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; @@ -55,6 +56,12 @@ public class ClientProxy extends CommonProxy } } + @Override + public World getClientWorld() + { + return Minecraft.getMinecraft().world; + } + @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { diff --git a/src/main/java/cpw/mods/ironchest/network/MessageCrystalChestSync.java b/src/main/java/cpw/mods/ironchest/network/MessageCrystalChestSync.java new file mode 100644 index 0000000..3d4cc8d --- /dev/null +++ b/src/main/java/cpw/mods/ironchest/network/MessageCrystalChestSync.java @@ -0,0 +1,118 @@ +package cpw.mods.ironchest.network; + +import cpw.mods.ironchest.IronChest; +import cpw.mods.ironchest.TileEntityIronChest; +import io.netty.buffer.ByteBuf; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class MessageCrystalChestSync implements IMessage +{ + int dimension; + BlockPos pos; + private ItemStack[] topStacks; + + public MessageCrystalChestSync(TileEntityIronChest tile, ItemStack[] stack) + { + this.dimension = tile.getWorld().provider.getDimension(); + this.pos = tile.getPos(); + this.topStacks = stack; + } + + public MessageCrystalChestSync() + { + } + + @Override + public void fromBytes(ByteBuf buf) + { + this.dimension = buf.readInt(); + this.pos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); + int size = buf.readInt(); + this.topStacks = new ItemStack[size]; + + int stackListSize = buf.readInt(); + + for (int i = 0; i < stackListSize; i++) + { + if (i < stackListSize) + { + this.topStacks[i] = readItemStack(buf); + } + else + { + this.topStacks[i] = null; + } + } + } + + @Override + public void toBytes(ByteBuf buf) + { + buf.writeInt(this.dimension); + buf.writeInt(this.pos.getX()); + buf.writeInt(this.pos.getY()); + buf.writeInt(this.pos.getZ()); + buf.writeInt(topStacks.length); + + int stackListSize = 0; + + for (ItemStack stack : topStacks) + { + if (stack != null) + { + stackListSize++; + } + } + + buf.writeInt(stackListSize); + + for (ItemStack stack : topStacks) + { + if (stack != null) + { + writeItemStack(buf, stack); + } + } + } + + public static void writeItemStack(ByteBuf buf, ItemStack stack) + { + buf.writeInt(Item.getIdFromItem(stack.getItem())); + buf.writeInt(stack.stackSize); + buf.writeInt(stack.getItemDamage()); + ByteBufUtils.writeTag(buf, stack.getItem().getNBTShareTag(stack)); + } + + public static ItemStack readItemStack(ByteBuf buf) + { + ItemStack stack = new ItemStack(Item.getItemById(buf.readInt()), buf.readInt(), buf.readInt()); + stack.setTagCompound(ByteBufUtils.readTag(buf)); + return stack; + } + + public static class Handler implements IMessageHandler + { + @Override + public IMessage onMessage(MessageCrystalChestSync message, MessageContext ctx) + { + World world = IronChest.proxy.getClientWorld(); + + if (world != null) + { + TileEntity tile = world.getTileEntity(message.pos); + + if (tile instanceof TileEntityIronChest) + ((TileEntityIronChest) tile).receiveMessageFromServer(message.topStacks); + } + return null; + } + } +} \ No newline at end of file