This commit is contained in:
BenceX100 2024-04-04 20:24:46 +02:00
parent 5b34367a56
commit 2dd3038526
34 changed files with 1688 additions and 45 deletions

99
pom.xml
View File

@ -23,8 +23,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
<source>12</source>
<target>12</target>
</configuration>
</plugin>
<plugin>
@ -95,13 +95,21 @@
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>techscode</id>
<url>https://repo.techscode.com/repository/maven-releases/</url>
</repository>
<repository>
<id>rosewood-repo</id>
<url>https://repo.rosewooddev.io/repository/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.artillexstudios.axapi</groupId>
<artifactId>axapi</artifactId>
<version>1.4.109</version>
<version>1.4.136</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -128,5 +136,90 @@
<version>3.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.aglerr.mobcoins</groupId>
<artifactId>MobCoins</artifactId>
<version>1.1.3</version>
<systemPath>${project.basedir}/libs/TheOnly-MobCoins-1.1.3.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>com.artillexstudios</groupId>
<artifactId>AxQuestBoardAPI</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.Realizedd</groupId>
<artifactId>TokenManager</artifactId>
<version>3.2.4</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>me.swanis.mobcoins</groupId>
<artifactId>MobCoins</artifactId>
<version>1.1.2</version>
<systemPath>${project.basedir}/libs/mobcoins-api-1.1.2-SNAPSHOT.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>me.rivaldev.harvesterhoes</groupId>
<artifactId>Main</artifactId>
<version>LATEST</version>
<systemPath>${project.basedir}/libs/RivalHarvesterHoesAPI.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>com.github.cryptomorin</groupId>
<artifactId>kingdoms</artifactId>
<version>LATEST</version>
<systemPath>${project.basedir}/libs/KingdomsX-1.16.14.1.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>su.nightexpress.coinsengine</groupId>
<artifactId>CoinsEngine</artifactId>
<version>2.1.1</version>
<systemPath>${project.basedir}/libs/CoinsEngine-2.1.1.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>me.qKing12.RoyaleEconomy</groupId>
<artifactId>RoyaleEconomy</artifactId>
<version>1.4.4</version>
<systemPath>${project.basedir}/libs/RoyaleEconomyAPI.jar</systemPath>
<scope>system</scope>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.black_ixx</groupId>
<artifactId>playerpoints</artifactId>
<version>3.2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.TechsCode</groupId>
<artifactId>UltraEconomyAPI</artifactId>
<version>2.6.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.rapha149.signgui</groupId>
<artifactId>signgui</artifactId>
<version>2.3.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -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<Runnable> 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("&#00ffdd[AxTrade] Loaded plugin!"));
Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("&#00FFDD[AxTrade] Loaded plugin!"));
}
}

View File

@ -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("&#00FFDD╚ &#AAFFDDSuccessful reload!"));
MESSAGEUTILS.sendLang(sender, "reload.success");
}

View File

@ -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<CurrencyHook> 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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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("&#33FF33[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<CurrencyHook> 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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Currency> 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> 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> 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> account = UltraEconomy.getAPI().getAccounts().uuid(player);
if (account.isEmpty()) return;
account.get().removeBalance(currency, amount);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Integer> getSlots(String r) {

View File

@ -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<CurrencyHook, Double> entry : player1.getCurrencies().entrySet()) {
if (entry.getKey().getBalance(player1.getPlayer().getUniqueId()) < entry.getValue()) {
abort();
return;
}
}
for (Map.Entry<CurrencyHook, Double> entry : player2.getCurrencies().entrySet()) {
if (entry.getKey().getBalance(player2.getPlayer().getUniqueId()) < entry.getValue()) {
abort();
return;
}
}
for (Map.Entry<CurrencyHook, Double> entry : player1.getCurrencies().entrySet()) {
entry.getKey().takeBalance(player1.getPlayer().getUniqueId(), entry.getValue());
entry.getKey().giveBalance(player2.getPlayer().getUniqueId(), entry.getValue());
}
for (Map.Entry<CurrencyHook, Double> 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;
}
}

View File

@ -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<Integer> slots = getSlots("own-slots");
protected final List<Integer> 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<ItemStack> getItems() {
final List<ItemStack> items = new ArrayList<>();
for (int slot : slots) {
items.add(gui.getInventory().getItem(slot));
}
return items;
}
}

View File

@ -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<CurrencyHook, Double> 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<CurrencyHook, Double> 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
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,27 +45,29 @@ own:
- " &7- &fDo you want to change something?"
- ""
- "&#00ffdd&l> &#00ffddClick &8- &#00ffddCancel 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: "&#00ffdd&lᴍɴᴇʏ"
lore:
- "&7Your offer"
- ""
- " &7- &fAmount:"
- " &7- &fAmount: &#00ffdd%amount%$"
- ""
- "&#00ffdd&l> &#00ffddClick &8- &#00ffddChange Amount"
currency2:
slot: 3
# you need Vault installed for this
currency: "vanilla:experience"
currency: "Experience"
material: "EXPERIENCE_BOTTLE"
name: "&#00ffdd&lᴇxᴘᴇʀɪᴇɴᴇ"
lore:
- "&7Your offer"
- ""
- " &7- &fAmount:"
- " &7- &fAmount: &#00ffdd%amount% EXP"
- ""
- "&#00ffdd&l> &#00ffddClick &8- &#00ffddChange 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: "&#00ffdd&lᴍɴᴇʏ"
lore:
- "&7%player%'s offer"
- ""
- " &7- &fAmount:"
- " &7- &fAmount: &#00ffdd%amount%$"
- ""
- "&#00ffdd&l> &#00ffddClick &8- &#00ffddChange Amount"
currency2:
slot: 5
# you need Vault installed for this
currency: "vanilla:experience"
currency: "Experience"
material: "EXPERIENCE_BOTTLE"
name: "&#00ffdd&lᴇxᴘᴇʀɪᴇɴᴇ"
lore:
- "&7%player%'s offer"
- ""
- " &7- &fAmount:"
- " &7- &fAmount: &#00ffdd%amount% EXP"
- ""
- "&#00ffdd&l> &#00ffddClick &8- &#00ffddChange Amount"

View File

@ -15,9 +15,52 @@ reload:
success: "&#33FF33Plugin 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 &#00FFDD%player%&#CCFFEE!"
trade-aborted: "&#CCFFEEYour trade with &#00FFDD%player% &#CCFFEEwas aborted!"
trade-completed: "&#CCFFEEYour trade with &#00FFDD%player% &#CCFFEEwas completed!"
trade:
started: "&#CCFFEEYou have started a trade with &#00FFDD%player%&#CCFFEE!"
completed: "&#CCFFEEYour trade with &#00FFDD%player% &#CCFFEEwas completed!"
aborted: "&#CCFFEEYour trade with &#00FFDD%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 &#00FFDD%player%&#CCFFEE!"
sent-receiver: |
&#CCFFEEYou have received a trade request from &#00FFDD%player%&#CCFFEE!
&#00FF00<click:run_command:'/trade accept %player%'>/trade accept %player%</click>
&#FF0000<click:run_command:'/trade deny %player%'>/trade deny %player%</click>
no-request: "&#CCFFEEYou don't have an active trade request from &#00FFDD%player%&#CCFFEE!"
deny-sender: "&#CCFFEEYou trade request was denied by &#00FFDD%player%&#CCFFEE!"
deny-receiver: "&#CCFFEEYou have successfully denied &#00FFDD%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 &#00FFDD%player%&#CCFFEE!"
too-far: "&#CCFFEEYou are too far from &#00FFDD%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