diff --git a/pom.xml b/pom.xml
index 24780a7..78f9c9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -221,5 +221,11 @@
2.3.2
compile
+
+ com.artillexstudios
+ AxShulkers
+ 1.5.6
+ provided
+
diff --git a/src/main/java/com/artillexstudios/axtrade/AxTrade.java b/src/main/java/com/artillexstudios/axtrade/AxTrade.java
index 33fb853..8bf6560 100644
--- a/src/main/java/com/artillexstudios/axtrade/AxTrade.java
+++ b/src/main/java/com/artillexstudios/axtrade/AxTrade.java
@@ -12,6 +12,7 @@ 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.lang.LanguageManager;
import com.artillexstudios.axtrade.listeners.PlayerInteractEntityListener;
import com.artillexstudios.axtrade.listeners.TradeListeners;
import com.artillexstudios.axtrade.trade.TradeTicker;
@@ -51,6 +52,8 @@ public final class AxTrade extends AxPlugin {
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());
+ LanguageManager.reload();
+
MESSAGEUTILS = new MessageUtils(LANG.getBackingDocument(), "prefix", CONFIG.getBackingDocument());
threadedQueue = new ThreadedQueue<>("AxRewards-Datastore-thread");
diff --git a/src/main/java/com/artillexstudios/axtrade/commands/Commands.java b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java
index b5bdede..3acd6fe 100644
--- a/src/main/java/com/artillexstudios/axtrade/commands/Commands.java
+++ b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java
@@ -3,6 +3,7 @@ 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.lang.LanguageManager;
import com.artillexstudios.axtrade.request.Requests;
import com.artillexstudios.axtrade.trade.Trades;
import com.artillexstudios.axtrade.utils.NumberUtils;
@@ -24,6 +25,7 @@ import java.util.Map;
import static com.artillexstudios.axtrade.AxTrade.CONFIG;
import static com.artillexstudios.axtrade.AxTrade.GUIS;
+import static com.artillexstudios.axtrade.AxTrade.HOOKS;
import static com.artillexstudios.axtrade.AxTrade.LANG;
import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS;
@@ -98,6 +100,14 @@ public class Commands implements OrphanCommand {
}
Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("FFDD╠ AAFFDDReloaded &fguis.ymlAAFFDD!"));
+ if (!HOOKS.reload()) {
+ MESSAGEUTILS.sendFormatted(sender, "reload.failed", Map.of("%file%", "currencies.yml"));
+ return;
+ }
+ Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("FFDD╠ AAFFDDReloaded &fcurrencies.ymlAAFFDD!"));
+
+ LanguageManager.reload();
+
Commands.registerCommand();
new HookManager().updateHooks();
diff --git a/src/main/java/com/artillexstudios/axtrade/lang/LanguageManager.java b/src/main/java/com/artillexstudios/axtrade/lang/LanguageManager.java
new file mode 100644
index 0000000..102b00c
--- /dev/null
+++ b/src/main/java/com/artillexstudios/axtrade/lang/LanguageManager.java
@@ -0,0 +1,78 @@
+package com.artillexstudios.axtrade.lang;
+
+import com.artillexstudios.axapi.config.Config;
+import com.artillexstudios.axapi.utils.StringUtils;
+import com.artillexstudios.axapi.utils.Version;
+import com.artillexstudios.axtrade.AxTrade;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.jetbrains.annotations.NotNull;
+import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
+
+import java.io.File;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.List;
+import java.util.Map;
+
+import static com.artillexstudios.axtrade.AxTrade.CONFIG;
+
+public class LanguageManager {
+ private static Config translations;
+
+ public static void reload() {
+ final String lang = CONFIG.getString("language", "en_US").toLowerCase();
+ final File file = new File(AxTrade.getInstance().getDataFolder(), "lib/translations/" + lang + ".yml");
+ boolean exists = file.exists();
+ translations = new Config(file);
+ if (exists && !translations.getBackingDocument().isEmpty(true)) return;
+
+ final List versions = Version.getServerVersion().versions;
+ final String version = versions.get(versions.size() - 1);
+ final String url = "https://api.github.com/repos/InventivetalentDev/minecraft-assets/contents/assets/minecraft/lang/" + lang + ".json?ref=" + version;
+ Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("FF00╠ AAFFAADownloading &f" + lang + " AAFFAAlanguage files.."));
+
+ final HttpClient client = HttpClient.newHttpClient();
+ final HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .build();
+
+ try {
+ final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
+ final Gson gson = new GsonBuilder().create();
+ final JsonObject object = gson.fromJson(response.body(), JsonObject.class);
+
+ final String base64Content = object.get("content").getAsString();
+
+ var gsonObject = gson.fromJson(new String(Base64Coder.decodeLines(base64Content)), JsonObject.class);
+
+ for (Map.Entry e : gsonObject.entrySet()) {
+ if (e.getKey().startsWith("item.minecraft.")) {
+ final String name = e.getKey().replace("item.minecraft.", "");
+ if (name.contains(".")) continue;
+ translations.set("material." + name, e.getValue().getAsString());
+ }
+ if (e.getKey().startsWith("block.minecraft.")) {
+ final String name = e.getKey().replace("block.minecraft.", "");
+ if (name.contains(".")) continue;
+ translations.set("material." + name, e.getValue().getAsString());
+ }
+ }
+ translations.save();
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ }
+
+ public static String getTranslated(@NotNull Material material) {
+ return translations.getString("material." + material.name().toLowerCase(), material.name().toLowerCase().replace("_", " "));
+ }
+}
diff --git a/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java b/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java
index 1ccb230..44faccd 100644
--- a/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java
+++ b/src/main/java/com/artillexstudios/axtrade/listeners/TradeListeners.java
@@ -44,6 +44,7 @@ public class TradeListeners implements Listener {
final Player player = event.getPlayer();
final Trade trade = Trades.getTrade(player);
if (trade == null) return;
+ if (System.currentTimeMillis() - trade.getPrepTime() < 1_000L) return;
event.setCancelled(true);
trade.abort();
}
diff --git a/src/main/java/com/artillexstudios/axtrade/request/Requests.java b/src/main/java/com/artillexstudios/axtrade/request/Requests.java
index 0690a7c..c74393d 100644
--- a/src/main/java/com/artillexstudios/axtrade/request/Requests.java
+++ b/src/main/java/com/artillexstudios/axtrade/request/Requests.java
@@ -16,24 +16,38 @@ public class Requests {
private static final ArrayList requests = new ArrayList<>();
public static void addRequest(@NotNull Player sender, @NotNull Player receiver) {
+ final Map replacements = Map.of("%player%", receiver.getName());
+
+ var disallowed = CONFIG.getStringList("disallowed-gamemodes");
+ if (disallowed.contains(sender.getGameMode().name()) || disallowed.contains(receiver.getGameMode().name())) {
+ MESSAGEUTILS.sendLang(sender, "request.disallowed-gamemode", replacements);
+ return;
+ }
+
+ var blacklisted = CONFIG.getStringList("blacklisted-worlds");
+ if (blacklisted.contains(sender.getWorld().getName()) || blacklisted.contains(receiver.getWorld().getName())) {
+ MESSAGEUTILS.sendLang(sender, "request.blacklisted-world", replacements);
+ return;
+ }
+
if (sender.isDead() || receiver.isDead()) {
- MESSAGEUTILS.sendLang(sender, "request.not-accepting", Map.of("%player%", receiver.getName()));
+ MESSAGEUTILS.sendLang(sender, "request.not-accepting", replacements);
return;
}
if (sender.equals(receiver)) {
- MESSAGEUTILS.sendLang(sender, "request.cant-trade-self", Map.of("%player%", receiver.getName()));
+ MESSAGEUTILS.sendLang(sender, "request.cant-trade-self", replacements);
return;
}
if (Trades.isTrading(receiver) || Trades.isTrading(sender)) {
- MESSAGEUTILS.sendLang(sender, "request.already-in-trade", Map.of("%player%", receiver.getName()));
+ MESSAGEUTILS.sendLang(sender, "request.already-in-trade", replacements);
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()));
+ MESSAGEUTILS.sendLang(sender, "request.too-far", replacements);
return;
}
@@ -45,13 +59,13 @@ public class Requests {
}
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()));
+ MESSAGEUTILS.sendLang(sender, "request.already-sent", replacements);
return;
}
requests.add(new Request(sender, receiver));
- MESSAGEUTILS.sendLang(sender, "request.sent-sender", Map.of("%player%", receiver.getName()));
+ MESSAGEUTILS.sendLang(sender, "request.sent-sender", replacements);
MESSAGEUTILS.sendLang(receiver, "request.sent-receiver", Map.of("%player%", sender.getName()));
SoundUtils.playSound(sender, "requested");
SoundUtils.playSound(receiver, "requested");
diff --git a/src/main/java/com/artillexstudios/axtrade/trade/Trade.java b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java
index 2fbdeef..3f5cbbc 100644
--- a/src/main/java/com/artillexstudios/axtrade/trade/Trade.java
+++ b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java
@@ -2,11 +2,17 @@ package com.artillexstudios.axtrade.trade;
import com.artillexstudios.axapi.scheduler.Scheduler;
import com.artillexstudios.axtrade.hooks.currency.CurrencyHook;
+import com.artillexstudios.axtrade.utils.HistoryUtils;
+import com.artillexstudios.axtrade.utils.NumberUtils;
import com.artillexstudios.axtrade.utils.SoundUtils;
+import com.artillexstudios.axtrade.utils.Utils;
import org.bukkit.entity.Player;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
+import static com.artillexstudios.axtrade.AxTrade.LANG;
import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS;
public class Trade {
@@ -69,34 +75,71 @@ public class Trade {
}
}
- 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");
+ List player1Currencies = new ArrayList<>();
+ for (Map.Entry entry : player1.getCurrencies().entrySet()) {
+ entry.getKey().takeBalance(player1.getPlayer().getUniqueId(), entry.getValue());
+ entry.getKey().giveBalance(player2.getPlayer().getUniqueId(), entry.getValue());
+ String currencyName = Utils.getFormattedCurrency(entry.getKey());
+ String currencyAm = NumberUtils.formatNumber(entry.getValue());
+ player1Currencies.add(currencyName + ": " + currencyAm);
+ MESSAGEUTILS.sendFormatted(player1.getPlayer(), LANG.getString("summary.give.currency"), Map.of("%amount%", currencyAm, "%currency%", currencyName));
+ MESSAGEUTILS.sendFormatted(player2.getPlayer(), LANG.getString("summary.get.currency"), Map.of("%amount%", currencyAm, "%currency%", currencyName));
+ }
+
+ List player2Currencies = new ArrayList<>();
+ for (Map.Entry entry : player2.getCurrencies().entrySet()) {
+ entry.getKey().takeBalance(player2.getPlayer().getUniqueId(), entry.getValue());
+ entry.getKey().giveBalance(player1.getPlayer().getUniqueId(), entry.getValue());
+ String currencyName = Utils.getFormattedCurrency(entry.getKey());
+ String currencyAm = NumberUtils.formatNumber(entry.getValue());
+ player2Currencies.add(currencyName + ": " + currencyAm);
+ MESSAGEUTILS.sendFormatted(player2.getPlayer(), LANG.getString("summary.give.currency"), Map.of("%amount%", currencyAm, "%currency%", currencyName));
+ MESSAGEUTILS.sendFormatted(player1.getPlayer(), LANG.getString("summary.get.currency"), Map.of("%amount%", currencyAm, "%currency%", currencyName));
+ }
+
+ List player1Items = new ArrayList<>();
player1.getTradeGui().getItems().forEach(itemStack -> {
if (itemStack == null) return;
player2.getPlayer().getInventory().addItem(itemStack);
+ final String itemName = Utils.getFormattedItemName(itemStack);
+ int itemAm = itemStack.getAmount();
+ player1Items.add(itemAm + "x " + itemName);
+ MESSAGEUTILS.sendFormatted(player1.getPlayer(), LANG.getString("summary.give.item"), Map.of("%amount%", "" + itemAm, "%item%", itemName));
+ MESSAGEUTILS.sendFormatted(player2.getPlayer(), LANG.getString("summary.get.item"), Map.of("%amount%", "" + itemAm, "%item%", itemName));
});
+
+ List player2Items = new ArrayList<>();
player2.getTradeGui().getItems().forEach(itemStack -> {
if (itemStack == null) return;
player1.getPlayer().getInventory().addItem(itemStack);
+ final String itemName = Utils.getFormattedItemName(itemStack);
+ int itemAm = itemStack.getAmount();
+ player2Items.add(itemAm + "x " + itemName);
+ MESSAGEUTILS.sendFormatted(player2.getPlayer(), LANG.getString("summary.give.item"), Map.of("%amount%", "" + itemAm, "%item%", itemName));
+ MESSAGEUTILS.sendFormatted(player1.getPlayer(), LANG.getString("summary.get.item"), Map.of("%amount%", "" + itemAm, "%item%", itemName));
});
+ HistoryUtils.writeToHistory(
+ String.format("%s: [Currencies: %s] [Items: %s] | %s: [Currencies: %s] [Items: %s]",
+ player1.getPlayer().getName(), player1Currencies.isEmpty() ? "---" : String.join(", ", player1Currencies), player1Items.isEmpty() ? "---" : String.join(", ", player1Items), player2.getPlayer().getName(), player2Currencies.isEmpty() ? "---" : String.join(", ", player2Currencies), player2Items.isEmpty() ? "---" : String.join(", ", player2Items)));
+
end();
}
public long getPrepTime() {
return prepTime;
}
+
+ public TradePlayer getPlayer1() {
+ return player1;
+ }
+
+ public TradePlayer getPlayer2() {
+ return player2;
+ }
}
diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java
index 8a17152..2037d09 100644
--- a/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java
+++ b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java
@@ -1,14 +1,20 @@
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.BlackListUtils;
import com.artillexstudios.axtrade.utils.NumberUtils;
+import com.artillexstudios.axtrade.utils.ShulkerUtils;
+import com.artillexstudios.axtrade.utils.Utils;
import de.rapha149.signgui.SignGUI;
import de.rapha149.signgui.SignGUIAction;
+import dev.triumphteam.gui.guis.BaseGui;
import dev.triumphteam.gui.guis.Gui;
import dev.triumphteam.gui.guis.GuiItem;
import dev.triumphteam.gui.guis.StorageGui;
+import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -16,6 +22,7 @@ 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;
@@ -41,8 +48,37 @@ public class TradeGui extends GuiFrame {
setGui(gui);
gui.setDefaultTopClickAction(event -> {
- player.cancel();
- Scheduler.get().run(scheduledTask -> trade.update());
+ final ItemStack it = event.getClick() == ClickType.NUMBER_KEY ? event.getView().getBottomInventory().getItem(event.getHotbarButton()) : event.getCurrentItem();
+ if (BlackListUtils.isBlackListed(it)) {
+ event.setCancelled(true);
+ MESSAGEUTILS.sendLang(player.getPlayer(), "trade.blacklisted-item");
+ return;
+ }
+
+ if (event.getCurrentItem() != null && event.getClick().isRightClick() && event.getCurrentItem().getType().toString().endsWith("SHULKER_BOX")) {
+ event.setCancelled(true);
+ player.cancel();
+ trade.update();
+ inSign = true;
+ trade.prepTime = System.currentTimeMillis();
+ event.getWhoClicked().closeInventory();
+
+ final BaseGui shulkerGui = Gui.storage().rows(3).title(StringUtils.format(Utils.getFormattedItemName(event.getCurrentItem()))).disableAllInteractions().create();
+ shulkerGui.getInventory().setContents(ShulkerUtils.getShulkerContents(event.getCurrentItem()));
+ shulkerGui.setCloseGuiAction(shulkerEvent -> Scheduler.get().run(new Consumer<>() {
+ @Override
+ public void accept(ScheduledTask scheduledTask) {
+ if (trade.ended) return;
+ trade.prepTime = System.currentTimeMillis();
+ gui.open(player.getPlayer());
+ inSign = false;
+ trade.update();
+ }
+ }));
+ shulkerGui.open(player.getPlayer());
+ return;
+ }
+
if (!slots.contains(event.getSlot())) {
event.setCancelled(true);
if (event.getCursor() == null) return;
@@ -50,23 +86,43 @@ public class TradeGui extends GuiFrame {
event.getCursor().setAmount(0);
return;
}
+
+ player.cancel();
+ Scheduler.get().run(scheduledTask -> trade.update());
});
gui.setDragAction(event -> {
- if (event.getInventory() == player.getPlayer().getInventory()) return;
+ boolean ownInv = true;
+ for (int s : event.getRawSlots()) {
+ if (s > 53) continue;
+ ownInv = false;
+ break;
+ }
+
+ if (ownInv) return;
+
if (!new HashSet<>(slots).containsAll(event.getInventorySlots())) {
event.setCancelled(true);
return;
}
+
player.cancel();
Scheduler.get().run(scheduledTask -> trade.update());
});
gui.setPlayerInventoryAction(event -> {
+ final ItemStack it = event.getClick() == ClickType.NUMBER_KEY ? event.getView().getBottomInventory().getItem(event.getHotbarButton()) : event.getCurrentItem();
+ if (BlackListUtils.isBlackListed(it)) {
+ event.setCancelled(true);
+ MESSAGEUTILS.sendLang(player.getPlayer(), "trade.blacklisted-item");
+ return;
+ }
+
if (event.isShiftClick() && !slots.contains(event.getView().getTopInventory().firstEmpty())) {
event.setCancelled(true);
return;
}
+
player.cancel();
Scheduler.get().run(scheduledTask -> trade.update());
});
diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java
index 17bea1e..62987c7 100644
--- a/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java
+++ b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java
@@ -59,11 +59,12 @@ public class TradePlayer {
}
public void cancel() {
- if (confirmed == null) return;
- this.confirmed = null;
+ if (confirmed != null) {
+ this.confirmed = null;
+ SoundUtils.playSound(player, "cancel");
+ SoundUtils.playSound(otherPlayer.getPlayer(), "cancel");
+ }
otherPlayer.setConfirmed(null);
- SoundUtils.playSound(player, "cancel");
- SoundUtils.playSound(otherPlayer.getPlayer(), "cancel");
}
public void setConfirmed(Integer confirmed) {
diff --git a/src/main/java/com/artillexstudios/axtrade/utils/BlackListUtils.java b/src/main/java/com/artillexstudios/axtrade/utils/BlackListUtils.java
new file mode 100644
index 0000000..27bbec4
--- /dev/null
+++ b/src/main/java/com/artillexstudios/axtrade/utils/BlackListUtils.java
@@ -0,0 +1,26 @@
+package com.artillexstudios.axtrade.utils;
+
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.Nullable;
+
+import static com.artillexstudios.axtrade.AxTrade.CONFIG;
+
+public class BlackListUtils {
+
+ public static boolean isBlackListed(@Nullable ItemStack it) {
+ if (it == null) return false;
+ for (String s : CONFIG.getSection("blacklisted-items").getRoutesAsStrings(false)) {
+ if (CONFIG.getString("blacklisted-items." + s + ".material") != null) {
+ if (!it.getType().toString().equalsIgnoreCase(CONFIG.getString("blacklisted-items." + s + ".material"))) continue;
+ return true;
+ }
+
+ if (CONFIG.getString("blacklisted-items." + s + ".name-contains") != null) {
+ if (it.getItemMeta() == null) continue;
+ if (!it.getItemMeta().getDisplayName().contains(CONFIG.getString("blacklisted-items." + s + ".name-contains"))) continue;
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/artillexstudios/axtrade/utils/HistoryUtils.java b/src/main/java/com/artillexstudios/axtrade/utils/HistoryUtils.java
new file mode 100644
index 0000000..2307e96
--- /dev/null
+++ b/src/main/java/com/artillexstudios/axtrade/utils/HistoryUtils.java
@@ -0,0 +1,33 @@
+package com.artillexstudios.axtrade.utils;
+
+import com.artillexstudios.axtrade.AxTrade;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.time.ZonedDateTime;
+
+public class HistoryUtils {
+
+ public static void writeToHistory(@NotNull String txt) {
+ final ZonedDateTime zdt = ZonedDateTime.now();
+ final File subdir = new File(AxTrade.getInstance().getDataFolder().getPath() + System.getProperty("file.separator") + "history");
+ subdir.mkdirs();
+ final File file = new File(subdir.getPath() + "/" + zdt.getYear() + "-" + twoDigit(zdt.getMonthValue()) + "-" + twoDigit(zdt.getDayOfMonth()) + ".log");
+
+ try (FileWriter fr = new FileWriter(file.getAbsoluteFile(), true)) {
+ try (PrintWriter pr = new PrintWriter(fr)) {
+ pr.print("[" + twoDigit(zdt.getHour()) + ":" + twoDigit(zdt.getMinute()) + ":" + twoDigit(zdt.getSecond()) + "] ");
+ pr.println(txt);
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ private static @NotNull String twoDigit(int i) {
+ return i > 9 ? Integer.toString(i) : "0" + i;
+ }
+}
diff --git a/src/main/java/com/artillexstudios/axtrade/utils/ShulkerUtils.java b/src/main/java/com/artillexstudios/axtrade/utils/ShulkerUtils.java
new file mode 100644
index 0000000..238036c
--- /dev/null
+++ b/src/main/java/com/artillexstudios/axtrade/utils/ShulkerUtils.java
@@ -0,0 +1,29 @@
+package com.artillexstudios.axtrade.utils;
+
+import com.artillexstudios.axapi.utils.ClassUtils;
+import org.bukkit.block.Barrel;
+import org.bukkit.block.ShulkerBox;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.BlockStateMeta;
+import org.jetbrains.annotations.NotNull;
+
+public class ShulkerUtils {
+
+ @NotNull
+ public static ItemStack[] getShulkerContents(@NotNull ItemStack item) {
+ if (!(item.getItemMeta() instanceof BlockStateMeta)) return new ItemStack[0];
+ final BlockStateMeta meta = (BlockStateMeta) item.getItemMeta();
+ if (meta.getBlockState() instanceof ShulkerBox) {
+ final ShulkerBox shulker = (ShulkerBox) meta.getBlockState();
+ if (ClassUtils.classExists("com.artillexstudios.axshulkers.utils.ShulkerUtils") && com.artillexstudios.axshulkers.utils.ShulkerUtils.getShulkerUUID(item) != null) {
+ return com.artillexstudios.axshulkers.AxShulkers.getDB().getShulker(com.artillexstudios.axshulkers.utils.ShulkerUtils.getShulkerUUID(item));
+ }
+ return shulker.getInventory().getContents();
+ } else if (meta.getBlockState() instanceof Barrel) {
+ final Barrel barrel = (Barrel) meta.getBlockState();
+ return barrel.getInventory().getContents();
+ }
+
+ return new ItemStack[0];
+ }
+}
diff --git a/src/main/java/com/artillexstudios/axtrade/utils/Utils.java b/src/main/java/com/artillexstudios/axtrade/utils/Utils.java
new file mode 100644
index 0000000..de02fab
--- /dev/null
+++ b/src/main/java/com/artillexstudios/axtrade/utils/Utils.java
@@ -0,0 +1,23 @@
+package com.artillexstudios.axtrade.utils;
+
+import com.artillexstudios.axtrade.hooks.currency.CurrencyHook;
+import com.artillexstudios.axtrade.hooks.currency.PlaceholderCurrencyHook;
+import com.artillexstudios.axtrade.lang.LanguageManager;
+import org.bukkit.inventory.ItemStack;
+import org.jetbrains.annotations.NotNull;
+
+import static com.artillexstudios.axtrade.AxTrade.HOOKS;
+
+public class Utils {
+
+ @NotNull
+ public static String getFormattedItemName(@NotNull ItemStack itemStack) {
+ return (itemStack.getItemMeta() == null || itemStack.getItemMeta().getDisplayName().isBlank()) ? LanguageManager.getTranslated(itemStack.getType()) : itemStack.getItemMeta().getDisplayName().replace("§", "&");
+ }
+
+ @NotNull
+ public static String getFormattedCurrency(@NotNull CurrencyHook currencyHook) {
+ final String sc = currencyHook instanceof PlaceholderCurrencyHook ? "placeholder-currencies" : "currencies";
+ return HOOKS.getString(sc + "." + currencyHook.getName() + ".name");
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index afcf009..4dc3288 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,5 +1,9 @@
prefix: "ffdd&lAxTrade &7» "
+# format: language_COUNTRY
+# after changing this, the server will download the default item names
+language: en_US
+
# you must define at least 1
# reloading will add new commands, however a restart is recommended when editing this
command-aliases:
@@ -12,7 +16,7 @@ trade-confirm-seconds: 10
# how fast should trade requests expire?
trade-request-expire-seconds: 60
-# how far can 2 people be to trade?
+# how far apart the 2 players can be from each other?
# set to -1 to disable
trade-max-distance: 10
@@ -28,9 +32,20 @@ number-formatting:
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
+# you can't trade in these gamemodes
disallowed-gamemodes:
- SPECTATOR
+# worlds where trades will not work
+blacklisted-worlds:
+ - "example_world"
+
+# list of items that can't be put in the trade menu
+# note: the name-contains string shouldn't include any color codes
+blacklisted-items:
+ "1":
+ material: "barrier"
+ name-contains: "Banned item's name"
+
# 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
index 1ae7b0f..5de30e1 100644
--- a/src/main/resources/currencies.yml
+++ b/src/main/resources/currencies.yml
@@ -4,7 +4,8 @@
placeholder-currencies:
Example-Currency:
register: false
- # if the currency uses whole numbers then disable this
+ name: "money"
+ # if the currency uses whole numbers, then disable this
# 100.5 - true
# 100 - false
uses-double: true
@@ -18,30 +19,42 @@ placeholder-currencies:
currencies:
Experience:
register: true
+ name: "exp"
Vault:
register: true
+ name: "money"
PlayerPoints:
register: true
+ name: "points"
RoyaleEconomy:
register: true
+ name: "money"
CoinsEngine:
register: true
currency-name: "coins"
+ name: "coins"
UltraEconomy:
register: true
currency-name: "coins"
+ name: "coins"
KingdomsX:
register: true
+ name: "nexus points"
RivalHarvesterHoes:
register: true
+ name: "essence"
SuperMobCoins:
register: true
+ name: "mobcoin"
TheOnly-MobCoins:
register: true
+ name: "mobcoins"
TokenManager:
register: true
+ name: "tokens"
AxQuestBoard:
register: true
+ name: "quest points"
# 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 b9787bf..bb4a61a 100644
--- a/src/main/resources/guis.yml
+++ b/src/main/resources/guis.yml
@@ -84,7 +84,7 @@ partner:
- ""
cancel:
material: "LIME_CONCRETE"
- name: "ffdd&lᴡᴀɪᴛɪɴɢ ғᴏʀ ʏᴏᴜ"
+ name: "ffdd&lᴡᴀɪᴛɪɴɢ"
lore:
- ""
- " &7- &fThe other player has confirmed the trade!"
diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml
index 6633073..1bd832c 100644
--- a/src/main/resources/lang.yml
+++ b/src/main/resources/lang.yml
@@ -2,13 +2,18 @@ player-help:
- " "
- "FFDD&lAxTrade &7»"
- " &7- &f/axtrade &7| FFDDSend trade request"
+ - " &7- &f/axtrade accept &7| FFDDAccept trade request"
+ - " &7- &f/axtrade deny &7| FFDDDeny trade request"
- " "
admin-help:
- " "
- "FFDD&lAxTrade &7»"
- " &7- &f/axtrade &7| FFDDSend trade request"
+ - " &7- &f/axtrade accept &7| FFDDAccept trade request"
+ - " &7- &f/axtrade deny &7| FFDDDeny trade request"
- " &7- &f/axtrade reload &7| FFDDReload plugin"
+ - " &7- &f/axtrade force &7| FFDDForce start a trade"
- " "
reload:
@@ -19,6 +24,16 @@ 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!"
+ blacklisted-item: "CCFFEEThis item is blacklisted!"
+
+# summary after a successful trade
+summary:
+ get:
+ item: "FF00&l+ FF00%amount%x %item%"
+ currency: "FF00&l+ FF00%amount% %currency%"
+ give:
+ item: "FF0000&l- FF0000%amount%x %item%"
+ currency: "FF0000&l- FF0000%amount% %currency%"
currency-editor:
success: "CCFFEESuccessfully changed value!"
@@ -39,6 +54,8 @@ request:
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!"
not-accepting: "CCFFEEThis player is not accepting trades right now!"
+ disallowed-gamemode: "CCFFEEEither you or the other player is in a disallowed gamemode!"
+ blacklisted-world: "CCFFEETrades are disabled in this world!"
# this must be 4 lines
# note: currently the first line must be left empty