From 6ac5ea30f00405ef0e5926cf2d77262d5dec5598 Mon Sep 17 00:00:00 2001 From: Kogepan229 <73163994+Kogepan229@users.noreply.github.com> Date: Tue, 10 Jun 2025 05:12:08 +0900 Subject: [PATCH] Rewrite Level Maintainer/Terminal Logic (#294) Co-authored-by: boubou19 --- .../github/api/registries/ILevelViewable.java | 6 + .../github/api/registries/LevelItemInfo.java | 20 + .../github/api/registries/LevelState.java | 9 + .../github/client/gui/GuiLevelMaintainer.java | 138 ++-- .../github/client/gui/GuiLevelTerminal.java | 245 ++----- .../container/ContainerLevelMaintainer.java | 100 +-- .../gui/container/ContainerLevelTerminal.java | 299 ++------ .../common/parts/PartFluidLevelEmitter.java | 13 + .../common/tile/TileLevelMaintainer.java | 694 ++++++++++-------- .../PartFluidLevelEmitterAdapter.java | 20 +- .../adapters/PartLevelEmitterAdapter.java | 49 +- .../opencomputers/DriverLevelMaintainer.java | 16 +- .../LevelMaintainerWailaDataProvider.java | 31 +- .../github/loader/ChannelLoader.java | 6 + .../network/CPacketLevelMaintainer.java | 63 +- .../SPacketLevelMaintainerGuiUpdate.java | 122 +++ .../network/SPacketLevelTerminalUpdate.java | 643 ++++++---------- .../network/SPacketMEItemInvUpdate.java | 3 - 18 files changed, 1050 insertions(+), 1427 deletions(-) create mode 100644 src/main/java/com/glodblock/github/api/registries/LevelItemInfo.java create mode 100644 src/main/java/com/glodblock/github/api/registries/LevelState.java create mode 100644 src/main/java/com/glodblock/github/network/SPacketLevelMaintainerGuiUpdate.java diff --git a/src/main/java/com/glodblock/github/api/registries/ILevelViewable.java b/src/main/java/com/glodblock/github/api/registries/ILevelViewable.java index 2f192602..21ab6f50 100644 --- a/src/main/java/com/glodblock/github/api/registries/ILevelViewable.java +++ b/src/main/java/com/glodblock/github/api/registries/ILevelViewable.java @@ -16,11 +16,13 @@ public interface ILevelViewable extends IGridHost, ISide, ISegmentedInventory, I TileEntity getTile(); + @Deprecated default long getSortValue() { TileEntity te = getTile(); return ((long) te.zCoord << 24) ^ ((long) te.xCoord << 8) ^ te.yCoord; } + @Deprecated default boolean shouldDisplay() { return true; } @@ -39,6 +41,7 @@ public interface ILevelViewable extends IGridHost, ISide, ISegmentedInventory, I return 1; }; + @Deprecated default ItemStack getSelfItemStack() { return null; } @@ -46,8 +49,11 @@ public interface ILevelViewable extends IGridHost, ISide, ISegmentedInventory, I /** * "Target" Display representation */ + @Deprecated default ItemStack getDisplayItemStack() { return null; } + LevelItemInfo[] getLevelItemInfoList(); + } diff --git a/src/main/java/com/glodblock/github/api/registries/LevelItemInfo.java b/src/main/java/com/glodblock/github/api/registries/LevelItemInfo.java new file mode 100644 index 00000000..82dc68df --- /dev/null +++ b/src/main/java/com/glodblock/github/api/registries/LevelItemInfo.java @@ -0,0 +1,20 @@ +package com.glodblock.github.api.registries; + +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; + +public class LevelItemInfo { + + public ItemStack stack; + public long quantity; + public long batchSize; + public LevelState state; + + public LevelItemInfo(@NotNull ItemStack stack, long quantity, long batchSize, LevelState state) { + this.stack = stack; + this.quantity = quantity; + this.batchSize = batchSize; + this.state = state; + } +} diff --git a/src/main/java/com/glodblock/github/api/registries/LevelState.java b/src/main/java/com/glodblock/github/api/registries/LevelState.java new file mode 100644 index 00000000..fb2c3ca1 --- /dev/null +++ b/src/main/java/com/glodblock/github/api/registries/LevelState.java @@ -0,0 +1,9 @@ +package com.glodblock.github.api.registries; + +public enum LevelState { + None, + Idle, + Craft, + Export, + Error +} diff --git a/src/main/java/com/glodblock/github/client/gui/GuiLevelMaintainer.java b/src/main/java/com/glodblock/github/client/gui/GuiLevelMaintainer.java index 7e405208..ee396053 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiLevelMaintainer.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiLevelMaintainer.java @@ -1,7 +1,5 @@ package com.glodblock.github.client.gui; -import static com.glodblock.github.client.gui.container.ContainerLevelMaintainer.createLevelValues; - import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; @@ -13,7 +11,6 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import net.minecraftforge.common.util.ForgeDirection; @@ -23,12 +20,11 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import com.glodblock.github.FluidCraft; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.client.gui.container.ContainerLevelMaintainer; import com.glodblock.github.common.item.ItemWirelessUltraTerminal; import com.glodblock.github.common.parts.PartLevelTerminal; import com.glodblock.github.common.tile.TileLevelMaintainer; -import com.glodblock.github.common.tile.TileLevelMaintainer.State; -import com.glodblock.github.common.tile.TileLevelMaintainer.TLMTags; import com.glodblock.github.inventory.gui.GuiType; import com.glodblock.github.inventory.gui.MouseRegionManager; import com.glodblock.github.inventory.item.IWirelessTerminal; @@ -49,9 +45,6 @@ import appeng.client.gui.AEBaseGui; import appeng.client.gui.widgets.GuiTabButton; import appeng.container.AEBaseContainer; import appeng.container.slot.SlotFake; -import appeng.core.AEConfig; -import appeng.core.AELog; -import appeng.core.features.AEFeature; import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.packets.PacketNEIDragClick; import appeng.util.calculators.ArithHelper; @@ -70,8 +63,6 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { private final Component[] component = new Component[TileLevelMaintainer.REQ_COUNT]; private final MouseRegionManager mouseRegions = new MouseRegionManager(this); private Widget focusedWidget; - private int lastWorkingTick; - private int refreshTick; private final CoFHFontRenderer render; protected ItemStack icon = null; @@ -89,7 +80,7 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { TEX_BG, Minecraft.getMinecraft().getTextureManager(), true); - this.refreshTick = 0; + if (ipl.player.openContainer instanceof AEBaseContainer container) { var target = container.getTarget(); if (target instanceof PartLevelTerminal terminal) { @@ -126,40 +117,11 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { } } - - } - - public void postUpdate(List list) { - for (Slot slot : this.cont.getRequestSlots()) { - if (!slot.getHasStack()) { - component[slot.getSlotIndex()].setState(State.None); - } - } - for (IAEItemStack is : list) { - NBTTagCompound data = is.getItemStack().getTagCompound(); - if (data == null) { - if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { - AELog.info("Received empty configuration: ", is); - } - continue; - } - long batch = data.getLong(TLMTags.Batch.tagName); - long quantity = data.getLong(TLMTags.Quantity.tagName); - int idx = data.getInteger(TLMTags.Index.tagName); - boolean isEnable = data.getBoolean(TLMTags.Enable.tagName); - State state = State.values()[data.getInteger(TLMTags.State.tagName)]; - component[idx].getQty().textField.setText(String.valueOf(quantity)); - component[idx].getBatch().textField.setText(String.valueOf(batch)); - component[idx].getQty().validate(); - component[idx].getBatch().validate(); - component[idx].setEnable(isEnable); - component[idx].setState(state); - } } + @Override public void initGui() { super.initGui(); - this.lastWorkingTick = this.refreshTick; for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) { component[i] = new Component( new Widget( @@ -176,7 +138,8 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { new GuiFCImgButton(guiLeft + 9, guiTop + 20 + 19 * i, "ENABLE", "ENABLE", false), new GuiFCImgButton(guiLeft + 9, guiTop + 20 + 19 * i, "DISABLE", "DISABLE", false), new FCGuiLineField(fontRendererObj, guiLeft + 47, guiTop + 33 + 19 * i, 125), - this.buttonList); + this.buttonList, + this.cont); } if (this.icon != null) { this.originalGuiBtn = new GuiTabButton( @@ -188,11 +151,10 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { this.originalGuiBtn.setHideEdge(13); this.buttonList.add(originalGuiBtn); } - FluidCraft.proxy.netHandler.sendToServer(new CPacketLevelMaintainer(Action.Refresh)); } + @Override public void drawScreen(final int mouseX, final int mouseY, final float btn) { - this.refreshTick++; super.drawScreen(mouseX, mouseY, btn); for (Component com : this.component) { com.getQty().textField.handleTooltip(mouseX, mouseY, this); @@ -205,12 +167,7 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { mc.getTextureManager().bindTexture(TEX_BG); drawTexturedModalRect(offsetX, offsetY, 0, 0, 176, ySize); - int tick = this.refreshTick; - int interval = 20; - if (tick > lastWorkingTick + interval && this.focusedWidget == null) { - FluidCraft.proxy.netHandler.sendToServer(new CPacketLevelMaintainer(Action.Refresh)); - lastWorkingTick = this.refreshTick; - } + for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) { this.component[i].draw(); } @@ -294,20 +251,6 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { } } - @Override - protected void handleMouseClick(final Slot slot, final int slotIdx, final int ctrlDown, final int mouseButton) { - if (slot instanceof SlotFluidConvertingFake && this.cont.getPlayerInv().getItemStack() != null) { - this.component[slot.getSlotIndex()].getQty().textField - .setText(String.valueOf(this.cont.getPlayerInv().getItemStack().stackSize)); - return; - } - super.handleMouseClick(slot, slotIdx, ctrlDown, mouseButton); - } - - public void updateAmount(int idx, int stackSize) { - this.component[idx].getQty().textField.setText(String.valueOf(stackSize)); - } - @Override protected void actionPerformed(final GuiButton btn) { if (btn == originalGuiBtn) { @@ -351,6 +294,15 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { return null; } + @Override + protected void handleMouseClick(Slot slot, int slotIdx, int ctrlDown, int mouseButton) { + if (slot instanceof SlotFluidConvertingFake && this.cont.getPlayerInv().getItemStack() == null) { + slot.putStack(null); + this.component[slot.getSlotIndex()].reset(); + } + super.handleMouseClick(slot, slotIdx, ctrlDown, mouseButton); + } + @Override public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button) { if (draggedStack == null) { @@ -366,11 +318,9 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { for (int i = 0; i < this.cont.getRequestSlots().length; i++) { SlotFluidConvertingFake slot = this.cont.getRequestSlots()[i]; if (slotAtPosition.equals(slot)) { - ItemStack itemStack = createLevelValues(draggedStack.copy()); - itemStack.getTagCompound().setInteger(TLMTags.Index.tagName, i); - slot.putStack(itemStack); - NetworkHandler.instance.sendToServer(new PacketNEIDragClick(itemStack, slot.getSlotIndex())); - this.updateAmount(slot.getSlotIndex(), itemStack.stackSize); + slot.putStack(draggedStack); + component[i].reset(); + NetworkHandler.instance.sendToServer(new PacketNEIDragClick(draggedStack, slot.getSlotIndex())); return true; } } @@ -382,26 +332,44 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { return false; } + public void updateComponent(int index, long quantity, long batchSize, boolean isEnabled, LevelState state) { + if (index < 0 || index >= TileLevelMaintainer.REQ_COUNT) return; + component[index].setEnable(isEnabled); + component[index].setState(state); + component[index].getQty().textField.setText(String.valueOf(quantity)); + component[index].getBatch().textField.setText(String.valueOf(batchSize)); + component[index].getQty().validate(); + component[index].getBatch().validate(); + } + + public void updateComponent(int index, LevelState state) { + if (index < 0 || index >= TileLevelMaintainer.REQ_COUNT) return; + component[index].setState(state); + } + private class Component { - public boolean isEnable = true; + public boolean isEnable = false; private final Widget qty; private final Widget batch; private final GuiFCImgButton disable; private final GuiFCImgButton enable; private final GuiFCImgButton submit; private final FCGuiLineField line; - private State state; + private LevelState state; + private final ContainerLevelMaintainer container; public Component(Widget qtyInput, Widget batchInput, GuiFCImgButton submitBtn, GuiFCImgButton enableBtn, - GuiFCImgButton disableBtn, FCGuiLineField line, List buttonList) { + GuiFCImgButton disableBtn, FCGuiLineField line, List buttonList, + ContainerLevelMaintainer container) { this.qty = qtyInput; this.batch = batchInput; this.enable = enableBtn; this.disable = disableBtn; this.submit = submitBtn; this.line = line; - this.state = State.None; + this.state = LevelState.None; + this.container = container; buttonList.add(this.submit); buttonList.add(this.enable); buttonList.add(this.disable); @@ -435,18 +403,25 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { batch.validate(); if (qty.getAmount() != null) { this.send(qty); + qty.textField.setText(String.valueOf(qty.getAmount())); } if (batch.getAmount() != null) { this.send(batch); + batch.textField.setText(String.valueOf(batch.getAmount())); } didSomething = true; } else if (this.enable == btn) { + this.setEnable(false); FluidCraft.proxy.netHandler.sendToServer(new CPacketLevelMaintainer(Action.Enable, this.getIndex())); didSomething = true; } else if (this.disable == btn) { - FluidCraft.proxy.netHandler.sendToServer(new CPacketLevelMaintainer(Action.Disable, this.getIndex())); - didSomething = true; + if (this.container.getInventory().get(this.getIndex()) != null) { + this.setEnable(true); + FluidCraft.proxy.netHandler + .sendToServer(new CPacketLevelMaintainer(Action.Disable, this.getIndex())); + didSomething = true; + } } return didSomething; } @@ -531,9 +506,18 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { } } - public void setState(State state) { + public void setState(LevelState state) { this.state = state; } + + public void reset() { + this.qty.textField.setText("0"); + this.batch.textField.setText("0"); + this.qty.validate(); + this.batch.validate(); + this.setEnable(false); + this.setState(LevelState.None); + } } private class Widget { @@ -585,7 +569,7 @@ public class GuiLevelMaintainer extends AEBaseGui implements INEIGuiHandler { public void validate() { final double result = Calculator.conversion(this.textField.getText()); - if (Double.isNaN(result)) { + if (Double.isNaN(result) || result < 0) { this.amount = null; this.textField.setTextColor(0xFF0000); } else { diff --git a/src/main/java/com/glodblock/github/client/gui/GuiLevelTerminal.java b/src/main/java/com/glodblock/github/client/gui/GuiLevelTerminal.java index 0ca7e7e1..3828b91b 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiLevelTerminal.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiLevelTerminal.java @@ -1,13 +1,6 @@ package com.glodblock.github.client.gui; import static com.glodblock.github.common.item.ItemWirelessUltraTerminal.hasInfinityBoosterCard; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.CLEAR_ALL_BIT; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.DISCONNECT_BIT; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.PacketAdd; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.PacketEntry; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.PacketOverwrite; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.PacketRemove; -import static com.glodblock.github.network.SPacketLevelTerminalUpdate.PacketRename; import java.text.NumberFormat; import java.util.ArrayList; @@ -17,7 +10,6 @@ import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -34,8 +26,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import net.minecraftforge.common.util.ForgeDirection; @@ -45,16 +35,17 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import com.glodblock.github.FluidCraft; +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.client.gui.base.FCBaseMEGui; import com.glodblock.github.client.gui.container.ContainerLevelTerminal; -import com.glodblock.github.common.tile.TileLevelMaintainer.State; -import com.glodblock.github.common.tile.TileLevelMaintainer.TLMTags; import com.glodblock.github.inventory.InventoryHandler; import com.glodblock.github.inventory.gui.GuiType; import com.glodblock.github.network.CPacketInventoryAction; import com.glodblock.github.network.CPacketLevelTerminalCommands; import com.glodblock.github.network.CPacketLevelTerminalCommands.Action; import com.glodblock.github.network.CPacketRenamer; +import com.glodblock.github.network.SPacketLevelTerminalUpdate; import com.glodblock.github.util.FCGuiColors; import com.glodblock.github.util.ModAndClassUtil; import com.glodblock.github.util.NameConst; @@ -65,7 +56,6 @@ import appeng.api.config.TerminalFontSize; import appeng.api.config.TerminalStyle; import appeng.api.config.YesNo; import appeng.api.storage.ITerminalHost; -import appeng.api.storage.data.IAEItemStack; import appeng.client.gui.IGuiTooltipHandler; import appeng.client.gui.widgets.GuiImgButton; import appeng.client.gui.widgets.GuiScrollbar; @@ -83,7 +73,6 @@ import appeng.core.localization.PlayerMessages; import appeng.helpers.InventoryAction; import appeng.integration.IntegrationRegistry; import appeng.integration.IntegrationType; -import appeng.tile.inventory.AppEngInternalInventory; import appeng.util.Platform; import appeng.util.ReadableNumberConverter; import appeng.util.item.AEItemStack; @@ -151,6 +140,7 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel }; searchFieldNames.setFocused(true); extraOptionsText.add(ButtonToolTips.HighlightInterface.getLocal()); + online = true; } public GuiLevelTerminal(final InventoryPlayer inventoryPlayer, final ITerminalHost te) { @@ -184,8 +174,6 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel final int unusedSpace = height - ySize; guiTop = (int) Math.floor(unusedSpace / (unusedSpace < 0 ? 3.8f : 2.0f)); - // modeSwitchView = new GuiFCImgButton(guiLeft + xSize - 40, guiTop + 1, "SWITCH", "OFF", false); - // modeSwitchEdit = new GuiFCImgButton(guiLeft + xSize - 40, guiTop + 1, "SWITCH", "ON", false); offsetY = guiTop + 8; terminalStyleBox = new GuiImgButton( guiLeft - 18, @@ -290,7 +278,6 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel buttonList.add(terminalStyleBox); buttonList.add(searchStringSave); buttonList.add(craftingStatusBtn); - // buttonList.add(Objects.equals(currentMode, "OFF") ? modeSwitchView : modeSwitchEdit); addSwitchGuiBtns(); super.drawScreen(mouseX, mouseY, btn); @@ -322,11 +309,6 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel @Override protected void actionPerformed(final GuiButton btn) { -// if (btn == modeSwitchView) { -// currentMode = "ON"; -// } else if (btn == modeSwitchEdit) { -// currentMode = "OFF"; -// } else if (ModAndClassUtil.isSaveText && btn == searchStringSave) { final boolean backwards = Mouse.isButtonDown(1); @@ -566,26 +548,21 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel if (viewY + rowYBot <= titleBottom) { continue; } - AppEngInternalInventory inv = entry.getInventory(); for (int col = 0; col < entry.rowSize; ++col) { final int colLeft = col * 18 + slotLeftMargin + 1; final int colRight = colLeft + 18 + 1; final int slotIdx = row * entry.rowSize + col; - ItemStack stack = inv.getStackInSlot(slotIdx); + LevelItemInfo info = entry.infoList[slotIdx]; boolean tooltip = relMouseX > colLeft - 1 && relMouseX < colRight - 1 && relMouseY >= Math.max(viewY + rowYTop, LevelTerminalSection.TITLE_HEIGHT) && relMouseY < Math.min(viewY + rowYBot, viewHeight); - if (stack != null) { - - NBTTagCompound data = stack.getTagCompound(); - ItemStack itemStack = data.hasKey(TLMTags.Stack.tagName) - ? ItemStack.loadItemStackFromNBT(data.getCompoundTag(TLMTags.Stack.tagName)) - : stack.copy(); - long quantity = data.getLong(TLMTags.Quantity.tagName); - long batch = data.getLong(TLMTags.Batch.tagName); - State state = State.values()[data.getInteger(TLMTags.State.tagName)]; + if (info != null) { + ItemStack itemStack = info.stack; + long quantity = info.quantity; + long batch = info.batchSize; + LevelState state = info.state; GL11.glPushMatrix(); GL11.glTranslatef(colLeft, viewY + rowYTop + 1, ITEM_STACK_Z); @@ -608,7 +585,7 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel drawRect(offset, offset, offset + size, offset + size, color); GL11.glTranslatef(0.0f, 0.0f, ITEM_STACK_OVERLAY_Z - ITEM_STACK_Z); this.drawReadableAmount(fontRendererObj, quantity, true, 16777215); - if (batch > 0) { + if (batch >= 0) { this.drawReadableAmount(fontRendererObj, batch, false, 16777215); } RenderHelper.disableStandardItemLighting(); @@ -622,7 +599,7 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel drawRect(0, 0, 16, 16, GuiColors.ItemSlotOverlayUnpowered.getColor()); } } else { - tooltipStack = stack; + tooltipStack = itemStack; } GL11.glPopMatrix(); } else if (entry.filteredRecipes[slotIdx]) { @@ -846,58 +823,50 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel && mouseY < guiTop + HEADER_HEIGHT + viewHeight; } - public void postUpdate(List updates, int statusFlags) { - if ((statusFlags & CLEAR_ALL_BIT) == CLEAR_ALL_BIT) { - /* Should clear all client entries. */ - masterList.list.clear(); - } - /* Should indicate disconnected, so the terminal turns dark. */ - online = (statusFlags & DISCONNECT_BIT) != DISCONNECT_BIT; - - for (PacketEntry cmd : updates) { - parsePacketCmd(cmd); + public void receivePackets(List packets) { + for (SPacketLevelTerminalUpdate.PacketEntry packet : packets) { + parsePacket(packet); } masterList.markDirty(); } - private void parsePacketCmd(PacketEntry cmd) { - long id = cmd.entryId; - if (cmd instanceof PacketAdd addCmd) { + private void parsePacket(SPacketLevelTerminalUpdate.PacketEntry packet) { + if (packet instanceof SPacketLevelTerminalUpdate.PacketAdd packetAdd) { LevelTerminalEntry entry = new LevelTerminalEntry( - id, - addCmd.name, - addCmd.rows, - addCmd.rowSize, - addCmd.online).setLocation(addCmd.x, addCmd.y, addCmd.z, addCmd.dim, addCmd.side) - .setIcons(addCmd.selfItemStack, addCmd.displayItemStack).setItems(addCmd.items); - masterList.addEntry(entry); - } else if (cmd instanceof PacketRemove) { - masterList.removeEntry(id); - } else if (cmd instanceof PacketOverwrite owCmd) { - LevelTerminalEntry entry = masterList.list.get(id); + packetAdd.entryId, + packetAdd.name, + packetAdd.rows, + packetAdd.rowSize, + true).setLocation(packetAdd.x, packetAdd.y, packetAdd.z, packetAdd.dim, packetAdd.side) + .setInfoList(packetAdd.infolist); + this.masterList.addEntry(entry); + } else if (packet instanceof SPacketLevelTerminalUpdate.PacketRemove packetRemove) { + this.masterList.removeEntry(packetRemove.entryId); + } else if (packet instanceof SPacketLevelTerminalUpdate.PacketRename packetRename) { + LevelTerminalEntry entry = masterList.list.get(packetRename.entryId); + if (entry == null) return; - if (entry == null) { - return; - } - - if (owCmd.itemsValid) { - if (owCmd.allItemUpdate) { - entry.fullItemUpdate(owCmd.items, owCmd.validIndices.length); - } else { - entry.partialItemUpdate(owCmd.items, owCmd.validIndices); - } + if (StatCollector.canTranslate(packetRename.newName)) { + entry.customName = StatCollector.translateToLocal(packetRename.newName); + } else { + entry.customName = StatCollector.translateToFallback(packetRename.newName); } masterList.isDirty = true; - } else if (cmd instanceof PacketRename renameCmd) { - LevelTerminalEntry entry = masterList.list.get(id); + } else if (packet instanceof SPacketLevelTerminalUpdate.PacketDisconnect) { + online = false; + } - if (entry != null) { - if (StatCollector.canTranslate(renameCmd.newName)) { - entry.customName = StatCollector.translateToLocal(renameCmd.newName); - } else { - entry.customName = StatCollector.translateToFallback(renameCmd.newName); - } - } + else if (packet instanceof SPacketLevelTerminalUpdate.PacketOverwriteSlot packetOverwirteSlot) { + LevelTerminalEntry entry = masterList.list.get(packetOverwirteSlot.entryId); + if (entry == null) return; + + entry.infoList[packetOverwirteSlot.index] = packetOverwirteSlot.info; + masterList.isDirty = true; + } else if (packet instanceof SPacketLevelTerminalUpdate.PacketOverwirteAllSlot packetOverwirteAllSlot) { + LevelTerminalEntry entry = masterList.list.get(packetOverwirteAllSlot.entryId); + if (entry == null) return; + + entry.infoList = packetOverwirteAllSlot.infoList; masterList.isDirty = true; } } @@ -932,22 +901,23 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel @Override public List handleItemTooltip(ItemStack stack, int mouseX, int mouseY, List currentToolTip) { + if (stack == null || !isShiftKeyDown()) return currentToolTip; - if (stack != null && isShiftKeyDown() && stack.hasTagCompound()) { - NBTTagCompound data = stack.getTagCompound(); + for (LevelTerminalSection section : this.masterList.getVisibleSections()) { + for (LevelTerminalEntry entry : section.visibleEntries) { + for (LevelItemInfo info : entry.infoList) { + if (info != null && info.stack.equals(stack)) { + currentToolTip.add( + I18n.format(NameConst.TT_LEVEL_MAINTAINER_REQUEST_SIZE, "\n", false) + ": " + + NumberFormat.getInstance().format(info.quantity)); - if (data.hasKey(TLMTags.Quantity.tagName)) { - long quantity = data.getLong(TLMTags.Quantity.tagName); - long batch = data.getLong(TLMTags.Batch.tagName); - - currentToolTip.add( - I18n.format(NameConst.TT_LEVEL_MAINTAINER_REQUEST_SIZE, "\n", false) + ": " - + NumberFormat.getNumberInstance(Locale.US).format(quantity)); - - if (batch > 0) { - currentToolTip.add( - I18n.format(NameConst.TT_LEVEL_MAINTAINER_BATCH_SIZE, "\n", false) + ": " - + NumberFormat.getNumberInstance(Locale.US).format(batch)); + if (info.batchSize >= 0) { + currentToolTip.add( + I18n.format(NameConst.TT_LEVEL_MAINTAINER_BATCH_SIZE, "\n", false) + ": " + + NumberFormat.getInstance().format(info.batchSize)); + } + break; + } } } } @@ -1102,13 +1072,7 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel String name; List entries = new ArrayList<>(); - Set visibleEntries = new TreeSet<>(Comparator.comparing(e -> { - if (e.displayItemStack != null) { - return e.displayItemStack.getDisplayName() + e.id; - } else { - return String.valueOf(e.id); - } - })); + Set visibleEntries = new TreeSet<>(Comparator.comparing(e -> e.customName + e.id)); int height; private boolean isDirty = true; boolean visible = false; @@ -1148,18 +1112,22 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel entry.dispY = -9999; // Find search terms if (!output.isEmpty()) { - AppEngInternalInventory inv = entry.inv; boolean shouldAdd = false; - for (int i = 0; i < inv.getSizeInventory(); ++i) { - ItemStack stack = inv.getStackInSlot(i); - if (itemStackMatchesSearchTerm(stack, output)) { + for (int i = 0; i < entry.infoList.length; ++i) { + if (entry.infoList[i] == null) { + entry.filteredRecipes[i] = true; + continue; + } + + if (itemStackMatchesSearchTerm(entry.infoList[i].stack, output)) { shouldAdd = true; entry.filteredRecipes[i] = false; } else { entry.filteredRecipes[i] = true; } } + if (!shouldAdd) { continue; } @@ -1207,12 +1175,9 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel private class LevelTerminalEntry { String customName; - AppEngInternalInventory inv; GuiFCImgButton highlightButton; GuiFCImgButton renameButton; GuiFCImgButton configButton; - /** Nullable - icon that represents the interface's "target" */ - ItemStack displayItemStack; LevelTerminalSection section; long id; int x, y, z, dim, side; @@ -1220,7 +1185,8 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel int guiHeight; int dispY = -9999; boolean[] filteredRecipes; - int numItems = 0; + + LevelItemInfo[] infoList; LevelTerminalEntry(long id, String name, int rows, int rowSize, boolean online) { this.id = id; @@ -1236,7 +1202,6 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel customName = StatCollector.translateToFallback(name); } } - inv = new AppEngInternalInventory(null, rows * rowSize, 1); highlightButton = new GuiFCImgButton(1, 0, "HIGHLIGHT", "YES"); renameButton = new GuiFCImgButton(1, 0, "EDIT", "YES"); configButton = new GuiFCImgButton(1, 0, "CONFIG", "YES"); @@ -1254,53 +1219,11 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel return this; } - LevelTerminalEntry setIcons(ItemStack selfItemStack, ItemStack displayItemStack) { - this.displayItemStack = displayItemStack; - + LevelTerminalEntry setInfoList(LevelItemInfo[] infoList) { + this.infoList = infoList; return this; } - public void fullItemUpdate(NBTTagList items, int newSize) { - inv = new AppEngInternalInventory(null, newSize); - rows = newSize / rowSize; - numItems = 0; - - for (int i = 0; i < inv.getSizeInventory(); ++i) { - setItemInSlot(ItemStack.loadItemStackFromNBT(items.getCompoundTagAt(i)), i); - } - guiHeight = 18 * rows + 4; - } - - LevelTerminalEntry setItems(NBTTagList items) { - assert items.tagCount() == inv.getSizeInventory(); - - for (int i = 0; i < items.tagCount(); ++i) { - setItemInSlot(ItemStack.loadItemStackFromNBT(items.getCompoundTagAt(i)), i); - } - return this; - } - - public void partialItemUpdate(NBTTagList items, int[] validIndices) { - for (int i = 0; i < validIndices.length; ++i) { - setItemInSlot(ItemStack.loadItemStackFromNBT(items.getCompoundTagAt(i)), validIndices[i]); - } - } - - private void setItemInSlot(ItemStack stack, int idx) { - final int oldHasItem = inv.getStackInSlot(idx) != null ? 1 : 0; - final int newHasItem = stack != null ? 1 : 0; - - inv.setInventorySlotContents(idx, stack); - - // Update item count - numItems += newHasItem - oldHasItem; - assert numItems >= 0; - } - - public AppEngInternalInventory getInventory() { - return inv; - } - public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) { if (!section.visible || mouseButton < 0 || mouseButton > 2) { return false; @@ -1368,20 +1291,10 @@ public class GuiLevelTerminal extends FCBaseMEGui implements IDropToFillTextFiel default -> null;// drop item: }; - if (action != null) { - ItemStack itemStack = getInventory().getStackInSlot(slotIdx); - if (itemStack != null && itemStack.hasTagCompound() - && itemStack.getTagCompound().hasKey(TLMTags.Stack.tagName)) { - long batch = itemStack.getTagCompound().getLong(TLMTags.Batch.tagName); - NBTTagCompound stackData = itemStack.getTagCompound().getCompoundTag(TLMTags.Stack.tagName); - ItemStack is = ItemStack.loadItemStackFromNBT(stackData); - IAEItemStack stack = AEItemStack.create(is); - - if (stack == null) return true; - stack.setStackSize(batch); - ((AEBaseContainer) inventorySlots).setTargetStack(stack); - FluidCraft.proxy.netHandler.sendToServer(new CPacketInventoryAction(action, slotIdx, 0, stack)); - } + if (action != null && this.infoList[slotIdx] != null) { + AEItemStack aeStack = AEItemStack.create(this.infoList[slotIdx].stack); + ((AEBaseContainer) inventorySlots).setTargetStack(aeStack); + FluidCraft.proxy.netHandler.sendToServer(new CPacketInventoryAction(action, slotIdx, 0, aeStack)); } return true; diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelMaintainer.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelMaintainer.java index c21a18e6..81ab4629 100644 --- a/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelMaintainer.java +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelMaintainer.java @@ -1,20 +1,15 @@ package com.glodblock.github.client.gui.container; -import java.util.Objects; - import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; +import com.glodblock.github.FluidCraft; import com.glodblock.github.common.tile.TileLevelMaintainer; -import com.glodblock.github.common.tile.TileLevelMaintainer.State; -import com.glodblock.github.common.tile.TileLevelMaintainer.TLMTags; import com.glodblock.github.inventory.AeItemStackHandler; import com.glodblock.github.inventory.slot.SlotFluidConvertingFake; -import com.glodblock.github.util.Util; +import com.glodblock.github.network.SPacketLevelMaintainerGuiUpdate; import appeng.api.config.SecurityPermissions; import appeng.container.AEBaseContainer; @@ -26,6 +21,10 @@ public class ContainerLevelMaintainer extends AEBaseContainer { private final TileLevelMaintainer tile; private final SlotFluidConvertingFake[] requestSlots = new SlotFluidConvertingFake[TileLevelMaintainer.REQ_COUNT]; + private static final int UPDATE_INTERVAL = 20; + private boolean isFirstUpdate = true; + private int updateCount = UPDATE_INTERVAL; + public ContainerLevelMaintainer(InventoryPlayer ipl, TileLevelMaintainer tile) { super(ipl, tile); this.tile = tile; @@ -48,49 +47,14 @@ public class ContainerLevelMaintainer extends AEBaseContainer { @Override public void doAction(EntityPlayerMP player, InventoryAction action, int slotId, long id) { - Slot slot = getSlot(slotId); - if (slot instanceof SlotFluidConvertingFake) { + if (getSlot(slotId) instanceof SlotFluidConvertingFake slot) { final ItemStack stack = player.inventory.getItemStack(); switch (action) { - case PICKUP_OR_SET_DOWN -> { + case PICKUP_OR_SET_DOWN, PLACE_SINGLE, SPLIT_OR_PLACE_SINGLE -> { if (stack == null) { slot.putStack(null); } else { - ((SlotFluidConvertingFake) slot).putConvertedStack(createLevelValues(stack.copy())); - } - } - case PLACE_SINGLE -> { - if (stack != null) { - ((SlotFluidConvertingFake) slot).putConvertedStack( - createLevelValues(Objects.requireNonNull(Util.copyStackWithSize(stack, 1)))); - } - } - case SPLIT_OR_PLACE_SINGLE -> { - ItemStack inSlot = slot.getStack(); - if (inSlot != null) { - if (stack == null) { - slot.putStack( - createLevelValues( - Objects.requireNonNull( - Util.copyStackWithSize( - inSlot, - Math.max(1, inSlot.stackSize - 1))))); - } else if (stack.isItemEqual(inSlot)) { - slot.putStack( - createLevelValues( - Objects.requireNonNull( - Util.copyStackWithSize( - inSlot, - Math.min( - inSlot.getMaxStackSize(), - inSlot.stackSize + 1))))); - } else { - ((SlotFluidConvertingFake) slot).putConvertedStack( - createLevelValues(Objects.requireNonNull(Util.copyStackWithSize(stack, 1)))); - } - } else if (stack != null) { - ((SlotFluidConvertingFake) slot).putConvertedStack( - createLevelValues(Objects.requireNonNull(Util.copyStackWithSize(stack, 1)))); + slot.putConvertedStack(stack); } } default -> {} @@ -109,10 +73,8 @@ public class ContainerLevelMaintainer extends AEBaseContainer { for (int i = 0; i < this.getRequestSlots().length; i++) { SlotFluidConvertingFake slot = this.getRequestSlots()[i]; if (!slot.getHasStack()) { - ItemStack itemStack = ((Slot) this.inventorySlots.get(idx)).getStack(); - ItemStack configuration = createLevelValues(itemStack.copy()); - configuration.getTagCompound().setInteger(TLMTags.Index.tagName, i); - slot.putConvertedStack(configuration); + ItemStack itemStack = this.inventorySlots.get(idx).getStack(); + tile.updateStack(i, itemStack.copy()); break; } } @@ -123,35 +85,23 @@ public class ContainerLevelMaintainer extends AEBaseContainer { @Override public void detectAndSendChanges() { + super.detectAndSendChanges(); + if (Platform.isClient()) { + return; + } + this.verifyPermissions(SecurityPermissions.BUILD, false); - super.detectAndSendChanges(); + if (this.updateCount++ >= UPDATE_INTERVAL) { + this.updateGui(); + } } - public static ItemStack createLevelValues(ItemStack itemStack) { - var data = itemStack.hasTagCompound() ? itemStack.getTagCompound() : new NBTTagCompound(); - if (!data.hasKey(TLMTags.Stack.tagName)) { - var itemStackTag = new NBTTagCompound(); - itemStack.copy().writeToNBT(itemStackTag); - data.setTag(TLMTags.Stack.tagName, itemStackTag); - } - if (!data.hasKey(TLMTags.Quantity.tagName)) { - data.setLong(TLMTags.Quantity.tagName, itemStack.stackSize > 0 ? itemStack.stackSize : 1); - } - if (!data.hasKey(TLMTags.Batch.tagName)) { - data.setLong(TLMTags.Batch.tagName, 1); - } - if (!data.hasKey(TLMTags.Enable.tagName)) { - data.setBoolean(TLMTags.Enable.tagName, false); - } - if (data.hasKey(TLMTags.Index.tagName)) { - data.removeTag(TLMTags.Index.tagName); - } - - data.setInteger(TLMTags.State.tagName, State.None.ordinal()); - itemStack.setTagCompound(data); - - return itemStack; + public void updateGui() { + FluidCraft.proxy.netHandler.sendTo( + new SPacketLevelMaintainerGuiUpdate(this.tile.requests, !this.isFirstUpdate), + (EntityPlayerMP) this.getInventoryPlayer().player); + this.isFirstUpdate = false; + this.updateCount = 0; } - } diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelTerminal.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelTerminal.java index 7a69c615..49e7183f 100644 --- a/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelTerminal.java +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerLevelTerminal.java @@ -1,30 +1,27 @@ package com.glodblock.github.client.gui.container; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; -import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.ForgeDirection; +import org.jetbrains.annotations.Nullable; + import com.glodblock.github.FluidCraft; import com.glodblock.github.api.registries.ILevelViewable; +import com.glodblock.github.api.registries.LevelItemInfo; import com.glodblock.github.client.gui.container.base.FCBaseContainer; import com.glodblock.github.common.parts.PartLevelTerminal; import com.glodblock.github.coremod.registries.LevelTerminalRegistry; import com.glodblock.github.inventory.item.IWirelessTerminal; import com.glodblock.github.network.SPacketLevelTerminalUpdate; -import com.google.common.primitives.Ints; import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; @@ -32,12 +29,7 @@ import appeng.api.networking.IGridNode; import appeng.api.networking.security.IActionHost; import appeng.api.storage.ITerminalHost; import appeng.api.util.DimensionalCoord; -import appeng.helpers.InventoryAction; -import appeng.items.misc.ItemEncodedPattern; -import appeng.util.InventoryAdaptor; import appeng.util.Platform; -import appeng.util.inv.AdaptorPlayerHand; -import appeng.util.inv.ItemSlot; public class ContainerLevelTerminal extends FCBaseContainer { @@ -50,8 +42,8 @@ public class ContainerLevelTerminal extends FCBaseContainer { private final Map trackedById = new HashMap<>(); private IGrid grid; - private SPacketLevelTerminalUpdate dirty; - private boolean isDirty; + private SPacketLevelTerminalUpdate updatePacket; + private boolean isPacketDirty; private boolean wasOff; private int ticks = 0; @@ -63,11 +55,13 @@ public class ContainerLevelTerminal extends FCBaseContainer { } else if (monitorable instanceof IWirelessTerminal wirelessTerminal) { grid = wirelessTerminal.getActionableNode().getGrid(); } - dirty = this.updateList(); - if (dirty != null) { - this.isDirty = true; + + updatePacket = this.updateList(); + if (updatePacket != null) { + this.isPacketDirty = true; } else { - dirty = new SPacketLevelTerminalUpdate(); + updatePacket = new SPacketLevelTerminalUpdate(); + this.isPacketDirty = false; } } @@ -92,7 +86,7 @@ public class ContainerLevelTerminal extends FCBaseContainer { if (!wasOff) { SPacketLevelTerminalUpdate update = new SPacketLevelTerminalUpdate(); - update.setDisconnect(); + update.addDisconnectEntry(); wasOff = true; FluidCraft.proxy.netHandler.sendTo(update, (EntityPlayerMP) this.getPlayerInv().player); } @@ -100,149 +94,20 @@ public class ContainerLevelTerminal extends FCBaseContainer { } wasOff = false; - if (isDirty) { - FluidCraft.proxy.netHandler.sendTo(dirty, (EntityPlayerMP) this.getPlayerInv().player); - dirty = new SPacketLevelTerminalUpdate(); - isDirty = false; + if (isPacketDirty) { + FluidCraft.proxy.netHandler.sendTo(updatePacket, (EntityPlayerMP) this.getPlayerInv().player); + updatePacket = new SPacketLevelTerminalUpdate(); + isPacketDirty = false; } else if (++ticks % 20 == 0) { ticks = 0; - SPacketLevelTerminalUpdate update = this.updateList(); - if (update != null) { - FluidCraft.proxy.netHandler.sendTo(update, (EntityPlayerMP) this.getPlayerInv().player); + SPacketLevelTerminalUpdate updateNew = this.updateList(); + if (updateNew != null) { + FluidCraft.proxy.netHandler.sendTo(updateNew, (EntityPlayerMP) this.getPlayerInv().player); } } } - /** - * Merge from slot -> player inv. Returns the items not added. - */ - private ItemStack mergeToPlayerInventory(InventoryAdaptor playerInv, ItemStack stack) { - if (stack == null) return null; - for (ItemSlot slot : playerInv) { - if (Platform.isSameItemPrecise(slot.getItemStack(), stack)) { - if (slot.getItemStack().stackSize < slot.getItemStack().getMaxStackSize()) { - ++slot.getItemStack().stackSize; - return null; - } - } - } - return playerInv.addItems(stack); - } - - @Override - public void doAction(final EntityPlayerMP player, final InventoryAction action, final int slotIdx, final long id) { - final ContainerLevelTerminal.InvTracker invTracker = this.trackedById.get(id); - if (invTracker != null) { - final ItemStack handStack = player.inventory.getItemStack(); - - if (handStack != null && !(handStack.getItem() instanceof ItemEncodedPattern)) { - // Why even bother if we're not dealing with an encoded pattern in hand - return; - } - - final ItemStack slotStack = invTracker.requests.getStackInSlot(slotIdx); - final InventoryAdaptor playerHand = new AdaptorPlayerHand(player); - - switch (action) { - /* Set down/pickup. This is the same as SPLIT_OR_PLACE_SINGLE as our max stack sizes are 1 in slots. */ - case PICKUP_OR_SET_DOWN -> { - if (handStack != null) { - for (int s = 0; s < invTracker.requests.getSizeInventory(); s++) { - /* Is there a duplicate pattern here? */ - if (Platform.isSameItemPrecise(invTracker.requests.getStackInSlot(s), handStack)) { - /* We're done here - dupe found. */ - return; - } - } - } - - if (slotStack == null) { - /* Insert to container, if valid */ - if (handStack == null) { - /* Nothing happens */ - return; - } - invTracker.requests.setInventorySlotContents(slotIdx, playerHand.removeItems(1, null, null)); - } else { - /* Exchange? */ - if (handStack != null && handStack.stackSize > 1) { - /* Exchange is impossible, abort */ - return; - } - invTracker.requests.setInventorySlotContents(slotIdx, playerHand.removeItems(1, null, null)); - playerHand.addItems(slotStack.copy()); - } - syncLevelTerminalSlot(invTracker, id, slotIdx, invTracker.requests.getStackInSlot(slotIdx)); - } - /* Shift click from slotIdx -> player. Player -> slotIdx is not supported. */ - case SHIFT_CLICK -> { - InventoryAdaptor playerInv = InventoryAdaptor.getAdaptor(player.inventory, ForgeDirection.UNKNOWN); - ItemStack leftOver = mergeToPlayerInventory(playerInv, slotStack); - - if (leftOver == null) { - invTracker.requests.setInventorySlotContents(slotIdx, null); - syncLevelTerminalSlot(invTracker, id, slotIdx, null); - } - } - /* Move all blank patterns -> player */ - case MOVE_REGION -> { - final InventoryAdaptor playerInv = InventoryAdaptor.getAdaptor(player, ForgeDirection.UNKNOWN); - List valid = new ArrayList<>(); - - for (int i = 0; i < invTracker.requests.getSizeInventory(); i++) { - ItemStack toExtract = invTracker.requests.getStackInSlot(i); - - if (toExtract == null) { - continue; - } - - ItemStack leftOver = mergeToPlayerInventory(playerInv, toExtract); - - if (leftOver != null) { - break; - } else { - invTracker.requests.setInventorySlotContents(i, null); - } - valid.add(i); - } - if (!valid.isEmpty()) { - int[] validIndices = Ints.toArray(valid); - NBTTagList tag = new NBTTagList(); - for (int i = 0; i < valid.size(); ++i) { - tag.appendTag(new NBTTagCompound()); - } - dirty.addOverwriteEntry(id).setItems(validIndices, tag); - isDirty = true; - } - } - case CREATIVE_DUPLICATE -> { - if (player.capabilities.isCreativeMode) { - playerHand.addItems(handStack); - } - } - default -> { - return; - } - } - - this.updateHeld(player); - } - } - - private void syncLevelTerminalSlot(ContainerLevelTerminal.InvTracker inv, long id, int slot, ItemStack stack) { - int[] validIndices = { slot }; - NBTTagList list = new NBTTagList(); - NBTTagCompound item = new NBTTagCompound(); - - if (stack != null) { - stack.writeToNBT(item); - } - list.appendTag(item); - inv.updateNBT(); - this.dirty.addOverwriteEntry(id).setItems(validIndices, list); - this.isDirty = true; - } - + @Nullable private SPacketLevelTerminalUpdate updateList() { SPacketLevelTerminalUpdate update = null; var supported = LevelTerminalRegistry.instance().getSupportedClasses(); @@ -257,64 +122,67 @@ public class ContainerLevelTerminal extends FCBaseContainer { final ILevelViewable machine = isAdopted ? LevelTerminalRegistry.instance().getAdapter(clz).adapt(gridHost) : (ILevelViewable) gridHost; + visited.add(gridHost); /* First check if we are already tracking this node */ if (tracked.containsKey(gridHost)) { - /* Check for updates */ ContainerLevelTerminal.InvTracker knownTracker = tracked.get(gridHost); /* Name changed? */ String name = machine.getCustomName(); - if (!Objects.equals(knownTracker.name, name)) { - if (update == null) update = new SPacketLevelTerminalUpdate(); - update.addRenamedEntry(knownTracker.id, name); knownTracker.name = name; + if (update == null) update = new SPacketLevelTerminalUpdate(); + update.addRenameEntry(knownTracker.id, name); } - /* Status changed? */ - boolean isActive = gridNode.isActive() || machine.shouldDisplay(); + LevelItemInfo[] prev = knownTracker.infoList; + LevelItemInfo[] curr = machine.getLevelItemInfoList(); + if (prev.length == curr.length) { + for (int i = 0; i < prev.length; i++) { + if (prev[i] == null && curr[i] == null) continue; - if (!knownTracker.online && isActive) { - /* Node offline -> online */ - knownTracker.online = true; - if (update == null) update = new SPacketLevelTerminalUpdate(); - knownTracker.updateNBT(); - update.addOverwriteEntry(knownTracker.id).setOnline(true) - .setItems(knownTracker.requests.getSizeInventory(), knownTracker.inventoryNbt); - } else if (knownTracker.online && !isActive) { - /* Node online -> offline */ - knownTracker.online = false; - if (update == null) update = new SPacketLevelTerminalUpdate(); - update.addOverwriteEntry(knownTracker.id).setOnline(false); - } - - for (int i = 0; i < knownTracker.requests.getSizeInventory(); i++) { - ItemStack knowmItemStack = ItemStack - .loadItemStackFromNBT(knownTracker.inventoryNbt.getCompoundTagAt(i)); - ItemStack machineItemStack = machine.getInventoryByName("config").getStackInSlot(i); - if (isDifferent(knowmItemStack, machineItemStack)) { - if (update == null) update = new SPacketLevelTerminalUpdate(); - knownTracker.updateNBT(); - update.addOverwriteEntry(knownTracker.id) - .setItems(knownTracker.requests.getSizeInventory(), knownTracker.inventoryNbt); + if (prev[i] == null) { + knownTracker.infoList[i] = curr[i]; + if (update == null) update = new SPacketLevelTerminalUpdate(); + update.addOverwriteSlotEntry(knownTracker.id, i, curr[i]); + } else if (curr[i] == null) { + knownTracker.infoList[i] = null; + if (update == null) update = new SPacketLevelTerminalUpdate(); + update.addOverwriteSlotEntry(knownTracker.id, i, null); + } else if (!ItemStack.areItemStacksEqual(prev[i].stack, curr[i].stack) + || prev[i].quantity == curr[i].quantity + || prev[i].batchSize == curr[i].batchSize + || prev[i].state == curr[i].state) { + knownTracker.infoList[i] = curr[i]; + if (update == null) update = new SPacketLevelTerminalUpdate(); + update.addOverwriteSlotEntry(knownTracker.id, i, curr[i]); + } } + } else { + knownTracker.infoList = curr; + if (update == null) update = new SPacketLevelTerminalUpdate(); + update.addOverwriteAllSlotEntry(knownTracker.id, curr); } } else { /* Add a new entry */ if (update == null) update = new SPacketLevelTerminalUpdate(); - ContainerLevelTerminal.InvTracker entry = new ContainerLevelTerminal.InvTracker( - nextId++, - machine, - gridNode.isActive()); - update.addNewEntry(entry.id, entry.name, entry.online) - .setLocation(entry.x, entry.y, entry.z, entry.dim, entry.side.ordinal()) - .setItems(entry.rows, entry.rowSize, entry.inventoryNbt) - .setViewItemStack(machine.getSelfItemStack(), machine.getDisplayItemStack()); + ContainerLevelTerminal.InvTracker entry = new ContainerLevelTerminal.InvTracker(nextId++, machine); + + update.addNewEntry( + entry.id, + entry.x, + entry.y, + entry.z, + entry.dim, + entry.side.ordinal(), + entry.rows, + entry.rowSize, + entry.name, + entry.infoList); tracked.put(gridHost, entry); trackedById.put(entry.id, entry); } - visited.add(gridHost); } } @@ -327,10 +195,9 @@ public class ContainerLevelTerminal extends FCBaseContainer { } if (update == null) update = new SPacketLevelTerminalUpdate(); - + update.addRemoveEntry(entry.getValue().id); trackedById.remove(entry.getValue().id); it.remove(); - update.addRemovalEntry(entry.getValue().id); } return update; } @@ -340,23 +207,10 @@ public class ContainerLevelTerminal extends FCBaseContainer { return false; } - private boolean isDifferent(final ItemStack a, final ItemStack b) { - if (a == null && b == null) { - return false; - } - - if (a == null || b == null) { - return true; - } - - return !ItemStack.areItemStacksEqual(a, b); - } - private static class InvTracker { private final long id; private String name; - private final IInventory requests; private final int rowSize; private final int rows; private final int x; @@ -364,16 +218,15 @@ public class ContainerLevelTerminal extends FCBaseContainer { private final int z; private final int dim; private final ForgeDirection side; - private boolean online; - private NBTTagList inventoryNbt; - public InvTracker(long id, ILevelViewable machine, boolean online) { + private LevelItemInfo[] infoList; + + public InvTracker(long id, ILevelViewable machine) { DimensionalCoord location = machine.getLocation(); this.id = id; this.name = machine.getCustomName(); - this.requests = machine.getInventoryByName("config"); this.rowSize = machine.rowSize(); this.rows = machine.rows(); this.x = location.x; @@ -381,26 +234,8 @@ public class ContainerLevelTerminal extends FCBaseContainer { this.z = location.z; this.dim = location.getDimension(); this.side = machine.getSide(); - this.online = online; - this.inventoryNbt = new NBTTagList(); - updateNBT(); + + this.infoList = machine.getLevelItemInfoList(); } - - private void updateNBT() { - this.inventoryNbt = new NBTTagList(); - for (int i = 0; i < this.rows; ++i) { - for (int j = 0; j < this.rowSize; ++j) { - final int offset = this.rowSize * i; - ItemStack stack = this.requests.getStackInSlot(offset + j); - - if (stack != null) { - this.inventoryNbt.appendTag(stack.writeToNBT(new NBTTagCompound())); - } else { - this.inventoryNbt.appendTag(new NBTTagCompound()); - } - } - } - } - } } diff --git a/src/main/java/com/glodblock/github/common/parts/PartFluidLevelEmitter.java b/src/main/java/com/glodblock/github/common/parts/PartFluidLevelEmitter.java index 76dea8ed..b45ca3a6 100644 --- a/src/main/java/com/glodblock/github/common/parts/PartFluidLevelEmitter.java +++ b/src/main/java/com/glodblock/github/common/parts/PartFluidLevelEmitter.java @@ -18,6 +18,8 @@ import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidStack; import com.glodblock.github.api.registries.ILevelViewable; +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.common.item.ItemFluidPacket; import com.glodblock.github.inventory.InventoryHandler; import com.glodblock.github.inventory.gui.GuiType; @@ -586,4 +588,15 @@ public class PartFluidLevelEmitter extends PartUpgradeable implements IStackWatc return super.getInventoryByName(name); } + + @Override + public LevelItemInfo[] getLevelItemInfoList() { + ItemStack stack = this.config.getStackInSlot(0); + if (stack == null) return new LevelItemInfo[] { null }; + return new LevelItemInfo[] { new LevelItemInfo( + stack, + this.getReportingValue(), + -1, + this.isProvidingStrongPower() > 0 ? LevelState.Craft : LevelState.Idle) }; + } } diff --git a/src/main/java/com/glodblock/github/common/tile/TileLevelMaintainer.java b/src/main/java/com/glodblock/github/common/tile/TileLevelMaintainer.java index 081b1a94..d1d3183b 100644 --- a/src/main/java/com/glodblock/github/common/tile/TileLevelMaintainer.java +++ b/src/main/java/com/glodblock/github/common/tile/TileLevelMaintainer.java @@ -1,23 +1,30 @@ package com.glodblock.github.common.tile; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Objects; import java.util.concurrent.Future; -import java.util.function.UnaryOperator; +import java.util.stream.Stream; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.glodblock.github.api.registries.ILevelViewable; +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.common.Config; import com.glodblock.github.common.item.ItemFluidDrop; import com.glodblock.github.crossmod.thaumcraft.ThaumicEnergisticsCrafting; import com.glodblock.github.inventory.AeItemStackHandler; import com.glodblock.github.inventory.AeStackInventory; -import com.glodblock.github.inventory.AeStackInventoryImpl; import com.glodblock.github.util.ModAndClassUtil; import com.google.common.collect.ImmutableSet; @@ -42,19 +49,16 @@ import appeng.api.networking.security.MachineSource; import appeng.api.networking.ticking.IGridTickable; import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickingRequest; -import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; import appeng.core.AELog; -import appeng.helpers.NonNullArrayIterator; import appeng.me.GridAccessException; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; import appeng.tile.grid.AENetworkTile; import appeng.tile.inventory.IAEAppEngInventory; import appeng.tile.inventory.InvOperation; -import appeng.util.Platform; import appeng.util.item.AEItemStack; import io.netty.buffer.ByteBuf; @@ -62,10 +66,19 @@ public class TileLevelMaintainer extends AENetworkTile implements IAEAppEngInventory, IGridTickable, ICraftingRequester, IPowerChannelState, ILevelViewable { public static final int REQ_COUNT = 5; - public final InventoryRequest requests = new InventoryRequest(this); + public static final String NBT_REQUESTS = "Requests"; + public static final String NBT_STACK = "stack"; + public static final String NBT_QUANTITY = "quantity"; + public static final String NBT_BATCH = "batch"; + public static final String NBT_ENABLE = "enable"; + public static final String NBT_STATE = "state"; + public static final String NBT_LINK = "link"; + + public final RequestInfo[] requests = new RequestInfo[REQ_COUNT]; + private final LevelMaintainerInventory inventory = new LevelMaintainerInventory(requests, this); private int firstRequest = 0; private final BaseActionSource source; - private final IInventory inv = new AeItemStackHandler(requests.requestStacks); + private final IInventory inv = new AeItemStackHandler(inventory); private boolean isPowered = false; public TileLevelMaintainer() { @@ -75,17 +88,23 @@ public class TileLevelMaintainer extends AENetworkTile } public AeStackInventory getRequestSlots() { - return requests.requestStacks; + return inventory; } @Override public ImmutableSet getRequestedJobs() { - return ImmutableSet.copyOf(new NonNullArrayIterator<>(requests.links)); + return ImmutableSet.copyOf( + Arrays.stream(this.requests).filter(Objects::nonNull).map(info -> info.link).filter(Objects::nonNull) + .iterator()); } @Override public IAEItemStack injectCraftedItems(ICraftingLink link, IAEItemStack items, Actionable mode) { - int idx = requests.getIdxByLink(link); + int idx = this.getRequestIndexByLink(link); + if (idx == -1) { + AELog.warn("Invalid crafting link: " + link); + return items; + } ; try { if (getProxy().isActive()) { final IEnergyGrid energy = getProxy().getEnergy(); @@ -97,7 +116,7 @@ public class TileLevelMaintainer extends AENetworkTile .injectItems(ItemFluidDrop.getAeFluidStack(items), mode, source); if (notInjectedItems != null) { items.setStackSize(notInjectedItems.getStackSize()); - requests.updateState(idx, State.Export); + this.updateState(idx, LevelState.Export); return items; } else { @@ -117,10 +136,9 @@ public class TileLevelMaintainer extends AENetworkTile @Override public void jobStateChange(ICraftingLink link) { - for (int x = 0; x < REQ_COUNT; x++) { - if (requests.getLink(x) == link) { - requests.updateLink(x, link); - return; + for (int i = 0; i < REQ_COUNT; i++) { + if (requests[i] != null && requests[i].link == link) { + this.updateLink(i, null); } } } @@ -164,92 +182,107 @@ public class TileLevelMaintainer extends AENetworkTile for (int j = 0; j < REQ_COUNT; ++j) { int i = (firstRequest + j) % REQ_COUNT; + if (requests[i] == null) continue; - long quantity = requests.getQuantity(i); - long batchSize = requests.getBatchSize(i); - boolean isEnable = requests.isEnable(i); - if (!isEnable || batchSize == 0) requests.updateState(i, State.None); - if (batchSize > 0) { - IAEItemStack craftItem = requests.getCraftItem(i); + final long quantity = requests[i].quantity; + final long batchSize = requests[i].batchSize; + final boolean isEnable = requests[i].enable; - if (ModAndClassUtil.ThE) { - if (craftItem != null && ThaumicEnergisticsCrafting.isAspectStack(craftItem.getItemStack())) { - craftItem = ThaumicEnergisticsCrafting.convertAspectStack(craftItem); - } - } + if (!isEnable || quantity == 0 || batchSize == 0) { + this.updateState(i, LevelState.None); + continue; + } - IAEItemStack aeItem = inv.findPrecise(craftItem); + IAEItemStack craftItem = requests[i].itemStack.copy(); + craftItem.setStackSize(batchSize); - long stackSize = aeItem == null ? 0 : aeItem.getStackSize(); - - if (ModAndClassUtil.ThE) { - if (aeItem != null && ThaumicEnergisticsCrafting.isAspectStack(aeItem.getItemStack())) { - stackSize = ThaumicEnergisticsCrafting.getEssentiaAmount(aeItem, grid); - } - } - - boolean isDone = requests.isDone(i); - boolean isCraftable = aeItem != null && aeItem.isCraftable(); - boolean shouldCraft = isCraftable && stackSize < quantity; - - if (isDone) requests.updateState(i, State.Idle); - if (!isCraftable) requests.updateState(i, State.Error); - - if (allBusy || !isDone || !shouldCraft) { - continue; - } - - if (craftingGrid.canEmitFor(craftItem)) { - continue; - } - - if (craftingGrid.isRequesting(craftItem)) { - continue; - } - - // do crafting - Future jobTask = requests.getJob(i); - - if (jobTask == null) { - if (itemToBegin == null) { - itemToBegin = craftItem; - itemToBeginIdx = i; - } - } else if (jobTask.isDone()) { - requests.updateState(i, State.Craft); - try { - ICraftingJob job = jobTask.get(); - if (job != null) { - if (jobToSubmit == null) { - jobToSubmit = job; - jobToSubmitIdx = i; - } - } else { - requests.updateState(i, State.Error); - } - } catch (Exception ignored) { - requests.updateState(i, State.Error); - } + if (ModAndClassUtil.ThE) { + if (ThaumicEnergisticsCrafting.isAspectStack(craftItem.getItemStack())) { + craftItem = ThaumicEnergisticsCrafting.convertAspectStack(craftItem); } } + + IAEItemStack aeItem = inv.findPrecise(craftItem); + + long stackSize = aeItem == null ? 0 : aeItem.getStackSize(); + + if (ModAndClassUtil.ThE) { + if (aeItem != null && ThaumicEnergisticsCrafting.isAspectStack(aeItem.getItemStack())) { + stackSize = ThaumicEnergisticsCrafting.getEssentiaAmount(aeItem, grid); + } + } + + boolean isDone = this.isDone(i); + boolean isCraftable = aeItem != null && aeItem.isCraftable(); + boolean shouldCraft = isCraftable && stackSize < quantity; + + if (isDone) { + if (this.requests[i].state != LevelState.Idle) { + this.updateState(i, LevelState.Idle); + } + if (this.requests[i].link != null) { + this.updateLink(i, null); + } + if (!isCraftable) { + updateState(i, LevelState.Error); + } + } + + if (allBusy || !isDone || !shouldCraft) { + continue; + } + + if (craftingGrid.canEmitFor(craftItem)) { + continue; + } + + if (craftingGrid.isRequesting(craftItem)) { + continue; + } + + // do crafting + Future jobTask = requests[i].job; + + if (jobTask == null) { + if (itemToBegin == null) { + itemToBegin = craftItem; + itemToBeginIdx = i; + } + } else if (jobTask.isDone()) { + this.updateState(i, LevelState.Craft); + try { + ICraftingJob job = jobTask.get(); + if (job != null) { + if (jobToSubmit == null) { + jobToSubmit = job; + jobToSubmitIdx = i; + } + } else { + this.updateState(i, LevelState.Error); + } + } catch (Exception ignored) { + this.updateState(i, LevelState.Error); + } + } + } if (jobToSubmit != null) { // Finished calculating a request, try to submit it. ICraftingLink link = craftingGrid.submitJob(jobToSubmit, this, null, false, source); - requests.updateJob(jobToSubmitIdx, null); + requests[jobToSubmitIdx].job = null; if (link != null) { - requests.updateState(jobToSubmitIdx, State.Craft); - requests.updateLink(jobToSubmitIdx, link); + this.updateState(jobToSubmitIdx, LevelState.Craft); + this.updateLink(jobToSubmitIdx, link); } else { - requests.updateState(jobToSubmitIdx, State.Error); + this.updateState(jobToSubmitIdx, LevelState.Error); } } else if (itemToBegin != null) { // No jobs to submit, start calculating some item. - requests.updateJob( - itemToBeginIdx, - craftingGrid.beginCraftingJob(getWorldObj(), grid, source, itemToBegin, null)); - requests.updateState(itemToBeginIdx, State.Craft); + + requests[itemToBeginIdx].job = craftingGrid + .beginCraftingJob(getWorldObj(), grid, source, itemToBegin, null); + this.updateState(itemToBeginIdx, LevelState.Craft); // Try the next item next time. firstRequest = (firstRequest + 1) % REQ_COUNT; @@ -284,9 +317,6 @@ public class TileLevelMaintainer extends AENetworkTile return getProxy().isActive(); } - @Override - public void gridChanged() {} - @Override public boolean isPowered() { return isPowered; @@ -297,120 +327,205 @@ public class TileLevelMaintainer extends AENetworkTile return isPowered; } - public InventoryRequest getRequestInventory() { - return requests; - } - public IInventory getInventory() { return inv; } public IInventory getInventoryByName(String name) { - if (name == "config") return new AeItemStackHandler(requests.requestStacks); + if (Objects.equals(name, "config")) return new AeItemStackHandler(this.inventory); return null; } + @Override + public LevelItemInfo[] getLevelItemInfoList() { + return Arrays.stream(this.requests).map(request -> { + if (request == null) return null; + return new LevelItemInfo( + request.itemStack.getItemStack(), + request.getQuantity(), + request.getBatchSize(), + request.getState()); + }).toArray(LevelItemInfo[]::new); + } + public void updateQuantity(int idx, long size) { - requests.updateQuantity(idx, size); + if (requests[idx] == null) return; + requests[idx].quantity = size > 0 ? size : 0; + this.checkState(idx); + this.saveChanges(); } public void updateBatchSize(int idx, long size) { - requests.updateBatchSize(idx, size); + if (requests[idx] == null) return; + requests[idx].batchSize = size > 0 ? size : 0; + this.checkState(idx); + this.saveChanges(); } public void updateStatus(int idx, boolean enable) { - requests.updateStatus(idx, enable); + if (requests[idx] == null) return; + requests[idx].enable = enable; + this.checkState(idx); + this.saveChanges(); } - /** - * @deprecated - */ - @Deprecated - private void readLinkFromNBT__old(NBTTagCompound data) { - try { - for (int i = 0; i < REQ_COUNT; i++) { - final NBTTagCompound link = data.getCompoundTag("links-" + i); - if (link != null && link.hasNoTags()) { - requests.updateLink(i, null); - } else { - requests.updateLink(i, AEApi.instance().storage().loadCraftingLink(link, this)); - if (!requests.isDone(i)) requests.updateState(i, State.Craft); - } + private void updateState(int idx, @NotNull LevelState state) { + if (requests[idx] == null) return; + requests[idx].state = state; + this.saveChanges(); + } + + public void updateStack(int idx, @Nullable ItemStack stack) { + if (stack == null) { + requests[idx] = null; + } else { + stack = this.removeRecursion(stack); + requests[idx] = new RequestInfo(stack, this); + } + this.saveChanges(); + } + + private void updateLink(int idx, @Nullable ICraftingLink link) { + if (requests[idx] == null) return; + requests[idx].link = link; + this.saveChanges(); + } + + private void checkState(int idx) { + if (!requests[idx].enable || requests[idx].quantity == 0 || requests[idx].batchSize == 0) { + this.updateState(idx, LevelState.None); + } else if (!this.isDone(idx)) { + this.updateState(idx, LevelState.Craft); + } else { + this.updateState(idx, LevelState.Idle); + } + } + + public boolean isDone(int i) { + if (requests[i] == null) { + return true; + } + ICraftingLink link = requests[i].link; + return link == null || link.isDone() || link.isCanceled(); + } + + private int getRequestIndexByLink(ICraftingLink link) { + for (int i = 0; i < REQ_COUNT; i++) { + if (requests[i] != null && requests[i].link == link) { + return i; } - } catch (Exception ignore) {} + } + return -1; } @TileEvent(TileEventType.WORLD_NBT_WRITE) public void writeToNBTEvent(NBTTagCompound data) { - requests.requestStacks.writeToNbt(data, TLMTags.RequestStacks.tagName); + NBTTagList tagList = new NBTTagList(); + for (int i = 0; i < REQ_COUNT; i++) { + if (this.requests[i] != null) { + tagList.appendTag(this.requests[i].writeToNBT()); + } else { + tagList.appendTag(new NBTTagCompound()); + } + } + data.setTag(NBT_REQUESTS, tagList); } @TileEvent(TileEventType.WORLD_NBT_READ) public void readFromNBTEvent(NBTTagCompound data) { - if (data.hasKey(TLMTags.RequestStacks.tagName)) { - requests.requestStacks.readFromNbt(data, TLMTags.RequestStacks.tagName); - if (Platform.isServer()) { - for (int i = 0; i < REQ_COUNT; i++) { - if (requests.requestStacks.getStack(i) != null) { - ItemStack storageStack = requests.requestStacks.getStack(i).getItemStack(); - ItemStack itemStack = loadItemStackFromTag(storageStack); - ItemStack craftStack = removeRecursion(storageStack); - if (!ItemStack.areItemStacksEqual(itemStack, craftStack)) { - requests.updateStack(i, craftStack); - AELog.info( - "[TileLevelMaintainer] Replace craft stack from: " + itemStack.toString() - + ":" - + (itemStack.hasTagCompound() ? itemStack.getTagCompound() : "{no tags}") - + "; with: " - + craftStack - + ":" - + (craftStack.hasTagCompound() ? craftStack.getTagCompound() - : "{no tags}")); - } + if (data.hasKey(NBT_REQUESTS)) { + NBTTagList tagList = data.getTagList(NBT_REQUESTS, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound tag = tagList.getCompoundTagAt(i); + if (tag == null || !tag.hasKey(NBT_STACK)) { + this.requests[i] = null; + } else if (this.requests[i] == null) { + try { + this.requests[i] = new RequestInfo(tag, this); + } catch (Exception ignored) { + this.requests[i] = null; } + } else { + this.requests[i].loadFromNBT(tag); + } + } + } else if (data.hasKey("RequestStacks")) { + // Migration from old NBT + NBTTagList stacksTag = data.getCompoundTag("RequestStacks") + .getTagList("Contents", Constants.NBT.TAG_COMPOUND); + IAEItemStack[] stacks = new IAEItemStack[REQ_COUNT]; + for (int i = 0; i < REQ_COUNT; i++) { + NBTTagCompound stackTag = stacksTag.getCompoundTagAt(i); + if (stackTag == null) continue; + stacks[i] = AEItemStack.loadItemStackFromNBT(stackTag); + if (stacks[i] == null) continue; + ItemStack itemstack = stacks[i].getItemStack(); + if (!itemstack.hasTagCompound()) continue; + NBTTagCompound itemTag = itemstack.getTagCompound(); + + ItemStack craftStack = ItemStack.loadItemStackFromNBT(itemTag.getCompoundTag("Stack")); + craftStack = removeRecursion(craftStack); + if (craftStack == null) continue; + requests[i] = new RequestInfo(craftStack, this); + if (itemTag.hasKey("Enable")) { + requests[i].enable = itemTag.getBoolean("Enable"); + } + if (itemTag.hasKey("Quantity")) { + requests[i].quantity = itemTag.getLong("Quantity"); + } + if (itemTag.hasKey("Batch")) { + requests[i].batchSize = itemTag.getLong("Batch"); } } } else { - // Migration from old data storage + // Migration from old old data storage + long[] batches = new long[REQ_COUNT]; long[] quantyties = new long[REQ_COUNT]; - requests.requestStacks.readFromNbt(data, "Batch"); + ItemStack[] stacks = new ItemStack[REQ_COUNT]; + + NBTTagList batchTag = data.getCompoundTag("Batch").getTagList("Contents", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < REQ_COUNT; i++) { - IAEItemStack batchStack = requests.requestStacks.getStack(i); - batches[i] = batchStack != null ? batchStack.getStackSize() : 0; + NBTTagCompound stackTag = batchTag.getCompoundTagAt(i); + IAEItemStack stack = AEItemStack.loadItemStackFromNBT(stackTag); + batches[i] = stack != null ? stack.getStackSize() : 0; } - requests.requestStacks.readFromNbt(data, "Count"); + + NBTTagList quantityTag = data.getCompoundTag("Count").getTagList("Contents", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < REQ_COUNT; i++) { - IAEItemStack quantityStack = requests.requestStacks.getStack(i); - quantyties[i] = quantityStack != null ? quantityStack.getStackSize() : 0; + NBTTagCompound stackTag = quantityTag.getCompoundTagAt(i); + IAEItemStack stack = AEItemStack.loadItemStackFromNBT(stackTag); + quantyties[i] = stack != null ? stack.getStackSize() : 0; } - requests.requestStacks.readFromNbt(data, "Inventory"); + + NBTTagList inventoryTag = data.getCompoundTag("Count").getTagList("Contents", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < REQ_COUNT; i++) { - IAEItemStack requestsStack = requests.requestStacks.getStack(i); - if (requestsStack != null) { - requests.updateStack(i, requestsStack.getItemStack()); - requests.updateBatchSize(i, batches[i]); - requests.updateQuantity(i, quantyties[i]); - } + NBTTagCompound stackTag = inventoryTag.getCompoundTagAt(i); + IAEItemStack stack = AEItemStack.loadItemStackFromNBT(stackTag); + stacks[i] = stack != null ? stack.getItemStack() : null; + } + + for (int i = 0; i < REQ_COUNT; i++) { + if (stacks[i] == null) continue; + this.requests[i] = new RequestInfo(stacks[i], this); + this.requests[i].batchSize = batches[i]; + this.requests[i].quantity = quantyties[i]; } - readLinkFromNBT__old(data); } } + // Remove old format NBT data from ItemStack private ItemStack removeRecursion(ItemStack itemStack) { - if (itemStack != null && itemStack.hasTagCompound() - && itemStack.getTagCompound().hasKey(TLMTags.Stack.tagName)) { - return removeRecursion(loadItemStackFromTag(itemStack)); + if (itemStack == null || !itemStack.hasTagCompound()) return itemStack; + + NBTTagCompound tag = itemStack.getTagCompound(); + if (tag.hasKey("Stack") && tag.hasKey("Quantity")) { + return removeRecursion(ItemStack.loadItemStackFromNBT(itemStack.getTagCompound().getCompoundTag("Stack"))); } return itemStack; } - @Nullable - private static ItemStack loadItemStackFromTag(ItemStack itemStack) { - return ItemStack.loadItemStackFromNBT(itemStack.getTagCompound().getCompoundTag(TLMTags.Stack.tagName)); - } - @TileEvent(TileEventType.NETWORK_READ) public boolean readFromStream(final ByteBuf data) { final boolean oldPower = isPowered; @@ -449,7 +564,7 @@ public class TileLevelMaintainer extends AENetworkTile } @Override - public TileEntity getTile() { + public @NotNull TileEntity getTile() { return this; } @@ -463,209 +578,140 @@ public class TileLevelMaintainer extends AENetworkTile return REQ_COUNT; } - @Override - public ItemStack getSelfItemStack() { - return getItemFromTile(this); - } + public static class RequestInfo { - public enum State { - None, - Idle, - Craft, - Export, - Error - } + private final TileLevelMaintainer tile; + private @NotNull IAEItemStack itemStack; + private long quantity; + private long batchSize; + private boolean enable; + private LevelState state; + @Nullable + private Future job; + @Nullable + private ICraftingLink link; - public enum TLMTags { - - RequestStacks("RequestStacks"), - Enable("Enable"), - Quantity("Quantity"), - Batch("Batch"), - Link("Link"), - State("State"), - Index("Index"), - Stack("Stack"); - - public final String tagName; - - TLMTags(String tagName) { - this.tagName = tagName; - } - } - - public static final class InventoryRequest { - - private final AeStackInventoryImpl requestStacks; - private final Future[] jobs; - private final ICraftingLink[] links; - private final State[] state = new State[REQ_COUNT]; - - @SuppressWarnings("unchecked") - public InventoryRequest(TileLevelMaintainer tile) { - requestStacks = new AeStackInventoryImpl<>(StorageChannel.ITEMS, REQ_COUNT, tile); - jobs = new Future[REQ_COUNT]; - links = new ICraftingLink[REQ_COUNT]; + public RequestInfo(@NotNull ItemStack stack, TileLevelMaintainer tile) { + this.tile = tile; + itemStack = AEItemStack.create(stack); + quantity = 0; + batchSize = 0; + enable = false; + state = LevelState.None; + link = null; + job = null; } - public State getState(int idx) { - IAEItemStack ias = requestStacks.getStack(idx); - if (ias == null) { - return State.None; - } else { - return state[idx] == null ? State.Idle : state[idx]; + public RequestInfo(NBTTagCompound tag, TileLevelMaintainer tile) throws IllegalArgumentException { + this.tile = tile; + itemStack = AEItemStack.loadItemStackFromNBT(tag.getCompoundTag(NBT_STACK)); + if (itemStack == null) { + throw new IllegalArgumentException("ItemStack cannot be null!"); } - } - - public int getIdxByLink(ICraftingLink link) { - for (int i = 0; i < REQ_COUNT; i++) { - if (links[i] == link) { - return i; + quantity = tag.getLong(NBT_QUANTITY); + batchSize = tag.getLong(NBT_BATCH); + enable = tag.getBoolean(NBT_ENABLE); + state = LevelState.values()[tag.getInteger(NBT_STATE)]; + if (tag.hasKey(NBT_LINK)) { + try { + this.link = AEApi.instance().storage().loadCraftingLink(tag.getCompoundTag(NBT_LINK), this.tile); + } catch (Exception ignored) { + this.link = null; } } - return 0; + job = null; } - public boolean isEnable(int idx) { - IAEItemStack ias = requestStacks.getStack(idx); - if (ias == null) { - return true; + public void loadFromNBT(NBTTagCompound tag) { + itemStack = AEItemStack.loadItemStackFromNBT(tag.getCompoundTag(NBT_STACK)); + quantity = tag.getLong(NBT_QUANTITY); + batchSize = tag.getLong(NBT_BATCH); + enable = tag.getBoolean(NBT_ENABLE); + state = LevelState.values()[tag.getInteger(NBT_STATE)]; + if (tag.hasKey(NBT_LINK)) { + try { + this.link = AEApi.instance().storage().loadCraftingLink(tag.getCompoundTag(NBT_LINK), this.tile); + } catch (Exception ignored) { + this.link = null; + } } - - ItemStack is = ias.getItemStack(); - return is.hasTagCompound() ? is.getTagCompound().getBoolean(TLMTags.Enable.tagName) : true; } - public boolean isDone(int index) { - if (links[index] == null) { - return true; + public NBTTagCompound writeToNBT() { + NBTTagCompound tag = new NBTTagCompound(); + NBTTagCompound stackTag = new NBTTagCompound(); + itemStack.writeToNBT(stackTag); + tag.setTag(NBT_STACK, stackTag); + tag.setLong(NBT_QUANTITY, quantity); + tag.setLong(NBT_BATCH, batchSize); + tag.setBoolean(NBT_ENABLE, enable); + tag.setInteger(NBT_STATE, state.ordinal()); + if (this.link != null) { + NBTTagCompound linkTag = new NBTTagCompound(); + this.link.writeToNBT(linkTag); + tag.setTag(NBT_LINK, linkTag); } - return links[index].isDone() || links[index].isCanceled(); + return tag; } - public Future getJob(int idx) { - return jobs[idx]; + public IAEItemStack getAEItemStack() { + return this.itemStack; } - public ICraftingLink getLink(int idx) { - return links[idx]; + public long getQuantity() { + return quantity; } - public void updateJob(int idx, Future job) { - jobs[idx] = job; + public long getBatchSize() { + return batchSize; } - private void updateField(int idx, UnaryOperator updater) { - IAEItemStack ias = requestStacks.getStack(idx); - if (ias == null) return; - - ItemStack itemStack = ias.getItemStack(); - NBTTagCompound data = itemStack.hasTagCompound() ? itemStack.getTagCompound() : new NBTTagCompound(); - data.setInteger(TLMTags.Index.tagName, idx); - itemStack.setTagCompound(updater.apply(data)); - IAEItemStack newRequestStack = AEItemStack.create(itemStack); - newRequestStack.setStackSize(ias.getStackSize()); - requestStacks.setStack(idx, newRequestStack); - + public boolean isEnable() { + return enable; } - public void updateLink(int idx, ICraftingLink link) { - links[idx] = link; + public LevelState getState() { + return state; + } + } - updateField(idx, data -> { - NBTTagCompound linkData = new NBTTagCompound(); - if (link != null) link.writeToNBT(linkData); - data.setTag(TLMTags.Link.tagName, linkData); + private static class LevelMaintainerInventory implements AeStackInventory { - return data; - }); + private final RequestInfo[] requests; + private final TileLevelMaintainer tile; + + private LevelMaintainerInventory(RequestInfo[] requests, TileLevelMaintainer tile) { + this.requests = requests; + this.tile = tile; } - public void updateState(int idx, State nextState) { - state[idx] = nextState; - - updateField(idx, data -> { - data.setInteger(TLMTags.State.tagName, nextState.ordinal()); - - return data; - }); + @Override + public @NotNull Iterator iterator() { + return Arrays.stream(requests).map(info -> info != null ? info.itemStack : null).iterator(); } - public void updateStatus(int idx, boolean enable) { - updateField(idx, data -> { - State nextState = enable ? State.Idle : State.None; - - data.setBoolean(TLMTags.Enable.tagName, enable); - data.setInteger(TLMTags.State.tagName, nextState.ordinal()); - return data; - }); + @Override + public int getSlotCount() { + return requests.length; } - public void updateQuantity(int idx, long quantity) { - updateField(idx, data -> { - data.setLong(TLMTags.Quantity.tagName, quantity); - - return data; - }); + @Override + public @Nullable IAEItemStack getStack(int slot) { + return requests[slot] != null ? requests[slot].itemStack : null; } - public void updateBatchSize(int idx, long batch) { - updateField(idx, data -> { - data.setLong(TLMTags.Batch.tagName, batch); - data.setBoolean(TLMTags.Enable.tagName, true); - - return data; - }); + @Override + public void setStack(int slot, @Nullable IAEItemStack stack) { + if (stack == null) { + this.tile.updateStack(slot, null); + } else { + this.tile.updateStack(slot, stack.getItemStack()); + } } - public void updateStack(int idx, ItemStack itemStack) { - updateField(idx, data -> { - NBTTagCompound stackData = new NBTTagCompound(); - if (itemStack != null) itemStack.writeToNBT(stackData); - data.setTag(TLMTags.Stack.tagName, stackData); - - return data; - }); - } - - public IAEItemStack getAEItemStack(int idx) { - return requestStacks.getStack(idx); - } - - public ItemStack getItemStack(int idx) { - return requestStacks.getStack(idx).getItemStack(); - } - - public long getQuantity(int idx) { - if (!isEnable(idx)) return 0; - IAEItemStack ias = requestStacks.getStack(idx); - if (ias == null) return 0; - ItemStack itemStack = ias.getItemStack(); - if (!itemStack.hasTagCompound()) return 0; - - return itemStack.getTagCompound().getLong(TLMTags.Quantity.tagName); - } - - public long getBatchSize(int idx) { - if (!isEnable(idx)) return 0; - IAEItemStack ias = requestStacks.getStack(idx); - if (ias == null) return 0; - ItemStack itemStack = ias.getItemStack(); - if (!itemStack.hasTagCompound()) return 0; - - return itemStack.getTagCompound().getLong(TLMTags.Batch.tagName); - } - - public IAEItemStack getCraftItem(int idx) { - IAEItemStack is = requestStacks.getStack(idx); - if (is == null) return null; - if (is.getItemStack() == null) return null; - ItemStack qis = loadItemStackFromTag(is.getItemStack()); - if (qis == null) return null; - IAEItemStack qais = AEItemStack.create(qis); - qais.setStackSize(getBatchSize(idx)); - - return qais; + @Override + public Stream stream() { + return Arrays.stream(requests).map(info -> info != null ? info.itemStack : null); } } } diff --git a/src/main/java/com/glodblock/github/coremod/registries/adapters/PartFluidLevelEmitterAdapter.java b/src/main/java/com/glodblock/github/coremod/registries/adapters/PartFluidLevelEmitterAdapter.java index b8aad794..b9109783 100644 --- a/src/main/java/com/glodblock/github/coremod/registries/adapters/PartFluidLevelEmitterAdapter.java +++ b/src/main/java/com/glodblock/github/coremod/registries/adapters/PartFluidLevelEmitterAdapter.java @@ -1,7 +1,5 @@ package com.glodblock.github.coremod.registries.adapters; -import static com.glodblock.github.coremod.registries.adapters.PartLevelEmitterAdapter.getPatchedInventory; - import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -9,8 +7,9 @@ import net.minecraftforge.common.util.ForgeDirection; import com.glodblock.github.api.registries.ILevelViewable; import com.glodblock.github.api.registries.ILevelViewableAdapter; +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.common.parts.PartFluidLevelEmitter; -import com.glodblock.github.common.tile.TileLevelMaintainer.State; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; @@ -45,10 +44,7 @@ public class PartFluidLevelEmitterAdapter implements ILevelViewable, ILevelViewa @Override public IInventory getInventoryByName(String name) { - long value = delegate.getReportingValue(); - State state = delegate.isProvidingStrongPower() > 0 ? State.Craft : State.Idle; - - return getPatchedInventory(delegate.getInventoryByName(name), value, state); + return delegate.getInventoryByName(name); } @Override @@ -82,7 +78,13 @@ public class PartFluidLevelEmitterAdapter implements ILevelViewable, ILevelViewa } @Override - public ItemStack getSelfItemStack() { - return delegate.getItemStack(); + public LevelItemInfo[] getLevelItemInfoList() { + ItemStack stack = delegate.getInventoryByName("config").getStackInSlot(0); + if (stack == null) return new LevelItemInfo[] { null }; + return new LevelItemInfo[] { new LevelItemInfo( + stack, + delegate.getReportingValue(), + -1, + delegate.isProvidingStrongPower() > 0 ? LevelState.Craft : LevelState.Idle) }; } } diff --git a/src/main/java/com/glodblock/github/coremod/registries/adapters/PartLevelEmitterAdapter.java b/src/main/java/com/glodblock/github/coremod/registries/adapters/PartLevelEmitterAdapter.java index cf4cd255..c799a452 100644 --- a/src/main/java/com/glodblock/github/coremod/registries/adapters/PartLevelEmitterAdapter.java +++ b/src/main/java/com/glodblock/github/coremod/registries/adapters/PartLevelEmitterAdapter.java @@ -2,34 +2,24 @@ package com.glodblock.github.coremod.registries.adapters; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.ForgeDirection; -import org.jetbrains.annotations.NotNull; - import com.glodblock.github.api.registries.ILevelViewable; import com.glodblock.github.api.registries.ILevelViewableAdapter; -import com.glodblock.github.common.tile.TileLevelMaintainer.State; -import com.glodblock.github.common.tile.TileLevelMaintainer.TLMTags; -import com.glodblock.github.inventory.AeItemStackHandler; -import com.glodblock.github.inventory.AeStackInventoryImpl; +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; -import appeng.api.storage.StorageChannel; -import appeng.api.storage.data.IAEItemStack; import appeng.api.util.AECableType; import appeng.api.util.DimensionalCoord; import appeng.parts.automation.PartLevelEmitter; -import appeng.util.item.AEItemStack; public class PartLevelEmitterAdapter implements ILevelViewable, ILevelViewableAdapter { private PartLevelEmitter delegate; - private static final int SLOT_IN = 0; - public PartLevelEmitterAdapter() {} public ILevelViewable adapt(IGridHost gridHost) { @@ -37,21 +27,6 @@ public class PartLevelEmitterAdapter implements ILevelViewable, ILevelViewableAd return this; } - @NotNull - static public IInventory getPatchedInventory(IInventory inventory, long quantity, State state) { - ItemStack itemStack = inventory.getStackInSlot(SLOT_IN); - if (itemStack == null) return inventory; - NBTTagCompound data = !itemStack.hasTagCompound() ? new NBTTagCompound() : itemStack.getTagCompound(); - data.setLong(TLMTags.Quantity.tagName, quantity); - data.setInteger(TLMTags.State.tagName, state.ordinal()); - itemStack.setTagCompound(data); - - AeStackInventoryImpl inv = new AeStackInventoryImpl<>(StorageChannel.ITEMS, 1); - inv.setStack(SLOT_IN, AEItemStack.create(itemStack)); - - return new AeItemStackHandler(inv); - } - @Override public DimensionalCoord getLocation() { return delegate.getLocation(); @@ -64,10 +39,7 @@ public class PartLevelEmitterAdapter implements ILevelViewable, ILevelViewableAd @Override public IInventory getInventoryByName(String name) { - long value = delegate.getReportingValue(); - State state = delegate.isProvidingStrongPower() > 0 ? State.Craft : State.Idle; - - return getPatchedInventory(delegate.getInventoryByName(name), value, state); + return delegate.getInventoryByName(name); } @Override @@ -106,12 +78,13 @@ public class PartLevelEmitterAdapter implements ILevelViewable, ILevelViewableAd } @Override - public ItemStack getSelfItemStack() { - return delegate.getItemStack(); - } - - @Override - public ItemStack getDisplayItemStack() { - return delegate.getCrafterIcon(); + public LevelItemInfo[] getLevelItemInfoList() { + ItemStack stack = delegate.getInventoryByName("config").getStackInSlot(0); + if (stack == null) return new LevelItemInfo[] { null }; + return new LevelItemInfo[] { new LevelItemInfo( + stack, + delegate.getReportingValue(), + -1, + delegate.isProvidingStrongPower() > 0 ? LevelState.Craft : LevelState.Idle) }; } } diff --git a/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverLevelMaintainer.java b/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverLevelMaintainer.java index df233632..81691399 100644 --- a/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverLevelMaintainer.java +++ b/src/main/java/com/glodblock/github/crossmod/opencomputers/DriverLevelMaintainer.java @@ -61,7 +61,7 @@ public class DriverLevelMaintainer extends DriverSidedTileEntity { if (slot < 0 || slot >= TileLevelMaintainer.REQ_COUNT) { throw new IllegalArgumentException("Invalid slot"); } - return tileEntity.requests.isDone(slot); + return tileEntity.isDone(slot); } private boolean isEnable(Arguments args) { @@ -69,7 +69,7 @@ public class DriverLevelMaintainer extends DriverSidedTileEntity { if (slot < 0 || slot >= TileLevelMaintainer.REQ_COUNT) { throw new IllegalArgumentException("Invalid slot"); } - return tileEntity.requests.isEnable(slot); + return tileEntity.requests[slot].isEnable(); } private boolean setEnable(Arguments args) { @@ -81,7 +81,7 @@ public class DriverLevelMaintainer extends DriverSidedTileEntity { throw new IllegalArgumentException("Invalid slot"); } boolean enable = args.checkBoolean(1); - tileEntity.requests.updateStatus(slot, enable); + tileEntity.updateStatus(slot, enable); return true; } } @@ -103,12 +103,12 @@ public class DriverLevelMaintainer extends DriverSidedTileEntity { result.put("label", stack.getDisplayName()); result.put("maxDamage", stack.getMaxDamage()); result.put("name", GameRegistry.findUniqueIdentifierFor(stack.getItem()).toString()); - result.put("quantity", tileEntity.requests.getQuantity(slot)); - result.put("batch", tileEntity.requests.getBatchSize(slot)); + result.put("quantity", tileEntity.requests[slot].getQuantity()); + result.put("batch", tileEntity.requests[slot].getBatchSize()); result.put("isFluid", ItemFluidDrop.isFluidStack(stack)); if (ItemFluidDrop.isFluidStack(stack)) result.put("fluid", ItemFluidDrop.getFluidStack(stack)); - result.put("isEnable", tileEntity.requests.isEnable(slot)); - result.put("isDone", tileEntity.requests.isDone(slot)); + result.put("isEnable", tileEntity.requests[slot].isEnable()); + result.put("isDone", tileEntity.isDone(slot)); return new Object[] { result }; } return new Object[] { null }; @@ -122,7 +122,7 @@ public class DriverLevelMaintainer extends DriverSidedTileEntity { if (dbStack == null) { throw new IllegalArgumentException("Invalid slot"); } - tileEntity.requests.updateStack(slot, dbStack); + tileEntity.updateStack(slot, dbStack); } else { throw new IllegalArgumentException("Not a database"); } diff --git a/src/main/java/com/glodblock/github/crossmod/waila/tile/LevelMaintainerWailaDataProvider.java b/src/main/java/com/glodblock/github/crossmod/waila/tile/LevelMaintainerWailaDataProvider.java index 7cc01b0d..297c8d46 100644 --- a/src/main/java/com/glodblock/github/crossmod/waila/tile/LevelMaintainerWailaDataProvider.java +++ b/src/main/java/com/glodblock/github/crossmod/waila/tile/LevelMaintainerWailaDataProvider.java @@ -5,13 +5,14 @@ import java.util.List; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; import com.glodblock.github.common.tile.TileLevelMaintainer; import com.glodblock.github.crossmod.waila.Tooltip; -import appeng.api.storage.data.IAEItemStack; import appeng.integration.modules.waila.BaseWailaDataProvider; import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; @@ -23,16 +24,24 @@ public class LevelMaintainerWailaDataProvider extends BaseWailaDataProvider { final IWailaDataAccessor accessor, final IWailaConfigHandler config) { final TileEntity te = accessor.getTileEntity(); if (te instanceof TileLevelMaintainer tileLevelMaintainer) { - te.readFromNBT(accessor.getNBTData()); - for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) { - IAEItemStack ias = tileLevelMaintainer.requests.getAEItemStack(i); - if (ias != null) { - currentToolTip.add( - Tooltip.tileLevelMaintainerFormat( - ias.getItemStack().getDisplayName(), - tileLevelMaintainer.requests.getQuantity(i), - tileLevelMaintainer.requests.getBatchSize(i), - tileLevelMaintainer.requests.isEnable(i))); + NBTTagCompound data = accessor.getNBTData(); + if (data.hasKey(TileLevelMaintainer.NBT_REQUESTS)) { + NBTTagList tagList = data.getTagList(TileLevelMaintainer.NBT_REQUESTS, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound tag = tagList.getCompoundTagAt(i); + if (tag == null || !tag.hasKey(TileLevelMaintainer.NBT_STACK)) continue; + + try { + TileLevelMaintainer.RequestInfo request = new TileLevelMaintainer.RequestInfo( + tag, + tileLevelMaintainer); + currentToolTip.add( + Tooltip.tileLevelMaintainerFormat( + request.getAEItemStack().getItemStack().getDisplayName(), + request.getQuantity(), + request.getBatchSize(), + request.isEnable())); + } catch (Exception ignored) {} } } } diff --git a/src/main/java/com/glodblock/github/loader/ChannelLoader.java b/src/main/java/com/glodblock/github/loader/ChannelLoader.java index dc91301c..87fd2f96 100644 --- a/src/main/java/com/glodblock/github/loader/ChannelLoader.java +++ b/src/main/java/com/glodblock/github/loader/ChannelLoader.java @@ -20,6 +20,7 @@ import com.glodblock.github.network.CPacketSwitchGuis; import com.glodblock.github.network.CPacketTransferRecipe; import com.glodblock.github.network.CPacketValueConfig; import com.glodblock.github.network.SPacketFluidUpdate; +import com.glodblock.github.network.SPacketLevelMaintainerGuiUpdate; import com.glodblock.github.network.SPacketLevelTerminalUpdate; import com.glodblock.github.network.SPacketMEFluidInvUpdate; import com.glodblock.github.network.SPacketMEItemInvUpdate; @@ -87,6 +88,11 @@ public class ChannelLoader implements Runnable { SPacketPatternItemRenamer.class, id++, Side.SERVER); + netHandler.registerMessage( + new SPacketLevelMaintainerGuiUpdate.Handler(), + SPacketLevelMaintainerGuiUpdate.class, + id++, + Side.CLIENT); } public static void sendPacketToAllPlayers(Packet packet, World world) { diff --git a/src/main/java/com/glodblock/github/network/CPacketLevelMaintainer.java b/src/main/java/com/glodblock/github/network/CPacketLevelMaintainer.java index 65c3f7bb..7c5732c5 100644 --- a/src/main/java/com/glodblock/github/network/CPacketLevelMaintainer.java +++ b/src/main/java/com/glodblock/github/network/CPacketLevelMaintainer.java @@ -1,16 +1,9 @@ package com.glodblock.github.network; -import java.util.ArrayList; -import java.util.List; - import javax.annotation.Nullable; -import net.minecraft.entity.player.EntityPlayerMP; - import com.glodblock.github.client.gui.container.ContainerLevelMaintainer; -import com.glodblock.github.common.tile.TileLevelMaintainer; -import appeng.api.storage.data.IAEItemStack; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; @@ -19,28 +12,18 @@ import io.netty.buffer.ByteBuf; public class CPacketLevelMaintainer implements IMessage { public enum Action { - Refresh, Quantity, Batch, Enable, - Disable + Disable, } private Action action; private long size; private int slotIndex; - public CPacketLevelMaintainer() { - this.action = Action.Refresh; - this.slotIndex = 0; - this.size = 0; - } - - public CPacketLevelMaintainer(Action action) { - this.action = action; - this.slotIndex = 0; - this.size = 0; - } + @SuppressWarnings("unused") + public CPacketLevelMaintainer() {} public CPacketLevelMaintainer(Action action, int slotIndex) { this.action = action; @@ -70,43 +53,17 @@ public class CPacketLevelMaintainer implements IMessage { public static class Handler implements IMessageHandler { - private List refresh(ContainerLevelMaintainer cca) { - List toSend = new ArrayList<>(TileLevelMaintainer.REQ_COUNT); - for (int i = 0; i < TileLevelMaintainer.REQ_COUNT; i++) { - IAEItemStack ias = cca.getTile().requests.getAEItemStack(i); - if (ias != null) { - toSend.add(ias); - } - } - return toSend; - } - @Nullable @Override public IMessage onMessage(CPacketLevelMaintainer message, MessageContext ctx) { if (ctx.getServerHandler().playerEntity.openContainer instanceof final ContainerLevelMaintainer clm) { - EntityPlayerMP player = ctx.getServerHandler().playerEntity; - List toSend = switch (message.action) { - case Quantity -> { - clm.getTile().updateQuantity(message.slotIndex, message.size); - yield this.refresh(clm); - } - case Batch -> { - clm.getTile().updateBatchSize(message.slotIndex, message.size); - yield this.refresh(clm); - } - case Enable -> { - clm.getTile().updateStatus(message.slotIndex, false); - yield this.refresh(clm); - } - case Disable -> { - clm.getTile().updateStatus(message.slotIndex, true); - yield this.refresh(clm); - } - case Refresh -> this.refresh(clm); - }; - - SPacketMEUpdateBuffer.scheduleItemUpdate(player, toSend); + switch (message.action) { + case Quantity -> clm.getTile().updateQuantity(message.slotIndex, message.size); + case Batch -> clm.getTile().updateBatchSize(message.slotIndex, message.size); + case Enable -> clm.getTile().updateStatus(message.slotIndex, false); + case Disable -> clm.getTile().updateStatus(message.slotIndex, true); + } + clm.updateGui(); } return null; } diff --git a/src/main/java/com/glodblock/github/network/SPacketLevelMaintainerGuiUpdate.java b/src/main/java/com/glodblock/github/network/SPacketLevelMaintainerGuiUpdate.java new file mode 100644 index 00000000..4ca244d7 --- /dev/null +++ b/src/main/java/com/glodblock/github/network/SPacketLevelMaintainerGuiUpdate.java @@ -0,0 +1,122 @@ +package com.glodblock.github.network; + +import static com.glodblock.github.common.tile.TileLevelMaintainer.REQ_COUNT; +import static com.glodblock.github.common.tile.TileLevelMaintainer.RequestInfo; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; + +import com.glodblock.github.api.registries.LevelState; +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 SPacketLevelMaintainerGuiUpdate implements IMessage { + + private Info[] infoList; + private boolean onlyState; + + @SuppressWarnings("unused") + public SPacketLevelMaintainerGuiUpdate() {} + + public SPacketLevelMaintainerGuiUpdate(RequestInfo[] requests, boolean onlyState) { + this.infoList = new Info[REQ_COUNT]; + this.onlyState = onlyState; + + for (int i = 0; i < REQ_COUNT; i++) { + if (requests[i] == null) { + this.infoList[i] = null; + } else { + this.infoList[i] = new Info( + requests[i].getQuantity(), + requests[i].getBatchSize(), + requests[i].isEnable(), + requests[i].getState()); + } + } + } + + @Override + public void fromBytes(ByteBuf buf) { + this.infoList = new Info[REQ_COUNT]; + this.onlyState = buf.readBoolean(); + + for (int i = 0; i < REQ_COUNT; i++) { + if (buf.readBoolean()) { + if (this.onlyState) { + this.infoList[i] = new Info(LevelState.values()[buf.readInt()]); + } else { + this.infoList[i] = new Info( + buf.readLong(), + buf.readLong(), + buf.readBoolean(), + LevelState.values()[buf.readInt()]); + } + } else { + this.infoList[i] = null; + } + } + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(this.onlyState); + for (Info info : this.infoList) { + buf.writeBoolean(info != null); + if (info == null) continue; + if (!this.onlyState) { + buf.writeLong(info.quantity); + buf.writeLong(info.batchSize); + buf.writeBoolean(info.enable); + } + buf.writeInt(info.state.ordinal()); + } + } + + private static class Info { + + long quantity; + long batchSize; + boolean enable; + LevelState state; + + Info(long quantity, long batchSize, boolean enable, LevelState state) { + this.quantity = quantity; + this.batchSize = batchSize; + this.enable = enable; + this.state = state; + } + + Info(LevelState state) { + this.quantity = 0; + this.batchSize = 0; + this.enable = false; + this.state = state; + } + } + + public static class Handler implements IMessageHandler { + + @Override + public IMessage onMessage(SPacketLevelMaintainerGuiUpdate message, MessageContext ctx) { + final GuiScreen gs = Minecraft.getMinecraft().currentScreen; + + if (gs instanceof GuiLevelMaintainer gui) { + for (int i = 0; i < REQ_COUNT; i++) { + Info info = message.infoList[i]; + if (info == null) continue; + if (message.onlyState) { + gui.updateComponent(i, info.state); + } else { + gui.updateComponent(i, info.quantity, info.batchSize, info.enable, info.state); + } + } + } + + return null; + } + } +} diff --git a/src/main/java/com/glodblock/github/network/SPacketLevelTerminalUpdate.java b/src/main/java/com/glodblock/github/network/SPacketLevelTerminalUpdate.java index 515278f3..951715c5 100644 --- a/src/main/java/com/glodblock/github/network/SPacketLevelTerminalUpdate.java +++ b/src/main/java/com/glodblock/github/network/SPacketLevelTerminalUpdate.java @@ -1,22 +1,17 @@ package com.glodblock.github.network; -import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import javax.annotation.Nullable; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompressedStreamTools; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.util.Constants.NBT; -import net.minecraftforge.common.util.ForgeDirection; +import org.jetbrains.annotations.Nullable; + +import com.glodblock.github.api.registries.LevelItemInfo; +import com.glodblock.github.api.registries.LevelState; import com.glodblock.github.client.gui.GuiLevelTerminal; import appeng.core.AEConfig; @@ -27,58 +22,28 @@ 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; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.ByteBufOutputStream; -import io.netty.buffer.Unpooled; -/** - * Packet used for level terminal updates. Packet allows the server to send an array of command packets, which are then - * processed in order. This allows for chaining commands to produce the desired update. - */ public class SPacketLevelTerminalUpdate implements IMessage { - public static final int CLEAR_ALL_BIT = 1; - public static final int DISCONNECT_BIT = 2; - private final List commands = new ArrayList<>(); - private int statusFlags; - - public SPacketLevelTerminalUpdate() {} + @Override public void fromBytes(ByteBuf buf) { - this.statusFlags = buf.readByte(); - int numEntries = buf.readInt(); + int entryNum = buf.readInt(); - for (int i = 0; i < numEntries; ++i) { - try { - PacketType type = PacketType.values()[buf.readByte()]; + for (int i = 0; i < entryNum; i++) { + PacketType type = PacketType.values()[buf.readByte()]; - switch (type) { - case ADD -> this.commands.add(new PacketAdd(buf)); - case REMOVE -> this.commands.add(new PacketRemove(buf)); - case OVERWRITE -> this.commands.add(new PacketOverwrite(buf)); - case RENAME -> this.commands.add(new PacketRename(buf)); - default -> throw new IOException("Unknown packet type received of index " + type); - } - } catch (Exception e) { - if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { - AELog.info( - "Corrupted packet commands: (" + i - + ") of (" - + numEntries - + ") -> " - + this.commands.size() - + " : " - + this.commands.stream().map(packetEntry -> packetEntry.getClass().getSimpleName()) - .collect(Collectors.groupingBy(String::new, Collectors.counting()))); - if (AEConfig.instance.isFeatureEnabled(AEFeature.DebugLogging)) { - AELog.info(" <- Parsed content: " + this.commands); - } - } - AELog.debug(e); - return; + switch (type) { + case ADD -> this.commands.add(new PacketAdd(buf)); + case REMOVE -> this.commands.add(new PacketRemove(buf)); + case RENAME -> this.commands.add(new PacketRename(buf)); + case DISCONNECT -> this.commands.add(new PacketDisconnect(buf)); + case OVERWRITE_SLOT -> this.commands.add(new PacketOverwriteSlot(buf)); + case OVERWITE_ALL_SLOT -> this.commands.add(new PacketOverwirteAllSlot(buf)); } } + if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { AELog.info( " <- Received commands " + this.commands.size() @@ -88,80 +53,49 @@ public class SPacketLevelTerminalUpdate implements IMessage { } } + @Override public void toBytes(ByteBuf buf) { - try { - if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { - AELog.info( - " <- Sent commands " + this.commands.size() - + " : " - + this.commands.stream().map(packetEntry -> packetEntry.getClass().getSimpleName()) - .collect(Collectors.groupingBy(String::new, Collectors.counting()))); - if (AEConfig.instance.isFeatureEnabled(AEFeature.DebugLogging)) { - AELog.info(" -> Sent commands: " + this.commands); - } - } + buf.writeInt(commands.size()); + for (PacketEntry entry : this.commands) { + buf.writeByte(entry.getType().ordinal()); + entry.write(buf); + } - buf.writeByte(statusFlags); - buf.writeInt(commands.size()); - for (PacketEntry entry : commands) { - entry.write(buf); + if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { + AELog.info( + " <- Sent commands " + this.commands.size() + + " : " + + this.commands.stream().map(packetEntry -> packetEntry.getClass().getSimpleName()) + .collect(Collectors.groupingBy(String::new, Collectors.counting()))); + if (AEConfig.instance.isFeatureEnabled(AEFeature.DebugLogging)) { + AELog.info(" -> Sent commands: " + this.commands); } - } catch (IOException e) { - throw new IllegalStateException(e); } } - /** - * Remove all entries on the terminal. This is done BEFORE any entries are processed, so you can set this to clear - * old entries, and add new ones after in one packet. - */ - public void setClear() { - statusFlags |= CLEAR_ALL_BIT; + public void addNewEntry(long id, int x, int y, int z, int dim, int side, int rows, int rowSize, String name, + LevelItemInfo[] infolist) { + this.commands.add(new PacketAdd(id, x, y, z, dim, side, rows, rowSize, name, infolist)); } - /** - * The terminal disconnected. Entries are still processed, but indicates for the GUI to darken/turn off the - * terminal. No further updates will arrive until the terminal reconnects. - */ - public void setDisconnect() { - this.statusFlags |= DISCONNECT_BIT; + public void addRemoveEntry(long id) { + this.commands.add(new PacketRemove(id)); } - /** - * Adds a new entry. Fill out the rest of the command using the {@link PacketAdd#setItems(int, int, NBTTagList)} and - * {@link PacketAdd#setLocation(int, int, int, int, int)}. - * - * @return the packet, which needs to have information filled out. - */ - public PacketAdd addNewEntry(long id, String name, boolean online) { - PacketAdd packet = new PacketAdd(id, name, online); - - commands.add(packet); - return packet; + public void addRenameEntry(long id, String newName) { + this.commands.add(new PacketRename(id, newName)); } - /** - * Remove the entry with the id from the terminal. - */ - public void addRemovalEntry(long id) { - commands.add(new PacketRemove(id)); + public void addDisconnectEntry() { + this.commands.add(new PacketDisconnect()); } - /** - * Rename the entry - */ - public void addRenamedEntry(long id, String newName) { - commands.add(new PacketRename(id, newName)); + public void addOverwriteSlotEntry(long id, int index, LevelItemInfo info) { + this.commands.add(new PacketOverwriteSlot(id, index, info)); } - /** - * Overwrite the entry with new items or new status - */ - public PacketOverwrite addOverwriteEntry(long id) { - PacketOverwrite packet = new PacketOverwrite(id); - - commands.add(packet); - return packet; + public void addOverwriteAllSlotEntry(long id, LevelItemInfo[] info) { + this.commands.add(new PacketOverwirteAllSlot(id, info)); } public static class Handler implements IMessageHandler { @@ -172,23 +106,22 @@ public class SPacketLevelTerminalUpdate implements IMessage { final GuiScreen gs = Minecraft.getMinecraft().currentScreen; if (gs instanceof GuiLevelTerminal levelTerminal) { - levelTerminal.postUpdate(message.commands, message.statusFlags); + levelTerminal.receivePackets(message.commands); } return null; } } - enum PacketType { + protected enum PacketType { ADD, REMOVE, - OVERWRITE, RENAME, + DISCONNECT, + OVERWRITE_SLOT, + OVERWITE_ALL_SLOT, } - /** - * A packet for updating an entry. - */ public abstract static class PacketEntry { public final long entryId; @@ -197,181 +130,87 @@ public class SPacketLevelTerminalUpdate implements IMessage { this.entryId = entryId; } - protected PacketEntry(ByteBuf buf) throws IOException { + public PacketEntry(ByteBuf buf) { this.entryId = buf.readLong(); - read(buf); } - /** - * Needs to write the packet id. - */ - protected abstract void write(ByteBuf buf) throws IOException; + protected abstract PacketType getType(); - /** - * Reading the entry id is not needed. - */ - protected abstract void read(ByteBuf buf) throws IOException; + protected void write(ByteBuf buf) { + buf.writeLong(this.entryId); + } } - /** - * A command for sending a new entry. - */ public static class PacketAdd extends PacketEntry { - public String name; public int x, y, z, dim, side; public int rows, rowSize; - public boolean online; - public ItemStack selfItemStack; - public ItemStack displayItemStack; - public NBTTagList items; + public String name; + public LevelItemInfo[] infolist; - PacketAdd(long id, String name, boolean online) { + PacketAdd(long id, int x, int y, int z, int dim, int side, int rows, int rowSize, String name, + LevelItemInfo[] infolist) { super(id); - this.name = name; - this.online = online; - } - - PacketAdd(ByteBuf buf) throws IOException { - super(buf); - } - - public PacketAdd setLocation(int x, int y, int z, int dim, int side) { this.x = x; this.y = y; this.z = z; this.dim = dim; this.side = side; - return this; - } - - public PacketAdd setItems(int rows, int rowSize, NBTTagList items) { this.rows = rows; this.rowSize = rowSize; - this.items = items; - - return this; + this.name = name; + this.infolist = infolist; } - public PacketAdd setViewItemStack(ItemStack selfItemStack, ItemStack displayItemStack) { - this.selfItemStack = selfItemStack; - this.displayItemStack = displayItemStack; - - return this; - } - - @Override - protected void write(ByteBuf buf) throws IOException { - buf.writeByte(PacketType.ADD.ordinal()); - buf.writeLong(entryId); - ByteBufUtils.writeUTF8String(buf, this.name); - buf.writeInt(x); - buf.writeInt(y); - buf.writeInt(z); - buf.writeInt(dim); - buf.writeByte(side); - buf.writeInt(rows); - buf.writeInt(rowSize); - - ByteBuf tempBuf = Unpooled.directBuffer(256); - try { - try (ByteBufOutputStream stream = new ByteBufOutputStream(tempBuf)) { - - NBTTagCompound wrapper = new NBTTagCompound(); - - if (selfItemStack != null) { - wrapper.setTag("self", selfItemStack.writeToNBT(new NBTTagCompound())); - } - if (displayItemStack != null) { - wrapper.setTag("display", displayItemStack.writeToNBT(new NBTTagCompound())); - } - wrapper.setTag("data", items); - CompressedStreamTools.writeCompressed(wrapper, stream); - } - buf.writeInt(tempBuf.readableBytes()); - buf.writeBytes(tempBuf); - } finally { - tempBuf.release(); - } - } - - @Override - protected void read(ByteBuf buf) throws IOException { - this.name = ByteBufUtils.readUTF8String(buf); + public PacketAdd(ByteBuf buf) { + super(buf); this.x = buf.readInt(); this.y = buf.readInt(); this.z = buf.readInt(); this.dim = buf.readInt(); - this.side = buf.readByte(); + this.side = buf.readInt(); this.rows = buf.readInt(); this.rowSize = buf.readInt(); - int payloadSize = buf.readInt(); - try (ByteBufInputStream stream = new ByteBufInputStream(buf, payloadSize)) { - NBTTagCompound payload = CompressedStreamTools.readCompressed(stream); - int available = stream.available(); - if (available > 0) { - byte[] left = new byte[available]; - int read = stream.read(left); - if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { - AELog.info( - "Unread bytes detected (" + read - + "): " - + Arrays.toString(left) - + " at " - + dim - + "#(" - + x - + ":" - + y - + ":" - + z - + ")@" - + ForgeDirection.getOrientation(side)); - } - } - - if (payload.hasKey("self", NBT.TAG_COMPOUND)) { - this.selfItemStack = ItemStack.loadItemStackFromNBT(payload.getCompoundTag("self")); - } - - if (payload.hasKey("display", NBT.TAG_COMPOUND)) { - this.displayItemStack = ItemStack.loadItemStackFromNBT(payload.getCompoundTag("display")); - } - - this.items = payload.getTagList("data", NBT.TAG_COMPOUND); + this.name = ByteBufUtils.readUTF8String(buf); + int infoSize = buf.readInt(); + infolist = new LevelItemInfo[infoSize]; + for (int i = 0; i < infoSize; i++) { + if (!buf.readBoolean()) continue; + ItemStack stack = ByteBufUtils.readItemStack(buf); + long quantity = buf.readLong(); + long batchSize = buf.readLong(); + LevelState state = LevelState.values()[buf.readInt()]; + infolist[i] = new LevelItemInfo(stack, quantity, batchSize, state); } } @Override - public String toString() { - return "PacketAdd{" + "name='" - + name - + '\'' - + ", x=" - + x - + ", y=" - + y - + ", z=" - + z - + ", dim=" - + dim - + ", side=" - + side - + ", rows=" - + rows - + ", rowSize=" - + rowSize - + ", online=" - + online - + ", selfItemStack=" - + selfItemStack - + ", displayItemStack=" - + displayItemStack - + ", items=" - + items - + ", entryId=" - + entryId - + '}'; + protected PacketType getType() { + return PacketType.ADD; + } + + @Override + protected void write(ByteBuf buf) { + super.write(buf); + buf.writeInt(this.x); + buf.writeInt(this.y); + buf.writeInt(this.z); + buf.writeInt(this.dim); + buf.writeInt(this.side); + buf.writeInt(this.rows); + buf.writeInt(this.rowSize); + ByteBufUtils.writeUTF8String(buf, this.name); + buf.writeInt(this.infolist.length); + for (int i = 0; i < this.infolist.length; i++) { + LevelItemInfo info = this.infolist[i]; + buf.writeBoolean(info != null); + if (info == null) continue; + // System.out.println("Writing info: " + info.stack != null); + ByteBufUtils.writeItemStack(buf, info.stack); + buf.writeLong(info.quantity); + buf.writeLong(info.batchSize); + buf.writeInt(info.state.ordinal()); + } } } @@ -381,205 +220,147 @@ public class SPacketLevelTerminalUpdate implements IMessage { super(id); } - PacketRemove(ByteBuf buf) throws IOException { + PacketRemove(ByteBuf buf) { super(buf); } + @Override + protected PacketType getType() { + return PacketType.REMOVE; + } + @Override protected void write(ByteBuf buf) { - buf.writeByte(PacketType.REMOVE.ordinal()); - buf.writeLong(entryId); - } - - @Override - protected void read(ByteBuf buf) {} - - @Override - public String toString() { - return "PacketRemove{" + "entryId=" + entryId + '}'; + super.write(buf); } } - /** - * Overwrite online status or inventory of the entry. - */ - public static class PacketOverwrite extends PacketEntry { - - public static final int ONLINE_BIT = 1; - public static final int ONLINE_VALID = 1 << 1; - public static final int ITEMS_VALID = 1 << 2; - public static final int ALL_ITEM_UPDATE_BIT = 1 << 3; - public boolean onlineValid; - public boolean online; - public boolean itemsValid; - public boolean allItemUpdate; - public int[] validIndices; - public NBTTagList items; - - protected PacketOverwrite(long id) { - super(id); - } - - protected PacketOverwrite(ByteBuf buf) throws IOException { - super(buf); - } - - public PacketOverwrite setOnline(boolean online) { - this.onlineValid = true; - this.online = online; - return this; - } - - public PacketOverwrite setItems(int[] validIndices, NBTTagList items) { - this.itemsValid = true; - this.allItemUpdate = validIndices == null || validIndices.length == 0; - this.validIndices = validIndices; - this.items = items; - - return this; - } - - public PacketOverwrite setItems(int newSize, NBTTagList items) { - this.itemsValid = true; - this.allItemUpdate = true; - this.validIndices = new int[newSize]; - this.items = items; - - return this; - } - - @Override - protected void write(ByteBuf buf) throws IOException { - buf.writeByte(PacketType.OVERWRITE.ordinal()); - buf.writeLong(entryId); - - int flags = 0; - - if (onlineValid) { - flags |= ONLINE_VALID; - flags |= online ? ONLINE_BIT : 0; - } - if (itemsValid) { - flags |= ITEMS_VALID; - if (allItemUpdate) { - flags |= ALL_ITEM_UPDATE_BIT; - buf.writeByte(flags); - buf.writeInt(validIndices.length); - } else { - buf.writeByte(flags); - buf.writeInt(validIndices.length); - for (int validIndex : validIndices) { - buf.writeInt(validIndex); - } - } - ByteBuf tempBuf = Unpooled.directBuffer(256); - try { - try (ByteBufOutputStream stream = new ByteBufOutputStream(tempBuf)) { - - NBTTagCompound wrapper = new NBTTagCompound(); - - wrapper.setTag("data", items); - CompressedStreamTools.writeCompressed(wrapper, stream); - } - buf.writeInt(tempBuf.readableBytes()); - buf.writeBytes(tempBuf); - } finally { - tempBuf.release(); - } - } else { - buf.writeByte(flags); - } - } - - @Override - protected void read(ByteBuf buf) throws IOException { - int flags = buf.readByte(); - - /* Decide whether to use online flag or not */ - if ((flags & ONLINE_VALID) == ONLINE_VALID) { - this.onlineValid = true; - this.online = (flags & ONLINE_BIT) == ONLINE_BIT; - } - /* Decide whether to read item list or not */ - if ((flags & ITEMS_VALID) == ITEMS_VALID) { - this.itemsValid = true; - if ((flags & ALL_ITEM_UPDATE_BIT) == ALL_ITEM_UPDATE_BIT) { - this.allItemUpdate = true; - int numItems = buf.readInt(); - this.validIndices = new int[numItems]; - } else { - int numItems = buf.readInt(); - this.validIndices = new int[numItems]; - for (int i = 0; i < numItems; ++i) { - this.validIndices[i] = buf.readInt(); - } - } - int payloadSize = buf.readInt(); - try (ByteBufInputStream stream = new ByteBufInputStream(buf, payloadSize)) { - this.items = CompressedStreamTools.readCompressed(stream).getTagList("data", NBT.TAG_COMPOUND); - int available = stream.available(); - if (available > 0) { - byte[] left = new byte[available]; - int read = stream.read(left); - if (AEConfig.instance.isFeatureEnabled(AEFeature.PacketLogging)) { - AELog.info("Unread bytes detected (" + read + "): " + Arrays.toString(left)); - } - } - } - } - } - - @Override - public String toString() { - return "PacketOverwrite{" + "onlineValid=" - + onlineValid - + ", online=" - + online - + ", itemsValid=" - + itemsValid - + ", allItemUpdate=" - + allItemUpdate - + ", validIndices=" - + Arrays.toString(validIndices) - + ", items=" - + items - + ", entryId=" - + entryId - + '}'; - } - } - - /** - * Rename the entry. - */ public static class PacketRename extends PacketEntry { public String newName; - protected PacketRename(long id, String newName) { + PacketRename(long id, String newName) { super(id); this.newName = newName; } - protected PacketRename(ByteBuf buf) throws IOException { + PacketRename(ByteBuf buf) { super(buf); + this.newName = ByteBufUtils.readUTF8String(buf); + } + + @Override + protected PacketType getType() { + return PacketType.RENAME; } @Override protected void write(ByteBuf buf) { - buf.writeByte(PacketType.RENAME.ordinal()); - buf.writeLong(entryId); - ByteBufUtils.writeUTF8String(buf, newName); + super.write(buf); + ByteBufUtils.writeUTF8String(buf, this.newName); + } + } + + public static class PacketDisconnect extends PacketEntry { + + PacketDisconnect() { + super(0); // Ignored id + } + + PacketDisconnect(ByteBuf buf) { + super(buf); } @Override - protected void read(ByteBuf buf) { - newName = ByteBufUtils.readUTF8String(buf); + protected PacketType getType() { + return PacketType.DISCONNECT; + } + } + + public static class PacketOverwriteSlot extends PacketEntry { + + public int index; + public LevelItemInfo info; + + PacketOverwriteSlot(long id, int index, LevelItemInfo info) { + super(id); + this.index = index; + this.info = info; + } + + PacketOverwriteSlot(ByteBuf buf) { + super(buf); + this.index = buf.readInt(); + if (buf.readBoolean()) { + this.info = new LevelItemInfo( + ByteBufUtils.readItemStack(buf), + buf.readLong(), + buf.readLong(), + LevelState.values()[buf.readInt()]); + } else { + this.info = null; + } } @Override - public String toString() { - return "PacketRename{" + "newName='" + newName + '\'' + ", entryId=" + entryId + '}'; + protected PacketType getType() { + return PacketType.OVERWRITE_SLOT; + } + + @Override + protected void write(ByteBuf buf) { + super.write(buf); + buf.writeInt(index); + buf.writeBoolean(info != null); + ByteBufUtils.writeItemStack(buf, info.stack); + buf.writeLong(info.quantity); + buf.writeLong(info.batchSize); + buf.writeInt(info.state.ordinal()); + } + } + + public static class PacketOverwirteAllSlot extends PacketEntry { + + public LevelItemInfo[] infoList; + + PacketOverwirteAllSlot(long id, LevelItemInfo[] info) { + super(id); + this.infoList = info; + } + + PacketOverwirteAllSlot(ByteBuf buf) { + super(buf); + int infoSize = buf.readInt(); + this.infoList = new LevelItemInfo[infoSize]; + for (int i = 0; i < infoSize; i++) { + if (!buf.readBoolean()) continue; + ItemStack stack = ByteBufUtils.readItemStack(buf); + long quantity = buf.readLong(); + long batchSize = buf.readLong(); + LevelState state = LevelState.values()[buf.readInt()]; + this.infoList[i] = new LevelItemInfo(stack, quantity, batchSize, state); + } + } + + @Override + protected PacketType getType() { + return PacketType.OVERWITE_ALL_SLOT; + } + + @Override + protected void write(ByteBuf buf) { + super.write(buf); + buf.writeInt(this.infoList.length); + for (int i = 0; i < this.infoList.length; i++) { + LevelItemInfo info = this.infoList[i]; + buf.writeBoolean(info != null); + if (info == null) continue; + buf.writeInt(i); + ByteBufUtils.writeItemStack(buf, info.stack); + buf.writeLong(info.quantity); + buf.writeLong(info.batchSize); + buf.writeInt(info.state.ordinal()); + } } } } diff --git a/src/main/java/com/glodblock/github/network/SPacketMEItemInvUpdate.java b/src/main/java/com/glodblock/github/network/SPacketMEItemInvUpdate.java index 4c871580..0ebb1aa0 100644 --- a/src/main/java/com/glodblock/github/network/SPacketMEItemInvUpdate.java +++ b/src/main/java/com/glodblock/github/network/SPacketMEItemInvUpdate.java @@ -9,7 +9,6 @@ import net.minecraft.client.gui.GuiScreen; import com.glodblock.github.client.gui.GuiFluidCraftConfirm; import com.glodblock.github.client.gui.GuiItemMonitor; -import com.glodblock.github.client.gui.GuiLevelMaintainer; import appeng.api.storage.data.IAEItemStack; import appeng.util.item.AEItemStack; @@ -97,8 +96,6 @@ public class SPacketMEItemInvUpdate implements IMessage { ((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; }