Added BlackMarketVillagerType

This commit is contained in:
Teriuihi 2023-08-05 03:02:23 +02:00
parent cea765e157
commit b0f4d39b47
16 changed files with 460 additions and 86 deletions

View File

@ -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(

View File

@ -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<Component> 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("<green>" + price + "</green>")); //TODO configurable
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@ -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<VillagerType> optionalVillagerType = VillagerType.getVillagerTypes().stream()
Optional<VillagerType> optionalVillagerType = VillagerTypeManager.getVillagerTypes().stream()
.filter(villagerType -> villagerType.getBuying().stream()
.map(ItemStack::getType)
.anyMatch(material -> material.equals(item)))

View File

@ -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<VillagerType> first = VillagerType.getVillagerTypes().stream().filter(villagerType -> villagerType.getName().equalsIgnoreCase(args[1])).findFirst();
Optional<VillagerType> 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<String> getTabComplete(CommandSender commandSender, String[] args) {
List<String> 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()));

View File

@ -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<String, Integer> 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<String, Integer> 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<String, Integer> 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<String> getTabComplete(CommandSender commandSender, String[] args) {
List<String> 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");

View File

@ -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<VillagerType> optionalVillagerType = VillagerType.getVillagerTypes().stream()
Optional<VillagerType> optionalVillagerType = VillagerTypeManager.getVillagerTypes().stream()
.filter(villagerType -> villagerType.getSelling().stream()
.map(ItemStack::getType)
.anyMatch(material -> material.equals(item)))

View File

@ -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 = "<trader> points: <points>";
public static String BUY_WINDOW = "<trader> points: <points>";
public static String SELL_WINDOW = "<trader> points: <points>";
public static String TRADE_WINDOW = "<trader> trades left: <remaining_trades>";
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 = "<gold>VillagerShopUI help:\n<commands></gold>";
@ -82,11 +88,13 @@ public final class Config extends AbstractConfig {
public static String NO_PERMISSION = "<red>You do not have permission to do that.</red>";
public static String NO_CONSOLE = "<red>You cannot use this command from console.</red>";
public static String CLICKING_TOO_FAST = "<red>You're clicking too fast.</red>";
public static String NO_TRADES_REMAINING = "<red>No remaining trades, wait until the next reboot</red>";
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 = "<green><name></green>";
@ -111,6 +119,8 @@ public final class Config extends AbstractConfig {
"<total_points> for <villager_name>!</green>";
public static String SOLD_ITEM = "<green>You sold <amount> <item> for <price> and got <points> points for a total of " +
"<total_points> for <villager_name>!</green>";
public static String TRADED_ITEM = "<green>You traded <amount> <item> for <price>, you have <trades_remaining> trades remaining!</green>";
public static String REMOVED_VILLAGER = "<green>Removed villager with uuid <uuid></green>";
public static String POINTS_HEADER = "<gold>Villager points for <player>: ";
public static String POINTS_CONTENT = "<gold><villager_type>: points:<dark_aqua><points></dark_aqua> " +
@ -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"))
);
}
});
}

View File

@ -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

View File

@ -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<Material, Price> buy = new Object2ObjectOpenHashMap<>();
public static Object2ObjectOpenHashMap<Material, Price> sell = new Object2ObjectOpenHashMap<>();
public static Object2ObjectOpenHashMap<Material, Double> 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<Material, Double> 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<String> 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<Material, Price> map) {

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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<ItemStack> trading;
private final int maxAvailableItems;
private final int maxTradesPerReboot;
private final HashMap<UUID, Set<ItemStack>> playerTrades = new HashMap<>();
private final HashMap<UUID, Integer> playerTradeCount = new HashMap<>();
public BlackMarketVillagerType(String name, String displayName, String profession, int maxAvailableItems, int maxTradesPerReboot, Set<ItemStack> 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<ItemStack> getResizedCustomTradingSet() {
Set<ItemStack> randomSubset = new TreeSet<>(new ItemStackComparator());
if (trading.size() < maxAvailableItems) {
randomSubset.addAll(trading);
return randomSubset;
}
List<ItemStack> 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<ItemStack> getBuying() {
return Set.of();
}
@Override
public Set<ItemStack> getSelling() {
return Set.of();
}
public Set<ItemStack> 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();
}
}

View File

@ -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));
}
}

View File

@ -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<ItemStack> buying;
private final Set<ItemStack> selling;
private final Villager.Profession profession;
public ShopVillagerType(String name, String displayName, TreeSet<ItemStack> buying, TreeSet<ItemStack> 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<ItemStack> getBuying() {
return buying;
}
public Set<ItemStack> getSelling() {
return selling;
}
public Villager.Profession getProfession() {
return profession;
}
public String getPermission() {
return "villagerui.villager." + getName();
}
}

View File

@ -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<VillagerType> villagerTypes = new HashSet<>();
public interface VillagerType {
public static Set<VillagerType> 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<ItemStack> getBuying();
public static void clearVillagerTypes() {
villagerTypes.clear();
}
private final String name;
private final String displayName;
private final Set<ItemStack> buying;
private final Set<ItemStack> selling;
private final Villager.Profession profession;
Set<ItemStack> getSelling();
public VillagerType(String name, String displayName, TreeSet<ItemStack> buying, TreeSet<ItemStack> 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<ItemStack> getBuying() {
return buying;
}
public Set<ItemStack> getSelling() {
return selling;
}
public Villager.Profession getProfession() {
return profession;
}
public String getPermission() {
return "villagerui.villager." + getName();
}
String getPermission();
}

View File

@ -0,0 +1,24 @@
package com.alttd.objects;
import java.util.HashSet;
import java.util.Set;
public class VillagerTypeManager {
private static final Set<VillagerType> villagerTypes = new HashSet<>();
public static Set<VillagerType> 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();
}
}