diff --git a/pom.xml b/pom.xml index 1550ddf..24780a7 100644 --- a/pom.xml +++ b/pom.xml @@ -23,8 +23,8 @@ maven-compiler-plugin 3.8.1 - 11 - 11 + 12 + 12 @@ -95,13 +95,21 @@ placeholderapi https://repo.extendedclip.com/content/repositories/placeholderapi/ + + techscode + https://repo.techscode.com/repository/maven-releases/ + + + rosewood-repo + https://repo.rosewooddev.io/repository/public/ + com.artillexstudios.axapi axapi - 1.4.109 + 1.4.136 compile @@ -128,5 +136,90 @@ 3.0.2 compile + + + me.aglerr.mobcoins + MobCoins + 1.1.3 + ${project.basedir}/libs/TheOnly-MobCoins-1.1.3.jar + system + + + com.artillexstudios + AxQuestBoardAPI + 1 + provided + + + com.github.Realizedd + TokenManager + 3.2.4 + provided + + + * + * + + + + + me.swanis.mobcoins + MobCoins + 1.1.2 + ${project.basedir}/libs/mobcoins-api-1.1.2-SNAPSHOT.jar + system + + + me.rivaldev.harvesterhoes + Main + LATEST + ${project.basedir}/libs/RivalHarvesterHoesAPI.jar + system + + + com.github.cryptomorin + kingdoms + LATEST + ${project.basedir}/libs/KingdomsX-1.16.14.1.jar + system + + + su.nightexpress.coinsengine + CoinsEngine + 2.1.1 + ${project.basedir}/libs/CoinsEngine-2.1.1.jar + system + + + me.qKing12.RoyaleEconomy + RoyaleEconomy + 1.4.4 + ${project.basedir}/libs/RoyaleEconomyAPI.jar + system + + + com.github.MilkBowl + VaultAPI + 1.7 + provided + + + org.black_ixx + playerpoints + 3.2.6 + provided + + + me.TechsCode + UltraEconomyAPI + 2.6.4 + provided + + + de.rapha149.signgui + signgui + 2.3.2 + compile + diff --git a/src/main/java/com/artillexstudios/axtrade/AxTrade.java b/src/main/java/com/artillexstudios/axtrade/AxTrade.java index c27b2e8..33fb853 100644 --- a/src/main/java/com/artillexstudios/axtrade/AxTrade.java +++ b/src/main/java/com/artillexstudios/axtrade/AxTrade.java @@ -11,7 +11,11 @@ import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.updater.U import com.artillexstudios.axapi.utils.MessageUtils; import com.artillexstudios.axapi.utils.StringUtils; import com.artillexstudios.axtrade.commands.Commands; +import com.artillexstudios.axtrade.hooks.HookManager; +import com.artillexstudios.axtrade.listeners.PlayerInteractEntityListener; +import com.artillexstudios.axtrade.listeners.TradeListeners; import com.artillexstudios.axtrade.trade.TradeTicker; +import com.artillexstudios.axtrade.utils.NumberUtils; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -22,6 +26,7 @@ public final class AxTrade extends AxPlugin { public static Config CONFIG; public static Config LANG; public static Config GUIS; + public static Config HOOKS; public static MessageUtils MESSAGEUTILS; private static AxPlugin instance; private static ThreadedQueue threadedQueue; @@ -44,6 +49,7 @@ public final class AxTrade extends AxPlugin { CONFIG = new Config(new File(getDataFolder(), "config.yml"), getResource("config.yml"), GeneralSettings.builder().setUseDefaults(false).build(), LoaderSettings.builder().setAutoUpdate(true).build(), DumperSettings.DEFAULT, UpdaterSettings.builder().setKeepAll(true).setVersioning(new BasicVersioning("version")).build()); GUIS = new Config(new File(getDataFolder(), "guis.yml"), getResource("guis.yml"), GeneralSettings.builder().setUseDefaults(false).build(), LoaderSettings.builder().setAutoUpdate(true).build(), DumperSettings.DEFAULT, UpdaterSettings.builder().setKeepAll(true).setVersioning(new BasicVersioning("version")).build()); LANG = new Config(new File(getDataFolder(), "lang.yml"), getResource("lang.yml"), GeneralSettings.builder().setUseDefaults(false).build(), LoaderSettings.builder().setAutoUpdate(true).build(), DumperSettings.DEFAULT, UpdaterSettings.builder().setKeepAll(true).setVersioning(new BasicVersioning("version")).build()); + HOOKS = new Config(new File(getDataFolder(), "currencies.yml"), getResource("currencies.yml"), GeneralSettings.builder().setUseDefaults(false).build(), LoaderSettings.builder().setAutoUpdate(true).build(), DumperSettings.DEFAULT, UpdaterSettings.builder().setKeepAll(true).setVersioning(new BasicVersioning("version")).build()); MESSAGEUTILS = new MessageUtils(LANG.getBackingDocument(), "prefix", CONFIG.getBackingDocument()); @@ -51,10 +57,16 @@ public final class AxTrade extends AxPlugin { BUKKITAUDIENCES = BukkitAudiences.create(this); + getServer().getPluginManager().registerEvents(new PlayerInteractEntityListener(), this); + getServer().getPluginManager().registerEvents(new TradeListeners(), this); + + new HookManager().setupHooks(); + NumberUtils.reload(); + new TradeTicker().start(); Commands.registerCommand(); - Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�ffdd[AxTrade] Loaded plugin!")); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD[AxTrade] Loaded plugin!")); } } \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/commands/Commands.java b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java index 5a46e14..b5bdede 100644 --- a/src/main/java/com/artillexstudios/axtrade/commands/Commands.java +++ b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java @@ -2,13 +2,18 @@ package com.artillexstudios.axtrade.commands; import com.artillexstudios.axapi.utils.StringUtils; import com.artillexstudios.axtrade.AxTrade; +import com.artillexstudios.axtrade.hooks.HookManager; +import com.artillexstudios.axtrade.request.Requests; import com.artillexstudios.axtrade.trade.Trades; +import com.artillexstudios.axtrade.utils.NumberUtils; +import com.artillexstudios.axtrade.utils.SoundUtils; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.permissions.PermissionDefault; import org.jetbrains.annotations.NotNull; import revxrsal.commands.annotation.DefaultFor; +import revxrsal.commands.annotation.Optional; import revxrsal.commands.annotation.Subcommand; import revxrsal.commands.bukkit.BukkitCommandHandler; import revxrsal.commands.bukkit.annotation.CommandPermission; @@ -24,19 +29,53 @@ import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; public class Commands implements OrphanCommand { - @DefaultFor({"~", "~ help"}) public void help(@NotNull CommandSender sender) { - if (!sender.hasPermission("axtrade.admin")) { - for (String m : LANG.getStringList("player-help")) { - sender.sendMessage(StringUtils.formatToString(m)); - } - } else { + if (sender.hasPermission("axtrade.admin")) { for (String m : LANG.getStringList("admin-help")) { sender.sendMessage(StringUtils.formatToString(m)); } + } else { + for (String m : LANG.getStringList("player-help")) { + sender.sendMessage(StringUtils.formatToString(m)); + } } } + @DefaultFor({"~"}) + public void trade(@NotNull Player sender, @Optional Player other) { + if (other == null) { + help(sender); + return; + } + + Requests.addRequest(sender, other); + } + + @Subcommand("accept") + public void accept(@NotNull Player sender, @NotNull Player other) { + var request = Requests.getRequest(sender, other); + if (request == null || request.getSender().equals(sender)) { + MESSAGEUTILS.sendLang(sender, "request.no-request", Map.of("%player%", other.getName())); + return; + } + + Requests.addRequest(sender, other); + } + + @Subcommand("deny") + public void deny(@NotNull Player sender, @NotNull Player other) { + var request = Requests.getRequest(sender, other); + if (request == null || request.getSender().equals(sender)) { + MESSAGEUTILS.sendLang(sender, "request.no-request", Map.of("%player%", other.getName())); + return; + } + + MESSAGEUTILS.sendLang(request.getSender(), "request.deny-sender", Map.of("%player%", request.getReceiver().getName())); + MESSAGEUTILS.sendLang(request.getReceiver(), "request.deny-receiver", Map.of("%player%", request.getSender().getName())); + SoundUtils.playSound(request.getSender(), "deny"); + SoundUtils.playSound(request.getReceiver(), "deny"); + } + @Subcommand("reload") @CommandPermission(value = "axtrade.admin", defaultAccess = PermissionDefault.OP) public void reload(@NotNull CommandSender sender) { @@ -61,6 +100,9 @@ public class Commands implements OrphanCommand { Commands.registerCommand(); + new HookManager().updateHooks(); + NumberUtils.reload(); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╚ &#AAFFDDSuccessful reload!")); MESSAGEUTILS.sendLang(sender, "reload.success"); } diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/HookManager.java b/src/main/java/com/artillexstudios/axtrade/hooks/HookManager.java new file mode 100644 index 0000000..aa19e79 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/HookManager.java @@ -0,0 +1,124 @@ +package com.artillexstudios.axtrade.hooks; + +import com.artillexstudios.axapi.utils.StringUtils; +import com.artillexstudios.axtrade.hooks.currency.AxQuestBoardHook; +import com.artillexstudios.axtrade.hooks.currency.CoinsEngineHook; +import com.artillexstudios.axtrade.hooks.currency.CurrencyHook; +import com.artillexstudios.axtrade.hooks.currency.ExperienceHook; +import com.artillexstudios.axtrade.hooks.currency.KingdomsXHook; +import com.artillexstudios.axtrade.hooks.currency.PlaceholderCurrencyHook; +import com.artillexstudios.axtrade.hooks.currency.PlayerPointsHook; +import com.artillexstudios.axtrade.hooks.currency.RivalHarvesterHoesHook; +import com.artillexstudios.axtrade.hooks.currency.RoyaleEconomyHook; +import com.artillexstudios.axtrade.hooks.currency.SuperMobCoinsHook; +import com.artillexstudios.axtrade.hooks.currency.TheOnlyMobCoins; +import com.artillexstudios.axtrade.hooks.currency.TokenManagerHook; +import com.artillexstudios.axtrade.hooks.currency.UltraEconomyHook; +import com.artillexstudios.axtrade.hooks.currency.VaultHook; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + +import static com.artillexstudios.axtrade.AxTrade.HOOKS; + +public class HookManager { + private static final ArrayList currency = new ArrayList<>(); + + public void setupHooks() { + updateHooks(); + } + + public void updateHooks() { + currency.removeIf(currencyHook -> !currencyHook.isPersistent()); + + if (HOOKS.getBoolean("currencies.Experience.register", true)) + currency.add(new ExperienceHook()); + + if (HOOKS.getBoolean("currencies.Vault.register", true) && Bukkit.getPluginManager().getPlugin("Vault") != null) { + currency.add(new VaultHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into Vault!")); + } + + if (HOOKS.getBoolean("currencies.PlayerPoints.register", true) && Bukkit.getPluginManager().getPlugin("PlayerPoints") != null) { + currency.add(new PlayerPointsHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into PlayerPoints!")); + } + + if (HOOKS.getBoolean("currencies.CoinsEngine.register", true) && Bukkit.getPluginManager().getPlugin("CoinsEngine") != null) { + currency.add(new CoinsEngineHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into CoinsEngine!")); + } + + if (HOOKS.getBoolean("currencies.RoyaleEconomy.register", true) && Bukkit.getPluginManager().getPlugin("RoyaleEconomy") != null) { + currency.add(new RoyaleEconomyHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into RoyaleEconomy!")); + } + + if (HOOKS.getBoolean("currencies.UltraEconomy.register", true) && Bukkit.getPluginManager().getPlugin("UltraEconomy") != null) { + currency.add(new UltraEconomyHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into UltraEconomy!")); + } + + if (HOOKS.getBoolean("currencies.KingdomsX.register", true) && Bukkit.getPluginManager().getPlugin("Kingdoms") != null) { + currency.add(new KingdomsXHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into KingdomsX!")); + } + + if (HOOKS.getBoolean("currencies.RivalHarvesterHoes.register", true) && Bukkit.getPluginManager().getPlugin("RivalHarvesterHoes") != null) { + currency.add(new RivalHarvesterHoesHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into RivalHarvesterHoes!")); + } + + if (HOOKS.getBoolean("currencies.SuperMobCoins.register", true) && Bukkit.getPluginManager().getPlugin("SuperMobCoins") != null) { + currency.add(new SuperMobCoinsHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into SuperMobCoins!")); + } + + if (HOOKS.getBoolean("currencies.TheOnly-MobCoins.register", true) && Bukkit.getPluginManager().getPlugin("TheOnly-MobCoins") != null) { + currency.add(new TheOnlyMobCoins()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into TheOnly-MobCoins!")); + } + + if (HOOKS.getBoolean("currencies.TokenManager.register", true) && Bukkit.getPluginManager().getPlugin("TokenManager") != null) { + currency.add(new TokenManagerHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into TokenManager!")); + } + + if (HOOKS.getBoolean("currencies.AxQuestBoard.register", true) && Bukkit.getPluginManager().getPlugin("AxQuestBoard") != null) { + currency.add(new AxQuestBoardHook()); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into AxQuestBoard!")); + } + + for (String str : HOOKS.getSection("placeholder-currencies").getRoutesAsStrings(false)) { + if (!HOOKS.getBoolean("placeholder-currencies." + str + ".register", false)) continue; + currency.add(new PlaceholderCurrencyHook(str, HOOKS.getSection("placeholder-currencies." + str))); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Loaded placeholder currency " + str + "!")); + } + + for (CurrencyHook hook : currency) hook.setup(); + } + + @SuppressWarnings("unused") + public static void registerCurrencyHook(@NotNull Plugin plugin, @NotNull CurrencyHook currencyHook) { + currency.add(currencyHook); + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("!FF33[AxTrade] Hooked into " + plugin.getName() + "! Note: You must set the currency provider to CUSTOM or it will be overridden after reloading!")); + } + + @NotNull + public static ArrayList getCurrency() { + return currency; + } + + @Nullable + public static CurrencyHook getCurrencyHook(@NotNull String name) { + for (CurrencyHook hook : currency) { + if (!hook.getName().equals(name)) continue; + return hook; + } + + return null; + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/AxQuestBoardHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/AxQuestBoardHook.java new file mode 100644 index 0000000..a938cb7 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/AxQuestBoardHook.java @@ -0,0 +1,48 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import com.artillexstudios.axquestboard.api.AxQuestBoardAPI; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class AxQuestBoardHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "AxQuestBoard"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return AxQuestBoardAPI.getPoints(player); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + AxQuestBoardAPI.modifyPoints(player, (int) amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + AxQuestBoardAPI.modifyPoints(player, (int) amount * -1); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/CoinsEngineHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/CoinsEngineHook.java new file mode 100644 index 0000000..81b636d --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/CoinsEngineHook.java @@ -0,0 +1,57 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import su.nightexpress.coinsengine.api.CoinsEngineAPI; +import su.nightexpress.coinsengine.api.currency.Currency; + +import java.util.UUID; + +import static com.artillexstudios.axtrade.AxTrade.HOOKS; + +public class CoinsEngineHook implements CurrencyHook { + private Currency currency = null; + + @Override + public void setup() { + currency = CoinsEngineAPI.getCurrency(HOOKS.getString("currencies.CoinsEngine.currency-name", "coins")); + } + + @Override + public String getName() { + return "CoinsEngine"; + } + + @Override + public boolean worksOffline() { + return false; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + if (currency == null) return 0; + return CoinsEngineAPI.getBalance(Bukkit.getPlayer(player), currency); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + if (currency == null) return; + CoinsEngineAPI.addBalance(Bukkit.getPlayer(player), currency, amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + if (currency == null) return; + CoinsEngineAPI.removeBalance(Bukkit.getPlayer(player), currency, amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/CurrencyHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/CurrencyHook.java new file mode 100644 index 0000000..3b7db74 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/CurrencyHook.java @@ -0,0 +1,23 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public interface CurrencyHook { + void setup(); + + String getName(); + + boolean worksOffline(); + + boolean usesDouble(); + + boolean isPersistent(); + + double getBalance(@NotNull UUID player); + + void giveBalance(@NotNull UUID player, double amount); + + void takeBalance(@NotNull UUID player, double amount); +} diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/ExperienceHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/ExperienceHook.java new file mode 100644 index 0000000..afcd2ba --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/ExperienceHook.java @@ -0,0 +1,120 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class ExperienceHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "Experience"; + } + + @Override + public boolean worksOffline() { + return false; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + final Player pl = Bukkit.getPlayer(player); + return getExp(pl); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + final Player pl = Bukkit.getPlayer(player); + changeExp(pl, (int) amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + final Player pl = Bukkit.getPlayer(player); + changeExp(pl, (int) (amount * -1)); + } + + // credit: https://gist.githubusercontent.com/Jikoo/30ec040443a4701b8980/raw/0745ca25a8aaaf749ba2f2164a809e998f6a37c4/Experience.java + private int getExp(@NotNull Player player) { + return getExpFromLevel(player.getLevel()) + Math.round(getExpToNext(player.getLevel()) * player.getExp()); + } + + private int getExpFromLevel(int level) { + if (level > 30) { + return (int) (4.5 * level * level - 162.5 * level + 2220); + } + if (level > 15) { + return (int) (2.5 * level * level - 40.5 * level + 360); + } + return level * level + 6 * level; + } + + private double getLevelFromExp(long exp) { + int level = getIntLevelFromExp(exp); + + // Get remaining exp progressing towards next level. Cast to float for next bit of math. + float remainder = exp - (float) getExpFromLevel(level); + + // Get level progress with float precision. + float progress = remainder / getExpToNext(level); + + // Slap both numbers together and call it a day. While it shouldn't be possible for progress + // to be an invalid value (value < 0 || 1 <= value) + return ((double) level) + progress; + } + + private int getIntLevelFromExp(long exp) { + if (exp > 1395) { + return (int) ((Math.sqrt(72 * exp - 54215D) + 325) / 18); + } + if (exp > 315) { + return (int) (Math.sqrt(40 * exp - 7839D) / 10 + 8.1); + } + if (exp > 0) { + return (int) (Math.sqrt(exp + 9D) - 3); + } + return 0; + } + + private int getExpToNext(int level) { + if (level >= 30) { + // Simplified formula. Internal: 112 + (level - 30) * 9 + return level * 9 - 158; + } + if (level >= 15) { + // Simplified formula. Internal: 37 + (level - 15) * 5 + return level * 5 - 38; + } + // Internal: 7 + level * 2 + return level * 2 + 7; + } + + private void changeExp(Player player, int exp) { + exp += getExp(player); + + if (exp < 0) { + exp = 0; + } + + double levelAndExp = getLevelFromExp(exp); + int level = (int) levelAndExp; + player.setLevel(level); + player.setExp((float) (levelAndExp - level)); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/KingdomsXHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/KingdomsXHook.java new file mode 100644 index 0000000..628bcb4 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/KingdomsXHook.java @@ -0,0 +1,52 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import org.jetbrains.annotations.NotNull; +import org.kingdoms.constants.player.KingdomPlayer; + +import java.util.UUID; + +public class KingdomsXHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "KingdomsX"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + final KingdomPlayer kingdomPlayer = KingdomPlayer.getKingdomPlayer(player); + if (kingdomPlayer.getKingdom() == null) return 0.0D; + return kingdomPlayer.getKingdom().getResourcePoints(); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + final KingdomPlayer kingdomPlayer = KingdomPlayer.getKingdomPlayer(player); + kingdomPlayer.getKingdom().addResourcePoints((long) amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + final KingdomPlayer kingdomPlayer = KingdomPlayer.getKingdomPlayer(player); + kingdomPlayer.getKingdom().addResourcePoints((long) (amount * -1)); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlaceholderCurrencyHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlaceholderCurrencyHook.java new file mode 100644 index 0000000..71adbc1 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlaceholderCurrencyHook.java @@ -0,0 +1,70 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.block.implementation.Section; +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class PlaceholderCurrencyHook implements CurrencyHook { + private final String name; + private final Section section; + + public PlaceholderCurrencyHook(String name, Section section) { + this.name = name; + this.section = section; + } + + @Override + public void setup() { + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean worksOffline() { + return section.getBoolean("works-offline", false); + } + + @Override + public boolean usesDouble() { + return section.getBoolean("uses-double", false); + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + final OfflinePlayer pl = Bukkit.getOfflinePlayer(player); + final String placeholder = section.getString("settings.raw-placeholder"); + return Double.parseDouble(PlaceholderAPI.setPlaceholders(pl.getPlayer() == null ? pl : pl.getPlayer(), placeholder)); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + final OfflinePlayer pl = Bukkit.getOfflinePlayer(player); + if (pl.getName() == null) return; + final String placeholder = section.getString("settings.give-command") + .replace("%amount%", "" + amount) + .replace("%player%", pl.getName()); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), placeholder); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + final OfflinePlayer pl = Bukkit.getOfflinePlayer(player); + if (pl.getName() == null) return; + final String placeholder = section.getString("settings.take-command") + .replace("%amount%", "" + amount) + .replace("%player%", pl.getName()); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), placeholder); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlayerPointsHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlayerPointsHook.java new file mode 100644 index 0000000..ff60dd3 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/PlayerPointsHook.java @@ -0,0 +1,51 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import org.black_ixx.playerpoints.PlayerPoints; +import org.black_ixx.playerpoints.PlayerPointsAPI; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class PlayerPointsHook implements CurrencyHook { + private PlayerPointsAPI econ = null; + + @Override + public void setup() { + econ = PlayerPoints.getInstance().getAPI(); + } + + @Override + public String getName() { + return "PlayerPoints"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return econ.look(player); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + econ.give(player, (int) amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + econ.take(player, (int) Math.round(amount)); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/RivalHarvesterHoesHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/RivalHarvesterHoesHook.java new file mode 100644 index 0000000..76f42e3 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/RivalHarvesterHoesHook.java @@ -0,0 +1,49 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.rivaldev.harvesterhoes.Main; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class RivalHarvesterHoesHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "RivalHarvesterHoes"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return Main.instance.getEconomy().getEconomyAmount(Bukkit.getOfflinePlayer(player)); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + Main.instance.getEconomy().giveEconomyAmount(Bukkit.getOfflinePlayer(player), amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + Main.instance.getEconomy().removeEconomyAmount(Bukkit.getOfflinePlayer(player), amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/RoyaleEconomyHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/RoyaleEconomyHook.java new file mode 100644 index 0000000..84d20f7 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/RoyaleEconomyHook.java @@ -0,0 +1,48 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.qKing12.RoyaleEconomy.RoyaleEconomy; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class RoyaleEconomyHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "RoyaleEconomy"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return RoyaleEconomy.apiHandler.balance.getBalance(player.toString()); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + RoyaleEconomy.apiHandler.balance.addBalance(player.toString(), amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + RoyaleEconomy.apiHandler.balance.removeBalance(player.toString(), amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/SuperMobCoinsHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/SuperMobCoinsHook.java new file mode 100644 index 0000000..3b3d3ce --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/SuperMobCoinsHook.java @@ -0,0 +1,51 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.swanis.mobcoins.MobCoinsAPI; +import me.swanis.mobcoins.profile.Profile; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class SuperMobCoinsHook implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "SuperMobCoins"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return MobCoinsAPI.getProfileManager().getProfile(player).getMobCoins(); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + final Profile profile = MobCoinsAPI.getProfileManager().getProfile(player); + profile.setMobCoins((long) (profile.getMobCoins() + amount)); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + final Profile profile = MobCoinsAPI.getProfileManager().getProfile(player); + profile.setMobCoins((long) (profile.getMobCoins() - amount)); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/TheOnlyMobCoins.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/TheOnlyMobCoins.java new file mode 100644 index 0000000..644b3df --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/TheOnlyMobCoins.java @@ -0,0 +1,52 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.aglerr.mobcoins.api.MobCoinsAPI; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class TheOnlyMobCoins implements CurrencyHook { + + @Override + public void setup() { + } + + @Override + public String getName() { + return "TheOnly-MobCoins"; + } + + @Override + public boolean worksOffline() { + return false; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + if (MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)) == null) return 0; + return MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)).getCoins(); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + if (MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)) == null) return; + MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)).addCoins(amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + if (MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)) == null) return; + MobCoinsAPI.getPlayerData(Bukkit.getPlayer(player)).reduceCoins(amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/TokenManagerHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/TokenManagerHook.java new file mode 100644 index 0000000..b4331ef --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/TokenManagerHook.java @@ -0,0 +1,51 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.realized.tokenmanager.api.TokenManager; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class TokenManagerHook implements CurrencyHook { + private TokenManager eco; + + @Override + public void setup() { + eco = (TokenManager) Bukkit.getPluginManager().getPlugin("TokenManager"); + } + + @Override + public String getName() { + return "TokenManager"; + } + + @Override + public boolean worksOffline() { + return false; + } + + @Override + public boolean usesDouble() { + return false; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return eco.getTokens(Bukkit.getPlayer(player)).orElse(0); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + eco.addTokens(Bukkit.getPlayer(player), (long) amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + eco.removeTokens(Bukkit.getPlayer(player), (long) amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/UltraEconomyHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/UltraEconomyHook.java new file mode 100644 index 0000000..95dcec0 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/UltraEconomyHook.java @@ -0,0 +1,63 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import me.TechsCode.UltraEconomy.UltraEconomy; +import me.TechsCode.UltraEconomy.objects.Account; +import me.TechsCode.UltraEconomy.objects.Currency; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.UUID; + +import static com.artillexstudios.axtrade.AxTrade.HOOKS; + +public class UltraEconomyHook implements CurrencyHook { + private Currency currency = null; + + @Override + public void setup() { + final Optional currencyOptional = UltraEconomy.getAPI().getCurrencies().name(HOOKS.getString("currencies.UltraEconomy.currency-name", "coins")); + if (!currencyOptional.isPresent()) throw new RuntimeException("Currency not found!"); + currency = currencyOptional.get(); + } + + @Override + public String getName() { + return "UltraEconomy"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + final Optional account = UltraEconomy.getAPI().getAccounts().uuid(player); + if (!account.isPresent()) return 0.0D; + return account.get().getBalance(currency).getOnHand(); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + final Optional account = UltraEconomy.getAPI().getAccounts().uuid(player); + if (account.isEmpty()) return; + account.get().addBalance(currency, amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + final Optional account = UltraEconomy.getAPI().getAccounts().uuid(player); + if (account.isEmpty()) return; + account.get().removeBalance(currency, amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/hooks/currency/VaultHook.java b/src/main/java/com/artillexstudios/axtrade/hooks/currency/VaultHook.java new file mode 100644 index 0000000..9c27d84 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/hooks/currency/VaultHook.java @@ -0,0 +1,55 @@ +package com.artillexstudios.axtrade.hooks.currency; + +import net.milkbowl.vault.economy.Economy; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public class VaultHook implements CurrencyHook { + private Economy econ = null; + + @Override + public void setup() { + final RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) return; + + econ = rsp.getProvider(); + } + + @Override + public String getName() { + return "Vault"; + } + + @Override + public boolean worksOffline() { + return true; + } + + @Override + public boolean usesDouble() { + return true; + } + + @Override + public boolean isPersistent() { + return false; + } + + @Override + public double getBalance(@NotNull UUID player) { + return econ.getBalance(Bukkit.getOfflinePlayer(player)); + } + + @Override + public void giveBalance(@NotNull UUID player, double amount) { + econ.depositPlayer(Bukkit.getOfflinePlayer(player), amount); + } + + @Override + public void takeBalance(@NotNull UUID player, double amount) { + econ.withdrawPlayer(Bukkit.getOfflinePlayer(player), amount); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/listeners/PlayerInteractEntityListener.java b/src/main/java/com/artillexstudios/axtrade/listeners/PlayerInteractEntityListener.java new file mode 100644 index 0000000..4e2d67c --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/listeners/PlayerInteractEntityListener.java @@ -0,0 +1,30 @@ +package com.artillexstudios.axtrade.listeners; + +import com.artillexstudios.axtrade.commands.Commands; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.WeakHashMap; + +public class PlayerInteractEntityListener implements Listener { + private final WeakHashMap cd = new WeakHashMap<>(); + + @EventHandler (ignoreCancelled = true) + public void onClick(@NotNull PlayerInteractEntityEvent event) { + final Player player = event.getPlayer(); + + if (cd.containsKey(player) && System.currentTimeMillis() - cd.get(player) < 100L) return; + + if (!player.isSneaking()) return; + if (!(event.getRightClicked() instanceof Player)) return; + + cd.put(player, System.currentTimeMillis()); + final Player sendTo = (Player) event.getRightClicked(); + if (!sendTo.isOnline()) return; + + new Commands().trade(player, sendTo); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java b/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java new file mode 100644 index 0000000..1ccb230 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java @@ -0,0 +1,59 @@ +package com.artillexstudios.axtrade.listeners; + +import com.artillexstudios.axtrade.trade.Trade; +import com.artillexstudios.axtrade.trade.Trades; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.jetbrains.annotations.NotNull; + +public class TradeListeners implements Listener { + + @EventHandler + public void onQuit(@NotNull PlayerQuitEvent event) { + final Player player = event.getPlayer(); + final Trade trade = Trades.getTrade(player); + if (trade == null) return; + trade.abort(); + } + + @EventHandler + public void onDrop(@NotNull PlayerDropItemEvent event) { + final Player player = event.getPlayer(); + final Trade trade = Trades.getTrade(player); + if (trade == null) return; + event.setCancelled(true); + } + + @EventHandler + public void onMove(@NotNull PlayerMoveEvent event) { + final Player player = event.getPlayer(); + final Trade trade = Trades.getTrade(player); + if (trade == null) return; + if (System.currentTimeMillis() - trade.getPrepTime() < 1_000L) return; + trade.abort(); + } + + @EventHandler + public void onInteract(@NotNull PlayerInteractEvent event) { + final Player player = event.getPlayer(); + final Trade trade = Trades.getTrade(player); + if (trade == null) return; + event.setCancelled(true); + trade.abort(); + } + + @EventHandler + public void onCommand(@NotNull PlayerCommandPreprocessEvent event) { + final Player player = event.getPlayer(); + final Trade trade = Trades.getTrade(player); + if (trade == null) return; + event.setCancelled(true); + trade.abort(); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/request/Request.java b/src/main/java/com/artillexstudios/axtrade/request/Request.java new file mode 100644 index 0000000..b243aa4 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/request/Request.java @@ -0,0 +1,27 @@ +package com.artillexstudios.axtrade.request; + +import org.bukkit.entity.Player; + +public class Request { + private final long time; + private final Player sender; + private final Player receiver; + + public Request(Player sender, Player receiver) { + this.time = System.currentTimeMillis(); + this.sender = sender; + this.receiver = receiver; + } + + public long getTime() { + return time; + } + + public Player getReceiver() { + return receiver; + } + + public Player getSender() { + return sender; + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/request/Requests.java b/src/main/java/com/artillexstudios/axtrade/request/Requests.java new file mode 100644 index 0000000..6e9f239 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/request/Requests.java @@ -0,0 +1,73 @@ +package com.artillexstudios.axtrade.request; + +import com.artillexstudios.axtrade.trade.Trades; +import com.artillexstudios.axtrade.utils.SoundUtils; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Map; + +import static com.artillexstudios.axtrade.AxTrade.CONFIG; +import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; + +public class Requests { + private static final ArrayList requests = new ArrayList<>(); + + public static void addRequest(@NotNull Player sender, @NotNull Player receiver) { + if (sender.equals(receiver)) { + MESSAGEUTILS.sendLang(sender, "request.cant-trade-self", Map.of("%player%", receiver.getName())); + return; + } + + if (Trades.isTrading(receiver) || Trades.isTrading(sender)) { + MESSAGEUTILS.sendLang(sender, "request.already-in-trade", Map.of("%player%", receiver.getName())); + return; + } + + int maxDist = CONFIG.getInt("trade-max-distance", 10); + if (maxDist != -1 && (sender.getWorld() != receiver.getWorld() || maxDist < sender.getLocation().distance(receiver.getLocation()))) { + MESSAGEUTILS.sendLang(sender, "request.too-far", Map.of("%player%", receiver.getName())); + return; + } + + var request = Requests.getRequest(sender, receiver); + if (request != null && !request.getSender().equals(sender)) { + Trades.addTrade(sender, receiver); + requests.remove(request); + return; + } + + if (request != null && System.currentTimeMillis() - request.getTime() < CONFIG.getInt("trade-request-expire-seconds", 60) * 1_000L) { + MESSAGEUTILS.sendLang(sender, "request.already-sent", Map.of("%player%", receiver.getName())); + return; + } + + requests.add(new Request(sender, receiver)); + + MESSAGEUTILS.sendLang(sender, "request.sent-sender", Map.of("%player%", receiver.getName())); + MESSAGEUTILS.sendLang(receiver, "request.sent-receiver", Map.of("%player%", sender.getName())); + SoundUtils.playSound(sender, "requested"); + SoundUtils.playSound(receiver, "requested"); + } + + public static boolean hasRequest(Player p1, Player p2) { + for (Request rq : requests) { + if (!((rq.getSender() == p1 || rq.getSender() == p2) && (rq.getReceiver() == p1 || rq.getReceiver() == p2))) continue; + return true; + } + + return false; + } + + @Nullable + public static Request getRequest(Player p1, Player p2) { + for (Request rq : requests) { + if (!((rq.getSender() == p1 || rq.getSender() == p2) && (rq.getReceiver() == p1 || rq.getReceiver() == p2))) continue; + return rq; + } + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java b/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java index 3812445..c6f5fbd 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java @@ -22,6 +22,7 @@ public class GuiFrame { protected final Config file; protected BaseGui gui; protected Player player; + protected boolean opened = false; public GuiFrame(Config file, Player player) { this.file = file; @@ -69,7 +70,13 @@ public class GuiFrame { final ItemStack it = buildItem(itemRoute, replacements); it.setAmount(amount); final GuiItem guiItem = new GuiItem(it, action); - gui.setItem(getSlots(slotRoute), guiItem); + if (opened) { + for (int slot : getSlots(slotRoute)) { + gui.updateItem(slot, guiItem); + } + } + else + gui.setItem(getSlots(slotRoute), guiItem); } protected List getSlots(String r) { diff --git a/src/main/java/com/artillexstudios/axtrade/trade/Trade.java b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java index cdd4d4e..2fbdeef 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/Trade.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java @@ -1,6 +1,8 @@ package com.artillexstudios.axtrade.trade; import com.artillexstudios.axapi.scheduler.Scheduler; +import com.artillexstudios.axtrade.hooks.currency.CurrencyHook; +import com.artillexstudios.axtrade.utils.SoundUtils; import org.bukkit.entity.Player; import java.util.Map; @@ -10,7 +12,8 @@ import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; public class Trade { protected final TradePlayer player1; protected final TradePlayer player2; - private boolean ended = false; + protected boolean ended = false; + protected long prepTime = System.currentTimeMillis(); public Trade(Player p1, Player p2) { this.player1 = new TradePlayer(this, p1); @@ -26,9 +29,18 @@ public class Trade { public void abort() { if (ended) return; - // todo: refund items - MESSAGEUTILS.sendLang(player1.getPlayer(), "trade-aborted", Map.of("%player%", player2.getPlayer().getName())); - MESSAGEUTILS.sendLang(player2.getPlayer(), "trade-aborted", Map.of("%player%", player1.getPlayer().getName())); + player1.getTradeGui().getItems().forEach(itemStack -> { + if (itemStack == null) return; + player1.getPlayer().getInventory().addItem(itemStack); + }); + player2.getTradeGui().getItems().forEach(itemStack -> { + if (itemStack == null) return; + player2.getPlayer().getInventory().addItem(itemStack); + }); + MESSAGEUTILS.sendLang(player1.getPlayer(), "trade.aborted", Map.of("%player%", player2.getPlayer().getName())); + MESSAGEUTILS.sendLang(player2.getPlayer(), "trade.aborted", Map.of("%player%", player1.getPlayer().getName())); + SoundUtils.playSound(player1.getPlayer(), "aborted"); + SoundUtils.playSound(player2.getPlayer(), "aborted"); end(); } @@ -41,4 +53,50 @@ public class Trade { player2.getPlayer().closeInventory(); player2.getPlayer().updateInventory(); } + + public void complete() { + for (Map.Entry entry : player1.getCurrencies().entrySet()) { + if (entry.getKey().getBalance(player1.getPlayer().getUniqueId()) < entry.getValue()) { + abort(); + return; + } + } + + for (Map.Entry entry : player2.getCurrencies().entrySet()) { + if (entry.getKey().getBalance(player2.getPlayer().getUniqueId()) < entry.getValue()) { + abort(); + return; + } + } + + for (Map.Entry entry : player1.getCurrencies().entrySet()) { + entry.getKey().takeBalance(player1.getPlayer().getUniqueId(), entry.getValue()); + entry.getKey().giveBalance(player2.getPlayer().getUniqueId(), entry.getValue()); + } + + for (Map.Entry entry : player2.getCurrencies().entrySet()) { + entry.getKey().takeBalance(player2.getPlayer().getUniqueId(), entry.getValue()); + entry.getKey().giveBalance(player1.getPlayer().getUniqueId(), entry.getValue()); + } + + MESSAGEUTILS.sendLang(player1.getPlayer(), "trade.completed", Map.of("%player%", player2.getPlayer().getName())); + MESSAGEUTILS.sendLang(player2.getPlayer(), "trade.completed", Map.of("%player%", player1.getPlayer().getName())); + SoundUtils.playSound(player1.getPlayer(), "completed"); + SoundUtils.playSound(player2.getPlayer(), "completed"); + + player1.getTradeGui().getItems().forEach(itemStack -> { + if (itemStack == null) return; + player2.getPlayer().getInventory().addItem(itemStack); + }); + player2.getTradeGui().getItems().forEach(itemStack -> { + if (itemStack == null) return; + player1.getPlayer().getInventory().addItem(itemStack); + }); + + end(); + } + + public long getPrepTime() { + return prepTime; + } } diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java index 4b423b0..33cf339 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java @@ -1,37 +1,47 @@ package com.artillexstudios.axtrade.trade; -import com.artillexstudios.axapi.scheduler.ScheduledTask; import com.artillexstudios.axapi.scheduler.Scheduler; import com.artillexstudios.axapi.utils.StringUtils; +import com.artillexstudios.axtrade.AxTrade; +import com.artillexstudios.axtrade.utils.NumberUtils; +import de.rapha149.signgui.SignGUI; +import de.rapha149.signgui.SignGUIAction; import dev.triumphteam.gui.guis.Gui; +import dev.triumphteam.gui.guis.GuiItem; import dev.triumphteam.gui.guis.StorageGui; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.function.Consumer; import static com.artillexstudios.axtrade.AxTrade.GUIS; +import static com.artillexstudios.axtrade.AxTrade.LANG; +import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; public class TradeGui extends GuiFrame { private final Trade trade; private final TradePlayer player; - private final boolean shouldMirror; protected final StorageGui gui; protected final List slots = getSlots("own-slots"); + protected final List otherSlots = getSlots("partner-slots"); + private boolean inSign = false; public TradeGui(@NotNull Trade trade, @NotNull TradePlayer player) { super(GUIS, player.getPlayer()); this.trade = trade; this.player = player; - this.shouldMirror = player == trade.player2; this.gui = Gui.storage() .rows(GUIS.getInt("rows",6)) .title(StringUtils.format(GUIS.getString("title").replace("%player%", player.getOtherPlayer().getPlayer().getName()))) + .disableItemDrop() .create(); setGui(gui); gui.setDefaultTopClickAction(event -> { + player.cancel(); if (!slots.contains(event.getSlot())) { event.setCancelled(true); if (event.getCursor() == null) return; @@ -42,8 +52,33 @@ public class TradeGui extends GuiFrame { Scheduler.get().run(scheduledTask -> trade.update()); }); + gui.setDragAction(event -> { + if (event.getInventory() == player.getPlayer().getInventory()) return; + if (!new HashSet<>(slots).containsAll(event.getInventorySlots())) { + event.setCancelled(true); + return; + } + player.cancel(); + Scheduler.get().run(scheduledTask -> trade.update()); + }); + + gui.setPlayerInventoryAction(event -> { + if (event.isShiftClick() && !slots.contains(event.getView().getTopInventory().firstEmpty())) { + event.setCancelled(true); + return; + } + player.cancel(); + Scheduler.get().run(scheduledTask -> trade.update()); + }); + + gui.setCloseGuiAction(event -> { + if (inSign) return; + trade.abort(); + }); + update(); gui.open(player.getPlayer()); + opened = true; } public void update() { @@ -51,6 +86,7 @@ public class TradeGui extends GuiFrame { super.createItem("own.confirm-item.slot", "own.confirm-item.cancel", event -> { event.setCancelled(true); player.cancel(); + trade.update(); }, Map.of(), player.getConfirmed()); } else { super.createItem("own.confirm-item.slot", "own.confirm-item.accept", event -> { @@ -68,6 +104,77 @@ public class TradeGui extends GuiFrame { event.setCancelled(true); }, Map.of()); } - gui.update(); + + for (String currencyItem : GUIS.getSection("own").getRoutesAsStrings(false)) { + final String currencyStr = GUIS.getString("own." + currencyItem + ".currency", null); + if (currencyStr == null) continue; + + super.createItem("own." + currencyItem, event -> { + event.setCancelled(true); + player.cancel(); + trade.update(); + inSign = true; + trade.prepTime = System.currentTimeMillis(); + event.getWhoClicked().closeInventory(); + + var lines = LANG.getStringList("currency-editor-sign"); + lines = StringUtils.formatListToString(lines); + final SignGUI signGUI = SignGUI.builder().setLines(lines.toArray(new String[0])).setHandler((player1, result) -> List.of(SignGUIAction.runSync(AxTrade.getInstance(), () -> { + if (trade.ended) return; + trade.prepTime = System.currentTimeMillis(); + String am = result.getLine(0); + TradePlayer.Result addResult = TradePlayer.Result.NOT_A_NUMBER; + if (com.artillexstudios.axapi.utils.NumberUtils.isDouble(am) && (addResult = player.setCurrency(currencyStr, Double.parseDouble(am))) == TradePlayer.Result.SUCCESS) { + MESSAGEUTILS.sendLang(player1, "currency-editor.success"); + } else { + switch (addResult) { + case NOT_ENOUGH_CURRENCY: + MESSAGEUTILS.sendLang(player1, "currency-editor.not-enough"); + break; + default: + MESSAGEUTILS.sendLang(player1, "currency-editor.failed"); + break; + } + } + gui.open(player.getPlayer()); + inSign = false; + trade.update(); + }))).build(); + signGUI.open(player.getPlayer()); + }, Map.of("%amount%", NumberUtils.formatNumber(player.getCurrency(currencyStr)))); + } + + for (String currencyItem : GUIS.getSection("partner").getRoutesAsStrings(false)) { + final String currencyStr = GUIS.getString("partner." + currencyItem + ".currency", null); + if (currencyStr == null) continue; + + super.createItem("partner." + currencyItem, event -> { + event.setCancelled(true); + }, Map.of( + "%amount%", NumberUtils.formatNumber(player.getOtherPlayer().getCurrency(currencyStr)), + "%player%", player.getOtherPlayer().getPlayer().getName() + )); + } + + for (int slot : otherSlots) { + gui.removeItem(slot); + } + + if (!opened) return; + var otherItems = player.getOtherPlayer().getTradeGui().getItems(); + int n = 0; + for (int slot : otherSlots) { + if (otherItems.get(n) != null) + gui.updateItem(slot, new GuiItem(otherItems.get(n), event -> event.setCancelled(true))); + n++; + } + } + + public List getItems() { + final List items = new ArrayList<>(); + for (int slot : slots) { + items.add(gui.getInventory().getItem(slot)); + } + return items; } } diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java index 906286e..17bea1e 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java @@ -1,7 +1,12 @@ package com.artillexstudios.axtrade.trade; +import com.artillexstudios.axtrade.hooks.HookManager; +import com.artillexstudios.axtrade.hooks.currency.CurrencyHook; +import com.artillexstudios.axtrade.utils.SoundUtils; import org.bukkit.entity.Player; +import java.util.HashMap; + import static com.artillexstudios.axtrade.AxTrade.CONFIG; public class TradePlayer { @@ -9,6 +14,7 @@ public class TradePlayer { private TradePlayer otherPlayer; private TradeGui tradeGui; private final Trade trade; + private final HashMap currencies = new HashMap<>(); // confirmed // null > not confirmed @@ -48,12 +54,16 @@ public class TradePlayer { public void confirm() { this.confirmed = CONFIG.getInt("trade-confirm-seconds", 10); trade.update(); + SoundUtils.playSound(player, "accept"); + SoundUtils.playSound(otherPlayer.getPlayer(), "accept"); } public void cancel() { + if (confirmed == null) return; this.confirmed = null; otherPlayer.setConfirmed(null); - trade.update(); + SoundUtils.playSound(player, "cancel"); + SoundUtils.playSound(otherPlayer.getPlayer(), "cancel"); } public void setConfirmed(Integer confirmed) { @@ -63,5 +73,36 @@ public class TradePlayer { public void tick() { confirmed -= 1; trade.update(); + SoundUtils.playSound(player, "countdown"); + } + + public HashMap getCurrencies() { + return currencies; + } + + public double getCurrency(String currency) { + final CurrencyHook currencyHook = HookManager.getCurrencyHook(currency); + if (currencyHook == null) return 0; + if (!currencies.containsKey(currencyHook)) return 0; + return currencies.get(currencyHook); + } + + public Result setCurrency(String currency, double amount) { + if (Double.isNaN(amount)) return Result.NOT_A_NUMBER; + final CurrencyHook currencyHook = HookManager.getCurrencyHook(currency); + if (currencyHook == null) return Result.CURRENCY_NOT_FOUND; + amount = currencyHook.usesDouble() ? amount : Math.round(amount); + if (amount < 0.1) return Result.TOO_LOW_VALUE; + if (currencyHook.getBalance(player.getUniqueId()) < amount) return Result.NOT_ENOUGH_CURRENCY; + currencies.put(currencyHook, amount); + return Result.SUCCESS; + } + + public enum Result { + NOT_A_NUMBER, + CURRENCY_NOT_FOUND, + TOO_LOW_VALUE, + NOT_ENOUGH_CURRENCY, + SUCCESS } } diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java b/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java index 141309f..ea1d3f7 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java @@ -2,10 +2,6 @@ package com.artillexstudios.axtrade.trade; import com.artillexstudios.axapi.scheduler.Scheduler; -import java.util.Map; - -import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; - public class TradeTicker { public void start() { @@ -14,10 +10,7 @@ public class TradeTicker { if (!(trade.player1.hasConfirmed() && trade.player2.hasConfirmed())) continue; if (trade.player1.getConfirmed() == 1) { - MESSAGEUTILS.sendLang(trade.player1.getPlayer(), "trade-completed", Map.of("%player%", trade.player2.getPlayer().getName())); - MESSAGEUTILS.sendLang(trade.player2.getPlayer(), "trade-completed", Map.of("%player%", trade.player1.getPlayer().getName())); - // todo: transfer items - trade.end(); + trade.complete(); continue; } diff --git a/src/main/java/com/artillexstudios/axtrade/trade/Trades.java b/src/main/java/com/artillexstudios/axtrade/trade/Trades.java index 7a00a18..325e6e2 100644 --- a/src/main/java/com/artillexstudios/axtrade/trade/Trades.java +++ b/src/main/java/com/artillexstudios/axtrade/trade/Trades.java @@ -1,6 +1,8 @@ package com.artillexstudios.axtrade.trade; +import com.artillexstudios.axtrade.utils.SoundUtils; import org.bukkit.entity.Player; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Map; @@ -13,8 +15,10 @@ public class Trades { public static void addTrade(Player p1, Player p2) { Trade trade = new Trade(p1, p2); trades.add(trade); - MESSAGEUTILS.sendLang(p1, "trade-started", Map.of("%player%", p2.getName())); - MESSAGEUTILS.sendLang(p2, "trade-started", Map.of("%player%", p1.getName())); + MESSAGEUTILS.sendLang(p1, "trade.started", Map.of("%player%", p2.getName())); + MESSAGEUTILS.sendLang(p2, "trade.started", Map.of("%player%", p1.getName())); + SoundUtils.playSound(p1, "started"); + SoundUtils.playSound(p2, "started"); } public static void removeTrade(Trade trade) { @@ -24,4 +28,13 @@ public class Trades { public static ArrayList getTrades() { return trades; } + + public static boolean isTrading(Player player) { + return trades.stream().anyMatch(trade -> trade.player1.getPlayer().equals(player) || trade.player2.getPlayer().equals(player)); + } + + @Nullable + public static Trade getTrade(Player player) { + return trades.stream().filter(trade -> trade.player1.getPlayer().equals(player) || trade.player2.getPlayer().equals(player)).findAny().orElse(null); + } } diff --git a/src/main/java/com/artillexstudios/axtrade/utils/NumberUtils.java b/src/main/java/com/artillexstudios/axtrade/utils/NumberUtils.java new file mode 100644 index 0000000..fa50a63 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/utils/NumberUtils.java @@ -0,0 +1,31 @@ +package com.artillexstudios.axtrade.utils; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; + +import static com.artillexstudios.axtrade.AxTrade.CONFIG; + +public class NumberUtils { + private static NumberFormat formatter = new DecimalFormat(CONFIG.getString("number-formatting.formatted", "#,###.##")); + + public static void reload() { + int mode = CONFIG.getInt("number-formatting.mode", 0); + switch (mode) { + case 0: + formatter = new DecimalFormat(CONFIG.getString("number-formatting.formatted", "#,###.##")); + break; + case 1: + final String[] lang = CONFIG.getString("number-formatting.short", "en_US").split("_"); + formatter = DecimalFormat.getCompactNumberInstance(new Locale(lang[0], lang[1]), NumberFormat.Style.SHORT); + break; + case 2: + formatter = null; + break; + } + } + + public static String formatNumber(double number) { + return formatter == null ? "" + number : formatter.format(number); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/utils/SoundUtils.java b/src/main/java/com/artillexstudios/axtrade/utils/SoundUtils.java new file mode 100644 index 0000000..ba6ccbf --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/utils/SoundUtils.java @@ -0,0 +1,28 @@ +package com.artillexstudios.axtrade.utils; + +import com.artillexstudios.axapi.utils.StringUtils; +import net.kyori.adventure.key.InvalidKeyException; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.artillexstudios.axtrade.AxTrade.BUKKITAUDIENCES; +import static com.artillexstudios.axtrade.AxTrade.LANG; + +public class SoundUtils { + + public static void playSound(@NotNull Player player, @Nullable String route) { + if (route == null) return; + if (LANG.getString("sounds." + route, "").isBlank()) return; + + try { + final Sound sound = Sound.sound().type(Key.key(LANG.getString("sounds." + route))).build(); + BUKKITAUDIENCES.player(player).playSound(sound); + } catch (InvalidKeyException ex) { + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("&#FFFFAA[AxAuctions] The sound %sound% does not exist, section: %section%!".replace("%sound%", LANG.getString("sounds." + route)).replace("%section%", route))); + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3d8962c..afcf009 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,5 +9,28 @@ command-aliases: # the time after clicking the trade confirm button before the trade finishes trade-confirm-seconds: 10 +# how fast should trade requests expire? +trade-request-expire-seconds: 60 + +# how far can 2 people be to trade? +# set to -1 to disable +trade-max-distance: 10 + +number-formatting: + # modes: + # 0 - formatted (customizable, look at the formatted part) + # 1 - short (1K) + # 2 - raw (1000.4242421412) + mode: 0 + # https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html + formatted: "#,###.##" + # format: language_COUNTRY + short: "en_US" + +# list of gamemodes: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/GameMode.html +# you can't use the trade in these gamemodes +disallowed-gamemodes: + - SPECTATOR + # do not change this version: 1 \ No newline at end of file diff --git a/src/main/resources/currencies.yml b/src/main/resources/currencies.yml new file mode 100644 index 0000000..1ae7b0f --- /dev/null +++ b/src/main/resources/currencies.yml @@ -0,0 +1,47 @@ +# you can create your own currencies by using placeholders +# make sure that none of the placeholders have any formatting on them +# requires PlaceholderAPI +placeholder-currencies: + Example-Currency: + register: false + # if the currency uses whole numbers then disable this + # 100.5 - true + # 100 - false + uses-double: true + # if the placeholder gets parsed even for offline players, enable this + works-offline: false + settings: + raw-placeholder: "%vault_eco_balance_fixed%" + give-command: "eco give %player% %amount%" + take-command: "eco take %player% %amount%" + +currencies: + Experience: + register: true + Vault: + register: true + PlayerPoints: + register: true + RoyaleEconomy: + register: true + CoinsEngine: + register: true + currency-name: "coins" + UltraEconomy: + register: true + currency-name: "coins" + KingdomsX: + register: true + RivalHarvesterHoes: + register: true + SuperMobCoins: + register: true + TheOnly-MobCoins: + register: true + TokenManager: + register: true + AxQuestBoard: + register: true + +# do not change this +version: 5 \ No newline at end of file diff --git a/src/main/resources/guis.yml b/src/main/resources/guis.yml index 7307e02..b9787bf 100644 --- a/src/main/resources/guis.yml +++ b/src/main/resources/guis.yml @@ -45,27 +45,29 @@ own: - " &7- &fDo you want to change something?" - "" - "�ffdd&l> �ffddClick &8- �ffddCancel Confirmation" - # you can define as many currencies as you want, also make sure to copy them to the 'partner' section! + # you can define as many currencies as you want, but make sure to copy them to the 'partner' section too! currency1: slot: 2 # you need Vault installed for this - currency: "vault:money" + currency: "Vault" material: "GOLD_NUGGET" name: "�ffdd&lᴍᴏɴᴇʏ" lore: + - "&7Your offer" - "" - - " &7- &fAmount:" + - " &7- &fAmount: �ffdd%amount%$" - "" - "�ffdd&l> �ffddClick &8- �ffddChange Amount" currency2: slot: 3 # you need Vault installed for this - currency: "vanilla:experience" + currency: "Experience" material: "EXPERIENCE_BOTTLE" name: "�ffdd&lᴇxᴘᴇʀɪᴇɴᴄᴇ" lore: + - "&7Your offer" - "" - - " &7- &fAmount:" + - " &7- &fAmount: �ffdd%amount% EXP" - "" - "�ffdd&l> �ffddClick &8- �ffddChange Amount" @@ -88,24 +90,24 @@ partner: - " &7- &fThe other player has confirmed the trade!" currency1: slot: 6 - # you need Vault installed for this - currency: "vault:money" + currency: "Vault" material: "GOLD_NUGGET" name: "�ffdd&lᴍᴏɴᴇʏ" lore: + - "&7%player%'s offer" - "" - - " &7- &fAmount:" + - " &7- &fAmount: �ffdd%amount%$" - "" - "�ffdd&l> �ffddClick &8- �ffddChange Amount" currency2: slot: 5 - # you need Vault installed for this - currency: "vanilla:experience" + currency: "Experience" material: "EXPERIENCE_BOTTLE" name: "�ffdd&lᴇxᴘᴇʀɪᴇɴᴄᴇ" lore: + - "&7%player%'s offer" - "" - - " &7- &fAmount:" + - " &7- &fAmount: �ffdd%amount% EXP" - "" - "�ffdd&l> �ffddClick &8- �ffddChange Amount" diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml index c60268d..4c37911 100644 --- a/src/main/resources/lang.yml +++ b/src/main/resources/lang.yml @@ -15,9 +15,52 @@ reload: success: "!FF33Plugin successfully reloaded!" failed: "&#FF3333Failed to reload the plugin! Something is wrong in the &f%file%&#FF3333 file, look in the console or use a yaml validator to fix the errors!" -trade-started: "&#CCFFEEYou have started a trade with �FFDD%player%&#CCFFEE!" -trade-aborted: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas aborted!" -trade-completed: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas completed!" +trade: + started: "&#CCFFEEYou have started a trade with �FFDD%player%&#CCFFEE!" + completed: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas completed!" + aborted: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas aborted!" + +currency-editor: + success: "&#CCFFEESuccessfully changed value!" + failed: "&#CCFFEEIncorrect value!" + not-enough: "&#CCFFEEYou don't have enough of this currency!" + +request: + sent-sender: "&#CCFFEEYou have successfully sent a trade request to �FFDD%player%&#CCFFEE!" + sent-receiver: | + &#CCFFEEYou have received a trade request from �FFDD%player%&#CCFFEE! + �FF00/trade accept %player% + &#FF0000/trade deny %player% + no-request: "&#CCFFEEYou don't have an active trade request from �FFDD%player%&#CCFFEE!" + deny-sender: "&#CCFFEEYou trade request was denied by �FFDD%player%&#CCFFEE!" + deny-receiver: "&#CCFFEEYou have successfully denied �FFDD%player%&#CCFFEE's trade request!" + cant-trade-self: "&#CCFFEEYou can't send a trade request to yourself!" + already-in-trade: "&#CCFFEEThe player is already trading with someone!" + already-sent: "&#CCFFEEYou have already sent a trade request to �FFDD%player%&#CCFFEE!" + too-far: "&#CCFFEEYou are too far from �FFDD%player% &#CCFFEEto send a trade request!" + +# this must be 4 lines +# note: currently the first line must be left empty +currency-editor-sign: + - "" + - "-----------" + - "Write the new value" + - "in the first line" + +# list of sounds: https://www.digminecraft.com/lists/sound_list_pc.php +# set to "" to disable +sounds: + # trade sounds + started: "entity.player.levelup" + completed: "entity.player.levelup" + aborted: "block.anvil.destroy" + # trade requests + deny: "block.anvil.land" + requested: "entity.experience_bottle.throw" + # gui sounds + accept: "ui.button.click" + countdown: "ui.button.click" + cancel: "ui.button.click" # do not change this version: 1 \ No newline at end of file