Split packets when sending items over network (#107)

Packets are now split into smaller chunks when sent. The packet
size is adjustable in the config.
This commit is contained in:
firenoo authored and GitHub committed 2023-03-23 17:14:14 +01:00
1 parent 6a244c12c4
commit 9c2ef02383
12 files changed
+316 -181

No files matched your search

@@ -19,10 +19,7 @@ import com.glodblock.github.util.ModAndClassUtil;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.*;
import cpw.mods.fml.common.network.NetworkRegistry;
@Mod(
@@ -25,13 +25,16 @@ public class GuiFluidMonitor extends FCGuiMonitor<IAEFluidStack> {
this.repo = new FluidRepo(getScrollBar(), this);
}
public void postUpdate(final List<IAEFluidStack> list) {
@Override
public void postUpdate(final List<IAEFluidStack> list, boolean resort) {
for (final IAEFluidStack is : list) {
IAEItemStack stack = AEItemStack.create(ItemFluidDrop.newDisplayStack(is.getFluidStack()));
stack.setStackSize(is.getStackSize());
this.repo.postUpdate(stack);
}
this.repo.updateView();
if (resort) {
this.repo.updateView();
}
this.setScrollBar();
}
@@ -22,11 +22,14 @@ public class GuiItemMonitor extends FCGuiMonitor<IAEItemStack> {
this.repo = new ItemRepo(getScrollBar(), this);
}
public void postUpdate(final List<IAEItemStack> list) {
@Override
public void postUpdate(final List<IAEItemStack> list, boolean resort) {
for (final IAEItemStack is : list) {
this.repo.postUpdate(is);
}
this.repo.updateView();
if (resort) {
this.repo.updateView();
}
this.setScrollBar();
}
@@ -107,7 +107,7 @@ public abstract class FCGuiMonitor<T extends IAEStack<T>> extends FCBaseMEGui
offsetY = y;
}
public abstract void postUpdate(final List<T> list);
public abstract void postUpdate(final List<T> list, boolean resort);
protected void setScrollBar() {
this.getScrollBar().setTop(18).setLeft(175).setHeight(this.rows * 18 - 2);
@@ -43,7 +43,7 @@ import com.glodblock.github.client.gui.container.base.FCContainerMonitor;
import com.glodblock.github.common.item.ItemFluidDrop;
import com.glodblock.github.network.CPacketFluidUpdate;
import com.glodblock.github.network.SPacketFluidUpdate;
import com.glodblock.github.network.SPacketMEInventoryUpdate;
import com.glodblock.github.network.SPacketMEFluidInvUpdate;
import com.glodblock.github.util.Util;
public class ContainerFluidMonitor extends FCContainerMonitor<IAEFluidStack> {
@@ -126,46 +126,51 @@ public class ContainerFluidMonitor extends FCContainerMonitor<IAEFluidStack> {
protected void processItemList() {
if (!this.fluids.isEmpty()) {
final IItemList<IAEFluidStack> monitorCache = this.monitor.getStorageList();
final SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate(true);
SPacketMEFluidInvUpdate packet = new SPacketMEFluidInvUpdate();
for (final IAEFluidStack is : this.fluids) {
final IAEFluidStack send = monitorCache.findPrecise(is);
if (send == null) {
is.setStackSize(0);
piu.appendFluid(is);
} else {
piu.appendFluid(send);
try {
if (send != null) {
packet.appendFluid(send);
} else {
is.setStackSize(0);
packet.appendFluid(is);
}
} catch (BufferOverflowException e) {
for (final Object c : this.crafters) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
packet = new SPacketMEFluidInvUpdate();
if (send != null) {
packet.appendFluid(send);
} else {
is.setStackSize(0);
packet.appendFluid(is);
}
}
}
if (!piu.isEmpty()) {
this.fluids.resetStatus();
for (final Object c : this.crafters) {
if (c instanceof EntityPlayer) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
}
}
for (final Object c : this.crafters) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
}
}
@Override
protected void queueInventory(final ICrafting c) {
if (Platform.isServer() && c instanceof EntityPlayer && this.monitor != null) {
SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate(true);
if (Platform.isServer() && c instanceof EntityPlayerMP && this.monitor != null) {
final IItemList<IAEFluidStack> monitorCache = this.monitor.getStorageList();
for (final IAEFluidStack send : monitorCache) {
SPacketMEFluidInvUpdate packet = new SPacketMEFluidInvUpdate();
for (final IAEFluidStack is : monitorCache) {
try {
piu.appendFluid(send);
} catch (final BufferOverflowException boe) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
piu = new SPacketMEInventoryUpdate(true);
piu.appendFluid(send);
packet.appendFluid(is);
} catch (BufferOverflowException e) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
packet = new SPacketMEFluidInvUpdate();
packet.appendFluid(is);
}
}
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
}
@@ -27,7 +27,7 @@ import appeng.util.Platform;
import com.glodblock.github.FluidCraft;
import com.glodblock.github.client.gui.container.base.FCContainerMonitor;
import com.glodblock.github.network.SPacketMEInventoryUpdate;
import com.glodblock.github.network.SPacketMEItemInvUpdate;
public class ContainerItemMonitor extends FCContainerMonitor<IAEItemStack> {
@@ -95,46 +95,55 @@ public class ContainerItemMonitor extends FCContainerMonitor<IAEItemStack> {
protected void processItemList() {
if (!this.items.isEmpty()) {
final IItemList<IAEItemStack> monitorCache = this.monitor.getStorageList();
final SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate();
SPacketMEItemInvUpdate packet = new SPacketMEItemInvUpdate();
for (final IAEItemStack is : this.items) {
final IAEItemStack send = monitorCache.findPrecise(is);
if (send == null) {
is.setStackSize(0);
piu.appendItem(is);
} else {
piu.appendItem(send);
}
}
if (!piu.isEmpty()) {
this.items.resetStatus();
for (final Object c : this.crafters) {
if (c instanceof EntityPlayer) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
try {
if (send != null) {
packet.appendItem(send);
} else {
is.setStackSize(0);
packet.appendItem(is);
}
} catch (BufferOverflowException e) {
for (final Object c : this.crafters) {
if (c instanceof EntityPlayerMP) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
}
packet = new SPacketMEItemInvUpdate();
if (send != null) {
packet.appendItem(send);
} else {
is.setStackSize(0);
packet.appendItem(is);
}
}
}
for (final Object c : this.crafters) {
if (c instanceof EntityPlayerMP) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
}
this.items.resetStatus();
}
}
@Override
protected void queueInventory(final ICrafting c) {
if (Platform.isServer() && c instanceof EntityPlayer && this.monitor != null) {
SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate();
final IItemList<IAEItemStack> monitorCache = this.monitor.getStorageList();
for (final IAEItemStack send : monitorCache) {
SPacketMEItemInvUpdate packet = new SPacketMEItemInvUpdate();
for (final IAEItemStack is : monitorCache) {
try {
piu.appendItem(send);
} catch (final BufferOverflowException boe) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
piu = new SPacketMEInventoryUpdate();
piu.appendItem(send);
packet.appendItem(is);
} catch (BufferOverflowException e) {
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
packet = new SPacketMEItemInvUpdate();
packet.appendItem(is);
}
}
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
FluidCraft.proxy.netHandler.sendTo(packet, (EntityPlayerMP) c);
}
}
@@ -17,6 +17,7 @@ public class Config {
public static boolean removeRecipe;
public static boolean blacklistEssentiaGas;
public static double portableCellBattery;
public static int packetSize;
public static void run() {
loadCategory();
@@ -51,7 +52,9 @@ public class Config {
"Blacklist Essentia Gas from Thaumic Energistics, so they won't be stored in Fluid Storage Cells.");
portableCellBattery = Config.get("Fluid Craft for AE2", "Portable Fluid Cell Battery Capacity", 20000D)
.getDouble();
packetSize = Config.get("Fluid Craft for AE2", "packetSize", 256, "Number of items to be sent per packet")
.getInt();
if (packetSize <= 0) packetSize = 256;
if (Config.hasChanged()) Config.save();
}
@@ -25,9 +25,11 @@ public class ChannelLoader implements Runnable {
Side.SERVER);
FluidCraft.proxy.netHandler
.registerMessage(new CPacketEncodePattern.Handler(), CPacketEncodePattern.class, id++, Side.SERVER);
FluidCraft.proxy.netHandler
.registerMessage(new SPacketMEItemInvUpdate.Handler(), SPacketMEItemInvUpdate.class, id++, Side.CLIENT);
FluidCraft.proxy.netHandler.registerMessage(
new SPacketMEInventoryUpdate.Handler(),
SPacketMEInventoryUpdate.class,
new SPacketMEFluidInvUpdate.Handler(),
SPacketMEFluidInvUpdate.class,
id++,
Side.CLIENT);
FluidCraft.proxy.netHandler
@@ -88,7 +88,7 @@ public class CPacketLevelMaintainer implements IMessage {
public static class Handler implements IMessageHandler<CPacketLevelMaintainer, IMessage> {
private void refresh(ContainerLevelMaintainer cca, EntityPlayerMP player) {
SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate(false);
SPacketMEItemInvUpdate packet = new SPacketMEItemInvUpdate();
for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) {
IAEItemStack is = cca.getTile().requests.getRequestQtyStack(i);
IAEItemStack is1 = cca.getTile().requests.getRequestBatches().getStack(i);
@@ -96,7 +96,7 @@ public class CPacketLevelMaintainer implements IMessage {
if (is1 != null) {
NBTTagCompound data;
data = is1.getItemStack().getTagCompound();
piu.appendItem(
packet.appendItem(
setTag(
is,
is1.getStackSize(),
@@ -104,11 +104,11 @@ public class CPacketLevelMaintainer implements IMessage {
data.getBoolean("Enable"),
cca.getTile().requests.getState(i).ordinal()));
} else {
piu.appendItem(setTag(is, 0, i, true, 0));
packet.appendItem(setTag(is, 0, i, true, 0));
}
}
}
FluidCraft.proxy.netHandler.sendTo(piu, player);
FluidCraft.proxy.netHandler.sendTo(packet, player);
}
@Nullable
@@ -0,0 +1,111 @@
package com.glodblock.github.network;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import appeng.api.storage.data.IAEFluidStack;
import appeng.util.item.AEFluidStack;
import com.glodblock.github.client.gui.GuiFluidCraftConfirm;
import com.glodblock.github.client.gui.GuiFluidMonitor;
import com.glodblock.github.common.Config;
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 io.netty.buffer.ByteBuf;
/**
* Dedicated packet for fluid updates.
*/
public class SPacketMEFluidInvUpdate implements IMessage {
private List<IAEFluidStack> list = new ArrayList<>();
private byte ref = (byte) 0;
private boolean resort = true;
public SPacketMEFluidInvUpdate() {}
/**
* Used for the GUI to confirm crafting. 0 = available 1 = pending 2 = missing
*/
public SPacketMEFluidInvUpdate(byte b) {
ref = b;
}
/**
* If resort, call "updateView()". Used when multiple packets are sent to open an inventory; only the last packet
* should resort.
*
* @param resort whether this packet should resort the term or not
*/
public SPacketMEFluidInvUpdate(boolean resort) {
this.resort = resort;
}
@Override
public void fromBytes(ByteBuf buf) {
ref = buf.readByte();
resort = buf.readBoolean();
int amount = buf.readInt();
list = new ArrayList<>(amount);
try {
for (int i = 0; i < amount; i++) {
list.add(AEFluidStack.loadFluidStackFromPacket(buf));
}
} catch (Exception io) {
System.out.println("Error handling payload w/ " + amount + " items.");
io.printStackTrace();
}
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeByte(ref);
buf.writeBoolean(resort);
buf.writeInt(list.size());
try {
for (IAEFluidStack is : list) {
is.writeToPacket(buf);
}
} catch (IOException io) {
io.printStackTrace();
}
}
public void setResort(boolean resort) {
this.resort = resort;
}
public void appendFluid(final IAEFluidStack is) throws BufferOverflowException {
if (list.size() <= Config.packetSize) {
list.add(is);
} else {
throw new BufferOverflowException();
}
}
public boolean isEmpty() {
return this.list.isEmpty();
}
public static class Handler implements IMessageHandler<SPacketMEFluidInvUpdate, IMessage> {
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public IMessage onMessage(SPacketMEFluidInvUpdate message, MessageContext ctx) {
final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if (gs instanceof GuiFluidMonitor) {
((GuiFluidMonitor) gs).postUpdate(message.list, message.resort);
} else if (gs instanceof GuiFluidCraftConfirm) {
((GuiFluidCraftConfirm) gs).postUpdate((List) message.list, message.ref);
}
return null;
}
}
}
@@ -1,112 +0,0 @@
package com.glodblock.github.network;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.util.item.AEFluidStack;
import appeng.util.item.AEItemStack;
import com.glodblock.github.client.gui.GuiFluidCraftConfirm;
import com.glodblock.github.client.gui.GuiFluidMonitor;
import com.glodblock.github.client.gui.GuiItemMonitor;
import com.glodblock.github.client.gui.GuiLevelMaintainer;
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 io.netty.buffer.ByteBuf;
public class SPacketMEInventoryUpdate implements IMessage {
private List<Object> list;
private byte ref;
private boolean isFluid = false;
public SPacketMEInventoryUpdate() {
ref = 0;
list = new LinkedList<>();
}
public SPacketMEInventoryUpdate(Boolean isFluid) {
ref = 0;
list = new LinkedList<>();
this.isFluid = isFluid;
}
public SPacketMEInventoryUpdate(byte b) {
ref = b;
list = new LinkedList<>();
}
@Override
public void fromBytes(ByteBuf buf) {
isFluid = buf.readBoolean();
long amount = buf.readLong();
ref = buf.readByte();
list = new LinkedList<>();
try {
for (int i = 0; i < amount; i++) {
if (isFluid) {
list.add(AEFluidStack.loadFluidStackFromPacket(buf));
} else {
list.add(AEItemStack.loadItemStackFromPacket(buf));
}
}
} catch (IOException io) {
io.printStackTrace();
}
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeBoolean(isFluid);
buf.writeLong(list.size());
buf.writeByte(ref);
try {
for (Object is : list) {
if (is instanceof IAEItemStack) ((IAEItemStack) is).writeToPacket(buf);
if (is instanceof IAEFluidStack) ((IAEFluidStack) is).writeToPacket(buf);
}
} catch (IOException io) {
io.printStackTrace();
}
}
public void appendItem(final IAEItemStack is) throws BufferOverflowException {
list.add(is);
}
public void appendFluid(final IAEFluidStack is) throws BufferOverflowException {
list.add(is);
}
public boolean isEmpty() {
return this.list.isEmpty();
}
public static class Handler implements IMessageHandler<SPacketMEInventoryUpdate, IMessage> {
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public IMessage onMessage(SPacketMEInventoryUpdate message, MessageContext ctx) {
final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if (gs instanceof GuiFluidMonitor) {
((GuiFluidMonitor) gs).postUpdate((List) message.list);
} else if (gs instanceof GuiItemMonitor) {
((GuiItemMonitor) gs).postUpdate((List) message.list);
} else if (gs instanceof GuiFluidCraftConfirm) {
((GuiFluidCraftConfirm) gs).postUpdate((List) message.list, message.ref);
} else if (gs instanceof GuiLevelMaintainer) {
((GuiLevelMaintainer) gs).postUpdate((List) message.list);
}
return null;
}
}
}
@@ -0,0 +1,114 @@
package com.glodblock.github.network;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import appeng.api.storage.data.IAEItemStack;
import appeng.util.item.AEItemStack;
import com.glodblock.github.client.gui.GuiFluidCraftConfirm;
import com.glodblock.github.client.gui.GuiItemMonitor;
import com.glodblock.github.client.gui.GuiLevelMaintainer;
import com.glodblock.github.common.Config;
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 io.netty.buffer.ByteBuf;
/**
* Packet dedicated to item inventory update.
*/
public class SPacketMEItemInvUpdate implements IMessage {
private List<IAEItemStack> list = new ArrayList<>();
private byte ref = (byte) 0;
private boolean resort = true;
public SPacketMEItemInvUpdate() {}
/**
* Used for the GUI to confirm crafting. 0 = available 1 = pending 2 = missing
*/
public SPacketMEItemInvUpdate(byte b) {
ref = b;
}
/**
* If resort, call "updateView()". Used when multiple packets are sent to open an inventory; only the last packet
* should resort.
*
* @param resort whether this packet should resort the term or not
*/
public SPacketMEItemInvUpdate(boolean resort) {
this.resort = resort;
}
@Override
public void fromBytes(ByteBuf buf) {
ref = buf.readByte();
resort = buf.readBoolean();
int amount = buf.readInt();
list = new ArrayList<>(amount);
try {
for (int i = 0; i < amount; i++) {
list.add(AEItemStack.loadItemStackFromPacket(buf));
}
} catch (Exception io) {
System.out.println("Error handling payload w/ " + amount + " items.");
io.printStackTrace();
}
}
@Override
public void toBytes(ByteBuf buf) {
buf.writeByte(ref);
buf.writeBoolean(resort);
buf.writeInt(list.size());
try {
for (IAEItemStack is : list) {
is.writeToPacket(buf);
}
} catch (IOException io) {
io.printStackTrace();
}
}
public void setResort(boolean resort) {
this.resort = resort;
}
public void appendItem(final IAEItemStack is) throws BufferOverflowException {
if (list.size() <= Config.packetSize) {
list.add(is);
} else {
throw new BufferOverflowException();
}
}
public boolean isEmpty() {
return this.list.isEmpty();
}
public static class Handler implements IMessageHandler<SPacketMEItemInvUpdate, IMessage> {
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public IMessage onMessage(SPacketMEItemInvUpdate message, MessageContext ctx) {
final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if (gs instanceof GuiItemMonitor) {
((GuiItemMonitor) gs).postUpdate(message.list, message.resort);
} else if (gs instanceof GuiFluidCraftConfirm) {
((GuiFluidCraftConfirm) gs).postUpdate(message.list, message.ref);
} else if (gs instanceof GuiLevelMaintainer) {
((GuiLevelMaintainer) gs).postUpdate(message.list);
}
return null;
}
}
}