From b0f4d39b47a0396ccf8ef10aab86567474d2ba89 Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sat, 5 Aug 2023 03:02:23 +0200 Subject: [PATCH] Added BlackMarketVillagerType --- .../java/com/alttd/GUI/windows/OpenGUI.java | 4 +- .../java/com/alttd/GUI/windows/TradeGUI.java | 166 ++++++++++++++++++ .../commands/subcommands/CommandBuy.java | 3 +- .../subcommands/CommandCreateVillager.java | 5 +- .../commands/subcommands/CommandPoints.java | 11 +- .../commands/subcommands/CommandSell.java | 3 +- src/main/java/com/alttd/config/Config.java | 42 +++-- .../java/com/alttd/config/VillagerConfig.java | 3 +- .../java/com/alttd/config/WorthConfig.java | 23 +++ .../java/com/alttd/events/SpawnShopEvent.java | 10 ++ .../java/com/alttd/events/VillagerEvents.java | 32 ++-- .../objects/BlackMarketVillagerType.java | 88 ++++++++++ .../java/com/alttd/objects/PriceRange.java | 27 +++ .../com/alttd/objects/ShopVillagerType.java | 47 +++++ .../java/com/alttd/objects/VillagerType.java | 58 +----- .../alttd/objects/VillagerTypeManager.java | 24 +++ 16 files changed, 460 insertions(+), 86 deletions(-) create mode 100644 src/main/java/com/alttd/GUI/windows/TradeGUI.java create mode 100644 src/main/java/com/alttd/objects/BlackMarketVillagerType.java create mode 100644 src/main/java/com/alttd/objects/PriceRange.java create mode 100644 src/main/java/com/alttd/objects/ShopVillagerType.java create mode 100644 src/main/java/com/alttd/objects/VillagerTypeManager.java diff --git a/src/main/java/com/alttd/GUI/windows/OpenGUI.java b/src/main/java/com/alttd/GUI/windows/OpenGUI.java index aa100ab..e7d71da 100644 --- a/src/main/java/com/alttd/GUI/windows/OpenGUI.java +++ b/src/main/java/com/alttd/GUI/windows/OpenGUI.java @@ -4,7 +4,7 @@ import com.alttd.GUI.GUIInventory; import com.alttd.VillagerUI; import com.alttd.config.Config; import com.alttd.objects.EconUser; -import com.alttd.objects.VillagerType; +import com.alttd.objects.ShopVillagerType; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; @@ -48,7 +48,7 @@ public class OpenGUI extends GUIInventory { } } - public OpenGUI(VillagerType villagerType, EconUser econUser) { + public OpenGUI(ShopVillagerType villagerType, EconUser econUser) { super(InventoryType.HOPPER, miniMessage.deserialize(Config.INITIAL_VILLAGER_WINDOW, TagResolver.resolver(Placeholder.unparsed("trader", villagerType.getDisplayName()), Placeholder.unparsed("points", String.valueOf(Objects.requireNonNullElse( diff --git a/src/main/java/com/alttd/GUI/windows/TradeGUI.java b/src/main/java/com/alttd/GUI/windows/TradeGUI.java new file mode 100644 index 0000000..79d3e45 --- /dev/null +++ b/src/main/java/com/alttd/GUI/windows/TradeGUI.java @@ -0,0 +1,166 @@ +package com.alttd.GUI.windows; + +import com.alttd.GUI.GUIMerchant; +import com.alttd.VillagerUI; +import com.alttd.config.Config; +import com.alttd.config.WorthConfig; +import com.alttd.events.SpawnShopEvent; +import com.alttd.objects.BlackMarketVillagerType; +import com.alttd.objects.EconUser; +import com.alttd.util.Logger; +import com.alttd.util.Utilities; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.milkbowl.vault.economy.Economy; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class TradeGUI extends GUIMerchant { + + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + private static final ItemStack confirm; + + private long lastClicked = 0; + + static { + ItemStack itemStack = new ItemStack(Material.EMERALD_BLOCK); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(MiniMessage.miniMessage().deserialize(Config.CONFIRM_BUTTON)); + itemStack.setItemMeta(itemMeta); + confirm = itemStack; + } + + public TradeGUI(BlackMarketVillagerType villagerType, EconUser econUser) { + super(MiniMessage.miniMessage().deserialize(Config.TRADE_WINDOW, TagResolver.resolver( + Placeholder.unparsed("trader", villagerType.getDisplayName()), + Placeholder.unparsed("remaining_trades", String.valueOf(villagerType.getRemainingTrades(econUser.getUuid())))) + ), villagerType); + for (ItemStack is : villagerType.getTrading(econUser.getUuid())) { + ItemStack itemStack = is.clone(); + Double price = WorthConfig.trade.getOrDefault(itemStack.getType(), null); + if (price == null) { + Logger.warning("No price found for" + itemStack.getType().name()); + continue; + } + addItem(itemStack, + getPriceItem(Utilities.round(price, 2)), + null, + player -> trade(villagerType, player, itemStack.getType(), itemStack.getAmount(), price) + ); + } + } + + private void trade(BlackMarketVillagerType villagerType, Player player, Material material, int amount, Double price) { + EconUser econUser = EconUser.getUser(player.getUniqueId()); + if (econUser == null) { + player.sendMiniMessage(Config.LOADING_ECON_DATA, null); + return; + } + + setItem(0, getBuyItemHover(material, amount, price), null); + setItem(1, confirm, player1 -> + trade2(player1, material, amount, villagerType, price)); + player.updateInventory(); + } + + private ItemStack getBuyItemHover(Material material, int amount, double price) { + ItemStack itemStack = new ItemStack(material); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(miniMessage.deserialize(Config.TRANSACTION_ITEM_NAME, TagResolver.resolver( + Placeholder.unparsed("item_name", material.name()) + ))); + List lore = new ArrayList<>(); + for (String entry : Config.TRANSACTION_ITEM_DESCRIPTION) { + lore.add(miniMessage.deserialize(entry, TagResolver.resolver( + Placeholder.unparsed("amount", String.valueOf(amount)), + Placeholder.unparsed("price", String.format("%,.2f", price)) + ))); + } + itemMeta.lore(lore); + itemStack.setItemMeta(itemMeta); + return itemStack; + } + + private void trade2(Player player, Material material, int amount, BlackMarketVillagerType villagerType, double price) { + long newTime = new Date().getTime(); + if ((newTime - 120) > lastClicked) + lastClicked = newTime; + else { + player.sendMiniMessage(Config.CLICKING_TOO_FAST, null); + return; + } + + UUID uuid = player.getUniqueId(); + if (villagerType.getRemainingTrades(uuid) <= 0) { + player.sendMiniMessage(Config.NO_TRADES_REMAINING, null); + return; + } + + Economy econ = VillagerUI.getInstance().getEconomy(); + double balance = econ.getBalance(player); + + if (balance < price) { + player.sendMiniMessage(Config.NOT_ENOUGH_MONEY, TagResolver.resolver( + Placeholder.unparsed("money", String.valueOf(Utilities.round(balance, 2))), + Placeholder.unparsed("price", String.format("%,.2f", price)) + )); + return; + } + + AtomicInteger atomicInteger = new AtomicInteger(0); + Arrays.stream(player.getInventory().getContents()) + .filter(itemStack -> itemStack == null || itemStack.getType().equals(material)) + .forEach(itemStack -> { + if (itemStack == null) + atomicInteger.addAndGet(material.getMaxStackSize()); + else + atomicInteger.addAndGet(itemStack.getMaxStackSize() - itemStack.getAmount()); + }); + if (atomicInteger.get() < amount) { + player.sendMiniMessage(Config.NOT_ENOUGH_SPACE, TagResolver.resolver( + Placeholder.unparsed("space", String.valueOf(atomicInteger.get())), + Placeholder.unparsed("amount", String.valueOf(amount)) + )); + return; + } + econ.withdrawPlayer(player, price); + villagerType.makeTrade(uuid); + player.getInventory().addItem(new ItemStack(material, amount)); + + player.sendMiniMessage(Config.TRADED_ITEM, TagResolver.resolver( + Placeholder.parsed("amount", String.valueOf(amount)), + Placeholder.parsed("item", Utilities.capitalize(material.name() + .toLowerCase().replaceAll("_", " "))), + Placeholder.parsed("price", String.format("%,.2f", price)), + Placeholder.parsed("villager_name", villagerType.getDisplayName()), + Placeholder.parsed("trades_remaining", String.valueOf(villagerType.getRemainingTrades(uuid))) + )); + + Bukkit.getServer().getPluginManager() + .callEvent(new SpawnShopEvent(player, material, amount, price, true)); + trade(villagerType, player, material, amount, price); + } + + private ItemStack getPriceItem(double price) { + if (price < 0) return nameItem(new ItemStack(Material.BARRIER), -1); + else if (price <= 10) return nameItem(new ItemStack(Material.IRON_INGOT), price); + else if (price <= 100) return nameItem(new ItemStack(Material.GOLD_INGOT), price); + else if (price <= 500) return nameItem(new ItemStack(Material.DIAMOND), price); + else return nameItem(new ItemStack(Material.NETHERITE_INGOT), price); + } + + private ItemStack nameItem(ItemStack itemStack, double price) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(miniMessage.deserialize("" + price + "")); //TODO configurable + itemStack.setItemMeta(itemMeta); + return itemStack; + } +} diff --git a/src/main/java/com/alttd/commands/subcommands/CommandBuy.java b/src/main/java/com/alttd/commands/subcommands/CommandBuy.java index cd70ad9..2ca9934 100644 --- a/src/main/java/com/alttd/commands/subcommands/CommandBuy.java +++ b/src/main/java/com/alttd/commands/subcommands/CommandBuy.java @@ -6,6 +6,7 @@ import com.alttd.config.WorthConfig; import com.alttd.objects.EconUser; import com.alttd.objects.Price; import com.alttd.objects.VillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Logger; import com.alttd.util.Utilities; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; @@ -43,7 +44,7 @@ public class CommandBuy extends SubCommand { return true; } Material item = Material.valueOf(args[1].toUpperCase()); - Optional optionalVillagerType = VillagerType.getVillagerTypes().stream() + Optional optionalVillagerType = VillagerTypeManager.getVillagerTypes().stream() .filter(villagerType -> villagerType.getBuying().stream() .map(ItemStack::getType) .anyMatch(material -> material.equals(item))) diff --git a/src/main/java/com/alttd/commands/subcommands/CommandCreateVillager.java b/src/main/java/com/alttd/commands/subcommands/CommandCreateVillager.java index 8da230e..5fafc7f 100644 --- a/src/main/java/com/alttd/commands/subcommands/CommandCreateVillager.java +++ b/src/main/java/com/alttd/commands/subcommands/CommandCreateVillager.java @@ -5,6 +5,7 @@ import com.alttd.config.Config; import com.alttd.config.VillagerConfig; import com.alttd.objects.LoadedVillagers; import com.alttd.objects.VillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Utilities; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; @@ -29,7 +30,7 @@ public class CommandCreateVillager extends SubCommand { return true; } - Optional first = VillagerType.getVillagerTypes().stream().filter(villagerType -> villagerType.getName().equalsIgnoreCase(args[1])).findFirst(); + Optional first = VillagerTypeManager.getVillagerTypes().stream().filter(villagerType -> villagerType.getName().equalsIgnoreCase(args[1])).findFirst(); if (first.isEmpty()) { commandSender.sendMiniMessage(getHelpMessage(), null); return true; @@ -77,7 +78,7 @@ public class CommandCreateVillager extends SubCommand { public List getTabComplete(CommandSender commandSender, String[] args) { List res = new ArrayList<>(); switch (args.length) { - case 2 -> res.addAll(VillagerType.getVillagerTypes().stream() + case 2 -> res.addAll(VillagerTypeManager.getVillagerTypes().stream() .map(VillagerType::getName) .collect(Collectors.toList())); case 3 -> res.addAll(Arrays.stream(Villager.Type.values()).map(Enum::name).collect(Collectors.toList())); diff --git a/src/main/java/com/alttd/commands/subcommands/CommandPoints.java b/src/main/java/com/alttd/commands/subcommands/CommandPoints.java index 7aeb251..2c0d6ca 100644 --- a/src/main/java/com/alttd/commands/subcommands/CommandPoints.java +++ b/src/main/java/com/alttd/commands/subcommands/CommandPoints.java @@ -5,6 +5,7 @@ import com.alttd.config.Config; import com.alttd.objects.EconUser; import com.alttd.objects.Price; import com.alttd.objects.VillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Logger; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.kyori.adventure.text.Component; @@ -44,7 +45,7 @@ public class CommandPoints extends SubCommand { Object2ObjectOpenHashMap pointsMap = user.getPointsMap(); pointsMap.keySet().forEach(key -> { - VillagerType villagerType = VillagerType.getVillagerType(key); + VillagerType villagerType = VillagerTypeManager.getVillagerType(key); if (villagerType == null) { Logger.warning("Player % has unused villager type % in their point list.", player.getName(), key); return; @@ -54,7 +55,7 @@ public class CommandPoints extends SubCommand { allPointsAreZero.set(false); ref.message = ref.message.append(miniMessage.deserialize("\n", TagResolver.resolver())); ref.message = ref.message.append(miniMessage.deserialize(Config.POINTS_CONTENT, TagResolver.resolver( - Placeholder.unparsed("villager_type", VillagerType.getVillagerType(key).getDisplayName()), + Placeholder.unparsed("villager_type", VillagerTypeManager.getVillagerType(key).getDisplayName()), Placeholder.unparsed("points", String.valueOf(currentPoints)), Placeholder.unparsed("buy_multiplier", String.valueOf(Price.getCurrentMultiplier(currentPoints, true))), Placeholder.unparsed("sell_multiplier", String.valueOf(Price.getCurrentMultiplier(currentPoints, false)))))); @@ -65,7 +66,7 @@ public class CommandPoints extends SubCommand { } else if (args.length == 2) { if (args[1].equals("all")) { - for (VillagerType villagerType : VillagerType.getVillagerTypes()) { + for (VillagerType villagerType : VillagerTypeManager.getVillagerTypes()) { Object2ObjectOpenHashMap pointsMap = user.getPointsMap(); int currentPoints = pointsMap.getOrDefault(villagerType.getName(), 0); @@ -78,7 +79,7 @@ public class CommandPoints extends SubCommand { ))); } } else { - VillagerType villagerType = VillagerType.getVillagerType(args[1].toLowerCase()); + VillagerType villagerType = VillagerTypeManager.getVillagerType(args[1].toLowerCase()); Object2ObjectOpenHashMap pointsMap = user.getPointsMap(); if (villagerType == null) { player.sendMiniMessage(Config.NOT_A_VILLAGER, TagResolver.resolver(Placeholder.unparsed("villager_type", args[1]))); @@ -108,7 +109,7 @@ public class CommandPoints extends SubCommand { public List getTabComplete(CommandSender commandSender, String[] args) { List res = new ArrayList<>(); if (args.length == 2) - res.addAll(VillagerType.getVillagerTypes().stream() + res.addAll(VillagerTypeManager.getVillagerTypes().stream() .map(VillagerType::getName) .collect(Collectors.toList())); res.add("all"); diff --git a/src/main/java/com/alttd/commands/subcommands/CommandSell.java b/src/main/java/com/alttd/commands/subcommands/CommandSell.java index dc7d892..2b1c773 100644 --- a/src/main/java/com/alttd/commands/subcommands/CommandSell.java +++ b/src/main/java/com/alttd/commands/subcommands/CommandSell.java @@ -6,6 +6,7 @@ import com.alttd.config.WorthConfig; import com.alttd.objects.EconUser; import com.alttd.objects.Price; import com.alttd.objects.VillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Logger; import com.alttd.util.Utilities; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; @@ -43,7 +44,7 @@ public class CommandSell extends SubCommand { return true; } Material item = Material.valueOf(args[1].toUpperCase()); - Optional optionalVillagerType = VillagerType.getVillagerTypes().stream() + Optional optionalVillagerType = VillagerTypeManager.getVillagerTypes().stream() .filter(villagerType -> villagerType.getSelling().stream() .map(ItemStack::getType) .anyMatch(material -> material.equals(item))) diff --git a/src/main/java/com/alttd/config/Config.java b/src/main/java/com/alttd/config/Config.java index 2939a6f..67a31cc 100644 --- a/src/main/java/com/alttd/config/Config.java +++ b/src/main/java/com/alttd/config/Config.java @@ -1,14 +1,18 @@ package com.alttd.config; +import com.alttd.objects.BlackMarketVillagerType; import com.alttd.objects.ItemStackComparator; -import com.alttd.objects.VillagerType; +import com.alttd.objects.ShopVillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Logger; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import java.io.File; -import java.util.*; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; public final class Config extends AbstractConfig { static Config config; @@ -52,11 +56,13 @@ public final class Config extends AbstractConfig { public static String INITIAL_VILLAGER_WINDOW = " points: "; public static String BUY_WINDOW = " points: "; public static String SELL_WINDOW = " points: "; + public static String TRADE_WINDOW = " trades left: "; private static void loadUI() { INITIAL_VILLAGER_WINDOW = config.getString("ui.initial-window-name", INITIAL_VILLAGER_WINDOW); BUY_WINDOW = config.getString("ui.buy-window-name", BUY_WINDOW); SELL_WINDOW = config.getString("ui.sell-window-name", SELL_WINDOW); + TRADE_WINDOW = config.getString("ui.trade-window-name", TRADE_WINDOW); } public static String HELP_MESSAGE_WRAPPER = "VillagerShopUI help:\n"; @@ -82,11 +88,13 @@ public final class Config extends AbstractConfig { public static String NO_PERMISSION = "You do not have permission to do that."; public static String NO_CONSOLE = "You cannot use this command from console."; public static String CLICKING_TOO_FAST = "You're clicking too fast."; + public static String NO_TRADES_REMAINING = "No remaining trades, wait until the next reboot"; private static void loadGeneric() { NO_PERMISSION = config.getString("generic.no-permission", NO_PERMISSION); NO_CONSOLE = config.getString("generic.no-console", NO_CONSOLE); CLICKING_TOO_FAST = config.getString("generic.clicking-too-fast", CLICKING_TOO_FAST); + NO_TRADES_REMAINING = config.getString("generic.no-trades-remaining", NO_TRADES_REMAINING); } public static String VILLAGER_NAME = ""; @@ -111,6 +119,8 @@ public final class Config extends AbstractConfig { " for !"; public static String SOLD_ITEM = "You sold for and got points for a total of " + " for !"; + + public static String TRADED_ITEM = "You traded for , you have trades remaining!"; public static String REMOVED_VILLAGER = "Removed villager with uuid "; public static String POINTS_HEADER = "Villager points for : "; public static String POINTS_CONTENT = ": points: " + @@ -133,6 +143,7 @@ public final class Config extends AbstractConfig { NOT_ENOUGH_SPACE = config.getString("messages.not-enough-space", NOT_ENOUGH_SPACE); PURCHASED_ITEM = config.getString("messages.purchased-item", PURCHASED_ITEM); SOLD_ITEM = config.getString("messages.sold-item", SOLD_ITEM); + TRADED_ITEM = config.getString("messages.traded-item", TRADED_ITEM); REMOVED_VILLAGER = config.getString("messages.removed-villager", REMOVED_VILLAGER); POINTS_HEADER = config.getString("messages.points-header", POINTS_HEADER); POINTS_CONTENT = config.getString("messages.points-content", POINTS_CONTENT); @@ -153,7 +164,7 @@ public final class Config extends AbstractConfig { } private static void loadVillagerTypes() { - VillagerType.clearVillagerTypes(); + VillagerTypeManager.clearVillagerTypes(); ConfigurationSection configurationSection = config.getConfigurationSection("villager-types"); if (configurationSection == null) { Logger.warning("No villager types found in config."); @@ -169,13 +180,24 @@ public final class Config extends AbstractConfig { if (villagerType == null) return; - VillagerType.addVillagerType(new VillagerType( - key, - villagerType.getString("name"), - loadProducts(villagerType.getConfigurationSection("buying")), - loadProducts(villagerType.getConfigurationSection("selling")), - villagerType.getString("profession")) - ); + if (villagerType.contains("trading")) { + VillagerTypeManager.addVillagerType(new BlackMarketVillagerType( + key, + villagerType.getString("name"), + villagerType.getString("profession"), + villagerType.getInt("max-available-items", 15), + villagerType.getInt("max-trades-per-reboot", 5), + loadProducts(villagerType.getConfigurationSection("trading"))) + ); + } else { + VillagerTypeManager.addVillagerType(new ShopVillagerType( + key, + villagerType.getString("name"), + loadProducts(villagerType.getConfigurationSection("buying")), + loadProducts(villagerType.getConfigurationSection("selling")), + villagerType.getString("profession")) + ); + } }); } diff --git a/src/main/java/com/alttd/config/VillagerConfig.java b/src/main/java/com/alttd/config/VillagerConfig.java index 207c0bf..ef48e02 100644 --- a/src/main/java/com/alttd/config/VillagerConfig.java +++ b/src/main/java/com/alttd/config/VillagerConfig.java @@ -2,6 +2,7 @@ package com.alttd.config; import com.alttd.objects.LoadedVillagers; import com.alttd.objects.VillagerType; +import com.alttd.objects.VillagerTypeManager; import com.alttd.util.Logger; import java.util.UUID; @@ -26,7 +27,7 @@ public class VillagerConfig extends AbstractConfig { private static void loadVillagers() { LoadedVillagers.clearLoadedVillagers(); config.getConfigurationSection("").getKeys(false).forEach(key -> { - VillagerType villagerType = VillagerType.getVillagerType(config.getString(key, "")); + VillagerType villagerType = VillagerTypeManager.getVillagerType(config.getString(key, "")); if (villagerType != null) LoadedVillagers.addLoadedVillager(UUID.fromString(key), villagerType); else diff --git a/src/main/java/com/alttd/config/WorthConfig.java b/src/main/java/com/alttd/config/WorthConfig.java index c329bbc..bc69ee0 100644 --- a/src/main/java/com/alttd/config/WorthConfig.java +++ b/src/main/java/com/alttd/config/WorthConfig.java @@ -2,6 +2,7 @@ package com.alttd.config; import com.alttd.VillagerUI; import com.alttd.objects.Price; +import com.alttd.objects.PriceRange; import com.alttd.util.Logger; import com.alttd.util.Utilities; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -30,9 +31,31 @@ public class WorthConfig extends AbstractConfig { public static Object2ObjectOpenHashMap buy = new Object2ObjectOpenHashMap<>(); public static Object2ObjectOpenHashMap sell = new Object2ObjectOpenHashMap<>(); + public static Object2ObjectOpenHashMap trade = new Object2ObjectOpenHashMap<>(); private static void loadWorth() { //TODO test after removing points loadWorth("buy", buy); loadWorth("sell", sell); + loadTradeWorth("trade", trade); + } + + private static void loadTradeWorth(String path, Object2ObjectOpenHashMap map) { + map.clear(); + ConfigurationSection worth = config.getConfigurationSection(path); + if (worth == null) { + Logger.severe("No ? in worth.yml! Stopping VillagerUI.", path); + VillagerUI.getInstance().getServer().getPluginManager().disablePlugin(VillagerUI.getInstance()); + return; + } + Set materials = worth.getKeys(false); + for (String key : materials) { + if (key == null) { + Logger.severe("Null key in worth.yml?"); + continue; + } + Material material = Material.getMaterial(key); + + map.put(material, new PriceRange(Utilities.round(worth.getDouble(key + ".lower"), 2), Utilities.round(worth.getDouble(key + ".upper"), 2)).getRandomPrice()); + } } private static void loadWorth(String path, Object2ObjectOpenHashMap map) { diff --git a/src/main/java/com/alttd/events/SpawnShopEvent.java b/src/main/java/com/alttd/events/SpawnShopEvent.java index da5c36a..0ee1012 100644 --- a/src/main/java/com/alttd/events/SpawnShopEvent.java +++ b/src/main/java/com/alttd/events/SpawnShopEvent.java @@ -31,6 +31,16 @@ public final class SpawnShopEvent extends Event { return player; } + public SpawnShopEvent(Player player, Material material, int amount, double price, boolean buy) { + this.player = player; + this.amount = amount; + this.price = price; + this.item = material; + this.pointsBefore = 0; + this.pointsAfter = 0; + this.buy = buy; + } + public int amount() { return amount; } diff --git a/src/main/java/com/alttd/events/VillagerEvents.java b/src/main/java/com/alttd/events/VillagerEvents.java index 3b6035d..bc4fab5 100644 --- a/src/main/java/com/alttd/events/VillagerEvents.java +++ b/src/main/java/com/alttd/events/VillagerEvents.java @@ -1,14 +1,11 @@ package com.alttd.events; import com.alttd.GUI.windows.OpenGUI; +import com.alttd.GUI.windows.TradeGUI; import com.alttd.VillagerUI; import com.alttd.config.Config; import com.alttd.config.VillagerConfig; -import com.alttd.objects.EconUser; -import com.alttd.objects.LoadedVillagers; -import com.alttd.objects.VillagerType; -import com.alttd.util.Utilities; -import jdk.jshell.execution.Util; +import com.alttd.objects.*; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; @@ -33,7 +30,6 @@ public class VillagerEvents implements Listener { VillagerType loadedVillager = LoadedVillagers.getLoadedVillager(villager.getUniqueId()); if (loadedVillager == null) return; - Player player = event.getPlayer(); event.setCancelled(true); if (!player.hasPermission(loadedVillager.getPermission())) { @@ -48,13 +44,23 @@ public class VillagerEvents implements Listener { new BukkitRunnable() { @Override public void run() { - OpenGUI openGUI = new OpenGUI(loadedVillager, user); - new BukkitRunnable() { - @Override - public void run() { - openGUI.open(player); - } - }.runTask(VillagerUI.getInstance()); + if (loadedVillager instanceof BlackMarketVillagerType blackMarketVillagerType) { + TradeGUI tradeGUI = new TradeGUI(blackMarketVillagerType, user); + new BukkitRunnable() { + @Override + public void run() { + tradeGUI.open(player); + } + }.runTask(VillagerUI.getInstance()); + } else if (loadedVillager instanceof ShopVillagerType shopVillagerType) { + OpenGUI openGUI = new OpenGUI(shopVillagerType, user); + new BukkitRunnable() { + @Override + public void run() { + openGUI.open(player); + } + }.runTask(VillagerUI.getInstance()); + } } }.runTaskAsynchronously(VillagerUI.getInstance()); } diff --git a/src/main/java/com/alttd/objects/BlackMarketVillagerType.java b/src/main/java/com/alttd/objects/BlackMarketVillagerType.java new file mode 100644 index 0000000..09f2abd --- /dev/null +++ b/src/main/java/com/alttd/objects/BlackMarketVillagerType.java @@ -0,0 +1,88 @@ +package com.alttd.objects; + +import org.bukkit.entity.Villager; +import org.bukkit.inventory.ItemStack; + +import java.util.*; + +public class BlackMarketVillagerType implements VillagerType { + + private final String name; + private final String displayName; + private final Villager.Profession profession; + private final Set trading; + private final int maxAvailableItems; + private final int maxTradesPerReboot; + private final HashMap> playerTrades = new HashMap<>(); + private final HashMap playerTradeCount = new HashMap<>(); + + public BlackMarketVillagerType(String name, String displayName, String profession, int maxAvailableItems, int maxTradesPerReboot, Set trading) { + this.name = name; + this.displayName = displayName; + this.profession = Villager.Profession.valueOf(profession.toUpperCase()); + this.maxAvailableItems = maxAvailableItems; + this.maxTradesPerReboot = maxTradesPerReboot; + this.trading = trading; + } + + private Set getResizedCustomTradingSet() { + Set randomSubset = new TreeSet<>(new ItemStackComparator()); + if (trading.size() < maxAvailableItems) { + randomSubset.addAll(trading); + return randomSubset; + } + List list = trading.stream().toList(); + Random random = new Random(); + + for (int i = 0; i < maxAvailableItems; i++) { + int randomIndex = random.nextInt(list.size()); + randomSubset.add(list.get(randomIndex)); + } + return randomSubset; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getDisplayName() { + return displayName; + } + + @Override + public Set getBuying() { + return Set.of(); + } + + @Override + public Set getSelling() { + return Set.of(); + } + + public Set getTrading(UUID uuid) { + if (!playerTrades.containsKey(uuid)) { + playerTrades.put(uuid, getResizedCustomTradingSet()); + } + return playerTrades.get(uuid); + } + + public void makeTrade(UUID uuid) { + playerTradeCount.put(uuid, playerTradeCount.getOrDefault(uuid, 0) + 1); + } + + public int getRemainingTrades(UUID uuid) { + return maxTradesPerReboot - playerTradeCount.getOrDefault(uuid, 0); + } + + @Override + public Villager.Profession getProfession() { + return profession; + } + + @Override + public String getPermission() { + return "villagerui.villager." + getName(); + } +} diff --git a/src/main/java/com/alttd/objects/PriceRange.java b/src/main/java/com/alttd/objects/PriceRange.java new file mode 100644 index 0000000..9b1a3ae --- /dev/null +++ b/src/main/java/com/alttd/objects/PriceRange.java @@ -0,0 +1,27 @@ +package com.alttd.objects; + +import java.util.Random; + +public class PriceRange { + private final double lowerBound; + private final double upperBound; + private final Random random; + + public PriceRange(double lowerBound, double upperBound) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + this.random = new Random(); + } + + public double getLowerBound() { + return lowerBound; + } + + public double getUpperBound() { + return upperBound; + } + + public double getRandomPrice() { + return lowerBound + (random.nextDouble() * (upperBound - lowerBound)); + } +} diff --git a/src/main/java/com/alttd/objects/ShopVillagerType.java b/src/main/java/com/alttd/objects/ShopVillagerType.java new file mode 100644 index 0000000..da2be58 --- /dev/null +++ b/src/main/java/com/alttd/objects/ShopVillagerType.java @@ -0,0 +1,47 @@ +package com.alttd.objects; + +import org.bukkit.entity.Villager; +import org.bukkit.inventory.ItemStack; + +import java.util.Set; +import java.util.TreeSet; + +public class ShopVillagerType implements VillagerType{ + private final String name; + private final String displayName; + private final Set buying; + private final Set selling; + private final Villager.Profession profession; + + public ShopVillagerType(String name, String displayName, TreeSet buying, TreeSet selling, String profession) { + this.name = name; + this.displayName = displayName; + this.buying = buying; + this.selling = selling; + this.profession = Villager.Profession.valueOf(profession.toUpperCase()); + } + + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + public Set getBuying() { + return buying; + } + + public Set getSelling() { + return selling; + } + + public Villager.Profession getProfession() { + return profession; + } + + public String getPermission() { + return "villagerui.villager." + getName(); + } +} diff --git a/src/main/java/com/alttd/objects/VillagerType.java b/src/main/java/com/alttd/objects/VillagerType.java index ce6911b..85afaee 100644 --- a/src/main/java/com/alttd/objects/VillagerType.java +++ b/src/main/java/com/alttd/objects/VillagerType.java @@ -3,63 +3,19 @@ package com.alttd.objects; import org.bukkit.entity.Villager; import org.bukkit.inventory.ItemStack; -import java.util.HashSet; import java.util.Set; -import java.util.TreeSet; -public class VillagerType { - private static final Set villagerTypes = new HashSet<>(); +public interface VillagerType { - public static Set getVillagerTypes() { - return villagerTypes; - } + String getName(); - public static VillagerType getVillagerType(String name) { - return villagerTypes.stream().filter(villagerType -> villagerType.getName().equals(name)).findFirst().orElse(null); - } + String getDisplayName(); - public static void addVillagerType(VillagerType villagerType) { - villagerTypes.add(villagerType); - } + Set getBuying(); - public static void clearVillagerTypes() { - villagerTypes.clear(); - } - private final String name; - private final String displayName; - private final Set buying; - private final Set selling; - private final Villager.Profession profession; + Set getSelling(); - public VillagerType(String name, String displayName, TreeSet buying, TreeSet selling, String profession) { - this.name = name; - this.displayName = displayName; - this.buying = buying; - this.selling = selling; - this.profession = Villager.Profession.valueOf(profession.toUpperCase()); - } + Villager.Profession getProfession(); - public String getName() { - return name; - } - - public String getDisplayName() { - return displayName; - } - - public Set getBuying() { - return buying; - } - - public Set getSelling() { - return selling; - } - - public Villager.Profession getProfession() { - return profession; - } - - public String getPermission() { - return "villagerui.villager." + getName(); - } + String getPermission(); } diff --git a/src/main/java/com/alttd/objects/VillagerTypeManager.java b/src/main/java/com/alttd/objects/VillagerTypeManager.java new file mode 100644 index 0000000..3370cb4 --- /dev/null +++ b/src/main/java/com/alttd/objects/VillagerTypeManager.java @@ -0,0 +1,24 @@ +package com.alttd.objects; + +import java.util.HashSet; +import java.util.Set; + +public class VillagerTypeManager { + private static final Set villagerTypes = new HashSet<>(); + + public static Set getVillagerTypes() { + return villagerTypes; + } + + public static VillagerType getVillagerType(String name) { + return villagerTypes.stream().filter(villagerType -> villagerType.getName().equals(name)).findFirst().orElse(null); + } + + public static void addVillagerType(VillagerType villagerType) { + villagerTypes.add(villagerType); + } + + public static void clearVillagerTypes() { + villagerTypes.clear(); + } +}