Minecraft Modding: Older Version TileEntity Tips

Warning: This information is for 1.7.10 and older versions. If you're working on 1.8 or later please see my modern version tips for TileEntity.

Turning Off Updates For TileEntity When Possible


The reason why Minecraft uses single block instances per type and limited metadata per block location is to ensure perf is acceptable in a world with a million (literally) block locations.  However, sometimes you want a "smarter" block that contains more information than the 4 bits that metadata allows.  So there is ability to associate a TileEntity with certain blocks.  However, if you place too many of these, it will again hurt performance.

Key Point: In some cases you may have a TileEntity that stores information or controls rendering but does not need to execute code.  Ticking is controlled by the canUpdate() method which was only checked at time tile entities are loaded, so you cannot dynamically change the return value in this method.

Warning: Even though the World.loadedTileEntityList is public, modifying it can cause co-modification error crashes.

Syncing Tile Entity Data Across All Clients


For efficiency reasons, tile entities normally only update other clients when the GUI is active. However it is possible that you want to communicate something else more continuously.  You can update the tile entities at any time by using the description packets approach.

Simply, the description packet should contain the data you want to sync.  So you should @Override the getDescriptionPacket() method in your custom tile entity to return a Packet (make sure you import this from the net.minecraft.network package not some other package).  In the payload for that packet you will put a buffer filled with your data.  I personally use an NBTCompound to hold all the data and pack that into the buffer, but you can also just put a series of integers, strings, booleans, etc.

You also need to @Override the onDataPacket() method to take any received packets and update the local field values based on the contents of the packet payload.

You do not want to sync every tick as that will create performance problems.  Instead you will want to only send a packet when there is a change worth sharing with the other clients.  In whatever code detects such a change you can then send a packet as needed using the following code:

worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); // Makes the server call getDescriptionPacket for a full data sync
markDirty(); // Marks the chunk as dirty, so that it is saved properly on changes.

That's it!

No comments:

Post a Comment