Initial commit

This commit is contained in:
Teriuihi 2022-01-03 22:26:15 +01:00
parent be656b4606
commit f5c096eb2b
23 changed files with 0 additions and 1562 deletions

View File

@ -1,20 +0,0 @@
package com.alttd.GUI;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.Merchant;
import java.util.HashMap;
import java.util.UUID;
public interface GUI {
HashMap<UUID, GUI> GUIByUUID = new HashMap<>();
void open(Player player);
GUIAction getAction(int slot);
Inventory getInventory();
Merchant getMerchant();
}

View File

@ -1,7 +0,0 @@
package com.alttd.GUI;
import org.bukkit.entity.Player;
public interface GUIAction {
void click(Player player);
}

View File

@ -1,50 +0,0 @@
package com.alttd.GUI;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Merchant;
import java.util.HashMap;
public abstract class GUIInventory implements GUI {
protected final Inventory inventory;
protected final HashMap<Integer, GUIAction> actions;
public GUIInventory(InventoryType type, Component name) {
inventory = Bukkit.createInventory(null, type, name);
actions = new HashMap<>();
}
public Merchant getMerchant() {
return null;
}
public Inventory getInventory() {
return inventory;
}
public void setItem(int slot, ItemStack stack, GUIAction action){
inventory.setItem(slot, stack);
if (action != null){
actions.put(slot, action);
}
}
public void setItem(int slot, ItemStack stack){
setItem(slot, stack, null);
}
public void open(Player player){
player.openInventory(inventory);
GUIByUUID.put(player.getUniqueId(), this);
}
public GUIAction getAction(int slot) {
return actions.get(slot);
}
}

View File

@ -1,92 +0,0 @@
package com.alttd.GUI;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.TradeSelectEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
public class GUIListener implements Listener {
/**
* Handles clicking inside a gui
* @param event gui click event
*/
@EventHandler
public void onClick(InventoryClickEvent event){
if (!(event.getWhoClicked() instanceof Player player)){
return;
}
GUI gui = GUI.GUIByUUID.get(player.getUniqueId());
if (gui == null || gui.getInventory() == null) {
if (event.getSlotType().equals(InventoryType.SlotType.CRAFTING) && event.getRawSlot() < 2)
event.setCancelled(true);
else if (event.getRawSlot() == 2 && event.getSlotType().equals(InventoryType.SlotType.RESULT)) {
event.setCancelled(true);
onResultSlotClick(event, gui);
}
return;
}
if (!gui.getInventory().equals(event.getInventory())) {
return;
}
event.setCancelled(true);
GUIAction action = gui.getAction(event.getSlot());
if (action != null){
action.click(player);
}
}
/**
* Handles clicking on an item in a gui result slot
* @param event click event
* @param gui gui that was clicked in
*/
private void onResultSlotClick(InventoryClickEvent event, GUI gui) {
ItemStack currentItem = event.getCurrentItem();
if (currentItem == null)
return;
if (event.getClick().isShiftClick())
event.getWhoClicked().sendMessage(MiniMessage.get().parse(currentItem.getType().name() + ": " + event.getCurrentItem().getType().getMaxStackSize()));
else
event.getWhoClicked().sendMessage(MiniMessage.get().parse(currentItem.getType().name() + ": " + event.getCurrentItem().getAmount()));
}
@EventHandler
public void onTradeSelect(TradeSelectEvent event) {
if (!(event.getWhoClicked() instanceof Player player)){
return;
}
GUI gui = GUI.GUIByUUID.get(player.getUniqueId());
if ((!(gui instanceof GUIMerchant guiMerchant)))
return;
if (!gui.getMerchant().equals(event.getMerchant())) {
return;
}
event.setCancelled(true);
GUIAction action = guiMerchant.getAction(event.getIndex());
if (action != null){
action.click(player);
}
}
@EventHandler
public void onClose(InventoryCloseEvent event) {
GUI.GUIByUUID.remove(event.getPlayer().getUniqueId());
}
@EventHandler
public void onQuit(PlayerQuitEvent event){
GUI.GUIByUUID.remove(event.getPlayer().getUniqueId());
}
}

View File

@ -1,61 +0,0 @@
package com.alttd.GUI;
import com.alttd.objects.VillagerType;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
public abstract class GUIMerchant implements GUI{
protected final Merchant merchant;
protected final HashMap<Integer, GUIAction> actions;
private final VillagerType villagerType;
public GUIMerchant(Component name, VillagerType villagerType) {
merchant = Bukkit.createMerchant(name);
actions = new HashMap<>();
this.villagerType = villagerType;
}
public Merchant getMerchant() {
return merchant;
}
public Inventory getInventory() {
return null;
}
public void addItem(@NotNull ItemStack result, @NotNull ItemStack one, @Nullable ItemStack two, @Nullable GUIAction action){
MerchantRecipe merchantRecipe = new MerchantRecipe(result, 0, 10000, false, 0, 0);
merchantRecipe.addIngredient(one);
if (two != null)
merchantRecipe.addIngredient(two);
merchantRecipe.setPriceMultiplier(0);
ArrayList<MerchantRecipe> recipes = new ArrayList<>(merchant.getRecipes());
recipes.add(merchantRecipe);
merchant.setRecipes(recipes);
if (action != null){
actions.put(recipes.size() - 1, action);
}
}
public void open(Player player){
player.openMerchant(merchant, false);
GUIByUUID.put(player.getUniqueId(), this);
}
public GUIAction getAction(int slot) {
return actions.get(slot);
}
public VillagerType getVillagerType() {
return villagerType;
}
}

