package codechicken.multipart; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import codechicken.lib.packet.PacketCustom; import codechicken.multipart.handler.MultipartProxy; import codechicken.multipart.handler.MultipartSPH; import codechicken.multipart.handler.MultipartSaveLoad; import scala.collection.JavaConversions; /** * Static helper class for handling the unusual way that multipart tile entities load from nbt and send description * packets. *
* Multipart tile entities will all save themselves with the id "savedMultipart" which if normally loaded by minecraft, * will create a dummy tile entity which just holds the NBT it was read from. These dummies are then converted to actual * container tiles on the ChunkLoad event. The createTileFromNBT function should be used to construct a multipart tile * from NBT without the ChunkLoad event. *
* Multipart tile entities do not send description packets via the conventional means of one packet per tile when * PlayerInstance calls for it, to do so would be terribly inefficient. Instead, the ChunkWatch event is used to batch * all the describing data for a chunk into one packet which is compressed using relative positions. The sendDescPacket * function should be used to send the description packet of a tile without a ChunkWatch event. *
* An example of using this class to move blocks/tile entites around can be found at * www.chickenbones.craftsaddle.org/Files/Other/ItemDevTool2.java *
* The reference carried a commented-out sendDescPackets batching several tiles at once. It was removed for compilation * until a PlayerInstance access transformer is pulled into forge, and is not reinstated here. */ public final class MultipartHelper { private MultipartHelper() {} public static TileEntity createTileFromNBT(World world, NBTTagCompound tag) { if (!tag.getString("id").equals("savedMultipart")) { return null; } MultipartSaveLoad.loadingWorld_$eq(world); return TileMultipart.createFromNBT(tag); } /** * Builds a render-ready client multipart tile from saved NBT without installing it into a world. Every registered * part factory must support * {@link MultiPartRegistry.IPartFactory2#createPartForClientPreview(String, NBTTagCompound)}; otherwise the whole * preview is rejected and null is returned. Part order and saved state are preserved. * *
* A non-null world must be client-side. The tile receives its saved coordinates, binds every part, then runs
* {@link TMultiPart#onWorldJoin()} and local {@link TMultiPart#onPartChanged(TMultiPart)} callbacks before
* rebuilding its render state. It is not validated, placed in a chunk, or announced to neighboring blocks. A null
* world creates a worldless staged preview; render caches initialize lazily when a renderer uses the tile.
*
* @param world client preview world, or null for worldless staging
* @param tag saved multipart NBT; it is read but not mutated
* @return a prepared client tile, or null for a foreign/empty tag, missing factory, or unsupported preview part
* @throws IllegalArgumentException if world is server-side
*/
public static TileMultipart createPreviewTileFromNBT(World world, NBTTagCompound tag) {
if (tag == null || !tag.getString("id").equals("savedMultipart")) {
return null;
}
if (world != null && !world.isRemote) {
throw new IllegalArgumentException("Multipart previews require a client world");
}
NBTTagList partTags = tag.getTagList("parts", 10);
List