Skip to content

Commit

Permalink
Network throttle: Force ME update packets to be sent once every 50ms.
Browse files Browse the repository at this point in the history
1. Item and fluid packets are separated to their own classes, as they are
not even allowed to be mixed together in the first place. This will enforce a strict
separation of the two.

2. New network worker thread for handling ME inventory updates. Instead of
creating packets directly, classes should schedule a packet to be sent at the
next 50ms boundary. The packet has a limit of 256 items to prevent killing the
client; should be adjusted until a good balance between startup time (see below)
and client lag is reached.

3. Upon opening a terminal GUI, ME update packets are split. Only the last received
packet will trigger a terminal sorting, so if the ME system is large, it may take
several seconds (!) to load all the items.
  • Loading branch information
firenoo committed Mar 21, 2023
1 parent 6a244c1 commit 708cdec
Show file tree
Hide file tree
Showing 12 changed files with 333 additions and 114 deletions.
16 changes: 12 additions & 4 deletions src/main/java/com/glodblock/github/FluidCraft.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@
import com.glodblock.github.loader.ItemAndBlockHolder;
import com.glodblock.github.loader.RecipeLoader;
import com.glodblock.github.loader.filter.FluidFilter;
import com.glodblock.github.network.SPacketMEUpdateBuffer;
import com.glodblock.github.proxy.CommonProxy;
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(
Expand Down Expand Up @@ -85,6 +83,16 @@ public static void postInit(FMLPostInitializationEvent event) {
proxy.postInit(event);
}

@Mod.EventHandler
public void onServerStart(FMLServerStartingEvent event) {
SPacketMEUpdateBuffer.init();
}

@Mod.EventHandler
public void onServerStop(FMLServerStoppedEvent event) {
SPacketMEUpdateBuffer.disable();
}

@Mod.EventHandler
public void onLoadComplete(FMLLoadCompleteEvent event) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ public GuiFluidMonitor(final InventoryPlayer inventoryPlayer, final ITerminalHos
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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ public GuiItemMonitor(final InventoryPlayer inventoryPlayer, final ITerminalHost
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();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void setOffsetY(int y) {
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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.glodblock.github.client.gui.container;

import java.nio.BufferOverflowException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.minecraft.entity.player.EntityPlayer;
Expand Down Expand Up @@ -43,7 +44,7 @@
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.SPacketMEUpdateBuffer;
import com.glodblock.github.util.Util;

public class ContainerFluidMonitor extends FCContainerMonitor<IAEFluidStack> {
Expand Down Expand Up @@ -126,46 +127,34 @@ public ItemStack transferStackInSlot(final EntityPlayer p, final int idx) {
protected void processItemList() {
if (!this.fluids.isEmpty()) {
final IItemList<IAEFluidStack> monitorCache = this.monitor.getStorageList();
final SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate(true);

List<IAEFluidStack> toSend = new ArrayList<>();
for (final IAEFluidStack is : this.fluids) {
final IAEFluidStack send = monitorCache.findPrecise(is);
if (send == null) {
is.setStackSize(0);
piu.appendFluid(is);
if (send != null) {
toSend.add(send);
} else {
piu.appendFluid(send);
is.setStackSize(0);
toSend.add(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) {
if (c instanceof EntityPlayerMP) {
SPacketMEUpdateBuffer.scheduleFluidUpdate((EntityPlayerMP) c, toSend);
}
}
this.fluids.resetStatus();
}
}

@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) {
try {
piu.appendFluid(send);
} catch (final BufferOverflowException boe) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
piu = new SPacketMEInventoryUpdate(true);
piu.appendFluid(send);
}
List<IAEFluidStack> toSend = new ArrayList<>();
for (final IAEFluidStack is : monitorCache) {
toSend.add(is);
}
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
SPacketMEUpdateBuffer.scheduleFluidUpdate((EntityPlayerMP) c, toSend);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.glodblock.github.client.gui.container;

import java.nio.BufferOverflowException;
import java.util.ArrayList;
import java.util.List;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
Expand All @@ -25,9 +26,8 @@
import appeng.me.helpers.ChannelPowerSrc;
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.SPacketMEUpdateBuffer;

public class ContainerItemMonitor extends FCContainerMonitor<IAEItemStack> {

Expand Down Expand Up @@ -95,46 +95,34 @@ protected ContainerItemMonitor(final InventoryPlayer ip, final ITerminalHost mon
protected void processItemList() {
if (!this.items.isEmpty()) {
final IItemList<IAEItemStack> monitorCache = this.monitor.getStorageList();
final SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate();
List<IAEItemStack> toSend = new ArrayList<>();
for (final IAEItemStack is : this.items) {
final IAEItemStack send = monitorCache.findPrecise(is);
if (send == null) {
is.setStackSize(0);
piu.appendItem(is);
if (send != null) {
toSend.add(send);
} else {
piu.appendItem(send);
is.setStackSize(0);
toSend.add(is);
}
}

if (!piu.isEmpty()) {
this.items.resetStatus();

for (final Object c : this.crafters) {
if (c instanceof EntityPlayer) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
}
for (final Object c : this.crafters) {
if (c instanceof EntityPlayer) {
SPacketMEUpdateBuffer.scheduleItemUpdate((EntityPlayerMP) c, toSend);
}
}
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) {
try {
piu.appendItem(send);
} catch (final BufferOverflowException boe) {
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);

piu = new SPacketMEInventoryUpdate();
piu.appendItem(send);
}
List<IAEItemStack> toSend = new ArrayList<>();
for (final IAEItemStack is : monitorCache) {
toSend.add(is);
}
FluidCraft.proxy.netHandler.sendTo(piu, (EntityPlayerMP) c);
SPacketMEUpdateBuffer.scheduleItemUpdate((EntityPlayerMP) c, toSend);
}
}

Expand All @@ -143,6 +131,9 @@ public void removeCraftingFromCrafters(final ICrafting c) {
super.removeCraftingFromCrafters(c);
if (this.crafters.isEmpty() && this.monitor != null) {
this.monitor.removeListener(this);
if (c instanceof EntityPlayerMP) {
SPacketMEUpdateBuffer.clear((EntityPlayerMP) c);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import appeng.util.Platform;

import com.glodblock.github.inventory.item.IWirelessTerminal;
import com.glodblock.github.network.SPacketMEUpdateBuffer;

public abstract class FCContainerMonitor<T extends IAEStack<T>> extends FCBaseContainer
implements IConfigManagerHost, IConfigurableObject, IMEMonitorHandlerReceiver<T> {
Expand Down Expand Up @@ -158,6 +159,10 @@ public void onContainerClosed(final EntityPlayer player) {
super.onContainerClosed(player);
if (this.monitor != null) {
this.monitor.removeListener(this);
if (player instanceof EntityPlayerMP && Platform.isServer()) {
SPacketMEUpdateBuffer.clear((EntityPlayerMP) player);
}

}
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/glodblock/github/loader/ChannelLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ public void run() {
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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.glodblock.github.network;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nullable;

import net.minecraft.entity.player.EntityPlayerMP;
Expand All @@ -9,7 +12,6 @@
import appeng.api.storage.data.IAEItemStack;
import appeng.util.item.AEItemStack;

import com.glodblock.github.FluidCraft;
import com.glodblock.github.client.gui.container.ContainerLevelMaintainer;
import com.glodblock.github.common.tile.TileLevelMaintainer;

Expand Down Expand Up @@ -88,27 +90,27 @@ public void toBytes(ByteBuf buf) {
public static class Handler implements IMessageHandler<CPacketLevelMaintainer, IMessage> {

private void refresh(ContainerLevelMaintainer cca, EntityPlayerMP player) {
SPacketMEInventoryUpdate piu = new SPacketMEInventoryUpdate(false);
List<IAEItemStack> toSend = new ArrayList<>(TileLevelMaintainer.REQ_COUNT);
for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) {
IAEItemStack is = cca.getTile().requests.getRequestQtyStack(i);
IAEItemStack is1 = cca.getTile().requests.getRequestBatches().getStack(i);
if (is != null) {
if (is1 != null) {
NBTTagCompound data;
data = is1.getItemStack().getTagCompound();
piu.appendItem(
toSend.add(
setTag(
is,
is1.getStackSize(),
i,
data.getBoolean("Enable"),
cca.getTile().requests.getState(i).ordinal()));
} else {
piu.appendItem(setTag(is, 0, i, true, 0));
toSend.add(setTag(is, 0, i, true, 0));
}
}
}
FluidCraft.proxy.netHandler.sendTo(piu, player);
SPacketMEUpdateBuffer.scheduleItemUpdate(player, toSend);
}

@Nullable
Expand Down
Loading

0 comments on commit 708cdec

Please sign in to comment.