commit 5b34367a5677c425249de62abbfc2064f5ea70df Author: BenceX100 <52270269+BenceX100@users.noreply.github.com> Date: Thu Apr 4 13:01:21 2024 +0200 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4788b4b --- /dev/null +++ b/.gitignore @@ -0,0 +1,113 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +target/ + +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next + +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# Common working directory +run/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2814d9f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Artillex-Studios + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1550ddf --- /dev/null +++ b/pom.xml @@ -0,0 +1,132 @@ + + + 4.0.0 + + com.artillexstudios + AxTrade + 1.0.0 + jar + + AxTrade + + + 1.8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.3.0 + + + package + + shade + + + false + + + com.artillexstudios.axapi + com.artillexstudios.axtrade.libs.axapi + + + org.bstats + com.artillexstudios.axtrade.libs.bstats + + + dev.triumphteam.gui + com.artillexstudios.axtrade.libs.gui + + + net.kyori.adventure + com.artillexstudios.axtrade.libs.kyori + + + revxrsal.commands + com.artillexstudios.axtrade.libs.lamp + + + + + + + + + + src/main/resources + true + + + + + + + Artillex-Studios + https://repo.artillex-studios.com/releases/ + + + spigotmc-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + sonatype + https://oss.sonatype.org/content/groups/public/ + + + jitpack.io + https://jitpack.io + + + placeholderapi + https://repo.extendedclip.com/content/repositories/placeholderapi/ + + + + + + com.artillexstudios.axapi + axapi + 1.4.109 + compile + + + org.spigotmc + spigot-api + 1.18-R0.1-SNAPSHOT + provided + + + dev.triumphteam + triumph-gui + 3.1.7 + compile + + + me.clip + placeholderapi + 2.11.3 + provided + + + org.bstats + bstats-bukkit + 3.0.2 + compile + + + diff --git a/src/main/java/com/artillexstudios/axtrade/AxTrade.java b/src/main/java/com/artillexstudios/axtrade/AxTrade.java new file mode 100644 index 0000000..c27b2e8 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/AxTrade.java @@ -0,0 +1,60 @@ +package com.artillexstudios.axtrade; + +import com.artillexstudios.axapi.AxPlugin; +import com.artillexstudios.axapi.config.Config; +import com.artillexstudios.axapi.data.ThreadedQueue; +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.dvs.versioning.BasicVersioning; +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.dumper.DumperSettings; +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.general.GeneralSettings; +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.loader.LoaderSettings; +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.settings.updater.UpdaterSettings; +import com.artillexstudios.axapi.utils.MessageUtils; +import com.artillexstudios.axapi.utils.StringUtils; +import com.artillexstudios.axtrade.commands.Commands; +import com.artillexstudios.axtrade.trade.TradeTicker; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import org.bstats.bukkit.Metrics; +import org.bukkit.Bukkit; + +import java.io.File; + +public final class AxTrade extends AxPlugin { + public static Config CONFIG; + public static Config LANG; + public static Config GUIS; + public static MessageUtils MESSAGEUTILS; + private static AxPlugin instance; + private static ThreadedQueue threadedQueue; + public static BukkitAudiences BUKKITAUDIENCES; + + public static ThreadedQueue getThreadedQueue() { + return threadedQueue; + } + + public static AxPlugin getInstance() { + return instance; + } + + public void enable() { + instance = this; + + int pluginId = 21500; + new Metrics(this, pluginId); + + 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()); + + MESSAGEUTILS = new MessageUtils(LANG.getBackingDocument(), "prefix", CONFIG.getBackingDocument()); + + threadedQueue = new ThreadedQueue<>("AxRewards-Datastore-thread"); + + BUKKITAUDIENCES = BukkitAudiences.create(this); + + new TradeTicker().start(); + + Commands.registerCommand(); + + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�ffdd[AxTrade] Loaded plugin!")); + } +} \ No newline at end of file diff --git a/src/main/java/com/artillexstudios/axtrade/commands/Commands.java b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java new file mode 100644 index 0000000..5a46e14 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/commands/Commands.java @@ -0,0 +1,80 @@ +package com.artillexstudios.axtrade.commands; + +import com.artillexstudios.axapi.utils.StringUtils; +import com.artillexstudios.axtrade.AxTrade; +import com.artillexstudios.axtrade.trade.Trades; +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.Subcommand; +import revxrsal.commands.bukkit.BukkitCommandHandler; +import revxrsal.commands.bukkit.annotation.CommandPermission; +import revxrsal.commands.orphan.OrphanCommand; +import revxrsal.commands.orphan.Orphans; + +import java.util.Map; + +import static com.artillexstudios.axtrade.AxTrade.CONFIG; +import static com.artillexstudios.axtrade.AxTrade.GUIS; +import static com.artillexstudios.axtrade.AxTrade.LANG; +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 { + for (String m : LANG.getStringList("admin-help")) { + sender.sendMessage(StringUtils.formatToString(m)); + } + } + } + + @Subcommand("reload") + @CommandPermission(value = "axtrade.admin", defaultAccess = PermissionDefault.OP) + public void reload(@NotNull CommandSender sender) { + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD[AxTrade] &#AAFFDDReloading configuration...")); + if (!CONFIG.reload()) { + MESSAGEUTILS.sendFormatted(sender, "reload.failed", Map.of("%file%", "config.yml")); + return; + } + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╠ &#AAFFDDReloaded &fconfig.yml&#AAFFDD!")); + + if (!LANG.reload()) { + MESSAGEUTILS.sendFormatted(sender, "reload.failed", Map.of("%file%", "lang.yml")); + return; + } + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╠ &#AAFFDDReloaded &flang.yml&#AAFFDD!")); + + if (!GUIS.reload()) { + MESSAGEUTILS.sendFormatted(sender, "reload.failed", Map.of("%file%", "guis.yml")); + return; + } + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╠ &#AAFFDDReloaded &fguis.yml&#AAFFDD!")); + + Commands.registerCommand(); + + Bukkit.getConsoleSender().sendMessage(StringUtils.formatToString("�FFDD╚ &#AAFFDDSuccessful reload!")); + MESSAGEUTILS.sendLang(sender, "reload.success"); + } + + @Subcommand("force") + @CommandPermission(value = "axtrade.admin", defaultAccess = PermissionDefault.OP) + public void force(@NotNull Player sender, Player other) { + Trades.addTrade(sender, other); + } + + public static void registerCommand() { + final BukkitCommandHandler handler = BukkitCommandHandler.create(AxTrade.getInstance()); + handler.unregisterAllCommands(); + handler.register(Orphans.path(CONFIG.getStringList("command-aliases").toArray(String[]::new)).handler(new Commands())); + handler.registerBrigadier(); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java b/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java new file mode 100644 index 0000000..3812445 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/GuiFrame.java @@ -0,0 +1,97 @@ +package com.artillexstudios.axtrade.trade; + +import com.artillexstudios.axapi.config.Config; +import com.artillexstudios.axapi.utils.NumberUtils; +import com.artillexstudios.axtrade.utils.ItemBuilderUtil; +import dev.triumphteam.gui.components.GuiAction; +import dev.triumphteam.gui.guis.BaseGui; +import dev.triumphteam.gui.guis.GuiItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class GuiFrame { + private static final ItemStack air = new ItemStack(Material.AIR); + protected final Config file; + protected BaseGui gui; + protected Player player; + + public GuiFrame(Config file, Player player) { + this.file = file; + this.player = player; + } + + public void setGui(BaseGui gui) { + this.gui = gui; + for (String str : file.getBackingDocument().getRoutesAsStrings(false)) createItem(str); + } + + @NotNull + public Config getFile() { + return file; + } + + protected ItemStack buildItem(@NotNull String key) { + if (file.getSection(key) == null) return air; + return ItemBuilderUtil.newBuilder(file.getSection(key), player).get(); + } + + protected ItemStack buildItem(@NotNull String key, Map replacements) { + if (file.getSection(key) == null) return air; + return ItemBuilderUtil.newBuilder(file.getSection(key), replacements, player).get(); + } + + protected void createItem(@NotNull String route) { + createItem(route, event -> event.setCancelled(true), Map.of()); + } + + protected void createItem(@NotNull String route, @Nullable GuiAction action) { + createItem(route, action, Map.of()); + } + + protected void createItem(@NotNull String route, @Nullable GuiAction action, Map replacements) { + createItem(route + ".slot", route, action, replacements); + } + + protected void createItem(@NotNull String slotRoute, String itemRoute, @Nullable GuiAction action, Map replacements) { + createItem(slotRoute, itemRoute, action, replacements, 1); + } + + protected void createItem(@NotNull String slotRoute, String itemRoute, @Nullable GuiAction action, Map replacements, int amount) { + if (file.getString(itemRoute + ".type") == null && file.getString(itemRoute + ".material") == null) return; + final ItemStack it = buildItem(itemRoute, replacements); + it.setAmount(amount); + final GuiItem guiItem = new GuiItem(it, action); + gui.setItem(getSlots(slotRoute), guiItem); + } + + protected List getSlots(String r) { + final List slots = new ArrayList<>(); + + if (!file.getStringList(r).isEmpty()) { + for (Object route : file.getStringList(r)) { + if (NumberUtils.isInt(("" + route))) { + slots.add(Integer.parseInt(("" + route))); + } else { + String[] split = ("" + route).split("-"); + int min = Integer.parseInt(split[0]); + int max = Integer.parseInt(split[1]); + for (int i = min; i <= max; i++) { + slots.add(i); + } + } + } + } else { + slots.add(file.getInt(r)); + } + + return slots; + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/Trade.java b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java new file mode 100644 index 0000000..cdd4d4e --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/Trade.java @@ -0,0 +1,44 @@ +package com.artillexstudios.axtrade.trade; + +import com.artillexstudios.axapi.scheduler.Scheduler; +import org.bukkit.entity.Player; + +import java.util.Map; + +import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; + +public class Trade { + protected final TradePlayer player1; + protected final TradePlayer player2; + private boolean ended = false; + + public Trade(Player p1, Player p2) { + this.player1 = new TradePlayer(this, p1); + this.player2 = new TradePlayer(this, p2); + player1.setOtherPlayer(player2); + player2.setOtherPlayer(player1); + } + + public void update() { + player1.getTradeGui().update(); + player2.getTradeGui().update(); + } + + 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())); + end(); + } + + public void end() { + if (ended) return; + ended = true; + Scheduler.get().run(scheduledTask -> Trades.removeTrade(Trade.this)); + player1.getPlayer().closeInventory(); + player1.getPlayer().updateInventory(); + player2.getPlayer().closeInventory(); + player2.getPlayer().updateInventory(); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java new file mode 100644 index 0000000..4b423b0 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradeGui.java @@ -0,0 +1,73 @@ +package com.artillexstudios.axtrade.trade; + +import com.artillexstudios.axapi.scheduler.ScheduledTask; +import com.artillexstudios.axapi.scheduler.Scheduler; +import com.artillexstudios.axapi.utils.StringUtils; +import dev.triumphteam.gui.guis.Gui; +import dev.triumphteam.gui.guis.StorageGui; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static com.artillexstudios.axtrade.AxTrade.GUIS; + +public class TradeGui extends GuiFrame { + private final Trade trade; + private final TradePlayer player; + private final boolean shouldMirror; + protected final StorageGui gui; + protected final List slots = getSlots("own-slots"); + + 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()))) + .create(); + setGui(gui); + + gui.setDefaultTopClickAction(event -> { + if (!slots.contains(event.getSlot())) { + event.setCancelled(true); + if (event.getCursor() == null) return; + player.getPlayer().getInventory().addItem(event.getCursor().clone()); + event.getCursor().setAmount(0); + return; + } + Scheduler.get().run(scheduledTask -> trade.update()); + }); + + update(); + gui.open(player.getPlayer()); + } + + public void update() { + if (player.hasConfirmed()) { + super.createItem("own.confirm-item.slot", "own.confirm-item.cancel", event -> { + event.setCancelled(true); + player.cancel(); + }, Map.of(), player.getConfirmed()); + } else { + super.createItem("own.confirm-item.slot", "own.confirm-item.accept", event -> { + event.setCancelled(true); + player.confirm(); + }, Map.of()); + } + + if (player.getOtherPlayer().hasConfirmed()) { + super.createItem("partner.confirm-item.slot", "partner.confirm-item.cancel", event -> { + event.setCancelled(true); + }, Map.of(), player.getOtherPlayer().getConfirmed()); + } else { + super.createItem("partner.confirm-item.slot", "partner.confirm-item.accept", event -> { + event.setCancelled(true); + }, Map.of()); + } + gui.update(); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java new file mode 100644 index 0000000..906286e --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradePlayer.java @@ -0,0 +1,67 @@ +package com.artillexstudios.axtrade.trade; + +import org.bukkit.entity.Player; + +import static com.artillexstudios.axtrade.AxTrade.CONFIG; + +public class TradePlayer { + private final Player player; + private TradePlayer otherPlayer; + private TradeGui tradeGui; + private final Trade trade; + + // confirmed + // null > not confirmed + // number > decrease every sec + private Integer confirmed = null; + + public TradePlayer(Trade trade, Player player) { + this.player = player; + this.trade = trade; + } + + public void setOtherPlayer(TradePlayer otherPlayer) { + this.otherPlayer = otherPlayer; + this.tradeGui = new TradeGui(trade, this); + } + + public Player getPlayer() { + return player; + } + + public TradePlayer getOtherPlayer() { + return otherPlayer; + } + + public TradeGui getTradeGui() { + return tradeGui; + } + + public Integer getConfirmed() { + return confirmed; + } + + public boolean hasConfirmed() { + return confirmed != null; + } + + public void confirm() { + this.confirmed = CONFIG.getInt("trade-confirm-seconds", 10); + trade.update(); + } + + public void cancel() { + this.confirmed = null; + otherPlayer.setConfirmed(null); + trade.update(); + } + + public void setConfirmed(Integer confirmed) { + this.confirmed = confirmed; + } + + public void tick() { + confirmed -= 1; + trade.update(); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java b/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java new file mode 100644 index 0000000..141309f --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/TradeTicker.java @@ -0,0 +1,30 @@ +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() { + Scheduler.get().runTimer(scheduledTask -> { + for (Trade trade : Trades.getTrades()) { + 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(); + continue; + } + + trade.player1.tick(); + trade.player2.tick(); + + } + }, 20, 20); + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/trade/Trades.java b/src/main/java/com/artillexstudios/axtrade/trade/Trades.java new file mode 100644 index 0000000..7a00a18 --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/trade/Trades.java @@ -0,0 +1,27 @@ +package com.artillexstudios.axtrade.trade; + +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Map; + +import static com.artillexstudios.axtrade.AxTrade.MESSAGEUTILS; + +public class Trades { + private static final ArrayList trades = new ArrayList<>(); + + 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())); + } + + public static void removeTrade(Trade trade) { + trades.remove(trade); + } + + public static ArrayList getTrades() { + return trades; + } +} diff --git a/src/main/java/com/artillexstudios/axtrade/utils/ItemBuilderUtil.java b/src/main/java/com/artillexstudios/axtrade/utils/ItemBuilderUtil.java new file mode 100644 index 0000000..5a6cd1d --- /dev/null +++ b/src/main/java/com/artillexstudios/axtrade/utils/ItemBuilderUtil.java @@ -0,0 +1,47 @@ +package com.artillexstudios.axtrade.utils; + +import com.artillexstudios.axapi.libs.boostedyaml.boostedyaml.block.implementation.Section; +import com.artillexstudios.axapi.utils.ClassUtils; +import com.artillexstudios.axapi.utils.ItemBuilder; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class ItemBuilderUtil { + + @NotNull + public static ItemBuilder newBuilder(@NotNull Section section, @Nullable Player player) { + return newBuilder(section, Map.of(), player); + } + + @NotNull + public static ItemBuilder newBuilder(@NotNull Section section, Map replacements, @Nullable Player player) { + final ItemBuilder builder = new ItemBuilder(section); + + section.getOptionalString("name").ifPresent((name) -> { + if (ClassUtils.classExists("me.clip.placeholderapi.PlaceholderAPI")) { + name = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(player, name); + } + builder.setName(name, replacements); + }); + + section.getOptionalStringList("lore").ifPresent((lore) -> { + if (ClassUtils.classExists("me.clip.placeholderapi.PlaceholderAPI")) { + lore = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(player, lore); + } + builder.setLore(lore, replacements); + }); + + return builder; + } + + @NotNull + @Contract("_ -> new") + public static ItemBuilder newBuilder(@NotNull ItemStack itemStack) { + return new ItemBuilder(itemStack); + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..3d8962c --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,13 @@ +prefix: "�ffdd&lAxTrade &7» " + +# you must define at least 1 +# reloading will add new commands, however a restart is recommended when editing this +command-aliases: + - "axtrade" + - "trade" + +# the time after clicking the trade confirm button before the trade finishes +trade-confirm-seconds: 10 + +# do not change this +version: 1 \ No newline at end of file diff --git a/src/main/resources/guis.yml b/src/main/resources/guis.yml new file mode 100644 index 0000000..7307e02 --- /dev/null +++ b/src/main/resources/guis.yml @@ -0,0 +1,118 @@ +# ----- SETTINGS ----- + +title: "&0Trading with: %player%" +# a gui can have 1-6 rows +rows: 6 + +# ----- SLOTS ----- + +# the slots where the items can be placed +# make sure to not put decorative items in the these slots (or change this too) +# the own-slots and partner-slots must have an equal amount of slots +own-slots: + - 9-12 + - 18-21 + - 27-30 + - 36-39 + - 45-48 + +partner-slots: + - 14-17 + - 23-26 + - 32-35 + - 41-44 + - 50-53 + +# ----- ITEMS ----- + +# items on your side +own: + confirm-item: + slot: 0 + accept: + material: "RED_CONCRETE" + name: "�ffdd&lᴀᴄᴄᴇᴘᴛ ᴛʀᴀᴅᴇ" + lore: + - "" + - " &7- &fAre you happy with the trade?" + - "" + - "�ffdd&l> �ffddClick &8- �ffddConfirm Trade" + cancel: + material: "LIME_CONCRETE" + name: "�ffdd&lᴄᴀɴᴄᴇʟ ᴄᴏɴғɪʀᴍᴀᴛɪᴏɴ" + lore: + - "" + - " &7- &fDo you want to change something?" + - "" + - "�ffdd&l> �ffddClick &8- �ffddCancel Confirmation" + # you can define as many currencies as you want, also make sure to copy them to the 'partner' section! + currency1: + slot: 2 + # you need Vault installed for this + currency: "vault:money" + material: "GOLD_NUGGET" + name: "�ffdd&lᴍᴏɴᴇʏ" + lore: + - "" + - " &7- &fAmount:" + - "" + - "�ffdd&l> �ffddClick &8- �ffddChange Amount" + currency2: + slot: 3 + # you need Vault installed for this + currency: "vanilla:experience" + material: "EXPERIENCE_BOTTLE" + name: "�ffdd&lᴇxᴘᴇʀɪᴇɴᴄᴇ" + lore: + - "" + - " &7- &fAmount:" + - "" + - "�ffdd&l> �ffddClick &8- �ffddChange Amount" + +# items on your trade partner's side +partner: + confirm-item: + slot: 8 + accept: + material: "RED_CONCRETE" + name: "�ffdd&lᴡᴀɪᴛɪɴɢ ғᴏʀ ᴏᴛʜᴇʀ ᴘʟᴀʏᴇʀ" + lore: + - "" + - " &7- &fThe other player has not yet confirmed the trade!" + - "" + cancel: + material: "LIME_CONCRETE" + name: "�ffdd&lᴡᴀɪᴛɪɴɢ ғᴏʀ ʏᴏᴜ" + lore: + - "" + - " &7- &fThe other player has confirmed the trade!" + currency1: + slot: 6 + # you need Vault installed for this + currency: "vault:money" + material: "GOLD_NUGGET" + name: "�ffdd&lᴍᴏɴᴇʏ" + lore: + - "" + - " &7- &fAmount:" + - "" + - "�ffdd&l> �ffddClick &8- �ffddChange Amount" + currency2: + slot: 5 + # you need Vault installed for this + currency: "vanilla:experience" + material: "EXPERIENCE_BOTTLE" + name: "�ffdd&lᴇxᴘᴇʀɪᴇɴᴄᴇ" + lore: + - "" + - " &7- &fAmount:" + - "" + - "�ffdd&l> �ffddClick &8- �ffddChange Amount" + +decoration-example: + slot: [4, 13, 22, 31, 40, 49] + material: "LIGHT_BLUE_STAINED_GLASS_PANE" + name: " " + +# do not change this +version: 1 \ No newline at end of file diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml new file mode 100644 index 0000000..c60268d --- /dev/null +++ b/src/main/resources/lang.yml @@ -0,0 +1,23 @@ +player-help: + - " " + - "�FFDD&lAxTrade &7»" + - " &7- &f/axtrade &7| �FFDDSend trade request" + - " " + +admin-help: + - " " + - "�FFDD&lAxTrade &7»" + - " &7- &f/axtrade &7| �FFDDSend trade request" + - " &7- &f/axtrade reload &7| �FFDDReload plugin" + - " " + +reload: + success: "!FF33Plugin successfully reloaded!" + failed: "&#FF3333Failed to reload the plugin! Something is wrong in the &f%file%&#FF3333 file, look in the console or use a yaml validator to fix the errors!" + +trade-started: "&#CCFFEEYou have started a trade with �FFDD%player%&#CCFFEE!" +trade-aborted: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas aborted!" +trade-completed: "&#CCFFEEYour trade with �FFDD%player% &#CCFFEEwas completed!" + +# do not change this +version: 1 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..ea19724 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,8 @@ +name: AxTrade +version: '${project.version}' +main: com.artillexstudios.axtrade.AxTrade +api-version: '1.18' +folia-supported: true + +softdepend: + - PlaceholderAPI \ No newline at end of file