View File

@ -1,87 +0,0 @@
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.EconUser;
import com.alttd.objects.Price;
import com.alttd.objects.VillagerType;
import com.alttd.util.Utilities;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.Template;
import net.milkbowl.vault.economy.Economy;
import org.apache.commons.lang.StringUtils;
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.Objects;
public class BuyGUI extends GUIMerchant {
private static final MiniMessage miniMessage = MiniMessage.get();
public BuyGUI(VillagerType villagerType, EconUser econUser) {
super(MiniMessage.get().parse(Config.BUY_WINDOW,
Template.of("trader", villagerType.getDisplayName()),
Template.of("points", String.valueOf(Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0)))), villagerType);
for (ItemStack itemStack : villagerType.getBuying()) {
Price price = Utilities.getPrice(itemStack);
if (price == null)
continue;
addItem(itemStack,
getPriceItem(price.getPrice(itemStack.getAmount())),
null,
player -> buy(villagerType, player, itemStack.getType(), itemStack.getAmount(), price)
);
}
}
private void buy(VillagerType villagerType, Player player, Material material, int amount, Price price) {
Economy econ = VillagerUI.getInstance().getEconomy();
double balance = econ.getBalance(player);
int trans_pts = (int) (Math.floor(price.getPrice(amount)/ WorthConfig.POINT_MOD) * amount);
EconUser econUser = EconUser.getUser(player.getUniqueId());
int oldPoints = Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0);
double cost = price.calculatePriceThing(oldPoints, trans_pts, true);
if (balance < cost) {
player.sendMessage(MiniMessage.get().parse(Config.NOT_ENOUGH_MONEY,
Template.of("money", String.valueOf(Utilities.round(balance, 2))),
Template.of("price", String.valueOf(price))));
return;
}
econ.withdrawPlayer(player, cost);
econUser.addPoints(villagerType.getName(), trans_pts);
player.getInventory().addItem(new ItemStack(material, amount));
player.sendMessage(MiniMessage.get().parse(Config.PURCHASED_ITEM,
Template.of("amount", String.valueOf(amount)),
Template.of("item", StringUtils.capitalize(material.name()
.toLowerCase().replaceAll("_", " "))),
Template.of("price", String.valueOf(cost))));
Bukkit.getServer().getPluginManager()
.callEvent(new SpawnShopEvent(player, amount, cost, material,
oldPoints, econUser.getPointsMap().get(villagerType.getName()), true));
}
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.parse("<green>" + price + "</green>")); //TODO configurable
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@ -1,67 +0,0 @@
package com.alttd.GUI.windows;
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 net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.Template;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Objects;
public class OpenGUI extends GUIInventory {
private static final ItemStack BUY = new ItemStack(Material.GOLD_INGOT);
private static final ItemStack SELL = new ItemStack(Material.BUCKET);
static {
MiniMessage miniMessage = MiniMessage.get();
ItemMeta itemMeta;
{
itemMeta = BUY.getItemMeta();
itemMeta.displayName(miniMessage.parse("<green>Buy</green>"));
BUY.setItemMeta(itemMeta);
}
{
itemMeta = SELL.getItemMeta();
itemMeta.displayName(miniMessage.parse("<green>Sell</green>"));
SELL.setItemMeta(itemMeta);
}
}
public OpenGUI(VillagerType villagerType, EconUser econUser) {
super(InventoryType.HOPPER, MiniMessage.get().parse(Config.INITIAL_VILLAGER_WINDOW,
Template.of("trader", villagerType.getDisplayName()),
Template.of("points", String.valueOf(Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0)))));
setItem(1, BUY, player -> new BukkitRunnable() {
@Override
public void run() {
BuyGUI buyGUI = new BuyGUI(villagerType, econUser);
new BukkitRunnable() {
@Override
public void run() {
buyGUI.open(player);
}
}.runTask(VillagerUI.getInstance());
}
}.runTaskAsynchronously(VillagerUI.getInstance()));
setItem(3, SELL, player -> new BukkitRunnable() {
@Override
public void run() {
SellGUI sellGUI = new SellGUI(villagerType, econUser);
new BukkitRunnable() {
@Override
public void run() {
sellGUI.open(player);
}
}.runTask(VillagerUI.getInstance());
}
}.runTaskAsynchronously(VillagerUI.getInstance()));
}
}

View File

