package gregtech.api.util; import java.io.IOException; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTSizeTracker; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; import com.google.common.io.ByteArrayDataInput; import io.netty.buffer.ByteBuf; /** * We could well have used {@link java.io.Serializable}, but that's too slow and should generally be avoided * * @author glease */ public interface ISerializableObject { @Nonnull ISerializableObject copy(); /** * If you are overriding this, you must NOT return {@link NBTTagInt} here! That return type is how we tell * that we are loading legacy data, and only {@link LegacyCoverData} is allowed to return it. You probably want to * return {@link NBTTagCompound} anyway. */ @Nonnull NBTBase saveDataToNBT(); /** * Write data to given ByteBuf The data saved this way is intended to be stored for short amount of time over * network. DO NOT store it to disks. */ // the NBT is an unfortunate piece of tech. everything uses it but its API is not as efficient as could be void writeToByteBuf(ByteBuf aBuf); void loadDataFromNBT(NBTBase aNBT); /** * Read data from given parameter and return this. The data read this way is intended to be stored for short amount * of time over network. * * @param aPlayer the player who is sending this packet to server. null if it's client reading data. */ // the NBT is an unfortunate piece of tech. everything uses it but its API is not as efficient as could be @Nonnull ISerializableObject readFromPacket(ByteArrayDataInput aBuf, @Nullable EntityPlayerMP aPlayer); /** * Reverse engineered and adapted {@link cpw.mods.fml.common.network.ByteBufUtils#readTag(ByteBuf)} Given buffer * must contain a serialized NBTTagCompound in minecraft encoding */ static NBTTagCompound readCompoundTagFromGreggyByteBuf(ByteArrayDataInput aBuf) { short size = aBuf.readShort(); if (size < 0) return null; else { byte[] buf = new byte[size]; // this is shit, how many copies have we been doing? aBuf.readFully(buf); try { return CompressedStreamTools.func_152457_a(buf, new NBTSizeTracker(2097152L)); } catch (IOException e) { throw new RuntimeException(e); } } } /** * Reverse engineered and adapted {@link cpw.mods.fml.common.network.ByteBufUtils#readItemStack(ByteBuf)} Given * buffer must contain a serialized ItemStack in minecraft encoding */ static ItemStack readItemStackFromGreggyByteBuf(ByteArrayDataInput aBuf) { ItemStack stack = null; short id = aBuf.readShort(); if (id >= 0) { byte size = aBuf.readByte(); short meta = aBuf.readShort(); stack = new ItemStack(Item.getItemById(id), size, meta); stack.stackTagCompound = readCompoundTagFromGreggyByteBuf(aBuf); } return stack; } final class LegacyCoverData implements ISerializableObject { private int mData; public LegacyCoverData() {} public LegacyCoverData(int mData) { this.mData = mData; } @Override @Nonnull public ISerializableObject copy() { return new LegacyCoverData(mData); } @Override @Nonnull public NBTBase saveDataToNBT() { return new NBTTagInt(mData); } @Override public void writeToByteBuf(ByteBuf aBuf) { aBuf.writeInt(mData); } @Override public void loadDataFromNBT(NBTBase aNBT) { mData = aNBT instanceof NBTTagInt ? ((NBTTagInt) aNBT).func_150287_d() : 0; } @Override @Nonnull public ISerializableObject readFromPacket(ByteArrayDataInput aBuf, EntityPlayerMP aPlayer) { mData = aBuf.readInt(); return this; } public int get() { return mData; } public void set(int mData) { this.mData = mData; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LegacyCoverData that = (LegacyCoverData) o; return mData == that.mData; } @Override public int hashCode() { return mData; } @Override public String toString() { return String.valueOf(mData); } } }