From 47422a5ae6beff21b3861986835ec84e78bca007 Mon Sep 17 00:00:00 2001 From: cubefury Date: Wed, 3 Sep 2025 01:51:20 +0800 Subject: [PATCH 01/40] GT Integration --- dependencies.gradle | 2 + .../vendingmachine/VendingMachine.java | 28 +- .../blocks/MTEVendingMachine.java | 355 ++++++++++++++++++ .../vendingmachine/items/VMItems.java | 17 + .../assets/vendingmachine/lang/en_US.lang | 2 - 5 files changed, 393 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java create mode 100644 src/main/java/com/cubefury/vendingmachine/items/VMItems.java diff --git a/dependencies.gradle b/dependencies.gradle index 1a44f0d..cc83ac8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -38,6 +38,8 @@ dependencies { implementation("com.github.GTNewHorizons:GTNHLib:0.6.39:dev") compileOnly("com.github.GTNewHorizons:BetterQuesting:3.7.11-GTNH:dev") implementation("com.github.GTNewHorizons:ModularUI2:2.2.16-1.7.10:dev") + implementation("com.github.GTNewHorizons:StructureLib:1.4.18:dev") + implementation("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.440:dev") } // deps may transitively add Baubles, so we replace it diff --git a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java index 9ee141e..2cfe80f 100644 --- a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java @@ -6,8 +6,7 @@ import org.apache.logging.log4j.Logger; import com.cubefury.vendingmachine.blocks.BlockVendingMachine; -import com.cubefury.vendingmachine.blocks.ItemBlockVendingMachine; -import com.cubefury.vendingmachine.blocks.TileVendingMachine; +import com.cubefury.vendingmachine.items.VMItems; import com.cubefury.vendingmachine.network.PacketTypeRegistry; import com.cubefury.vendingmachine.network.SerializedPacket; import com.cubefury.vendingmachine.util.ItemPlaceholder; @@ -47,6 +46,11 @@ public class VendingMachine { public static boolean isNeiLoaded = false; public static boolean isBqLoaded = false; + public static boolean isGtLoaded = false; + public static boolean isAeLoaded = false; + + public static int CONTROLLER_MTE_ID = 2741; + // public static int ME_UPLINK_MTE_ID = 2742; @SidedProxy( clientSide = "com.cubefury.vendingmachine.ClientProxy", @@ -74,21 +78,27 @@ public void preInit(FMLPreInitializationEvent event) { public void init(FMLInitializationEvent event) { proxy.init(event); - GameRegistry.registerBlock(vendingMachine, ItemBlockVendingMachine.class, "vending_machine"); - GameRegistry.registerTileEntity(TileVendingMachine.class, "vending_machine"); + isNeiLoaded = Loader.isModLoaded("NotEnoughItems"); + isBqLoaded = Loader.isModLoaded("betterquesting"); + isGtLoaded = Loader.isModLoaded("gregtech"); + isAeLoaded = Loader.isModLoaded("appliedenergistics2"); + + LOG.info("NEI Integration enabled: {}", isNeiLoaded); + LOG.info("Better Questing Integration enabled: {}", isBqLoaded); + LOG.info("Gregtech Integration enabled: {}", isGtLoaded); + LOG.info("AE2 Integration enabled {}", isAeLoaded); GameRegistry.registerItem(ItemPlaceholder.placeholder, "placeholder"); + if (isGtLoaded) { + VMItems.registerMultis(); + } + } @Mod.EventHandler // postInit "Handle interaction with other mods, complete your setup based on this." (Remove if not needed) public void postInit(FMLPostInitializationEvent event) { - isNeiLoaded = Loader.isModLoaded("NotEnoughItems"); - isBqLoaded = Loader.isModLoaded("betterquesting"); - - LOG.info("NEI Integration enabled: {}", isNeiLoaded); - LOG.info("Better Questing Integration enabled: {}", isBqLoaded); proxy.postInit(event); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java new file mode 100644 index 0000000..45281bd --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -0,0 +1,355 @@ +package com.cubefury.vendingmachine.blocks; + +import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.common.util.ForgeDirection; + +import com.gtnewhorizon.structurelib.StructureLibAPI; +import com.gtnewhorizon.structurelib.alignment.IAlignment; +import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; +import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; +import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable; +import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.Column; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.Row; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; + +import gregtech.api.GregTechAPI; +import gregtech.api.covers.CoverRegistry; +import gregtech.api.enums.Textures; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.ISecondaryDescribable; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.modularui.IAddUIWidgets; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.GTUtility; +import gregtech.api.util.MultiblockTooltipBuilder; + +public class MTEVendingMachine extends MetaTileEntity + implements ISurvivalConstructable, ISecondaryDescribable, IAlignment, IAddUIWidgets { + + public static final int INPUT_SLOTS = 7; + public static final int OUTPUT_SLOTS = 1; + + public static final int STRUCTURE_CHECK_TICKS = 20; + + private static final IStructureDefinition STRUCTURE_DEFINITION = IStructureDefinition + .builder() + .addShape("main", new String[][] { { "cc", "c~", "cc" } }) + .addElement('c', lazy(t -> ofBlock(GregTechAPI.sBlockCasings11, 0))) + .build(); + private static final ITexture[] FACING_SIDE = { + TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_ITEM_PIPE_TIN) }; + private static final ITexture[] FACING_FRONT = { + TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_INACTIVE) }; + private static final ITexture[] FACING_ACTIVE = { + TextureFactory.of(Textures.BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_ACTIVE), TextureFactory.builder() + .addIcon(Textures.BlockIcons.MACHINE_CASING_BRICKEDBLASTFURNACE_ACTIVE_GLOW) + .glow() + .build() }; + + private MultiblockTooltipBuilder tooltipBuilder; + + public int mUpdate = 0; + public boolean mMachine = false; + public ItemStack[] mInputItems = new ItemStack[INPUT_SLOTS]; + public ItemStack[] mOutputItems = new ItemStack[OUTPUT_SLOTS]; + public List outputBuffer = new ArrayList<>(); + + public MTEVendingMachine(final int aID, final String aName, final String aNameRegional) { + super(aID, aName, aNameRegional, INPUT_SLOTS + OUTPUT_SLOTS); + } + + public MTEVendingMachine(String aName) { + super(aName, INPUT_SLOTS + OUTPUT_SLOTS); + } + + @Override + public String[] getStructureDescription(ItemStack stackSize) { + return getTooltip().getStructureHint(); + } + + protected MultiblockTooltipBuilder getTooltip() { + if (tooltipBuilder == null) { + tooltipBuilder = new MultiblockTooltipBuilder(); + tooltipBuilder.addMachineType("Vending Machine") + .addInfo("Who even restocks this...") + .beginStructureBlock(2, 3, 1, false) + .addController("Middle") + .addOtherStructurePart("Tin Item Pipe Casings", "Everything except the controller") + .toolTipFinisher(); + } + return tooltipBuilder; + } + + @Override + public boolean isTeleporterCompatible() { + return false; + } + + @Override + public boolean isFacingValid(ForgeDirection facing) { + return (facing.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0; + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean active, boolean redstoneLevel) { + if (side == facing) { + return active ? FACING_ACTIVE : FACING_FRONT; + } + return FACING_SIDE; + } + + /* + * Use this to implement the items slowly dispensing? idk + * temp code copied from bricked blast furnace implementation + * Make sure to add progresstime and maxprogresstime to save/load nbt + * @Override + * public int getProgresstime() { + * return this.mProgresstime; + * } + * @Override + * public int maxProgresstime() { + * return this.mMaxProgresstime; + * } + * @Override + * public int increaseProgress(int aProgress) { + * this.mProgresstime += aProgress; + * return this.mMaxProgresstime - this.mProgresstime; + * } + */ + @Override + public String[] getDescription() { + return getCurrentDescription(); + } + + @Override + public boolean allowCoverOnSide(ForgeDirection side, ItemStack coverItem) { + return (CoverRegistry.getCoverPlacer(coverItem) + .allowOnPrimitiveBlock()) && (super.allowCoverOnSide(side, coverItem)); + } + + @Override + public String[] getPrimaryDescription() { + return getTooltip().getInformation(); + } + + @Override + public String[] getSecondaryDescription() { + return getTooltip().getStructureInformation(); + } + + @Override + public void saveNBTData(NBTTagCompound aNBT) { + if (this.mOutputItems != null) { + for (int i = 0; i < mOutputItems.length; i++) { + NBTTagCompound tNBT = new NBTTagCompound(); + if (this.mOutputItems[i] != null) { + this.mOutputItems[i].writeToNBT(tNBT); + } + aNBT.setTag("mOutputItem" + i, tNBT); + } + } + NBTTagList pendingOutputs = new NBTTagList(); + for (ItemStack itemStack : outputBuffer) { + pendingOutputs.appendTag(itemStack.writeToNBT(new NBTTagCompound())); + } + aNBT.setTag("outputBuffer", pendingOutputs); + } + + @Override + public void loadNBTData(NBTTagCompound aNBT) { + this.mOutputItems = new ItemStack[OUTPUT_SLOTS]; + for (int i = 0; i < OUTPUT_SLOTS; i++) { + this.mOutputItems[i] = GTUtility.loadItem(aNBT, "mOutputItem" + i); + } + this.outputBuffer.clear(); + NBTTagList pendingOutputs = aNBT.getTagList("outputBuffer", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < pendingOutputs.tagCount(); i++) { + outputBuffer.add(GTUtility.loadItem(pendingOutputs.getCompoundTagAt(i))); + } + } + + @Override + public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side, + ItemStack aStack) { + return false; + } + + @Override + public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side, + ItemStack aStack) { + return false; + } + + @Override + public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { + openGui(aPlayer); + return true; + } + + @Override + public byte getTileEntityBaseType() { + return 0; + } + + @Override + public ExtendedFacing getExtendedFacing() { + return ExtendedFacing.of(getBaseMetaTileEntity().getFrontFacing()); + } + + @Override + public void setExtendedFacing(ExtendedFacing alignment) { + getBaseMetaTileEntity().setFrontFacing(alignment.getDirection()); + } + + @Override + public IAlignmentLimits getAlignmentLimits() { + return (d, r, f) -> (d.flag & (ForgeDirection.UP.flag | ForgeDirection.DOWN.flag)) == 0; + } + + @Override + public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { + return new MTEVendingMachine(this.mName); + } + + private boolean checkMachine() { + return STRUCTURE_DEFINITION.check( + this, + "main", + getBaseMetaTileEntity().getWorld(), + getExtendedFacing(), + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getYCoord(), + getBaseMetaTileEntity().getZCoord(), + 1, + 1, + 0, + !mMachine); + } + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { + if ((aBaseMetaTileEntity.isClientSide()) && (aBaseMetaTileEntity.isActive())) { + // spawn something maybe + } + if (aBaseMetaTileEntity.isServerSide()) { + if (this.mUpdate++ % STRUCTURE_CHECK_TICKS == 0) { + this.mMachine = checkMachine(); + aBaseMetaTileEntity.setActive(this.mMachine); + } + /* + * if (this.mMachine) { + * // dispense mechanic goes here + * } + */ + } + } + + @Override + public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { + super.onFirstTick(aBaseMetaTileEntity); + if (aBaseMetaTileEntity.isClientSide()) + StructureLibAPI.queryAlignment((IAlignmentProvider) aBaseMetaTileEntity); + } + + @Override + public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { + if (mMachine) return -1; + return STRUCTURE_DEFINITION.survivalBuild( + this, + stackSize, + "main", + getBaseMetaTileEntity().getWorld(), + getExtendedFacing(), + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getYCoord(), + getBaseMetaTileEntity().getZCoord(), + 1, + 1, + 0, + elementBudget, + env, + false); + } + + @Override + public void construct(ItemStack stackSize, boolean hintsOnly) { + STRUCTURE_DEFINITION.buildOrHints( + this, + stackSize, + "main", + getBaseMetaTileEntity().getWorld(), + getExtendedFacing(), + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getYCoord(), + getBaseMetaTileEntity().getZCoord(), + 1, + 1, + 0, + hintsOnly); + } + + @Override + protected boolean useMui2() { + return true; + } + + @Override + public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { + /* + * TextFieldWidget tfw = new TextFieldWidget(); + * tfw.setText("coming soon!"); + * tfw.setSynced(false, false).setBackground(GTUITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY).setSize(120, 12); + * builder.widget(tfw.setPos(45, 4)); + */ + Column layout = new Column(); + + /* + * Row filterRow = new Row(); + * filterRow.addChild(new DrawableWidget().setSize(5,5)); + * filterRow.addChild(new TextWidget("Search: ").setMaxWidth(40).setPos(5, 5)); + * layout.widget(filterRow); + */ + layout.widget(new DrawableWidget().setSize(5, 3)); + + Row inputItems = new Row(); + for (int i = 0; i < INPUT_SLOTS; i++) { + inputItems.addChild( + new SlotWidget(inventoryHandler, i) + .setBackground(getGUITextureSet().getItemSlot(), GTUITextures.OVERLAY_SLOT_IN)); + } + inputItems.addChild(new DrawableWidget().setSize(18, 18)); + inputItems.addChild( + new ButtonWidget().setSize(18, 18) + .addTooltip("Eject Items") + .setBackground(GTUITextures.BUTTON_STANDARD, GTUITextures.OVERLAY_SLOT_RECYCLE)); + layout.widget( + inputItems.setPos(5, 15) + .setSize(18 * 9, 18)); + + // TODO: extend override phantomslot and update tradeables + // TODO: Add invisible state button overlays on top of items for trading + + builder.widget(layout); + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/items/VMItems.java b/src/main/java/com/cubefury/vendingmachine/items/VMItems.java new file mode 100644 index 0000000..bcc599d --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/items/VMItems.java @@ -0,0 +1,17 @@ +package com.cubefury.vendingmachine.items; + +import com.cubefury.vendingmachine.VendingMachine; +import com.cubefury.vendingmachine.blocks.MTEVendingMachine; + +import cpw.mods.fml.common.Optional; + +public class VMItems { + + private VMItems() {} + + @Optional.Method(modid = "gregtech") + public static void registerMultis() { + new MTEVendingMachine(VendingMachine.CONTROLLER_MTE_ID, "multimachine.vendingmachine", "Vending Machine") + .getStackForm(1); + } +} diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index b900271..e6d1297 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -1,5 +1,3 @@ -tile.vendingmachine.vending_machine.name=Vending Machine - item.vendingmachine.placeholder.name=Placeholder Item tooltip.vendingmachine=Who's even restocking this... From 4b1e20085501a64d8e08031cb932dddea326aa49 Mon Sep 17 00:00:00 2001 From: cubefury Date: Wed, 3 Sep 2025 19:28:45 +0800 Subject: [PATCH 02/40] Added text labels to trade groups --- .../java/com/cubefury/vendingmachine/trade/TradeGroup.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index 030fd7a..1d01a30 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -26,6 +26,7 @@ public class TradeGroup { private final List trades = new ArrayList<>(); public int cooldown = -1; public int maxTrades = -1; + public String label = ""; private final Set requirementSet = new HashSet<>(); // List of completed conditions for each player @@ -155,6 +156,7 @@ public boolean readFromNBT(NBTTagCompound nbt) { } this.cooldown = nbt.getInteger("cooldown"); this.maxTrades = nbt.getInteger("maxTrades"); + this.label = nbt.getString("label"); NBTTagList tradeList = nbt.getTagList("trades", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < tradeList.tagCount(); i++) { NBTTagCompound trade = tradeList.getCompoundTagAt(i); @@ -178,6 +180,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setTag("id", NBTConverter.UuidValueType.TRADEGROUP.writeId(this.id)); nbt.setInteger("cooldown", this.cooldown); nbt.setInteger("maxTrades", this.maxTrades); + nbt.setString("label", this.label); NBTTagList tList = new NBTTagList(); for (Trade t : trades) { tList.appendTag(t.writeToNBT(new NBTTagCompound())); From 9176b196b80ab973763e5ebc2aadf791a536a589 Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 4 Sep 2025 00:39:08 +0800 Subject: [PATCH 03/40] Added MUI2 UI --- .../blocks/MTEVendingMachine.java | 130 ++++++-------- .../blocks/gui/MTEVendingMachineGui.java | 164 ++++++++++++++++++ .../assets/vendingmachine/lang/en_US.lang | 1 + 3 files changed, 214 insertions(+), 81 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 45281bd..0879b38 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -6,13 +6,16 @@ import java.util.ArrayList; import java.util.List; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.ForgeDirection; +import org.jetbrains.annotations.NotNull; + +import com.cleanroommc.modularui.utils.item.ItemStackHandler; +import com.cubefury.vendingmachine.blocks.gui.MTEVendingMachineGui; import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; @@ -21,30 +24,23 @@ import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; import com.gtnewhorizon.structurelib.structure.IStructureDefinition; import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment; -import com.gtnewhorizons.modularui.api.screen.ModularWindow; -import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.common.widget.ButtonWidget; -import com.gtnewhorizons.modularui.common.widget.Column; -import com.gtnewhorizons.modularui.common.widget.DrawableWidget; -import com.gtnewhorizons.modularui.common.widget.Row; -import com.gtnewhorizons.modularui.common.widget.SlotWidget; import gregtech.api.GregTechAPI; import gregtech.api.covers.CoverRegistry; import gregtech.api.enums.Textures; -import gregtech.api.gui.modularui.GTUITextures; import gregtech.api.interfaces.ISecondaryDescribable; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; -import gregtech.api.interfaces.modularui.IAddUIWidgets; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; -import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.implementations.MTEMultiBlockBase; import gregtech.api.render.TextureFactory; import gregtech.api.util.GTUtility; import gregtech.api.util.MultiblockTooltipBuilder; -public class MTEVendingMachine extends MetaTileEntity - implements ISurvivalConstructable, ISecondaryDescribable, IAlignment, IAddUIWidgets { +public class MTEVendingMachine extends MTEMultiBlockBase + implements ISurvivalConstructable, ISecondaryDescribable, IAlignment { + + public static final int CUSTOM_UI_HEIGHT = 300; public static final int INPUT_SLOTS = 7; public static final int OUTPUT_SLOTS = 1; @@ -70,16 +66,22 @@ public class MTEVendingMachine extends MetaTileEntity public int mUpdate = 0; public boolean mMachine = false; - public ItemStack[] mInputItems = new ItemStack[INPUT_SLOTS]; - public ItemStack[] mOutputItems = new ItemStack[OUTPUT_SLOTS]; + + public ItemStackHandler inputItems = new ItemStackHandler(INPUT_SLOTS); + public ItemStackHandler outputItems = new ItemStackHandler(OUTPUT_SLOTS); public List outputBuffer = new ArrayList<>(); public MTEVendingMachine(final int aID, final String aName, final String aNameRegional) { - super(aID, aName, aNameRegional, INPUT_SLOTS + OUTPUT_SLOTS); + super(aID, aName, aNameRegional); + } + + @Override + public boolean getDefaultHasMaintenanceChecks() { + return false; } public MTEVendingMachine(String aName) { - super(aName, INPUT_SLOTS + OUTPUT_SLOTS); + super(aName); } @Override @@ -100,6 +102,21 @@ protected MultiblockTooltipBuilder getTooltip() { return tooltipBuilder; } + @Override + protected boolean forceUseMui2() { + return true; + } + + @Override + protected @NotNull MTEVendingMachineGui getGui() { + return new MTEVendingMachineGui(this, CUSTOM_UI_HEIGHT); + } + + @Override + public int getGUIHeight() { + return CUSTOM_UI_HEIGHT; + } + @Override public boolean isTeleporterCompatible() { return false; @@ -160,14 +177,12 @@ public String[] getSecondaryDescription() { @Override public void saveNBTData(NBTTagCompound aNBT) { - if (this.mOutputItems != null) { - for (int i = 0; i < mOutputItems.length; i++) { - NBTTagCompound tNBT = new NBTTagCompound(); - if (this.mOutputItems[i] != null) { - this.mOutputItems[i].writeToNBT(tNBT); - } - aNBT.setTag("mOutputItem" + i, tNBT); - } + super.saveNBTData(aNBT); + if (inputItems != null) { + aNBT.setTag("inputs", inputItems.serializeNBT()); + } + if (outputItems != null) { + aNBT.setTag("outputs", outputItems.serializeNBT()); } NBTTagList pendingOutputs = new NBTTagList(); for (ItemStack itemStack : outputBuffer) { @@ -178,11 +193,13 @@ public void saveNBTData(NBTTagCompound aNBT) { @Override public void loadNBTData(NBTTagCompound aNBT) { - this.mOutputItems = new ItemStack[OUTPUT_SLOTS]; - for (int i = 0; i < OUTPUT_SLOTS; i++) { - this.mOutputItems[i] = GTUtility.loadItem(aNBT, "mOutputItem" + i); + super.loadNBTData(aNBT); + if (inputItems != null) { + inputItems.deserializeNBT(aNBT.getCompoundTag("inputs")); + } + if (outputItems != null) { + outputItems.deserializeNBT(aNBT.getCompoundTag("outputs")); } - this.outputBuffer.clear(); NBTTagList pendingOutputs = aNBT.getTagList("outputBuffer", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < pendingOutputs.tagCount(); i++) { outputBuffer.add(GTUtility.loadItem(pendingOutputs.getCompoundTagAt(i))); @@ -201,12 +218,6 @@ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex return false; } - @Override - public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { - openGui(aPlayer); - return true; - } - @Override public byte getTileEntityBaseType() { return 0; @@ -232,7 +243,8 @@ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { return new MTEVendingMachine(this.mName); } - private boolean checkMachine() { + @Override + public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { return STRUCTURE_DEFINITION.check( this, "main", @@ -254,7 +266,7 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { } if (aBaseMetaTileEntity.isServerSide()) { if (this.mUpdate++ % STRUCTURE_CHECK_TICKS == 0) { - this.mMachine = checkMachine(); + this.mMachine = checkMachine(aBaseMetaTileEntity, null); aBaseMetaTileEntity.setActive(this.mMachine); } /* @@ -308,48 +320,4 @@ public void construct(ItemStack stackSize, boolean hintsOnly) { 0, hintsOnly); } - - @Override - protected boolean useMui2() { - return true; - } - - @Override - public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { - /* - * TextFieldWidget tfw = new TextFieldWidget(); - * tfw.setText("coming soon!"); - * tfw.setSynced(false, false).setBackground(GTUITextures.BACKGROUND_TEXT_FIELD_LIGHT_GRAY).setSize(120, 12); - * builder.widget(tfw.setPos(45, 4)); - */ - Column layout = new Column(); - - /* - * Row filterRow = new Row(); - * filterRow.addChild(new DrawableWidget().setSize(5,5)); - * filterRow.addChild(new TextWidget("Search: ").setMaxWidth(40).setPos(5, 5)); - * layout.widget(filterRow); - */ - layout.widget(new DrawableWidget().setSize(5, 3)); - - Row inputItems = new Row(); - for (int i = 0; i < INPUT_SLOTS; i++) { - inputItems.addChild( - new SlotWidget(inventoryHandler, i) - .setBackground(getGUITextureSet().getItemSlot(), GTUITextures.OVERLAY_SLOT_IN)); - } - inputItems.addChild(new DrawableWidget().setSize(18, 18)); - inputItems.addChild( - new ButtonWidget().setSize(18, 18) - .addTooltip("Eject Items") - .setBackground(GTUITextures.BUTTON_STANDARD, GTUITextures.OVERLAY_SLOT_RECYCLE)); - layout.widget( - inputItems.setPos(5, 15) - .setSize(18 * 9, 18)); - - // TODO: extend override phantomslot and update tradeables - // TODO: Add invisible state button overlays on top of items for trading - - builder.widget(layout); - } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java new file mode 100644 index 0000000..9ddd19d --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -0,0 +1,164 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.SingleChildWidget; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.ToggleButton; +import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.slot.ItemSlot; +import com.cleanroommc.modularui.widgets.slot.ModularSlot; +import com.cubefury.vendingmachine.VendingMachine; +import com.cubefury.vendingmachine.blocks.MTEVendingMachine; + +import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; +import gregtech.api.modularui2.GTGuiTextures; +import gregtech.api.modularui2.GTWidgetThemes; + +public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { + + private final MTEVendingMachine base; + private final int height; + + private boolean ejectItems = false; + + public MTEVendingMachineGui(MTEVendingMachine base, int height) { + super(base); + this.base = base; + this.height = height; + } + + @Override + public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { + registerSyncValues(syncManager); + ModularPanel panel = new ModularPanel("MTEMultiBlockBase").size(198, height) + .padding(4); + panel = panel.child( + new Column().width(170) + .child(createTitleTextStyle(base.getLocalName())) + .child(createInputRow(syncManager)) + .child(createInventoryRow(panel, syncManager))); + panel = panel.child( + new Column().size(20) + .right(5) + + .child(createOutputSlot())); + return panel; + } + + // why is this method private lmao + private IWidget createTitleTextStyle(String title) { + return new SingleChildWidget<>().coverChildren() + .topRel(0, -4, 1) + .leftRel(0, -4, 0) + .widgetTheme(GTWidgetThemes.BACKGROUND_TITLE) + .child( + IKey.str(title) + .asWidget() + .alignment(Alignment.Center) + .widgetTheme(GTWidgetThemes.TEXT_TITLE) + .marginLeft(5) + .marginRight(5) + .marginTop(5) + .marginBottom(1)); + } + + private void ejectItems() { + + VendingMachine.LOG.info("Ejecting Items"); + /* + * World world = base.getBaseMetaTileEntity().getWorld(); + * int posX = base.getBaseMetaTileEntity().getXCoord(); + * int posY = base.getBaseMetaTileEntity().getYCoord(); + * int posZ = base.getBaseMetaTileEntity().getZCoord(); + * int offsetX = base.getExtendedFacing().getDirection().offsetX; + * int offsetY = base.getExtendedFacing().getDirection().offsetY; + * int offsetZ = base.getExtendedFacing().getDirection().offsetZ; + * for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { + * ItemStack stack = base.inputItems.getStackInSlot(i); + * if (stack != null) { + * ItemStack extracted = base.inputItems.extractItem(i, stack.stackSize, false); + * final EntityItem itemEntity = new EntityItem( + * world, + * posX + offsetX, posY + offsetY, posZ + offsetZ, + * new ItemStack(extracted.getItem(), extracted.stackSize, extracted.getItemDamage()) + * ); + * if (extracted.hasTagCompound()) { + * itemEntity.getEntityItem().setTagCompound((NBTTagCompound) extracted.getTagCompound().copy()); + * } + * itemEntity.delayBeforeCanPickup = 0; + * world.spawnEntityInWorld(itemEntity); + * } + * } + */ + ejectItems = false; + } + + private IWidget createInputRow(PanelSyncManager syncManager) { + Row row = new Row(); + row.child( + SlotGroupWidget.builder() + .matrix("IIIIIII") + .key( + 'I', + index -> { + return new ItemSlot().slot(new ModularSlot(base.inputItems, index).slotGroup("inputSlotGroup")); + }) + .build()); + row.child( + new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) + .tooltipBuilder(t -> t.addLine(IKey.lang("vendingmachine.gui.item_eject"))) + .left(144) + .syncHandler("ejectItems")); + return row.height(18) + .width(162) + .top(0) + .left(4); + } + + private IWidget createOutputSlot() { + // we use slot group widget in case we want to increase the number of output slots in the future + return SlotGroupWidget.builder() + .matrix("I") + .key('I', index -> { + return new ItemSlot().slot( + new ModularSlot(base.outputItems, index).accessibility(false, true) + .slotGroup("outputSlotGroup")); + }) + .build(); + } + + // why is this method private lmao + private IWidget createInventoryRow(ModularPanel panel, PanelSyncManager syncManager) { + return new Row().widthRel(1) + .height(76) + .alignX(0) + .bottom(5) + .childIf( + base.doesBindPlayerInventory(), + SlotGroupWidget.playerInventory(false) + .marginLeft(4)); + } + + @Override + protected void registerSyncValues(PanelSyncManager syncManager) { + super.registerSyncValues(syncManager); + syncManager.registerSlotGroup("inputSlotGroup", 7, true); + syncManager.registerSlotGroup("outputSlotGroup", 1, false); + + BooleanSyncValue ejectItemsSyncer = new BooleanSyncValue(() -> this.ejectItems, val -> { + this.ejectItems = val; + ejectItems(); + }); + syncManager.syncValue("ejectItems", ejectItemsSyncer); + + } + +} diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index e6d1297..81ec797 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -9,3 +9,4 @@ vendingmachine.gui.requirement.betterquesting.missing=Missing Quest vendingmachine.gui.neiColor.conditionDefault=000000 vendingmachine.gui.neiColor.conditionSatisfied=55D441 vendingmachine.gui.neiColor.conditionUnsatisfied=A87A5E +vendingmachine.gui.item_eject=Eject Items From 05e11cdcef32077238fdd19cc3fe0d2a7b4071fc Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 4 Sep 2025 01:17:32 +0800 Subject: [PATCH 04/40] Fixed Eject Button for servers. --- .../blocks/gui/MTEVendingMachineGui.java | 84 ++++++++++++------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 9ddd19d..eec48c1 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,5 +1,10 @@ package com.cubefury.vendingmachine.blocks.gui; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; import com.cleanroommc.modularui.factory.PosGuiData; @@ -18,6 +23,8 @@ import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.relauncher.Side; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; import gregtech.api.modularui2.GTGuiTextures; import gregtech.api.modularui2.GTWidgetThemes; @@ -71,33 +78,52 @@ private IWidget createTitleTextStyle(String title) { } private void ejectItems() { - - VendingMachine.LOG.info("Ejecting Items"); - /* - * World world = base.getBaseMetaTileEntity().getWorld(); - * int posX = base.getBaseMetaTileEntity().getXCoord(); - * int posY = base.getBaseMetaTileEntity().getYCoord(); - * int posZ = base.getBaseMetaTileEntity().getZCoord(); - * int offsetX = base.getExtendedFacing().getDirection().offsetX; - * int offsetY = base.getExtendedFacing().getDirection().offsetY; - * int offsetZ = base.getExtendedFacing().getDirection().offsetZ; - * for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { - * ItemStack stack = base.inputItems.getStackInSlot(i); - * if (stack != null) { - * ItemStack extracted = base.inputItems.extractItem(i, stack.stackSize, false); - * final EntityItem itemEntity = new EntityItem( - * world, - * posX + offsetX, posY + offsetY, posZ + offsetZ, - * new ItemStack(extracted.getItem(), extracted.stackSize, extracted.getItemDamage()) - * ); - * if (extracted.hasTagCompound()) { - * itemEntity.getEntityItem().setTagCompound((NBTTagCompound) extracted.getTagCompound().copy()); - * } - * itemEntity.delayBeforeCanPickup = 0; - * world.spawnEntityInWorld(itemEntity); - * } - * } - */ + Side side = FMLCommonHandler.instance() + .getEffectiveSide(); + if (side.isServer()) { + if (base.getBaseMetaTileEntity() == null) { + VendingMachine.LOG.info("Unable to eject items as the base MTE for the Vending Machine was null."); + } else { + World world = base.getBaseMetaTileEntity() + .getWorld(); + int posX = base.getBaseMetaTileEntity() + .getXCoord(); + int posY = base.getBaseMetaTileEntity() + .getYCoord(); + int posZ = base.getBaseMetaTileEntity() + .getZCoord(); + int offsetX = base.getExtendedFacing() + .getDirection().offsetX; + int offsetY = base.getExtendedFacing() + .getDirection().offsetY; + int offsetZ = base.getExtendedFacing() + .getDirection().offsetZ; + VendingMachine.LOG.info("{} {} {}", offsetX, offsetY, offsetZ); + for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { + ItemStack stack = base.inputItems.getStackInSlot(i); + if (stack != null) { + ItemStack extracted = base.inputItems.extractItem(i, stack.stackSize, false); + final EntityItem itemEntity = new EntityItem( + world, + posX + offsetX * 0.5, + posY + offsetY * 0.5, + posZ + offsetZ * 0.5, + new ItemStack(extracted.getItem(), extracted.stackSize, extracted.getItemDamage())); + if (extracted.hasTagCompound()) { + itemEntity.getEntityItem() + .setTagCompound( + (NBTTagCompound) extracted.getTagCompound() + .copy()); + } + itemEntity.delayBeforeCanPickup = 0; + itemEntity.motionX = 0.05f * offsetX; + itemEntity.motionY = 0.05f * offsetY; + itemEntity.motionZ = 0.05f * offsetZ; + world.spawnEntityInWorld(itemEntity); + } + } + } + } ejectItems = false; } @@ -155,7 +181,9 @@ protected void registerSyncValues(PanelSyncManager syncManager) { BooleanSyncValue ejectItemsSyncer = new BooleanSyncValue(() -> this.ejectItems, val -> { this.ejectItems = val; - ejectItems(); + if (this.ejectItems) { + ejectItems(); + } }); syncManager.syncValue("ejectItems", ejectItemsSyncer); From 9bdd7508cb2f46b90de243450bd2cd3fe08d4530 Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 4 Sep 2025 02:04:17 +0800 Subject: [PATCH 05/40] Added Trades Interface Skeleton --- .../blocks/MTEVendingMachine.java | 2 ++ .../blocks/gui/MTEVendingMachineGui.java | 20 +++++++++++++++++-- .../vendingmachine/blocks/gui/TradeSlot.java | 18 +++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 0879b38..066a244 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -45,6 +45,8 @@ public class MTEVendingMachine extends MTEMultiBlockBase public static final int INPUT_SLOTS = 7; public static final int OUTPUT_SLOTS = 1; + public static final int MAX_TRADES = 999; + public static final int STRUCTURE_CHECK_TICKS = 20; private static final IStructureDefinition STRUCTURE_DEFINITION = IStructureDefinition diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index eec48c1..abe3d8e 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,5 +1,9 @@ package com.cubefury.vendingmachine.blocks.gui; +import com.cleanroommc.modularui.utils.item.IItemHandlerModifiable; +import com.cleanroommc.modularui.utils.item.ItemStackHandler; +import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -35,6 +39,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final int height; private boolean ejectItems = false; + private IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); public MTEVendingMachineGui(MTEVendingMachine base, int height) { super(base); @@ -51,11 +56,11 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(createInputRow(syncManager)) + .child(createTradeUI()) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) .right(5) - .child(createOutputSlot())); return panel; } @@ -98,7 +103,6 @@ private void ejectItems() { .getDirection().offsetY; int offsetZ = base.getExtendedFacing() .getDirection().offsetZ; - VendingMachine.LOG.info("{} {} {}", offsetX, offsetY, offsetZ); for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack stack = base.inputItems.getStackInSlot(i); if (stack != null) { @@ -161,6 +165,18 @@ private IWidget createOutputSlot() { .build(); } + private IWidget createTradeUI() { + ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9*18).margin(0); + sw.getScrollArea().getScrollY().setScrollSize(18*(MTEVendingMachine.MAX_TRADES)/9); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + int x = i % 9; + int y = i / 9; + sw.child(new TradeSlot().pos(x*18, y*18) + .slot(new ModularSlot(tradeItemHandler, i))); + } + return new Row().child(sw.top(0)).left(4).top(38); + } + // why is this method private lmao private IWidget createInventoryRow(ModularPanel panel, PanelSyncManager syncManager) { return new Row().widthRel(1) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java new file mode 100644 index 0000000..423d7b2 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -0,0 +1,18 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; +import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public class TradeSlot extends PhantomItemSlot { + + @Override + public @NotNull Result onMousePressed(int mouseButton) { + return Result.IGNORE; + } + + @Override + public boolean handleDragAndDrop(@NotNull ItemStack draggedStack, int button) { + return false; + } +} From 94fe11117cffd29dd9c8fc6db76e8cb8a35ebfc8 Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 4 Sep 2025 02:19:11 +0800 Subject: [PATCH 06/40] Added Trade Slot Overlays --- .../blocks/gui/MTEVendingMachineGui.java | 25 ++++++++++++------- .../vendingmachine/blocks/gui/TradeSlot.java | 25 ++++++++++++++++++- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index abe3d8e..310a230 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,9 +1,5 @@ package com.cubefury.vendingmachine.blocks.gui; -import com.cleanroommc.modularui.utils.item.IItemHandlerModifiable; -import com.cleanroommc.modularui.utils.item.ItemStackHandler; -import com.cleanroommc.modularui.widget.ScrollWidget; -import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -15,9 +11,13 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.utils.item.IItemHandlerModifiable; +import com.cleanroommc.modularui.utils.item.ItemStackHandler; import com.cleanroommc.modularui.value.sync.BooleanSyncValue; import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.ScrollWidget; import com.cleanroommc.modularui.widget.SingleChildWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; import com.cleanroommc.modularui.widgets.SlotGroupWidget; import com.cleanroommc.modularui.widgets.ToggleButton; import com.cleanroommc.modularui.widgets.layout.Column; @@ -166,15 +166,22 @@ private IWidget createOutputSlot() { } private IWidget createTradeUI() { - ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9*18).margin(0); - sw.getScrollArea().getScrollY().setScrollSize(18*(MTEVendingMachine.MAX_TRADES)/9); + ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) + .margin(0); + sw.getScrollArea() + .getScrollY() + .setScrollSize(18 * (MTEVendingMachine.MAX_TRADES) / 9); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int x = i % 9; int y = i / 9; - sw.child(new TradeSlot().pos(x*18, y*18) - .slot(new ModularSlot(tradeItemHandler, i))); + sw.child( + new TradeSlot(x, y).pos(x * 18, y * 18) + .slot(new ModularSlot(tradeItemHandler, i))); } - return new Row().child(sw.top(0)).left(4).top(38); + + return new Row().child(sw.top(0)) + .left(4) + .top(38); } // why is this method private lmao diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java index 423d7b2..4ae169f 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -1,11 +1,34 @@ package com.cubefury.vendingmachine.blocks.gui; -import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; import net.minecraft.item.ItemStack; + import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; + +import gregtech.api.modularui2.GTGuiTextures; + public class TradeSlot extends PhantomItemSlot { + private final int x; + private final int y; + + public TradeSlot(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public void onMouseStartHover() { + // VendingMachine.LOG.info("Hovering over {} {}", x, y); + this.hoverOverlay(GTGuiTextures.OVERLAY_BUTTON_BOUNDING_BOX); + } + + @Override + public void onMouseEndHover() { + this.disableHoverOverlay(); + } + @Override public @NotNull Result onMousePressed(int mouseButton) { return Result.IGNORE; From 97fa828a5f173708b0025edb9ff0c8030206ca81 Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 4 Sep 2025 20:24:59 +0800 Subject: [PATCH 07/40] Added Tooltip update per second and shift to freeze --- .../com/cubefury/vendingmachine/Config.java | 4 +- .../blocks/MTEVendingMachine.java | 2 + .../blocks/gui/MTEVendingMachineGui.java | 43 +++++++++-- .../blocks/gui/TradeMainPanel.java | 73 +++++++++++++++++++ .../vendingmachine/blocks/gui/TradeSlot.java | 16 +++- 5 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java diff --git a/src/main/java/com/cubefury/vendingmachine/Config.java b/src/main/java/com/cubefury/vendingmachine/Config.java index cf22851..af9f549 100644 --- a/src/main/java/com/cubefury/vendingmachine/Config.java +++ b/src/main/java/com/cubefury/vendingmachine/Config.java @@ -10,7 +10,7 @@ public class Config { public static String data_dir = "vendingmachine"; public static String config_dir = "config/vendingmachine"; - public static int gui_refresh_interval = 1; + public static int gui_refresh_interval = 20; public static File worldDir = null; @@ -24,7 +24,7 @@ public static void init(File configFile) { configuration.addCustomCategoryComment(CONFIG_CATEGORY_GUI, "GUI Settings"); gui_refresh_interval = configuration - .getInt("gui_refresh_interval", CONFIG_CATEGORY_GUI, gui_refresh_interval, 1, 3600, ""); + .getInt("gui_refresh_interval", CONFIG_CATEGORY_GUI, gui_refresh_interval, 20, 3600, "In number of ticks"); if (configuration.hasChanged()) { configuration.save(); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 066a244..35b4b41 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; +import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -111,6 +112,7 @@ protected boolean forceUseMui2() { @Override protected @NotNull MTEVendingMachineGui getGui() { + NetAvailableTradeSync.requestSync(); return new MTEVendingMachineGui(this, CUSTOM_UI_HEIGHT); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 310a230..8d4534b 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,6 +1,13 @@ package com.cubefury.vendingmachine.blocks.gui; +import com.cubefury.vendingmachine.api.storage.INameCache; +import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; +import com.cubefury.vendingmachine.storage.NameCache; +import com.cubefury.vendingmachine.trade.TradeGroup; +import com.cubefury.vendingmachine.trade.TradeGroupWrapper; +import com.cubefury.vendingmachine.trade.TradeManager; import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -33,13 +40,20 @@ import gregtech.api.modularui2.GTGuiTextures; import gregtech.api.modularui2.GTWidgetThemes; +import java.util.List; +import java.util.Set; +import java.util.UUID; + public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final MTEVendingMachine base; private final int height; private boolean ejectItems = false; - private IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); + private final IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); + private final ItemSlot[] tradeSlotList = new ItemSlot[MTEVendingMachine.MAX_TRADES]; + + private int debug_updateCount = 0; public MTEVendingMachineGui(MTEVendingMachine base, int height) { super(base); @@ -50,13 +64,13 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { @Override public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { registerSyncValues(syncManager); - ModularPanel panel = new ModularPanel("MTEMultiBlockBase").size(198, height) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, syncManager).size(198, height) .padding(4); panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(createInputRow(syncManager)) - .child(createTradeUI()) + .child(createTradeUI((TradeMainPanel) panel, syncManager)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) @@ -106,7 +120,12 @@ private void ejectItems() { for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack stack = base.inputItems.getStackInSlot(i); if (stack != null) { + // TODO: There's still a race condition here where the stack size changes between these + // two null checks. Fix ItemStack extracted = base.inputItems.extractItem(i, stack.stackSize, false); + if (extracted == null) { // if somehow it got pulled out already + continue; + } final EntityItem itemEntity = new EntityItem( world, posX + offsetX * 0.5, @@ -165,7 +184,7 @@ private IWidget createOutputSlot() { .build(); } - private IWidget createTradeUI() { + private IWidget createTradeUI(TradeMainPanel rootPanel, PanelSyncManager syncManager) { ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) .margin(0); sw.getScrollArea() @@ -174,9 +193,11 @@ private IWidget createTradeUI() { for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int x = i % 9; int y = i / 9; - sw.child( - new TradeSlot(x, y).pos(x * 18, y * 18) - .slot(new ModularSlot(tradeItemHandler, i))); + tradeSlotList[i] = new TradeSlot(x, y, rootPanel).pos(x * 18, y * 18) + .slot(new ModularSlot(tradeItemHandler, i)).tooltipDynamic(builder -> { + builder.add("yes " + debug_updateCount); + }); + sw.child(tradeSlotList[i]); } return new Row().child(sw.top(0)) @@ -209,7 +230,15 @@ protected void registerSyncValues(PanelSyncManager syncManager) { } }); syncManager.syncValue("ejectItems", ejectItemsSyncer); + } + + public void attemptPurchase(int x, int y) { + VendingMachine.LOG.info("Attempted Purchase of {} {}", x, y); + } + public void updateSlots() { + // this.tradeItemHandler.setStackInSlot(); + debug_updateCount += 1; } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java new file mode 100644 index 0000000..6263d5e --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -0,0 +1,73 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cubefury.vendingmachine.Config; +import com.cubefury.vendingmachine.VendingMachine; +import com.cubefury.vendingmachine.storage.NameCache; +import com.cubefury.vendingmachine.trade.TradeGroupWrapper; +import com.cubefury.vendingmachine.trade.TradeManager; +import net.minecraft.entity.player.EntityPlayer; +import org.jetbrains.annotations.NotNull; + +import java.awt.event.KeyEvent; +import java.util.List; +import java.util.UUID; + + +public class TradeMainPanel extends ModularPanel { + + public boolean shiftHeld = false; + private final MTEVendingMachineGui gui; + private final PanelSyncManager syncManager; + private EntityPlayer player = null; + private int ticksOpen = 0; + + public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PanelSyncManager syncManager) { + super(name); + this.gui = gui; + this.syncManager = syncManager; + } + + @Override + public boolean onKeyPressed(char typedChar, int keyCode) { + // left or right shift + if (keyCode == 0x2A || keyCode == 0x36) { + shiftHeld = true; + } + return super.onKeyPressed(typedChar, keyCode); + } + + @Override + public boolean onKeyRelease(char typedChar, int keyCode) { + // left or right shift + if (keyCode == 0x2A || keyCode == 0x36) { + shiftHeld = false; + } + return super.onKeyRelease(typedChar, keyCode); + } + + @Override + public void onUpdate() { + super.onUpdate(); + if (this.player == null && this.syncManager.isInitialised()) { + this.player = syncManager.getPlayer(); + } + if (this.ticksOpen % Config.gui_refresh_interval == 0 && player != null && !shiftHeld) { + VendingMachine.LOG.info("Refreshing Trade Info"); + List trades = TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer())); + + // TODO: Sort + + // TODO: Update slots + gui.updateSlots(); + } + this.ticksOpen += 1; + } + + public void attemptPurchase(int x, int y) { + gui.attemptPurchase(x, y); + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java index 4ae169f..8d212cb 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -1,5 +1,6 @@ package com.cubefury.vendingmachine.blocks.gui; +import com.cubefury.vendingmachine.VendingMachine; import net.minecraft.item.ItemStack; import org.jetbrains.annotations.NotNull; @@ -8,14 +9,18 @@ import gregtech.api.modularui2.GTGuiTextures; +import java.util.List; + public class TradeSlot extends PhantomItemSlot { private final int x; private final int y; + TradeMainPanel rootPanel; - public TradeSlot(int x, int y) { + public TradeSlot(int x, int y, TradeMainPanel rootPanel) { this.x = x; this.y = y; + this.rootPanel = rootPanel; } @Override @@ -31,11 +36,18 @@ public void onMouseEndHover() { @Override public @NotNull Result onMousePressed(int mouseButton) { - return Result.IGNORE; + if (rootPanel.shiftHeld) { + rootPanel.attemptPurchase(x, y); + } + return Result.SUCCESS; } @Override public boolean handleDragAndDrop(@NotNull ItemStack draggedStack, int button) { return false; } + + public void onTradeRefresh() { + + } } From 6d56a12601d9a68cb39ffadeaef90e860a55c1c2 Mon Sep 17 00:00:00 2001 From: cubefury Date: Fri, 5 Sep 2025 00:09:42 +0800 Subject: [PATCH 08/40] Added trade refresh mechanism --- .../blocks/MTEVendingMachine.java | 7 +- .../blocks/gui/MTEVendingMachineGui.java | 64 ++++++---- .../blocks/gui/TradeItemDisplay.java | 16 +++ .../blocks/gui/TradeMainPanel.java | 115 +++++++++++++++--- .../vendingmachine/blocks/gui/TradeSlot.java | 7 -- .../vendingmachine/trade/TradeGroup.java | 4 + .../assets/vendingmachine/lang/en_US.lang | 5 + 7 files changed, 169 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 35b4b41..e791f51 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.List; -import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -16,7 +15,9 @@ import org.jetbrains.annotations.NotNull; import com.cleanroommc.modularui.utils.item.ItemStackHandler; +import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.gui.MTEVendingMachineGui; +import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; @@ -112,7 +113,9 @@ protected boolean forceUseMui2() { @Override protected @NotNull MTEVendingMachineGui getGui() { - NetAvailableTradeSync.requestSync(); + if (VendingMachine.proxy.isClient()) { + NetAvailableTradeSync.requestSync(); + } return new MTEVendingMachineGui(this, CUSTOM_UI_HEIGHT); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 8d4534b..da39da2 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,13 +1,9 @@ package com.cubefury.vendingmachine.blocks.gui; -import com.cubefury.vendingmachine.api.storage.INameCache; -import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; -import com.cubefury.vendingmachine.storage.NameCache; -import com.cubefury.vendingmachine.trade.TradeGroup; -import com.cubefury.vendingmachine.trade.TradeGroupWrapper; -import com.cubefury.vendingmachine.trade.TradeManager; +import java.util.ArrayList; +import java.util.List; + import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -34,16 +30,10 @@ import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; -import cpw.mods.fml.common.FMLCommonHandler; -import cpw.mods.fml.relauncher.Side; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; import gregtech.api.modularui2.GTGuiTextures; import gregtech.api.modularui2.GTWidgetThemes; -import java.util.List; -import java.util.Set; -import java.util.UUID; - public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final MTEVendingMachine base; @@ -52,8 +42,8 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private boolean ejectItems = false; private final IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); private final ItemSlot[] tradeSlotList = new ItemSlot[MTEVendingMachine.MAX_TRADES]; - - private int debug_updateCount = 0; + private final List displayedTrades = new ArrayList<>(); + private PosGuiData guiData; public MTEVendingMachineGui(MTEVendingMachine base, int height) { super(base); @@ -63,14 +53,15 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { @Override public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { + this.guiData = guiData; registerSyncValues(syncManager); - ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, syncManager).size(198, height) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(198, height) .padding(4); panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(createInputRow(syncManager)) - .child(createTradeUI((TradeMainPanel) panel, syncManager)) + .child(createTradeUI((TradeMainPanel) panel)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) @@ -97,9 +88,7 @@ private IWidget createTitleTextStyle(String title) { } private void ejectItems() { - Side side = FMLCommonHandler.instance() - .getEffectiveSide(); - if (side.isServer()) { + if (!this.guiData.isClient()) { if (base.getBaseMetaTileEntity() == null) { VendingMachine.LOG.info("Unable to eject items as the base MTE for the Vending Machine was null."); } else { @@ -184,7 +173,7 @@ private IWidget createOutputSlot() { .build(); } - private IWidget createTradeUI(TradeMainPanel rootPanel, PanelSyncManager syncManager) { + private IWidget createTradeUI(TradeMainPanel rootPanel) { ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) .margin(0); sw.getScrollArea() @@ -193,9 +182,18 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PanelSyncManager syncMan for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int x = i % 9; int y = i / 9; + int slotNumber = i; // idk why it wants to copy a pass-by-value thing but ok tradeSlotList[i] = new TradeSlot(x, y, rootPanel).pos(x * 18, y * 18) - .slot(new ModularSlot(tradeItemHandler, i)).tooltipDynamic(builder -> { - builder.add("yes " + debug_updateCount); + .slot(new ModularSlot(tradeItemHandler, i)) + .tooltipDynamic(builder -> { + synchronized (displayedTrades) { + if (slotNumber < displayedTrades.size()) { + TradeItemDisplay cur = displayedTrades.get(slotNumber); + if (cur != null && cur.display() != null) { + builder.add("yes trade"); + } + } + } }); sw.child(tradeSlotList[i]); } @@ -236,9 +234,23 @@ public void attemptPurchase(int x, int y) { VendingMachine.LOG.info("Attempted Purchase of {} {}", x, y); } - public void updateSlots() { - // this.tradeItemHandler.setStackInSlot(); - debug_updateCount += 1; + public void updateSlots(List trades) { + synchronized (displayedTrades) { + displayedTrades.clear(); + displayedTrades.addAll(trades); + int displayedSize = displayedTrades.size(); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + if (i < displayedSize) { + tradeItemHandler.setStackInSlot( + i, + displayedTrades.get(i) != null ? displayedTrades.get(i) + .display() : null); + } else { + tradeItemHandler.setStackInSlot(i, null); + } + tradeSlotList[i].markTooltipDirty(); + } + } } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java new file mode 100644 index 0000000..b0a68ad --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java @@ -0,0 +1,16 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import java.util.List; +import java.util.UUID; + +import net.minecraft.item.ItemStack; + +import com.cubefury.vendingmachine.util.BigItemStack; +import com.github.bsideup.jabel.Desugar; + +@Desugar +public record TradeItemDisplay(List fromItems, List toItems, ItemStack display, UUID tgID, // TradeGroup + // UUID + int tradeGroupOrder, // ordering within tradegroup + String label, // additional text for tooltip + long cooldown, String cooldownText, boolean hasCooldown, boolean enabled) {} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 6263d5e..4027343 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -1,33 +1,39 @@ package com.cubefury.vendingmachine.blocks.gui; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; + import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; -import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.storage.NameCache; +import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; import com.cubefury.vendingmachine.trade.TradeManager; -import net.minecraft.entity.player.EntityPlayer; -import org.jetbrains.annotations.NotNull; - -import java.awt.event.KeyEvent; -import java.util.List; -import java.util.UUID; - +import com.cubefury.vendingmachine.util.BigItemStack; +import com.cubefury.vendingmachine.util.Translator; public class TradeMainPanel extends ModularPanel { public boolean shiftHeld = false; private final MTEVendingMachineGui gui; private final PanelSyncManager syncManager; + private final PosGuiData guiData; private EntityPlayer player = null; private int ticksOpen = 0; - public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PanelSyncManager syncManager) { + public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData guiData, + PanelSyncManager syncManager) { super(name); this.gui = gui; + this.guiData = guiData; this.syncManager = syncManager; } @@ -52,19 +58,100 @@ public boolean onKeyRelease(char typedChar, int keyCode) { @Override public void onUpdate() { super.onUpdate(); + if (!this.guiData.isClient()) { + return; + } if (this.player == null && this.syncManager.isInitialised()) { this.player = syncManager.getPlayer(); } if (this.ticksOpen % Config.gui_refresh_interval == 0 && player != null && !shiftHeld) { VendingMachine.LOG.info("Refreshing Trade Info"); - List trades = TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer())); + List trades = formatTrades( + TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + gui.updateSlots(trades); + } + this.ticksOpen += 1; + } - // TODO: Sort + public String convertCooldownText(long cd) { + if (cd < 60) { + return cd + Translator.translate("vendingmachine.gui.cooldown_display.second"); + } + if (cd < 3600) { + return cd / 60 + Translator.translate("vendingmachine.gui.cooldown_display.minute"); + } + if (cd < 86400) { + return cd / 3600 + Translator.translate("vendingmachine.gui.cooldown_display.hour"); + } + return cd / 86400 + Translator.translate("vendingmachine.gui.cooldown_display.day"); // doom.jpg + } + + public ItemStack convertToItemStack(BigItemStack stack) { + ItemStack display = stack.getCombinedStacks() + .get(0); + display.stackSize = stack.stackSize; + return display; + } - // TODO: Update slots - gui.updateSlots(); + public List formatTrades(List tradeGroups) { + List trades = new ArrayList<>(); + for (TradeGroupWrapper tgw : tradeGroups) { + List tradeList = tgw.trade() + .getTrades(); + for (int i = 0; i < tradeList.size(); i++) { + Trade trade = tgw.trade() + .getTrades() + .get(i); + BigItemStack displayItem = trade.toItems.get(0); + + trades.add( + new TradeItemDisplay( + trade.fromItems, + trade.toItems, + convertToItemStack(displayItem == null ? trade.displayItem : displayItem), + tgw.trade() + .getId(), + i, + tgw.trade() + .getLabel(), + tgw.cooldown(), + convertCooldownText(tgw.cooldown()), + tgw.cooldown() > 0, + tgw.enabled())); + } } - this.ticksOpen += 1; + // Build from bottom of list up + trades.sort((a, b) -> { + // null case + if (a == null || b == null) { + if (a == b) return 0; + return b == null ? 1 : -1; + } + // disabled trades - will filter down if both are disabled + if (!a.enabled() || !b.enabled()) { + if (a.enabled()) { + return 1; + } + if (b.enabled()) { + return -1; + } + } + // trades on cooldown - filter down if equal + if ((a.hasCooldown() || b.hasCooldown()) && (a.cooldown() != b.cooldown())) { + return a.cooldown() > b.cooldown() ? 1 : -1; + } + // tradegroupID + if (a.tgID() != b.tgID()) { + return a.tgID() + .compareTo(b.tgID()); + } + // tradegroup index + if (a.tradeGroupOrder() == b.tradeGroupOrder()) { + return 0; + } + return a.tradeGroupOrder() > b.tradeGroupOrder() ? 1 : -1; + }); + return trades; } public void attemptPurchase(int x, int y) { diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java index 8d212cb..1b9060a 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -1,6 +1,5 @@ package com.cubefury.vendingmachine.blocks.gui; -import com.cubefury.vendingmachine.VendingMachine; import net.minecraft.item.ItemStack; import org.jetbrains.annotations.NotNull; @@ -9,8 +8,6 @@ import gregtech.api.modularui2.GTGuiTextures; -import java.util.List; - public class TradeSlot extends PhantomItemSlot { private final int x; @@ -46,8 +43,4 @@ public void onMouseEndHover() { public boolean handleDragAndDrop(@NotNull ItemStack draggedStack, int button) { return false; } - - public void onTradeRefresh() { - - } } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index 1d01a30..9d7395c 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -194,6 +194,10 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { return nbt; } + public String getLabel() { + return this.label; + } + @Optional.Method(modid = "betterquesting") public void removeAllSatisfiedBqConditions(UUID player) { synchronized (tradeState) { diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index 81ec797..878a006 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -10,3 +10,8 @@ vendingmachine.gui.neiColor.conditionDefault=000000 vendingmachine.gui.neiColor.conditionSatisfied=55D441 vendingmachine.gui.neiColor.conditionUnsatisfied=A87A5E vendingmachine.gui.item_eject=Eject Items + +vendingmachine.gui.cooldown_display.second=s +vendingmachine.gui.cooldown_display.minute=m +vendingmachine.gui.cooldown_display.hour=h +vendingmachine.gui.cooldown_display.day=d From e24fb7b469334153851c0ac7154d09c2ff376072 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sat, 6 Sep 2025 00:13:02 +0800 Subject: [PATCH 09/40] Swapped IMC for NEI names --- .../cubefury/vendingmachine/integration/nei/IMCforNEI.java | 4 ++-- src/main/resources/assets/vendingmachine/lang/en_US.lang | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java index 7e4e9c9..b91a524 100644 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java +++ b/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java @@ -10,8 +10,8 @@ public class IMCforNEI { public static void IMCSender() { - sendCatalyst("vendingmachine", "vendingmachine:vending_machine"); - sendHandler("vendingmachine", "vendingmachine:vending_machine"); + sendCatalyst("vendingmachine", "vendingmachine:gt.blockmachines.multimachine.vendingmachine"); + sendHandler("vendingmachine", "vendingmachine:gt.blockmachines.multimachine.vendingmachine"); } private static void sendHandler(String name, String itemStack) { diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index 878a006..9e71265 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -15,3 +15,5 @@ vendingmachine.gui.cooldown_display.second=s vendingmachine.gui.cooldown_display.minute=m vendingmachine.gui.cooldown_display.hour=h vendingmachine.gui.cooldown_display.day=d + +gt.blockmachines.multimachine.vendingmachine.name=Vending Machine From ad903c56e8885e0711aa63fc76f035fcb1926f37 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sat, 6 Sep 2025 03:08:23 +0800 Subject: [PATCH 10/40] Added highlight for trades ready to execute --- .../blocks/gui/MTEVendingMachineGui.java | 31 ++++++++- .../blocks/gui/TradeItemDisplay.java | 2 +- .../blocks/gui/TradeMainPanel.java | 61 ++++++++++++++++-- .../vendingmachine/blocks/gui/TradeSlot.java | 13 ---- .../vendingmachine/gui/GuiTextures.java | 21 ++++++ .../gui/background/trade_available.png | Bin 0 -> 316 bytes .../textures/gui/overlay/trade_available.png | Bin 0 -> 163 bytes 7 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/trade_available.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_available.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index da39da2..5997c5f 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -10,6 +10,7 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.DynamicDrawable; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.UISettings; @@ -29,6 +30,7 @@ import com.cleanroommc.modularui.widgets.slot.ModularSlot; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.gui.GuiTextures; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; import gregtech.api.modularui2.GTGuiTextures; @@ -51,6 +53,10 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { this.height = height; } + public MTEVendingMachine getBase() { + return base; + } + @Override public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { this.guiData = guiData; @@ -70,7 +76,7 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe return panel; } - // why is this method private lmao + // why is the original method private lmao private IWidget createTitleTextStyle(String title) { return new SingleChildWidget<>().coverChildren() .topRel(0, -4, 1) @@ -186,6 +192,7 @@ private IWidget createTradeUI(TradeMainPanel rootPanel) { tradeSlotList[i] = new TradeSlot(x, y, rootPanel).pos(x * 18, y * 18) .slot(new ModularSlot(tradeItemHandler, i)) .tooltipDynamic(builder -> { + // builder.clearText(); synchronized (displayedTrades) { if (slotNumber < displayedTrades.size()) { TradeItemDisplay cur = displayedTrades.get(slotNumber); @@ -195,6 +202,26 @@ private IWidget createTradeUI(TradeMainPanel rootPanel) { } } }); + DynamicDrawable slotOverlay = new DynamicDrawable(() -> { + if ( + slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber) + .tradeableNow() + ) { + return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; + } + return null; + }); + DynamicDrawable slotBackground = new DynamicDrawable(() -> { + if ( + slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber) + .tradeableNow() + ) { + return GuiTextures.TRADE_AVAILABLE_BACKGROUND; + } + return GTGuiTextures.SLOT_ITEM_STANDARD; + }); + tradeSlotList[i].background(slotBackground); + tradeSlotList[i].overlay(slotOverlay); sw.child(tradeSlotList[i]); } @@ -203,7 +230,7 @@ private IWidget createTradeUI(TradeMainPanel rootPanel) { .top(38); } - // why is this method private lmao + // why is the original method private lmao private IWidget createInventoryRow(ModularPanel panel, PanelSyncManager syncManager) { return new Row().widthRel(1) .height(76) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java index b0a68ad..ad61d32 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java @@ -13,4 +13,4 @@ public record TradeItemDisplay(List fromItems, List // UUID int tradeGroupOrder, // ordering within tradegroup String label, // additional text for tooltip - long cooldown, String cooldownText, boolean hasCooldown, boolean enabled) {} + long cooldown, String cooldownText, boolean hasCooldown, boolean enabled, boolean tradeableNow) {} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 4027343..5da3c79 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -1,7 +1,10 @@ package com.cubefury.vendingmachine.blocks.gui; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.UUID; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -12,11 +15,11 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; -import com.cubefury.vendingmachine.VendingMachine; -import com.cubefury.vendingmachine.storage.NameCache; +import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.trade.Trade; +import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; -import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -65,9 +68,15 @@ public void onUpdate() { this.player = syncManager.getPlayer(); } if (this.ticksOpen % Config.gui_refresh_interval == 0 && player != null && !shiftHeld) { - VendingMachine.LOG.info("Refreshing Trade Info"); - List trades = formatTrades( - TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + List testTGW = new ArrayList<>(); + for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() + .entrySet()) { + testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + } + List trades = formatTrades(testTGW); + // TODO: SWAP BACK + // List trades = + // formatTrades(TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); gui.updateSlots(trades); } this.ticksOpen += 1; @@ -93,7 +102,37 @@ public ItemStack convertToItemStack(BigItemStack stack) { return display; } + public boolean checkItemsSatisfied(List trade, Map availableItems) { + for (BigItemStack bis : trade) { + ItemStack base = bis.getBaseStack(); + base.stackSize = 1; // shouldn't need this, but just in case + if (availableItems.get(base) == null || availableItems.get(base) < bis.stackSize) { + return false; + } + } + return true; + } + + public Map getAvailableItems() { + Map items = new HashMap<>(); + for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { + ItemStack stack = this.gui.getBase().inputItems.getStackInSlot(i); + if (stack != null) { + ItemStack tmp = stack.copy(); + tmp.stackSize = 1; + items.putIfAbsent(tmp, 0); + items.replace(tmp, items.get(tmp) + stack.stackSize); + } + } + return items; + } + public List formatTrades(List tradeGroups) { + + Map availableItems = this.guiData.isClient() && this.gui.getBase() != null + ? getAvailableItems() + : new HashMap<>(); + List trades = new ArrayList<>(); for (TradeGroupWrapper tgw : tradeGroups) { List tradeList = tgw.trade() @@ -117,7 +156,8 @@ public List formatTrades(List tradeGroups) tgw.cooldown(), convertCooldownText(tgw.cooldown()), tgw.cooldown() > 0, - tgw.enabled())); + tgw.enabled(), + checkItemsSatisfied(trade.fromItems, availableItems))); } } // Build from bottom of list up @@ -136,6 +176,13 @@ public List formatTrades(List tradeGroups) return -1; } } + // tradeable + if(a.tradeableNow() || b.tradeableNow()) { + if (a.tradeableNow() == b.tradeableNow()) { + return 0; + } + return a.tradeableNow() ? 1 : -1; + } // trades on cooldown - filter down if equal if ((a.hasCooldown() || b.hasCooldown()) && (a.cooldown() != b.cooldown())) { return a.cooldown() > b.cooldown() ? 1 : -1; diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java index 1b9060a..bcbbd9f 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -6,8 +6,6 @@ import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; -import gregtech.api.modularui2.GTGuiTextures; - public class TradeSlot extends PhantomItemSlot { private final int x; @@ -20,17 +18,6 @@ public TradeSlot(int x, int y, TradeMainPanel rootPanel) { this.rootPanel = rootPanel; } - @Override - public void onMouseStartHover() { - // VendingMachine.LOG.info("Hovering over {} {}", x, y); - this.hoverOverlay(GTGuiTextures.OVERLAY_BUTTON_BOUNDING_BOX); - } - - @Override - public void onMouseEndHover() { - this.disableHoverOverlay(); - } - @Override public @NotNull Result onMousePressed(int mouseButton) { if (rootPanel.shiftHeld) { diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java new file mode 100644 index 0000000..2848c4e --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -0,0 +1,21 @@ +package com.cubefury.vendingmachine.gui; + +import com.cleanroommc.modularui.drawable.UITexture; +import com.cubefury.vendingmachine.VendingMachine; + +public final class GuiTextures { + + public static final UITexture OVERLAY_TRADE_AVAILABLE_HIGHLIGHT = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/trade_available") + .imageSize(18, 18) + .canApplyTheme() + .name("trade_available_highlight") + .build(); + + public static final UITexture TRADE_AVAILABLE_BACKGROUND = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/trade_available") + .imageSize(18, 18) + .canApplyTheme() + .name("trade_available_background") + .build(); +} diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/trade_available.png b/src/main/resources/assets/vendingmachine/textures/gui/background/trade_available.png new file mode 100644 index 0000000000000000000000000000000000000000..ef1ac0ca5493d97984eaa0b3e47b71da5e501ae8 GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9EFZXnDkGR4^uC@5Xx z8c`CQpH@#Ar`$$FZ=Q}Iq*A#FgA$hk_nNm(5Z?Yhs$&r_k^repfA<&n(5O!ZBAx zcJ(tH%UH}_5hXsu<$?ZzCE-uzHvj%(*?8=jz!Bw!1m-epwut7tngKD6`)nIUZ`5+f zIJ}y7Kq$wE>4Ug|?F*^y&khQijo$z5KRkcS!o1yJrej4;qx6nV>H>}xK@0Xc$MVco za6ZL;W&Okk?b#a*s@$tw?smkjU45Wm;YO2ZF^hX~Ci5re1jZD#skXXdKrb Date: Sat, 6 Sep 2025 11:32:30 +0800 Subject: [PATCH 11/40] Force update trade panel when input items changed/purchase is made --- .../blocks/gui/MTEVendingMachineGui.java | 21 +++++-- .../blocks/gui/TradeMainPanel.java | 55 ++++++++++--------- .../vendingmachine/util/BigItemStack.java | 13 ++++- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 5997c5f..9fd9830 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -41,6 +41,8 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final MTEVendingMachine base; private final int height; + public boolean forceRefresh = false; + private boolean ejectItems = false; private final IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); private final ItemSlot[] tradeSlotList = new ItemSlot[MTEVendingMachine.MAX_TRADES]; @@ -150,11 +152,15 @@ private IWidget createInputRow(PanelSyncManager syncManager) { row.child( SlotGroupWidget.builder() .matrix("IIIIIII") - .key( - 'I', - index -> { - return new ItemSlot().slot(new ModularSlot(base.inputItems, index).slotGroup("inputSlotGroup")); - }) + .key('I', index -> { + return new ItemSlot().slot( + new ModularSlot(base.inputItems, index).slotGroup("inputSlotGroup") + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (guiData.isClient()) { + forceRefresh = true; + } + })); + }) .build()); row.child( new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) @@ -259,6 +265,11 @@ protected void registerSyncValues(PanelSyncManager syncManager) { public void attemptPurchase(int x, int y) { VendingMachine.LOG.info("Attempted Purchase of {} {}", x, y); + this.forceRefresh = true; + } + + public void resetForceRefresh() { + this.forceRefresh = false; } public void updateSlots(List trades) { diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 5da3c79..9d703a1 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -58,6 +58,19 @@ public boolean onKeyRelease(char typedChar, int keyCode) { return super.onKeyRelease(typedChar, keyCode); } + public void updateGui() { + List testTGW = new ArrayList<>(); + for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() + .entrySet()) { + testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + } + List trades = formatTrades(testTGW); + // TODO: SWAP BACK + // List trades = + // formatTrades(TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + gui.updateSlots(trades); + } + @Override public void onUpdate() { super.onUpdate(); @@ -67,17 +80,9 @@ public void onUpdate() { if (this.player == null && this.syncManager.isInitialised()) { this.player = syncManager.getPlayer(); } - if (this.ticksOpen % Config.gui_refresh_interval == 0 && player != null && !shiftHeld) { - List testTGW = new ArrayList<>(); - for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() - .entrySet()) { - testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); - } - List trades = formatTrades(testTGW); - // TODO: SWAP BACK - // List trades = - // formatTrades(TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); - gui.updateSlots(trades); + if (gui.forceRefresh || (this.ticksOpen % Config.gui_refresh_interval == 0 && player != null && !shiftHeld)) { + updateGui(); + gui.resetForceRefresh(); } this.ticksOpen += 1; } @@ -102,9 +107,9 @@ public ItemStack convertToItemStack(BigItemStack stack) { return display; } - public boolean checkItemsSatisfied(List trade, Map availableItems) { + public boolean checkItemsSatisfied(List trade, Map availableItems) { for (BigItemStack bis : trade) { - ItemStack base = bis.getBaseStack(); + BigItemStack base = bis.copy(); base.stackSize = 1; // shouldn't need this, but just in case if (availableItems.get(base) == null || availableItems.get(base) < bis.stackSize) { return false; @@ -113,12 +118,12 @@ public boolean checkItemsSatisfied(List trade, Map getAvailableItems() { - Map items = new HashMap<>(); + public Map getAvailableItems() { + Map items = new HashMap<>(); for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack stack = this.gui.getBase().inputItems.getStackInSlot(i); if (stack != null) { - ItemStack tmp = stack.copy(); + BigItemStack tmp = new BigItemStack(stack); tmp.stackSize = 1; items.putIfAbsent(tmp, 0); items.replace(tmp, items.get(tmp) + stack.stackSize); @@ -129,7 +134,7 @@ public Map getAvailableItems() { public List formatTrades(List tradeGroups) { - Map availableItems = this.guiData.isClient() && this.gui.getBase() != null + Map availableItems = this.guiData.isClient() && this.gui.getBase() != null ? getAvailableItems() : new HashMap<>(); @@ -165,29 +170,29 @@ public List formatTrades(List tradeGroups) // null case if (a == null || b == null) { if (a == b) return 0; - return b == null ? 1 : -1; + return b == null ? -1 : 1; } // disabled trades - will filter down if both are disabled if (!a.enabled() || !b.enabled()) { if (a.enabled()) { - return 1; + return -1; } if (b.enabled()) { - return -1; + return 1; } } // tradeable - if(a.tradeableNow() || b.tradeableNow()) { + if (a.tradeableNow() || b.tradeableNow()) { if (a.tradeableNow() == b.tradeableNow()) { return 0; } - return a.tradeableNow() ? 1 : -1; + return a.tradeableNow() ? -1 : 1; } // trades on cooldown - filter down if equal if ((a.hasCooldown() || b.hasCooldown()) && (a.cooldown() != b.cooldown())) { - return a.cooldown() > b.cooldown() ? 1 : -1; + return a.cooldown() > b.cooldown() ? -1 : 1; } - // tradegroupID + // tradegroupID - sort ascending if (a.tgID() != b.tgID()) { return a.tgID() .compareTo(b.tgID()); @@ -196,7 +201,7 @@ public List formatTrades(List tradeGroups) if (a.tradeGroupOrder() == b.tradeGroupOrder()) { return 0; } - return a.tradeGroupOrder() > b.tradeGroupOrder() ? 1 : -1; + return a.tradeGroupOrder() > b.tradeGroupOrder() ? -1 : 1; }); return trades; } diff --git a/src/main/java/com/cubefury/vendingmachine/util/BigItemStack.java b/src/main/java/com/cubefury/vendingmachine/util/BigItemStack.java index 3b07bdd..adeef95 100644 --- a/src/main/java/com/cubefury/vendingmachine/util/BigItemStack.java +++ b/src/main/java/com/cubefury/vendingmachine/util/BigItemStack.java @@ -142,16 +142,27 @@ public BigItemStack copy() { @Override public boolean equals(Object stack) { - if (stack == baseStack) return true; + if (stack == baseStack) return true; // idk why this was in BQ but ok if (stack instanceof ItemStack) { return baseStack.isItemEqual((ItemStack) stack) && ItemStack.areItemStackTagsEqual(baseStack, (ItemStack) stack); } + if (stack instanceof BigItemStack) { + BigItemStack castStack = (BigItemStack) stack; + return baseStack.isItemEqual(castStack.baseStack) && baseStack.stackSize == castStack.stackSize + && ItemStack.areItemStackTagsEqual(baseStack, castStack.baseStack); + } + return super.equals(stack); } + @Override + public int hashCode() { + return writeToNBT(new NBTTagCompound()).hashCode(); + } + @Nullable public static BigItemStack loadItemStackFromNBT(@Nonnull NBTTagCompound nbt) // Can load normal ItemStack NBTs. Does // NOT deal with placeholders From 53863fb0bf22972f93eef387c9a5030d7eeb4932 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sat, 6 Sep 2025 20:09:17 +0800 Subject: [PATCH 12/40] Added trade requests to server. --- .../com/cubefury/vendingmachine/Config.java | 17 +- .../blocks/MTEVendingMachine.java | 158 +++++++++++++++++- .../blocks/gui/MTEVendingMachineGui.java | 48 ++++-- .../blocks/gui/TradeItemDisplay.java | 117 ++++++++++++- .../blocks/gui/TradeMainPanel.java | 31 ++-- .../blocks/gui/TradeQueueAdapter.java | 57 +++++++ .../vendingmachine/gui/GuiTextures.java | 7 + .../network/PacketTypeRegistry.java | 4 +- .../network/handlers/NetTradeOutputSync.java | 65 ------- .../network/handlers/NetTradeRequestSync.java | 58 +++++++ .../network/handlers/NetTradeStateSync.java | 46 +---- .../vendingmachine/trade/TradeGroup.java | 11 +- .../textures/gui/overlay/trade_disabled.png | Bin 0 -> 159 bytes 13 files changed, 465 insertions(+), 154 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeQueueAdapter.java delete mode 100644 src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeOutputSync.java create mode 100644 src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_disabled.png diff --git a/src/main/java/com/cubefury/vendingmachine/Config.java b/src/main/java/com/cubefury/vendingmachine/Config.java index af9f549..8972650 100644 --- a/src/main/java/com/cubefury/vendingmachine/Config.java +++ b/src/main/java/com/cubefury/vendingmachine/Config.java @@ -6,11 +6,13 @@ public class Config { - private static final String CONFIG_CATEGORY_GUI = "GUI"; + private static final String CONFIG_CATEGORY_VM = "Vending Machine Settings"; public static String data_dir = "vendingmachine"; public static String config_dir = "config/vendingmachine"; public static int gui_refresh_interval = 20; + public static int dispense_frequency = 10; + public static int dispense_amount = 16; public static File worldDir = null; @@ -22,9 +24,18 @@ public static void init(File configFile) { config_dir = configuration .getString("config_dir", Configuration.CATEGORY_GENERAL, config_dir, "Configuration directory"); - configuration.addCustomCategoryComment(CONFIG_CATEGORY_GUI, "GUI Settings"); + configuration.addCustomCategoryComment(CONFIG_CATEGORY_VM, "Vending Machine Settings"); gui_refresh_interval = configuration - .getInt("gui_refresh_interval", CONFIG_CATEGORY_GUI, gui_refresh_interval, 20, 3600, "In number of ticks"); + .getInt("gui_refresh_interval", CONFIG_CATEGORY_VM, gui_refresh_interval, 20, 3600, "In number of ticks"); + dispense_frequency = configuration + .getInt("dispense_frequency", CONFIG_CATEGORY_VM, dispense_frequency, 1, 9000, "In number of ticks"); + dispense_amount = configuration.getInt( + "dispense_amount", + CONFIG_CATEGORY_VM, + dispense_amount, + 1, + Integer.MAX_VALUE, + "Number of items per dispense cycle"); if (configuration.hasChanged()) { configuration.save(); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index e791f51..22b9ff2 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -3,8 +3,9 @@ import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy; import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; -import java.util.ArrayList; -import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -15,9 +16,15 @@ import org.jetbrains.annotations.NotNull; import com.cleanroommc.modularui.utils.item.ItemStackHandler; +import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.gui.MTEVendingMachineGui; +import com.cubefury.vendingmachine.blocks.gui.TradeItemDisplay; import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; +import com.cubefury.vendingmachine.network.handlers.NetTradeRequestSync; +import com.cubefury.vendingmachine.network.handlers.NetTradeStateSync; +import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.util.BigItemStack; import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; @@ -73,12 +80,155 @@ public class MTEVendingMachine extends MTEMultiBlockBase public ItemStackHandler inputItems = new ItemStackHandler(INPUT_SLOTS); public ItemStackHandler outputItems = new ItemStackHandler(OUTPUT_SLOTS); - public List outputBuffer = new ArrayList<>(); + public Queue outputBuffer = new ConcurrentLinkedQueue<>(); + + public final Queue pendingTrades = new LinkedBlockingQueue<>(); + private boolean newBufferedOutputs = false; + private int ticksSinceOutput = 0; public MTEVendingMachine(final int aID, final String aName, final String aNameRegional) { super(aID, aName, aNameRegional); } + public void sendTradeRequest(TradeItemDisplay trade) { + IGregTechTileEntity baseTile = getBaseMetaTileEntity(); + if (baseTile == null) { + return; + } + NetTradeRequestSync.sendTradeRequest( + trade, + baseTile.getWorld(), + baseTile.getXCoord(), + baseTile.getYCoord(), + baseTile.getZCoord()); + } + + public void addTradeRequest(TradeItemDisplay trade) { + this.pendingTrades.add(trade); + } + + public void dispenseItems() { + if (!this.pendingTrades.isEmpty()) { + VendingMachine.LOG.info("Received trade on server"); + if (!processTradeOnServer(this.pendingTrades.poll())) { + VendingMachine.LOG.warn( + "Unable to complete trade. Either input items changed after trade submission, or a double click was sent."); + } + } + if ( + this.newBufferedOutputs + || (!this.outputBuffer.isEmpty() && this.ticksSinceOutput % Config.dispense_frequency == 0) + ) { + VendingMachine.LOG.info("Dispensing"); + int remainingDispensables = Config.dispense_amount; + while (!this.outputBuffer.isEmpty() && remainingDispensables > 0) { + ItemStack next = this.outputBuffer.peek(); + + if (next == null) { // impossible, but just in case + this.outputBuffer.poll(); + } else { + int toAdd = next.stackSize; + ItemStack nextCopy = next.copy(); + nextCopy.stackSize = 1; + for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { + // check for existing stacks + ItemStack cur = this.outputItems.getStackInSlot(i); + if (cur != null) { + ItemStack curCopy = cur.copy(); + curCopy.stackSize = 1; + if (ItemStack.areItemStacksEqual(curCopy, nextCopy)) { + int change = Math.min( + Math.min(remainingDispensables, curCopy.getMaxStackSize() - cur.stackSize), + next.stackSize); + cur.stackSize += change; + // technically not required, but we do this in case down the line + // the ItemStackHandlers passes copies instead + this.outputItems.setStackInSlot(i, cur); + toAdd -= change; + remainingDispensables -= change; + next.stackSize -= change; + } + } + } + + for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { + // make new stack + ItemStack cur = this.outputItems.getStackInSlot(i); + if (cur == null) { + int change = Math.min(remainingDispensables, toAdd); + ItemStack output = next.copy(); + output.stackSize = change; + this.outputItems.setStackInSlot(i, output); + remainingDispensables -= change; + toAdd -= change; + } + } + + if (toAdd == 0) { + this.outputBuffer.poll(); + } else { // outputs full or dispensed enough items this cycle + break; + } + } + } + ticksSinceOutput = this.newBufferedOutputs ? 0 : ticksSinceOutput + 1; + this.newBufferedOutputs = false; + } + } + + private boolean processTradeOnServer(TradeItemDisplay trade) { + if ( + trade == null || !TradeDatabase.INSTANCE.getTradeGroups() + .get(trade.tgID) + .canExecuteTrade(trade.playerID) + ) { + return false; + } + ItemStack[] inputSlots = new ItemStack[MTEVendingMachine.INPUT_SLOTS]; + for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { + ItemStack curStack = this.inputItems.getStackInSlot(i); + inputSlots[i] = curStack == null ? null : curStack.copy(); + } + + for (BigItemStack stack : trade.fromItems) { + ItemStack requiredStack = stack.getBaseStack(); + int requiredAmount = stack.stackSize; + // Remove Items from last stacks if possible + for (int i = MTEVendingMachine.INPUT_SLOTS - 1; i >= 0 && requiredAmount > 0; i--) { + ItemStack tmp = inputSlots[i].copy(); + tmp.stackSize = 1; + if ( + ItemStack.areItemStacksEqual(requiredStack, tmp) + && ItemStack.areItemStackTagsEqual(requiredStack, tmp) + ) { + if (requiredAmount >= inputSlots[i].stackSize) { + requiredAmount -= inputSlots[i].stackSize; + inputSlots[i] = null; + } else { + inputSlots[i].stackSize -= requiredAmount; + requiredAmount = 0; + } + } + } + if (requiredAmount > 0) { + return false; + } + } + + for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { + this.inputItems.setStackInSlot(i, inputSlots[i]); + } + + for (BigItemStack toItem : trade.toItems) { + this.outputBuffer.addAll(toItem.getCombinedStacks()); + this.newBufferedOutputs = true; + } + TradeDatabase.INSTANCE.getTradeGroups() + .get(trade.tgID) + .executeTrade(trade.playerID); + return true; + } + @Override public boolean getDefaultHasMaintenanceChecks() { return false; @@ -115,6 +265,7 @@ protected boolean forceUseMui2() { protected @NotNull MTEVendingMachineGui getGui() { if (VendingMachine.proxy.isClient()) { NetAvailableTradeSync.requestSync(); + NetTradeStateSync.requestSync(); } return new MTEVendingMachineGui(this, CUSTOM_UI_HEIGHT); } @@ -272,6 +423,7 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { // spawn something maybe } if (aBaseMetaTileEntity.isServerSide()) { + dispenseItems(); if (this.mUpdate++ % STRUCTURE_CHECK_TICKS == 0) { this.mMachine = checkMachine(aBaseMetaTileEntity, null); aBaseMetaTileEntity.setActive(this.mMachine); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 9fd9830..af1838c 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -47,6 +47,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); private final ItemSlot[] tradeSlotList = new ItemSlot[MTEVendingMachine.MAX_TRADES]; private final List displayedTrades = new ArrayList<>(); + private PosGuiData guiData; public MTEVendingMachineGui(MTEVendingMachine base, int height) { @@ -202,32 +203,39 @@ private IWidget createTradeUI(TradeMainPanel rootPanel) { synchronized (displayedTrades) { if (slotNumber < displayedTrades.size()) { TradeItemDisplay cur = displayedTrades.get(slotNumber); - if (cur != null && cur.display() != null) { + if (cur != null && cur.display != null) { builder.add("yes trade"); } } } }); - DynamicDrawable slotOverlay = new DynamicDrawable(() -> { + DynamicDrawable tradeAvailableOverlay = new DynamicDrawable(() -> { if ( - slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber) - .tradeableNow() + slotNumber < displayedTrades.size() + && (displayedTrades.get(slotNumber).hasCooldown || !displayedTrades.get(slotNumber).enabled) ) { + return GuiTextures.OVERLAY_TRADE_DISABLED; + } + if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).tradeableNow) { return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; } return null; }); + DynamicDrawable tradeCooldownOverlay = new DynamicDrawable(() -> { + if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).hasCooldown) { + return IKey.str(displayedTrades.get(slotNumber).cooldownText); + } + return null; + }); DynamicDrawable slotBackground = new DynamicDrawable(() -> { - if ( - slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber) - .tradeableNow() - ) { + if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).tradeableNow) { return GuiTextures.TRADE_AVAILABLE_BACKGROUND; } return GTGuiTextures.SLOT_ITEM_STANDARD; }); tradeSlotList[i].background(slotBackground); - tradeSlotList[i].overlay(slotOverlay); + tradeSlotList[i].overlay(tradeAvailableOverlay); + tradeSlotList[i].overlay(tradeCooldownOverlay); sw.child(tradeSlotList[i]); } @@ -264,10 +272,24 @@ protected void registerSyncValues(PanelSyncManager syncManager) { } public void attemptPurchase(int x, int y) { - VendingMachine.LOG.info("Attempted Purchase of {} {}", x, y); + TradeItemDisplay trade = null; + synchronized (displayedTrades) { + trade = displayedTrades.get(y * 9 + x); + } + if (trade == null) { + return; + } + submitTradesToServer(displayedTrades.get(y * 9 + x)); this.forceRefresh = true; } + private void submitTradesToServer(TradeItemDisplay trade) { + if (!trade.tradeableNow || !trade.enabled) { + return; + } + base.sendTradeRequest(trade); + } + public void resetForceRefresh() { this.forceRefresh = false; } @@ -279,10 +301,8 @@ public void updateSlots(List trades) { int displayedSize = displayedTrades.size(); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { if (i < displayedSize) { - tradeItemHandler.setStackInSlot( - i, - displayedTrades.get(i) != null ? displayedTrades.get(i) - .display() : null); + tradeItemHandler + .setStackInSlot(i, displayedTrades.get(i) != null ? displayedTrades.get(i).display : null); } else { tradeItemHandler.setStackInSlot(i, null); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java index ad61d32..f3f3bba 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java @@ -1,16 +1,117 @@ package com.cubefury.vendingmachine.blocks.gui; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; import com.cubefury.vendingmachine.util.BigItemStack; -import com.github.bsideup.jabel.Desugar; - -@Desugar -public record TradeItemDisplay(List fromItems, List toItems, ItemStack display, UUID tgID, // TradeGroup - // UUID - int tradeGroupOrder, // ordering within tradegroup - String label, // additional text for tooltip - long cooldown, String cooldownText, boolean hasCooldown, boolean enabled, boolean tradeableNow) {} +import com.cubefury.vendingmachine.util.NBTConverter; + +public class TradeItemDisplay { + + public List fromItems; + public List toItems; + public ItemStack display; + public UUID tgID; + public int tradeGroupOrder; + public String label; + public long cooldown; + public String cooldownText; + public boolean hasCooldown; + public boolean enabled; + public boolean tradeableNow; + public UUID playerID; // used to identify player who claimed a trade on the server + + public TradeItemDisplay(List fromItems, List toItems, ItemStack display, UUID tgID, + int tradeGroupOrder, String label, long cooldown, String cooldownText, boolean hasCooldown, boolean enabled, + boolean tradeableNow, UUID playerID) { + this.fromItems = fromItems; + this.toItems = toItems; + this.display = display; + this.tgID = tgID; + this.tradeGroupOrder = tradeGroupOrder; + this.label = label; + this.cooldown = cooldown; + this.cooldownText = cooldownText; + this.hasCooldown = hasCooldown; + this.enabled = enabled; + this.tradeableNow = tradeableNow; + this.playerID = playerID; + } + + public static TradeItemDisplay readFromNBT(NBTTagCompound nbt) { + List newFromItems = new ArrayList<>(); + NBTTagList fromItemsList = nbt.getTagList("fromItems", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < fromItemsList.tagCount(); i++) { + newFromItems.add(BigItemStack.loadItemStackFromNBT(fromItemsList.getCompoundTagAt(i))); + } + List newToItems = new ArrayList<>(); + NBTTagList toItemsList = nbt.getTagList("toItems", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < fromItemsList.tagCount(); i++) { + newToItems.add(BigItemStack.loadItemStackFromNBT(toItemsList.getCompoundTagAt(i))); + } + return new TradeItemDisplay( + newFromItems, + newToItems, + ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("display")), + NBTConverter.UuidValueType.TRADEGROUP.readId(nbt), + nbt.getInteger("tradeGroupOrder"), + nbt.getString("label"), + nbt.getLong("cooldown"), + nbt.getString("cooldownText"), + nbt.getBoolean("hasCooldown"), + nbt.getBoolean("enabled"), + nbt.getBoolean("tradeableNow"), + NBTConverter.UuidValueType.PLAYER.readId(nbt)); + } + + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + NBTTagList fromItemsNBT = new NBTTagList(); + for (BigItemStack bis : this.fromItems) { + fromItemsNBT.appendTag(bis.writeToNBT(new NBTTagCompound())); + } + nbt.setTag("fromItems", fromItemsNBT); + NBTTagList toItemsNBT = new NBTTagList(); + for (BigItemStack bis : this.toItems) { + toItemsNBT.appendTag(bis.writeToNBT(new NBTTagCompound())); + } + nbt.setTag("toItems", toItemsNBT); + nbt.setTag("display", this.display.writeToNBT(new NBTTagCompound())); + NBTConverter.UuidValueType.TRADEGROUP.writeId(this.tgID, nbt); + nbt.setInteger("tradeGroupOrder", this.tradeGroupOrder); + nbt.setString("label", this.label); + nbt.setLong("cooldown", this.cooldown); + nbt.setString("cooldownText", this.cooldownText); + nbt.setBoolean("hasCooldown", this.hasCooldown); + nbt.setBoolean("enabled", this.enabled); + nbt.setBoolean("tradeableNow", this.tradeableNow); + NBTConverter.UuidValueType.PLAYER.writeId(this.playerID, nbt); + + return nbt; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TradeItemDisplay)) { + return false; + } + TradeItemDisplay other = (TradeItemDisplay) obj; + return this.fromItems.equals(other.fromItems) && this.toItems.equals(other.toItems) + && ItemStack.areItemStacksEqual(this.display, other.display) + && ItemStack.areItemStackTagsEqual(this.display, other.display) + && this.tgID == other.tgID + && this.tradeGroupOrder == other.tradeGroupOrder + && this.label.equals(other.label) + && this.cooldown == other.cooldown + && this.cooldownText.equals(other.cooldownText) + && this.hasCooldown == other.hasCooldown + && this.enabled == other.enabled + && this.tradeableNow == other.tradeableNow + && this.playerID == other.playerID; + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 9d703a1..6c9c54c 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -16,6 +16,7 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeDatabase; import com.cubefury.vendingmachine.trade.TradeGroup; @@ -31,6 +32,7 @@ public class TradeMainPanel extends ModularPanel { private final PosGuiData guiData; private EntityPlayer player = null; private int ticksOpen = 0; + private UUID playerID = null; public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData guiData, PanelSyncManager syncManager) { @@ -38,6 +40,7 @@ public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData this.gui = gui; this.guiData = guiData; this.syncManager = syncManager; + this.playerID = NameCache.INSTANCE.getUUIDFromPlayer(guiData.getPlayer()); } @Override @@ -162,7 +165,8 @@ public List formatTrades(List tradeGroups) convertCooldownText(tgw.cooldown()), tgw.cooldown() > 0, tgw.enabled(), - checkItemsSatisfied(trade.fromItems, availableItems))); + checkItemsSatisfied(trade.fromItems, availableItems), + playerID)); } } // Build from bottom of list up @@ -173,35 +177,34 @@ public List formatTrades(List tradeGroups) return b == null ? -1 : 1; } // disabled trades - will filter down if both are disabled - if (!a.enabled() || !b.enabled()) { - if (a.enabled()) { + if (!a.enabled || !b.enabled) { + if (a.enabled) { return -1; } - if (b.enabled()) { + if (b.enabled) { return 1; } } // tradeable - if (a.tradeableNow() || b.tradeableNow()) { - if (a.tradeableNow() == b.tradeableNow()) { + if (a.tradeableNow || b.tradeableNow) { + if (a.tradeableNow == b.tradeableNow) { return 0; } - return a.tradeableNow() ? -1 : 1; + return a.tradeableNow ? -1 : 1; } // trades on cooldown - filter down if equal - if ((a.hasCooldown() || b.hasCooldown()) && (a.cooldown() != b.cooldown())) { - return a.cooldown() > b.cooldown() ? -1 : 1; + if ((a.hasCooldown || b.hasCooldown) && (a.cooldown != b.cooldown)) { + return a.cooldown > b.cooldown ? -1 : 1; } // tradegroupID - sort ascending - if (a.tgID() != b.tgID()) { - return a.tgID() - .compareTo(b.tgID()); + if (a.tgID != b.tgID) { + return a.tgID.compareTo(b.tgID); } // tradegroup index - if (a.tradeGroupOrder() == b.tradeGroupOrder()) { + if (a.tradeGroupOrder == b.tradeGroupOrder) { return 0; } - return a.tradeGroupOrder() > b.tradeGroupOrder() ? -1 : 1; + return a.tradeGroupOrder > b.tradeGroupOrder ? -1 : 1; }); return trades; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeQueueAdapter.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeQueueAdapter.java new file mode 100644 index 0000000..97d0f77 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeQueueAdapter.java @@ -0,0 +1,57 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import java.io.IOException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Queue; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.NotNull; + +import com.cleanroommc.modularui.utils.serialization.IByteBufAdapter; + +public class TradeQueueAdapter implements IByteBufAdapter> { + + @Override + public Queue deserialize(PacketBuffer buffer) throws IOException { + int size = buffer.readVarIntFromBuffer(); + Queue queue = new LinkedList<>(); + + for (int i = 0; i < size; i++) { + NBTTagCompound tag = buffer.readNBTTagCompoundFromBuffer(); + if (tag != null) { + queue.add(TradeItemDisplay.readFromNBT(tag)); + } + } + return queue; + } + + @Override + public void serialize(PacketBuffer buffer, Queue queue) throws IOException { + buffer.writeVarIntToBuffer(queue.size()); + for (TradeItemDisplay item : queue) { + buffer.writeNBTTagCompoundToBuffer(item.writeToNBT(new NBTTagCompound())); + } + } + + @Override + public boolean areEqual(@NotNull Queue t1, @NotNull Queue t2) { + if (t1.size() != t2.size()) { + return false; + } + + Iterator it1 = t1.iterator(); + Iterator it2 = t2.iterator(); + + while (it1.hasNext() && it2.hasNext()) { + TradeItemDisplay d1 = it1.next(); + TradeItemDisplay d2 = it2.next(); + if (!d1.equals(d2)) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index 2848c4e..e8ff5a8 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -12,6 +12,13 @@ public final class GuiTextures { .name("trade_available_highlight") .build(); + public static final UITexture OVERLAY_TRADE_DISABLED = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/trade_disabled") + .imageSize(18, 18) + .canApplyTheme() + .name("trade_disabled") + .build(); + public static final UITexture TRADE_AVAILABLE_BACKGROUND = UITexture.builder() .location(VendingMachine.MODID, "gui/background/trade_available") .imageSize(18, 18) diff --git a/src/main/java/com/cubefury/vendingmachine/network/PacketTypeRegistry.java b/src/main/java/com/cubefury/vendingmachine/network/PacketTypeRegistry.java index 2d298f3..7237519 100644 --- a/src/main/java/com/cubefury/vendingmachine/network/PacketTypeRegistry.java +++ b/src/main/java/com/cubefury/vendingmachine/network/PacketTypeRegistry.java @@ -17,7 +17,7 @@ import com.cubefury.vendingmachine.network.handlers.NetNameSync; import com.cubefury.vendingmachine.network.handlers.NetSatisfiedQuestSync; import com.cubefury.vendingmachine.network.handlers.NetTradeDbSync; -import com.cubefury.vendingmachine.network.handlers.NetTradeOutputSync; +import com.cubefury.vendingmachine.network.handlers.NetTradeRequestSync; import com.cubefury.vendingmachine.network.handlers.NetTradeStateSync; public class PacketTypeRegistry implements IPacketRegistry { @@ -30,8 +30,8 @@ public class PacketTypeRegistry implements IPacketRegistry { public void init() { NetTradeDbSync.registerHandler(); NetTradeStateSync.registerHandler(); - NetTradeOutputSync.registerHandler(); NetAvailableTradeSync.registerHandler(); + NetTradeRequestSync.registerHandler(); NetSatisfiedQuestSync.registerHandler(); NetNameSync.registerHandler(); diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeOutputSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeOutputSync.java deleted file mode 100644 index 4a0e40d..0000000 --- a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeOutputSync.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.cubefury.vendingmachine.network.handlers; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.util.Constants; - -import com.cubefury.vendingmachine.VendingMachine; -import com.cubefury.vendingmachine.api.network.UnserializedPacket; -import com.cubefury.vendingmachine.api.util.Tuple2; -import com.cubefury.vendingmachine.network.PacketSender; -import com.cubefury.vendingmachine.network.PacketTypeRegistry; -import com.cubefury.vendingmachine.storage.NameCache; -import com.cubefury.vendingmachine.trade.TradeManager; -import com.cubefury.vendingmachine.util.BigItemStack; -import com.cubefury.vendingmachine.util.JsonHelper; -import com.cubefury.vendingmachine.util.NBTConverter; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -public class NetTradeOutputSync { - - private static final ResourceLocation ID_NAME = new ResourceLocation("vendingmachine:trade_output_sync"); - - public static void registerHandler() { - PacketTypeRegistry.INSTANCE.registerServerHandler(ID_NAME, NetTradeOutputSync::onServer); - - if (VendingMachine.proxy.isClient()) { - PacketTypeRegistry.INSTANCE.registerClientHandler(ID_NAME, NetTradeOutputSync::onClient); - } - } - - public static void sendReward(EntityPlayerMP player, NBTTagList pending) { - NBTTagCompound payload = new NBTTagCompound(); - UUID playerId = NameCache.INSTANCE.getUUIDFromPlayer(player); - NBTConverter.UuidValueType.PLAYER.writeId(playerId, payload); - payload.setTag("pending", pending); - - PacketSender.INSTANCE.sendToPlayers(new UnserializedPacket(ID_NAME, payload), player); - } - - public static void onServer(Tuple2 message) { - VendingMachine.LOG.warn("Impossible trade output sync request received on server..."); - } - - @SideOnly(Side.CLIENT) - public static void onClient(NBTTagCompound message) { - UUID playerId = NBTConverter.UuidValueType.PLAYER.readId(message); - NBTTagList pending = message.getTagList("pending", Constants.NBT.TAG_COMPOUND); - List pendingItems = new ArrayList<>(); - for (int i = 0; i < pending.tagCount(); i++) { - pendingItems.add(JsonHelper.JsonToItemStack(pending.getCompoundTagAt(i))); - } - TradeManager.INSTANCE.addPending(playerId, pendingItems); - - // we let the auto refresh on the Vending Machine - // container handle the dispensing - } -} diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java new file mode 100644 index 0000000..9e76ea4 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java @@ -0,0 +1,58 @@ +package com.cubefury.vendingmachine.network.handlers; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import com.cubefury.vendingmachine.api.network.UnserializedPacket; +import com.cubefury.vendingmachine.api.util.Tuple2; +import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.blocks.gui.TradeItemDisplay; +import com.cubefury.vendingmachine.network.PacketSender; +import com.cubefury.vendingmachine.network.PacketTypeRegistry; + +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; + +public class NetTradeRequestSync { + + private static final ResourceLocation ID_NAME = new ResourceLocation("vendingmachine:traderequest_sync"); + + public static void registerHandler() { + PacketTypeRegistry.INSTANCE.registerServerHandler(ID_NAME, NetTradeRequestSync::onServer); + } + + public static void sendTradeRequest(TradeItemDisplay trade, World world, int x, int y, int z) { + NBTTagCompound payload = new NBTTagCompound(); + payload.setTag("trade", trade.writeToNBT(new NBTTagCompound())); + payload.setInteger("dim", world.provider.dimensionId); + payload.setInteger("x", x); + payload.setInteger("y", y); + payload.setInteger("z", z); + PacketSender.INSTANCE.sendToServer(new UnserializedPacket(ID_NAME, payload)); + } + + public static void onServer(Tuple2 message) { + World world = DimensionManager.getWorld( + message.first() + .getInteger("dim")); + TileEntity te = world.getTileEntity( + message.first() + .getInteger("x"), + message.first() + .getInteger("y"), + message.first() + .getInteger("z")); + if ( + te instanceof IGregTechTileEntity + && ((IGregTechTileEntity) te).getMetaTileEntity() instanceof MTEVendingMachine + ) { + ((MTEVendingMachine) ((IGregTechTileEntity) te).getMetaTileEntity()).addTradeRequest( + TradeItemDisplay.readFromNBT( + message.first() + .getCompoundTag("trade"))); + } + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeStateSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeStateSync.java index 9bf9c06..7c3d619 100644 --- a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeStateSync.java +++ b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeStateSync.java @@ -7,9 +7,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.util.Constants; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.api.network.UnserializedPacket; @@ -17,11 +15,7 @@ import com.cubefury.vendingmachine.network.PacketSender; import com.cubefury.vendingmachine.network.PacketTypeRegistry; import com.cubefury.vendingmachine.storage.NameCache; -import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeDatabase; -import com.cubefury.vendingmachine.trade.TradeGroup; -import com.cubefury.vendingmachine.util.BigItemStack; -import com.cubefury.vendingmachine.util.JsonHelper; import com.cubefury.vendingmachine.util.NBTConverter; import cpw.mods.fml.relauncher.Side; @@ -58,51 +52,21 @@ public static void sendTradeState(@Nullable EntityPlayerMP player, boolean merge } @SideOnly(Side.CLIENT) - public static void getTrades() { + public static void requestSync() { NBTTagCompound payload = new NBTTagCompound(); payload.setString("requestType", "getTrades"); PacketSender.INSTANCE.sendToServer(new UnserializedPacket(ID_NAME, payload)); } - @SideOnly(Side.CLIENT) - public static void claimTrade(UUID tradeGroup, Trade trade) { - NBTTagCompound payload = new NBTTagCompound(); - payload.setString("requestType", "claimTrade"); - NBTConverter.UuidValueType.TRADEGROUP.writeId(tradeGroup, payload); - - NBTTagList pendingOutput = new NBTTagList(); - for (BigItemStack stack : trade.toItems) { - pendingOutput.appendTag(JsonHelper.ItemStackToJson(stack, new NBTTagCompound())); - } - payload.setTag("pendingOutput", pendingOutput); - - PacketSender.INSTANCE.sendToServer(new UnserializedPacket(ID_NAME, payload)); - } - public static void onServer(Tuple2 message) { TradeDatabase db = TradeDatabase.INSTANCE; String requestType = message.first() .getString("requestType"); - switch (requestType) { - case "claimTrade": - UUID playerId = NameCache.INSTANCE.getUUIDFromPlayer(message.second()); - NBTTagList pendingOutput = message.first() - .getTagList("pendingOutput", Constants.NBT.TAG_COMPOUND); - TradeGroup tg = db.getTradeGroupFromId(NBTConverter.UuidValueType.TRADEGROUP.readId(message.first())); - if (tg.attemptExecuteTrade(playerId)) { - NetTradeOutputSync.sendReward(message.second(), pendingOutput); - sendTradeState(message.second(), false); - } else { - VendingMachine.LOG - .warn("Player {} made invalid reward claim attempt for trade group {}", playerId, tg.getId()); - } - break; // technically we can let this continue cuz we sendTradeState in both cases... - case "getTrades": - sendTradeState(message.second(), false); - break; - default: - VendingMachine.LOG.warn("Unknown trade state sync request type received: {}", requestType); + if (requestType.equals("getTrades")) { + sendTradeState(message.second(), false); + } else { + VendingMachine.LOG.warn("Unknown trade state sync request type received: {}", requestType); } } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index 9d7395c..73b58cb 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -127,22 +127,25 @@ public void setTradeState(UUID player, TradeHistory history) { } } - public boolean attemptExecuteTrade(UUID player) { + public boolean canExecuteTrade(UUID player) { List availableTrades = TradeManager.INSTANCE.getTrades(player); for (TradeGroupWrapper trade : availableTrades) { if (trade == null) { // shouldn't happen continue; } if (trade.trade().id == this.id && trade.enabled() && cooldown < 0) { - TradeHistory newTradeHistory = getTradeState(player); - newTradeHistory.executeTrade(); - setTradeState(player, newTradeHistory); return true; } } return false; } + public void executeTrade(UUID player) { + TradeHistory newTradeHistory = getTradeState(player); + newTradeHistory.executeTrade(); + setTradeState(player, newTradeHistory); + } + public boolean readFromNBT(NBTTagCompound nbt) { this.trades.clear(); this.requirementSet.clear(); diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_disabled.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..32c804b929fd284106be331ec313e34a7633c0c4 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg`m7HxOnNnd0mS6qGJ; zjVKAuPb(=;EJ|f?PR%K Date: Sun, 7 Sep 2025 00:52:12 +0800 Subject: [PATCH 13/40] Added trade claiming. --- .../blocks/MTEVendingMachine.java | 39 +++++++------------ .../blocks/gui/MTEVendingMachineGui.java | 26 ++++++++----- .../blocks/gui/TradeMainPanel.java | 7 ++-- .../vendingmachine/trade/TradeGroup.java | 2 +- .../vendingmachine/trade/TradeManager.java | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 22b9ff2..91b47fb 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -119,7 +119,7 @@ public void dispenseItems() { this.newBufferedOutputs || (!this.outputBuffer.isEmpty() && this.ticksSinceOutput % Config.dispense_frequency == 0) ) { - VendingMachine.LOG.info("Dispensing"); + VendingMachine.LOG.info("stack in output slot: {}", this.outputItems.getStackInSlot(0)); int remainingDispensables = Config.dispense_amount; while (!this.outputBuffer.isEmpty() && remainingDispensables > 0) { ItemStack next = this.outputBuffer.peek(); @@ -136,13 +136,14 @@ public void dispenseItems() { if (cur != null) { ItemStack curCopy = cur.copy(); curCopy.stackSize = 1; - if (ItemStack.areItemStacksEqual(curCopy, nextCopy)) { + if ( + ItemStack.areItemStacksEqual(curCopy, nextCopy) + && ItemStack.areItemStackTagsEqual(curCopy, nextCopy) + ) { int change = Math.min( Math.min(remainingDispensables, curCopy.getMaxStackSize() - cur.stackSize), next.stackSize); cur.stackSize += change; - // technically not required, but we do this in case down the line - // the ItemStackHandlers passes copies instead this.outputItems.setStackInSlot(i, cur); toAdd -= change; remainingDispensables -= change; @@ -150,10 +151,12 @@ public void dispenseItems() { } } } + VendingMachine.LOG.info("Make new stack: {} {}", remainingDispensables, toAdd); for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { // make new stack ItemStack cur = this.outputItems.getStackInSlot(i); + VendingMachine.LOG.info("slot data: {}", cur); if (cur == null) { int change = Math.min(remainingDispensables, toAdd); ItemStack output = next.copy(); @@ -171,12 +174,13 @@ public void dispenseItems() { } } } - ticksSinceOutput = this.newBufferedOutputs ? 0 : ticksSinceOutput + 1; - this.newBufferedOutputs = false; } + ticksSinceOutput = this.newBufferedOutputs ? 0 : ticksSinceOutput + 1; + this.newBufferedOutputs = false; } private boolean processTradeOnServer(TradeItemDisplay trade) { + VendingMachine.LOG.info("breakpoint 1"); if ( trade == null || !TradeDatabase.INSTANCE.getTradeGroups() .get(trade.tgID) @@ -184,6 +188,7 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { ) { return false; } + VendingMachine.LOG.info("breakpoint 2"); ItemStack[] inputSlots = new ItemStack[MTEVendingMachine.INPUT_SLOTS]; for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack curStack = this.inputItems.getStackInSlot(i); @@ -195,6 +200,9 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { int requiredAmount = stack.stackSize; // Remove Items from last stacks if possible for (int i = MTEVendingMachine.INPUT_SLOTS - 1; i >= 0 && requiredAmount > 0; i--) { + if (inputSlots[i] == null) { + continue; + } ItemStack tmp = inputSlots[i].copy(); tmp.stackSize = 1; if ( @@ -214,6 +222,7 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { return false; } } + VendingMachine.LOG.info("breakpoint 3"); for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { this.inputItems.setStackInSlot(i, inputSlots[i]); @@ -294,24 +303,6 @@ public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirect return FACING_SIDE; } - /* - * Use this to implement the items slowly dispensing? idk - * temp code copied from bricked blast furnace implementation - * Make sure to add progresstime and maxprogresstime to save/load nbt - * @Override - * public int getProgresstime() { - * return this.mProgresstime; - * } - * @Override - * public int maxProgresstime() { - * return this.mMaxProgresstime; - * } - * @Override - * public int increaseProgress(int aProgress) { - * this.mProgresstime += aProgress; - * return this.mMaxProgresstime - this.mProgresstime; - * } - */ @Override public String[] getDescription() { return getCurrentDescription(); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index af1838c..99f429a 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -179,9 +179,13 @@ private IWidget createOutputSlot() { return SlotGroupWidget.builder() .matrix("I") .key('I', index -> { - return new ItemSlot().slot( - new ModularSlot(base.outputItems, index).accessibility(false, true) - .slotGroup("outputSlotGroup")); + ModularSlot ms = new ModularSlot(base.outputItems, index).accessibility(false, true) + .slotGroup("outputSlotGroup"); + ms.changeListener((newItem, onlyAmountChanged, client, init) -> { + VendingMachine.LOG.info("Changed output slot"); + VendingMachine.LOG.info(base.outputItems.getStackInSlot(0)); + }); + return new ItemSlot().slot(ms); }) .build(); } @@ -233,9 +237,9 @@ private IWidget createTradeUI(TradeMainPanel rootPanel) { } return GTGuiTextures.SLOT_ITEM_STANDARD; }); + tradeSlotList[i].background(slotBackground); - tradeSlotList[i].overlay(tradeAvailableOverlay); - tradeSlotList[i].overlay(tradeCooldownOverlay); + tradeSlotList[i].overlay(tradeAvailableOverlay, tradeCooldownOverlay); sw.child(tradeSlotList[i]); } @@ -273,13 +277,17 @@ protected void registerSyncValues(PanelSyncManager syncManager) { public void attemptPurchase(int x, int y) { TradeItemDisplay trade = null; + synchronized (displayedTrades) { + if (displayedTrades.size() < y * 9 + x - 1) { + return; + } trade = displayedTrades.get(y * 9 + x); + if (trade == null) { + return; + } + submitTradesToServer(displayedTrades.get(y * 9 + x)); } - if (trade == null) { - return; - } - submitTradesToServer(displayedTrades.get(y * 9 + x)); this.forceRefresh = true; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 6c9c54c..d908c5d 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -21,6 +21,7 @@ import com.cubefury.vendingmachine.trade.TradeDatabase; import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; +import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -67,10 +68,10 @@ public void updateGui() { .entrySet()) { testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); } - List trades = formatTrades(testTGW); + // List trades = formatTrades(testTGW); // TODO: SWAP BACK - // List trades = - // formatTrades(TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + List trades = formatTrades( + TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); gui.updateSlots(trades); } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index 73b58cb..00000c5 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -133,7 +133,7 @@ public boolean canExecuteTrade(UUID player) { if (trade == null) { // shouldn't happen continue; } - if (trade.trade().id == this.id && trade.enabled() && cooldown < 0) { + if (trade.trade().id.equals(this.id) && trade.enabled() && trade.cooldown() < 0) { return true; } } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeManager.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeManager.java index aab753a..77137a3 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeManager.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeManager.java @@ -111,7 +111,7 @@ public List getTrades(UUID player) { if ( tg.cooldown != -1 && lastTradeTime != -1 && (currentTimestamp - lastTradeTime) / 1000 < tg.cooldown ) { - cooldownRemaining = (currentTimestamp - lastTradeTime) / 1000; + cooldownRemaining = tg.cooldown - (currentTimestamp - lastTradeTime) / 1000; } else { cooldownRemaining = -1; } From 9a818e21838a7e7f0eecb2e68c00dada7ceb4f36 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 7 Sep 2025 01:18:42 +0800 Subject: [PATCH 14/40] Added trade state saveload --- .../vendingmachine/blocks/MTEVendingMachine.java | 9 +-------- .../vendingmachine/blocks/gui/TradeMainPanel.java | 10 ++++++++-- .../com/cubefury/vendingmachine/trade/TradeGroup.java | 4 ++++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 91b47fb..6a3c940 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -109,7 +109,6 @@ public void addTradeRequest(TradeItemDisplay trade) { public void dispenseItems() { if (!this.pendingTrades.isEmpty()) { - VendingMachine.LOG.info("Received trade on server"); if (!processTradeOnServer(this.pendingTrades.poll())) { VendingMachine.LOG.warn( "Unable to complete trade. Either input items changed after trade submission, or a double click was sent."); @@ -119,7 +118,6 @@ public void dispenseItems() { this.newBufferedOutputs || (!this.outputBuffer.isEmpty() && this.ticksSinceOutput % Config.dispense_frequency == 0) ) { - VendingMachine.LOG.info("stack in output slot: {}", this.outputItems.getStackInSlot(0)); int remainingDispensables = Config.dispense_amount; while (!this.outputBuffer.isEmpty() && remainingDispensables > 0) { ItemStack next = this.outputBuffer.peek(); @@ -151,12 +149,9 @@ public void dispenseItems() { } } } - VendingMachine.LOG.info("Make new stack: {} {}", remainingDispensables, toAdd); - for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { // make new stack ItemStack cur = this.outputItems.getStackInSlot(i); - VendingMachine.LOG.info("slot data: {}", cur); if (cur == null) { int change = Math.min(remainingDispensables, toAdd); ItemStack output = next.copy(); @@ -180,7 +175,6 @@ public void dispenseItems() { } private boolean processTradeOnServer(TradeItemDisplay trade) { - VendingMachine.LOG.info("breakpoint 1"); if ( trade == null || !TradeDatabase.INSTANCE.getTradeGroups() .get(trade.tgID) @@ -188,7 +182,6 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { ) { return false; } - VendingMachine.LOG.info("breakpoint 2"); ItemStack[] inputSlots = new ItemStack[MTEVendingMachine.INPUT_SLOTS]; for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack curStack = this.inputItems.getStackInSlot(i); @@ -222,7 +215,6 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { return false; } } - VendingMachine.LOG.info("breakpoint 3"); for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { this.inputItems.setStackInSlot(i, inputSlots[i]); @@ -235,6 +227,7 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { TradeDatabase.INSTANCE.getTradeGroups() .get(trade.tgID) .executeTrade(trade.playerID); + return true; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index d908c5d..1bbd154 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -194,8 +194,14 @@ public List formatTrades(List tradeGroups) return a.tradeableNow ? -1 : 1; } // trades on cooldown - filter down if equal - if ((a.hasCooldown || b.hasCooldown) && (a.cooldown != b.cooldown)) { - return a.cooldown > b.cooldown ? -1 : 1; + if (a.hasCooldown && b.hasCooldown && a.cooldown != b.cooldown) { + return a.cooldown > b.cooldown ? 1 : -1; + } + if (a.hasCooldown || b.hasCooldown) { + if (a.cooldown == b.cooldown) { + return 0; + } + return a.hasCooldown ? -1 : 1; } // tradegroupID - sort ascending if (a.tgID != b.tgID) { diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index 00000c5..b2f980d 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -1,6 +1,7 @@ package com.cubefury.vendingmachine.trade; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -14,6 +15,7 @@ import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.api.trade.ICondition; +import com.cubefury.vendingmachine.handlers.SaveLoadHandler; import com.cubefury.vendingmachine.integration.betterquesting.BqAdapter; import com.cubefury.vendingmachine.integration.betterquesting.BqCondition; import com.cubefury.vendingmachine.util.NBTConverter; @@ -124,6 +126,7 @@ public TradeHistory getTradeState(UUID player) { public void setTradeState(UUID player, TradeHistory history) { synchronized (tradeState) { tradeState.put(player, history); + } } @@ -144,6 +147,7 @@ public void executeTrade(UUID player) { TradeHistory newTradeHistory = getTradeState(player); newTradeHistory.executeTrade(); setTradeState(player, newTradeHistory); + SaveLoadHandler.INSTANCE.writeTradeState(Collections.singleton(player)); } public boolean readFromNBT(NBTTagCompound nbt) { From f19c2306cd4e946109cc3e60b88886c6ee4a6486 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 7 Sep 2025 18:00:10 +0800 Subject: [PATCH 15/40] Fixed Incorrect Item counts dispensed --- .../blocks/MTEVendingMachine.java | 17 ++-- .../blocks/gui/MTEVendingMachineGui.java | 1 + .../blocks/gui/TradeMainPanel.java | 77 +++++++++---------- src/main/resources/mcmod.info | 6 +- 4 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 6a3c940..82c9448 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -125,10 +125,10 @@ public void dispenseItems() { if (next == null) { // impossible, but just in case this.outputBuffer.poll(); } else { - int toAdd = next.stackSize; ItemStack nextCopy = next.copy(); nextCopy.stackSize = 1; - for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { + for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 + && next.stackSize > 0; i++) { // check for existing stacks ItemStack cur = this.outputItems.getStackInSlot(i); if (cur != null) { @@ -143,26 +143,26 @@ public void dispenseItems() { next.stackSize); cur.stackSize += change; this.outputItems.setStackInSlot(i, cur); - toAdd -= change; - remainingDispensables -= change; next.stackSize -= change; + remainingDispensables -= change; } } } - for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 && toAdd > 0; i++) { + for (int i = 0; i < MTEVendingMachine.OUTPUT_SLOTS && remainingDispensables > 0 + && next.stackSize > 0; i++) { // make new stack ItemStack cur = this.outputItems.getStackInSlot(i); if (cur == null) { - int change = Math.min(remainingDispensables, toAdd); + int change = Math.min(remainingDispensables, next.stackSize); ItemStack output = next.copy(); output.stackSize = change; this.outputItems.setStackInSlot(i, output); remainingDispensables -= change; - toAdd -= change; + next.stackSize -= change; } } - if (toAdd == 0) { + if (next.stackSize == 0) { this.outputBuffer.poll(); } else { // outputs full or dispensed enough items this cycle break; @@ -221,6 +221,7 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { } for (BigItemStack toItem : trade.toItems) { + if (toItem == null) continue; this.outputBuffer.addAll(toItem.getCombinedStacks()); this.newBufferedOutputs = true; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 99f429a..05e40b3 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import com.cleanroommc.modularui.widgets.ListWidget; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 1bbd154..23a931e 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -7,6 +7,7 @@ import java.util.UUID; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import org.jetbrains.annotations.NotNull; @@ -170,52 +171,50 @@ public List formatTrades(List tradeGroups) playerID)); } } - // Build from bottom of list up trades.sort((a, b) -> { // null case - if (a == null || b == null) { - if (a == b) return 0; - return b == null ? -1 : 1; + if (a == null && b == null) return 0; + if (a == null) return 1; + if (b == null) return -1; + if (a.display.getItem() == null && b.display.getItem() == null) return 0; + if (a.display.getItem() == null) return 1; + if (b.display.getItem() == null) return -1; + + int rankA = getCategoryRank(a); + int rankB = getCategoryRank(b); + + if (rankA != rankB) { + return Integer.compare(rankA, rankB); } - // disabled trades - will filter down if both are disabled - if (!a.enabled || !b.enabled) { - if (a.enabled) { - return -1; - } - if (b.enabled) { - return 1; - } - } - // tradeable - if (a.tradeableNow || b.tradeableNow) { - if (a.tradeableNow == b.tradeableNow) { - return 0; - } - return a.tradeableNow ? -1 : 1; - } - // trades on cooldown - filter down if equal - if (a.hasCooldown && b.hasCooldown && a.cooldown != b.cooldown) { - return a.cooldown > b.cooldown ? 1 : -1; - } - if (a.hasCooldown || b.hasCooldown) { - if (a.cooldown == b.cooldown) { - return 0; - } - return a.hasCooldown ? -1 : 1; - } - // tradegroupID - sort ascending - if (a.tgID != b.tgID) { - return a.tgID.compareTo(b.tgID); - } - // tradegroup index - if (a.tradeGroupOrder == b.tradeGroupOrder) { - return 0; - } - return a.tradeGroupOrder > b.tradeGroupOrder ? -1 : 1; + + // cooldown + int cooldownCmp = Long.compare(b.cooldown, a.cooldown); + if (cooldownCmp != 0) return cooldownCmp; + + // display item ordering + int idCmp = Integer + .compare(Item.getIdFromItem(a.display.getItem()), Item.getIdFromItem(b.display.getItem())); + if (idCmp != 0) return idCmp; + int dmgCmp = Integer.compare(a.display.getItemDamage(), b.display.getItemDamage()); + if (dmgCmp != 0) return dmgCmp; + + // sort by tradegroup Order + return Integer.compare(a.tradeGroupOrder, b.tradeGroupOrder); + }); return trades; } + private static int getCategoryRank(TradeItemDisplay t) { + if (!t.enabled) { + return 5; + } + if (t.tradeableNow) { + return t.hasCooldown ? 2 : 1; + } + return t.hasCooldown ? 4 : 3; + } + public void attemptPurchase(int x, int y) { gui.attemptPurchase(x, y); } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 6275554..c02ed51 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -3,12 +3,12 @@ "modList": [{ "modid": "${modId}", "name": "${modName}", - "description": "An example mod for Minecraft 1.7.10 with Forge focused on a stable setup.", + "description": "Adds a vending machine.", "version": "${modVersion}", "mcversion": "${minecraftVersion}", - "url": "https://github.com/SinTh0r4s/MyMod", + "url": "https://github.com/cubefury/VendingMachine", "updateUrl": "", - "authorList": ["SinTho0r4s"], + "authorList": ["cubefury"], "credits": "", "logoFile": "", "screenshots": [], From 93754b9e5e61fc2a1aa8b7b44d1c786c3060a331 Mon Sep 17 00:00:00 2001 From: cubefury Date: Mon, 8 Sep 2025 01:49:03 +0800 Subject: [PATCH 16/40] Added trade tabs --- .../blocks/MTEVendingMachine.java | 7 +- .../blocks/gui/MTEVendingMachineGui.java | 200 ++++++++++++------ .../blocks/gui/TradeMainPanel.java | 132 +++++++----- .../vendingmachine/blocks/gui/TradeSlot.java | 13 +- .../vendingmachine/trade/TradeCategory.java | 73 +++++++ .../vendingmachine/trade/TradeDatabase.java | 33 ++- .../vendingmachine/trade/TradeGroup.java | 21 +- .../assets/vendingmachine/lang/en_US.lang | 9 + .../textures/gui/icons/unknown.png | Bin 0 -> 504 bytes .../textures/items/placeholder.png | Bin 288 -> 3125 bytes 10 files changed, 340 insertions(+), 148 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/trade/TradeCategory.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/unknown.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 82c9448..baf81f4 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -54,7 +54,7 @@ public class MTEVendingMachine extends MTEMultiBlockBase public static final int INPUT_SLOTS = 7; public static final int OUTPUT_SLOTS = 1; - public static final int MAX_TRADES = 999; + public static final int MAX_TRADES = 300; public static final int STRUCTURE_CHECK_TICKS = 20; @@ -413,11 +413,6 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { this.mMachine = checkMachine(aBaseMetaTileEntity, null); aBaseMetaTileEntity.setActive(this.mMachine); } - /* - * if (this.mMachine) { - * // dispense mechanic goes here - * } - */ } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 05e40b3..490f85c 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -1,9 +1,10 @@ package com.cubefury.vendingmachine.blocks.gui; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import com.cleanroommc.modularui.widgets.ListWidget; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -23,15 +24,20 @@ import com.cleanroommc.modularui.widget.ScrollWidget; import com.cleanroommc.modularui.widget.SingleChildWidget; import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.PageButton; +import com.cleanroommc.modularui.widgets.PagedWidget; import com.cleanroommc.modularui.widgets.SlotGroupWidget; import com.cleanroommc.modularui.widgets.ToggleButton; import com.cleanroommc.modularui.widgets.layout.Column; +import com.cleanroommc.modularui.widgets.layout.Flow; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.slot.ItemSlot; import com.cleanroommc.modularui.widgets.slot.ModularSlot; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.gui.GuiTextures; +import com.cubefury.vendingmachine.trade.TradeCategory; +import com.cubefury.vendingmachine.trade.TradeDatabase; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; import gregtech.api.modularui2.GTGuiTextures; @@ -45,16 +51,25 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { public boolean forceRefresh = false; private boolean ejectItems = false; - private final IItemHandlerModifiable tradeItemHandler = new ItemStackHandler(MTEVendingMachine.MAX_TRADES); - private final ItemSlot[] tradeSlotList = new ItemSlot[MTEVendingMachine.MAX_TRADES]; - private final List displayedTrades = new ArrayList<>(); + private final Map tradeItemHandlers = new HashMap<>(); + private final Map> displayedTrades = new HashMap<>(); + private final List tradeCategories = new ArrayList<>(); private PosGuiData guiData; + private static final int ITEMS_PER_ROW = 3; + public MTEVendingMachineGui(MTEVendingMachine base, int height) { super(base); this.base = base; this.height = height; + + this.tradeCategories.add(TradeCategory.ALL); + this.tradeCategories.addAll(TradeDatabase.INSTANCE.getTradeCategories()); + + for (TradeCategory c : this.tradeCategories) { + tradeItemHandlers.put(c, new ItemStackHandler(MTEVendingMachine.MAX_TRADES)); + } } public MTEVendingMachine getBase() { @@ -64,14 +79,19 @@ public MTEVendingMachine getBase() { @Override public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { this.guiData = guiData; + + PagedWidget.Controller tabController = new PagedWidget.Controller(); + registerSyncValues(syncManager); - ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(198, height) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager, tabController) + .size(198, height) .padding(4); + panel = panel.child(createCategoryTabs(tabController)); panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(createInputRow(syncManager)) - .child(createTradeUI((TradeMainPanel) panel)) + .child(createTradeUI((TradeMainPanel) panel, tabController)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) @@ -80,6 +100,26 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe return panel; } + public IWidget createCategoryTabs(PagedWidget.Controller tabController) { + Flow tabColumn = new Column().width(40) + .height(100) + .left(-30) + .top(50) + .coverChildren(); + + for (int i = 0; i < this.tradeCategories.size(); i++) { + tabColumn = tabColumn.child( + new PageButton(i, tabController).tab(com.cleanroommc.modularui.drawable.GuiTextures.TAB_LEFT, -1) + .overlay( + this.tradeCategories.get(i) + .getTexture() + .asIcon() + .margin(4) + .center())); + } + return tabColumn; + } + // why is the original method private lmao private IWidget createTitleTextStyle(String title) { return new SingleChildWidget<>().coverChildren() @@ -191,63 +231,68 @@ private IWidget createOutputSlot() { .build(); } - private IWidget createTradeUI(TradeMainPanel rootPanel) { - ScrollWidget sw = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) - .margin(0); - sw.getScrollArea() - .getScrollY() - .setScrollSize(18 * (MTEVendingMachine.MAX_TRADES) / 9); - for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { - int x = i % 9; - int y = i / 9; - int slotNumber = i; // idk why it wants to copy a pass-by-value thing but ok - tradeSlotList[i] = new TradeSlot(x, y, rootPanel).pos(x * 18, y * 18) - .slot(new ModularSlot(tradeItemHandler, i)) - .tooltipDynamic(builder -> { - // builder.clearText(); - synchronized (displayedTrades) { - if (slotNumber < displayedTrades.size()) { - TradeItemDisplay cur = displayedTrades.get(slotNumber); - if (cur != null && cur.display != null) { - builder.add("yes trade"); + // spotless:off + private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller tabController) { + PagedWidget paged = new PagedWidget<>().expanded().debugName("paged").controller(tabController).height(100); + + for (TradeCategory category : this.tradeCategories) { + ScrollWidget tradeList = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) + .margin(0); + tradeList.getScrollArea() + .getScrollY() + .setScrollSize(18 * (MTEVendingMachine.MAX_TRADES) / 9); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + int index = i; + int x = i % ITEMS_PER_ROW; + int y = i / ITEMS_PER_ROW; + tradeList.child(new TradeSlot(category, i, rootPanel).pos(x * 30, y * 30) + .slot(new ModularSlot(tradeItemHandlers.get(category), i)) + .tooltipDynamic(builder -> { + // builder.clearText(); + synchronized (displayedTrades) { + if (index < displayedTrades.get(category).size()) { + TradeItemDisplay cur = displayedTrades.get(category).get(index); + if (cur != null && cur.display != null) { + builder.add("yes trade"); + } } } - } - }); - DynamicDrawable tradeAvailableOverlay = new DynamicDrawable(() -> { - if ( - slotNumber < displayedTrades.size() - && (displayedTrades.get(slotNumber).hasCooldown || !displayedTrades.get(slotNumber).enabled) - ) { - return GuiTextures.OVERLAY_TRADE_DISABLED; - } - if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).tradeableNow) { - return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; - } - return null; - }); - DynamicDrawable tradeCooldownOverlay = new DynamicDrawable(() -> { - if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).hasCooldown) { - return IKey.str(displayedTrades.get(slotNumber).cooldownText); - } - return null; - }); - DynamicDrawable slotBackground = new DynamicDrawable(() -> { - if (slotNumber < displayedTrades.size() && displayedTrades.get(slotNumber).tradeableNow) { - return GuiTextures.TRADE_AVAILABLE_BACKGROUND; - } - return GTGuiTextures.SLOT_ITEM_STANDARD; - }); - - tradeSlotList[i].background(slotBackground); - tradeSlotList[i].overlay(tradeAvailableOverlay, tradeCooldownOverlay); - sw.child(tradeSlotList[i]); + }) + .tooltipAutoUpdate(true) // if it starts lagging, we'll need to index all + // the tradeslots and then call updateTooltip() every + // refresh + .background(new DynamicDrawable(() -> { + if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).tradeableNow) { + return GuiTextures.TRADE_AVAILABLE_BACKGROUND; + } + return GTGuiTextures.SLOT_ITEM_STANDARD; + })) + .overlay( + new DynamicDrawable(() -> { + if ( + index < displayedTrades.get(category).size() + && (displayedTrades.get(category).get(index).hasCooldown || !displayedTrades.get(category).get(index).enabled) + ) { + return GuiTextures.OVERLAY_TRADE_DISABLED; + } + if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).tradeableNow) { + return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; + } + return null; }), + new DynamicDrawable(() -> { + if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).hasCooldown) { + return IKey.str(displayedTrades.get(category).get(index).cooldownText); + } + return null; }))); + } + paged.addPage(tradeList); } - return new Row().child(sw.top(0)) + return new Row().child(paged.top(0)) .left(4) .top(38); } + // spotless:on // why is the original method private lmao private IWidget createInventoryRow(ModularPanel panel, PanelSyncManager syncManager) { @@ -276,18 +321,24 @@ protected void registerSyncValues(PanelSyncManager syncManager) { syncManager.syncValue("ejectItems", ejectItemsSyncer); } - public void attemptPurchase(int x, int y) { + public void attemptPurchase(TradeCategory category, int index) { TradeItemDisplay trade = null; synchronized (displayedTrades) { - if (displayedTrades.size() < y * 9 + x - 1) { + if ( + displayedTrades.get(category) + .size() <= index + ) { return; } - trade = displayedTrades.get(y * 9 + x); + trade = displayedTrades.get(category) + .get(index); if (trade == null) { return; } - submitTradesToServer(displayedTrades.get(y * 9 + x)); + submitTradesToServer( + displayedTrades.get(category) + .get(index)); } this.forceRefresh = true; } @@ -303,19 +354,28 @@ public void resetForceRefresh() { this.forceRefresh = false; } - public void updateSlots(List trades) { + public void updateSlots(Map> trades) { synchronized (displayedTrades) { displayedTrades.clear(); - displayedTrades.addAll(trades); - int displayedSize = displayedTrades.size(); - for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { - if (i < displayedSize) { - tradeItemHandler - .setStackInSlot(i, displayedTrades.get(i) != null ? displayedTrades.get(i).display : null); - } else { - tradeItemHandler.setStackInSlot(i, null); + displayedTrades.putAll(trades); + for (Map.Entry> entry : displayedTrades.entrySet()) { + int displayedSize = displayedTrades.get(entry.getKey()) + .size(); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + if (i < displayedSize) { + tradeItemHandlers.get(entry.getKey()) + .setStackInSlot( + i, + displayedTrades.get(entry.getKey()) + .get(i) != null + ? displayedTrades.get(entry.getKey()) + .get(i).display + : null); + } else { + tradeItemHandlers.get(entry.getKey()) + .setStackInSlot(i, null); + } } - tradeSlotList[i].markTooltipDirty(); } } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 23a931e..1241395 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -15,14 +15,15 @@ import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.PagedWidget; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; +import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; -import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -35,14 +36,16 @@ public class TradeMainPanel extends ModularPanel { private EntityPlayer player = null; private int ticksOpen = 0; private UUID playerID = null; + private PagedWidget.Controller tabController = null; public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData guiData, - PanelSyncManager syncManager) { + PanelSyncManager syncManager, PagedWidget.Controller tabController) { super(name); this.gui = gui; this.guiData = guiData; this.syncManager = syncManager; this.playerID = NameCache.INSTANCE.getUUIDFromPlayer(guiData.getPlayer()); + this.tabController = tabController; } @Override @@ -69,15 +72,18 @@ public void updateGui() { .entrySet()) { testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); } - // List trades = formatTrades(testTGW); + Map> trades = formatTrades(testTGW); // TODO: SWAP BACK - List trades = formatTrades( - TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + /* + * List trades = formatTrades( + * TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + */ gui.updateSlots(trades); } @Override public void onUpdate() { + super.onUpdate(); if (!this.guiData.isClient()) { return; @@ -137,75 +143,87 @@ public Map getAvailableItems() { return items; } - public List formatTrades(List tradeGroups) { + public Map> formatTrades(List tradeGroups) { Map availableItems = this.guiData.isClient() && this.gui.getBase() != null ? getAvailableItems() : new HashMap<>(); - List trades = new ArrayList<>(); + Map> trades = new HashMap<>(); + trades.put(TradeCategory.ALL, new ArrayList<>()); + for (TradeGroupWrapper tgw : tradeGroups) { List tradeList = tgw.trade() .getTrades(); + TradeCategory category = tgw.trade() + .getCategory(); + trades.putIfAbsent(category, new ArrayList<>()); for (int i = 0; i < tradeList.size(); i++) { Trade trade = tgw.trade() .getTrades() .get(i); BigItemStack displayItem = trade.toItems.get(0); - - trades.add( - new TradeItemDisplay( - trade.fromItems, - trade.toItems, - convertToItemStack(displayItem == null ? trade.displayItem : displayItem), - tgw.trade() - .getId(), - i, - tgw.trade() - .getLabel(), - tgw.cooldown(), - convertCooldownText(tgw.cooldown()), - tgw.cooldown() > 0, - tgw.enabled(), - checkItemsSatisfied(trade.fromItems, availableItems), - playerID)); + TradeItemDisplay tid = new TradeItemDisplay( + trade.fromItems, + trade.toItems, + convertToItemStack(displayItem == null ? trade.displayItem : displayItem), + tgw.trade() + .getId(), + i, + tgw.trade() + .getLabel(), + tgw.cooldown(), + convertCooldownText(tgw.cooldown()), + tgw.cooldown() > 0, + tgw.enabled(), + checkItemsSatisfied(trade.fromItems, availableItems), + playerID); + + trades.get(category) + .add(tid); + trades.get(TradeCategory.ALL) + .add(tid); } } - trades.sort((a, b) -> { - // null case - if (a == null && b == null) return 0; - if (a == null) return 1; - if (b == null) return -1; - if (a.display.getItem() == null && b.display.getItem() == null) return 0; - if (a.display.getItem() == null) return 1; - if (b.display.getItem() == null) return -1; - - int rankA = getCategoryRank(a); - int rankB = getCategoryRank(b); - - if (rankA != rankB) { - return Integer.compare(rankA, rankB); - } - // cooldown - int cooldownCmp = Long.compare(b.cooldown, a.cooldown); - if (cooldownCmp != 0) return cooldownCmp; - - // display item ordering - int idCmp = Integer - .compare(Item.getIdFromItem(a.display.getItem()), Item.getIdFromItem(b.display.getItem())); - if (idCmp != 0) return idCmp; - int dmgCmp = Integer.compare(a.display.getItemDamage(), b.display.getItemDamage()); - if (dmgCmp != 0) return dmgCmp; - - // sort by tradegroup Order - return Integer.compare(a.tradeGroupOrder, b.tradeGroupOrder); - - }); + for (List filteredTrades : trades.values()) { + filteredTrades.sort((a, b) -> { + // null case + if (a == null && b == null) return 0; + if (a == null) return 1; + if (b == null) return -1; + if (a.display.getItem() == null && b.display.getItem() == null) return 0; + if (a.display.getItem() == null) return 1; + if (b.display.getItem() == null) return -1; + + // enabled or has cooldown + int rankA = getRank(a); + int rankB = getRank(b); + + if (rankA != rankB) { + return Integer.compare(rankA, rankB); + } + + // cooldown time + int cooldownCmp = Long.compare(b.cooldown, a.cooldown); + if (cooldownCmp != 0) return cooldownCmp; + + // display item ordering + int idCmp = Integer + .compare(Item.getIdFromItem(a.display.getItem()), Item.getIdFromItem(b.display.getItem())); + if (idCmp != 0) return idCmp; + int dmgCmp = Integer.compare(a.display.getItemDamage(), b.display.getItemDamage()); + if (dmgCmp != 0) return dmgCmp; + + // sort by tradegroup Order + return Integer.compare(a.tradeGroupOrder, b.tradeGroupOrder); + + }); + } return trades; } - private static int getCategoryRank(TradeItemDisplay t) { + private static int getRank(TradeItemDisplay t) { if (!t.enabled) { return 5; } @@ -215,7 +233,7 @@ private static int getCategoryRank(TradeItemDisplay t) { return t.hasCooldown ? 4 : 3; } - public void attemptPurchase(int x, int y) { - gui.attemptPurchase(x, y); + public void attemptPurchase(TradeCategory category, int index) { + gui.attemptPurchase(category, index); } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java index bcbbd9f..e4be8eb 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java @@ -5,23 +5,24 @@ import org.jetbrains.annotations.NotNull; import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; +import com.cubefury.vendingmachine.trade.TradeCategory; public class TradeSlot extends PhantomItemSlot { - private final int x; - private final int y; + private TradeCategory category; + private int index; TradeMainPanel rootPanel; - public TradeSlot(int x, int y, TradeMainPanel rootPanel) { - this.x = x; - this.y = y; + public TradeSlot(TradeCategory category, int index, TradeMainPanel rootPanel) { + this.category = category; + this.index = index; this.rootPanel = rootPanel; } @Override public @NotNull Result onMousePressed(int mouseButton) { if (rootPanel.shiftHeld) { - rootPanel.attemptPurchase(x, y); + rootPanel.attemptPurchase(category, index); } return Result.SUCCESS; } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeCategory.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeCategory.java new file mode 100644 index 0000000..da740a3 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeCategory.java @@ -0,0 +1,73 @@ +package com.cubefury.vendingmachine.trade; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.cleanroommc.modularui.drawable.UITexture; +import com.cubefury.vendingmachine.VendingMachine; + +public enum TradeCategory { + + UNKNOWN("unknown", "vendingmachine.category.unknown", "gui/icons/unknown.png"), + ALL("all", "vendingmachine.category.all", "gui/icons/all.png"), + COMPONENTS("components", "vendingmachine.category.components", "gui/icons/components.png"), + RAW("raw", "vendingmachine.category.raw", "gui/icons/raw.png"), + FARMING("farming", "vendingmachine.category.farming", "gui/icons/farming.png"), + CHEMISTRY("chemistry", "vendingmachine.category.chemistry", "gui/icons/chemistry.png"), + MAGIC("magic", "vendingmachine.category.magic", "gui/icons/magic.png"), + BEES("bees", "vendingmachine.category.bees", "gui/icons/bees.png"), + MISC("misc", "vendingmachine.category.misc", "gui/icons/misc.png"); + + private final String key; + private final String unlocalized_name; + private final UITexture texture; + + private static final Map ENUM_MAP; + + private static final int size_x = 32; + private static final int size_y = 32; + + TradeCategory(String key, String unlocalized_name, String texture) { + this.key = key; + this.unlocalized_name = unlocalized_name; + this.texture = UITexture.builder() + .location(VendingMachine.MODID, texture) + .imageSize(size_x, size_y) + .name(unlocalized_name) + .build(); + } + + static { + Map map = new HashMap<>(); + for (TradeCategory instance : TradeCategory.values()) { + map.put(instance.getKey(), instance); + } + ENUM_MAP = Collections.unmodifiableMap(map); + } + + public String getKey() { + return this.key; + } + + public String getUnlocalized_name() { + return this.unlocalized_name; + } + + public UITexture getTexture() { + return this.texture; + } + + public static TradeCategory ofString(String key) { + if (ENUM_MAP.get(key) == null) { + VendingMachine.LOG.warn("Unknown trade category {}, defaulting to UNKNOWN", key); + return UNKNOWN; + } + return ENUM_MAP.get(key); + } + + @Override + public String toString() { + return getUnlocalized_name(); + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index 7251fa6..e9d4c30 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -1,13 +1,19 @@ package com.cubefury.vendingmachine.trade; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; +import org.antlr.v4.misc.OrderedHashMap; + import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.integration.betterquesting.BqAdapter; import com.cubefury.vendingmachine.integration.nei.NeiRecipeCache; @@ -21,12 +27,14 @@ public class TradeDatabase { public static final TradeDatabase INSTANCE = new TradeDatabase(); public int version = -1; - private final Map tradeGroups = new HashMap<>(); + private final Map tradeGroups = new OrderedHashMap<>(); + private final Map> tradeCategories = new HashMap<>(); private TradeDatabase() {} public void clear() { tradeGroups.clear(); + tradeCategories.clear(); } public void clearTradeState(UUID player) { @@ -45,6 +53,14 @@ public Map getTradeGroups() { return tradeGroups; } + public List getTradeCategories() { + return new ArrayList<>(tradeCategories.keySet()); + } + + public Set getTradeGroupsFromCategory(TradeCategory category) { + return tradeCategories.get(category); + } + public int getTradeCount() { return tradeGroups.values() .stream() @@ -61,27 +77,32 @@ public void readFromNBT(NBTTagCompound nbt, boolean merge) { BqAdapter.INSTANCE.resetQuestTriggers(null); } } - int newIdCount = 0; + int newMetadataCount = 0; this.version = nbt.getInteger("version"); NBTTagList trades = nbt.getTagList("tradeGroups", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < trades.tagCount(); i++) { TradeGroup tg = new TradeGroup(); - newIdCount += tg.readFromNBT(trades.getCompoundTagAt(i)) ? 1 : 0; + newMetadataCount += tg.readFromNBT(trades.getCompoundTagAt(i)) ? 1 : 0; if (tradeGroups.containsKey(tg.getId())) { VendingMachine.LOG.warn("Multiple trade groups with id {} exist in the file!", tg); continue; } + tradeCategories.computeIfAbsent(tg.getCategory(), k -> new HashSet<>()); + tradeCategories.get(tg.getCategory()) + .add(tg.getId()); + tradeGroups.put(tg.getId(), tg); } - if (newIdCount > 0) { - VendingMachine.LOG.info("Updating {} new trades with UUIDs", newIdCount); + if (newMetadataCount > 0) { + VendingMachine.LOG.info("Appended metadata to {} new trades", newMetadataCount); DirtyDbMarker.markDirty(); } if (VendingMachine.proxy.isClient() && VendingMachine.isNeiLoaded) { refreshNeiCache(); } TradeManager.INSTANCE.recomputeAvailableTrades(null); - VendingMachine.LOG.info("Loaded {} trade groups containing {} trades.", getTradeGroupCount(), getTradeCount()); + VendingMachine.LOG + .info("Loaded {} trade groups containing {} trade groups.", getTradeGroupCount(), getTradeCount()); } public NBTTagCompound writeToNBT(NBTTagCompound nbt) { diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java index b2f980d..5702483 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeGroup.java @@ -29,6 +29,8 @@ public class TradeGroup { public int cooldown = -1; public int maxTrades = -1; public String label = ""; + private TradeCategory category = TradeCategory.UNKNOWN; + private String original_category_str = ""; private final Set requirementSet = new HashSet<>(); // List of completed conditions for each player @@ -83,6 +85,10 @@ public List getTrades() { return trades; } + public TradeCategory getCategory() { + return category; + } + public List getRequirements() { return new ArrayList<>(requirementSet); } @@ -154,12 +160,20 @@ public boolean readFromNBT(NBTTagCompound nbt) { this.trades.clear(); this.requirementSet.clear(); - boolean generatedRandomUUID = false; + boolean generatedMetadata = false; if (nbt.hasKey("id")) { this.id = NBTConverter.UuidValueType.TRADEGROUP.readId(nbt.getCompoundTag("id")); } else { this.id = UUID.randomUUID(); - generatedRandomUUID = true; + generatedMetadata = true; + } + if (nbt.hasKey("category")) { + this.original_category_str = nbt.getString("category"); + this.category = TradeCategory.ofString(original_category_str); + } else { + this.original_category_str = TradeCategory.UNKNOWN.getUnlocalized_name(); + this.category = TradeCategory.UNKNOWN; + generatedMetadata = true; } this.cooldown = nbt.getInteger("cooldown"); this.maxTrades = nbt.getInteger("maxTrades"); @@ -180,7 +194,7 @@ public boolean readFromNBT(NBTTagCompound nbt) { BqAdapter.INSTANCE.addQuestTrigger(bqc.getQuestId(), this); } } - return generatedRandomUUID; + return generatedMetadata; } public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @@ -188,6 +202,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setInteger("cooldown", this.cooldown); nbt.setInteger("maxTrades", this.maxTrades); nbt.setString("label", this.label); + nbt.setString("category", this.category.getKey()); NBTTagList tList = new NBTTagList(); for (Trade t : trades) { tList.appendTag(t.writeToNBT(new NBTTagCompound())); diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index 9e71265..cdbb4c2 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -17,3 +17,12 @@ vendingmachine.gui.cooldown_display.hour=h vendingmachine.gui.cooldown_display.day=d gt.blockmachines.multimachine.vendingmachine.name=Vending Machine + +vendingmachine.category.unknown=Unknown Category +vendingmachine.category.components=Components +vendingmachine.category.raw=Raw Materials +vendingmachine.category.farming=Farming +vendingmachine.category.chemistry=Chemistry +vendingmachine.category.magic=Magic +vendingmachine.category.bees=Bees +vendingmachine.category.misc=Miscellaneous diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/unknown.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..25bddf9eaf1603b84736412d186247df9b51dabc GIT binary patch literal 504 zcmVz>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0004l zNkl{&FIsLD%L##9Gsd&W6$%7Dq__G-iDSU2-KB(p<#k)QfLUE1D8a! z&T0UThvDIT4ru(WJvva&>{#GE&+CYek^G9HifOk1D5~&%(LV_+mD2ksi|)}vT2V#+ zKLr5ckl)cD9q_I21aKJa0lMt07Z{Wc*ahAPXph!SJSAEHuCo@~8B;F6UPK8XVV81> zDo$hrT-t=64|S~N?1OcCrWTt4c8*MvTZUY~!rBYTEh7P3*`>6iihbFDzDkF>0XWX< zv>B%52bf!ZVLM|=1OVZXe-UW^P@4Mcw!02+D}HBB!2{FK}|sb0I`n?{9y$E017v0Lqkw=Qb$4{Nkv08F*!CiEix`K z002mdotAf0Q`r`W&%HOjP?8Xel+bHvQUXW~y-1NRDlrKVO2Ci+A~r-+a70m&rU)`9 z;DDn;k+C9*g#l5q>jW7@)NybW8eS9UZc9vd* zf9@GXANa%eSALld0I;TIwb}ZIZD|z%UF!i*yZwjFU@riQvc7c=eQ_STd|pz-;w)z? ztK8gNO97v2DKF^n`kxMeLtlK)Qoh~qM8wF>;&Ay4=AVc7 z9|!(*9)A`Q{3O1JFO)?@%ce{qOqR7<$Ps@_@A2i55xYX*}0a9+V~OBmRJI% zAsRq_9snpR5g-YBWGm3`eGA4%1NqI1(V3W?`_F>@eOI_l{>T<2e~x2EL^8M%QO@j| z{8|DuAOJ-`1L{B<=mQhL1h&8txBw5}0|G%Ph<^leU@_o=6p#T#AQu#XwV)W3f~{aD zs0MYQ5j2A~a2RxfW8gG62QGojU!?g~$*UQipUPL&zMmg;!4Do9IA%up=Rh?=qPj=x&RGBx1dpI68aT-2O}^EromdU z5r1q2vtUm+2#$mo!O8G4I3F&8x4@Nf1AGwfgiphl;1O5~KY^zafDjQnqKhyQ7Q#kC zk$5Bt5h1IP5~KoYK-!QVq#wD8NRg+=TNDOGMKMrJlncrq6@}uWmZ4UmHlwOh2T+}; zKGapzC~6Az5lu#GqRr9H=m2yqIvJgdE`LT>pqtPg=(Fe%^f>wz27{qvj4_TFe@q-E z6|(}f8M7PHjyZ)H#*AU6u~@7+)*S1K4aIV>Vr((C3VRTH5_<(Zj(vk8;&gDfIA2^m zPKYbSRp451CvaDA6Sx_?65bH+j1R^0@XPUK_(psWeh5E~pCKp{j0vuUNJ1)MEq|es z&_*~*xJ!6JBog(APQ-AcfVhTONjyY6PaGw_B~eIbBsM95Bq41f?I)cg-6FjplgUP8 z4{|(NOx{9nCZ8eSC%;jkDp)E6DDV_kE7T}-DqK-`rifQGRP zUdc#_t;A7UrBtJIROyD&v@%uMMt?a}IYW7~a*Of>RIYI4MQ`g1<+DyrL=EogS06Xii({|v`U^zjmmKqDIK93(F5q|^fLNk z`gQs{RV`IdRle#b)i%{Ds;|}NsClUI)k@Ub)kf6bsWa4l)YH_rsduU0(|LZ@rEqJ6vJJH{f4iNjE!Q9HW+moJu+4^4lvF) zZZ*DZLN;+XS!U8;a?KQD$}&we-EDf=3^ubjOEIf48#0H@9n1yhyUm9!&=yV>LW>5A z8%z?@lbOS8WsX|XErTr!ExRnASs7TxTWz!IxB6&pZ=G)4Xnn_qVt*58Q)ts;^Q*0y zE!Vcj_S#(XT;I8?=XTG1Zf9=Cx7%ZP)1GP{V!y$@*ZzZpql3ty&0*5fz%kLW*6{|5 z#tLI?W}SCJJ9#;+b~@(t*4e>X?0ney7Z;{WnoEnzqj|>j`12a)jk)T%a$M_OrEUzj zM7OZX~g?%5634ad@uL*w`VG~gh(Z7JY zV9A1(1+OB#BFiH0M43cMqI#nhqZ6W=qhH5($CSrNW36IW#$Jlkh!ezh$7AE8xdr`1lgVC7dNk648kGzWRKONg3!bO?r`DyuP76)j zpY|y|CcQlamywupR7eq~3Hvg&GxIWsv&^%Kv!u(Mm+f3OB?=NXWkcDEvb)7J+0WE~ z#6+@QGMeL-Q%XSL?4XT0OqTZ_RsyNzibcgYHn?o4 z+lbmI*f_Xp?xw0uA4_;87fY>6D@xyQ=5D_DmCaX`Uwzt=v}Lf&p={4q%vRyn>)YJ7 z9Vk~W&wno;+a9vLa|dHb$&Qyhm+ZVyVOLSNi?B z>BD~Ee(8aT1AWbo&CM;EEoH56tE6@EV8X%6-+y?2)7{2wt8b^bmmUI#B!?bmEKDc(k|2rKjV2%kTFe(>+#mT;+J# z3Brk@6Q54zpPW9Gb?WKqB=X}qd>G$kEdEWK>u?x-@ zj(=WcUF^E#aH(^^exTzA`yV<69R@px9EZ9uJ6-M>o;Q5riu;w*SG}*EyB2Wm(#ZUg z;pqt>?FMZqM9Va~FNLH%A*>}Hq z{4y{VJ2n1X^!(GWn_sBE*#FY*W$$#@^!-;EuV!ACyitF1;4SNI|GSuX6EnH*vF|HC zn11N_81(V(r;JaZegpS}^ZUoqJ9q#903c&XQcVB=dL{q>fP?@5`Tzg`fam}Kb$>7b z0P0`>06Lfe02gqax=}m;000SaNLh0L01m?d01m?e$8V@)0000RbVXQnQ*UN;cVTj6 z07GSLb9r+hQ*?D?X>TA@Z*OeDr{R1600BWsL_t(Ijir*YQo=wGhQAAD(m2B-NGByU z8496AsC@&`&c+VbxBKnR|F04e z{u4?>U|!agF@D(nwPRi$0qYt+R9iqQ;3xoI@WWF}^Aph7)@s1(-J!JVCE{;z4*+<^ z4?9K8y5?<>(7gOw1F97_eHeJ^q*fw|!E^T@n`ZqteNX5Gk$il{j?yAlD}Qb}9C)f( z%WU!p2ymuz(?!C05Xo{CJ3A3KVL}W|wr_KC)&(P~6*s-T_Efu3%H$`rgsYp~WGf)2 zw6Q^vLs`I{(vw+&2(%k^hjxGhr7wag1sD!I$L5eeq!G}yDQ$6Rj30J$msq5<)gkkg zVSQb_Ag{Cux$k?bRo^(I0V&5vt^g=SZgLSs1O>2M#VT*(AL9qHbMWCRQYGZx^prw85kH?(j9#r85lP9bN@+X1@buyJR*x382FBWFymBh zK53vJTavfC3&VdPi@{jE<};9DFY)wsWxvlQ&BCcZ@oLs=pwI+Q7sn6_|Fx4Z@-`^& zxNtMSFnjlZ^=%8rpoJ5sEzWrKd*i}#_qB#gYHK}Ja?*9xWU_TTl4`|f9TQl5k+Dad zsYr^&ouCh8{% Date: Mon, 8 Sep 2025 03:02:32 +0800 Subject: [PATCH 17/40] Made trade tab lengths dynamically change based on how many items are present in the tab. --- .../blocks/gui/MTEVendingMachineGui.java | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 490f85c..ad2de73 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -13,6 +13,7 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.Rectangle; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.UISettings; @@ -21,9 +22,8 @@ import com.cleanroommc.modularui.utils.item.ItemStackHandler; import com.cleanroommc.modularui.value.sync.BooleanSyncValue; import com.cleanroommc.modularui.value.sync.PanelSyncManager; -import com.cleanroommc.modularui.widget.ScrollWidget; import com.cleanroommc.modularui.widget.SingleChildWidget; -import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.ListWidget; import com.cleanroommc.modularui.widgets.PageButton; import com.cleanroommc.modularui.widgets.PagedWidget; import com.cleanroommc.modularui.widgets.SlotGroupWidget; @@ -56,8 +56,11 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final List tradeCategories = new ArrayList<>(); private PosGuiData guiData; + private PagedWidget.Controller tabController; - private static final int ITEMS_PER_ROW = 3; + public static final int ITEMS_PER_ROW = 3; + private static final int ITEM_HEIGHT = 18; + private static final int ROW_SEPARATOR_HEIGHT = 5; public MTEVendingMachineGui(MTEVendingMachine base, int height) { super(base); @@ -70,6 +73,8 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { for (TradeCategory c : this.tradeCategories) { tradeItemHandlers.put(c, new ItemStackHandler(MTEVendingMachine.MAX_TRADES)); } + + this.tabController = new PagedWidget.Controller(); } public MTEVendingMachine getBase() { @@ -80,18 +85,16 @@ public MTEVendingMachine getBase() { public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { this.guiData = guiData; - PagedWidget.Controller tabController = new PagedWidget.Controller(); - registerSyncValues(syncManager); - ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager, tabController) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager, this.tabController) .size(198, height) .padding(4); - panel = panel.child(createCategoryTabs(tabController)); + panel = panel.child(createCategoryTabs(this.tabController)); panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(createInputRow(syncManager)) - .child(createTradeUI((TradeMainPanel) panel, tabController)) + .child(createTradeUI((TradeMainPanel) panel, this.tabController)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) @@ -233,19 +236,20 @@ private IWidget createOutputSlot() { // spotless:off private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller tabController) { - PagedWidget paged = new PagedWidget<>().expanded().debugName("paged").controller(tabController).height(100); - + PagedWidget paged = new PagedWidget<>().expanded().debugName("paged").controller(tabController).heightRel(0.5f); for (TradeCategory category : this.tradeCategories) { - ScrollWidget tradeList = new ScrollWidget<>(new VerticalScrollData()).size(9 * 18) - .margin(0); - tradeList.getScrollArea() - .getScrollY() - .setScrollSize(18 * (MTEVendingMachine.MAX_TRADES) / 9); + ListWidget tradeList = new ListWidget<>().debugName("items").heightRel(1.0f) + .widthRel(1.0f).childSeparator(new Rectangle().setColor(0x0).asIcon().size(ROW_SEPARATOR_HEIGHT)) + .collapseDisabledChild(true); + + Flow row = new Row().height(ITEM_HEIGHT).collapseDisabledChild(true).setEnabledIf(r -> + r.getChildren().stream().anyMatch(IWidget::isEnabled)); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int index = i; int x = i % ITEMS_PER_ROW; int y = i / ITEMS_PER_ROW; - tradeList.child(new TradeSlot(category, i, rootPanel).pos(x * 30, y * 30) + row.child(new TradeSlot(category, i, rootPanel) .slot(new ModularSlot(tradeItemHandlers.get(category), i)) .tooltipDynamic(builder -> { // builder.clearText(); @@ -283,7 +287,17 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).hasCooldown) { return IKey.str(displayedTrades.get(category).get(index).cooldownText); } - return null; }))); + return null; })) + .setEnabledIf(slot -> tradeItemHandlers.get(category).getStackInSlot(index) != null)); + if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { + tradeList.child(row); + + row = new Row().height(ITEM_HEIGHT).collapseDisabledChild(true).setEnabledIf(r -> + r.getChildren().stream().anyMatch(IWidget::isEnabled)); + } + } + if (row.hasChildren()) { + tradeList.child(row); } paged.addPage(tradeList); } From 0d3470d0ff2926e61eb93a2a221c255a40cbaa47 Mon Sep 17 00:00:00 2001 From: cubefury Date: Mon, 8 Sep 2025 03:06:11 +0800 Subject: [PATCH 18/40] Separated trade row code to look cleaner --- .../blocks/gui/MTEVendingMachineGui.java | 6 ++---- .../vendingmachine/blocks/gui/TradeRow.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeRow.java diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index ad2de73..3ee3324 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -242,8 +242,7 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t .widthRel(1.0f).childSeparator(new Rectangle().setColor(0x0).asIcon().size(ROW_SEPARATOR_HEIGHT)) .collapseDisabledChild(true); - Flow row = new Row().height(ITEM_HEIGHT).collapseDisabledChild(true).setEnabledIf(r -> - r.getChildren().stream().anyMatch(IWidget::isEnabled)); + Flow row = new TradeRow().height(ITEM_HEIGHT); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int index = i; @@ -292,8 +291,7 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { tradeList.child(row); - row = new Row().height(ITEM_HEIGHT).collapseDisabledChild(true).setEnabledIf(r -> - r.getChildren().stream().anyMatch(IWidget::isEnabled)); + row = new TradeRow().height(ITEM_HEIGHT); } } if (row.hasChildren()) { diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeRow.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeRow.java new file mode 100644 index 0000000..a4ec70b --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeRow.java @@ -0,0 +1,16 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.widgets.layout.Row; + +public class TradeRow extends Row { + + public TradeRow() { + super(); + this.collapseDisabledChild(true) + .setEnabledIf( + r -> r.getChildren() + .stream() + .anyMatch(IWidget::isEnabled)); + } +} From 654de916dcd8d84a6a706ffb3b5dd674db477984 Mon Sep 17 00:00:00 2001 From: cubefury Date: Mon, 8 Sep 2025 03:43:14 +0800 Subject: [PATCH 19/40] Added tooltips to tabs. --- .../vendingmachine/blocks/gui/MTEVendingMachineGui.java | 9 ++++++++- .../com/cubefury/vendingmachine/trade/TradeDatabase.java | 5 ++++- src/main/resources/assets/vendingmachine/lang/en_US.lang | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 3ee3324..44f2011 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Map; +import com.cleanroommc.modularui.screen.RichTooltip; +import com.cubefury.vendingmachine.util.Translator; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -111,6 +113,7 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { .coverChildren(); for (int i = 0; i < this.tradeCategories.size(); i++) { + int index = i; tabColumn = tabColumn.child( new PageButton(i, tabController).tab(com.cleanroommc.modularui.drawable.GuiTextures.TAB_LEFT, -1) .overlay( @@ -118,7 +121,11 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { .getTexture() .asIcon() .margin(4) - .center())); + .center()) + .tooltipBuilder(builder -> { + builder.clearText(); + builder.addLine(Translator.translate(this.tradeCategories.get(index).getUnlocalized_name())); + })); } return tabColumn; } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index e9d4c30..f3e1806 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -1,6 +1,7 @@ package com.cubefury.vendingmachine.trade; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -54,7 +55,9 @@ public Map getTradeGroups() { } public List getTradeCategories() { - return new ArrayList<>(tradeCategories.keySet()); + List tradeCategoryList = new ArrayList<>(tradeCategories.keySet()); + tradeCategoryList.sort(Comparator.comparing(TradeCategory::getKey)); + return tradeCategoryList; } public Set getTradeGroupsFromCategory(TradeCategory category) { diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index cdbb4c2..96531d1 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -19,6 +19,7 @@ vendingmachine.gui.cooldown_display.day=d gt.blockmachines.multimachine.vendingmachine.name=Vending Machine vendingmachine.category.unknown=Unknown Category +vendingmachine.category.all=All Items vendingmachine.category.components=Components vendingmachine.category.raw=Raw Materials vendingmachine.category.farming=Farming From 79c25374146d9e8ce49d790894fba66594d01076 Mon Sep 17 00:00:00 2001 From: cubefury Date: Mon, 8 Sep 2025 23:49:40 +0800 Subject: [PATCH 20/40] Added sidebar for IO --- .../vendingmachine/VendingMachine.java | 4 + .../blocks/MTEVendingMachine.java | 4 +- .../blocks/gui/MTEVendingMachineGui.java | 83 +++++++++++------- .../vendingmachine/gui/GuiTextures.java | 8 ++ .../vendingmachine/gui/WidgetThemes.java | 23 +++++ .../textures/gui/background/panel_side.png | Bin 0 -> 3259 bytes .../vendingmachine/textures/gui/icons/raw.png | Bin 0 -> 1121 bytes 7 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/gui/WidgetThemes.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/panel_side.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/raw.png diff --git a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java index 2cfe80f..fde7e33 100644 --- a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java @@ -6,6 +6,7 @@ import org.apache.logging.log4j.Logger; import com.cubefury.vendingmachine.blocks.BlockVendingMachine; +import com.cubefury.vendingmachine.gui.WidgetThemes; import com.cubefury.vendingmachine.items.VMItems; import com.cubefury.vendingmachine.network.PacketTypeRegistry; import com.cubefury.vendingmachine.network.SerializedPacket; @@ -71,6 +72,9 @@ public void preInit(FMLPreInitializationEvent event) { network.registerMessage(SerializedPacket.HandleClient.class, SerializedPacket.class, 0, Side.CLIENT); network.registerMessage(SerializedPacket.HandleServer.class, SerializedPacket.class, 0, Side.SERVER); + // ModularUI + WidgetThemes.register(); + } @Mod.EventHandler diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index baf81f4..55f4798 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -51,8 +51,8 @@ public class MTEVendingMachine extends MTEMultiBlockBase public static final int CUSTOM_UI_HEIGHT = 300; - public static final int INPUT_SLOTS = 7; - public static final int OUTPUT_SLOTS = 1; + public static final int INPUT_SLOTS = 6; + public static final int OUTPUT_SLOTS = 4; public static final int MAX_TRADES = 300; diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 44f2011..4bd3571 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -5,8 +5,6 @@ import java.util.List; import java.util.Map; -import com.cleanroommc.modularui.screen.RichTooltip; -import com.cubefury.vendingmachine.util.Translator; import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -24,6 +22,7 @@ import com.cleanroommc.modularui.utils.item.ItemStackHandler; import com.cleanroommc.modularui.value.sync.BooleanSyncValue; import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widget.SingleChildWidget; import com.cleanroommc.modularui.widgets.ListWidget; import com.cleanroommc.modularui.widgets.PageButton; @@ -38,8 +37,10 @@ import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.gui.GuiTextures; +import com.cubefury.vendingmachine.gui.WidgetThemes; import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.util.Translator; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; import gregtech.api.modularui2.GTGuiTextures; @@ -95,13 +96,12 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) - .child(createInputRow(syncManager)) .child(createTradeUI((TradeMainPanel) panel, this.tabController)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( new Column().size(20) - .right(5) - .child(createOutputSlot())); + .right(5)); + panel = panel.child(createIOColumn(syncManager)); return panel; } @@ -124,7 +124,10 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { .center()) .tooltipBuilder(builder -> { builder.clearText(); - builder.addLine(Translator.translate(this.tradeCategories.get(index).getUnlocalized_name())); + builder.addLine( + Translator.translate( + this.tradeCategories.get(index) + .getUnlocalized_name())); })); } return tabColumn; @@ -199,36 +202,52 @@ private void ejectItems() { ejectItems = false; } - private IWidget createInputRow(PanelSyncManager syncManager) { - Row row = new Row(); - row.child( - SlotGroupWidget.builder() - .matrix("IIIIIII") - .key('I', index -> { - return new ItemSlot().slot( - new ModularSlot(base.inputItems, index).slotGroup("inputSlotGroup") - .changeListener((newItem, onlyAmountChanged, client, init) -> { - if (guiData.isClient()) { - forceRefresh = true; - } - })); - }) - .build()); - row.child( - new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) - .tooltipBuilder(t -> t.addLine(IKey.lang("vendingmachine.gui.item_eject"))) - .left(144) - .syncHandler("ejectItems")); - return row.height(18) - .width(162) - .top(0) - .left(4); + private IWidget createIOColumn(PanelSyncManager syncManager) { + return new ParentWidget<>().excludeAreaInNEI() + .width(50) + .height(160) + .right(-48) + .top(40) + .widgetTheme(WidgetThemes.BACKGROUND_SIDEPANEL) + .child( + new Column().child( + new Row().child(createInputRow(syncManager).center()) + .top(20) + .height(18 * 3)) + .child( + new Row().child( + new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) + .tooltipBuilder(t -> t.addLine(IKey.lang("vendingmachine.gui.item_eject"))) + .syncHandler("ejectItems") + .center()) + .top(80) + .height(18)) + .child( + new Row().child(createOutputSlots().center()) + .bottom(6) + .height(18 * 2)) + .right(1)); + } + + private SlotGroupWidget createInputRow(PanelSyncManager syncManager) { + return SlotGroupWidget.builder() + .matrix("II", "II", "II") + .key('I', index -> { + return new ItemSlot().slot( + new ModularSlot(base.inputItems, index).slotGroup("inputSlotGroup") + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (guiData.isClient()) { + forceRefresh = true; + } + })); + }) + .build(); } - private IWidget createOutputSlot() { + private SlotGroupWidget createOutputSlots() { // we use slot group widget in case we want to increase the number of output slots in the future return SlotGroupWidget.builder() - .matrix("I") + .matrix("II", "II") .key('I', index -> { ModularSlot ms = new ModularSlot(base.outputItems, index).accessibility(false, true) .slotGroup("outputSlotGroup"); diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index e8ff5a8..5ebd2fa 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -25,4 +25,12 @@ public final class GuiTextures { .canApplyTheme() .name("trade_available_background") .build(); + + public static final UITexture SIDE_PANEL_BACKGROUND = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/panel_side") + .imageSize(195, 136) + .adaptable(4) + .canApplyTheme() + .name("panel_side_background") + .build(); } diff --git a/src/main/java/com/cubefury/vendingmachine/gui/WidgetThemes.java b/src/main/java/com/cubefury/vendingmachine/gui/WidgetThemes.java new file mode 100644 index 0000000..caf00cf --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/gui/WidgetThemes.java @@ -0,0 +1,23 @@ +package com.cubefury.vendingmachine.gui; + +import com.cleanroommc.modularui.api.IThemeApi; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.utils.Color; + +public final class WidgetThemes { + + public static final String BACKGROUND_SIDEPANEL = "background_side_panel"; + + public static void register() { + IThemeApi themeApi = IThemeApi.get(); + registerThemedTexture(themeApi, BACKGROUND_SIDEPANEL, GuiTextures.SIDE_PANEL_BACKGROUND); + } + + private static void registerThemedTexture(IThemeApi themeApi, String textureThemeId, UITexture background) { + themeApi.registerWidgetTheme( + textureThemeId, + new WidgetTheme(background, null, Color.WHITE.main, 0xFF404040, false), + WidgetTheme::new); + } +} diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/panel_side.png b/src/main/resources/assets/vendingmachine/textures/gui/background/panel_side.png new file mode 100644 index 0000000000000000000000000000000000000000..030802cf429f84af51d26e848dfd1b221369a290 GIT binary patch literal 3259 zcmeHJ=_Aw)7yTiGtYc{+Tb8M8Gs&(ngF*IX?2RVmvCPzr$2#_Xdn_fg@5LhtjinLU zV~o8-){2M`Vj9Zp{rvt5?}u~Gz2|;A=fl0pRu;zGoEJC&0N^%3B5Y2%=M+h2*-oqT z(rwmLI^(Txt`7i>|8O09oX(u;K5)1d-p1HK(!>z12GvwkQ-mo&0RWj?lpADcJ1d+> zC99LIviVXTj``lRVMcP3ky%Ptpd5UrU73Ki8o~~Tu+FMJ3xh00Rlu_vrBmXWtQ$Aa zfDu#oae|_`CU@(>i?2gyl!8Tx!wBCJGWC-;jX2W|WFE(|zP;th5p}N2QE+*!FDX6M z8_mviZU9n`zy^Ny)=DCut~Pm6x`* zOP_TGiwtS#q6%e6mP2{3RLw_KOh=`iVqgwA_+15;@Pm9$Ud=sNoDO&xKf2<%^Lbu= zHCZ-aHpVPXj;33~n5&yC=43pD_eJ+Jf?Z+q8I5t9vp#VD?Z087ZB z+dC7=jw4jiFmK=Jh_jM_OidD4&eb*{JqMJ!Or@HyrS^@e@TjL>T7iDZ2Rn%^KLEU_ z$4-JF{@|C=+8;DDHB|f+{W~F3k#5HY*@u7Uy2nLsgAo$+o&!`wJ~!~9+OuVrk?8Lu z1h{Q7S#|tQq@b07l$V`>JjDCr?cwe=y(X5-`+b+0YYRX90DcdDX?=3h*wm zFzZ8-&fG^smtq7nnGlj9f>AA{=O4z@qvfBn1(x!w#;W1Y6QVIosv7J{(ZlF7^Gr4> zJjGF$cQ{A%_~POR`Gjl|36k(Zv6u0VnWCRrSmFFuVh_*C!VQqjLVBB}Hc!QB6E@1c z)?L;igbVEeH=I;zeNTWP6v}={g`>LL`31ipYZKa1<7`HpNcYeVOhZB`hSc>4#}dxB z9cS6|c!}SU^Ja7ne-t0TR(YxlzwlclgREc~4t}Y+Oo2*fAH9#6;*}C@DafpvK^H+b zLqn+5t%qFiB!uEu%5%#c%G4@qt=X-Lp5BrLzY`x*=(w%9UE8Z_g4UHsP%HSgzycpFjkj-aXZVLF z-6)(l;_S_g5-A8MjpKP7(%_1RVp;Z>k%n2TS+Ks0z|SO$UR-%pYl5SR4noILOtw?j z8tEmYb~#!`%3o?rzDW9$G+8od$mlNb10APZ3kCslB~pv>Z>&qNI9@pe*%5TOIt3wI zakUPvPC}{L?c2Hjo7do27L2%${P9e{eF&Lc-)rq$WmiG4`<5`#46~m#(zMfrhcrD% z-DUk^EU3_zv;tqYPJtXjydfC7xLQk3+qS8|DWeUi4GnJiwQANe8=tCX?7i6L%R(tB zMW)TB#ir@+?h9SMSSC8ovi@x!#_(VSGPLa#?Jey)H{_<(rmxmEOn-eE^7O~F>D0$* zqp5{w*QSV5lT)N;LC+Q^^?dSt;(R~<^?h8U?gxR#KVw*IyD(cbaczDk?m9*Fk}B%n z_N3TY;mpL$?&Q0P+6k?SpLPY$x5|oY$?&7NgGwIz0dwQhCiq(AC?D_&3 zHQ{>T??Bo1pY5^j*FyV4twZBOw?Ys1IT#ARWqw~|kQugYT5M8mtZemcB<>#x3O#~7 zZVA5=8q(9!@1&`n4+QJN9Io-GjH(A*@ANfLyRYu#HGzIW5yZTMnP2GZvZadN5}3@%@A31@aGp?%Rpe6aP$+Q%JNCKwH*Js@ z_x!O%0iW&>2NLdp?%Cd(#O&48=PSN{)qn8Ob=P&Vt#0jaDlx!2V1P7-37RbaOXAL( z?#}mrVq+^}2g@iP6XRXb@y3}SY^nX67=N##AOr0X&HBH!zV6S=b~}9!|L{vhq}uF> zS?X{_NdF#v@4{Mo+eX_1*G;#ofO8}Si5y@P7JJ0POXMv!&KZcSdFEZarcd>D zpK+IN;Awd8=Y3#$a2eY>NA2hh8%taPeX-rbFQTaGv!v;uchm)J{Nm-v=E%$wwG&Y$ zXQuh6uTjtR2D%0ky6H!$yW;LyT+e+J@Vs# zYO5?jxV%Vpy*6R0kF6krWgGQ^*c6F_}gjukxh*`baRntZ6*MLs?BMR!#ZQ{r5 zX3rNRWqwqL5r^fO&AEBfMF>iXsw^=l{*sJm#~2S~Jl1~v{k4?`%9@n=!tAA)GuU<3 z&C{x-WrG-K`V*OsG7qcw+N%Eez9Xcg;rovdlMXfZDCfg~1~iQl`i3#eR*{fG%p+x5|g?Pc-Jq%vm9@e%Rwa;UrP#aJPO?S_U-c|hHMr}D@@kK*DJrq?)Z((?yZGW zi@qIxzZtUd^SF^~R3yXwuG{za&$ws!u87iA_9F=`wu@}qiDHTE%Gz$*;9~Xgm6W4L zlPGdSafdK&Yhv&?YkAZ9J$3=vDn%aZ__gl9s9z)D1E}*(co8D$bMXW@<><+wXoTwT zMz;+~-5VRaT07|OSZ&OFqx?r%fw`r<|rdza>n2jqzI$~WEV!N(>uIr%kx zH?N+!9*umS4SExN3{w%(zW&E`|9G;Y;P%ruA5JE=J!ymw`@d1(1~2!=udO5TONyKR zCmne~plfZkM%vYzc@gWs&hP)&u1T{jiC{U5+dCQ<*A6~?DJ3yT8*=~%l>>mNH~?Ur zN>S?o5U2tG8)yK~$^!rqTw%Ml&gp^!hjhXN0GGgj!8GwH;`me)B^WvqY_VR1Add&0 z0Nm3LAA*;(B?R8}!Aja;v3}h(%i#dPG+=_zw+k-Znr=*Y)<17Fo*z}c9-H|D5_bhD zUd}BODp|mN5UME8^IHaQu`hp#I5a)7_v`fn?J$_^j+uMKRC2fedgLcOQ4~M=h8%q| zQMf0c)HdTB#v4PPrybtc5g%~&9rd5>m_@+20?ci;Gv)J^S@ z2eBZ|@j>-^0sj9t|6@WI{o>p6eK@V6Qwu>XX*9kW=RNs^fmLWRb#0+zsl>&X0_~?W Y8))^)v|QuKIZYlgF|z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000B* zNklU3^%?1R>zOq3$dOk@Sc_(h$=Oh3tB2urDn z;^>OnxMjuZ)DI%A4i{9+EUV7Jf+7`U3}TnYb{AQh4V`UH(lkj=nw*Ot+Osxi&1qK} zW#aQK?|IMr{CIdC-W)=bB>bB}{13Qg0iHm#06-`IuFXWehdNuk{ttP4=ezmDqt&RRNwrR005|?#{CH%=j<>pxfspss^w+nn-usQ9%t5e%G@*n?C>X ziUK@=D0S~$R(>=!4bik7Bt@f;PXhq5?4JMtgSiF(z~xu~5W0O%T5niO7PzZog=23D z@Nm6N_X|Y=ym=D1 z%#~hlN;ziN6Wu;%qZ(jMl5vex3m}Oi_xbDh8`S`gB;#TMz*2KNfVnZN1QNxW3FD`y z7JNP*APPKwJRaCO6949>N&sV$apkK8kR%b|;EUUGY&=p4KqeWN0L+z;*3DE*Z?Xdb ziri#bV&xdh&DV8e>;?b;gb(g~Jj=$MRuGwkcgWPrv%X^hyFk?b|`pdYH_%huCYs{i+H8 z0F!3bs#jWDN99V$p-i9*IiVb({ZE3VwV()TLPP63jV}+K90=li(ux4DKdArg%OPVa z-FN1h*Fw(a0>0SS0)wS)!0gztbM#WUU%6lPGV=O^`m=oz)A@mmUvY)vW1=vP7dlR> z0z&OiK@Q0y+ygJdcNilPBXAP52^sRK>xKc#5>TNySw3;>&(cawvCAKm=_fdyY6ZnHi3$Tqiz zDy Date: Tue, 9 Sep 2025 01:41:48 +0800 Subject: [PATCH 21/40] Added Searchbar --- dependencies.gradle | 5 +- .../vendingmachine/VendingMachine.java | 3 - .../blocks/gui/MTEVendingMachineGui.java | 18 ++++ .../vendingmachine/blocks/gui/SearchBar.java | 101 ++++++++++++++++++ .../blocks/gui/TradeItemDisplay.java | 13 +++ .../blocks/gui/TradeMainPanel.java | 14 ++- .../vendingmachine/gui/GuiTextures.java | 8 ++ .../vendingmachine/trade/TradeDatabase.java | 7 +- .../assets/vendingmachine/lang/en_US.lang | 1 + .../gui/background/text_field_light_gray.png | Bin 0 -> 103 bytes 10 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/SearchBar.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/text_field_light_gray.png diff --git a/dependencies.gradle b/dependencies.gradle index cc83ac8..d4a2fbb 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,10 +34,11 @@ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { - compileOnly("com.github.GTNewHorizons:NotEnoughItems:2.7.77-GTNH:dev") + implementation("com.github.GTNewHorizons:NotEnoughItems:2.7.77-GTNH:dev") implementation("com.github.GTNewHorizons:GTNHLib:0.6.39:dev") compileOnly("com.github.GTNewHorizons:BetterQuesting:3.7.11-GTNH:dev") - implementation("com.github.GTNewHorizons:ModularUI2:2.2.16-1.7.10:dev") + implementation("com.github.GTNewHorizons:ModularUI2:2.2.18-1.7.10:dev") + // implementation("com.github.GTNewHorizons:ModularUI2:99.99:dev") implementation("com.github.GTNewHorizons:StructureLib:1.4.18:dev") implementation("com.github.GTNewHorizons:GT5-Unofficial:5.09.51.440:dev") } diff --git a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java index fde7e33..aea0677 100644 --- a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java @@ -45,7 +45,6 @@ public class VendingMachine { public static Block vendingMachine = new BlockVendingMachine(); - public static boolean isNeiLoaded = false; public static boolean isBqLoaded = false; public static boolean isGtLoaded = false; public static boolean isAeLoaded = false; @@ -82,12 +81,10 @@ public void preInit(FMLPreInitializationEvent event) { public void init(FMLInitializationEvent event) { proxy.init(event); - isNeiLoaded = Loader.isModLoaded("NotEnoughItems"); isBqLoaded = Loader.isModLoaded("betterquesting"); isGtLoaded = Loader.isModLoaded("gregtech"); isAeLoaded = Loader.isModLoaded("appliedenergistics2"); - LOG.info("NEI Integration enabled: {}", isNeiLoaded); LOG.info("Better Questing Integration enabled: {}", isBqLoaded); LOG.info("Gregtech Integration enabled: {}", isGtLoaded); LOG.info("AE2 Integration enabled {}", isAeLoaded); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 4bd3571..01e6664 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -60,6 +60,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private PosGuiData guiData; private PagedWidget.Controller tabController; + private SearchBar searchBar; public static final int ITEMS_PER_ROW = 3; private static final int ITEM_HEIGHT = 18; @@ -78,12 +79,17 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { } this.tabController = new PagedWidget.Controller(); + this.searchBar = createSearchBar(); } public MTEVendingMachine getBase() { return base; } + public void setForceRefresh() { + this.forceRefresh = true; + } + @Override public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISettings uiSettings) { this.guiData = guiData; @@ -96,6 +102,7 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe panel = panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) + .child(this.searchBar) .child(createTradeUI((TradeMainPanel) panel, this.tabController)) .child(createInventoryRow(panel, syncManager))); panel = panel.child( @@ -150,6 +157,13 @@ private IWidget createTitleTextStyle(String title) { .marginBottom(1)); } + private SearchBar createSearchBar() { + return new SearchBar(this).width(163) + .left(3) + .top(5) + .height(10); + } + private void ejectItems() { if (!this.guiData.isClient()) { if (base.getBaseMetaTileEntity() == null) { @@ -418,4 +432,8 @@ public void updateSlots(Map> trades) { } } + public String getSearchBarText() { + return this.searchBar.getText(); + } + } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/SearchBar.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/SearchBar.java new file mode 100644 index 0000000..a758b07 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/SearchBar.java @@ -0,0 +1,101 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import java.awt.Point; + +import org.jetbrains.annotations.NotNull; + +import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; +import com.cleanroommc.modularui.theme.WidgetTextFieldTheme; +import com.cleanroommc.modularui.widgets.textfield.BaseTextFieldWidget; +import com.cubefury.vendingmachine.gui.GuiTextures; +import com.cubefury.vendingmachine.util.Translator; + +public class SearchBar extends BaseTextFieldWidget { + + private MTEVendingMachineGui gui; + private String previousText; + + public SearchBar(MTEVendingMachineGui gui) { + super(); + + this.gui = gui; + + background(GuiTextures.TEXT_FIELD_BACKGROUND); + setText(""); + this.previousText = ""; + hintText(Translator.translate("vendingmachine.gui.search")); + } + + @Override + public void onFocus(ModularGuiContext context) { + super.onFocus(context); + Point main = this.handler.getMainCursor(); + if (main.x == 0) { + this.handler.setCursor(main.y, getText().length(), true, true); + } + } + + @Override + public boolean canHover() { + return true; + } + + @Override + public void drawForeground(ModularGuiContext context) { + if ( + hasTooltip() && getScrollData().isScrollBarActive(getScrollArea()) + && isHoveringFor(getTooltip().getShowUpTimer()) + ) { + getTooltip().draw(getContext()); + } + } + + @NotNull + public String getText() { + if ( + this.handler.getText() + .isEmpty() + ) { + return ""; + } + if ( + this.handler.getText() + .size() > 1 + ) { + throw new IllegalStateException("TextFieldWidget can only have one line!"); + } + return this.handler.getText() + .get(0); + } + + @Override + protected void setupDrawText(ModularGuiContext context, WidgetTextFieldTheme widgetTheme) { + this.renderer.setSimulate(false); + this.renderer.setPos(getArea().getPadding().left, 0); + this.renderer.setScale(this.scale); + this.renderer.setAlignment(this.textAlignment, -1, getArea().height); + } + + public void setText(@NotNull String text) { + if ( + this.handler.getText() + .isEmpty() + ) { + this.handler.getText() + .add(text); + } else { + this.handler.getText() + .set(0, text); + } + } + + @Override + public void onUpdate() { + super.onUpdate(); + String curText = getText(); + if (!curText.equals(previousText)) { + gui.setForceRefresh(); + } + previousText = curText; + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java index f3f3bba..44eadfd 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java @@ -12,6 +12,8 @@ import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.NBTConverter; +import codechicken.nei.api.ItemFilter; + public class TradeItemDisplay { public List fromItems; @@ -114,4 +116,15 @@ public boolean equals(Object obj) { && this.tradeableNow == other.tradeableNow && this.playerID == other.playerID; } + + public boolean satisfiesSearch(ItemFilter filter, String searchStringNoCase) { + if (filter == null) { + return this.label.toLowerCase() + .contains(searchStringNoCase); + } + return filter.matches(this.display) || this.toItems.stream() + .anyMatch(bis -> filter.matches(bis.getBaseStack())) + || this.fromItems.stream() + .anyMatch(bis -> filter.matches(bis.getBaseStack())); + } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 1241395..a2a2aa7 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; @@ -27,6 +28,9 @@ import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; +import codechicken.nei.SearchField; +import codechicken.nei.api.ItemFilter; + public class TradeMainPanel extends ModularPanel { public boolean shiftHeld = false; @@ -186,7 +190,14 @@ public Map> formatTrades(List filteredTrades : trades.values()) { + String searchString = gui.getSearchBarText(); + ItemFilter filter = SearchField.getFilter(searchString); + + for (TradeCategory category : trades.keySet()) { + List filteredTrades = trades.get(category); + filteredTrades = filteredTrades.stream() + .filter(tid -> tid.satisfiesSearch(filter, searchString.toLowerCase())) + .collect(Collectors.toList()); filteredTrades.sort((a, b) -> { // null case if (a == null && b == null) return 0; @@ -219,6 +230,7 @@ public Map> formatTrades(ListeA~B9x`lah4ok30~IlNy85}Sb4q9e0M Date: Tue, 9 Sep 2025 02:12:19 +0800 Subject: [PATCH 22/40] Added Item Tooltips --- .../blocks/gui/MTEVendingMachineGui.java | 15 ++++++++++++++- .../assets/vendingmachine/lang/en_US.lang | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 01e6664..655a44a 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -40,6 +40,7 @@ import com.cubefury.vendingmachine.gui.WidgetThemes; import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; import gregtech.api.metatileentity.implementations.gui.MTEMultiBlockBaseGui; @@ -296,7 +297,19 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t if (index < displayedTrades.get(category).size()) { TradeItemDisplay cur = displayedTrades.get(category).get(index); if (cur != null && cur.display != null) { - builder.add("yes trade"); + builder.clearText(); + for (BigItemStack toItem : cur.toItems) { + builder.addLine(IKey.str(toItem.stackSize + " " + toItem.getBaseStack().getDisplayName()).style(IKey.AQUA)); + // builder.add(new ItemDrawable(toItem.getBaseStack())); + } + builder.emptyLine(); + builder.addLine(IKey.str(Translator.translate("vendingmachine.gui.required_inputs")).style(IKey.DARK_GREEN, IKey.ITALIC)); + for (BigItemStack fromItem : cur.fromItems) { + builder.addLine(IKey.str(fromItem.stackSize + " " + fromItem.getBaseStack().getDisplayName()).style(IKey.DARK_GREEN)); + } + + builder.emptyLine(); + builder.addLine(IKey.str(cur.label).style(IKey.GRAY)); } } } diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index 957fe09..be90e15 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -11,6 +11,7 @@ vendingmachine.gui.neiColor.conditionSatisfied=55D441 vendingmachine.gui.neiColor.conditionUnsatisfied=A87A5E vendingmachine.gui.item_eject=Eject Items vendingmachine.gui.search=Search +vendingmachine.gui.required_inputs=Requires: vendingmachine.gui.cooldown_display.second=s vendingmachine.gui.cooldown_display.minute=m From e000b57f53cd5e9e0ef8c804e33fde1d5a8abac8 Mon Sep 17 00:00:00 2001 From: cubefury Date: Tue, 9 Sep 2025 02:19:36 +0800 Subject: [PATCH 23/40] Active check for purchasing/dispensing items --- .../cubefury/vendingmachine/blocks/MTEVendingMachine.java | 7 ++++++- .../vendingmachine/blocks/gui/MTEVendingMachineGui.java | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 55f4798..c461fe3 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -407,7 +407,7 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { if ((aBaseMetaTileEntity.isClientSide()) && (aBaseMetaTileEntity.isActive())) { // spawn something maybe } - if (aBaseMetaTileEntity.isServerSide()) { + if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isActive()) { dispenseItems(); if (this.mUpdate++ % STRUCTURE_CHECK_TICKS == 0) { this.mMachine = checkMachine(aBaseMetaTileEntity, null); @@ -416,6 +416,11 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { } } + public boolean getActive() { + return this.getBaseMetaTileEntity() != null && this.getBaseMetaTileEntity() + .isActive(); + } + @Override public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { super.onFirstTick(aBaseMetaTileEntity); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 655a44a..964a4eb 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -388,6 +388,9 @@ protected void registerSyncValues(PanelSyncManager syncManager) { public void attemptPurchase(TradeCategory category, int index) { TradeItemDisplay trade = null; + if (!base.getActive()) { + return; + } synchronized (displayedTrades) { if ( From b4bea69b68d60de719dfc6222096fa5b2f08e7dc Mon Sep 17 00:00:00 2001 From: cubefury Date: Tue, 9 Sep 2025 20:10:36 +0800 Subject: [PATCH 24/40] Removed unnecessary UI object reassignments --- .../blocks/gui/MTEVendingMachineGui.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 964a4eb..4972d43 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -99,17 +99,17 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager, this.tabController) .size(198, height) .padding(4); - panel = panel.child(createCategoryTabs(this.tabController)); - panel = panel.child( + panel.child(createCategoryTabs(this.tabController)); + panel.child( new Column().width(170) .child(createTitleTextStyle(base.getLocalName())) .child(this.searchBar) .child(createTradeUI((TradeMainPanel) panel, this.tabController)) .child(createInventoryRow(panel, syncManager))); - panel = panel.child( + panel.child( new Column().size(20) .right(5)); - panel = panel.child(createIOColumn(syncManager)); + panel.child(createIOColumn(syncManager)); return panel; } @@ -122,7 +122,7 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { for (int i = 0; i < this.tradeCategories.size(); i++) { int index = i; - tabColumn = tabColumn.child( + tabColumn.child( new PageButton(i, tabController).tab(com.cleanroommc.modularui.drawable.GuiTextures.TAB_LEFT, -1) .overlay( this.tradeCategories.get(i) From 07f46783df1da0530e1d17cb1cbdb18bb3d64eb6 Mon Sep 17 00:00:00 2001 From: cubefury Date: Tue, 9 Sep 2025 22:50:37 +0800 Subject: [PATCH 25/40] Swapped Purchase Icon graphics to buttons --- .../blocks/gui/MTEVendingMachineGui.java | 98 ++++++------------ .../blocks/gui/TradeItemDisplayWidget.java | 60 +++++++++++ .../blocks/gui/TradeMainPanel.java | 11 +- .../vendingmachine/blocks/gui/TradeSlot.java | 34 ------ .../vendingmachine/gui/GuiTextures.java | 16 +++ .../gui/background/trade_button_pressed.png | Bin 0 -> 263 bytes .../gui/background/trade_button_unpressed.png | Bin 0 -> 241 bytes 7 files changed, 113 insertions(+), 106 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java delete mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_unpressed.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 4972d43..451540d 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -18,8 +18,6 @@ import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.utils.Alignment; -import com.cleanroommc.modularui.utils.item.IItemHandlerModifiable; -import com.cleanroommc.modularui.utils.item.ItemStackHandler; import com.cleanroommc.modularui.value.sync.BooleanSyncValue; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.widget.ParentWidget; @@ -55,8 +53,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { public boolean forceRefresh = false; private boolean ejectItems = false; - private final Map tradeItemHandlers = new HashMap<>(); - private final Map> displayedTrades = new HashMap<>(); + private final Map> displayedTrades = new HashMap<>(); private final List tradeCategories = new ArrayList<>(); private PosGuiData guiData; @@ -64,7 +61,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private SearchBar searchBar; public static final int ITEMS_PER_ROW = 3; - private static final int ITEM_HEIGHT = 18; + public static final int ITEM_HEIGHT = 54; private static final int ROW_SEPARATOR_HEIGHT = 5; public MTEVendingMachineGui(MTEVendingMachine base, int height) { @@ -76,7 +73,11 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { this.tradeCategories.addAll(TradeDatabase.INSTANCE.getTradeCategories()); for (TradeCategory c : this.tradeCategories) { - tradeItemHandlers.put(c, new ItemStackHandler(MTEVendingMachine.MAX_TRADES)); + displayedTrades.put(c, new ArrayList<>(MTEVendingMachine.MAX_TRADES)); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + displayedTrades.get(c) + .add(new TradeItemDisplayWidget(null)); + } } this.tabController = new PagedWidget.Controller(); @@ -96,8 +97,7 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe this.guiData = guiData; registerSyncValues(syncManager); - ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager, this.tabController) - .size(198, height) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(198, height) .padding(4); panel.child(createCategoryTabs(this.tabController)); panel.child( @@ -116,8 +116,8 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe public IWidget createCategoryTabs(PagedWidget.Controller tabController) { Flow tabColumn = new Column().width(40) .height(100) - .left(-30) - .top(50) + .left(-29) + .top(40) .coverChildren(); for (int i = 0; i < this.tradeCategories.size(); i++) { @@ -287,17 +287,14 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int index = i; - int x = i % ITEMS_PER_ROW; - int y = i / ITEMS_PER_ROW; - row.child(new TradeSlot(category, i, rootPanel) - .slot(new ModularSlot(tradeItemHandlers.get(category), i)) + displayedTrades.get(category).get(i).setRootPanel(rootPanel); + row.child(displayedTrades.get(category).get(i) .tooltipDynamic(builder -> { - // builder.clearText(); + builder.clearText(); synchronized (displayedTrades) { if (index < displayedTrades.get(category).size()) { - TradeItemDisplay cur = displayedTrades.get(category).get(index); - if (cur != null && cur.display != null) { - builder.clearText(); + TradeItemDisplay cur = displayedTrades.get(category).get(index).getDisplay(); + if (cur != null) { for (BigItemStack toItem : cur.toItems) { builder.addLine(IKey.str(toItem.stackSize + " " + toItem.getBaseStack().getDisplayName()).style(IKey.AQUA)); // builder.add(new ItemDrawable(toItem.getBaseStack())); @@ -317,30 +314,24 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t .tooltipAutoUpdate(true) // if it starts lagging, we'll need to index all // the tradeslots and then call updateTooltip() every // refresh - .background(new DynamicDrawable(() -> { - if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).tradeableNow) { - return GuiTextures.TRADE_AVAILABLE_BACKGROUND; - } - return GTGuiTextures.SLOT_ITEM_STANDARD; - })) .overlay( new DynamicDrawable(() -> { if ( index < displayedTrades.get(category).size() - && (displayedTrades.get(category).get(index).hasCooldown || !displayedTrades.get(category).get(index).enabled) + && (displayedTrades.get(category).get(index).getDisplay().hasCooldown || !displayedTrades.get(category).get(index).getDisplay().enabled) ) { return GuiTextures.OVERLAY_TRADE_DISABLED; } - if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).tradeableNow) { + if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).getDisplay().tradeableNow) { return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; } return null; }), new DynamicDrawable(() -> { - if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).hasCooldown) { - return IKey.str(displayedTrades.get(category).get(index).cooldownText); + if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).getDisplay().hasCooldown) { + return IKey.str(displayedTrades.get(category).get(index).getDisplay().cooldownText); } return null; })) - .setEnabledIf(slot -> tradeItemHandlers.get(category).getStackInSlot(index) != null)); + .setEnabledIf(slot -> ((TradeItemDisplayWidget) slot).getDisplay() != null)); if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { tradeList.child(row); @@ -386,32 +377,13 @@ protected void registerSyncValues(PanelSyncManager syncManager) { syncManager.syncValue("ejectItems", ejectItemsSyncer); } - public void attemptPurchase(TradeCategory category, int index) { - TradeItemDisplay trade = null; - if (!base.getActive()) { - return; - } - - synchronized (displayedTrades) { - if ( - displayedTrades.get(category) - .size() <= index - ) { - return; - } - trade = displayedTrades.get(category) - .get(index); - if (trade == null) { - return; - } - submitTradesToServer( - displayedTrades.get(category) - .get(index)); - } + public void attemptPurchase(TradeItemDisplay display) { + submitTradesToServer(display); this.forceRefresh = true; } private void submitTradesToServer(TradeItemDisplay trade) { + VendingMachine.LOG.info("attempted trade for {}", trade.display); if (!trade.tradeableNow || !trade.enabled) { return; } @@ -424,24 +396,20 @@ public void resetForceRefresh() { public void updateSlots(Map> trades) { synchronized (displayedTrades) { - displayedTrades.clear(); - displayedTrades.putAll(trades); - for (Map.Entry> entry : displayedTrades.entrySet()) { - int displayedSize = displayedTrades.get(entry.getKey()) + for (Map.Entry> entry : displayedTrades.entrySet()) { + int displayedSize = trades.get(entry.getKey()) .size(); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { if (i < displayedSize) { - tradeItemHandlers.get(entry.getKey()) - .setStackInSlot( - i, - displayedTrades.get(entry.getKey()) - .get(i) != null - ? displayedTrades.get(entry.getKey()) - .get(i).display - : null); + displayedTrades.get(entry.getKey()) + .get(i) + .setDisplay( + trades.get(entry.getKey()) + .get(i)); } else { - tradeItemHandlers.get(entry.getKey()) - .setStackInSlot(i, null); + displayedTrades.get(entry.getKey()) + .get(i) + .setDisplay(null); } } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java new file mode 100644 index 0000000..26d41c8 --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -0,0 +1,60 @@ +package com.cubefury.vendingmachine.blocks.gui; + +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; + +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.widgets.ItemDisplayWidget; +import com.cubefury.vendingmachine.gui.GuiTextures; + +public class TradeItemDisplayWidget extends ItemDisplayWidget implements Interactable { + + private TradeMainPanel rootPanel; + private boolean pressed = false; + + private TradeItemDisplay display; + + public TradeItemDisplayWidget(TradeItemDisplay display) { + size(MTEVendingMachineGui.ITEM_HEIGHT); + background( + new DynamicDrawable(() -> pressed ? GuiTextures.TRADE_BUTTON_PRESSED : GuiTextures.TRADE_BUTTON_UNPRESSED)); + + this.display = display; + this.item((ItemStack) null); + } + + public void setDisplay(TradeItemDisplay display) { + this.display = display; + this.item(display == null ? null : display.display); + } + + public TradeItemDisplay getDisplay() { + return this.display; + } + + public @NotNull Interactable.Result onMousePressed(int mouseButton) { + if (rootPanel.shiftHeld) { + rootPanel.attemptPurchase(this.display); + pressed = true; + return Result.SUCCESS; + } + return Result.IGNORE; + } + + @Override + public void onMouseEndHover() { + pressed = false; + } + + @Override + public boolean onMouseRelease(int mouseButton) { + pressed = false; + return true; + } + + public void setRootPanel(TradeMainPanel rootPanel) { + this.rootPanel = rootPanel; + } +} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index a2a2aa7..6add5b5 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -16,7 +16,6 @@ import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.value.sync.PanelSyncManager; -import com.cleanroommc.modularui.widgets.PagedWidget; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.storage.NameCache; @@ -39,17 +38,15 @@ public class TradeMainPanel extends ModularPanel { private final PosGuiData guiData; private EntityPlayer player = null; private int ticksOpen = 0; - private UUID playerID = null; - private PagedWidget.Controller tabController = null; + private final UUID playerID; public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData guiData, - PanelSyncManager syncManager, PagedWidget.Controller tabController) { + PanelSyncManager syncManager) { super(name); this.gui = gui; this.guiData = guiData; this.syncManager = syncManager; this.playerID = NameCache.INSTANCE.getUUIDFromPlayer(guiData.getPlayer()); - this.tabController = tabController; } @Override @@ -245,7 +242,7 @@ private static int getRank(TradeItemDisplay t) { return t.hasCooldown ? 4 : 3; } - public void attemptPurchase(TradeCategory category, int index) { - gui.attemptPurchase(category, index); + public void attemptPurchase(TradeItemDisplay display) { + gui.attemptPurchase(display); } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java deleted file mode 100644 index e4be8eb..0000000 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeSlot.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.cubefury.vendingmachine.blocks.gui; - -import net.minecraft.item.ItemStack; - -import org.jetbrains.annotations.NotNull; - -import com.cleanroommc.modularui.widgets.slot.PhantomItemSlot; -import com.cubefury.vendingmachine.trade.TradeCategory; - -public class TradeSlot extends PhantomItemSlot { - - private TradeCategory category; - private int index; - TradeMainPanel rootPanel; - - public TradeSlot(TradeCategory category, int index, TradeMainPanel rootPanel) { - this.category = category; - this.index = index; - this.rootPanel = rootPanel; - } - - @Override - public @NotNull Result onMousePressed(int mouseButton) { - if (rootPanel.shiftHeld) { - rootPanel.attemptPurchase(category, index); - } - return Result.SUCCESS; - } - - @Override - public boolean handleDragAndDrop(@NotNull ItemStack draggedStack, int button) { - return false; - } -} diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index 346180b..6423ebe 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -41,4 +41,20 @@ public final class GuiTextures { .canApplyTheme() .name("text_field_background") .build(); + + public static final UITexture TRADE_BUTTON_UNPRESSED = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/trade_button_unpressed") + .imageSize(195, 136) + .adaptable(4) + .canApplyTheme() + .name("trade_button_unpressed") + .build(); + + public static final UITexture TRADE_BUTTON_PRESSED = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/trade_button_pressed") + .imageSize(195, 136) + .adaptable(4) + .canApplyTheme() + .name("trade_button_pressed") + .build(); } diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed.png b/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2b58e4419d2658191260759a96971e483673bb87 GIT binary patch literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^hk>|*g&9b$IOk*rq*&4&eH|GXHuiJ>Nn{1`8H|*g&9b$IOk*rq*&4&eH|GXHuiJ>Nn{1`8HTlah~XZ9{}m^}|@J%gvKpUXO@geCw{eM&X} literal 0 HcmV?d00001 From 3203f8573739edd58fdb1cc4c41c03bb668f98ed Mon Sep 17 00:00:00 2001 From: cubefury Date: Wed, 10 Sep 2025 02:07:46 +0800 Subject: [PATCH 26/40] Fixed Trade Panel Display --- .../blocks/gui/MTEVendingMachineGui.java | 26 ++++++++----- .../blocks/gui/TradeItemDisplayWidget.java | 36 +++++++++++++++++- .../vendingmachine/gui/GuiTextures.java | 6 +-- .../trade_button_pressed_color_corrected.png | Bin 0 -> 3261 bytes ...trade_button_unpressed_color_corrected.png | Bin 0 -> 3280 bytes 5 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed_color_corrected.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_unpressed_color_corrected.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 451540d..bb952a0 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -61,7 +61,8 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private SearchBar searchBar; public static final int ITEMS_PER_ROW = 3; - public static final int ITEM_HEIGHT = 54; + public static final int ITEM_HEIGHT = 25; + public static final int ITEM_WIDTH = 47; private static final int ROW_SEPARATOR_HEIGHT = 5; public MTEVendingMachineGui(MTEVendingMachine base, int height) { @@ -97,7 +98,7 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe this.guiData = guiData; registerSyncValues(syncManager); - ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(198, height) + ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(178, height) .padding(4); panel.child(createCategoryTabs(this.tabController)); panel.child( @@ -159,7 +160,7 @@ private IWidget createTitleTextStyle(String title) { } private SearchBar createSearchBar() { - return new SearchBar(this).width(163) + return new SearchBar(this).width(162) .left(3) .top(5) .height(10); @@ -277,7 +278,13 @@ private SlotGroupWidget createOutputSlots() { // spotless:off private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller tabController) { - PagedWidget paged = new PagedWidget<>().expanded().debugName("paged").controller(tabController).heightRel(0.5f); + PagedWidget paged = new PagedWidget<>() + .width(162) + .debugName("paged") + .controller(tabController) + .background(GuiTextures.TEXT_FIELD_BACKGROUND) + .padding(4) + .heightRel(0.5f); for (TradeCategory category : this.tradeCategories) { ListWidget tradeList = new ListWidget<>().debugName("items").heightRel(1.0f) .widthRel(1.0f).childSeparator(new Rectangle().setColor(0x0).asIcon().size(ROW_SEPARATOR_HEIGHT)) @@ -288,7 +295,8 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int index = i; displayedTrades.get(category).get(i).setRootPanel(rootPanel); - row.child(displayedTrades.get(category).get(i) + row.childPadding(5) + .child(displayedTrades.get(category).get(i) .tooltipDynamic(builder -> { builder.clearText(); synchronized (displayedTrades) { @@ -311,9 +319,7 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t } } }) - .tooltipAutoUpdate(true) // if it starts lagging, we'll need to index all - // the tradeslots and then call updateTooltip() every - // refresh + .tooltipAutoUpdate(true) .overlay( new DynamicDrawable(() -> { if ( @@ -345,8 +351,8 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t } return new Row().child(paged.top(0)) - .left(4) - .top(38); + .left(3) + .top(24); } // spotless:on diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java index 26d41c8..1e26262 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -4,8 +4,15 @@ import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.value.IValue; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.utils.Platform; +import com.cleanroommc.modularui.value.sync.GenericSyncValue; +import com.cleanroommc.modularui.value.sync.SyncHandler; import com.cleanroommc.modularui.widgets.ItemDisplayWidget; import com.cubefury.vendingmachine.gui.GuiTextures; @@ -13,11 +20,13 @@ public class TradeItemDisplayWidget extends ItemDisplayWidget implements Interac private TradeMainPanel rootPanel; private boolean pressed = false; + private IValue value; private TradeItemDisplay display; public TradeItemDisplayWidget(TradeItemDisplay display) { - size(MTEVendingMachineGui.ITEM_HEIGHT); + height(MTEVendingMachineGui.ITEM_HEIGHT); + width(MTEVendingMachineGui.ITEM_WIDTH); background( new DynamicDrawable(() -> pressed ? GuiTextures.TRADE_BUTTON_PRESSED : GuiTextures.TRADE_BUTTON_UNPRESSED)); @@ -43,6 +52,31 @@ public TradeItemDisplay getDisplay() { return Result.IGNORE; } + @Override + public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { + ItemStack item = value.getValue(); + if (!Platform.isStackEmpty(item)) { + GuiDraw.drawText(" " + this.display.display.stackSize, 4, 9, 1.0f, 0x0, false); + GuiDraw.drawItem(item, 26, 4, 16, 16, context.getCurrentDrawingZ()); + + } + } + + @Override + public boolean isValidSyncHandler(SyncHandler syncHandler) { + if (syncHandler instanceof GenericSyncValuegenericSyncValue && genericSyncValue.isOfType(ItemStack.class)) { + this.value = genericSyncValue.cast(); + return true; + } + return false; + } + + public ItemDisplayWidget item(IValue itemSupplier) { + this.value = itemSupplier; + setValue(itemSupplier); + return this; + } + @Override public void onMouseEndHover() { pressed = false; diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index 6423ebe..b5e4265 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -43,18 +43,16 @@ public final class GuiTextures { .build(); public static final UITexture TRADE_BUTTON_UNPRESSED = UITexture.builder() - .location(VendingMachine.MODID, "gui/background/trade_button_unpressed") + .location(VendingMachine.MODID, "gui/background/trade_button_unpressed_color_corrected") .imageSize(195, 136) .adaptable(4) - .canApplyTheme() .name("trade_button_unpressed") .build(); public static final UITexture TRADE_BUTTON_PRESSED = UITexture.builder() - .location(VendingMachine.MODID, "gui/background/trade_button_pressed") + .location(VendingMachine.MODID, "gui/background/trade_button_pressed_color_corrected") .imageSize(195, 136) .adaptable(4) - .canApplyTheme() .name("trade_button_pressed") .build(); } diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed_color_corrected.png b/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_pressed_color_corrected.png new file mode 100644 index 0000000000000000000000000000000000000000..1c15f01d60f3eb27b5e2c35f4a16befc66aab7c6 GIT binary patch literal 3261 zcmds(={wX77sr1iTNtv8+mu^miDbr-NTxzUG-I-x$eL{!%Vf-0vyP#WY%!JfW<-{; zG|G}COUbR0ts;Ywtdl+D@%#=da005hrUcGtf zorjS5c@Nd``)!^>89NjAaSdPFkm-xdO?@V)v+C@BM` z9yH^&PUSyWS3wvSi2AKhQ)wN0dYZ8_A3f-oxeygdynp=ObCHY_gX!F%%jTU4p1K}ty=-0_jVT>i_|mk+Bt=MD^WsO z(mGYztw4cZOU{K~x9kdbqhe)`7L}+X| zK*2cDuZ{DD=*=P~|HXgPKlQ$rmezfybapzkplu;qZx0;FLCAAL+j5eY-zIwsWN_ny zzS*mosTf{DAhP;cgWv=Gt^?iG>NWf0y~(qy7xd9r>E3Ud&ARAUL~KPKu}OX_mz)NpOzb2%nF%q2x&W5G=Pl?30x5!<=KqAZh7RVfxI{9^c6l`Ff8WXcRl9OXpbQ2H_N-0PiHB$KNuF0FlOm1kQof=}jN zerFy36*4~#(Og-Z6*R#-I1Er7<8Lb#-XTMvmJ+TrrEWD89>Bck4wHURiv3Oxo zHdK07(xj`L)gQRb9v@*3Zl_rEy zy3MZXH_p`%F#J%!w6xDu%Ot&3e5(sF`dmmti_?vVaP<8lr~`D&lTpZUVAwFcJWRa# zZ_wDr=0#b9$iYPKl^kVwkYk4f!`E2gmXn$=eoN6l2`4S=oHD)3U2`SZkGZPAP;`H=ru){E!%vix%Ou(4@^0 z>SJmSl8USwFmhs4#RcRAJX!Wfq{@660z{KuzSSL z4bA=ITZ-$}tk8Vrk33J%ne?9U`4gPmt~tPnd$;Upc{W0=(E*Q%sIOfa_4nB^? z7#j>&i!Ky>O=Fs(Jw850D&Fu}Ae_%W&qWhI-!^)DTxtCL7!o$(FyP?a7SWIVM)k4t z({V$+NNc?8ahX-XevPMxgt6#Ty`k8^$AKS1t_SL|*E`0#a#y~x_2=BC856V3s;r+= zjz7j%l%^$Fw)2~#PTvp%En|`0ogMB^dWfj{vKMm!|GL6G;n{Y@BmDvukOjN-u#D!o zX4RJb?H{|VkuM`$Cn2rj5htsL9Q!b1Q+#{Pdz;&cUn3mU+QB72{QF5u$m+SlbLu)Z zI%F{k$dJUk(&z=I!nOf9fUI6}(OUDIX1xX;)~{W84(pM{dA3nem82RU(s@z7Mzl~A zELvCb&345JA>$+JaO^_;HLn}Pc@=(;VWsB?aYg8xR6Xc@s&GmG<Rv3;>L z1(-sDVuRB3!{Q7S$0IDc`Kd%!W@Y9*>$suVq4aaK`W7Fp2waqrUS_LOi`5m#zQxAT zy9tP*Dks9e&12#+w$62FH7F*oq@%1Tq>cT@Y4@^qx7|c}aFy?K+h-GK z1R*BUWwl_sJ^T1!y)8Cn^+jY3&w!ihJB8zqv zraj&f94BpFpvMKi6mBkV=2Ew*=>w|+_pDTrcL`&m4UxF@{q#@1WfcRxPgO3M>(Zh_ zr)~{2jjff>mBG85q!y?@qXL6IzxjdyA@*~c;Z9A9Q9EwcRx3@ap?1jI4Nat<$EO{8 z?!H@Cij<7>zihuZIE)*cjOzS(ZSKYb&FRQHz5!u9A!p_+Y2lZD^_P*A%4RKf2~9jf zH#lqtw!1vjQW6ed@%ow{T{AED+jUC5++;Q_OJ-!BzU96^p6$&=k9=r7ZGe(Vt?hn# zkoo6R5@)Y$rfgRHnfU#TI~iqVU&{h6VfL|m#Gh+B^RfB=L{~)>?y_FpmX4mMIcRJB zd3X>!HNvv{RZVSn-h3H89KFe*&FHL!B;aNzWg>gRMs_bP?srA7`4*EXX{3{{E)kXit0%VN*LHQdRb&p|%%g#(4j}*_DE41KAHPNI9S%?6jqUMPxI1`)Yp^F^9Ne5TB0WphqKb?dRjH!oG*uq;_6^< h&h><9yhiu7$b7`P4vD7uDClRvEg){s%~7?P&l2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_unpressed_color_corrected.png b/src/main/resources/assets/vendingmachine/textures/gui/background/trade_button_unpressed_color_corrected.png new file mode 100644 index 0000000000000000000000000000000000000000..13c9e0107d5860a4bad8cc3bcaff39113a2bc9bc GIT binary patch literal 3280 zcmds3`6JU0AO9c|a?Bhpa^;wE4LOr*7!q?0p-D(#!{i)t-``Locdp_q3C+E!?pZM+IY`J1`O9!tZqts(fVe8c28TdpRGd|U%|(?OWYmc#$1$Ml*3Li?6Mi^e z!EBSeHPG4jAzS3US&_qt2Sp^xch4=tWDD^4B!>CJ4SUw8b0zk?^VFWiv=mPa3&Xi> zfXN$}!`0X8^V5tNa~Z?Gq?*}xgAN7^FSu_nO-nDPY4EhA zW?-NK)U&i^r8X(I7`#cmZZCGJ4jO(_6@X<<%P$95-}RPr%Y-RK%PocgbI5_)+hYp$ zLlnp$SI_W}qdbp9Wg=9{$vQqQ3z9NVp_o%sdWIA^)zU64z`x`|9faon0T0TF18;~A z^sTto7j+GFMISkzHrPa@^GROj;lpf~*vL&NLWI_JfR4!J0Nzx%H%`$Le7yJo=QRe) z*53(ai~^ASwk?p8;3wP??qb!wAnSRhdV1Q)jG^d(jKazmy@)f?;C490s_pyM57*$` zEcHx0+`vW6*CVt7(cM41fIB+3T$Df)Vfhm%%nv@1XiHRhVu%>5xFLEYyYW^(B#}8+ zKVFws^qj`k^`~sAIXmeq4Lp)<&sZ*YK{rAefL#WQvWDHgGO|Tr?=@yRBBzYz<`f)L zqW=)kO*j7Z^GiggyBQ;tns`vd>(5Ud8C669LtUm-UBMM5NXMCX9pEN_YmSLg50-ew z4+Ecz=6%e75EbB!YAingB)SG8{Sp*d3|5Iz#hu4La+_08XOVw2h&eOOV5P`e7$vjK zHl)iP8`saxXO(~#HRu<58)yGmaEXc80BkAr|=o1NLUF$5^PJO^+4m9N1P;7m<%9c09!~g>!GlT68^| z1KYFdJgNjoaf3Bqq$q;L#C2pzk^z)H7grxZD8SA0-g5&8LanRmW*NQs(e>EqC){;4T{NLR1hQDJA z;|}8qW7bM1#9UgyO z>ZBKm!62!uuVaz=mtEybGDnQm&6>=D^(1)q6K{6oUPLv;+nZcNT(c08Y?DMGJtS0R z9!ZG#h;2w0h<_I+iDnHL-R1JX=5S+1-&d+gY*xA*Reah0@)_7Ruicdi82+*oD!3vM ztzxrh=nWJBE3}+-zd2EZnV|CjuvoRvlK=ISiC5m`AL<${VovVj5)ll9LNe8%zsL z(?0s~$y_WE9A#Shxu-;Tr3ccrY~^e%Y};0)KB<1XQdRqD`DMt=)n`rhWa&`AE| z*yPUm$FZt0&C-3Fyw@8g1yv-2*#_-F#d+-YU)xh6@ zk}dl!F)hlWy`iYkxX_Kz!#!5I>~D$R7wIIrHAoXA24V))fQTHw;$^#dyPV^H$JeH% zrrk+ZJs$|wRc1G#5?Z`^ISx+Yid^Sj=IuTDEov(44ihZKUZr*9wen_JL$;eC-i?VW9(|HQO{7Y$Ra;^22%~U=~eLn<9P+`be3<#?8t^Hbg%DtNK@v!I5D)YB}na zZePdKM+CjHVrIQhdR)=uXv0ozF&q-pfAF|nJ;O~GnxcXl1tjs zD9Hy6?~O&3H=0#8d2h;ZLJC>1EZEGgj|x-^iDs#%(%PmE&1VX)XYls2J@e7IH^jq@mzH` zm`Zuu+M_Z>nTYB}yme7}zL;&DwJW8jd5A3ZFI2>0nx}Tm2c>riyX`KI96OyyZx!Eq z^A3YAr+%c{j#QObhoaYNk3jj@eh4{q#2BYi5J{o1qeK zirtXi{N&oVY2rl~TArdH@=f?HDS*Yzcp&|m*0c5Zmab?NG3AZfTQf(f)0DHjWn<$i zA<%RmnT9qGtMS;V`1-juq_uYa*Ozg-N?Ww!p>Hi_iyYcc9|o1iClhiA8ppz_MrsF< zWO_@pN$IPGpIs625kDU#G7-q>WU}0IIrkb|by?sJ=0oS;Y;ffG_g?R6Y$frTFk^y5 zf^cLWZDYSnFCpxoH|Y%oPnxq2OJivnWYuX#KZ2)NKP0_?6y01d%D?_JaP{ZUrExcsS?E@Nl6F9i!h7tt_sG;PHJnoL^Ke}! zWM==Qj(u1l-Q}+Hddm{-RX|5X@gmEyh$iSFNGm}op+!Nt{B#^msx55g z$8C)DpJdFhp*~}0kWFHwf!3oHJ9-V37~o5pb_ft45SI$aNXf^~4+SGse%Cp#ifUh9 z)z;j`bjE18P1i~5xc}XYc)ucc6pb=}Rf8UO`e_xl0sw)E z0I-Sy0L>f#5WwZPpst+`tT?1Y006M_{1*&k-y=>=OF_J$J>DAYfe&)^cLxmIy#qo5 zM6L0GcfGKpHdw58XXSi205D9OAoOg4^EamJ%=s;OqehP();$DR6#W2GPk$ysQ;?`D zAOpT1)XX1#C$TPWL8r21;DPV%kB3|9n?pnS0fj70qOD-Vt_2)j-{Cg$cgw~|5#(87oriYAW}H(a+H05c)Z z{V!&z9ZtjNm|X%To)^6nmB=9ee`=PoXO(;2v<3`Mt>uZ-3eRW0?^aYkO_bZOXF?={ v!-9xv^{rIN_*|;!jGuI{Kx>$XM+DOpSF}DVnqA}c8~_u;n~2x?nCSliI3Ms} literal 0 HcmV?d00001 From 9f9134475dc15b83ccb12d78f941c31ef571667b Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 11 Sep 2025 01:41:06 +0800 Subject: [PATCH 27/40] Changed trading to server authoritative model --- .../blocks/MTEVendingMachine.java | 28 +++++++++++++------ .../blocks/gui/MTEVendingMachineGui.java | 3 -- .../blocks/gui/TradeItemDisplay.java | 11 ++------ .../blocks/gui/TradeMainPanel.java | 6 +--- .../network/handlers/NetTradeRequestSync.java | 13 +++++++-- .../vendingmachine/trade/TradeDatabase.java | 4 +-- .../vendingmachine/trade/TradeRequest.java | 20 +++++++++++++ 7 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index c461fe3..66cb30b 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -23,7 +23,9 @@ import com.cubefury.vendingmachine.network.handlers.NetAvailableTradeSync; import com.cubefury.vendingmachine.network.handlers.NetTradeRequestSync; import com.cubefury.vendingmachine.network.handlers.NetTradeStateSync; +import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.trade.TradeRequest; import com.cubefury.vendingmachine.util.BigItemStack; import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; @@ -82,7 +84,7 @@ public class MTEVendingMachine extends MTEMultiBlockBase public ItemStackHandler outputItems = new ItemStackHandler(OUTPUT_SLOTS); public Queue outputBuffer = new ConcurrentLinkedQueue<>(); - public final Queue pendingTrades = new LinkedBlockingQueue<>(); + public final Queue pendingTrades = new LinkedBlockingQueue<>(); private boolean newBufferedOutputs = false; private int ticksSinceOutput = 0; @@ -103,7 +105,8 @@ public void sendTradeRequest(TradeItemDisplay trade) { baseTile.getZCoord()); } - public void addTradeRequest(TradeItemDisplay trade) { + public void addTradeRequest(TradeRequest trade) { + VendingMachine.LOG.info("received new trade request"); this.pendingTrades.add(trade); } @@ -174,11 +177,11 @@ public void dispenseItems() { this.newBufferedOutputs = false; } - private boolean processTradeOnServer(TradeItemDisplay trade) { + private boolean processTradeOnServer(TradeRequest tradeRequest) { if ( - trade == null || !TradeDatabase.INSTANCE.getTradeGroups() - .get(trade.tgID) - .canExecuteTrade(trade.playerID) + tradeRequest == null || !TradeDatabase.INSTANCE.getTradeGroups() + .get(tradeRequest.tradeGroup) + .canExecuteTrade(tradeRequest.player) ) { return false; } @@ -188,6 +191,9 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { inputSlots[i] = curStack == null ? null : curStack.copy(); } + Trade trade = TradeDatabase.INSTANCE.getTradeGroupFromId(tradeRequest.tradeGroup) + .getTrades() + .get(tradeRequest.tradeGroupOrder); for (BigItemStack stack : trade.fromItems) { ItemStack requiredStack = stack.getBaseStack(); int requiredAmount = stack.stackSize; @@ -226,8 +232,8 @@ private boolean processTradeOnServer(TradeItemDisplay trade) { this.newBufferedOutputs = true; } TradeDatabase.INSTANCE.getTradeGroups() - .get(trade.tgID) - .executeTrade(trade.playerID); + .get(tradeRequest.tradeGroup) + .executeTrade(tradeRequest.player); return true; } @@ -388,6 +394,10 @@ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { @Override public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) { + if (getBaseMetaTileEntity() == null) { + VendingMachine.LOG.warn("Check machine failed as Base MTE is null"); + return false; + } return STRUCTURE_DEFINITION.check( this, "main", @@ -407,7 +417,7 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) { if ((aBaseMetaTileEntity.isClientSide()) && (aBaseMetaTileEntity.isActive())) { // spawn something maybe } - if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isActive()) { + if (aBaseMetaTileEntity.isServerSide()) { dispenseItems(); if (this.mUpdate++ % STRUCTURE_CHECK_TICKS == 0) { this.mMachine = checkMachine(aBaseMetaTileEntity, null); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index bb952a0..f2473f6 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -188,8 +188,6 @@ private void ejectItems() { for (int i = 0; i < MTEVendingMachine.INPUT_SLOTS; i++) { ItemStack stack = base.inputItems.getStackInSlot(i); if (stack != null) { - // TODO: There's still a race condition here where the stack size changes between these - // two null checks. Fix ItemStack extracted = base.inputItems.extractItem(i, stack.stackSize, false); if (extracted == null) { // if somehow it got pulled out already continue; @@ -389,7 +387,6 @@ public void attemptPurchase(TradeItemDisplay display) { } private void submitTradesToServer(TradeItemDisplay trade) { - VendingMachine.LOG.info("attempted trade for {}", trade.display); if (!trade.tradeableNow || !trade.enabled) { return; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java index 44eadfd..95548c0 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplay.java @@ -27,11 +27,10 @@ public class TradeItemDisplay { public boolean hasCooldown; public boolean enabled; public boolean tradeableNow; - public UUID playerID; // used to identify player who claimed a trade on the server public TradeItemDisplay(List fromItems, List toItems, ItemStack display, UUID tgID, int tradeGroupOrder, String label, long cooldown, String cooldownText, boolean hasCooldown, boolean enabled, - boolean tradeableNow, UUID playerID) { + boolean tradeableNow) { this.fromItems = fromItems; this.toItems = toItems; this.display = display; @@ -43,7 +42,6 @@ public TradeItemDisplay(List fromItems, List toItems this.hasCooldown = hasCooldown; this.enabled = enabled; this.tradeableNow = tradeableNow; - this.playerID = playerID; } public static TradeItemDisplay readFromNBT(NBTTagCompound nbt) { @@ -68,8 +66,7 @@ public static TradeItemDisplay readFromNBT(NBTTagCompound nbt) { nbt.getString("cooldownText"), nbt.getBoolean("hasCooldown"), nbt.getBoolean("enabled"), - nbt.getBoolean("tradeableNow"), - NBTConverter.UuidValueType.PLAYER.readId(nbt)); + nbt.getBoolean("tradeableNow")); } public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @@ -92,7 +89,6 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setBoolean("hasCooldown", this.hasCooldown); nbt.setBoolean("enabled", this.enabled); nbt.setBoolean("tradeableNow", this.tradeableNow); - NBTConverter.UuidValueType.PLAYER.writeId(this.playerID, nbt); return nbt; } @@ -113,8 +109,7 @@ public boolean equals(Object obj) { && this.cooldownText.equals(other.cooldownText) && this.hasCooldown == other.hasCooldown && this.enabled == other.enabled - && this.tradeableNow == other.tradeableNow - && this.playerID == other.playerID; + && this.tradeableNow == other.tradeableNow; } public boolean satisfiesSearch(ItemFilter filter, String searchStringNoCase) { diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 6add5b5..297b6ea 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -18,7 +18,6 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; -import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; @@ -38,7 +37,6 @@ public class TradeMainPanel extends ModularPanel { private final PosGuiData guiData; private EntityPlayer player = null; private int ticksOpen = 0; - private final UUID playerID; public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData guiData, PanelSyncManager syncManager) { @@ -46,7 +44,6 @@ public TradeMainPanel(@NotNull String name, MTEVendingMachineGui gui, PosGuiData this.gui = gui; this.guiData = guiData; this.syncManager = syncManager; - this.playerID = NameCache.INSTANCE.getUUIDFromPlayer(guiData.getPlayer()); } @Override @@ -177,8 +174,7 @@ public Map> formatTrades(List 0, tgw.enabled(), - checkItemsSatisfied(trade.fromItems, availableItems), - playerID); + checkItemsSatisfied(trade.fromItems, availableItems)); trades.get(category) .add(tid); diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java index 9e76ea4..cba5905 100644 --- a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java +++ b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java @@ -13,6 +13,9 @@ import com.cubefury.vendingmachine.blocks.gui.TradeItemDisplay; import com.cubefury.vendingmachine.network.PacketSender; import com.cubefury.vendingmachine.network.PacketTypeRegistry; +import com.cubefury.vendingmachine.storage.NameCache; +import com.cubefury.vendingmachine.trade.TradeRequest; +import com.cubefury.vendingmachine.util.NBTConverter; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; @@ -26,7 +29,8 @@ public static void registerHandler() { public static void sendTradeRequest(TradeItemDisplay trade, World world, int x, int y, int z) { NBTTagCompound payload = new NBTTagCompound(); - payload.setTag("trade", trade.writeToNBT(new NBTTagCompound())); + NBTConverter.UuidValueType.TRADEGROUP.writeId(trade.tgID, payload); + payload.setInteger("tradeGroupOrder", trade.tradeGroupOrder); payload.setInteger("dim", world.provider.dimensionId); payload.setInteger("x", x); payload.setInteger("y", y); @@ -50,9 +54,12 @@ public static void onServer(Tuple2 message) { && ((IGregTechTileEntity) te).getMetaTileEntity() instanceof MTEVendingMachine ) { ((MTEVendingMachine) ((IGregTechTileEntity) te).getMetaTileEntity()).addTradeRequest( - TradeItemDisplay.readFromNBT( + new TradeRequest( + NameCache.INSTANCE.getUUIDFromPlayer(message.second()), + NBTConverter.UuidValueType.TRADEGROUP.readId(message.first()), message.first() - .getCompoundTag("trade"))); + .getInteger("tradeGroupOrder"), + (MTEVendingMachine) ((IGregTechTileEntity) te).getMetaTileEntity())); } } } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index 861458c..e9c0dc5 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -13,8 +13,6 @@ import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.Constants; -import org.antlr.v4.misc.OrderedHashMap; - import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.integration.betterquesting.BqAdapter; import com.cubefury.vendingmachine.integration.nei.NeiRecipeCache; @@ -28,7 +26,7 @@ public class TradeDatabase { public static final TradeDatabase INSTANCE = new TradeDatabase(); public int version = -1; - private final Map tradeGroups = new OrderedHashMap<>(); + private final Map tradeGroups = new HashMap<>(); private final Map> tradeCategories = new HashMap<>(); private TradeDatabase() {} diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java new file mode 100644 index 0000000..7635d6f --- /dev/null +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java @@ -0,0 +1,20 @@ +package com.cubefury.vendingmachine.trade; + +import java.util.UUID; + +import com.cubefury.vendingmachine.blocks.MTEVendingMachine; + +public class TradeRequest { + + public UUID player; + public UUID tradeGroup; + public int tradeGroupOrder; + MTEVendingMachine target; + + public TradeRequest(UUID player, UUID tradeGroup, int tradeGroupOrder, MTEVendingMachine target) { + this.player = player; + this.tradeGroup = tradeGroup; + this.tradeGroupOrder = tradeGroupOrder; + this.target = target; + } +} From 5eb261b5049c67419e1f27e832c7c7ce81d723d1 Mon Sep 17 00:00:00 2001 From: cubefury Date: Thu, 11 Sep 2025 20:47:45 +0800 Subject: [PATCH 28/40] Fixed button overlays for trade status --- .../blocks/MTEVendingMachine.java | 6 ++--- .../blocks/gui/MTEVendingMachineGui.java | 18 -------------- .../blocks/gui/TradeItemDisplayWidget.java | 15 ++++++++++-- .../blocks/gui/TradeMainPanel.java | 23 +++++++++--------- .../vendingmachine/gui/GuiTextures.java | 7 +++--- .../network/handlers/NetTradeRequestSync.java | 1 + .../vendingmachine/trade/TradeRequest.java | 9 +++++-- .../textures/gui/overlay/trade_available.png | Bin 163 -> 0 bytes .../textures/gui/overlay/trade_disabled.png | Bin 159 -> 0 bytes 9 files changed, 39 insertions(+), 40 deletions(-) delete mode 100644 src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_available.png delete mode 100644 src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_disabled.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 66cb30b..07af9a7 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -181,7 +181,7 @@ private boolean processTradeOnServer(TradeRequest tradeRequest) { if ( tradeRequest == null || !TradeDatabase.INSTANCE.getTradeGroups() .get(tradeRequest.tradeGroup) - .canExecuteTrade(tradeRequest.player) + .canExecuteTrade(tradeRequest.playerID) ) { return false; } @@ -233,8 +233,8 @@ private boolean processTradeOnServer(TradeRequest tradeRequest) { } TradeDatabase.INSTANCE.getTradeGroups() .get(tradeRequest.tradeGroup) - .executeTrade(tradeRequest.player); - + .executeTrade(tradeRequest.playerID); + NetTradeStateSync.sendTradeState(tradeRequest.player, false); return true; } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index f2473f6..fe98e2b 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -12,7 +12,6 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; -import com.cleanroommc.modularui.drawable.DynamicDrawable; import com.cleanroommc.modularui.drawable.Rectangle; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; @@ -318,23 +317,6 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t } }) .tooltipAutoUpdate(true) - .overlay( - new DynamicDrawable(() -> { - if ( - index < displayedTrades.get(category).size() - && (displayedTrades.get(category).get(index).getDisplay().hasCooldown || !displayedTrades.get(category).get(index).getDisplay().enabled) - ) { - return GuiTextures.OVERLAY_TRADE_DISABLED; - } - if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).getDisplay().tradeableNow) { - return GuiTextures.OVERLAY_TRADE_AVAILABLE_HIGHLIGHT; - } - return null; }), - new DynamicDrawable(() -> { - if (index < displayedTrades.get(category).size() && displayedTrades.get(category).get(index).getDisplay().hasCooldown) { - return IKey.str(displayedTrades.get(category).get(index).getDisplay().cooldownText); - } - return null; })) .setEnabledIf(slot -> ((TradeItemDisplayWidget) slot).getDisplay() != null)); if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { tradeList.child(row); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java index 1e26262..5d22792 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.value.IValue; import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.DynamicDrawable; @@ -56,9 +57,19 @@ public TradeItemDisplay getDisplay() { public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { ItemStack item = value.getValue(); if (!Platform.isStackEmpty(item)) { - GuiDraw.drawText(" " + this.display.display.stackSize, 4, 9, 1.0f, 0x0, false); + GuiDraw.drawText(" " + this.display.display.stackSize, 4, 10, 1.0f, 0x0, false); GuiDraw.drawItem(item, 26, 4, 16, 16, context.getCurrentDrawingZ()); - + if (this.display.tradeableNow) { + GuiDraw.drawOutline(1, 1, 45, 23, 0x883CFF00, 2); + } + if (this.display.hasCooldown || !this.display.enabled) { + GuiDraw.drawRoundedRect(1, 1, 45, 23, 0xBB000000, 1, 1); + } + if (display.hasCooldown) { + this.overlay( + IKey.str(this.display.cooldownText) + .style(IKey.WHITE)); + } } } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 297b6ea..f9856cd 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -4,7 +4,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.stream.Collectors; import net.minecraft.entity.player.EntityPlayer; @@ -18,11 +17,11 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeCategory; -import com.cubefury.vendingmachine.trade.TradeDatabase; -import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; +import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -65,17 +64,17 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { - List testTGW = new ArrayList<>(); - for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() - .entrySet()) { - testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); - } - Map> trades = formatTrades(testTGW); - // TODO: SWAP BACK /* - * List trades = formatTrades( - * TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + * List testTGW = new ArrayList<>(); + * for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() + * .entrySet()) { + * testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + * } + * Map> trades = formatTrades(testTGW); */ + // TODO: SWAP BACK + Map> trades = formatTrades( + TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); gui.updateSlots(trades); } diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index b5e4265..b718f67 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -7,14 +7,15 @@ public final class GuiTextures { public static final UITexture OVERLAY_TRADE_AVAILABLE_HIGHLIGHT = UITexture.builder() .location(VendingMachine.MODID, "gui/overlay/trade_available") - .imageSize(18, 18) - .canApplyTheme() + .imageSize(47, 25) + .adaptable(6) .name("trade_available_highlight") .build(); public static final UITexture OVERLAY_TRADE_DISABLED = UITexture.builder() .location(VendingMachine.MODID, "gui/overlay/trade_disabled") - .imageSize(18, 18) + .imageSize(47, 25) + .adaptable(4) .canApplyTheme() .name("trade_disabled") .build(); diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java index cba5905..67a5ae6 100644 --- a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java +++ b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java @@ -55,6 +55,7 @@ public static void onServer(Tuple2 message) { ) { ((MTEVendingMachine) ((IGregTechTileEntity) te).getMetaTileEntity()).addTradeRequest( new TradeRequest( + message.second(), NameCache.INSTANCE.getUUIDFromPlayer(message.second()), NBTConverter.UuidValueType.TRADEGROUP.readId(message.first()), message.first() diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java index 7635d6f..4c64d0b 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeRequest.java @@ -2,17 +2,22 @@ import java.util.UUID; +import net.minecraft.entity.player.EntityPlayerMP; + import com.cubefury.vendingmachine.blocks.MTEVendingMachine; public class TradeRequest { - public UUID player; + public EntityPlayerMP player; + public UUID playerID; public UUID tradeGroup; public int tradeGroupOrder; MTEVendingMachine target; - public TradeRequest(UUID player, UUID tradeGroup, int tradeGroupOrder, MTEVendingMachine target) { + public TradeRequest(EntityPlayerMP player, UUID playerID, UUID tradeGroup, int tradeGroupOrder, + MTEVendingMachine target) { this.player = player; + this.playerID = playerID; this.tradeGroup = tradeGroup; this.tradeGroupOrder = tradeGroupOrder; this.target = target; diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_available.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/trade_available.png deleted file mode 100644 index 720054056dde7befb04382cd657fb08b836e6745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg`m7HxOnNnd0mS6qGJ; zjVKAuPb(=;EJ|f?PR%K Date: Thu, 11 Sep 2025 20:54:53 +0800 Subject: [PATCH 29/40] Fixed text overlay remaining on buttons after moving around. --- .../vendingmachine/blocks/gui/TradeItemDisplayWidget.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java index 5d22792..e4f34f6 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -65,11 +65,9 @@ public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { if (this.display.hasCooldown || !this.display.enabled) { GuiDraw.drawRoundedRect(1, 1, 45, 23, 0xBB000000, 1, 1); } - if (display.hasCooldown) { - this.overlay( - IKey.str(this.display.cooldownText) - .style(IKey.WHITE)); - } + this.overlay( + IKey.str(display.hasCooldown ? this.display.cooldownText : "") + .style(IKey.WHITE)); } } From 39501aabab5d6ecc715370d150e1ecfeb7c4141d Mon Sep 17 00:00:00 2001 From: cubefury Date: Fri, 12 Sep 2025 01:43:25 +0800 Subject: [PATCH 30/40] Added null check for empty vending machine categories --- .../blocks/MTEVendingMachine.java | 6 ++++- .../blocks/gui/MTEVendingMachineGui.java | 10 +++----- .../blocks/gui/TradeItemDisplayWidget.java | 2 +- .../blocks/gui/TradeMainPanel.java | 25 +++++++++++-------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 07af9a7..ff67fcb 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -7,6 +7,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue; +import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -272,7 +273,10 @@ protected boolean forceUseMui2() { @Override protected @NotNull MTEVendingMachineGui getGui() { - if (VendingMachine.proxy.isClient()) { + if ( + !Minecraft.getMinecraft() + .isIntegratedServerRunning() + ) { NetAvailableTradeSync.requestSync(); NetTradeStateSync.requestSync(); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index fe98e2b..5b5c0f7 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -264,10 +264,7 @@ private SlotGroupWidget createOutputSlots() { .key('I', index -> { ModularSlot ms = new ModularSlot(base.outputItems, index).accessibility(false, true) .slotGroup("outputSlotGroup"); - ms.changeListener((newItem, onlyAmountChanged, client, init) -> { - VendingMachine.LOG.info("Changed output slot"); - VendingMachine.LOG.info(base.outputItems.getStackInSlot(0)); - }); + ms.changeListener((newItem, onlyAmountChanged, client, init) -> {}); return new ItemSlot().slot(ms); }) .build(); @@ -382,8 +379,9 @@ public void resetForceRefresh() { public void updateSlots(Map> trades) { synchronized (displayedTrades) { for (Map.Entry> entry : displayedTrades.entrySet()) { - int displayedSize = trades.get(entry.getKey()) - .size(); + int displayedSize = trades.get(entry.getKey()) == null ? 0 + : trades.get(entry.getKey()) + .size(); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { if (i < displayedSize) { displayedTrades.get(entry.getKey()) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java index e4f34f6..a40be03 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -57,7 +57,7 @@ public TradeItemDisplay getDisplay() { public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { ItemStack item = value.getValue(); if (!Platform.isStackEmpty(item)) { - GuiDraw.drawText(" " + this.display.display.stackSize, 4, 10, 1.0f, 0x0, false); + GuiDraw.drawText(" " + this.display.display.stackSize, 4, 9, 1.0f, 0x0, false); GuiDraw.drawItem(item, 26, 4, 16, 16, context.getCurrentDrawingZ()); if (this.display.tradeableNow) { GuiDraw.drawOutline(1, 1, 45, 23, 0x883CFF00, 2); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index f9856cd..9a9028e 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; import net.minecraft.entity.player.EntityPlayer; @@ -17,11 +18,11 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; -import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeCategory; +import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; -import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -64,17 +65,19 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { + + List testTGW = new ArrayList<>(); + for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() + .entrySet()) { + testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + } + Map> trades = formatTrades(testTGW); + + // TODO: SWAP BACK /* - * List testTGW = new ArrayList<>(); - * for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() - * .entrySet()) { - * testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); - * } - * Map> trades = formatTrades(testTGW); + * Map> trades = formatTrades( + * TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); */ - // TODO: SWAP BACK - Map> trades = formatTrades( - TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); gui.updateSlots(trades); } From 58b9c4b8f4fa3048408cc5775acf407730f6e053 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sat, 13 Sep 2025 03:14:51 +0800 Subject: [PATCH 31/40] Fixed NEI integration --- .../cubefury/vendingmachine/ClientProxy.java | 6 +- .../vendingmachine/VendingMachine.java | 7 +- .../blocks/BlockVendingMachine.java | 66 --------------- .../blocks/ItemBlockVendingMachine.java | 28 ------- .../blocks/TileVendingMachine.java | 80 ------------------- .../integration/nei/IMCforNEI.java | 42 ---------- .../integration/nei/NEIConfig.java | 20 +++-- .../integration/nei/NeiRecipeHandler.java | 34 ++++++++ .../vendingmachine/items/VMItems.java | 12 ++- 9 files changed, 60 insertions(+), 235 deletions(-) delete mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/BlockVendingMachine.java delete mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/ItemBlockVendingMachine.java delete mode 100644 src/main/java/com/cubefury/vendingmachine/blocks/TileVendingMachine.java delete mode 100644 src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java diff --git a/src/main/java/com/cubefury/vendingmachine/ClientProxy.java b/src/main/java/com/cubefury/vendingmachine/ClientProxy.java index d92aff8..2e6bd39 100644 --- a/src/main/java/com/cubefury/vendingmachine/ClientProxy.java +++ b/src/main/java/com/cubefury/vendingmachine/ClientProxy.java @@ -1,8 +1,9 @@ package com.cubefury.vendingmachine; import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.common.MinecraftForge; -import com.cubefury.vendingmachine.integration.nei.IMCforNEI; +import com.cubefury.vendingmachine.integration.nei.NEIConfig; import cpw.mods.fml.client.FMLClientHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -13,14 +14,13 @@ public class ClientProxy extends CommonProxy { @Override public void preInit(FMLPreInitializationEvent event) { super.preInit(event); - - IMCforNEI.IMCSender(); } // Override CommonProxy methods here, if you want a different behaviour on the client (e.g. registering renders). // Don't forget to call the super methods as well. @Override public void init(FMLInitializationEvent event) { + MinecraftForge.EVENT_BUS.register(new NEIConfig()); super.init(event); } diff --git a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java index aea0677..9041006 100644 --- a/src/main/java/com/cubefury/vendingmachine/VendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/VendingMachine.java @@ -1,11 +1,8 @@ package com.cubefury.vendingmachine; -import net.minecraft.block.Block; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import com.cubefury.vendingmachine.blocks.BlockVendingMachine; import com.cubefury.vendingmachine.gui.WidgetThemes; import com.cubefury.vendingmachine.items.VMItems; import com.cubefury.vendingmachine.network.PacketTypeRegistry; @@ -43,8 +40,6 @@ public class VendingMachine { @Mod.Instance(MODID) public static VendingMachine instance; - public static Block vendingMachine = new BlockVendingMachine(); - public static boolean isBqLoaded = false; public static boolean isGtLoaded = false; public static boolean isAeLoaded = false; @@ -79,7 +74,6 @@ public void preInit(FMLPreInitializationEvent event) { @Mod.EventHandler // load "Do your mod setup. Build whatever data structures you care about. Register recipes." (Remove if not needed) public void init(FMLInitializationEvent event) { - proxy.init(event); isBqLoaded = Loader.isModLoaded("betterquesting"); isGtLoaded = Loader.isModLoaded("gregtech"); @@ -95,6 +89,7 @@ public void init(FMLInitializationEvent event) { VMItems.registerMultis(); } + proxy.init(event); } @Mod.EventHandler diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/BlockVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/BlockVendingMachine.java deleted file mode 100644 index 8a287b2..0000000 --- a/src/main/java/com/cubefury/vendingmachine/blocks/BlockVendingMachine.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.cubefury.vendingmachine.blocks; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockContainer; -import net.minecraft.block.material.Material; -import net.minecraft.client.renderer.texture.IIconRegister; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.IIcon; -import net.minecraft.world.World; - -import com.cubefury.vendingmachine.VendingMachine; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -public class BlockVendingMachine extends BlockContainer { - - private IIcon topIcon; - - public BlockVendingMachine() { - super(Material.iron); - this.setHardness(1); - this.setBlockName("vendingmachine.vending_machine"); - this.setBlockTextureName("vendingmachine:vending_machine"); - this.setCreativeTab(CreativeTabs.tabDecorations); - } - - @Override - public TileEntity createNewTileEntity(World worldIn, int meta) { - return new TileVendingMachine(); - } - - /** - * Called upon block activation (right click on the block.) - */ - @Override - public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, - float hitY, float hitZ) { - if (!world.isRemote) { - player.openGui(VendingMachine.instance, 0, world, x, y, z); - } - return true; - } - - @Override - public void breakBlock(World world, int x, int y, int z, Block block, int meta) { - TileVendingMachine vendingMachine = (TileVendingMachine) world.getTileEntity(x, y, z); - // TODO: Drop items in input slots. - } - - /** - * Gets the block's texture. Args: side, meta - */ - @SideOnly(Side.CLIENT) - public IIcon getIcon(int side, int meta) { - return (side == 0 || side == 1) ? topIcon : blockIcon; - } - - @SideOnly(Side.CLIENT) - public void registerBlockIcons(IIconRegister p_149651_1_) { - this.blockIcon = p_149651_1_.registerIcon(this.getTextureName() + "_side"); - this.topIcon = p_149651_1_.registerIcon(this.getTextureName() + "_top"); - } -} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/ItemBlockVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/ItemBlockVendingMachine.java deleted file mode 100644 index 2a35cd0..0000000 --- a/src/main/java/com/cubefury/vendingmachine/blocks/ItemBlockVendingMachine.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.cubefury.vendingmachine.blocks; - -import java.util.List; - -import net.minecraft.block.Block; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; - -import com.cubefury.vendingmachine.util.Translator; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -public class ItemBlockVendingMachine extends ItemBlock { - - public ItemBlockVendingMachine(Block block) { - super(block); - } - - @Override - @SideOnly(Side.CLIENT) - public void addInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean f3_h) { - tooltip.add(""); - tooltip.add("§o" + Translator.translate("tooltip.vendingmachine")); - } - -} diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/TileVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/TileVendingMachine.java deleted file mode 100644 index fb33224..0000000 --- a/src/main/java/com/cubefury/vendingmachine/blocks/TileVendingMachine.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.cubefury.vendingmachine.blocks; - -import java.util.List; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; - -import com.cubefury.vendingmachine.VendingMachine; -import com.cubefury.vendingmachine.trade.TradeGroupWrapper; - -public class TileVendingMachine extends TileEntity implements IInventory { - - public List visibleTrades; - - public TileVendingMachine() { - super(); - } - - @Override - public int getSizeInventory() { - return 0; - } - - @Override - public ItemStack getStackInSlot(int idx) { - return null; - } - - @Override - public ItemStack decrStackSize(int index, int count) { - return null; - } - - @Override - public ItemStack getStackInSlotOnClosing(int index) { - return null; - } - - @Override - public void setInventorySlotContents(int index, ItemStack stack) {} - - @Override - public String getInventoryName() { - return VendingMachine.vendingMachine.getLocalizedName(); - } - - @Override - public boolean hasCustomInventoryName() { - return false; - } - - @Override - public int getInventoryStackLimit() { - return 0; - } - - @Override - public boolean isUseableByPlayer(EntityPlayer player) { - return player.getDistanceSq(this.xCoord, this.yCoord, this.zCoord) < 256; - } - - @Override - public void openInventory() {} - - @Override - public void closeInventory() {} - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) { - return false; - } - - @Override - public void updateEntity() { - return; - } - -} diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java deleted file mode 100644 index b91a524..0000000 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/IMCforNEI.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.cubefury.vendingmachine.integration.nei; - -import net.minecraft.nbt.NBTTagCompound; - -import com.cubefury.vendingmachine.VendingMachine; - -import cpw.mods.fml.common.event.FMLInterModComms; - -public class IMCforNEI { - - public static void IMCSender() { - - sendCatalyst("vendingmachine", "vendingmachine:gt.blockmachines.multimachine.vendingmachine"); - sendHandler("vendingmachine", "vendingmachine:gt.blockmachines.multimachine.vendingmachine"); - } - - private static void sendHandler(String name, String itemStack) { - NBTTagCompound nbt = new NBTTagCompound(); - nbt.setString("handler", name); - nbt.setString("modName", VendingMachine.NAME); - nbt.setString("modId", VendingMachine.MODID); - nbt.setBoolean("modRequired", true); - nbt.setString("itemName", itemStack); - nbt.setInteger("handlerHeight", 105); - nbt.setInteger("handlerWidth", 166); - nbt.setInteger("maxRecipesPerPage", 3); - nbt.setInteger("yShift", 0); - FMLInterModComms.sendMessage("NotEnoughItems", "registerHandlerInfo", nbt); - } - - private static void sendCatalyst(String name, String itemStack, int priority) { - NBTTagCompound nbt = new NBTTagCompound(); - nbt.setString("handlerID", name); - nbt.setString("itemName", itemStack); - nbt.setInteger("priority", priority); - FMLInterModComms.sendMessage("NotEnoughItems", "registerCatalystInfo", nbt); - } - - private static void sendCatalyst(String name, String itemStack) { - sendCatalyst(name, itemStack, 0); - } -} diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java index 0877a12..2aad5ac 100644 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java +++ b/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java @@ -1,22 +1,22 @@ package com.cubefury.vendingmachine.integration.nei; -import java.util.ArrayList; -import java.util.List; - import com.cubefury.vendingmachine.Tags; import com.cubefury.vendingmachine.VendingMachine; +import com.cubefury.vendingmachine.items.VMItems; import codechicken.nei.api.API; import codechicken.nei.api.IConfigureNEI; +import codechicken.nei.event.NEIRegisterHandlerInfosEvent; +import codechicken.nei.recipe.HandlerInfo; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class NEIConfig implements IConfigureNEI { - public static List instances = new ArrayList<>(); - @Override public void loadConfig() { - API.registerRecipeHandler(new NeiRecipeHandler()); - API.registerUsageHandler(new NeiRecipeHandler()); + NeiRecipeHandler handler = new NeiRecipeHandler(); + API.addRecipeCatalyst(VMItems.vendingMachine, "vendingmachine", 0); + handler.addHandler(); } @Override @@ -29,4 +29,10 @@ public String getVersion() { return Tags.VERSION; } + @SubscribeEvent + public void registerHandlerInfo(NEIRegisterHandlerInfosEvent event) { + event.registerHandlerInfo( + new HandlerInfo.Builder("vendingmachine", VendingMachine.NAME, VendingMachine.MODID).setMaxRecipesPerPage(3) + .build()); + } } diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java index bb0e3d8..b72ea6c 100644 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java +++ b/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java @@ -43,9 +43,13 @@ import codechicken.lib.gui.GuiDraw; import codechicken.nei.NEIServerUtils; import codechicken.nei.PositionedStack; +import codechicken.nei.api.API; +import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipe; import codechicken.nei.recipe.TemplateRecipeHandler; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Optional; +import cpw.mods.fml.common.event.FMLInterModComms; public class NeiRecipeHandler extends TemplateRecipeHandler { @@ -63,6 +67,19 @@ public class NeiRecipeHandler extends TemplateRecipeHandler { private Rectangle lastHoveredTextArea = null; private UUID lastHoveredQuestId = null; + public NeiRecipeHandler() {} + + public void addHandler() { + FMLInterModComms.sendRuntimeMessage( + FMLCommonHandler.instance() + .findContainerFor(VendingMachine.MODID), + "NEIPlugins", + "register-crafting-handler", + "vendingmachine@" + this.getRecipeName() + "@" + this.getOverlayIdentifier()); + GuiCraftingRecipe.craftinghandlers.add(this); + API.registerUsageHandler(this); + } + private UUID getCurrentPlayerUUID() { if (currentPlayerId == null) { currentPlayerId = NameCache.INSTANCE.getUUIDFromPlayer(Minecraft.getMinecraft().thePlayer); @@ -287,6 +304,19 @@ public void drawExtras(int recipeIndex) { y += LINE_SPACE; } } + + // some test code to replace the header of the NEI display + /* + * GL11.glPushMatrix(); + * RenderHelper.enableGUIStandardItemLighting(); + * Minecraft mc = Minecraft.getMinecraft(); + * RenderItem renderItem = new RenderItem(); + * renderItem.renderItemAndEffectIntoGUI(mc.fontRenderer, mc.getTextureManager(), VMItems.vendingMachine, 3, 3); + * renderItem.renderItemOverlayIntoGUI(mc.fontRenderer, mc.getTextureManager(), VMItems.vendingMachine, 3, 3); + * RenderHelper.disableStandardItemLighting(); + * GL11.glPopMatrix(); + */ + } public class CachedTradeRecipe extends CachedRecipe { @@ -344,4 +374,8 @@ public List getOtherStacks() { } } + @Override + public void loadTransferRects() { + transferRects.add(new RecipeTransferRect(new Rectangle(75, 0, 16, 24), getOverlayIdentifier())); + } } diff --git a/src/main/java/com/cubefury/vendingmachine/items/VMItems.java b/src/main/java/com/cubefury/vendingmachine/items/VMItems.java index bcc599d..5b478b5 100644 --- a/src/main/java/com/cubefury/vendingmachine/items/VMItems.java +++ b/src/main/java/com/cubefury/vendingmachine/items/VMItems.java @@ -1,5 +1,7 @@ package com.cubefury.vendingmachine.items; +import net.minecraft.item.ItemStack; + import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; @@ -7,11 +9,15 @@ public class VMItems { - private VMItems() {} + public static ItemStack vendingMachine; + + public VMItems() {} @Optional.Method(modid = "gregtech") public static void registerMultis() { - new MTEVendingMachine(VendingMachine.CONTROLLER_MTE_ID, "multimachine.vendingmachine", "Vending Machine") - .getStackForm(1); + vendingMachine = new MTEVendingMachine( + VendingMachine.CONTROLLER_MTE_ID, + "multimachine.vendingmachine", + "Vending Machine").getStackForm(1); } } From c7e72e425f1c8e56fdb125441870d233a099c225 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sat, 13 Sep 2025 17:53:46 +0800 Subject: [PATCH 32/40] Fixed NEI header icon --- .../vendingmachine/integration/nei/NEIConfig.java | 1 + .../integration/nei/NeiRecipeHandler.java | 13 ------------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java index 2aad5ac..9a16209 100644 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java +++ b/src/main/java/com/cubefury/vendingmachine/integration/nei/NEIConfig.java @@ -33,6 +33,7 @@ public String getVersion() { public void registerHandlerInfo(NEIRegisterHandlerInfosEvent event) { event.registerHandlerInfo( new HandlerInfo.Builder("vendingmachine", VendingMachine.NAME, VendingMachine.MODID).setMaxRecipesPerPage(3) + .setDisplayStack(VMItems.vendingMachine) .build()); } } diff --git a/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java b/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java index b72ea6c..6b5477e 100644 --- a/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java +++ b/src/main/java/com/cubefury/vendingmachine/integration/nei/NeiRecipeHandler.java @@ -304,19 +304,6 @@ public void drawExtras(int recipeIndex) { y += LINE_SPACE; } } - - // some test code to replace the header of the NEI display - /* - * GL11.glPushMatrix(); - * RenderHelper.enableGUIStandardItemLighting(); - * Minecraft mc = Minecraft.getMinecraft(); - * RenderItem renderItem = new RenderItem(); - * renderItem.renderItemAndEffectIntoGUI(mc.fontRenderer, mc.getTextureManager(), VMItems.vendingMachine, 3, 3); - * renderItem.renderItemOverlayIntoGUI(mc.fontRenderer, mc.getTextureManager(), VMItems.vendingMachine, 3, 3); - * RenderHelper.disableStandardItemLighting(); - * GL11.glPopMatrix(); - */ - } public class CachedTradeRecipe extends CachedRecipe { From bc232319e2782ebee624da91b868f821c02056e5 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 15:44:07 +0800 Subject: [PATCH 33/40] Added Sidebar and UI icons --- .../blocks/gui/MTEVendingMachineGui.java | 20 ++++++++++++++---- .../vendingmachine/gui/GuiTextures.java | 12 +++++++++++ .../vendingmachine/trade/TradeDatabase.java | 2 +- .../textures/gui/background/input.png | Bin 0 -> 1124 bytes .../textures/gui/background/output.png | Bin 0 -> 1089 bytes .../vendingmachine/textures/gui/icons/all.png | Bin 0 -> 441 bytes .../textures/gui/icons/bees.png | Bin 0 -> 700 bytes .../textures/gui/icons/chemistry.png | Bin 0 -> 310 bytes .../textures/gui/icons/components.png | Bin 0 -> 736 bytes .../textures/gui/icons/farming.png | Bin 0 -> 321 bytes .../textures/gui/icons/magic.png | Bin 0 -> 459 bytes .../vendingmachine/textures/gui/icons/raw.png | Bin 1121 -> 810 bytes .../textures/gui/nei_header.png | Bin 0 -> 135 bytes 13 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/input.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/output.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/all.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/chemistry.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/components.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/farming.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/magic.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/nei_header.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 5b5c0f7..c303074 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -128,7 +128,7 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { this.tradeCategories.get(i) .getTexture() .asIcon() - .margin(4) + .margin(6) .center()) .tooltipBuilder(builder -> { builder.clearText(); @@ -224,9 +224,15 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .widgetTheme(WidgetThemes.BACKGROUND_SIDEPANEL) .child( new Column().child( - new Row().child(createInputRow(syncManager).center()) - .top(20) - .height(18 * 3)) + GuiTextures.INPUT_SPRITE.asWidget() + .leftRel(0.5f) + .top(8) + .width(30) + .height(20)) + .child( + new Row().child(createInputRow(syncManager).center()) + .top(20) + .height(18 * 3)) .child( new Row().child( new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) @@ -235,6 +241,12 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .center()) .top(80) .height(18)) + .child( + GuiTextures.OUTPUT_SPRITE.asWidget() + .leftRel(0.5f) + .bottom(34) + .width(30) + .height(20)) .child( new Row().child(createOutputSlots().center()) .bottom(6) diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index b718f67..b7012a3 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -56,4 +56,16 @@ public final class GuiTextures { .adaptable(4) .name("trade_button_pressed") .build(); + + public static final UITexture INPUT_SPRITE = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/input") + .imageSize(30, 20) + .name("background_input") + .build(); + + public static final UITexture OUTPUT_SPRITE = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/output") + .imageSize(30, 20) + .name("background_output") + .build(); } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index e9c0dc5..e4689ce 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -54,7 +54,7 @@ public Map getTradeGroups() { public List getTradeCategories() { List tradeCategoryList = new ArrayList<>(tradeCategories.keySet()); - tradeCategoryList.sort(Comparator.comparing(TradeCategory::getKey)); + tradeCategoryList.sort(Comparator.comparing(TradeCategory::ordinal)); return tradeCategoryList; } diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/input.png b/src/main/resources/assets/vendingmachine/textures/gui/background/input.png new file mode 100644 index 0000000000000000000000000000000000000000..67cd44ccd73722a5a235a52e372625823831ed56 GIT binary patch literal 1124 zcmV-q1e^PbP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000B; zNklm_5D1)fSuY)8rcP)Vqi~a zXe3rZa=?+^5xrMzY469^5CLnyLO9JzYh>1Oo>0Rlk)XoU*2r7#$7^+lbE#F3=vx}z z5^n_(U&q0X3s9SZuu9q*Ipg$q>OtOBx12y!3W7-vYLYk6=y^LPa$ zgrE%J6gOKVN1X1cpXY$oKn-fOWK~MoT@*9%6K5_~sAt*6wjeO{gjh|y&XF(;G2QTdHgVbsW%51epzH~Yd z`Z+%H*Slsr3u?I^18FX*Uxb%o@s3cF8#!AU~l{Y zdA@4{V=ZB+MNJS^c)%Jt2ryDnqEe7r(+RE3Kr?`eoTwI54|2%Qfzlm;y=aZR3bB*R zIXva(dE3tsolpYvry#6ypEdFoz^x@EUU$?$t9=AsJ#W|OO9ekV4^0`if*X_za3E?z%SR>yTiYlE-Gffj}Gvuw2QlY4Z zb(#r3AC5uTEj6v3*I%*_`_Wa zQ*E1n4R*pe=qx9b{g7PgvYCRg$_NnX3_t301g)Qg`YeQ1Hd-Ucm(#r}*une#9Ou2B zsGA#qMV|*v&}$*l8+CVm4#H~t`uopd2T%BU>Pmx7NB=nzb#LuVv<@cQ7ybVRZjF(u q5(IQMT8C3W6Xs8mutu8yROfHAy7nRuVQF&!0000z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000Bb zNklo&5vx&5B*X+XlDca2 z#SqYh$4V2##ArfO2r4F|CKx|}2cyPLF#1vr>PYc}wrpE5(28KRo#}S34|BI))KWH{ zw>$To|L>mvnR|s&ic(^AzxW)e=rYyXQtCx1;MM)&W1s=Z13z||YQz5uj@OH+n~mu< zPWEIOPwj*1jp4^r^^n>JeJ{=`(fCida<2=lp%aDidZChg;oJ^b{tm=%2Lyb7C!}73 ziVXO@M0&F1=K@|A*mgxtPnO|jZ$R(!kZyzM5}*uzdI**u2APDy-_X5r?oQ_oPPcKv zsO9vTrV#M!RdPUKy%_{+M_qY4|hXd zJDhEX%9U)rctpKh%(Ggc`hF;@2xo5XfyhEKo}*5e1h!t$f-x=F3b|dNo%jwY^klhQ zwVr1ZFR|Z9gfp*ehv>}^404a>sFU*s+pgFoE#BAj0>Em4$RbvGj{0`$-yTb|>5miY z1KSl1#!|jIqh}tsAvg~~KM#72I(|*C?TRO4lD7;KL^%{jAsB>UfVG~ZzP4SlK$`qj zUIP?h{4)4CqMoDjwksM9lP`<}lu1x|2>QX#vBh(y&wLu#cExjY8E;A}T&r>L`yd#g z(Q}k*yFy5dLU|QLZVYqAETsw0#M-R!0+Q}&r$7Hfo)gpimhOe zu~b8Yupk)ZUe8gV0j$aiRVE?2c)D$4zk?csE^`9jWSAV2CWvU56AZxUS$24idKExq zI;jM9R@}nwqTm#ZCZM(}UWl#W_2R*1h8Ax29CbkFKOilR%Op^ybI!x)&+G>FicBZ1 z@eDhQ)~SNFx1T1@Q75#>_E?$&hB-U57=8}?UbcCTI;`s+l@>>3O53hSGty0qSaS&# zslKYyM?6P;sEaqt6df`-H*^Bt3x1A=Jx6_{>mQRz-jmj3=lM$@)(oK{i~h6dK56mE zRJ*PfQx4zgIpMQuyJE9U(jim2>md+#^`WGxZ92!}o}-TF;wl1s{SO z1iyv%Uh6$6Qyh}XaFk-@FDMZOzi;xc*{-<5NN}nY=mdQ7{@?03s$1)BlPTU-V;UR` z@|5SOLwa+GQOo)0Vklow^luhrF=IV5N5J?M7`q6;01G`w{i*e{(qzBLbh6!Z)It5R zMw$$lRfaDQgpY{I&jFp~P@)_}WU}+Z2>3Z}@EmnTbDsSdcJRj^<3ZP900000NkvXX Hu0mjfHJ$$x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/all.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/all.png new file mode 100644 index 0000000000000000000000000000000000000000..20ae98fc1e6bbac51b5b6018b56035c12b66c6cb GIT binary patch literal 441 zcmV;q0Y?6bP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0003* zNkly=%g+V8AW^8P#l1}H8BS|lpApVwvrIEt?8 zQZxb98!G8`UF@xn(MxGGf^<#B!Ob@S@WCB(A1%|s+Cm946C)I5LEFYIj*kxc;QD40 zlT*`ZnMR^?dA@?{hY$d;vDJhqO7J`vm*?&L!q1Pl1R5{$JeOjkC>1Y^qw%8j$}MD} z_jk8gTv{2zt}fbm?R3!Z_p+Z23q3nMfikBiiU1(^2{2o$;rZz?AB>|>VOCLkxSvD4 jp%UNsF&KoIMd|qk*M|P#3=PCb00000NkvXXu0mjf6-~3Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png new file mode 100644 index 0000000000000000000000000000000000000000..09fad74fa093a8e95071c41a8569b931dcd28d74 GIT binary patch literal 700 zcmV;t0z>_YP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0006< zNklt3*URUii-Njl)9m52b95v4)>EnaZ)J|E?5HVj&j0_CT!4`n)n%>K)Gl$5I-^Tq~ zBTknatv;A*CAq}!O{1-|onniF@UB*Z`~zuwXv;|%aaq#3A7enQU4Z{(erg#e;@E3u7* zd8fT>uyqe!NL9r}W(qFhD9AuD6nbk>y_Iy>!-*8Gg*nvg^va8Y?rVv+=~*=$%X iW-)(1|Ne^qHh%z6nHcc18Qb*$0000tDas$58mx!DC0G)nledH;ICzeVMdjJ@`n6-#pUxJUjJDX3-kmdKI;Vst E0RIJgi~s-t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/components.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/components.png new file mode 100644 index 0000000000000000000000000000000000000000..23359d75d5dd87fc1fc218def1f22367695308af GIT binary patch literal 736 zcmV<60w4W}P)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0007O zNklf5|B2yp-R1$hxx@x6>nSmLirmEdK_ zmQ5cK#|fSiD%A#`?cKg|mzh$9u2nuc zmC?WBL-h~#qZq5noa6b^8H$BG;X=Rt8&ZHn&+&ZW#gdBWWDS(JjY3ul|}@W7!#F~%@{>74rF@Db_g z?BdUGfwqngPK_K@gI|3oY3ew0YPfmjCHTPS;^lnSu3L{Wn$Z(O@BSSAOWpwKAb0SO SjkgT|0000 z`?#LTu=|FZ$Ey!3Sld^we5mW;@rx_8nn7g}OQXAD*0h8P3r;){I>XZTfPZ_Bj`a23 z%hTikl{a;KI4>9zpc$%b_56rJfTrs?%O{n53yC9LbZ<8 z9Nue**}4o5iXsxrs~*Jd`Q6O0VDbdB-^Qmlxy)J?|Gc`{iqrELz>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT00042 zNkl_y@setK3 zh5+F8rGewS!vXZyps8!LxjF;kVIO}kH1!y%N&xvn8{9520Jz~*iZ3nnVBcW3EPL4o zw>b-{M&R1Yc51acD&8VeNtyWuO>8UgpyU5)V0Nhta9PPwd_ZN(SQCXtMEJNju&~#d3v3|6FkdY_P z$r44v49^V@O~;vt{d5ChI3y7m&}>aE^9@epJ^^f4wBe@>2Y~Y|{cF7h&jic}(S zWkPsS(M1`gg@m*~hfarPi{8Tv&G7wgIbC|(cD6as+4*%Ng{Yw6_Ye5oJP%=vVJjnR zfexo<+k^I2?;H?6rsoa!?3IiEe+@dE9--Fl^6N5oaI;Dr%Jc*)O4RZ-cPitX1|3e1 zzS`X$*nK!pJ2W z;sA64!FShB7_xNmj|33%s%U=t?jN{(nUsb$SAYR9nJn zbAuRmN{}YvIB~uJO?53uvzq1U;d#FKdDm)iy-KbWvNLz{@Ud|OM5|&~&K|VA@E|Fj zgLlXeSN-ReqpVlPP*EcIKCp#Hu1ebJ_!Q4SbwnQSpX7a$J|rY3$YX;Oe0#%})wkJb sCokqRrm9ex3R#iSR{wGBV{c`D0J11w@S&EeVX;&I$ z;`1%tP4=ezmDqt&RRNwrR005|?#{CH%=j<>pxfspss^w+nn-usQ9%t5e%G@*n?C>X ziUK@=D0S~$R(>=!4bik7Bt@f;PXhq5?4JMtgSiF(z~xu~5W0O%T5niOe-^l_VufRG z3h;2fP4^2$0=#(>04xT;$*w*3rN;XDE%tk;Y&s?^8}Q+`!_w8UDeT|138Dxj(lh%H z_f7x+NRk2o6uE5Kdt8o1>EoUT#V`X4ezlK4+sEU`>*7jZ_ODi6Zy;>-QVg0FET%VgbNXe{(y4xiPB*62+Mb zfjCK;Ci%$1PV%~VWp zvI78$++cgWPrv%X^hyFk?b|`pdYH_%huCYs z{i+H80F!3bs#jWDN99V$p-i9*IiVb({ZE3VwV()TLPP63jV}+K90=li(ux4DKdArg z%OPVa-FN1h*Fw(a0>0SS0)wS)!0gztbM#WUU%6lPGV=O^fBLh15!3mBi(het;$xyP zjTbsjs{%spPeBw5kN}vN23TwEh$SxcHc1r{sRB9=bP)cwebSDXI_*8-V_t!udgIwQ zPpATpx3>V0Kv9Nqd&AwqEpA^=&%v!14CZwNm%Fm`+fWYI6VDTo(;*1}(YUVpQ5$3E zC=|tJzL>*Qe>Q_;Dg}z70Z1SS0wk#eP3u3UX#HCmHaZLdo11r&gMA;}{QrRkUm$L? zJ^08rw}vXM5rv{qEb{sIKrB`&6$OH%K+{IvV%_-rUnAd5Ea|*ueix8K!x;^&HDbeR ujR1gGZm>F>#AGVE=;62Sm(hO)@Hb3AO5YPqSMC4+3IG5}MNUMnLSTX-$nxg^ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/nei_header.png b/src/main/resources/assets/vendingmachine/textures/gui/nei_header.png new file mode 100644 index 0000000000000000000000000000000000000000..963b277efc2ff01ad69c67a1fd87380fd626194c GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucK^adM#}EtuWCiv=>QX&f3Tz-eVRa+RfddQ- Y!uFn*ABOL-0jgv0boFyt=akR{0FtF4ga7~l literal 0 HcmV?d00001 From 83c091a39b27c71896b92f8a097c776e7d278edb Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 15:44:07 +0800 Subject: [PATCH 34/40] Added Sidebar and UI icons --- .../blocks/gui/MTEVendingMachineGui.java | 20 ++++++++++++++---- .../vendingmachine/gui/GuiTextures.java | 12 +++++++++++ .../vendingmachine/trade/TradeDatabase.java | 2 +- .../textures/gui/background/input.png | Bin 0 -> 1124 bytes .../textures/gui/background/output.png | Bin 0 -> 1089 bytes .../vendingmachine/textures/gui/icons/all.png | Bin 0 -> 441 bytes .../textures/gui/icons/bees.png | Bin 0 -> 700 bytes .../textures/gui/icons/chemistry.png | Bin 0 -> 310 bytes .../textures/gui/icons/components.png | Bin 0 -> 736 bytes .../textures/gui/icons/farming.png | Bin 0 -> 321 bytes .../textures/gui/icons/magic.png | Bin 0 -> 459 bytes .../textures/gui/icons/misc.png | Bin 0 -> 301 bytes .../vendingmachine/textures/gui/icons/raw.png | Bin 1121 -> 810 bytes .../textures/gui/nei_header.png | Bin 0 -> 135 bytes 14 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/input.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/background/output.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/all.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/chemistry.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/components.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/farming.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/magic.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/icons/misc.png create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/nei_header.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 5b5c0f7..c303074 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -128,7 +128,7 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { this.tradeCategories.get(i) .getTexture() .asIcon() - .margin(4) + .margin(6) .center()) .tooltipBuilder(builder -> { builder.clearText(); @@ -224,9 +224,15 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .widgetTheme(WidgetThemes.BACKGROUND_SIDEPANEL) .child( new Column().child( - new Row().child(createInputRow(syncManager).center()) - .top(20) - .height(18 * 3)) + GuiTextures.INPUT_SPRITE.asWidget() + .leftRel(0.5f) + .top(8) + .width(30) + .height(20)) + .child( + new Row().child(createInputRow(syncManager).center()) + .top(20) + .height(18 * 3)) .child( new Row().child( new ToggleButton().overlay(GTGuiTextures.OVERLAY_BUTTON_CYCLIC) @@ -235,6 +241,12 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .center()) .top(80) .height(18)) + .child( + GuiTextures.OUTPUT_SPRITE.asWidget() + .leftRel(0.5f) + .bottom(34) + .width(30) + .height(20)) .child( new Row().child(createOutputSlots().center()) .bottom(6) diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index b718f67..b7012a3 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -56,4 +56,16 @@ public final class GuiTextures { .adaptable(4) .name("trade_button_pressed") .build(); + + public static final UITexture INPUT_SPRITE = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/input") + .imageSize(30, 20) + .name("background_input") + .build(); + + public static final UITexture OUTPUT_SPRITE = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/output") + .imageSize(30, 20) + .name("background_output") + .build(); } diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index e9c0dc5..e4689ce 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -54,7 +54,7 @@ public Map getTradeGroups() { public List getTradeCategories() { List tradeCategoryList = new ArrayList<>(tradeCategories.keySet()); - tradeCategoryList.sort(Comparator.comparing(TradeCategory::getKey)); + tradeCategoryList.sort(Comparator.comparing(TradeCategory::ordinal)); return tradeCategoryList; } diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/input.png b/src/main/resources/assets/vendingmachine/textures/gui/background/input.png new file mode 100644 index 0000000000000000000000000000000000000000..67cd44ccd73722a5a235a52e372625823831ed56 GIT binary patch literal 1124 zcmV-q1e^PbP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000B; zNklm_5D1)fSuY)8rcP)Vqi~a zXe3rZa=?+^5xrMzY469^5CLnyLO9JzYh>1Oo>0Rlk)XoU*2r7#$7^+lbE#F3=vx}z z5^n_(U&q0X3s9SZuu9q*Ipg$q>OtOBx12y!3W7-vYLYk6=y^LPa$ zgrE%J6gOKVN1X1cpXY$oKn-fOWK~MoT@*9%6K5_~sAt*6wjeO{gjh|y&XF(;G2QTdHgVbsW%51epzH~Yd z`Z+%H*Slsr3u?I^18FX*Uxb%o@s3cF8#!AU~l{Y zdA@4{V=ZB+MNJS^c)%Jt2ryDnqEe7r(+RE3Kr?`eoTwI54|2%Qfzlm;y=aZR3bB*R zIXva(dE3tsolpYvry#6ypEdFoz^x@EUU$?$t9=AsJ#W|OO9ekV4^0`if*X_za3E?z%SR>yTiYlE-Gffj}Gvuw2QlY4Z zb(#r3AC5uTEj6v3*I%*_`_Wa zQ*E1n4R*pe=qx9b{g7PgvYCRg$_NnX3_t301g)Qg`YeQ1Hd-Ucm(#r}*une#9Ou2B zsGA#qMV|*v&}$*l8+CVm4#H~t`uopd2T%BU>Pmx7NB=nzb#LuVv<@cQ7ybVRZjF(u q5(IQMT8C3W6Xs8mutu8yROfHAy7nRuVQF&!0000z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT000Bb zNklo&5vx&5B*X+XlDca2 z#SqYh$4V2##ArfO2r4F|CKx|}2cyPLF#1vr>PYc}wrpE5(28KRo#}S34|BI))KWH{ zw>$To|L>mvnR|s&ic(^AzxW)e=rYyXQtCx1;MM)&W1s=Z13z||YQz5uj@OH+n~mu< zPWEIOPwj*1jp4^r^^n>JeJ{=`(fCida<2=lp%aDidZChg;oJ^b{tm=%2Lyb7C!}73 ziVXO@M0&F1=K@|A*mgxtPnO|jZ$R(!kZyzM5}*uzdI**u2APDy-_X5r?oQ_oPPcKv zsO9vTrV#M!RdPUKy%_{+M_qY4|hXd zJDhEX%9U)rctpKh%(Ggc`hF;@2xo5XfyhEKo}*5e1h!t$f-x=F3b|dNo%jwY^klhQ zwVr1ZFR|Z9gfp*ehv>}^404a>sFU*s+pgFoE#BAj0>Em4$RbvGj{0`$-yTb|>5miY z1KSl1#!|jIqh}tsAvg~~KM#72I(|*C?TRO4lD7;KL^%{jAsB>UfVG~ZzP4SlK$`qj zUIP?h{4)4CqMoDjwksM9lP`<}lu1x|2>QX#vBh(y&wLu#cExjY8E;A}T&r>L`yd#g z(Q}k*yFy5dLU|QLZVYqAETsw0#M-R!0+Q}&r$7Hfo)gpimhOe zu~b8Yupk)ZUe8gV0j$aiRVE?2c)D$4zk?csE^`9jWSAV2CWvU56AZxUS$24idKExq zI;jM9R@}nwqTm#ZCZM(}UWl#W_2R*1h8Ax29CbkFKOilR%Op^ybI!x)&+G>FicBZ1 z@eDhQ)~SNFx1T1@Q75#>_E?$&hB-U57=8}?UbcCTI;`s+l@>>3O53hSGty0qSaS&# zslKYyM?6P;sEaqt6df`-H*^Bt3x1A=Jx6_{>mQRz-jmj3=lM$@)(oK{i~h6dK56mE zRJ*PfQx4zgIpMQuyJE9U(jim2>md+#^`WGxZ92!}o}-TF;wl1s{SO z1iyv%Uh6$6Qyh}XaFk-@FDMZOzi;xc*{-<5NN}nY=mdQ7{@?03s$1)BlPTU-V;UR` z@|5SOLwa+GQOo)0Vklow^luhrF=IV5N5J?M7`q6;01G`w{i*e{(qzBLbh6!Z)It5R zMw$$lRfaDQgpY{I&jFp~P@)_}WU}+Z2>3Z}@EmnTbDsSdcJRj^<3ZP900000NkvXX Hu0mjfHJ$$x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/all.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/all.png new file mode 100644 index 0000000000000000000000000000000000000000..20ae98fc1e6bbac51b5b6018b56035c12b66c6cb GIT binary patch literal 441 zcmV;q0Y?6bP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0003* zNkly=%g+V8AW^8P#l1}H8BS|lpApVwvrIEt?8 zQZxb98!G8`UF@xn(MxGGf^<#B!Ob@S@WCB(A1%|s+Cm946C)I5LEFYIj*kxc;QD40 zlT*`ZnMR^?dA@?{hY$d;vDJhqO7J`vm*?&L!q1Pl1R5{$JeOjkC>1Y^qw%8j$}MD} z_jk8gTv{2zt}fbm?R3!Z_p+Z23q3nMfikBiiU1(^2{2o$;rZz?AB>|>VOCLkxSvD4 jp%UNsF&KoIMd|qk*M|P#3=PCb00000NkvXXu0mjf6-~3Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/bees.png new file mode 100644 index 0000000000000000000000000000000000000000..09fad74fa093a8e95071c41a8569b931dcd28d74 GIT binary patch literal 700 zcmV;t0z>_YP)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0006< zNklt3*URUii-Njl)9m52b95v4)>EnaZ)J|E?5HVj&j0_CT!4`n)n%>K)Gl$5I-^Tq~ zBTknatv;A*CAq}!O{1-|onniF@UB*Z`~zuwXv;|%aaq#3A7enQU4Z{(erg#e;@E3u7* zd8fT>uyqe!NL9r}W(qFhD9AuD6nbk>y_Iy>!-*8Gg*nvg^va8Y?rVv+=~*=$%X iW-)(1|Ne^qHh%z6nHcc18Qb*$0000tDas$58mx!DC0G)nledH;ICzeVMdjJ@`n6-#pUxJUjJDX3-kmdKI;Vst E0RIJgi~s-t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/components.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/components.png new file mode 100644 index 0000000000000000000000000000000000000000..23359d75d5dd87fc1fc218def1f22367695308af GIT binary patch literal 736 zcmV<60w4W}P)z>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT0007O zNklf5|B2yp-R1$hxx@x6>nSmLirmEdK_ zmQ5cK#|fSiD%A#`?cKg|mzh$9u2nuc zmC?WBL-h~#qZq5noa6b^8H$BG;X=Rt8&ZHn&+&ZW#gdBWWDS(JjY3ul|}@W7!#F~%@{>74rF@Db_g z?BdUGfwqngPK_K@gI|3oY3ew0YPfmjCHTPS;^lnSu3L{Wn$Z(O@BSSAOWpwKAb0SO SjkgT|0000 z`?#LTu=|FZ$Ey!3Sld^we5mW;@rx_8nn7g}OQXAD*0h8P3r;){I>XZTfPZ_Bj`a23 z%hTikl{a;KI4>9zpc$%b_56rJfTrs?%O{n53yC9LbZ<8 z9Nue**}4o5iXsxrs~*Jd`Q6O0VDbdB-^Qmlxy)J?|Gc`{iqrELz>%8+1ijbW?9;ba!ELWdK8EY;$>YAX9X8WNB|8RBvx=!KdMT00042 zNkl_y@setK3 zh5+F8rGewS!vXZyps8!LxjF;kVIO}kH1!y%N&xvn8{9520Jz~*iZ3nnVBcW3EPL4o zw>b-{M&R1Yc51acD&8VeNtyWuO>8UgpyU5)V0Nhta9PPwd_ZN(SQCXtMEJNju&~#d3v3|6FkdY_P z$r44v49^V@O~;vt{d5ChI3y7m&}>aE^9@epJ^^f4wBe@>2Y~_DQMw!jNZkq>$qsQz;kv5v3n0+-;)0U^aF#ZtDnm{r-UW|yti;S literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/vendingmachine/textures/gui/icons/raw.png b/src/main/resources/assets/vendingmachine/textures/gui/icons/raw.png index 6904d2fd8eb427ac9cc8da283f78ce6f6c9a503d..5c7fe4c84ef983676230d597d2695895a85b050d 100644 GIT binary patch delta 762 zcmVY|{cF7h&jic}(S zWkPsS(M1`gg@m*~hfarPi{8Tv&G7wgIbC|(cD6as+4*%Ng{Yw6_Ye5oJP%=vVJjnR zfexo<+k^I2?;H?6rsoa!?3IiEe+@dE9--Fl^6N5oaI;Dr%Jc*)O4RZ-cPitX1|3e1 zzS`X$*nK!pJ2W z;sA64!FShB7_xNmj|33%s%U=t?jN{(nUsb$SAYR9nJn zbAuRmN{}YvIB~uJO?53uvzq1U;d#FKdDm)iy-KbWvNLz{@Ud|OM5|&~&K|VA@E|Fj zgLlXeSN-ReqpVlPP*EcIKCp#Hu1ebJ_!Q4SbwnQSpX7a$J|rY3$YX;Oe0#%})wkJb sCokqRrm9ex3R#iSR{wGBV{c`D0J11w@S&EeVX;&I$ z;`1%tP4=ezmDqt&RRNwrR005|?#{CH%=j<>pxfspss^w+nn-usQ9%t5e%G@*n?C>X ziUK@=D0S~$R(>=!4bik7Bt@f;PXhq5?4JMtgSiF(z~xu~5W0O%T5niOe-^l_VufRG z3h;2fP4^2$0=#(>04xT;$*w*3rN;XDE%tk;Y&s?^8}Q+`!_w8UDeT|138Dxj(lh%H z_f7x+NRk2o6uE5Kdt8o1>EoUT#V`X4ezlK4+sEU`>*7jZ_ODi6Zy;>-QVg0FET%VgbNXe{(y4xiPB*62+Mb zfjCK;Ci%$1PV%~VWp zvI78$++cgWPrv%X^hyFk?b|`pdYH_%huCYs z{i+H80F!3bs#jWDN99V$p-i9*IiVb({ZE3VwV()TLPP63jV}+K90=li(ux4DKdArg z%OPVa-FN1h*Fw(a0>0SS0)wS)!0gztbM#WUU%6lPGV=O^fBLh15!3mBi(het;$xyP zjTbsjs{%spPeBw5kN}vN23TwEh$SxcHc1r{sRB9=bP)cwebSDXI_*8-V_t!udgIwQ zPpATpx3>V0Kv9Nqd&AwqEpA^=&%v!14CZwNm%Fm`+fWYI6VDTo(;*1}(YUVpQ5$3E zC=|tJzL>*Qe>Q_;Dg}z70Z1SS0wk#eP3u3UX#HCmHaZLdo11r&gMA;}{QrRkUm$L? zJ^08rw}vXM5rv{qEb{sIKrB`&6$OH%K+{IvV%_-rUnAd5Ea|*ueix8K!x;^&HDbeR ujR1gGZm>F>#AGVE=;62Sm(hO)@Hb3AO5YPqSMC4+3IG5}MNUMnLSTX-$nxg^ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/nei_header.png b/src/main/resources/assets/vendingmachine/textures/gui/nei_header.png new file mode 100644 index 0000000000000000000000000000000000000000..963b277efc2ff01ad69c67a1fd87380fd626194c GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucK^adM#}EtuWCiv=>QX&f3Tz-eVRa+RfddQ- Y!uFn*ABOL-0jgv0boFyt=akR{0FtF4ga7~l literal 0 HcmV?d00001 From 8b938b5396ed18eed34dbbabe75e75957b15d91b Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 16:27:58 +0800 Subject: [PATCH 35/40] Fixed sidebar looking weird --- .../blocks/gui/MTEVendingMachineGui.java | 2 +- .../blocks/gui/TradeMainPanel.java | 28 ++++++++++-------- .../vendingmachine/gui/GuiTextures.java | 5 ++++ .../vendingmachine/textures/gui/tabs_left.png | Bin 0 -> 3140 bytes 4 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index c303074..eb70460 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -123,7 +123,7 @@ public IWidget createCategoryTabs(PagedWidget.Controller tabController) { for (int i = 0; i < this.tradeCategories.size(); i++) { int index = i; tabColumn.child( - new PageButton(i, tabController).tab(com.cleanroommc.modularui.drawable.GuiTextures.TAB_LEFT, -1) + new PageButton(i, tabController).tab(GuiTextures.TAB_LEFT, -1) .overlay( this.tradeCategories.get(i) .getTexture() diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 9a9028e..390bdf5 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -18,11 +18,13 @@ import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cubefury.vendingmachine.Config; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.storage.NameCache; import com.cubefury.vendingmachine.trade.Trade; import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeGroupWrapper; +import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.Translator; @@ -65,20 +67,20 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { - - List testTGW = new ArrayList<>(); - for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() - .entrySet()) { - testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + boolean test = false; + if (test) { + List testTGW = new ArrayList<>(); + for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() + .entrySet()) { + testTGW.add(new TradeGroupWrapper(entry.getValue(), -1, true)); + } + Map> trades = formatTrades(testTGW); + gui.updateSlots(trades); + } else { + Map> trades = formatTrades( + TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); + gui.updateSlots(trades); } - Map> trades = formatTrades(testTGW); - - // TODO: SWAP BACK - /* - * Map> trades = formatTrades( - * TradeManager.INSTANCE.getTrades(NameCache.INSTANCE.getUUIDFromPlayer(syncManager.getPlayer()))); - */ - gui.updateSlots(trades); } @Override diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index b7012a3..0b308a0 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -1,5 +1,8 @@ package com.cubefury.vendingmachine.gui; +import com.cleanroommc.modularui.ModularUI; +import com.cleanroommc.modularui.api.GuiAxis; +import com.cleanroommc.modularui.drawable.TabTexture; import com.cleanroommc.modularui.drawable.UITexture; import com.cubefury.vendingmachine.VendingMachine; @@ -68,4 +71,6 @@ public final class GuiTextures { .imageSize(30, 20) .name("background_output") .build(); + + public static final TabTexture TAB_LEFT = TabTexture.of(UITexture.fullImage(VendingMachine.MODID, "gui/tabs_left", true), GuiAxis.X, false, 32, 28, 4); } diff --git a/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png b/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png new file mode 100644 index 0000000000000000000000000000000000000000..0c532c63b880212a322cf41a264edf3881e04bc5 GIT binary patch literal 3140 zcmXw*c|6qH8^^!M*s^a;WXm$jSSF1vWf=^TeP0@l^@f=kS;x-UuPu>1JJ+@E5!thh zJriZA5LrS@L-kYl^*iVFeBRIboadb9{CVPx?&&ZyUS1t`h<&@xX=y@doAmj2f{me{BJOpBw zLYGk*TYSdkLpKv@By$%sRr;D71Djq?3LpYUm|+pdsb%yq$VynTW@^1id^DAD{q_Yg zV)hZ1i!W2xsRq3KB4BSkXIbzh|&7>*XqVVY*KDC-IJ?1s#S+Mng5ojlHThzi{WBLvBP$Ce@4%s^e4b2EuT@O0+} z?6;|mI)4zxQ8GY$L$@yr{*gdOu!Bkenw0DH>ZK(+eX4?ok}{inlmeDe&HKSblkRtW zpB()U(-qTja+(ebUM_)Ui2mV;HSG6`>jea|Al*-20Uq`<(e7B83@yZH*)u$8)|tWKue8gOO0=nhO_5FOAmV+z`8<1 ztqzI3@CYTh62X;1g%IN93TrOBlo3&blBfXr7P8An!m*cd;pi24MLOy5QPhPcDic|j z{4mLV#xXUvsOVufZW97dNOPFKA=)a1?;{PZCc6=T2ECZ329lavZM)E3 zb`yfT+yO9awiX(@aZtDe>8{E$l=a%wv3t-qq6`)3lcRWhNA_Wgg3=MKJx{PS!EC!x zhJ8<0*sU1vgqO32v9T*ZPmpEjd8Mt9>MzQ`E?k|$Q9|vm_BKVJM6f*`nOZ(<%LUTX zk~6xS!Sq^?J9_PTW|2h^ytvAk&M2?q_N@6V;~EopN~&XYyvnbWpG}Cw67^^fvA|8_j{fOp*k z54je`AhsZmAX=4VeB{+N9JWRAzTK^RvDf>}S8T8nSW7Ht8~6psd$zqq)`7$Q(XY;A z?O@gr`a8)5!Vu0xhJT}w8rK}5MQM}Tiu!H({_3I}-(v6eW1ok$#aQXyLfkUs7wZ-? zM!JZ?CBsF9J%x89@fJX0x z1KLkITv7wEYnrRZ@sLx9D+Fy8Rb}XG+CJ+$tG#8trO2##ql|Xa#J#i$;}+Q@$sHe` zr`M#Hub1@t5x3-(BEBh_&Cf?LiX+9BqGAp;H#G0w5}$+5U9YO0TdxSH_&TRI`*u!y z_I>4zS^VtGY-^=o z!#|ljKRtgi^Ln~!TDka}SjPA6s%pQQQqTR=+`iV8}B>=Nf+Ub3i@)@ za(pnt_?0o*_0Dkubdu*Dk46G0f$uKIOnP>ohjX&cG&B;*1nrb6um)QV*m^c@wNl(X zF?n9^-0(v&4>;XS-Dc2-)iv4BH!Xw5Z|x53mfNd09ux6iu3kf}i)g=@{J#VryzK3M z^D{ECIC8jX+;MuUM{cTq{wpY9kP+?alIN$P5};J`Sb6#Qm>1xh}JGI6F+;u6~-b_!^bI|hs+yH8-CFdlVOuPMJKNk`!b{P zg2@c5OtlQ5mmE2b*`{8Gb)ZHfGHGi?xt(8SSnSZT9B;ssXKcc|__UuEZY5JkKg7OJ6-#cFxgK8%o7>r6B;16FqgxmDm zPuUjQ*0rE;r5mp)=95*W)q$4VwbC}K-Gi9%@aCvy_lKd7CTS^|;C5*jd&5+Vsb|mY zzlChuCUD1V4Jg3dJSrAr-$E7?+uV1{stg46{l$3oYxJ+{Eo0Wby2($*EuY-SzfEg$ zt{W@zAX;wjZbDXHe%FY;}q60qRxn=(2z4%)3F4YD{_S zQvqs%C_x}JhrIKxPn{6-cU^K5-j!_cN!MIl!ntMlUTN;hwAfDaw!rPn{!OhzrR5)j zM)ytxXH+eG>^}LE7+%Fa=PbClUXXkHiSO3u&mU*dUHXB0xpAsKH8L+S`yP{|!;N5K z-sh7qcLLsjJF91!;7xXLvj5WY5nJig6H@qr?o?12bOoeB;3ss*sMzm<^A&>E;!mH< zSa#Lsck*C&riaf`SGSGdVBRC!gu6yMzi(PlYBpMZyogKIKD_wWkNMMG@u$yD_(J4= z)Z1?fsovgFRo+MSMyjBf>Lur6XGk0`A#=xp?0=>^pPpSl zaOe6jyVJ3cB)^ybXE0fAm7729j?QLkbM9BXT=+G;>%50sIQn4;u61#E`ocKWX9c?L z`KvR_kMl;1#~buLpzsHk(bba%;$^$) zey|Ww8Tb^ie^Yv)#q*RKmA{d(RLw-yAmBh@F*;opJAc^kVU_R)Na{Zjg0lVQN-ChA z4KqlmbQ?1956LajHu#(XbJ~=MkWq9e%gWDD;^V1x>dWqOM5g`$Tvd z_KX(S2lr>_fsbi_}G+&12+!BbDGzB~FY2{Hp5BI14TRSeNrT2jf c`SETSupVERbz7BT;P*jYt$T=nHBb@%1D;gDL;wH) literal 0 HcmV?d00001 From 6c615af862e42f8a420a676b2213c378abba779b Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 16:28:24 +0800 Subject: [PATCH 36/40] Spotless --- .../java/com/cubefury/vendingmachine/gui/GuiTextures.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index 0b308a0..5892355 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -1,6 +1,5 @@ package com.cubefury.vendingmachine.gui; -import com.cleanroommc.modularui.ModularUI; import com.cleanroommc.modularui.api.GuiAxis; import com.cleanroommc.modularui.drawable.TabTexture; import com.cleanroommc.modularui.drawable.UITexture; @@ -72,5 +71,6 @@ public final class GuiTextures { .name("background_output") .build(); - public static final TabTexture TAB_LEFT = TabTexture.of(UITexture.fullImage(VendingMachine.MODID, "gui/tabs_left", true), GuiAxis.X, false, 32, 28, 4); + public static final TabTexture TAB_LEFT = TabTexture + .of(UITexture.fullImage(VendingMachine.MODID, "gui/tabs_left", true), GuiAxis.X, false, 32, 28, 4); } From 118fda336806d4dd4038f711d95b667203e36a29 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 17:11:22 +0800 Subject: [PATCH 37/40] Fixed layout of trade panel --- .../blocks/gui/MTEVendingMachineGui.java | 17 +++++++++-------- .../blocks/gui/TradeMainPanel.java | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index eb70460..6e28b27 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -12,7 +12,6 @@ import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.api.widget.IWidget; -import com.cleanroommc.modularui.drawable.Rectangle; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; import com.cleanroommc.modularui.screen.UISettings; @@ -289,20 +288,20 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t .debugName("paged") .controller(tabController) .background(GuiTextures.TEXT_FIELD_BACKGROUND) - .padding(4) .heightRel(0.5f); for (TradeCategory category : this.tradeCategories) { ListWidget tradeList = new ListWidget<>().debugName("items").heightRel(1.0f) - .widthRel(1.0f).childSeparator(new Rectangle().setColor(0x0).asIcon().size(ROW_SEPARATOR_HEIGHT)) + .width(156) + .margin(1) .collapseDisabledChild(true); - Flow row = new TradeRow().height(ITEM_HEIGHT); + // Higher first row top margin + Flow row = new TradeRow().height(ITEM_HEIGHT).margin(1).marginTop(4); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { int index = i; displayedTrades.get(category).get(i).setRootPanel(rootPanel); - row.childPadding(5) - .child(displayedTrades.get(category).get(i) + row.child(displayedTrades.get(category).get(i) .tooltipDynamic(builder -> { builder.clearText(); synchronized (displayedTrades) { @@ -326,16 +325,18 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t } }) .tooltipAutoUpdate(true) - .setEnabledIf(slot -> ((TradeItemDisplayWidget) slot).getDisplay() != null)); + .setEnabledIf(slot -> ((TradeItemDisplayWidget) slot).getDisplay() != null) + .margin(2)); if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { tradeList.child(row); - row = new TradeRow().height(ITEM_HEIGHT); + row = new TradeRow().height(ITEM_HEIGHT).margin(1); } } if (row.hasChildren()) { tradeList.child(row); } + tradeList.child(new Row().height(2)); // bottom padding for last row paged.addPage(tradeList); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 390bdf5..9e23077 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -67,7 +67,7 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { - boolean test = false; + boolean test = true; if (test) { List testTGW = new ArrayList<>(); for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() From 93448c533a5b5c7aff2e58060ceb6ffe2824cb61 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 19:38:17 +0800 Subject: [PATCH 38/40] Added Ack for trade system to refresh UI --- .../blocks/MTEVendingMachine.java | 4 +++- .../blocks/gui/MTEVendingMachineGui.java | 12 ++++++------ .../blocks/gui/TradeMainPanel.java | 2 +- .../network/handlers/NetTradeRequestSync.java | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index ff67fcb..f7e3ebd 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -113,10 +113,12 @@ public void addTradeRequest(TradeRequest trade) { public void dispenseItems() { if (!this.pendingTrades.isEmpty()) { - if (!processTradeOnServer(this.pendingTrades.poll())) { + TradeRequest tradeRequest = this.pendingTrades.poll(); + if (!processTradeOnServer(tradeRequest)) { VendingMachine.LOG.warn( "Unable to complete trade. Either input items changed after trade submission, or a double click was sent."); } + NetTradeRequestSync.sendAck(tradeRequest.player); } if ( this.newBufferedOutputs diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index 6e28b27..d7bf19d 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -48,7 +48,7 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private final MTEVendingMachine base; private final int height; - public boolean forceRefresh = false; + public static boolean forceRefresh = false; private boolean ejectItems = false; private final Map> displayedTrades = new HashMap<>(); @@ -87,8 +87,8 @@ public MTEVendingMachine getBase() { return base; } - public void setForceRefresh() { - this.forceRefresh = true; + public static void setForceRefresh() { + forceRefresh = true; } @Override @@ -375,7 +375,7 @@ protected void registerSyncValues(PanelSyncManager syncManager) { public void attemptPurchase(TradeItemDisplay display) { submitTradesToServer(display); - this.forceRefresh = true; + forceRefresh = true; } private void submitTradesToServer(TradeItemDisplay trade) { @@ -385,8 +385,8 @@ private void submitTradesToServer(TradeItemDisplay trade) { base.sendTradeRequest(trade); } - public void resetForceRefresh() { - this.forceRefresh = false; + public static void resetForceRefresh() { + forceRefresh = false; } public void updateSlots(Map> trades) { diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 9e23077..390bdf5 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -67,7 +67,7 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { - boolean test = true; + boolean test = false; if (test) { List testTGW = new ArrayList<>(); for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() diff --git a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java index 67a5ae6..1fa532d 100644 --- a/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java +++ b/src/main/java/com/cubefury/vendingmachine/network/handlers/NetTradeRequestSync.java @@ -7,9 +7,11 @@ import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; +import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.api.network.UnserializedPacket; import com.cubefury.vendingmachine.api.util.Tuple2; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; +import com.cubefury.vendingmachine.blocks.gui.MTEVendingMachineGui; import com.cubefury.vendingmachine.blocks.gui.TradeItemDisplay; import com.cubefury.vendingmachine.network.PacketSender; import com.cubefury.vendingmachine.network.PacketTypeRegistry; @@ -17,6 +19,8 @@ import com.cubefury.vendingmachine.trade.TradeRequest; import com.cubefury.vendingmachine.util.NBTConverter; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; public class NetTradeRequestSync { @@ -25,6 +29,10 @@ public class NetTradeRequestSync { public static void registerHandler() { PacketTypeRegistry.INSTANCE.registerServerHandler(ID_NAME, NetTradeRequestSync::onServer); + + if (VendingMachine.proxy.isClient()) { + PacketTypeRegistry.INSTANCE.registerClientHandler(ID_NAME, NetTradeRequestSync::onClient); + } } public static void sendTradeRequest(TradeItemDisplay trade, World world, int x, int y, int z) { @@ -38,6 +46,10 @@ public static void sendTradeRequest(TradeItemDisplay trade, World world, int x, PacketSender.INSTANCE.sendToServer(new UnserializedPacket(ID_NAME, payload)); } + public static void sendAck(EntityPlayerMP player) { + PacketSender.INSTANCE.sendToPlayers(new UnserializedPacket(ID_NAME, new NBTTagCompound()), player); + } + public static void onServer(Tuple2 message) { World world = DimensionManager.getWorld( message.first() @@ -63,4 +75,9 @@ public static void onServer(Tuple2 message) { (MTEVendingMachine) ((IGregTechTileEntity) te).getMetaTileEntity())); } } + + @SideOnly(Side.CLIENT) + public static void onClient(NBTTagCompound message) { + MTEVendingMachineGui.setForceRefresh(); + } } From 9ab53277b8b4e26679978d2379f118235565f7b5 Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 20:08:16 +0800 Subject: [PATCH 39/40] Fixed Server side crash --- .../vendingmachine/blocks/MTEVendingMachine.java | 3 +-- .../blocks/gui/MTEVendingMachineGui.java | 16 +++++++++------- .../blocks/gui/TradeMainPanel.java | 2 +- .../vendingmachine/trade/TradeDatabase.java | 5 +++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index f7e3ebd..14b2661 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -276,8 +276,7 @@ protected boolean forceUseMui2() { @Override protected @NotNull MTEVendingMachineGui getGui() { if ( - !Minecraft.getMinecraft() - .isIntegratedServerRunning() + VendingMachine.proxy.isClient() ) { NetAvailableTradeSync.requestSync(); NetTradeStateSync.requestSync(); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java index d7bf19d..93f1d45 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/MTEVendingMachineGui.java @@ -79,8 +79,8 @@ public MTEVendingMachineGui(MTEVendingMachine base, int height) { } } - this.tabController = new PagedWidget.Controller(); - this.searchBar = createSearchBar(); + this.tabController = VendingMachine.proxy.isClient() ? new PagedWidget.Controller() : null; + this.searchBar = VendingMachine.proxy.isClient() ? createSearchBar() : null; } public MTEVendingMachine getBase() { @@ -99,12 +99,14 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe ModularPanel panel = new TradeMainPanel("MTEMultiBlockBase", this, guiData, syncManager).size(178, height) .padding(4); panel.child(createCategoryTabs(this.tabController)); - panel.child( - new Column().width(170) - .child(createTitleTextStyle(base.getLocalName())) + Flow mainColumn = new Column().width(170); + if (VendingMachine.proxy.isClient()) { // client side filtering + mainColumn.child(createTitleTextStyle(base.getLocalName())) .child(this.searchBar) - .child(createTradeUI((TradeMainPanel) panel, this.tabController)) - .child(createInventoryRow(panel, syncManager))); + .child(createTradeUI((TradeMainPanel) panel, this.tabController)); + } + mainColumn.child(createInventoryRow(panel, syncManager)); + panel.child(mainColumn); panel.child( new Column().size(20) .right(5)); diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java index 390bdf5..9e23077 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeMainPanel.java @@ -67,7 +67,7 @@ public boolean onKeyRelease(char typedChar, int keyCode) { } public void updateGui() { - boolean test = false; + boolean test = true; if (test) { List testTGW = new ArrayList<>(); for (Map.Entry entry : TradeDatabase.INSTANCE.getTradeGroups() diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index e4689ce..71007ae 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -98,8 +98,9 @@ public void readFromNBT(NBTTagCompound nbt, boolean merge) { VendingMachine.LOG.info("Appended metadata to {} new trades", newMetadataCount); DirtyDbMarker.markDirty(); } - - refreshNeiCache(); + if (VendingMachine.proxy.isClient()) { + refreshNeiCache(); + } TradeManager.INSTANCE.recomputeAvailableTrades(null); VendingMachine.LOG From c2fe4bc6c915a8d631c44e54d5c584473e777f8a Mon Sep 17 00:00:00 2001 From: cubefury Date: Sun, 14 Sep 2025 21:02:01 +0800 Subject: [PATCH 40/40] spotless --- .../cubefury/vendingmachine/blocks/MTEVendingMachine.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 14b2661..f329527 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -7,7 +7,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.LinkedBlockingQueue; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -275,9 +274,7 @@ protected boolean forceUseMui2() { @Override protected @NotNull MTEVendingMachineGui getGui() { - if ( - VendingMachine.proxy.isClient() - ) { + if (VendingMachine.proxy.isClient()) { NetAvailableTradeSync.requestSync(); NetTradeStateSync.requestSync(); }