From 91470b7b7783a52d49e17d28044b585e89677ce4 Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sun, 5 Apr 2026 19:30:50 +0100 Subject: [PATCH 1/9] Begin 21.1.1 upgrade --- .github/workflows/gradle.yml | 4 ++-- build.gradle | 7 ++++--- .../mrfloris/antiduping/AntiDupingListener.java | 15 --------------- .../mrfloris/antiduping/AntiDupingMechanics.java | 2 -- src/main/resources/plugin.yml | 6 +++--- 5 files changed, 9 insertions(+), 25 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 0060a83..0c444ec 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,10 +14,10 @@ jobs: steps: - uses: actions/checkout@v6.0.2 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v5.2.0 with: - java-version: "21" + java-version: "25" distribution: "microsoft" - name: Setup Gradle diff --git a/build.gradle b/build.gradle index c229623..3d9f6b3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,14 @@ plugins { id 'java' + id("io.github.greymagic27.McTestServer") version "1.0.0" } group = 'com.mrfloris' -version = '1.1.0' +version = '1.2.0' java { toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(25) } } @@ -17,7 +18,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:26.1.1.build.20-alpha") implementation("org.jspecify:jspecify:1.0.0") } diff --git a/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java b/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java index 2cb2512..621276a 100644 --- a/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java +++ b/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java @@ -45,25 +45,19 @@ public AntiDupingListener(AntiDupingMechanics plugin) { public void reloadFromConfig() { var c = plugin.getConfig(); - debugEnabled = c.getBoolean("debug.enabled", false); debugToConsole = c.getBoolean("debug.log_to_console", true); msgPrefix = color(c.getString("messages.prefix", "&8[&6AntiDuping&8] &r")); - perWorld.clear(); - ConfigurationSection worlds = c.getConfigurationSection("worlds"); ConfigurationSection def = worlds != null ? worlds.getConfigurationSection("__default__") : null; defaultSettings = WorldSettings.fromConfig(def, new WorldSettings()); // baseline defaults if missing - if (worlds != null) { for (String key : worlds.getKeys(false)) { if (key == null) continue; if (key.equalsIgnoreCase("__default__")) continue; - ConfigurationSection worldSec = worlds.getConfigurationSection(key); if (worldSec == null) continue; - // merge: start from defaultSettings, then override WorldSettings ws = defaultSettings.copy(); ws.applyOverrides(worldSec); @@ -147,10 +141,8 @@ public void onInventoryOpen(@NonNull InventoryOpenEvent event) { public void onInteractEntity(@NonNull PlayerInteractEntityEvent event) { Player player = event.getPlayer(); if (bypass(player)) return; - WorldSettings ws = settingsForWorld(player.getWorld().getName()); Entity clicked = event.getRightClicked(); - if (ws.donkeys.enabled && ws.donkeys.blockAttachChest) { if (clicked instanceof ChestedHorse chestedHorse) { ItemStack inHand = player.getInventory().getItem(event.getHand()); @@ -182,13 +174,10 @@ public void onInteractEntity(@NonNull PlayerInteractEntityEvent event) { public void onInventoryClick(@NonNull InventoryClickEvent event) { if (!(event.getWhoClicked() instanceof Player player)) return; if (bypass(player)) return; - WorldSettings ws = settingsForWorld(player.getWorld().getName()); if (!ws.bundles.enabled || !ws.bundles.blockInsertItems) return; - ItemStack current = event.getCurrentItem(); // clicked slot item ItemStack cursor = event.getCursor(); // cursor item - // Putting a cursor item onto a bundle (insert) if (isBundle(current) && cursor.getType() != Material.AIR) { event.setCancelled(true); @@ -196,7 +185,6 @@ public void onInventoryClick(@NonNull InventoryClickEvent event) { debug("Blocked bundle insert via click (cursor -> bundle): player=" + player.getName() + ", world=" + player.getWorld().getName() + ", cursor=" + cursor.getType()); return; } - // Risky swap case: bundle on cursor + clicking a non-air item (could insert depending on client behavior) if (isBundle(cursor) && current != null && current.getType() != Material.AIR) { event.setCancelled(true); @@ -209,13 +197,10 @@ public void onInventoryClick(@NonNull InventoryClickEvent event) { public void onInventoryDrag(@NonNull InventoryDragEvent event) { if (!(event.getWhoClicked() instanceof Player player)) return; if (bypass(player)) return; - WorldSettings ws = settingsForWorld(player.getWorld().getName()); if (!ws.bundles.enabled || !ws.bundles.blockInsertItems) return; - ItemStack cursor = event.getOldCursor(); if (cursor.getType() == Material.AIR) return; - for (int rawSlot : event.getRawSlots()) { ItemStack inSlot = event.getView().getItem(rawSlot); if (isBundle(inSlot)) { diff --git a/src/main/java/com/mrfloris/antiduping/AntiDupingMechanics.java b/src/main/java/com/mrfloris/antiduping/AntiDupingMechanics.java index 5dc0562..da09b00 100644 --- a/src/main/java/com/mrfloris/antiduping/AntiDupingMechanics.java +++ b/src/main/java/com/mrfloris/antiduping/AntiDupingMechanics.java @@ -9,10 +9,8 @@ public final class AntiDupingMechanics extends JavaPlugin { @Override public void onEnable() { saveDefaultConfig(); - listener = new AntiDupingListener(this); getServer().getPluginManager().registerEvents(listener, this); - var cmd = getCommand("antiduping"); if (cmd != null) { var command = new AntiDupingCommand(this, listener); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 03c8149..c7f91f1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: AntiDupingMechanics version: ${version} -main: com.example.antiduping.AntiDupingMechanics -api-version: "1.21.11" +main: com.mrfloris.antiduping.AntiDupingMechanics +api-version: "26.1.1" author: Floris commands: @@ -15,4 +15,4 @@ permissions: default: op antiduping.bypass: description: Bypass all AntiDupingMechanics blocks - default: op + default: op \ No newline at end of file From cef55575dafad76e57c269ef6462950dc7403ecb Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sun, 5 Apr 2026 19:31:08 +0100 Subject: [PATCH 2/9] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9f6fb0c..788310c 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,13 @@ worlds: ## Build -Requires Java 21+. +Requires Java 25+. ```bash ./gradlew build ``` -Jar will be in `build/libs/AntiDupingMechanics-1.1.0.jar`. +Jar will be in `build/libs/AntiDupingMechanics-1.2.0.jar`. ## Notes From fcc53a2f58a46700c098644e987ef404fb62ba3f Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sat, 11 Apr 2026 16:44:51 +0100 Subject: [PATCH 3/9] Update for 26.1.2 --- .github/workflows/gradle.yml | 2 +- build.gradle | 2 +- src/main/resources/plugin.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 0c444ec..05dc59d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,7 +21,7 @@ jobs: distribution: "microsoft" - name: Setup Gradle - uses: gradle/actions/setup-gradle@v6 + uses: gradle/actions/setup-gradle@v6.1.0 with: gradle-version: current - name: Build with Gradle Wrapper diff --git a/build.gradle b/build.gradle index 3d9f6b3..7f1a035 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:26.1.1.build.20-alpha") + compileOnly("io.papermc.paper:paper-api:26.1.2.build.5-alpha") implementation("org.jspecify:jspecify:1.0.0") } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c7f91f1..1668f94 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: AntiDupingMechanics version: ${version} main: com.mrfloris.antiduping.AntiDupingMechanics -api-version: "26.1.1" +api-version: "26.1.2" author: Floris commands: From acd137533547c1614ae46da6a5de33a770b77f92 Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sat, 11 Apr 2026 17:00:21 +0100 Subject: [PATCH 4/9] Split into classes and add ColorUtil --- README.md | 4 +- .../antiduping/AntiDupingCommand.java | 25 ++-- .../antiduping/AntiDupingListener.java | 123 ++---------------- .../settings/entity/BundleSettings.java | 18 +++ .../settings/entity/ChestBoatSettings.java | 18 +++ .../settings/entity/DonkeySettings.java | 20 +++ .../settings/world/WorldSettings.java | 54 ++++++++ .../mrfloris/antiduping/util/ColorUtil.java | 12 ++ 8 files changed, 147 insertions(+), 127 deletions(-) create mode 100644 src/main/java/com/mrfloris/antiduping/settings/entity/BundleSettings.java create mode 100644 src/main/java/com/mrfloris/antiduping/settings/entity/ChestBoatSettings.java create mode 100644 src/main/java/com/mrfloris/antiduping/settings/entity/DonkeySettings.java create mode 100644 src/main/java/com/mrfloris/antiduping/settings/world/WorldSettings.java create mode 100644 src/main/java/com/mrfloris/antiduping/util/ColorUtil.java diff --git a/README.md b/README.md index 788310c..52e7e45 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,8 @@ Jar will be in `build/libs/AntiDupingMechanics-1.2.0.jar`. ## Notes -Bundle behavior in Minecraft can vary across versions/clients. This plugin blocks the common insert methods: +Bundle behaviour in Minecraft can vary across versions/clients. This plugin blocks the common insert methods: - click/drag items onto a bundle in inventories - certain right-click interactions involving item entities (where applicable) -If you find a specific interaction path that still inserts into bundles on your server, note the exact steps and we can tighten the checks. +If you find a specific interaction path that still inserts into bundles on your server, note the exact steps, and we can tighten the checks. diff --git a/src/main/java/com/mrfloris/antiduping/AntiDupingCommand.java b/src/main/java/com/mrfloris/antiduping/AntiDupingCommand.java index 223eb85..cb7d2a9 100644 --- a/src/main/java/com/mrfloris/antiduping/AntiDupingCommand.java +++ b/src/main/java/com/mrfloris/antiduping/AntiDupingCommand.java @@ -1,8 +1,8 @@ package com.mrfloris.antiduping; +import com.mrfloris.antiduping.util.ColorUtil; import java.util.ArrayList; import java.util.List; -import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -19,37 +19,32 @@ public AntiDupingCommand(AntiDupingMechanics plugin, AntiDupingListener listener this.listener = listener; } - private String color(String s) { - return ChatColor.translateAlternateColorCodes('&', s); - } - @Override public boolean onCommand(@NonNull CommandSender sender, @NonNull Command command, @NonNull String label, @NonNull String @NonNull [] args) { if (!sender.hasPermission("antiduping.admin")) { - sender.sendMessage(color("&cNo permission.")); + sender.sendMessage(ColorUtil.color("&cNo permission.")); return true; } if (args.length == 0) { - sender.sendMessage(color("&7Usage: &f/antiduping ")); + sender.sendMessage(ColorUtil.color("&7Usage: &f/antiduping ")); return true; } switch (args[0].toLowerCase()) { case "reload" -> { plugin.reloadAll(); - sender.sendMessage(color("&aAntiDupingMechanics reloaded.")); + sender.sendMessage(ColorUtil.color("&aAntiDupingMechanics reloaded.")); } case "status" -> { - sender.sendMessage(color("&6AntiDupingMechanics status:")); - sender.sendMessage(color("&7- Debug: &f" + listener.statusDebug())); - sender.sendMessage(color("&7- Worlds loaded: &f" + listener.statusWorldsLoaded())); - sender.sendMessage(color("&7- Bypass perm: &fantiduping.bypass")); - sender.sendMessage(color("&7Use /antiduping reload after config changes.")); + sender.sendMessage(ColorUtil.color("&6AntiDupingMechanics status:")); + sender.sendMessage(ColorUtil.color("&7- Debug: &f" + listener.statusDebug())); + sender.sendMessage(ColorUtil.color("&7- Worlds loaded: &f" + listener.statusWorldsLoaded())); + sender.sendMessage(ColorUtil.color("&7- Bypass perm: &fantiduping.bypass")); + sender.sendMessage(ColorUtil.color("&7Use /antiduping reload after config changes.")); } - default -> sender.sendMessage(color("&7Usage: &f/antiduping ")); + default -> sender.sendMessage(ColorUtil.color("&7Usage: &f/antiduping ")); } - return true; } diff --git a/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java b/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java index 621276a..d86a63f 100644 --- a/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java +++ b/src/main/java/com/mrfloris/antiduping/AntiDupingListener.java @@ -1,9 +1,12 @@ package com.mrfloris.antiduping; +import com.mrfloris.antiduping.settings.world.WorldSettings; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.ChestBoat; @@ -31,7 +34,7 @@ public final class AntiDupingListener implements Listener { private final Map perWorld = new HashMap<>(); private boolean debugEnabled; private boolean debugToConsole; - private String msgPrefix; + private TextComponent msgPrefix; private WorldSettings defaultSettings; public AntiDupingListener(AntiDupingMechanics plugin) { @@ -39,10 +42,6 @@ public AntiDupingListener(AntiDupingMechanics plugin) { reloadFromConfig(); } - private static @NonNull String colorStatic(String s) { - return ChatColor.translateAlternateColorCodes('&', s == null ? "" : s); - } - public void reloadFromConfig() { var c = plugin.getConfig(); debugEnabled = c.getBoolean("debug.enabled", false); @@ -59,7 +58,7 @@ public void reloadFromConfig() { ConfigurationSection worldSec = worlds.getConfigurationSection(key); if (worldSec == null) continue; // merge: start from defaultSettings, then override - WorldSettings ws = defaultSettings.copy(); + WorldSettings ws = Objects.requireNonNull(defaultSettings).copy(); ws.applyOverrides(worldSec); perWorld.put(key.toLowerCase(), ws); } @@ -79,19 +78,20 @@ private WorldSettings settingsForWorld(String worldName) { return perWorld.getOrDefault(worldName.toLowerCase(), defaultSettings); } - private @NonNull String color(String s) { - return ChatColor.translateAlternateColorCodes('&', s == null ? "" : s); + private @NonNull TextComponent color(String s) { + return LegacyComponentSerializer.legacyAmpersand().deserialize(s); } - private void msg(Player p, String message) { - if (message != null && !message.isBlank()) { - p.sendMessage(msgPrefix + message); + private void msg(Player p, TextComponent message) { + if (message != null) { + p.sendMessage(msgPrefix.append(message)); } } private void debug(String line) { if (!debugEnabled) return; if (debugToConsole) { + //noinspection UnstableApiUsage Bukkit.getLogger().info("[AntiDupingMechanics] " + line); } } @@ -185,7 +185,7 @@ public void onInventoryClick(@NonNull InventoryClickEvent event) { debug("Blocked bundle insert via click (cursor -> bundle): player=" + player.getName() + ", world=" + player.getWorld().getName() + ", cursor=" + cursor.getType()); return; } - // Risky swap case: bundle on cursor + clicking a non-air item (could insert depending on client behavior) + // Risky swap case: bundle on cursor + clicking a non-air item (could insert depending on client behaviour) if (isBundle(cursor) && current != null && current.getType() != Material.AIR) { event.setCancelled(true); msg(player, ws.bundles.message); @@ -211,101 +211,4 @@ public void onInventoryDrag(@NonNull InventoryDragEvent event) { } } } - - // --- Settings types --- - static final class WorldSettings { - ChestBoatSettings chestBoats = new ChestBoatSettings(); - DonkeySettings donkeys = new DonkeySettings(); - BundleSettings bundles = new BundleSettings(); - - static @NonNull WorldSettings fromConfig(ConfigurationSection sec, WorldSettings fallback) { - WorldSettings ws = (fallback == null ? new WorldSettings() : fallback.copy()); - if (sec == null) return ws; - ws.applyOverrides(sec); - return ws; - } - - private static @NonNull String colorLocal(String s) { - return ChatColor.translateAlternateColorCodes('&', s == null ? "" : s); - } - - void applyOverrides(@NonNull ConfigurationSection sec) { - // chest_boats - ConfigurationSection cb = sec.getConfigurationSection("chest_boats"); - if (cb != null) { - if (cb.contains("enabled")) chestBoats.enabled = cb.getBoolean("enabled"); - if (cb.contains("block_open_inventory")) chestBoats.blockOpenInventory = cb.getBoolean("block_open_inventory"); - if (cb.contains("message")) chestBoats.message = colorLocal(cb.getString("message")); - } - - // donkeys - ConfigurationSection dk = sec.getConfigurationSection("donkeys"); - if (dk != null) { - if (dk.contains("enabled")) donkeys.enabled = dk.getBoolean("enabled"); - if (dk.contains("block_open_inventory")) donkeys.blockOpenInventory = dk.getBoolean("block_open_inventory"); - if (dk.contains("block_attach_chest")) donkeys.blockAttachChest = dk.getBoolean("block_attach_chest"); - if (dk.contains("message")) donkeys.message = colorLocal(dk.getString("message")); - } - - // bundles - ConfigurationSection bd = sec.getConfigurationSection("bundles"); - if (bd != null) { - if (bd.contains("enabled")) bundles.enabled = bd.getBoolean("enabled"); - if (bd.contains("block_insert_items")) bundles.blockInsertItems = bd.getBoolean("block_insert_items"); - if (bd.contains("message")) bundles.message = colorLocal(bd.getString("message")); - } - } - - @NonNull WorldSettings copy() { - WorldSettings ws = new WorldSettings(); - ws.chestBoats = chestBoats.copy(); - ws.donkeys = donkeys.copy(); - ws.bundles = bundles.copy(); - return ws; - } - } - - static final class ChestBoatSettings { - boolean enabled = true; - boolean blockOpenInventory = true; - String message = colorStatic("&cYou can't use chest storage in chest boats on this server."); - - @NonNull ChestBoatSettings copy() { - ChestBoatSettings s = new ChestBoatSettings(); - s.enabled = enabled; - s.blockOpenInventory = blockOpenInventory; - s.message = message; - return s; - } - } - - static final class DonkeySettings { - boolean enabled = true; - boolean blockOpenInventory = true; - boolean blockAttachChest = true; - String message = colorStatic("&cYou can't use chest storage on pack animals on this server."); - - @NonNull DonkeySettings copy() { - DonkeySettings s = new DonkeySettings(); - s.enabled = enabled; - s.blockOpenInventory = blockOpenInventory; - s.blockAttachChest = blockAttachChest; - s.message = message; - return s; - } - } - - static final class BundleSettings { - boolean enabled = true; - boolean blockInsertItems = true; - String message = colorStatic("&cYou can't put items into bundles on this server."); - - @NonNull BundleSettings copy() { - BundleSettings s = new BundleSettings(); - s.enabled = enabled; - s.blockInsertItems = blockInsertItems; - s.message = message; - return s; - } - } } diff --git a/src/main/java/com/mrfloris/antiduping/settings/entity/BundleSettings.java b/src/main/java/com/mrfloris/antiduping/settings/entity/BundleSettings.java new file mode 100644 index 0000000..14da9c3 --- /dev/null +++ b/src/main/java/com/mrfloris/antiduping/settings/entity/BundleSettings.java @@ -0,0 +1,18 @@ +package com.mrfloris.antiduping.settings.entity; + +import com.mrfloris.antiduping.util.ColorUtil; +import net.kyori.adventure.text.TextComponent; + +public class BundleSettings { + public boolean enabled = true; + public boolean blockInsertItems = true; + public TextComponent message = ColorUtil.color("&cYou can't put items into bundles on this server."); + + public BundleSettings copy() { + BundleSettings s = new BundleSettings(); + s.enabled = enabled; + s.blockInsertItems = blockInsertItems; + s.message = message; + return s; + } +} diff --git a/src/main/java/com/mrfloris/antiduping/settings/entity/ChestBoatSettings.java b/src/main/java/com/mrfloris/antiduping/settings/entity/ChestBoatSettings.java new file mode 100644 index 0000000..f25d78c --- /dev/null +++ b/src/main/java/com/mrfloris/antiduping/settings/entity/ChestBoatSettings.java @@ -0,0 +1,18 @@ +package com.mrfloris.antiduping.settings.entity; + +import com.mrfloris.antiduping.util.ColorUtil; +import net.kyori.adventure.text.TextComponent; + +public class ChestBoatSettings { + public boolean enabled = true; + public boolean blockOpenInventory = true; + public TextComponent message = ColorUtil.color("&cYou can't use chest storage in chest boats on this server."); + + public ChestBoatSettings copy() { + ChestBoatSettings s = new ChestBoatSettings(); + s.enabled = enabled; + s.blockOpenInventory = blockOpenInventory; + s.message = message; + return s; + } +} diff --git a/src/main/java/com/mrfloris/antiduping/settings/entity/DonkeySettings.java b/src/main/java/com/mrfloris/antiduping/settings/entity/DonkeySettings.java new file mode 100644 index 0000000..31dbda6 --- /dev/null +++ b/src/main/java/com/mrfloris/antiduping/settings/entity/DonkeySettings.java @@ -0,0 +1,20 @@ +package com.mrfloris.antiduping.settings.entity; + +import com.mrfloris.antiduping.util.ColorUtil; +import net.kyori.adventure.text.TextComponent; + +public class DonkeySettings { + public boolean enabled = true; + public boolean blockOpenInventory = true; + public boolean blockAttachChest = true; + public TextComponent message = ColorUtil.color("&cYou can't use chest storage on pack animals on this server."); + + public DonkeySettings copy() { + DonkeySettings s = new DonkeySettings(); + s.enabled = enabled; + s.blockOpenInventory = blockOpenInventory; + s.blockAttachChest = blockAttachChest; + s.message = message; + return s; + } +} diff --git a/src/main/java/com/mrfloris/antiduping/settings/world/WorldSettings.java b/src/main/java/com/mrfloris/antiduping/settings/world/WorldSettings.java new file mode 100644 index 0000000..9c2d0bd --- /dev/null +++ b/src/main/java/com/mrfloris/antiduping/settings/world/WorldSettings.java @@ -0,0 +1,54 @@ +package com.mrfloris.antiduping.settings.world; + +import com.mrfloris.antiduping.util.ColorUtil; +import com.mrfloris.antiduping.settings.entity.BundleSettings; +import com.mrfloris.antiduping.settings.entity.ChestBoatSettings; +import com.mrfloris.antiduping.settings.entity.DonkeySettings; +import org.bukkit.configuration.ConfigurationSection; +import org.jspecify.annotations.NonNull; + +public class WorldSettings { + public ChestBoatSettings chestBoats = new ChestBoatSettings(); + public DonkeySettings donkeys = new DonkeySettings(); + public BundleSettings bundles = new BundleSettings(); + + public static WorldSettings fromConfig(ConfigurationSection sec, WorldSettings fallback) { + WorldSettings ws = (fallback == null ? new WorldSettings() : fallback.copy()); + if (sec == null) return ws; + ws.applyOverrides(sec); + return ws; + } + + public void applyOverrides(@NonNull ConfigurationSection sec) { + // chest_boats + ConfigurationSection cb = sec.getConfigurationSection("chest_boats"); + if (cb != null) { + if (cb.contains("enabled")) chestBoats.enabled = cb.getBoolean("enabled"); + if (cb.contains("block_open_inventory")) chestBoats.blockOpenInventory = cb.getBoolean("block_open_inventory"); + if (cb.contains("message")) chestBoats.message = ColorUtil.color(cb.getString("message")); + } + // donkeys + ConfigurationSection dk = sec.getConfigurationSection("donkeys"); + if (dk != null) { + if (dk.contains("enabled")) donkeys.enabled = dk.getBoolean("enabled"); + if (dk.contains("block_open_inventory")) donkeys.blockOpenInventory = dk.getBoolean("block_open_inventory"); + if (dk.contains("block_attach_chest")) donkeys.blockAttachChest = dk.getBoolean("block_attach_chest"); + if (dk.contains("message")) donkeys.message = ColorUtil.color(dk.getString("message")); + } + // bundles + ConfigurationSection bd = sec.getConfigurationSection("bundles"); + if (bd != null) { + if (bd.contains("enabled")) bundles.enabled = bd.getBoolean("enabled"); + if (bd.contains("block_insert_items")) bundles.blockInsertItems = bd.getBoolean("block_insert_items"); + if (bd.contains("message")) bundles.message = ColorUtil.color(bd.getString("message")); + } + } + + public WorldSettings copy() { + WorldSettings ws = new WorldSettings(); + ws.chestBoats = chestBoats.copy(); + ws.donkeys = donkeys.copy(); + ws.bundles = bundles.copy(); + return ws; + } +} diff --git a/src/main/java/com/mrfloris/antiduping/util/ColorUtil.java b/src/main/java/com/mrfloris/antiduping/util/ColorUtil.java new file mode 100644 index 0000000..22d2083 --- /dev/null +++ b/src/main/java/com/mrfloris/antiduping/util/ColorUtil.java @@ -0,0 +1,12 @@ +package com.mrfloris.antiduping.util; + +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jspecify.annotations.NonNull; + +public class ColorUtil { + + public static @NonNull TextComponent color(String s) { + return LegacyComponentSerializer.legacyAmpersand().deserialize(s); + } +} From 05a6ff0cd397e4777ba64fbe98fa0073e2eb23f5 Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sat, 11 Apr 2026 17:03:08 +0100 Subject: [PATCH 5/9] Update version variable in plugin.yml --- src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1668f94..76c8e08 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: AntiDupingMechanics -version: ${version} +version: @version@ main: com.mrfloris.antiduping.AntiDupingMechanics api-version: "26.1.2" author: Floris From 49e8831673a3f58cd575e8d5cef37c7f6bfd5f52 Mon Sep 17 00:00:00 2001 From: Greymagic27 Date: Sat, 11 Apr 2026 17:04:59 +0100 Subject: [PATCH 6/9] Update version variable in plugin.yml --- build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build.gradle b/build.gradle index 7f1a035..86b5215 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,5 @@ +import org.apache.tools.ant.filters.ReplaceTokens + plugins { id 'java' id("io.github.greymagic27.McTestServer") version "1.0.0" @@ -22,6 +24,13 @@ dependencies { implementation("org.jspecify:jspecify:1.0.0") } +processResources { + from(sourceSets.main.resources.srcDirs) { + filter ReplaceTokens, tokens: [version: version] + duplicatesStrategy = DuplicatesStrategy.WARN + } +} + tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs += ['-Xlint:deprecation'] From f71a184a4c6c773609e4cb126629209338bc26c9 Mon Sep 17 00:00:00 2001 From: Greymagic27 <46166848+Greymagic27@users.noreply.github.com> Date: Sat, 11 Apr 2026 17:30:07 +0100 Subject: [PATCH 7/9] Rename plugin to '1MB-AntiDupingMechanics' --- src/main/resources/plugin.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 76c8e08..9e4116b 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,4 +1,4 @@ -name: AntiDupingMechanics +name: 1MB-AntiDupingMechanics version: @version@ main: com.mrfloris.antiduping.AntiDupingMechanics api-version: "26.1.2" @@ -15,4 +15,4 @@ permissions: default: op antiduping.bypass: description: Bypass all AntiDupingMechanics blocks - default: op \ No newline at end of file + default: op From 54e59c1557a29548532dace5b8226be8d9aae50d Mon Sep 17 00:00:00 2001 From: Greymagic27 <46166848+Greymagic27@users.noreply.github.com> Date: Sun, 12 Apr 2026 10:32:01 +0100 Subject: [PATCH 8/9] Update build.gradle --- build.gradle | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 86b5215..ad6ed40 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.mrfloris' -version = '1.2.0' +version = '26.1.2' java { toolchain { @@ -20,7 +20,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:26.1.2.build.5-alpha") + compileOnly("io.papermc.paper:paper-api:${version}.build.5-alpha") implementation("org.jspecify:jspecify:1.0.0") } @@ -35,3 +35,7 @@ tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs += ['-Xlint:deprecation'] } + +tasks.jar { + archiveVersion.set("${version}") +} From a526524799249d84eb60c06bed944052d0fe8f3e Mon Sep 17 00:00:00 2001 From: Greymagic27 <46166848+Greymagic27@users.noreply.github.com> Date: Mon, 4 May 2026 13:17:50 +0100 Subject: [PATCH 9/9] Update paper version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ad6ed40..2eca015 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ repositories { } dependencies { - compileOnly("io.papermc.paper:paper-api:${version}.build.5-alpha") + compileOnly("io.papermc.paper:paper-api:${version}.build.+") implementation("org.jspecify:jspecify:1.0.0") }