Applied-Energistics-2-tiler.../src/main/java/appeng/core/sync/packets/PacketMEInventoryUpdate.java

198 lines
6.3 KiB
Java

/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.core.sync.packets;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.BufferOverflowException;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.annotation.Nullable;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.implementations.GuiController;
import appeng.client.gui.implementations.GuiCraftConfirm;
import appeng.client.gui.implementations.GuiCraftingCPU;
import appeng.client.gui.implementations.GuiMEMonitorable;
import appeng.client.gui.implementations.GuiNetworkStatus;
import appeng.core.AELog;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.util.item.AEItemStack;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
public class PacketMEInventoryUpdate extends AppEngPacket {
private static final int UNCOMPRESSED_PACKET_BYTE_LIMIT = 16 * 1024 * 1024;
private static final int OPERATION_BYTE_LIMIT = 2 * 1024;
private static final int TEMP_BUFFER_SIZE = 1024;
private static final int STREAM_MASK = 0xff;
// input.
@Nullable
private final List<IAEItemStack> list;
// output...
private final byte ref;
@Nullable
private final ByteBuf data;
@Nullable
private final GZIPOutputStream compressFrame;
private int writtenBytes = 0;
private boolean empty = true;
// automatic.
public PacketMEInventoryUpdate(final ByteBuf stream) throws IOException {
this.data = null;
this.compressFrame = null;
this.list = new LinkedList<IAEItemStack>();
this.ref = stream.readByte();
// int originalBytes = stream.readableBytes();
final GZIPInputStream gzReader = new GZIPInputStream(new InputStream() {
@Override
public int read() throws IOException {
if (stream.readableBytes() <= 0) {
return -1;
}
return stream.readByte() & STREAM_MASK;
}
});
final ByteBuf uncompressed = Unpooled.buffer(stream.readableBytes());
final byte[] tmp = new byte[TEMP_BUFFER_SIZE];
while (gzReader.available() != 0) {
final int bytes = gzReader.read(tmp);
if (bytes > 0) {
uncompressed.writeBytes(tmp, 0, bytes);
}
}
gzReader.close();
// int uncompressedBytes = uncompressed.readableBytes();
// AELog.info( "Receiver: " + originalBytes + " -> " + uncompressedBytes );
while (uncompressed.readableBytes() > 0) {
this.list.add(AEItemStack.loadItemStackFromPacket(uncompressed));
}
this.empty = this.list.isEmpty();
}
// api
public PacketMEInventoryUpdate() throws IOException {
this((byte) 0);
}
// api
public PacketMEInventoryUpdate(final byte ref) throws IOException {
this.ref = ref;
this.data = Unpooled.buffer(OPERATION_BYTE_LIMIT);
this.data.writeInt(this.getPacketID());
this.data.writeByte(this.ref);
this.compressFrame = new GZIPOutputStream(new OutputStream() {
@Override
public void write(final int value) throws IOException {
PacketMEInventoryUpdate.this.data.writeByte(value);
}
});
this.list = null;
}
@Override
@SideOnly(Side.CLIENT)
public void clientPacketData(
final INetworkInfo network, final AppEngPacket packet, final EntityPlayer player
) {
final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if (gs instanceof GuiCraftConfirm) {
((GuiCraftConfirm) gs).postUpdate(this.list, this.ref);
}
if (gs instanceof GuiCraftingCPU) {
((GuiCraftingCPU) gs).postUpdate(this.list, this.ref);
}
if (gs instanceof GuiMEMonitorable) {
((GuiMEMonitorable) gs).postUpdate(this.list);
}
if (gs instanceof GuiNetworkStatus) {
((GuiNetworkStatus) gs).postUpdate(this.list);
}
if (gs instanceof GuiController) {
((GuiController) gs).postUpdate(this.list);
}
}
@Nullable
@Override
public FMLProxyPacket getProxy() {
try {
this.compressFrame.close();
this.configureWrite(this.data);
return super.getProxy();
} catch (final IOException e) {
AELog.debug(e);
}
return null;
}
public void appendItem(final IAEItemStack is)
throws IOException, BufferOverflowException {
final ByteBuf tmp = Unpooled.buffer(OPERATION_BYTE_LIMIT);
is.writeToPacket(tmp);
this.compressFrame.flush();
if (this.writtenBytes + tmp.readableBytes() > UNCOMPRESSED_PACKET_BYTE_LIMIT) {
throw new BufferOverflowException();
} else {
this.writtenBytes += tmp.readableBytes();
this.compressFrame.write(tmp.array(), 0, tmp.readableBytes());
this.empty = false;
}
}
public int getLength() {
return this.data.readableBytes();
}
public boolean isEmpty() {
return this.empty;
}
}