@ -1,114 +0,0 @@
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.EconUser;
import com.alttd.objects.Price;
import com.alttd.objects.VillagerType;
import com.alttd.util.Utilities;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.Template;
import net.milkbowl.vault.economy.Economy;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays;
import java.util.Objects;
public class SellGUI extends GUIMerchant {
private static final MiniMessage miniMessage = MiniMessage.get();
public SellGUI(VillagerType villagerType, EconUser econUser) {
super(MiniMessage.get().parse(Config.SELL_WINDOW,
Template.of("trader", villagerType.getDisplayName()),
Template.of("points", String.valueOf(Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0)))), villagerType);
for (ItemStack itemStack : villagerType.getSelling()) {
Price price = Utilities.getPrice(itemStack);
if (price == null)
continue;
addItem(itemStack,
getPriceItem(price.getPrice(itemStack.getAmount())),
null,
player -> sell(villagerType, player, itemStack.getType(), itemStack.getAmount(), price)
);
}
}
private void sell(VillagerType villagerType, Player player, Material material, int amount, Price price) {
PlayerInventory inventory = player.getInventory();
if (!inventory.containsAtLeast(new ItemStack(material), amount)) {
player.sendMessage(miniMessage.parse(Config.NOT_ENOUGH_ITEMS,
Template.of("type", material.name()),
Template.of("amount", String.valueOf(amount))));
return;
}
Economy econ = VillagerUI.getInstance().getEconomy();
EconUser econUser = EconUser.getUser(player.getUniqueId());
int oldPoints = Objects.requireNonNullElse(econUser.getPointsMap().get(villagerType.getName()), 0);
int trans_pts = (int) ((Math.floor(price.getPrice(amount) / WorthConfig.POINT_MOD) + 1) * amount);
double cost = price.calculatePriceThing(oldPoints, trans_pts, false);
econ.depositPlayer(player, cost);
econUser.addPoints(villagerType.getName(), -price.getPoints());
removeItems(inventory, material, amount);
player.sendMessage(MiniMessage.get().parse(Config.SOLD_ITEM,
Template.of("amount", String.valueOf(amount)),
Template.of("item", StringUtils.capitalize(material.name()
.toLowerCase().replaceAll("_", " "))),
Template.of("price", String.valueOf(cost))));
Bukkit.getServer().getPluginManager()
.callEvent(new SpawnShopEvent(player, amount, cost, material,
oldPoints, econUser.getPointsMap().get(villagerType.getName()), false));
}
private void removeItems(Inventory inventory, Material material, int amount) {
var ref = new Object() {
int tmpAmount = amount;
};
Arrays.stream(inventory.getContents())
.filter(Objects::nonNull)
.filter(itemStack -> itemStack.getType().equals(material))
.forEach(itemStack -> {
if (ref.tmpAmount == 0)
return;
if (itemStack.getAmount() > ref.tmpAmount) {
itemStack.setAmount(itemStack.getAmount() - ref.tmpAmount);
ref.tmpAmount = 0;
} else {
ref.tmpAmount -= itemStack.getAmount();
itemStack.setAmount(0);
}
});
}
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.parse("<red>" + price * -1 + "</red>")); //TODO configurable
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@ -1,120 +0,0 @@
package com.alttd.commands.subcommands;
import com.alttd.VillagerUI;
import com.alttd.commands.SubCommand;
import com.alttd.config.Config;
import com.alttd.config.VillagerConfig;
import com.alttd.objects.LoadedVillagers;
import com.alttd.objects.VillagerType;
import com.alttd.util.Utilities;
import net.kyori.adventure.text.minimessage.Template;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.event.entity.CreatureSpawnEvent;
import java.util.*;
import java.util.stream.Collectors;
public class CommandCreateVillager extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (args.length != 9) {
commandSender.sendMessage(getMiniMessage().parse(getHelpMessage()));
return true;
}
Optional<VillagerType> first = VillagerType.getVillagerTypes().stream().filter(villagerType -> villagerType.getName().equalsIgnoreCase(args[1])).findFirst();
if (first.isEmpty()) {
commandSender.sendMessage(getMiniMessage().parse(getHelpMessage()));
return true;
}
VillagerType villagerType = first.get();
Villager.Type type = Villager.Type.valueOf(args[2].toUpperCase());
if (type == null) { //TODO test if this might need a try catch?
commandSender.sendMessage(getMiniMessage().parse(getHelpMessage()));
return true;
}
World world = Bukkit.getServer().getWorld(args[8]);
if (world == null) {
commandSender.sendMessage(getMiniMessage().parse(getHelpMessage()));
return true;
}
Location location = new Location(world, Double.parseDouble(args[3]),Double.parseDouble(args[4]),Double.parseDouble(args[5]), Float.parseFloat(args[6]), Float.parseFloat(args[7]));
Villager villager = (Villager) world.spawnEntity(location, EntityType.VILLAGER, CreatureSpawnEvent.SpawnReason.CUSTOM);
villager.setPersistent(true);
villager.setInvulnerable(true);
villager.setVillagerType(type);
villager.setProfession(villagerType.getProfession());
villager.setRemoveWhenFarAway(false);
villager.customName(getMiniMessage().parse(Config.VILLAGER_NAME, Template.of("name", villagerType.getDisplayName())));
villager.setCustomNameVisible(true);
villager.setAI(false);
UUID uuid = villager.getUniqueId();
LoadedVillagers.addLoadedVillager(uuid, villagerType);
VillagerConfig.addVillager(uuid, villagerType);
return true;
}
@Override
public String getName() {
return "createvillager";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
List<String> res = new ArrayList<>();
switch (args.length) {
case 2 -> res.addAll(VillagerType.getVillagerTypes().stream()
.map(VillagerType::getName)
.collect(Collectors.toList()));
case 3 -> res.addAll(Arrays.stream(Villager.Type.values()).map(Enum::name).collect(Collectors.toList()));
case 4 -> {
if (commandSender instanceof Player player) {
res.add(String.valueOf(Utilities.round(player.getLocation().getX(), 2)));
}
}
case 5 -> {
if (commandSender instanceof Player player) {
res.add(String.valueOf(Utilities.round(player.getLocation().getY(), 1)));
}
}
case 6 -> {
if (commandSender instanceof Player player) {
res.add(String.valueOf(Utilities.round(player.getLocation().getZ(), 2)));
}
}
case 7 -> {
if (commandSender instanceof Player player) {
res.add(String.valueOf(Utilities.round(player.getLocation().getYaw(), 2)));
}
}
case 8 -> {
if (commandSender instanceof Player player) {
res.add(String.valueOf(Utilities.round(player.getLocation().getPitch(), 2)));
}
}
case 9 -> {
if (commandSender instanceof Player player) {
res.add(player.getLocation().getWorld().getName());
}
}
}
return res;
}
@Override
public String getHelpMessage() {
return Config.CREATE_VILLAGER_MESSAGE;
}
}

