diff --git a/README.md b/README.md index c193ac2..e91cd13 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Alpha Testing This can be used as a standalone mod with several dependencies. The vending machine block and ME Vending Uplink do not come with default recipes. ### Required Dependencies: -- GT5U +- GT5Unofficial-GTNH (Not compatible with main GT5U branch!) - ModularUI 2 - NotEnoughItems - Applied Energistics 2 diff --git a/dependencies.gradle b/dependencies.gradle index d4a2fbb..9bd54c8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,13 +34,13 @@ * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { - 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.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") + implementation("com.github.GTNewHorizons:NotEnoughItems:2.8.6-GTNH:dev") + implementation("com.github.GTNewHorizons:GTNHLib:0.7.0:dev") + compileOnly("com.github.GTNewHorizons:BetterQuesting:3.8.8-GTNH:dev") + implementation("com.github.GTNewHorizons:ModularUI2:2.2.20-1.7.10:dev") + // implementation("com.github.GTNewHorizons:ModularUI2:2.2.20-1.7.10:dev") + implementation("com.github.GTNewHorizons:StructureLib:1.4.23:dev") + implementation("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.21:dev") } // deps may transitively add Baubles, so we replace it @@ -49,7 +49,7 @@ project.getConfigurations() final DependencySubstitutions ds = c.getResolutionStrategy() .getDependencySubstitution() ds.substitute(ds.module("com.github.GTNewHorizons:Baubles")) - .using(ds.module("com.github.GTNewHorizons:Baubles-Expanded:2.1.9-GTNH")) + .using(ds.module("com.github.GTNewHorizons:Baubles-Expanded:2.2.0-GTNH")) .withClassifier("dev") .because("Baubles-Expanded replaces Baubles") }) diff --git a/settings.gradle.kts b/settings.gradle.kts index cbf0d00..0966c6f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,5 +17,5 @@ pluginManagement { } plugins { - id("com.gtnewhorizons.gtnhsettingsconvention") version("1.0.41") + id("com.gtnewhorizons.gtnhsettingsconvention") version("1.0.43") } diff --git a/src/main/java/com/cubefury/vendingmachine/Config.java b/src/main/java/com/cubefury/vendingmachine/Config.java index 8972650..d812ea9 100644 --- a/src/main/java/com/cubefury/vendingmachine/Config.java +++ b/src/main/java/com/cubefury/vendingmachine/Config.java @@ -4,6 +4,9 @@ import net.minecraftforge.common.config.Configuration; +import com.cubefury.vendingmachine.blocks.gui.MTEVendingMachineGui; +import com.cubefury.vendingmachine.blocks.gui.TradeItemDisplayWidget.DisplayType; + public class Config { private static final String CONFIG_CATEGORY_VM = "Vending Machine Settings"; @@ -13,6 +16,8 @@ public class Config { public static int gui_refresh_interval = 20; public static int dispense_frequency = 10; public static int dispense_amount = 16; + public static DisplayType display_type = DisplayType.TILE; + public static MTEVendingMachineGui.SortMode sort_mode = MTEVendingMachineGui.SortMode.SMART; public static File worldDir = null; @@ -36,6 +41,26 @@ public static void init(File configFile) { 1, Integer.MAX_VALUE, "Number of items per dispense cycle"); + try { + display_type = DisplayType.valueOf( + configuration.getString( + "display_type", + CONFIG_CATEGORY_VM, + "TILE", + "Default trade display format, either TILE or LIST. Case sensitive.")); + } catch (IllegalArgumentException e) { + display_type = DisplayType.TILE; + } + try { + sort_mode = MTEVendingMachineGui.SortMode.valueOf( + configuration.getString( + "sort_mode", + CONFIG_CATEGORY_VM, + "SMART", + "Default sort mode, either SMART or ALPHABET. Case sensitive.")); + } catch (IllegalArgumentException e) { + sort_mode = MTEVendingMachineGui.SortMode.SMART; + } if (configuration.hasChanged()) { configuration.save(); diff --git a/src/main/java/com/cubefury/vendingmachine/api/enums/Textures.java b/src/main/java/com/cubefury/vendingmachine/api/enums/Textures.java index 13af61d..59354b4 100644 --- a/src/main/java/com/cubefury/vendingmachine/api/enums/Textures.java +++ b/src/main/java/com/cubefury/vendingmachine/api/enums/Textures.java @@ -18,7 +18,10 @@ public class Textures { VM_OVERLAY_ACTIVE_0 = new CustomIcon("vendingmachine:vending_machine_overlay_active_0"), VM_OVERLAY_ACTIVE_1 = new CustomIcon("vendingmachine:vending_machine_overlay_active_1"), VM_OVERLAY_ACTIVE_2 = new CustomIcon("vendingmachine:vending_machine_overlay_active_2"), - VM_OVERLAY_ACTIVE_3 = new CustomIcon("vendingmachine:vending_machine_overlay_active_3"); + VM_OVERLAY_ACTIVE_3 = new CustomIcon("vendingmachine:vending_machine_overlay_active_3"), + + VUPLINK_OVERLAY_0 = new CustomIcon("vendingmachine:vending_uplink_machine_overlay_inactive"), + VUPLINK_OVERLAY_1 = new CustomIcon("vendingmachine:vending_uplink_machine_overlay_active"); public static final IIconContainer[] VM_OVERLAY_ACTIVE = { VM_OVERLAY_ACTIVE_0, VM_OVERLAY_ACTIVE_1, VM_OVERLAY_ACTIVE_2, VM_OVERLAY_ACTIVE_3, VM_OVERLAY_4 // bottom right not animated diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java index 54df808..41cdc09 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingMachine.java @@ -5,6 +5,8 @@ import static com.cubefury.vendingmachine.api.enums.Textures.VM_MACHINE_FRONT_ON_GLOW; import static com.cubefury.vendingmachine.api.enums.Textures.VM_OVERLAY; import static com.cubefury.vendingmachine.api.enums.Textures.VM_OVERLAY_ACTIVE; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; +import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain; import static gregtech.api.util.GTStructureUtility.ofHatchAdderOptional; import java.util.ArrayList; @@ -46,6 +48,7 @@ import com.cubefury.vendingmachine.trade.TradeRequest; import com.cubefury.vendingmachine.util.BigItemStack; import com.cubefury.vendingmachine.util.OverlayHelper; +import com.cubefury.vendingmachine.util.Translator; import com.gtnewhorizon.structurelib.StructureLibAPI; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits; @@ -79,12 +82,14 @@ public class MTEVendingMachine extends MTEMultiBlockBase .addShape("main", new String[][] { { "cc", "c~", "cc" } }) .addElement( 'c', - ofHatchAdderOptional( - MTEVendingMachine::addUplinkHatch, - ((BlockCasings11) GregTechAPI.sBlockCasings11).getTextureIndex(0), - 1, - GregTechAPI.sBlockCasings11, - 0)) + ofChain( + ofHatchAdderOptional( + MTEVendingMachine::addUplinkHatch, + ((BlockCasings11) GregTechAPI.sBlockCasings11).getTextureIndex(0), + 1, + GregTechAPI.sBlockCasings11, + 0), + ofBlock(GregTechAPI.sBlockCasings11, 0))) .build(); private final ArrayList uplinkHatches = new ArrayList<>(); @@ -343,7 +348,7 @@ public boolean getDefaultHasMaintenanceChecks() { @Override public String[] getStructureDescription(ItemStack stackSize) { - return getTooltip().getStructureHint(); + return new String[] { Translator.translate("structure.vendingmachine.hint.1") }; } @Override @@ -359,6 +364,7 @@ protected MultiblockTooltipBuilder getTooltip() { .beginStructureBlock(2, 3, 1, false) .addController("Middle") .addOtherStructurePart("Tin Item Pipe Casings", "Everything except the controller") + .addOtherStructurePart("ME Vending Uplink Hatch", "Any Pipe Casing, Optional") .addStructureInfo("Cannot be flipped onto its side") .toolTipFinisher(); } diff --git a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingUplinkHatch.java b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingUplinkHatch.java index 10e6d6b..d190276 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingUplinkHatch.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/MTEVendingUplinkHatch.java @@ -1,7 +1,7 @@ package com.cubefury.vendingmachine.blocks; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_FLUID_HATCH; -import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_ME_INPUT_FLUID_HATCH_ACTIVE; +import static com.cubefury.vendingmachine.api.enums.Textures.VUPLINK_OVERLAY_0; +import static com.cubefury.vendingmachine.api.enums.Textures.VUPLINK_OVERLAY_1; import java.util.EnumSet; @@ -120,12 +120,12 @@ public void securityBreak() {} @Override public ITexture[] getTexturesActive(ITexture aBaseTexture) { - return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_FLUID_HATCH_ACTIVE) }; + return new ITexture[] { aBaseTexture, TextureFactory.of(VUPLINK_OVERLAY_1) }; } @Override public ITexture[] getTexturesInactive(ITexture aBaseTexture) { - return new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_ME_INPUT_FLUID_HATCH) }; + return new ITexture[] { aBaseTexture, TextureFactory.of(VUPLINK_OVERLAY_0) }; } @Override 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 5fcfd38..a3d3f66 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,8 @@ package com.cubefury.vendingmachine.blocks.gui; +import static com.cubefury.vendingmachine.gui.GuiTextures.SORT_ALPHABET; +import static com.cubefury.vendingmachine.gui.GuiTextures.SORT_SMART; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -13,14 +16,20 @@ 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.Icon; +import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.RichTooltip; import com.cleanroommc.modularui.screen.UISettings; import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.IntValue; 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.CycleButtonWidget; import com.cleanroommc.modularui.widgets.ListWidget; import com.cleanroommc.modularui.widgets.PagedWidget; import com.cleanroommc.modularui.widgets.SlotGroupWidget; @@ -30,6 +39,7 @@ 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.Config; import com.cubefury.vendingmachine.VendingMachine; import com.cubefury.vendingmachine.blocks.MTEVendingMachine; import com.cubefury.vendingmachine.gui.GuiTextures; @@ -57,7 +67,8 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { private boolean ejectItems = false; private boolean ejectCoins = false; private final Map ejectSingleCoin = new HashMap<>(); - private final Map> displayedTrades = new HashMap<>(); + private final Map> displayedTradesTiles = new HashMap<>(); + private final Map> displayedTradesList = new HashMap<>(); private final List tradeCategories = new ArrayList<>(); private final List inputSlots = new ArrayList<>(); @@ -67,15 +78,44 @@ public class MTEVendingMachineGui extends MTEMultiBlockBaseGui { public static String lastSearch = ""; public static int lastPage = 0; + public static TradeItemDisplayWidget.DisplayType displayType = Config.display_type; + public static SortMode sortMode = Config.sort_mode; public static final int CUSTOM_UI_HEIGHT = 320; - public static final int ITEMS_PER_ROW = 3; - public static final int ITEM_HEIGHT = 25; - public static final int ITEM_WIDTH = 47; + // Trade Item Display + public static final int TILE_ITEMS_PER_ROW = 3; + public static final int TILE_ITEM_HEIGHT = 25; + public static final int TILE_ITEM_WIDTH = 47; + public static final int LIST_ITEM_HEIGHT = 14; + public static final int LIST_ITEM_WIDTH = 153; + private static final int COIN_COLUMN_WIDTH = 40; private static final int COIN_COLUMN_ROW_COUNT = 4; + public enum SortMode { + + SMART("smart", SORT_SMART), + ALPHABET("alphabet", SORT_ALPHABET); + + private String mode; + private Icon texture; + + SortMode(String mode, UITexture texture) { + this.mode = mode; + this.texture = texture.asIcon(); + } + + public String getLocalizedName() { + return IKey.lang("vendingmachine.gui.display_sort_" + this.mode) + .toString(); + } + + public Icon getTexture() { + return this.texture; + } + } + public MTEVendingMachineGui(MTEVendingMachine base) { super(base); this.base = base; @@ -88,10 +128,15 @@ public MTEVendingMachineGui(MTEVendingMachine base) { this.tradeCategories.addAll(TradeDatabase.INSTANCE.getTradeCategories()); for (TradeCategory c : this.tradeCategories) { - displayedTrades.put(c, new ArrayList<>(MTEVendingMachine.MAX_TRADES)); + displayedTradesTiles.put(c, new ArrayList<>(MTEVendingMachine.MAX_TRADES)); for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { - displayedTrades.get(c) - .add(new TradeItemDisplayWidget(null)); + displayedTradesTiles.get(c) + .add(new TradeItemDisplayWidget(null, TradeItemDisplayWidget.DisplayType.TILE)); + } + displayedTradesList.put(c, new ArrayList<>(MTEVendingMachine.MAX_TRADES)); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + displayedTradesList.get(c) + .add(new TradeItemDisplayWidget(null, TradeItemDisplayWidget.DisplayType.LIST)); } } @@ -117,8 +162,13 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe .padding(4); panel.child(createCategoryTabs(this.tabController)); Flow mainColumn = new Column().width(170); - if (VendingMachine.proxy.isClient()) { // client side filtering - mainColumn.child(createTitleTextStyle(base.getLocalName())) + if (VendingMachine.proxy.isClient()) { // client side sort and filtering + panel.child(createQolButtonColumn()); + mainColumn.child( + createTitleTextStyle( + IKey.lang("gt.blockmachines.multimachine.vendingmachine.name.gui") + .style(IKey.DARK_GRAY) + .get())) .child(this.searchBar) .child(createTradeUI((TradeMainPanel) panel, this.tabController)); mainColumn.child(createCoinInventoryRow((TradeMainPanel) panel)); @@ -128,7 +178,7 @@ public ModularPanel build(PosGuiData guiData, PanelSyncManager syncManager, UISe panel.child( new Column().size(20) .right(5)); - panel.child(createIOColumn(syncManager)); + panel.child(createIOColumn()); return panel; } @@ -139,6 +189,47 @@ public void restorePreviousSettings() { this.searchBar.setText(lastSearch); } + public IWidget createQolButtonColumn() { + Flow buttonColumn = new Column().width(8) + .height(20) + .left(-17) + .top(1) + .coverChildren(); + buttonColumn.child( + new CycleButtonWidget().size(14) + .overlay( + new DynamicDrawable( + () -> displayType.getTexture() + .size(14))) + .stateCount(TradeItemDisplayWidget.DisplayType.values().length) + .value( + new IntValue.Dynamic( + () -> displayType.ordinal(), + val -> { displayType = TradeItemDisplayWidget.DisplayType.values()[val]; })) + .tooltipDynamic(builder -> { + builder.clearText(); + builder + .addLine(IKey.lang("vendingmachine.gui.display_mode") + " " + displayType.getLocalizedName()); + }) + .tooltipAutoUpdate(true)); + buttonColumn.child( + new CycleButtonWidget().size(14) + .top(17) + .overlay( + new DynamicDrawable( + () -> sortMode.getTexture() + .size(14))) + .stateCount(SortMode.values().length) + .value(new IntValue.Dynamic(() -> sortMode.ordinal(), val -> { sortMode = SortMode.values()[val]; })) + .tooltipDynamic(builder -> { + builder.clearText(); + builder.addLine(IKey.lang("vendingmachine.gui.display_sort") + " " + sortMode.getLocalizedName()); + setForceRefresh(); + }) + .tooltipAutoUpdate(true)); + return buttonColumn; + } + public IWidget createCategoryTabs(PagedWidget.Controller tabController) { Flow tabColumn = new Column().width(40) .height(100) @@ -253,7 +344,7 @@ private void doEjectItems() { ejectItems = false; } - private IWidget createIOColumn(PanelSyncManager syncManager) { + private IWidget createIOColumn() { return new ParentWidget<>().excludeAreaInNEI() .width(50) .height(178) @@ -268,7 +359,7 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .width(30) .height(20)) .child( - new Row().child(createInputRow().center()) + new Row().child(createInputSlots().center()) .top(20) .height(18 * 3)) .child( @@ -299,7 +390,7 @@ private IWidget createIOColumn(PanelSyncManager syncManager) { .right(1)); } - private SlotGroupWidget createInputRow() { + private SlotGroupWidget createInputSlots() { return SlotGroupWidget.builder() .matrix("II", "II", "II") .key('I', index -> { @@ -336,14 +427,52 @@ private SlotGroupWidget createOutputSlots() { return SlotGroupWidget.builder() .matrix("II", "II", "II") .key('I', index -> { - ModularSlot ms = new ModularSlot(base.outputItems, index).accessibility(false, true) - .slotGroup("outputSlotGroup"); - ms.changeListener((newItem, onlyAmountChanged, client, init) -> {}); - return new ItemSlot().slot(ms); + return new ItemSlot().slot( + new ModularSlot(base.outputItems, index).accessibility(false, true) + .slotGroup("outputSlotGroup")); }) .build(); } + private void constructTradeTooltip(RichTooltip builder, TradeItemDisplay cur) { + 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())); + } + builder.emptyLine(); + builder.addLine( + IKey.str(Translator.translate("vendingmachine.gui.required_inputs")) + .style(IKey.DARK_GREEN, IKey.ITALIC)); + for (CurrencyItem currencyItem : cur.fromCurrency) { + builder.addLine( + IKey.str(currencyItem.value + " " + currencyItem.type.getLocalizedName()) + .style(IKey.DARK_GREEN)); + } + 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)); + builder.addLine( + IKey.str(Translator.translate("vendingmachine.gui.trade_hint")) + .style(IKey.GRAY)); + } + } + // spotless:off private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller tabController) { PagedWidget paged = new PagedWidget<>() @@ -361,49 +490,60 @@ private IWidget createTradeUI(TradeMainPanel rootPanel, PagedWidget.Controller t tradeList.child(new Row().height(2)); // Higher first row top margin - Flow row = new TradeRow().height(ITEM_HEIGHT+2).left(2); + Flow row = new TradeRow().height(TILE_ITEM_HEIGHT +2).left(2); + // Tiles Display 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) + displayedTradesTiles.get(category).get(i).setRootPanel(rootPanel); + row.child(displayedTradesTiles.get(category).get(i) .tooltipDynamic(builder -> { builder.clearText(); - synchronized (displayedTrades) { - if (index < displayedTrades.get(category).size()) { - 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())); - } - builder.emptyLine(); - builder.addLine(IKey.str(Translator.translate("vendingmachine.gui.required_inputs")).style(IKey.DARK_GREEN, IKey.ITALIC)); - for (CurrencyItem currencyItem: cur.fromCurrency) { - builder.addLine(IKey.str(currencyItem.value + " " + currencyItem.type.getLocalizedName()).style(IKey.DARK_GREEN)); - } - 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)); + synchronized (displayedTradesTiles) { + if (index < displayedTradesTiles.get(category).size()) { + constructTradeTooltip(builder, displayedTradesTiles.get(category).get(index).getDisplay()); } } - } }) .tooltipAutoUpdate(true) - .setEnabledIf(slot -> ((TradeItemDisplayWidget) slot).getDisplay() != null) + .setEnabledIf(slot -> { + TradeItemDisplayWidget display = ((TradeItemDisplayWidget) slot); + return displayType == display.displayType && display.getDisplay() != null; + }) .margin(2)); - if (i % ITEMS_PER_ROW == ITEMS_PER_ROW - 1) { + if (i % TILE_ITEMS_PER_ROW == TILE_ITEMS_PER_ROW - 1) { tradeList.child(row); - row = new TradeRow().height(ITEM_HEIGHT+2).left(2); + row = new TradeRow().height(TILE_ITEM_HEIGHT +2).left(2); } } if (row.hasChildren()) { tradeList.child(row); } + + // List Display + row = new TradeRow().height(LIST_ITEM_HEIGHT).left(2); + for (int i = 0; i < MTEVendingMachine.MAX_TRADES; i++) { + int index = i; + displayedTradesList.get(category).get(i).setRootPanel(rootPanel); + row.child(displayedTradesList.get(category).get(i) + .tooltipDynamic(builder -> { + builder.clearText(); + synchronized (displayedTradesList) { + if (index < displayedTradesList.get(category).size()) { + constructTradeTooltip(builder, displayedTradesList.get(category).get(index).getDisplay()); + } + } + }) + .tooltipAutoUpdate(true) + .setEnabledIf(slot -> { + TradeItemDisplayWidget display = ((TradeItemDisplayWidget) slot); + return displayType == display.displayType && display.getDisplay() != null; + })); + tradeList.child(row); + row = new TradeRow().height(LIST_ITEM_HEIGHT).left(2); + } + tradeList.child(new Row().height(2)); // bottom padding for last row paged.addPage(tradeList); } @@ -488,8 +628,8 @@ private IWidget createInventoryRow() { @Override protected void registerSyncValues(PanelSyncManager syncManager) { super.registerSyncValues(syncManager); - syncManager.registerSlotGroup("inputSlotGroup", 6, true); - syncManager.registerSlotGroup("outputSlotGroup", 4, false); + syncManager.registerSlotGroup("inputSlotGroup", 2, true); + syncManager.registerSlotGroup("outputSlotGroup", 2, false); BooleanSyncValue ejectItemsSyncer = new BooleanSyncValue(() -> this.ejectItems, val -> { this.ejectItems = val; @@ -533,9 +673,10 @@ public static void resetForceRefresh() { forceRefresh = false; } - public void updateTradeDisplay(Map> trades) { - synchronized (displayedTrades) { - for (Map.Entry> entry : displayedTrades.entrySet()) { + private void updateTradeDisplay(Map> trades, + Map> display) { + synchronized (display) { + for (Map.Entry> entry : display.entrySet()) { int displayedSize = trades.get(entry.getKey()) == null ? 0 : trades.get(entry.getKey()) .size(); @@ -556,10 +697,16 @@ public void updateTradeDisplay(Map> trades } } - public Map> getTradeDisplayData() { + public void updateTradeDisplay(Map> trades) { + this.updateTradeDisplay(trades, displayedTradesTiles); + this.updateTradeDisplay(trades, displayedTradesList); + } + + public Map> getCurrentTradeDisplayData() { Map> currentData = new HashMap<>(); - synchronized (displayedTrades) { - this.displayedTrades.forEach((k, v) -> { + + synchronized (displayedTradesTiles) { + this.displayedTradesTiles.forEach((k, v) -> { currentData.put( k, v.stream() @@ -568,6 +715,18 @@ public Map> getTradeDisplayData() { .collect(Collectors.toList())); }); } + + synchronized (displayedTradesList) { + this.displayedTradesList.forEach((k, v) -> { + currentData.get(k) + .addAll( + v.stream() + .map(TradeItemDisplayWidget::getDisplay) + .filter(Objects::nonNull) + .collect(Collectors.toList())); + }); + } + return currentData; } 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 65641ef..4a4c680 100644 --- a/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java +++ b/src/main/java/com/cubefury/vendingmachine/blocks/gui/TradeItemDisplayWidget.java @@ -1,5 +1,8 @@ package com.cubefury.vendingmachine.blocks.gui; +import static com.cubefury.vendingmachine.gui.GuiTextures.MODE_LIST; +import static com.cubefury.vendingmachine.gui.GuiTextures.MODE_TILE; + import net.minecraft.item.ItemStack; import org.jetbrains.annotations.NotNull; @@ -9,6 +12,8 @@ import com.cleanroommc.modularui.api.widget.Interactable; import com.cleanroommc.modularui.drawable.DynamicDrawable; import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.drawable.Icon; +import com.cleanroommc.modularui.drawable.UITexture; import com.cleanroommc.modularui.screen.viewport.ModularGuiContext; import com.cleanroommc.modularui.theme.WidgetTheme; import com.cleanroommc.modularui.utils.Platform; @@ -19,17 +24,51 @@ public class TradeItemDisplayWidget extends ItemDisplayWidget implements Interactable { + public enum DisplayType { + + TILE("tile", MODE_TILE), + LIST("list", MODE_LIST); + + private String type; + private Icon texture; + + DisplayType(String type, UITexture texture) { + this.type = type; + this.texture = texture.asIcon(); + } + + public String getLocalizedName() { + return IKey.lang("vendingmachine.gui.display_mode_" + this.type) + .toString(); + } + + public Icon getTexture() { + return this.texture; + } + } + private TradeMainPanel rootPanel; private boolean pressed = false; private IValue value; + public final DisplayType displayType; private TradeItemDisplay display; - public TradeItemDisplayWidget(TradeItemDisplay display) { - height(MTEVendingMachineGui.ITEM_HEIGHT); - width(MTEVendingMachineGui.ITEM_WIDTH); - background( - new DynamicDrawable(() -> pressed ? GuiTextures.TRADE_BUTTON_PRESSED : GuiTextures.TRADE_BUTTON_UNPRESSED)); + public TradeItemDisplayWidget(TradeItemDisplay display, DisplayType displayType) { + this.displayType = displayType; + if (displayType == DisplayType.TILE) { + height(MTEVendingMachineGui.TILE_ITEM_HEIGHT); + width(MTEVendingMachineGui.TILE_ITEM_WIDTH); + background( + new DynamicDrawable( + () -> pressed ? GuiTextures.TILE_TRADE_BUTTON_PRESSED : GuiTextures.TILE_TRADE_BUTTON_UNPRESSED)); + } else if (displayType == DisplayType.LIST) { + height(MTEVendingMachineGui.LIST_ITEM_HEIGHT); + width(MTEVendingMachineGui.LIST_ITEM_WIDTH); + background( + new DynamicDrawable( + () -> pressed ? GuiTextures.LIST_TRADE_BUTTON_PRESSED : GuiTextures.LIST_TRADE_BUTTON_UNPRESSED)); + } this.display = display; this.item((ItemStack) null); @@ -57,24 +96,47 @@ 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.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, + if (this.displayType == DisplayType.TILE) { + 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); + } + if (this.display.hasCooldown || !this.display.enabled) { + GuiDraw.drawRoundedRect( + 1, + 1, + MTEVendingMachineGui.TILE_ITEM_WIDTH - 2, + MTEVendingMachineGui.TILE_ITEM_HEIGHT - 2, + 0xBB000000, + 1, + 1); + } + this.overlay( + IKey.str(display.hasCooldown ? this.display.cooldownText : "") + .style(IKey.WHITE)); + } else if (this.displayType == DisplayType.LIST) { + GuiDraw.drawText("" + this.display.display.stackSize, 6, 4, 0.9f, 0x0, false); + GuiDraw.drawText("" + this.display.display.getDisplayName(), 24, 4, 0.9f, 0x0, false); + GuiDraw.drawRect( 1, - MTEVendingMachineGui.ITEM_WIDTH - 2, - MTEVendingMachineGui.ITEM_HEIGHT - 2, - 0xBB000000, 1, - 1); + 3, + MTEVendingMachineGui.LIST_ITEM_HEIGHT - 3, + this.display.tradeableNow ? 0x883CFF00 : 0x88333333); + if (this.display.hasCooldown || !this.display.enabled) { + GuiDraw.drawRect( + 1, + 1, + MTEVendingMachineGui.LIST_ITEM_WIDTH - 2, + MTEVendingMachineGui.LIST_ITEM_HEIGHT - 2, + 0xBB000000); + } + this.overlay( + IKey.str(display.hasCooldown ? this.display.cooldownText : "") + .style(IKey.WHITE) + .scale(0.9f)); } - this.overlay( - IKey.str(display.hasCooldown ? 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 c25667b..37cbccc 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.network.handlers.NetResetVMUser; import com.cubefury.vendingmachine.trade.TradeCategory; import com.cubefury.vendingmachine.trade.TradeDatabase; +import com.cubefury.vendingmachine.trade.TradeGroup; import com.cubefury.vendingmachine.trade.TradeManager; import com.cubefury.vendingmachine.util.BigItemStack; @@ -64,7 +65,7 @@ public boolean onKeyRelease(char typedChar, int keyCode) { public void updateGui() { if (shiftHeld) { - this.updateTradeInformation(gui.getTradeDisplayData()); + this.updateTradeInformation(gui.getCurrentTradeDisplayData()); } else { Map> trades = formatTrades(); gui.updateTradeDisplay(trades); @@ -125,9 +126,14 @@ public ItemStack convertToItemStack(BigItemStack stack) { public Map> formatTrades() { Map> trades = new HashMap<>(); trades.put(TradeCategory.ALL, new ArrayList<>()); + MTEVendingMachineGui.SortMode sortMode = MTEVendingMachineGui.sortMode; + for (TradeItemDisplay tid : TradeManager.INSTANCE.tradeData) { - TradeCategory category = TradeDatabase.INSTANCE.getTradeGroupFromId(tid.tgID) - .getCategory(); + TradeGroup group = TradeDatabase.INSTANCE.getTradeGroupFromId(tid.tgID); + if (group == null) { + continue; + } + TradeCategory category = group.getCategory(); trades.putIfAbsent(category, new ArrayList<>()); trades.get(category) .add(tid); @@ -152,28 +158,35 @@ public Map> formatTrades() { 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); + if (sortMode == MTEVendingMachineGui.SortMode.ALPHABET) { + return (a.display.getDisplayName() + .compareTo(b.display.getDisplayName())); + } else if (sortMode == MTEVendingMachineGui.SortMode.SMART) { + // 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); } - // 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); - + // impossible + return 0; }); trades.replace(category, filteredTrades); } diff --git a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java index 8ee5829..3de4571 100644 --- a/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java +++ b/src/main/java/com/cubefury/vendingmachine/gui/GuiTextures.java @@ -45,20 +45,59 @@ public final class GuiTextures { .name("text_field_background") .build(); - public static final UITexture TRADE_BUTTON_UNPRESSED = UITexture.builder() + // TODO: Restore canApplyTheme to trade button textures after scrolling texture bug is fixed in MUI2 + public static final UITexture TILE_TRADE_BUTTON_UNPRESSED = UITexture.builder() .location(VendingMachine.MODID, "gui/background/trade_button_unpressed_color_corrected") .imageSize(195, 136) .adaptable(4) .name("trade_button_unpressed") .build(); - public static final UITexture TRADE_BUTTON_PRESSED = UITexture.builder() + public static final UITexture TILE_TRADE_BUTTON_PRESSED = UITexture.builder() .location(VendingMachine.MODID, "gui/background/trade_button_pressed_color_corrected") .imageSize(195, 136) .adaptable(4) .name("trade_button_pressed") .build(); + public static final UITexture LIST_TRADE_BUTTON_UNPRESSED = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/list_trade_button_unpressed_color_corrected") + .imageSize(195, 136) + .adaptable(2) + .name("list_trade_button_unpressed") + .build(); + + public static final UITexture LIST_TRADE_BUTTON_PRESSED = UITexture.builder() + .location(VendingMachine.MODID, "gui/background/list_trade_button_pressed_color_corrected") + .imageSize(195, 136) + .adaptable(2) + .name("list_trade_button_pressed") + .build(); + + public static final UITexture MODE_TILE = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/mode_tile") + .imageSize(32, 32) + .name("mode_tile") + .build(); + + public static final UITexture MODE_LIST = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/mode_list") + .imageSize(32, 32) + .name("mode_list") + .build(); + + public static final UITexture SORT_SMART = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/sort_smart") + .imageSize(32, 32) + .name("sort_smart") + .build(); + + public static final UITexture SORT_ALPHABET = UITexture.builder() + .location(VendingMachine.MODID, "gui/overlay/sort_alphabet") + .imageSize(32, 32) + .name("sort_alphabet") + .build(); + public static final UITexture INPUT_SPRITE = UITexture.builder() .location(VendingMachine.MODID, "gui/background/input") .imageSize(30, 20) diff --git a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java index a6e669a..f1db10f 100644 --- a/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java +++ b/src/main/java/com/cubefury/vendingmachine/trade/TradeDatabase.java @@ -109,9 +109,10 @@ public void readFromNBT(NBTTagCompound nbt, boolean merge) { public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setInteger("version", this.version); NBTTagList tgList = new NBTTagList(); - for (TradeGroup tg : tradeGroups.values()) { - tgList.appendTag(tg.writeToNBT(new NBTTagCompound())); - } + tradeGroups.values() + .stream() + .sorted(Comparator.comparing(TradeGroup::getId)) + .forEach(tg -> tgList.appendTag(tg.writeToNBT(new NBTTagCompound()))); nbt.setTag("tradeGroups", tgList); return nbt; } @@ -126,7 +127,9 @@ public void populateTradeStateFromNBT(NBTTagCompound nbt, UUID player, boolean m UUID tgId = NBTConverter.UuidValueType.TRADEGROUP.readId(state); TradeGroup tg = TradeDatabase.INSTANCE.getTradeGroupFromId(tgId); TradeHistory th = new TradeHistory(state.getLong("lastTrade"), state.getInteger("tradeCount")); - tg.setTradeState(player, th); + if (tg != null) { + tg.setTradeState(player, th); + } } TradeManager.INSTANCE.populateCurrencyFromNBT(nbt, player, merge); } diff --git a/src/main/java/com/cubefury/vendingmachine/util/NBTConverter.java b/src/main/java/com/cubefury/vendingmachine/util/NBTConverter.java index 5daf73f..d09ef91 100644 --- a/src/main/java/com/cubefury/vendingmachine/util/NBTConverter.java +++ b/src/main/java/com/cubefury/vendingmachine/util/NBTConverter.java @@ -176,20 +176,11 @@ else if (value instanceof NBTTagByteArray) { out.endArray(); } else if (value instanceof NBTTagList) { List tagList = getTagList((NBTTagList) value); - if (format) { - out.beginObject(); - for (int i = 0; i < tagList.size(); i++) { - NBTBase tag = tagList.get(i); - out.name(i + ":" + tag.getId()); - NBTtoJSON_Base(tag, true, out); - } - out.endObject(); - } else { - out.beginArray(); - for (NBTBase tag : tagList) { - NBTtoJSON_Base(tag, false, out); - } + out.beginArray(); + for (NBTBase tag : tagList) { + NBTtoJSON_Base(tag, format, out); } + out.endArray(); } else if (value instanceof NBTTagCompound) { NBTtoJSON_Compound((NBTTagCompound) value, out, format); } else { @@ -233,31 +224,15 @@ private static JsonElement NBTtoJSON_Base(NBTBase tag, boolean format) { } else if (tag instanceof NBTTagCompound) { return NBTtoJSON_Compound((NBTTagCompound) tag, new JsonObject(), format); } else if (tag instanceof NBTTagList) { - if (format) { - JsonObject jAry = new JsonObject(); - - List tagList = getTagList((NBTTagList) tag); - - for (int i = 0; i < tagList.size(); i++) { - jAry.add( - i + ":" - + tagList.get(i) - .getId(), - NBTtoJSON_Base(tagList.get(i), true)); - } - - return jAry; - } else { - JsonArray jAry = new JsonArray(); - - List tagList = getTagList((NBTTagList) tag); + JsonArray jAry = new JsonArray(); - for (NBTBase t : tagList) { - jAry.add(NBTtoJSON_Base(t, false)); - } + List tagList = getTagList((NBTTagList) tag); - return jAry; + for (NBTBase t : tagList) { + jAry.add(NBTtoJSON_Base(t, format)); } + + return jAry; } else if (tag instanceof NBTTagByteArray) { JsonArray jAry = new JsonArray(); diff --git a/src/main/resources/assets/vendingmachine/lang/en_US.lang b/src/main/resources/assets/vendingmachine/lang/en_US.lang index 70de284..1162c3d 100644 --- a/src/main/resources/assets/vendingmachine/lang/en_US.lang +++ b/src/main/resources/assets/vendingmachine/lang/en_US.lang @@ -2,6 +2,8 @@ item.vendingmachine.placeholder.name=Placeholder Item tooltip.vendingmachine=Who's even restocking this... +structure.vendingmachine.hint.1=Hint 1 Dot: Tin Item Pipe Casing, ME Vending Uplink Hatch + vendingmachine.gui.requirementHeader=Requirements: vendingmachine.gui.requirement.unknown=Unknown Requirement vendingmachine.gui.requirement.betterquesting=Quest @@ -14,6 +16,13 @@ vendingmachine.gui.coin_eject=Eject All Coins vendingmachine.gui.single_coin_type_eject_hint=Shift-Click to Extract vendingmachine.gui.search=Search vendingmachine.gui.required_inputs=Requires: +vendingmachine.gui.trade_hint=Shift-Click to Purchase +vendingmachine.gui.display_mode=Display: +vendingmachine.gui.display_mode_tile=Tiles +vendingmachine.gui.display_mode_list=List +vendingmachine.gui.display_sort=Sort: +vendingmachine.gui.display_sort_smart=Smart +vendingmachine.gui.display_sort_alphabet=Alphabetical Order vendingmachine.gui.cooldown_display.second=s vendingmachine.gui.cooldown_display.minute=m @@ -23,6 +32,7 @@ vendingmachine.gui.cooldown_display.day=d vendingmachine.gui.error.player_using=Someone is using the vending machine at the moment. gt.blockmachines.multimachine.vendingmachine.name=Vending Machine +gt.blockmachines.multimachine.vendingmachine.name.gui=Vending Machine hatch.vendinguplink.me.name=ME Vending Uplink Hatch vendingmachine.category.unknown=Unknown Category diff --git a/src/main/resources/assets/vendingmachine/lang/zh_CN.lang b/src/main/resources/assets/vendingmachine/lang/zh_CN.lang index 2893c68..40f3eea 100644 --- a/src/main/resources/assets/vendingmachine/lang/zh_CN.lang +++ b/src/main/resources/assets/vendingmachine/lang/zh_CN.lang @@ -2,6 +2,8 @@ item.vendingmachine.placeholder.name=占位符物品 tooltip.vendingmachine=到底是谁在补货啊... +structure.vendingmachine.hint.1=提示 1:锡质物品管道外壳,ME自动售货接入接口 + vendingmachine.gui.requirementHeader=需求条件: vendingmachine.gui.requirement.unknown=未知需求 vendingmachine.gui.requirement.betterquesting=任务 @@ -10,15 +12,22 @@ vendingmachine.gui.neiColor.conditionDefault=000000 vendingmachine.gui.neiColor.conditionSatisfied=55D441 vendingmachine.gui.neiColor.conditionUnsatisfied=A87A5E vendingmachine.gui.item_eject=取出物品 +vendingmachine.gui.coin_eject=取出所有代币 +vendingmachine.gui.single_coin_type_eject_hint=Shift-点击提取 vendingmachine.gui.search=搜索 vendingmachine.gui.required_inputs=需要: +vendingmachine.gui.trade_hint=Shift-点击购买 vendingmachine.gui.cooldown_display.second=秒 vendingmachine.gui.cooldown_display.minute=分 vendingmachine.gui.cooldown_display.hour=时 vendingmachine.gui.cooldown_display.day=天 +vendingmachine.gui.error.player_using=当前有其他玩家正在使用此自动售货机 + gt.blockmachines.multimachine.vendingmachine.name=自动售货机 +gt.blockmachines.multimachine.vendingmachine.name.gui=自动售货机 +hatch.vendinguplink.me.name=ME自动售货接入接口 vendingmachine.category.unknown=未知分类 vendingmachine.category.all=全部物品 @@ -29,3 +38,18 @@ vendingmachine.category.chemistry=化工 vendingmachine.category.magic=魔法 vendingmachine.category.bees=蜜蜂 vendingmachine.category.misc=杂项 + +vendingmachine.coin.adventure=探险家代币 +vendingmachine.coin.bees=养蜂员代币 +vendingmachine.coin.blood=吸血鬼代币 +vendingmachine.coin.chemist=化学家代币 +vendingmachine.coin.cook=厨师代币 +vendingmachine.coin.darkWizard=魔法师代币 +vendingmachine.coin.farmer=农民代币 +vendingmachine.coin.flower=园艺代币 +vendingmachine.coin.forestry=护林员代币 +vendingmachine.coin.smith=匠师代币 +vendingmachine.coin.space=太空代币 +vendingmachine.coin.survivor=幸存者代币 +vendingmachine.coin.technician=技术员代币 +vendingmachine.coin.witch=巫师代币 diff --git a/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_active.png b/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_active.png new file mode 100644 index 0000000..358ce0b Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_active.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_inactive.png b/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_inactive.png new file mode 100644 index 0000000..2393590 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/blocks/vending_uplink_machine_overlay_inactive.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed.png b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed.png new file mode 100644 index 0000000..aefd2f7 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed_color_corrected.png b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed_color_corrected.png new file mode 100644 index 0000000..994c3d1 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_pressed_color_corrected.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed.png b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed.png new file mode 100644 index 0000000..48b5d22 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed_color_corrected.png b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed_color_corrected.png new file mode 100644 index 0000000..e931d75 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/background/list_trade_button_unpressed_color_corrected.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_list.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_list.png new file mode 100644 index 0000000..039e5ef Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_list.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_tile.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_tile.png new file mode 100644 index 0000000..426e54f Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/overlay/mode_tile.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_alphabet.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_alphabet.png new file mode 100644 index 0000000..19f0991 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_alphabet.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_smart.png b/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_smart.png new file mode 100644 index 0000000..7df0dc2 Binary files /dev/null and b/src/main/resources/assets/vendingmachine/textures/gui/overlay/sort_smart.png differ diff --git a/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png b/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png index 0c532c6..9e5b665 100644 Binary files a/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png and b/src/main/resources/assets/vendingmachine/textures/gui/tabs_left.png differ