From 1254320033d9345c8cf27e2dbeeb0b098735d029 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sat, 11 May 2024 00:35:40 -0400 Subject: (AutoTrade) Allow setting a maximum acceptable price. --- .../trashyaddon/modules/AcceptablePrices.java | 93 ++++++++++++++++++++++ .../modules/AcceptablePricesScreen.java | 78 ++++++++++++++++++ .../chrisoft/trashyaddon/modules/AutoTrade.java | 30 +++++-- 3 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePrices.java create mode 100644 src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePricesScreen.java (limited to 'src/main/java/org/chrisoft/trashyaddon/modules') diff --git a/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePrices.java b/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePrices.java new file mode 100644 index 0000000..9e96dfe --- /dev/null +++ b/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePrices.java @@ -0,0 +1,93 @@ +package org.chrisoft.trashyaddon.modules; + +import meteordevelopment.meteorclient.MeteorClient; +import meteordevelopment.meteorclient.gui.GuiTheme; +import meteordevelopment.meteorclient.gui.WidgetScreen; +import meteordevelopment.meteorclient.utils.misc.ICopyable; +import meteordevelopment.meteorclient.utils.misc.ISerializable; +import meteordevelopment.meteorclient.gui.utils.IScreenFactory; +import net.minecraft.item.Item; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; +import net.minecraft.registry.Registries; +import net.minecraft.util.Identifier; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Stream; + +public class AcceptablePrices implements ICopyable, ISerializable, IScreenFactory { + public static final List allItems = Stream.concat(AutoTrade.allSellItems.stream(), AutoTrade.allBuyItems.stream()).toList(); + private HashMap prices; + AcceptablePrices(HashMap prices) { + this.prices = prices; + } + Integer getMaxPriceForItem(Item i) { + return prices.get(i); + } + void setMaxPriceForItem(Item i, int p) { + prices.put(i, p); + } + void unsetMaxPriceForItem(Item i) { + prices.remove(i); + } + List allConfiguredItems() { + return prices.keySet().stream().toList(); + } + + @Override + public WidgetScreen createScreen(GuiTheme theme) { + return new AcceptablePricesScreen(theme, this); + } + + @Override + public AcceptablePrices set(AcceptablePrices value) { + this.prices = value.prices; + return this; + } + + @Override + public AcceptablePrices copy() { + return new AcceptablePrices(new HashMap<>(this.prices)); + } + + @Override + public NbtCompound toTag() { + NbtCompound ret = new NbtCompound(); + NbtList l = new NbtList(); + for (Item i : this.prices.keySet()) { + NbtCompound a = new NbtCompound(); + a.putString("Item", Registries.ITEM.getId(i).toString()); + a.putInt("Price", prices.get(i)); + l.add(a); + } + ret.put("Prices", l); + MeteorClient.LOG.warn("AcceptablePrices NBT result: " + ret.asString()); + return ret; + } + + @Override + public AcceptablePrices fromTag(NbtCompound tag) { + MeteorClient.LOG.warn("AcceptablePrices NBT from: " + tag.asString()); + HashMap ret = new HashMap<>(); + try { + NbtList l = tag.getList("Prices", NbtElement.COMPOUND_TYPE); + for (int i = 0; i < l.size(); ++i) { + NbtCompound a = l.getCompound(i); + String item_id = a.getString("Item"); + Item item = Registries.ITEM.get(new Identifier(item_id)); + int price = a.getInt("Price"); + ret.put(item, price); + } + } catch (NullPointerException e) { + this.prices = new HashMap<>(); + return this; + } + MeteorClient.LOG.warn(ret.toString()); + this.prices = ret; + return this; + } +} diff --git a/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePricesScreen.java b/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePricesScreen.java new file mode 100644 index 0000000..aec721d --- /dev/null +++ b/src/main/java/org/chrisoft/trashyaddon/modules/AcceptablePricesScreen.java @@ -0,0 +1,78 @@ +package org.chrisoft.trashyaddon.modules; + +import meteordevelopment.meteorclient.gui.GuiTheme; +import meteordevelopment.meteorclient.gui.WindowScreen; +import meteordevelopment.meteorclient.gui.screens.settings.ItemSettingScreen; +import meteordevelopment.meteorclient.gui.widgets.WItemWithLabel; +import meteordevelopment.meteorclient.gui.widgets.containers.WHorizontalList; +import meteordevelopment.meteorclient.gui.widgets.containers.WTable; +import meteordevelopment.meteorclient.gui.widgets.input.WIntEdit; +import meteordevelopment.meteorclient.gui.widgets.pressable.WMinus; +import meteordevelopment.meteorclient.settings.ItemSetting; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.Item; +import net.minecraft.item.Items; + +import java.util.ArrayList; + +public class AcceptablePricesScreen extends WindowScreen { + private final AcceptablePrices targetValue; + private WTable table; + private ArrayList rowItems; + public AcceptablePricesScreen(GuiTheme theme, AcceptablePrices prices) { + super(theme, "Configure max prices for each trade"); + targetValue = prices; + rowItems = new ArrayList<>(); + } + + @Override + public void initWidgets() { + this.add(theme.label("The amount set here corresponds to the max number of items in the first input slot.")); + table = this.add(theme.table()).expandX().widget(); + initTable(); + WHorizontalList hl = theme.horizontalList(); + hl.add(theme.label("")).expandCellX(); + hl.add(theme.plus()).widget().action = () -> { + ItemSetting t = new ItemSetting("", "", Items.AIR, null, null, null, + (Item item) -> AcceptablePrices.allItems.contains(item) && (targetValue.getMaxPriceForItem(item) == null)); + ItemSettingScreen screen = new ItemSettingScreen(this.theme, t); + screen.onClosed(() -> { + Item item = t.get(); + if (item != null && item != Items.AIR) + addRowForItem(item); + }); + MinecraftClient.getInstance().setScreen(screen); + }; + this.add(hl).expandX(); + } + + private void initTable() { + for (Item i : targetValue.allConfiguredItems()) { + addRowForItem(i); + } + } + private void addRowForItem(Item item) { + rowItems.add(item); + WItemWithLabel itemDisplay = theme.itemWithLabel(item.getDefaultStack(), item.getName().getString()); + table.add(itemDisplay).expandCellX(); + Integer v = targetValue.getMaxPriceForItem(item); + if (v == null) { + targetValue.setMaxPriceForItem(item, 1); + v = 1; + } + WIntEdit priceEdit = theme.intEdit(v, 1, 64, true); + priceEdit.action = () -> { + targetValue.setMaxPriceForItem(item, priceEdit.get()); + }; + table.add(priceEdit); + WMinus deleteButton = theme.minus(); + deleteButton.action = () -> { + table.removeRow(rowItems.indexOf(item)); + this.invalidate(); + rowItems.remove(item); + targetValue.unsetMaxPriceForItem(item); + }; + table.add(deleteButton); + table.row(); + } +} diff --git a/src/main/java/org/chrisoft/trashyaddon/modules/AutoTrade.java b/src/main/java/org/chrisoft/trashyaddon/modules/AutoTrade.java index c5df1b9..0b71598 100644 --- a/src/main/java/org/chrisoft/trashyaddon/modules/AutoTrade.java +++ b/src/main/java/org/chrisoft/trashyaddon/modules/AutoTrade.java @@ -20,14 +20,11 @@ import net.minecraft.village.TradeOffer; import net.minecraft.village.TradeOfferList; import org.chrisoft.trashyaddon.mixin.MerchantScreenAccessor; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; -import java.util.Optional; +import java.util.*; public class AutoTrade extends Module { private final SettingGroup sgGeneral = settings.getDefaultGroup(); - private static final List allSellItems = List.of( + public static final List allSellItems = List.of( Items.COAL, Items.CHICKEN, Items.PORKCHOP, @@ -73,7 +70,7 @@ public class AutoTrade extends Module { Items.QUARTZ ); - private static final List allBuyItems = List.of( + public static final List allBuyItems = List.of( Items.BELL, Items.COOKED_PORKCHOP, Items.COOKED_CHICKEN, @@ -129,6 +126,12 @@ public class AutoTrade extends Module { .filter((item) -> allBuyItems.contains(item)) .build() ); + private final Setting acceptablePricesSetting = sgGeneral.add(new GenericSetting.Builder() + .name("acceptable-prices") + .description("Configure maximum acceptable price for each item.") + .defaultValue(new AcceptablePrices(new HashMap<>())) + .build() + ); private final Setting interactionRate = sgGeneral.add(new IntSetting.Builder() .name("Interaction Rate") .description("Number of ticks between interactions.") @@ -190,10 +193,21 @@ public class AutoTrade extends Module { ItemStack msell = o.getSellItem(); List sells = sellingEnabled.get() ? this.sellsSetting.get() : List.of(); List buys = buyingEnabled.get() ? this.buysSetting.get() : List.of(); - if (!sells.contains(mbuy.getItem()) && !buys.contains(msell.getItem())) + Item interestedItem = null; + if (sells.contains(mbuy.getItem())) + interestedItem = mbuy.getItem(); + if (buys.contains(msell.getItem())) + interestedItem = msell.getItem(); + if (interestedItem == null) return false; + Integer maxPrice = acceptablePricesSetting.get().getMaxPriceForItem(interestedItem); + if (maxPrice != null && mbuy.getCount() > maxPrice) { + return false; + } FindItemResult rs = InvUtils.find((stack) -> stack.getItem().equals(mbuy.getItem()) && stack.getCount() >= mbuy.getCount()); - if (!rs.found()) + ItemStack s0is = screen.getScreenHandler().slots.get(0).getStack(); + boolean remainingFirstSlotSufficient = s0is.getItem().equals(mbuy.getItem()) && s0is.getCount() >= mbuy.getCount(); + if (!rs.found() && !remainingFirstSlotSufficient) return false; return true; } -- cgit v1.2.3