View File

@ -1,54 +0,0 @@
package com.alttd.commands.subcommands;
import com.alttd.commands.SubCommand;
import com.alttd.config.Config;
import com.alttd.config.VillagerConfig;
import com.alttd.objects.LoadedVillagers;
import net.kyori.adventure.text.minimessage.Template;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class CommandRemoveVillager extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (!(commandSender instanceof Player player)) {
commandSender.sendMessage(getMiniMessage().parse(Config.NO_CONSOLE));
return true;
}
for(Entity entity : player.getNearbyEntities(2, 2, 2)){
if (!entity.getType().equals(EntityType.VILLAGER))
continue;
UUID uuid = entity.getUniqueId();
if (LoadedVillagers.getLoadedVillager(uuid) == null)
continue;
LoadedVillagers.removeLoadedVillager(uuid);
VillagerConfig.removeVillager(uuid);
entity.remove();
player.sendMessage(getMiniMessage().parse(Config.REMOVED_VILLAGER, Template.of("uuid", uuid.toString())));
}
return true;
}
@Override
public String getName() {
return "removevillager";
}
@Override
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
return new ArrayList<>();
}
@Override
public String getHelpMessage() {
return Config.REMOVE_VILLAGER_MESSAGE;
}
}

View File

@ -1,45 +0,0 @@
package com.alttd.config;
import com.alttd.objects.LoadedVillagers;
import com.alttd.objects.VillagerType;
import com.alttd.util.Logger;
import java.util.UUID;
public class VillagerConfig extends AbstractConfig {
static VillagerConfig config;
static int version;
public VillagerConfig() {
super("villagerConfig.yml");
}
public static void reload() {
config = new VillagerConfig();
version = config.getInt("config-version", 1);
config.set("config-version", 1);
config.readConfig(VillagerConfig.class, null);
}
private static void loadVillagers() {
LoadedVillagers.clearLoadedVillagers();
config.getConfigurationSection("").getKeys(false).forEach(key -> {
VillagerType villagerType = VillagerType.getVillagerType(config.getString(key, ""));
if (villagerType != null)
LoadedVillagers.addLoadedVillager(UUID.fromString(key), villagerType);
else
Logger.warning("Invalid config entry %.", key);
});
}
public static void removeVillager(UUID uuid) {
config.set(uuid.toString(), null);
}
public static void addVillager(UUID uuid, VillagerType villagerType) {
config.set(uuid.toString(), villagerType.getName());
}
}

View File

@ -1,54 +0,0 @@
package com.alttd.config;
import com.alttd.VillagerUI;
import com.alttd.objects.Price;
import com.alttd.util.Logger;
import com.alttd.util.Utilities;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import java.io.File;
import java.util.Set;
public class WorthConfig extends AbstractConfig {
static WorthConfig config;
static int version;
public WorthConfig() {
super(new File(System.getProperty("user.home") + File.separator + "share" + File.separator + "configs" + File.separator + "VillagerShopUI"), "worth.yml");
}
public static void reload() {
config = new WorthConfig();
version = config.getInt("config-version", 1);
config.set("config-version", 1);
config.readConfig(WorthConfig.class, null);
}
public static Object2ObjectOpenHashMap<Material, Price> prices = new Object2ObjectOpenHashMap<>();
private static void loadWorth() { //TODO test after removing points
prices.clear();
ConfigurationSection worth = config.getConfigurationSection("worth");
if (worth == null) {
Logger.severe("No worth in worth.yml! Stopping VillagerUI.");
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;
}
prices.put(Material.getMaterial(key), new Price(Utilities.round(worth.getDouble(key), 2)));
}
}
public static int POINT_MOD = 4;
private static void loadOtherStuff() {
POINT_MOD = config.getInt("point-mod", POINT_MOD);
}
}

