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.yml&#AAFFDD!")); + if (!HOOKS.reload()) { + MESSAGEUTILS.sendFormatted(sender, "reload.failed", Map.of("%file%", "currencies.yml")); + return; + } + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╠ &#AAFFDDReloaded &fcurrencies.yml&#AAFFDD!")); + + 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