package coloredlightscore.network; import coloredlightscore.server.ChunkStorageRGB; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.NibbleArray; import java.lang.reflect.Method; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; @SuppressWarnings("ConstantConditions") public class ChunkColorDataPacket implements IMessage, IMessageHandler<ChunkColorDataPacket, IMessage> { // In order of packet layout: //public int packetId; public int chunkXPosition; public int chunkZPosition; public int arraySize; // The following are stored as raw byte data: public NibbleArray[] RedColorArray; public NibbleArray[] GreenColorArray; public NibbleArray[] BlueColorArray; public int[] yLocation; private final boolean USE_COMPRESSION = true; private static Method methodGetValueArray = null; public ChunkColorDataPacket() { } public ChunkColorDataPacket(Method methodGetValueArray) { ChunkColorDataPacket.methodGetValueArray = methodGetValueArray; } @Override public IMessage onMessage(ChunkColorDataPacket packet, MessageContext context) { if (context.side == Side.CLIENT) processColorDataPacket(packet); return null; } @SideOnly(Side.CLIENT) private void processColorDataPacket(ChunkColorDataPacket packet) { Chunk targetChunk = Minecraft.getMinecraft().theWorld.getChunkFromChunkCoords(packet.chunkXPosition, packet.chunkZPosition); if (targetChunk != null) { ChunkStorageRGB.loadColorData(targetChunk, packet.arraySize, packet.yLocation, packet.RedColorArray, packet.GreenColorArray, packet.BlueColorArray); //FMLLog.info("ProcessColorDataPacket() loaded RGB for (%s,%s)", ccdPacket.chunkXPosition, ccdPacket.chunkZPosition); } else FMLLog.warning("ProcessColorDataPacket() Chunk located at (%s, %s) could not be found in the local world!", packet.chunkXPosition, packet.chunkZPosition); } @Override public void fromBytes(ByteBuf bytes) { try { byte[] rawColorData = new byte[2048 * 16 * 3]; byte[] compressedColorData = new byte[32000]; byte[] nibbleData; int compressedSize; int arraysPresent; int p = 0; chunkXPosition = bytes.readInt(); chunkZPosition = bytes.readInt(); arraySize = bytes.readInt(); yLocation = new int[arraySize]; for (int i = 0; i < arraySize; i++) yLocation[i] = bytes.readInt(); arraysPresent = bytes.readInt(); RedColorArray = new NibbleArray[arraySize]; GreenColorArray = new NibbleArray[arraySize]; BlueColorArray = new NibbleArray[arraySize]; if (USE_COMPRESSION) { compressedSize = bytes.readInt(); bytes.readBytes(compressedColorData, 0, compressedSize); Inflater inflater = new Inflater(); inflater.setInput(compressedColorData); try { inflater.inflate(rawColorData); } catch (DataFormatException e) { FMLLog.warning("ChunkColorDataPacket() ", e); } finally { inflater.end(); } } else // !USE_COMPRESSION bytes.readBytes(rawColorData); for (int i = 0; i < arraySize; i++) { if ((arraysPresent & (1 << i)) != 0) { nibbleData = new byte[2048]; System.arraycopy(rawColorData, p, nibbleData, 0, 2048); RedColorArray[i] = new NibbleArray(nibbleData, 4); p += 2048; nibbleData = new byte[2048]; System.arraycopy(rawColorData, p, nibbleData, 0, 2048); GreenColorArray[i] = new NibbleArray(nibbleData, 4); p += 2048; nibbleData = new byte[2048]; System.arraycopy(rawColorData, p, nibbleData, 0, 2048); BlueColorArray[i] = new NibbleArray(nibbleData, 4); // 4,59,10 y:3[11] cx:-16 cz:10 p += 2048; } else { RedColorArray[i] = new NibbleArray(4096, 4); GreenColorArray[i] = new NibbleArray(4096, 4); BlueColorArray[i] = new NibbleArray(4096, 4); } } } catch (Exception e) { FMLLog.getLogger().error("fromBytes ", e); } } @Override public void toBytes(ByteBuf bytes) { try { byte[] rawColorData = new byte[2048 * 16 * 3]; byte[] compressedColorData = new byte[32000]; int compressedSize; int arraysPresent = 0; int p = 0; bytes.writeInt(chunkXPosition); bytes.writeInt(chunkZPosition); bytes.writeInt(arraySize); // Crank out nibble arrays for (int i = 0; i < arraySize; i++) { if (RedColorArray[i] != null || GreenColorArray[i] != null || BlueColorArray[i] != null) { arraysPresent |= (1 << i); if (FMLCommonHandler.instance().getModName().contains("cauldron")) { byte[] localRed = (byte[]) methodGetValueArray.invoke(RedColorArray[i]); byte[] localGreen = (byte[]) methodGetValueArray.invoke(GreenColorArray[i]); byte[] localBlue = (byte[]) methodGetValueArray.invoke(BlueColorArray[i]); System.arraycopy(localRed, 0, rawColorData, p, localRed.length); p += localRed.length; System.arraycopy(localGreen, 0, rawColorData, p, localGreen.length); p += localGreen.length; System.arraycopy(localBlue, 0, rawColorData, p, localBlue.length); p += localBlue.length; } else { System.arraycopy(RedColorArray[i].data, 0, rawColorData, p, RedColorArray[i].data.length); p += RedColorArray[i].data.length; System.arraycopy(GreenColorArray[i].data, 0, rawColorData, p, GreenColorArray[i].data.length); p += GreenColorArray[i].data.length; System.arraycopy(BlueColorArray[i].data, 0, rawColorData, p, BlueColorArray[i].data.length); p += BlueColorArray[i].data.length; } } // Add Y location bytes.writeInt(yLocation[i]); } bytes.writeInt(arraysPresent); if (USE_COMPRESSION) { Deflater deflate = new Deflater(-1); deflate.setInput(rawColorData); deflate.finish(); compressedSize = deflate.deflate(compressedColorData); if (compressedSize == 0) FMLLog.warning("writePacket compression failed"); bytes.writeInt(compressedSize); bytes.writeBytes(compressedColorData, 0, compressedSize); } else // !USE_COMPRESSION bytes.writeBytes(rawColorData, 0, rawColorData.length); } catch (Exception e) { FMLLog.getLogger().error("toBytes ", e); } } }