View File

@ -1,98 +0,0 @@
package com.alttd.database;
import com.alttd.VillagerUI;
import com.alttd.config.Config;
import com.alttd.util.Logger;
import org.bukkit.Bukkit;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Database {
private static Database instance = null;
public static Connection connection = null;
private Database() {
}
public static Database getDatabase(){
if (instance == null)
instance = new Database();
return (instance);
}
public void init() {
try {
openConnection();
} catch (SQLException e) {
e.printStackTrace();
}
// Tables
createUserPointsTable();
createUserSeenTable();
}
/**
* Opens the connection if it's not already open.
* @throws SQLException If it can't create the connection.
*/
private void openConnection() throws SQLException {
if (connection != null && !connection.isClosed()) {
return;
}
synchronized (this) {
if (connection != null && !connection.isClosed()) {
return;
}
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
connection = DriverManager.getConnection(
"jdbc:mysql://" + Config.IP + ":" + Config.PORT + "/" + Config.DATABASE_NAME +
"?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true",
Config.USERNAME, Config.PASSWORD);
}
}
private static void createUserPointsTable() {
try {
String sql = "CREATE TABLE IF NOT EXISTS user_points(" +
"UUID VARCHAR(36) NOT NULL, " +
"points int NOT NULL, " +
"villager_type VARCHAR(128) NOT NULL, " +
"PRIMARY KEY (UUID, villager_type)" +
")";
connection.prepareStatement(sql).executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
Logger.severe("Error while trying to create user point table");
Logger.severe("Shutting down VillagerUI");
Bukkit.getPluginManager().disablePlugin(VillagerUI.getInstance());
}
}
private static void createUserSeenTable() {
try {
String sql = "CREATE TABLE IF NOT EXISTS user_seen(" +
"UUID VARCHAR(36) NOT NULL, " +
"seen BIGINT NOT NULL, " +
"PRIMARY KEY (UUID)" +
")";
connection.prepareStatement(sql).executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
Logger.severe("Error while trying to create user seen table");
Logger.severe("Shutting down VillagerUI");
Bukkit.getPluginManager().disablePlugin(VillagerUI.getInstance());
}
}
}

View File

@ -1,131 +0,0 @@
package com.alttd.database;
import com.alttd.objects.EconUser;
import com.alttd.util.Logger;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class Queries {
/**
* NOTE: run async
* Add a specified amount of points to the user for the given villager type
*
* @param uuid Uuid for the user you want to add the points to
* @param pointsMap Contains all (villagerType, points) entries for user
*/
public static void updateUserPoints(UUID uuid, Object2ObjectArrayMap<String, Integer> pointsMap) {
String sql = "INSERT INTO user_points " +
"(uuid, villager_type, points) " +
"VALUES (?, ?, ?) " +
"ON DUPLICATE KEY UPDATE points = ?";
try {
PreparedStatement preparedStatement = Database.connection.prepareStatement(sql);
preparedStatement.setString(1, uuid.toString());
pointsMap.forEach((villagerType, points) -> {
try {
preparedStatement.setString(2, villagerType);
preparedStatement.setInt(3, points);
preparedStatement.setInt(4, points);
preparedStatement.addBatch();
} catch (SQLException e) {
e.printStackTrace();
Logger.warning("Unable to add % points to %" +
" for villager type %", String.valueOf(points), uuid.toString(), villagerType);
}
});
preparedStatement.execute();
} catch (SQLException e) {
e.printStackTrace();
return;
}
setLastUpdated(uuid);
}
/**
* Get the econ user
* @param uuid UUID of the user to get
*
* @return EconUser
*/
public static EconUser getEconUser(UUID uuid) {
String sql = "SELECT * FROM user_points WHERE uuid = ?";
try {
PreparedStatement preparedStatement = Database.connection.prepareStatement(sql);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
Object2ObjectArrayMap<String, Integer> points = new Object2ObjectArrayMap<>();
while (resultSet.next()) {
points.put(
resultSet.getString("villager_type"),
resultSet.getInt("points"));
}
return (new EconUser(uuid, points));
} catch (SQLException e) {
e.printStackTrace();
}
return (null);
}
/**
* Set last seen to current time for user
* @param uuid UUID of user to update last seen for
*/
private static void setLastUpdated(UUID uuid) {
String sql = "INSERT INTO user_seen " +
"(uuid, seen) " +
"VALUES (?, ?) " +
"ON DUPLICATE KEY UPDATE seen = ?";
long time = new Date().getTime();
try {
PreparedStatement preparedStatement = Database.connection.prepareStatement(sql);
preparedStatement.setString(1, uuid.toString());
preparedStatement.setLong(2, time);
preparedStatement.setLong(3, time);
preparedStatement.execute();
} catch (SQLException e) {
e.printStackTrace();
Logger.warning("Unable to set last updated time for %.", uuid.toString());
}
}
/**
* Get last seen for user
* @param uuid UUID of user to get last seen for
*
* @return minutes since last seen
*/
public static int getMinutesSinceUpdated(UUID uuid) {
String sql = "SELECT seen FROM user_seen WHERE uuid = ?";
long time;
try {
PreparedStatement preparedStatement = Database.connection.prepareStatement(sql);
preparedStatement.setString(1, uuid.toString());
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next())
time = resultSet.getLong("seen");
else
return (0);
if (time != 0)
return (int) TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - time);
} catch (SQLException e) {
e.printStackTrace();
Logger.warning("Unable to set last updated time for %.", uuid.toString());
}
return (0);
}
}

