diff --git a/dependencies.gradle b/dependencies.gradle index b324775b..c4b4098a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,11 +34,11 @@ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { - api('com.github.GTNewHorizons:NotEnoughItems:2.7.31-GTNH:dev') - api('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-554-GTNH:dev') + api('com.github.GTNewHorizons:NotEnoughItems:2.7.34-GTNH:dev') + api('com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-580-GTNH:dev') api('curse.maven:cofh-core-69162:2388751') api('com.github.GTNewHorizons:waila:1.8.4:dev') - api("com.github.GTNewHorizons:GTNHLib:0.6.16:dev") + api("com.github.GTNewHorizons:GTNHLib:0.6.18:dev") implementation("com.github.GTNewHorizons:WirelessCraftingTerminal:1.12.0:dev") { exclude group: 'com.github.GTNewHorizons', module: 'Applied-Energistics-2-Unofficial' @@ -47,15 +47,15 @@ dependencies { compileOnly('com.github.GTNewHorizons:Baubles-Expanded:2.1.6-GTNH:dev') compileOnly('com.github.GTNewHorizons:ExtraCells2:2.5.35:dev') { transitive = false } compileOnly('com.github.GTNewHorizons:ForestryMC:4.10.5:dev') - compileOnly('com.github.GTNewHorizons:EnderIO:2.9.5:dev') - compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.189:dev') { + compileOnly('com.github.GTNewHorizons:EnderIO:2.9.7:dev') + compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.227:dev') { exclude group: 'com.github.GTNewHorizons', module: 'AE2FluidCraft-Rework' exclude group: 'com.github.GTNewHorizons', module: 'Applied-Energistics-2-Unofficial' } compileOnly('thaumcraft:Thaumcraft:1.7.10-4.2.3.5:dev') compileOnly('com.gregoriust.gregtech:gregtech_1.7.10:6.14.23:dev') { transitive = false } - compileOnly('com.github.GTNewHorizons:OpenComputers:1.11.12-GTNH:dev') { transitive = false } + compileOnly('com.github.GTNewHorizons:OpenComputers:1.11.13-GTNH:dev') { transitive = false } compileOnly('com.github.GTNewHorizons:ThaumicEnergistics:1.7.6-GTNH:dev') { transitive = false } compileOnly("com.github.GTNewHorizons:Hodgepodge:2.6.31:dev") { transitive = false } diff --git a/gradle.properties b/gradle.properties index 4f19ca8f..71e62947 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ modId = ae2fc modGroup = com.glodblock.github # Whether to use modGroup as the maven publishing group. -# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. +# When false, com.github.GTNewHorizons is used. useModGroupForPublishing = false # Updates your build.gradle and settings.gradle automatically whenever an update is available. diff --git a/settings.gradle b/settings.gradle index 40fb369e..ff436f2c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.37' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38' } diff --git a/src/main/java/com/glodblock/github/client/gui/GuiFluidLevelEmitter.java b/src/main/java/com/glodblock/github/client/gui/GuiFluidLevelEmitter.java index ad58d53f..848fdf46 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiFluidLevelEmitter.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiFluidLevelEmitter.java @@ -3,6 +3,9 @@ package com.glodblock.github.client.gui; import net.minecraft.client.gui.GuiButton; import net.minecraft.entity.player.InventoryPlayer; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + import com.glodblock.github.FluidCraft; import com.glodblock.github.client.gui.container.ContainerFluidLevelEmitter; import com.glodblock.github.common.parts.PartFluidLevelEmitter; @@ -14,15 +17,17 @@ import appeng.api.config.Settings; import appeng.api.storage.data.IAEFluidStack; import appeng.client.gui.implementations.GuiUpgradeable; import appeng.client.gui.widgets.GuiImgButton; -import appeng.client.gui.widgets.GuiNumberBox; +import appeng.client.gui.widgets.MEGuiTextField; import appeng.core.AEConfig; -import appeng.core.AELog; import appeng.core.localization.GuiColors; import appeng.core.localization.GuiText; +import appeng.util.calculators.ArithHelper; +import appeng.util.calculators.Calculator; public class GuiFluidLevelEmitter extends GuiUpgradeable { - private GuiNumberBox level; + private MEGuiTextField amountTextField; + private GuiButton plus1; private GuiButton plus10; private GuiButton plus100; @@ -31,6 +36,9 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { private GuiButton minus10; private GuiButton minus100; private GuiButton minus1000; + + private GuiButton setButton; + private boolean isMul = false; public GuiFluidLevelEmitter(final InventoryPlayer inventoryPlayer, final PartFluidLevelEmitter te) { @@ -41,13 +49,12 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { public void initGui() { super.initGui(); - this.level = new GuiNumberBox(this.fontRendererObj, 24, 43, 79, this.fontRendererObj.FONT_HEIGHT, Long.class); - this.level.setEnableBackgroundDrawing(false); - this.level.setMaxStringLength(16); - this.level.setTextColor(GuiColors.LevelEmitterValue.getColor()); - this.level.setVisible(true); - this.level.setFocused(true); - ((ContainerFluidLevelEmitter) this.inventorySlots).setTextField(this.level); + this.amountTextField = new MEGuiTextField(90, 12); + this.amountTextField.x = this.guiLeft + 39; + this.amountTextField.y = this.guiTop + 44; + this.amountTextField.setFocused(true); + ((ContainerFluidLevelEmitter) this.inventorySlots).setTextField(this.amountTextField); + this.validateText(); } @Override @@ -68,10 +75,19 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { this.buttonList.add(this.plus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 17, 32, 20, "+" + c)); this.buttonList.add(this.plus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 17, 38, 20, "+" + d)); - this.buttonList.add(this.minus1 = new GuiButton(0, this.guiLeft + 20, this.guiTop + 59, 22, 20, "-" + a)); - this.buttonList.add(this.minus10 = new GuiButton(0, this.guiLeft + 48, this.guiTop + 59, 28, 20, "-" + b)); - this.buttonList.add(this.minus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 59, 32, 20, "-" + c)); - this.buttonList.add(this.minus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 59, 38, 20, "-" + d)); + this.buttonList.add(this.minus1 = new GuiButton(0, this.guiLeft + 20, this.guiTop + 63, 22, 20, "-" + a)); + this.buttonList.add(this.minus10 = new GuiButton(0, this.guiLeft + 48, this.guiTop + 63, 28, 20, "-" + b)); + this.buttonList.add(this.minus100 = new GuiButton(0, this.guiLeft + 82, this.guiTop + 63, 32, 20, "-" + c)); + this.buttonList.add(this.minus1000 = new GuiButton(0, this.guiLeft + 120, this.guiTop + 63, 38, 20, "-" + d)); + + this.buttonList.add( + this.setButton = new GuiButton( + 0, + this.guiLeft + 134, + this.guiTop + 40, + 28, + 20, + GuiText.Set.getLocal())); this.buttonList.add(this.redstoneMode); } @@ -89,19 +105,18 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { this.ySize - 96 + 3, GuiColors.UpgradableInventory.getColor()); this.redstoneMode.set(this.cvb.getRedStoneMode()); - this.level.drawTextBox(); + if (isShiftKeyDown() && !isMul) { - for (Object btn : this.buttonList) { + for (GuiButton btn : this.buttonList) { if (btn instanceof GuiButton) { - ((GuiButton) btn).displayString += "000"; + btn.displayString += "000"; } } isMul = true; } else if (!isShiftKeyDown() && isMul) { - for (Object btn : this.buttonList) { + for (GuiButton btn : this.buttonList) { if (btn instanceof GuiButton) { - ((GuiButton) btn).displayString = ((GuiButton) btn).displayString - .substring(0, ((GuiButton) btn).displayString.lastIndexOf("000")); + btn.displayString = btn.displayString.substring(0, btn.displayString.lastIndexOf("000")); } } isMul = false; @@ -111,6 +126,11 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { @Override public void drawBG(final int offsetX, final int offsetY, final int mouseX, final int mouseY) { super.drawBG(offsetX, offsetY, mouseX, mouseY); + this.amountTextField.drawTextBox(); + + // Without these two lines, the liquid slot will not draw properly. + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + this.bindTexture(this.getBackground()); } @Override @@ -124,75 +144,76 @@ public class GuiFluidLevelEmitter extends GuiUpgradeable { @Override protected void actionPerformed(final GuiButton btn) { super.actionPerformed(btn); - final boolean isPlus = btn == this.plus1 || btn == this.plus10 || btn == this.plus100 || btn == this.plus1000; - final boolean isMinus = btn == this.minus1 || btn == this.minus10 - || btn == this.minus100 - || btn == this.minus1000; - if (isPlus || isMinus) { - this.addQty(this.getQty(btn)); + if (btn == this.setButton && this.setButton.enabled) { + final long amount = this.getAmountLong(); + this.amountTextField.setText(Long.toString(amount)); + + FluidCraft.proxy.netHandler.sendToServer(new CPacketValueConfig(amount, 0)); + } else { + final boolean isPlus = btn == this.plus1 || btn == this.plus10 + || btn == this.plus100 + || btn == this.plus1000; + final boolean isMinus = btn == this.minus1 || btn == this.minus10 + || btn == this.minus100 + || btn == this.minus1000; + + if (isPlus || isMinus) { + long result = addOrderAmount(this.getQty(btn)); + this.amountTextField.setText(Long.toString(result)); + } } } - private void addQty(final long i) { - try { - String Out = this.level.getText(); + private long addOrderAmount(final int i) { + long resultL = getAmountLong(); - boolean Fixed = false; - while (Out.startsWith("0") && Out.length() > 1) { - Out = Out.substring(1); - Fixed = true; - } - - if (Fixed) { - this.level.setText(Out); - } - - if (Out.isEmpty()) { - Out = "0"; - } - - long result = Long.parseLong(Out); - result += i; - if (result < 0) { - result = 0; - } - - this.level.setText(Out = Long.toString(result)); - - FluidCraft.proxy.netHandler.sendToServer(new CPacketValueConfig(result, 0)); - } catch (final NumberFormatException e) { - this.level.setText("0"); + if (resultL == 1 && i > 1) { + resultL = 0; } + + resultL += i; + if (resultL < 1) { + resultL = 1; + } + return resultL; + } + + private long getAmountLong() { + String out = this.amountTextField.getText(); + double resultD = Calculator.conversion(out); + + if (resultD <= 0 || Double.isNaN(resultD)) { + return 0; + } else { + return (long) ArithHelper.round(resultD, 0); + } + } + + private void validateText() { + String text = this.amountTextField.getText(); + double resultD = Calculator.conversion(text); + this.setButton.enabled = !Double.isNaN(resultD); + } + + @Override + protected void mouseClicked(int xCoord, int yCoord, int btn) { + this.amountTextField.mouseClicked(xCoord, yCoord, btn); + super.mouseClicked(xCoord, yCoord, btn); } @Override protected void keyTyped(final char character, final int key) { if (!this.checkHotbarKeys(key)) { - if ((key == 211 || key == 205 || key == 203 || key == 14 || Character.isDigit(character)) - && this.level.textboxKeyTyped(character, key)) { - try { - String Out = this.level.getText(); - - boolean Fixed = false; - while (Out.startsWith("0") && Out.length() > 1) { - Out = Out.substring(1); - Fixed = true; - } - - if (Fixed) { - this.level.setText(Out); - } - - if (Out.isEmpty()) { - Out = "0"; - } - FluidCraft.proxy.netHandler.sendToServer(new CPacketValueConfig(Long.parseLong(Out), 0)); - } catch (final NumberFormatException e) { - AELog.debug(e); - } + if (key == Keyboard.KEY_RETURN || key == Keyboard.KEY_NUMPADENTER) { + this.actionPerformed(this.setButton); } else { - super.keyTyped(character, key); + boolean typedTextbox = this.amountTextField.textboxKeyTyped(character, key); + if (typedTextbox) { + this.validateText(); + } else { + super.keyTyped(character, key); + } } } } diff --git a/src/main/java/com/glodblock/github/client/gui/GuiPatternMulti.java b/src/main/java/com/glodblock/github/client/gui/GuiPatternMulti.java index 30299e6d..cab3ec3b 100644 --- a/src/main/java/com/glodblock/github/client/gui/GuiPatternMulti.java +++ b/src/main/java/com/glodblock/github/client/gui/GuiPatternMulti.java @@ -50,8 +50,10 @@ public class GuiPatternMulti extends GuiAmount { Settings.ACTIONS, ActionItems.MULTIPLY)); - this.amountTextField.xPosition = this.guiLeft + 50; + this.amountTextField.x = this.guiLeft + 48; + this.amountTextField.w = 73; this.amountTextField.setText(String.valueOf(DEFAULT_VALUE)); + this.amountTextField.setCursorPositionEnd(); this.amountTextField.setSelectionPos(0); } diff --git a/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidLevelEmitter.java b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidLevelEmitter.java index f80fbc67..4de7b37a 100644 --- a/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidLevelEmitter.java +++ b/src/main/java/com/glodblock/github/client/gui/container/ContainerFluidLevelEmitter.java @@ -1,6 +1,5 @@ package com.glodblock.github.client.gui.container; -import net.minecraft.client.gui.GuiTextField; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; @@ -14,6 +13,7 @@ import appeng.api.config.RedstoneMode; import appeng.api.config.SecurityPermissions; import appeng.api.config.Settings; import appeng.api.implementations.IUpgradeableHost; +import appeng.client.gui.widgets.MEGuiTextField; import appeng.container.guisync.GuiSync; import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.util.Platform; @@ -25,7 +25,7 @@ public class ContainerFluidLevelEmitter extends FCContainerFluidConfigurable { private final PartFluidLevelEmitter lvlEmitter; @SideOnly(Side.CLIENT) - private GuiTextField textField; + private MEGuiTextField textField; @GuiSync(2) public long EmitterValue = -1; @@ -50,15 +50,12 @@ public class ContainerFluidLevelEmitter extends FCContainerFluidConfigurable { @Override protected void setupConfig() { final IInventory inv = this.getUpgradeable().getInventoryByName("config"); - final int y = 40; - final int x = 80 + 44; - this.addSlotToContainer(new OptionalFluidSlotFakeTypeOnly(inv, null, this, 0, x, y, 0, 0, 0)); + this.addSlotToContainer(new OptionalFluidSlotFakeTypeOnly(inv, null, this, 0, 17, 42, 0, 0, 0)); } @SideOnly(Side.CLIENT) - public void setTextField(final GuiTextField level) { + public void setTextField(final MEGuiTextField level) { this.textField = level; - this.textField.setText(String.valueOf(this.EmitterValue)); } public void setLevel(final long l, final EntityPlayer player) { @@ -99,6 +96,10 @@ public class ContainerFluidLevelEmitter extends FCContainerFluidConfigurable { if (field.equals("EmitterValue")) { if (this.textField != null) { this.textField.setText(String.valueOf(this.EmitterValue)); + + if (String.valueOf(oldValue).equals("-1")) { + this.textField.setCursorPositionEnd(); + } } } } diff --git a/src/main/java/com/glodblock/github/common/item/ItemBaseWirelessTerminal.java b/src/main/java/com/glodblock/github/common/item/ItemBaseWirelessTerminal.java index f061877e..32c18dc0 100644 --- a/src/main/java/com/glodblock/github/common/item/ItemBaseWirelessTerminal.java +++ b/src/main/java/com/glodblock/github/common/item/ItemBaseWirelessTerminal.java @@ -119,6 +119,9 @@ public class ItemBaseWirelessTerminal extends ToolWirelessTerminal implements II @Override public boolean canHandle(final ItemStack is) { + if (is == null) { + return false; + } return is.getItem() instanceof ItemBaseWirelessTerminal; } diff --git a/src/main/java/com/glodblock/github/common/storage/CreativeFluidCellInventory.java b/src/main/java/com/glodblock/github/common/storage/CreativeFluidCellInventory.java index f01c1446..d9987ef5 100644 --- a/src/main/java/com/glodblock/github/common/storage/CreativeFluidCellInventory.java +++ b/src/main/java/com/glodblock/github/common/storage/CreativeFluidCellInventory.java @@ -60,7 +60,7 @@ public class CreativeFluidCellInventory extends FluidCellInventory { if (fs == null) continue; IAEFluidStack iaeFluidStack = Util.FluidUtil.createAEFluidStack(fs); if (this.cellFluids.findPrecise(iaeFluidStack) == null) { - iaeFluidStack.setStackSize(Integer.MAX_VALUE * 1_000_000L); + iaeFluidStack.setStackSize((long) (Math.pow(2, 52) - 1)); this.cellFluids.add(iaeFluidStack); } } diff --git a/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java b/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java index c907d67b..a5725207 100644 --- a/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java +++ b/src/main/java/com/glodblock/github/common/storage/FluidCellInventoryHandler.java @@ -39,7 +39,9 @@ public class FluidCellInventoryHandler extends MEInventoryHandler final ItemStack is = config.getStackInSlot(x); final FluidStack fluid = Util.getFluidFromItem(is); if (fluid != null) { - priorityList.add(AEFluidStack.create(fluid)); + AEFluidStack stack = AEFluidStack.create(fluid); + stack.setStackSize(1); + priorityList.add(stack); } } if (!priorityList.isEmpty()) { diff --git a/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java b/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java index fc3818cf..baff13b0 100644 --- a/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java +++ b/src/main/java/com/glodblock/github/inventory/FluidConvertingInventoryAdaptor.java @@ -374,7 +374,7 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor { } private boolean isItemConduit(TileEntity te) { - if (ModAndClassUtil.EIO && conduitClazz.isInstance(te)) { + if (isConduit(te)) { try { return eioTypeCheck.invoke(te, IItemConduit.class) != null; } catch (InvocationTargetException | IllegalAccessException e) { @@ -385,7 +385,7 @@ public class FluidConvertingInventoryAdaptor extends InventoryAdaptor { } private boolean isConduit(TileEntity te) { - return ModAndClassUtil.EIO && te instanceof IItemDuct; + return ModAndClassUtil.EIO && conduitClazz.isInstance(te); } private ItemStack fillEIOConduit(ItemStack item, TileEntity te, ForgeDirection direction) { diff --git a/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java b/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java index 54a8305f..e77e099b 100644 --- a/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java +++ b/src/main/java/com/glodblock/github/inventory/MEMonitorIFluidHandler.java @@ -1,14 +1,18 @@ package com.glodblock.github.inventory; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import javax.annotation.Nonnull; +import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; @@ -25,10 +29,13 @@ import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.StorageChannel; import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IItemList; +import appeng.core.AELog; import appeng.util.item.AEFluidStack; public class MEMonitorIFluidHandler implements IMEMonitor { + private static boolean WrongFluidRemovedWarnIssued = false; + private final IFluidHandler handler; private final ForgeDirection side; private IItemList cache = AEApi.instance().storage().createFluidList(); @@ -57,6 +64,10 @@ public class MEMonitorIFluidHandler implements IMEMonitor { } public IAEFluidStack injectItems(IAEFluidStack input, Actionable type, BaseActionSource src) { + if (!this.handler.canFill(this.side, input.getFluid())) { + return input; + } + int filled = this.handler.fill(this.side, input.getFluidStack(), type == Actionable.MODULATE); if (type == Actionable.MODULATE) { @@ -73,8 +84,41 @@ public class MEMonitorIFluidHandler implements IMEMonitor { } public IAEFluidStack extractItems(IAEFluidStack request, Actionable type, BaseActionSource src) { + if (!this.handler.canDrain(this.side, request.getFluid())) { + return null; + } FluidStack removed = this.handler.drain(this.side, request.getFluidStack(), type == Actionable.MODULATE); if (removed != null && removed.amount != 0) { + // perform a one time log if the removed fluid isn't what's reported since this will create a dupe exploit + if (!WrongFluidRemovedWarnIssued && !removed.isFluidEqual(request.getFluidStack())) { + WrongFluidRemovedWarnIssued = true; + String issuesUrl = "https://github.com/GTNewHorizons/GT-New-Horizons-Modpack/issues/new"; + String msg = String.format( + "[AE2FC] MEMonitorIFluidHandler.extractItems got the wrong fluids while extracting from %s. expected %s got %s. Please report this message if seen: ", + this.handler.getClass().getSimpleName(), + request.getFluidStack().getUnlocalizedName(), + removed.getUnlocalizedName()); + // elevate log to error if chat msg is removed to make it easier to find. + AELog.warn(msg + issuesUrl); + + ChatComponentText chatTxt = new ChatComponentText(msg); + chatTxt.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.RED).setBold(true)); + + ChatComponentText chatUrl = new ChatComponentText(issuesUrl); + chatUrl.setChatStyle( + new ChatStyle().setUnderlined(true) + .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, issuesUrl)) + .setChatHoverEvent( + new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new ChatComponentText("Click to open link")))); + + ChatComponentText chat = new ChatComponentText(""); + chat.appendSibling(chatTxt); + chat.appendSibling(chatUrl); + + MinecraftServer.getServer().getConfigurationManager().sendChatMsg(chat); + } IAEFluidStack o = request.copy(); o.setStackSize(removed.amount); if (type == Actionable.MODULATE) { @@ -98,8 +142,6 @@ public class MEMonitorIFluidHandler implements IMEMonitor { // *Decompiled Stuff*// public TickRateModulation onTick() { - boolean changed = false; - List changes = new ArrayList<>(); FluidTankInfo[] tankProperties = this.handler.getTankInfo(this.side); IItemList currentlyOnStorage = AEApi.instance().storage().createFluidList(); @@ -111,37 +153,32 @@ public class MEMonitorIFluidHandler implements IMEMonitor { } } - Iterator var9 = this.cache.iterator(); - - IAEFluidStack is; - while (var9.hasNext()) { - is = (IAEFluidStack) var9.next(); - is.setStackSize(-is.getStackSize()); + // make diff between cache and new contents + IItemList changes = AEApi.instance().storage().createFluidList(); + // using non-enhanced for to prevent concurrency errors + for (Iterator iter = this.cache.iterator(); iter.hasNext();) { + IAEFluidStack copy = iter.next().copy(); + copy.setStackSize(-copy.getStackSize()); + changes.add(copy); } - - var9 = currentlyOnStorage.iterator(); - - while (var9.hasNext()) { - is = (IAEFluidStack) var9.next(); - this.cache.add(is); + for (IAEFluidStack is : currentlyOnStorage) { + changes.add(is); } - - var9 = this.cache.iterator(); - - while (var9.hasNext()) { - is = (IAEFluidStack) var9.next(); - if (is.getStackSize() != 0L) { - changes.add(is); + // update cache as soon as possible + this.cache = currentlyOnStorage; + // remove unchanged values + for (Iterator iter = changes.iterator(); iter.hasNext();) { + if (iter.next().getStackSize() == 0L) { + iter.remove(); } } - this.cache = currentlyOnStorage; if (!changes.isEmpty()) { this.postDifference(changes); - changed = true; + return TickRateModulation.URGENT; } - return changed ? TickRateModulation.URGENT : TickRateModulation.SLOWER; + return TickRateModulation.SLOWER; } private void postDifference(Iterable a) { diff --git a/src/main/java/com/glodblock/github/nei/NEICellViewHandler.java b/src/main/java/com/glodblock/github/nei/NEICellViewHandler.java new file mode 100644 index 00000000..6f8b0d77 --- /dev/null +++ b/src/main/java/com/glodblock/github/nei/NEICellViewHandler.java @@ -0,0 +1,278 @@ +package com.glodblock.github.nei; + +import static net.minecraft.util.EnumChatFormatting.GRAY; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidStack; + +import org.lwjgl.opengl.GL11; + +import com.glodblock.github.common.item.ItemFluidDrop; +import com.glodblock.github.common.storage.FluidCellInventoryHandler; +import com.glodblock.github.util.ModAndClassUtil; +import com.mitchej123.hodgepodge.textures.IPatchedTextureAtlasSprite; + +import appeng.api.AEApi; +import appeng.api.config.TerminalFontSize; +import appeng.api.storage.StorageChannel; +import appeng.api.storage.data.IAEFluidStack; +import appeng.api.storage.data.IAEStack; +import appeng.client.render.StackSizeRenderer; +import appeng.core.localization.GuiText; +import appeng.util.Platform; +import appeng.util.item.FluidList; +import codechicken.nei.PositionedStack; +import codechicken.nei.api.IOverlayHandler; +import codechicken.nei.api.IRecipeOverlayRenderer; +import codechicken.nei.recipe.GuiRecipe; +import codechicken.nei.recipe.IUsageHandler; + +public class NEICellViewHandler implements IUsageHandler { + + private static class ViewItemStack { + + public PositionedStack stack; + public long amount; + public IIcon icon; + public int color; + + public ViewItemStack(PositionedStack stack, long amount, IIcon icon, int color) { + this.stack = stack; + this.amount = amount; + this.icon = icon; + this.color = color; + } + } + + private static final ResourceLocation SLOT_TEXTURE_LOCATION = new ResourceLocation("nei", "textures/slot.png"); + private static final int OFFSET_X = 2; + private static final int INFO_OFFSET_Y = 4; + private static final int ITEMS_OFFSET_Y = INFO_OFFSET_Y + Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT * 2 + 6; + private static final int ROW_ITEM_NUM = 9; + + private final List stacks = new ArrayList<>(); + private FluidCellInventoryHandler cellHandler; + + @Override + public IUsageHandler getUsageHandler(String inputId, Object... ingredients) { + if (ingredients.length > 0 && ingredients[0] instanceof ItemStack ingredient && AEApi.instance().registries().cell() + .getCellInventory(ingredient, null, StorageChannel.FLUIDS) instanceof final FluidCellInventoryHandler handler && handler.getTotalBytes() > 0) { + this.cellHandler = handler; + + FluidList list = new FluidList(); + handler.getAvailableItems(list, appeng.util.IterationCounter.fetchNewId()); + + List sortedStacks = new ArrayList<>(); + list.iterator().forEachRemaining(sortedStacks::add); + sortedStacks.sort(Comparator.comparing(IAEStack::getStackSize, Comparator.reverseOrder())); + + + stacks.clear(); + int count = 0; + for (IAEFluidStack aeFluid : sortedStacks) { + FluidStack fluid = aeFluid.getFluidStack(); + long amount = fluid.amount; + ItemStack fluidItemStack = ItemFluidDrop.newStack(fluid); + if (fluidItemStack != null) { + fluidItemStack.stackSize = 1; + PositionedStack positionedStack = new PositionedStack( + fluidItemStack, + OFFSET_X + count % ROW_ITEM_NUM * 18 + 1, + ITEMS_OFFSET_Y + count / ROW_ITEM_NUM * 18 + 1); + stacks.add(new ViewItemStack(positionedStack, amount, fluid.getFluid().getIcon(), fluid.getFluid().getColor())); + count++; + } + } + + return this; + } + return null; + } + + @Override + public String getRecipeName() { + return GuiText.CellView.getLocal(); + } + + @Override + public int numRecipes() { + return 1; + } + + @Override + public void drawBackground(int recipe) {} + + @Override + public void drawForeground(int recipe) { + final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + final String usedBytes = Platform.formatByteDouble(cellHandler.getUsedBytes()); + final String totalBytes = Platform.formatByteDouble(cellHandler.getTotalBytes()); + fontRenderer.drawString( + usedBytes + " " + GuiText.Of.getLocal() + ' ' + totalBytes + ' ' + GuiText.BytesUsed.getLocal(), + OFFSET_X, + INFO_OFFSET_Y, + 0); + fontRenderer.drawString( + NumberFormat.getInstance().format(cellHandler.getUsedTypes()) + " " + + GuiText.Of.getLocal() + + ' ' + + NumberFormat.getInstance().format(cellHandler.getTotalTypes()) + + ' ' + + GuiText.Types.getLocal(), + OFFSET_X, + INFO_OFFSET_Y + fontRenderer.FONT_HEIGHT + 2, + 0); + + final Tessellator tessellator = Tessellator.instance; + GL11.glColor3f(1F, 1F, 1F); + + // Draw slots + Minecraft.getMinecraft().getTextureManager().bindTexture(SLOT_TEXTURE_LOCATION); + tessellator.startDrawingQuads(); + for (int i = 0; i < this.cellHandler.getTotalTypes(); i++) { + final int line = i % ROW_ITEM_NUM; + final int row = i / ROW_ITEM_NUM; + tessellator.addVertexWithUV(OFFSET_X + 18 * (line + 1), ITEMS_OFFSET_Y + 18 * row, 0, 1, 0); + tessellator.addVertexWithUV(OFFSET_X + 18 * line, ITEMS_OFFSET_Y + 18 * row, 0, 0, 0); + tessellator.addVertexWithUV(OFFSET_X + 18 * line, ITEMS_OFFSET_Y + 18 * (row + 1), 0, 0, 1); + tessellator.addVertexWithUV(OFFSET_X + 18 * (line + 1), ITEMS_OFFSET_Y + 18 * (row + 1), 0, 1, 1); + } + tessellator.draw(); + + // Draw fluids + Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + tessellator.startDrawingQuads(); + for (int i = 0; i < this.stacks.size(); i++) { + final IIcon icon = this.stacks.get(i).icon; + final int color = this.stacks.get(i).color; + final int line = i % ROW_ITEM_NUM; + final int row = i / ROW_ITEM_NUM; + + if (ModAndClassUtil.HODGEPODGE && icon instanceof IPatchedTextureAtlasSprite sprite) { + sprite.markNeedsAnimationUpdate(); + } + + tessellator.setColorRGBA(color >> 16 & 0xFF, color >> 8 & 0xFF, color & 0xFF, 0xFF); + tessellator.addVertexWithUV( + OFFSET_X + 18 * (line + 1) - 1, + ITEMS_OFFSET_Y + 18 * row + 1, + 0, + icon.getMaxU(), + icon.getMinV()); + tessellator.addVertexWithUV( + OFFSET_X + 18 * line + 1, + ITEMS_OFFSET_Y + 18 * row + 1, + 0, + icon.getMinU(), + icon.getMinV()); + tessellator.addVertexWithUV( + OFFSET_X + 18 * line + 1, + ITEMS_OFFSET_Y + 18 * (row + 1) - 1, + 0, + icon.getMinU(), + icon.getMaxV()); + tessellator.addVertexWithUV( + OFFSET_X + 18 * (line + 1) - 1, + ITEMS_OFFSET_Y + 18 * (row + 1) - 1, + 0, + icon.getMaxU(), + icon.getMaxV()); + } + tessellator.draw(); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_BLEND); + + // Draw amount + for (ViewItemStack viewStack : this.stacks) { + StackSizeRenderer.drawStackSize( + viewStack.stack.relx, + viewStack.stack.rely, + viewStack.amount, + fontRenderer, + TerminalFontSize.SMALL); + } + } + + @Override + public List getIngredientStacks(int recipe) { + return new ArrayList<>(); + } + + @Override + public List getOtherStacks(int recipe) { + return this.stacks.stream().map(stack -> stack.stack).collect(Collectors.toList()); + } + + @Override + public PositionedStack getResultStack(int recipe) { + return null; + } + + @Override + public void onUpdate() {} + + @Override + public boolean hasOverlay(GuiContainer gui, Container container, int recipe) { + return false; + } + + @Override + public IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe) { + return null; + } + + @Override + public IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe) { + return null; + } + + @Override + public int recipiesPerPage() { + return 1; + } + + @Override + public List handleTooltip(GuiRecipe gui, List currenttip, int recipe) { + return currenttip; + } + + @Override + public List handleItemTooltip(GuiRecipe gui, ItemStack stack, List currenttip, int recipe) { + if (stack == null) return currenttip; + + this.stacks.stream().filter(viewStack -> viewStack.stack.item.equals(stack)).findFirst().ifPresent( + viewItemStack -> currenttip.set( + 1, + GRAY + GuiText.Stored.getLocal() + + ": " + + NumberFormat.getNumberInstance().format(viewItemStack.amount))); + return currenttip; + } + + @Override + public boolean keyTyped(GuiRecipe gui, char keyChar, int keyCode, int recipe) { + return false; + } + + @Override + public boolean mouseClicked(GuiRecipe gui, int button, int recipe) { + return false; + } +} diff --git a/src/main/java/com/glodblock/github/nei/NEI_FC_Config.java b/src/main/java/com/glodblock/github/nei/NEI_FC_Config.java index 3f08bc67..bae93cf9 100644 --- a/src/main/java/com/glodblock/github/nei/NEI_FC_Config.java +++ b/src/main/java/com/glodblock/github/nei/NEI_FC_Config.java @@ -20,6 +20,7 @@ public class NEI_FC_Config implements IConfigureNEI { API.registerNEIGuiHandler(new AE2FC_NEIGuiHandler()); API.addSearchProvider(new NEIItemFilter()); API.registerStackStringifyHandler(new FCStackStringifyHandler()); + API.registerUsageHandler(new NEICellViewHandler()); if (ModAndClassUtil.AVARITIA) { API.registerGuiOverlay(GuiFluidPatternWireless.class, "extreme", null);