View File

@ -1,32 +0,0 @@
package com.alttd.events;
import com.alttd.VillagerUI;
import com.alttd.config.Config;
import com.alttd.database.Queries;
import com.alttd.objects.EconUser;
import com.alttd.util.Logger;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
public class LoginEvent implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
new BukkitRunnable() {
@Override
public void run() {
UUID uuid = event.getPlayer().getUniqueId();
EconUser user = EconUser.getUser(uuid);
int minutes = Queries.getMinutesSinceUpdated(uuid);
user.removePoints(minutes * 2);
if (Config.DEBUG)
Logger.info("Loaded EconUser for % and removed % points",
event.getPlayer().getName(), String.valueOf(minutes * 2));
}
}.runTask(VillagerUI.getInstance());
}
}

View File

@ -1,20 +0,0 @@
package com.alttd.events;
import com.alttd.GUI.GUI;
import com.alttd.objects.EconUser;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.UUID;
public class LogoutEvent implements Listener {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
UUID uuid = event.getPlayer().getUniqueId();
EconUser.getUser(uuid).syncPoints();
EconUser.removeUser(uuid);
GUI.GUIByUUID.remove(uuid);
}
}

View File

@ -1,63 +0,0 @@
package com.alttd.events;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
public final class SpawnShopEvent extends Event {
private final Player player;
private final int amount;
private final double price;
private final Material item;
private final int pointsBefore;
private final int pointsAfter;
private final boolean buy;
private final HandlerList handlers = new HandlerList();
public SpawnShopEvent(Player player, int amount, double price, Material item,
int pointsBefore, int pointsAfter, boolean buy) {
this.player = player;
this.amount = amount;
this.price = price;
this.item = item;
this.pointsBefore = pointsBefore;
this.pointsAfter = pointsAfter;
this.buy = buy;
}
public Player player() {
return player;
}
public int amount() {
return amount;
}
public double price() {
return price;
}
public Material item() {
return item;
}
public int pointsBefore() {
return pointsBefore;
}
public int pointsAfter() {
return pointsAfter;
}
public boolean buy() {
return buy;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
}

View File

@ -1,60 +0,0 @@
package com.alttd.events;
import com.alttd.GUI.windows.OpenGUI;
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 net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
public class VillagerEvents implements Listener {
@EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (!(event.getRightClicked() instanceof Villager villager))
return;
VillagerType loadedVillager = LoadedVillagers.getLoadedVillager(villager.getUniqueId());
if (loadedVillager == null)
return;
event.setCancelled(true);
if (!event.getPlayer().hasPermission(loadedVillager.getPermission())) {
event.getPlayer().sendMessage(MiniMessage.get().parse(Config.NO_PERMISSION)); //TODO more specific message?
return;
}
new BukkitRunnable() {
@Override
public void run() {
OpenGUI openGUI = new OpenGUI(loadedVillager, EconUser.getUser(event.getPlayer().getUniqueId()));
new BukkitRunnable() {
@Override
public void run() {
openGUI.open(event.getPlayer());
}
}.runTask(VillagerUI.getInstance());
}
}.runTaskAsynchronously(VillagerUI.getInstance());
}
@EventHandler
public void onVillagerDeath(EntityDeathEvent event) {
if (!event.getEntityType().equals(EntityType.VILLAGER))
return;
UUID uuid = event.getEntity().getUniqueId();
LoadedVillagers.removeLoadedVillager(uuid);
VillagerConfig.removeVillager(uuid);
}
}

View File

@ -1,110 +0,0 @@
package com.alttd.objects;
import com.alttd.VillagerUI;
import com.alttd.config.Config;
import com.alttd.database.Queries;
import com.alttd.util.Logger;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import org.apache.commons.math3.analysis.function.Log;
import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.Unmodifiable;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class EconUser {
private final static Object2ObjectArrayMap<UUID, EconUser> users = new Object2ObjectArrayMap<>();
private final UUID uuid;
private final Object2ObjectArrayMap<String, Integer> pointsMap;
public EconUser(UUID uuid, Object2ObjectArrayMap<String, Integer> points) {
this.uuid = uuid;
this.pointsMap = points;
users.put(this.uuid, this);
if (Config.DEBUG)
Logger.info("Created EconUser for: %", uuid.toString());
}
public UUID getUuid() {
return uuid;
}
public Object2ObjectArrayMap<String, Integer> getPointsMap() {
return pointsMap;
}
public void addPoints(String villagerType, int points) {
if (Config.DEBUG)
Logger.info("Adding % points to % for %", String.valueOf(points), villagerType, uuid.toString());
if (pointsMap.containsKey(villagerType))
pointsMap.put(villagerType,pointsMap.get(villagerType) + points);
else
pointsMap.put(villagerType, points);
}
public void syncPoints() {
new BukkitRunnable() {
@Override
public void run() {
Queries.updateUserPoints(uuid, pointsMap);
}
}.runTaskAsynchronously(VillagerUI.getInstance());
}
private void removePoints(String villagerType, int points, int remove)
{
if (points == 0)
return;
if (points > 0)
if (points < remove)
points = 0;
else
points -= remove;
else
if (-points < remove)
points = 0;
else
points += remove;
pointsMap.put(villagerType, points);
if (Config.DEBUG)
Logger.info("Removed % points from villagerType: % for %",
String.valueOf(points), villagerType, uuid.toString());
}
public void removePoints(int remove) {
pointsMap.forEach((villagerType, points) -> removePoints(villagerType, points, remove));
}
public void removePoints() {
pointsMap.forEach((villagerType, points) -> {
if (points == 0)
return;
int remove = points;
if (remove < 0)
remove *= -1;
removePoints(villagerType, points, (int) (0.9 * remove) - 10);
});
}
public static EconUser getUser(UUID uuid) {
EconUser user = users.get(uuid);
if (user == null) {
user = Queries.getEconUser(uuid);
EconUser.users.put(uuid, user);
}
return (user);
}
public static void removeUser(UUID uuid) {
users.remove(uuid);
}
@Unmodifiable
public static List<EconUser> getEconUsers() {
return Collections.unmodifiableList(users.values().stream().toList());
}
}

View File

@ -1,25 +0,0 @@
package com.alttd.objects;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class LoadedVillagers {
private final static Map<UUID, VillagerType> loadedVillagers = new HashMap<>();
public static VillagerType getLoadedVillager(UUID uuid) {
return loadedVillagers.get(uuid);
}
public static void addLoadedVillager(UUID uuid, VillagerType villagerType) {
loadedVillagers.put(uuid, villagerType);
}
public static void removeLoadedVillager(UUID uuid) {
loadedVillagers.remove(uuid);
}
public static void clearLoadedVillagers() {
loadedVillagers.clear();
}
}

View File

@ -1,45 +0,0 @@
package com.alttd.objects;
import com.alttd.util.Utilities;
import org.apache.commons.math3.analysis.function.StepFunction;
import org.apache.commons.math3.analysis.integration.TrapezoidIntegrator;
public final class Price {
private final double price;
private final int points;
private static final double[] xMult = {Integer.MIN_VALUE, -4000, -2000, -500, 500, 2000, 4000};
private static final double[] yMultSell = {2.5, 1.75, 1.25, 1, 1.5, 2.5, 5};
private static final double[] yMultBuy = {5, 2.5, 1.5, 1, 1.25, 1.75, 2.5};
private static final StepFunction multiplierModelBuy = new StepFunction(xMult, yMultBuy);
private static final StepFunction multiplierModelSell = new StepFunction(xMult, yMultSell);
public Price(double price) {
this.price = price;
this.points = (int) price;
}
public static Price addPrice(Price one, Price two) {
return (new Price(Utilities.round(one.getPrice(1) + two.getPrice(1), 2)));
}
public double getPrice(int multiplier) {
return (Utilities.round(price * multiplier, 2));
}
public double calculatePriceThing(int oldPoints, int transPts, boolean buying) {
// Compute numerical integration to determine price
TrapezoidIntegrator trapez = new TrapezoidIntegrator();
if (buying) {
return (Utilities.round(price * trapez.integrate(10, multiplierModelBuy, oldPoints, oldPoints + transPts), 2));
} else {
return (Utilities.round(price * trapez.integrate(10, multiplierModelSell, oldPoints - transPts, oldPoints), 2));
}
}
public int getPoints() {
return (points);
}
}

View File

@ -1,70 +0,0 @@
package com.alttd.objects;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.Set;
public class VillagerType {
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();
}
private final String name;
private final String displayName;
private final Set<ItemStack> buying;
private final Set<ItemStack> selling;
private final double priceModifier;
private final Villager.Profession profession;
public VillagerType(String name, String displayName, Set<ItemStack> buying, Set<ItemStack> selling, double priceModifier, String profession) {
this.name = name;
this.displayName = displayName;
this.buying = buying;
this.selling = selling;
this.priceModifier = priceModifier;
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 double getPriceModifier() {
return priceModifier;
}
public Villager.Profession getProfession() {
return profession;
}
public String getPermission() {
return "villagerui.villager." + getName();
}
}

View File

@ -1,137 +0,0 @@
package com.alttd.util;
import com.alttd.config.WorthConfig;
import com.alttd.objects.Price;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.*;
import java.util.List;
public class Utilities {
/**
* Rounds num down to precision (rounds up if last cut off decimal is bigger than 4)
*
* @param num value to be rounded
* @param precision length to round to
* @return num rounded
*/
public static double round(double num, int precision) {
double scale = Math.pow(10, precision);
double total = (double) (Math.round(num * scale)) / scale;
scale = (int) Math.pow(10, precision + 1);
long tmp = (Math.round(num * scale));
tmp %= 10;
if (tmp > 4)
total += 0.01;
return total;
}
/**
* Calculate the price for an ItemStack (this considers stack size)
*
* @param item to calculate price for
* @return price or int < 0 for error
*/
public static Price getPrice(ItemStack item) {
if (WorthConfig.prices.containsKey(item.getType()))
return (WorthConfig.prices.get(item.getType()));
Price price = getWorth(item, null);
if (price == null)
return (null);
WorthConfig.prices.put(item.getType(), price);
return (WorthConfig.prices.get(item.getType()));
}
/**
* Get the worth of the material an ItemStack consists of
*
* @param item to get the worth of
* @param blockedMaterial Material to ignore set to null on initial call
* @return Worth of the item as a double
*/
private static Price getWorth(ItemStack item, Material blockedMaterial) {
Price price = null;
if (item == null)
return (null);
if (WorthConfig.prices.containsKey(item.getType()))
return (WorthConfig.prices.get(item.getType()));
List<Recipe> recipes = Bukkit.getRecipesFor(item);
for (Recipe recipe : recipes) {
Price possiblePrice;
if (recipe instanceof ShapedRecipe shapedRecipe) {
List<ItemStack> values = shapedRecipe.getIngredientMap().values().stream().toList();
if (!values.isEmpty() && blockedMaterial != null && values.stream()
.anyMatch(itemStack -> itemStack != null && itemStack.getType().equals(blockedMaterial)))
continue;
possiblePrice = getWorth(values, item.getType());
if (possiblePrice == null)
continue;
if (price == null || price.getPrice(1) > possiblePrice.getPrice(1))
price = possiblePrice;
} else if (recipe instanceof ShapelessRecipe shapelessRecipe) {
if (shapelessRecipe.getIngredientList().stream()
.anyMatch(itemStack -> itemStack.getType().equals(blockedMaterial)))
continue;
possiblePrice = getWorth(shapelessRecipe.getIngredientList(), item.getType());
if (possiblePrice == null)
continue;
if (price == null || price.getPrice(1) > possiblePrice.getPrice(1))
price = possiblePrice;
} else if (recipe instanceof CampfireRecipe campfireRecipe) {
possiblePrice = getWorth(campfireRecipe.getInput(), item.getType());
if (possiblePrice == null)
continue;
if (price == null || price.getPrice(1) > possiblePrice.getPrice(1))
price = possiblePrice;
} else if (recipe instanceof StonecuttingRecipe stonecuttingRecipe) {
possiblePrice = getWorth(stonecuttingRecipe.getInput(), item.getType());
if (possiblePrice == null)
continue;
if (price == null || price.getPrice(1) > possiblePrice.getPrice(1))
price = possiblePrice;
} else if (recipe instanceof CookingRecipe cookingRecipe) {
if ((recipe instanceof FurnaceRecipe || recipe instanceof BlastingRecipe ) &&
!cookingRecipe.getInput().getType().isBlock() &&
!cookingRecipe.getInput().getType().equals(Material.CLAY_BALL)) //Needs exception for clay ball idk a better way to do it...
continue;
possiblePrice = getWorth(cookingRecipe.getInput(), item.getType());
if (possiblePrice == null)
continue;
if (price == null || price.getPrice(1) > possiblePrice.getPrice(1))
price = possiblePrice;
}
}
return price;
}
/**
* Get the total worth of a list of ItemStack's (amount of items in ItemStack is ignored)
*
* @param items Items to get the worth of
* @param blockedMaterial Material to ignore set to null on initial call
* @return Worth of ItemStack as a double
*/
private static Price getWorth(List<ItemStack> items, Material blockedMaterial) {
Price price = null;
for (ItemStack item : items) {
if (item == null)
continue;
Price tmp = getWorth(new ItemStack(item.getType()), blockedMaterial);
if (tmp == null || tmp.getPrice(1) == -1)
return null;
WorthConfig.prices.put(item.getType(), tmp);
if (price == null)
price = tmp;
else
price = Price.addPrice(price, tmp);
}
return (price);
}
}