From 5261018dcc4f4f4f5a6df211c64ccf6d0fe6d950 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 8 May 2020 02:05:49 +0100 Subject: [PATCH 001/190] Update repositories --- pom.xml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 5407f7007..1c43bd4f4 100644 --- a/pom.xml +++ b/pom.xml @@ -94,18 +94,15 @@ papermc https://papermc.io/repo/repository/maven-public/ - - vault-repo - http://nexus.hc.to/content/repositories/pub_releases - sk89q-repo - http://maven.sk89q.com/repo/ - - - onarandombox - http://repo.onarandombox.com/nexus/content/groups/public + https://maven.sk89q.com/repo/ + + + + + CodeMC https://repo.codemc.org/repository/maven-public @@ -114,7 +111,7 @@ mvdw-software https://repo.mvdw-software.com/content/groups/public/ - + jitpack.io https://jitpack.io From b4410ede3f7f040f2fabeedc54c7b40682624df1 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 11 May 2020 23:04:30 +0100 Subject: [PATCH 002/190] Fix admin chunk regen command --- .editorconfig | 6 ++++++ .../ultimateskyblock/command/AdminCommand.java | 2 +- .../command/admin/ChunkCommand.java | 14 ++++++++------ .../ultimateskyblock/world/ChunkRegenerator.java | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..210d3ca85 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*.java] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=4 diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index 278195e6f..fe8790c25 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -87,6 +87,6 @@ protected void doExecute(CommandSender sender, PlayerInfo playerInfo) { add(new SetMaintenanceCommand(plugin)); add(new NBTCommand()); add(new ProtectAllCommand(plugin)); - add(new ChunkCommand()); + add(new ChunkCommand(plugin)); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java index 0212522f3..d44ec6ec4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java @@ -6,6 +6,7 @@ import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -13,16 +14,17 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class ChunkCommand extends CompositeCommand { - public ChunkCommand() { + private final uSkyBlock plugin; + + public ChunkCommand(uSkyBlock plugin) { super("chunk", "usb.admin.chunk", marktr("various chunk commands")); + this.plugin = plugin; + add(new RequireChunkCommand("regen", marktr("regenerate current chunk")) { @Override void doChunkCommand(Player player, Chunk chunk) { - if (chunk.getWorld().regenerateChunk(chunk.getX(), chunk.getZ())) { - player.sendMessage(tr("successfully regenerated chunk at {0},{1}", chunk.getX(), chunk.getZ())); - } else { - player.sendMessage(tr("\u00a74FAILED!\u00a7e could not regenerate chunk at {0},{1}", chunk.getX(), chunk.getZ())); - } + plugin.getWorldManager().getChunkRegenerator(chunk.getWorld()).regenerateChunk(chunk); + player.sendMessage(tr("successfully regenerated chunk at {0},{1}", chunk.getX(), chunk.getZ())); } }); add(new RequireChunkCommand("unload", marktr("unload current chunk")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java index 52b4f2f59..36056a38a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java @@ -68,7 +68,7 @@ public void regenerateChunks(@NotNull List chunkList, @Nullable Runnable * Regenerates the given {@link Chunk}, removing all it's entities except players and setting the default biome. * @param chunk Chunk to regenerate. */ - private void regenerateChunk(@NotNull Chunk chunk) { + public void regenerateChunk(@NotNull Chunk chunk) { Validate.notNull(chunk, "Chunk cannot be null"); spawnTeleportPlayers(chunk); From e6c3e70394696de43ee9dab5cadd9156e8de9d92 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 12 May 2020 22:41:35 +0100 Subject: [PATCH 003/190] Update deprecated calls in LocationUtil#findNearestSpawnLocation --- po-utils/pom.xml | 1 - pom.xml | 6 ++++ uSkyBlock-API/pom.xml | 4 +-- uSkyBlock-Core/pom.xml | 3 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 36 ++++--------------- .../ultimateskyblock/util/LocationUtil.java | 36 +++++++------------ 6 files changed, 28 insertions(+), 58 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 067655151..baf580243 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -27,7 +27,6 @@ org.jetbrains annotations - 17.0.0 diff --git a/pom.xml b/pom.xml index 1c43bd4f4..be69c0c91 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,7 @@ Ultimate SkyBlock + 19.0.0 ${project.version} 1.23-SNAPSHOT 1.2 @@ -208,6 +209,11 @@ DeluxeChatPlaceholderAPI ${deluxechat.version} + + org.jetbrains + annotations + ${jbannotations.version} + \ No newline at end of file diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index c38608171..6a92f060e 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -30,7 +30,7 @@ org.jetbrains annotations - 17.0.0 + 19.0.0 @@ -79,7 +79,7 @@ org.bukkit bukkit - 1.15-R0.1-SNAPSHOT + 1.15.2-R0.1-SNAPSHOT true compile diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 2f8b5a304..9d6c0b9ed 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -230,7 +230,7 @@ org.bukkit bukkit - 1.15-R0.1-SNAPSHOT + 1.15.2-R0.1-SNAPSHOT true compile @@ -436,7 +436,6 @@ org.jetbrains annotations - 17.0.0 commons-lang diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index b0bafb2c2..08012c327 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -101,6 +101,7 @@ import java.io.File; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Random; import java.util.UUID; import java.util.logging.Level; @@ -624,27 +625,6 @@ private void setBiome(Location loc, Biome biome) { new SetBiomeTask(this, loc, biome, null).runTask(this); } - public void changePlayerBiome(Player player, final String bName, final Callback callback) { - callback.setState(false); - if (bName.equalsIgnoreCase("ocean") || player.hasPermission("usb.biome." + bName)) { - PlayerInfo playerInfo = getPlayerInfo(player); - final IslandInfo islandInfo = islandLogic.getIslandInfo(playerInfo); - if (islandInfo.hasPerm(player, "canChangeBiome")) { - player.sendMessage(tr("\u00a77The pixies are busy changing the biome of your island to \u00a79{0}\u00a77, be patient.", bName)); - new SetBiomeTask(this, playerInfo.getIslandLocation(), getBiome(bName), new Runnable() { - @Override - public void run() { - islandInfo.setBiome(bName); - callback.setState(true); - callback.run(); - } - }).runTask(this); - return; - } - } - callback.run(); - } - public void createIsland(final Player player, String cSchem) { PlayerInfo pi = getPlayerInfo(player); if (pi.isIslandGenerating()) { @@ -685,17 +665,15 @@ private void generateIsland(final Player player, final PlayerInfo pi, final Loca islandLogic.clearIsland(next, createTask); } - public Location getChestSpawnLoc(final Location loc) { - Location chestLocation = LocationUtil.findChestLocation(loc); - return LocationUtil.findNearestSpawnLocation(chestLocation != null ? chestLocation : loc); - } - public IslandInfo setNewPlayerIsland(final PlayerInfo playerInfo, final Location loc) { playerInfo.startNewIsland(loc); - Location chestSpawnLocation = getChestSpawnLoc(loc); - if (chestSpawnLocation != null) { - playerInfo.setHomeLocation(chestSpawnLocation); + Location chestLocation = LocationUtil.findChestLocation(loc); + Optional chestSpawnLocation = LocationUtil.findNearestSpawnLocation( + chestLocation != null ? chestLocation : loc); + + if (chestSpawnLocation.isPresent()) { + playerInfo.setHomeLocation(chestSpawnLocation.get()); } else { log(Level.SEVERE, "Could not find a safe chest within 15 blocks of the island spawn. Bad schematic!"); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java index e5c60821c..8463f0687 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock.util; import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; @@ -8,13 +9,15 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.material.MaterialData; -import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.block.data.BlockData; +import org.bukkit.material.Directional; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import java.util.Locale; +import java.util.Optional; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -44,7 +47,7 @@ public static String asString(Location loc) { return null; } String s = ""; - if (loc.getWorld() != null && loc.getWorld().getName() != null) { + if (loc.getWorld() != null) { s += loc.getWorld().getName() + ":"; } s += String.format(Locale.ENGLISH, "%.2f,%.2f,%.2f", loc.getX(), loc.getY(), loc.getZ()); @@ -155,24 +158,9 @@ public static Location findChestLocation(final Location loc) { return null; } - /** - * Finds the nearest block to loc that is a chest. - * - * @param loc The location to scan for a chest. - * @return The location of the chest - */ - public static void findChestLocationAsync(final JavaPlugin plugin, final Location loc, final Callback callback) { - ChunkUtil.Chunks snapshots; - if (loc.getBlockX() % 16 == 0 && loc.getBlockZ() % 16 == 0) { - // chunk aligned - snapshots = ChunkUtil.getSnapshots4x4(loc); - } else { - snapshots = ChunkUtil.getSnapshots(loc, 1); - } - new ScanChest(loc, callback, snapshots).runTaskAsynchronously(plugin); - } + public static Optional findNearestSpawnLocation(@NotNull Location loc) { + Validate.notNull(loc.getWorld(), "World in the given Location cannot be null."); - public static Location findNearestSpawnLocation(Location loc) { loadChunkAt(loc); World world = loc.getWorld(); int px = loc.getBlockX(); @@ -182,9 +170,9 @@ public static Location findNearestSpawnLocation(Location loc) { if (chestBlock.getType() == Material.CHEST) { BlockFace primaryDirection = null; // Start by checking in front of the chest. - MaterialData data = chestBlock.getState().getData(); - if (data instanceof org.bukkit.material.Chest) { - primaryDirection = ((org.bukkit.material.Chest) data).getFacing(); + BlockData data = chestBlock.getBlockData(); + if (data instanceof Directional) { + primaryDirection = ((Directional) data).getFacing(); } if (primaryDirection == BlockFace.NORTH) { // Neg Z @@ -200,7 +188,7 @@ public static Location findNearestSpawnLocation(Location loc) { px += 1; // start one block in the east dir } } - return findNearestSafeLocation(new Location(loc.getWorld(), px, py, pz), loc); + return Optional.ofNullable(findNearestSafeLocation(new Location(loc.getWorld(), px, py, pz), loc)); } public static Location findNearestSafeLocation(Location loc, Location lookAt) { From dbee9aac929fec9dd6e23fed7167036b5666e299 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 12 May 2020 22:48:20 +0100 Subject: [PATCH 004/190] Implement new OfflinePlayer methods to NullPlayer --- .../ultimateskyblock/uuid/NullPlayer.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java index fb18bed42..f31e43674 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java @@ -1,8 +1,12 @@ package us.talabrek.ultimateskyblock.uuid; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.Statistic; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.UUID; @@ -67,6 +71,96 @@ public Location getBedSpawnLocation() { return null; } + @Override + public void incrementStatistic(@NotNull Statistic statistic) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic) throws IllegalArgumentException { + + } + + @Override + public void incrementStatistic(@NotNull Statistic statistic, int amount) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic, int amount) throws IllegalArgumentException { + + } + + @Override + public void setStatistic(@NotNull Statistic statistic, int newValue) throws IllegalArgumentException { + + } + + @Override + public int getStatistic(@NotNull Statistic statistic) throws IllegalArgumentException { + return 0; + } + + @Override + public void incrementStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException { + + } + + @Override + public int getStatistic(@NotNull Statistic statistic, @NotNull Material material) throws IllegalArgumentException { + return 0; + } + + @Override + public void incrementStatistic(@NotNull Statistic statistic, @NotNull Material material, int amount) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic, @NotNull Material material, int amount) throws IllegalArgumentException { + + } + + @Override + public void setStatistic(@NotNull Statistic statistic, @NotNull Material material, int newValue) throws IllegalArgumentException { + + } + + @Override + public void incrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException { + + } + + @Override + public int getStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType) throws IllegalArgumentException { + return 0; + } + + @Override + public void incrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int amount) throws IllegalArgumentException { + + } + + @Override + public void decrementStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int amount) { + + } + + @Override + public void setStatistic(@NotNull Statistic statistic, @NotNull EntityType entityType, int newValue) { + + } + @Override public Map serialize() { return null; From 79ca3f0aa3b87a531f7ec922f04ab9300a67e41f Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 13 May 2020 22:16:52 +0100 Subject: [PATCH 005/190] Update bStats, Multiverse, AnvilGUI, PaperLib --- pom.xml | 6 ++++ uSkyBlock-Core/pom.xml | 13 ++++---- .../ultimateskyblock/MetricsManager.java | 32 +++++++++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 10 ++---- 4 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java diff --git a/pom.xml b/pom.xml index be69c0c91..8a058c765 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ 19.0.0 ${project.version} 1.23-SNAPSHOT + 1.0.3 1.2 1.6 1.7 @@ -214,6 +215,11 @@ annotations ${jbannotations.version} + + io.papermc + paperlib + ${paperlib.version} + \ No newline at end of file diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 9d6c0b9ed..47afacdc6 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -357,22 +357,21 @@ io.papermc paperlib - 1.0.2 compile com.github.WesJD AnvilGUI - 4b7a469d7e + master-SNAPSHOT compile com.onarandombox.multiversecore Multiverse-Core - 2.5 - compile + 4.1.0 + provided true @@ -384,8 +383,8 @@ com.onarandombox.multiverseinventories Multiverse-Inventories - 2.5.0-SNAPSHOT - compile + 3.0.0 + provided true @@ -398,7 +397,7 @@ org.bstats bstats-bukkit - 1.4 + 1.7 compile diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java new file mode 100644 index 000000000..507d12280 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java @@ -0,0 +1,32 @@ +package us.talabrek.ultimateskyblock; + +import org.bstats.bukkit.Metrics; + +import java.util.logging.Level; + +public class MetricsManager { + // Pushing to two accounts at the moment to track both legacy and current installations. + private static final int BSTATS_MUSPAH_ID = 7525; + private static final int BSTATS_RLF_ID = 2801; + + private final uSkyBlock plugin; + + public MetricsManager(uSkyBlock plugin) { + this.plugin = plugin; + + try { + setupMetrics(BSTATS_MUSPAH_ID); + setupMetrics(BSTATS_RLF_ID); + } catch (Exception ex) { + plugin.getLogger().log(Level.WARNING, "Failed to setup bStats metrics:", ex); + } + } + + private void setupMetrics(int pluginId) { + Metrics bStats = new Metrics(plugin, pluginId); + bStats.addCustomChart(new Metrics.SimplePie("language", + () -> plugin.getConfig().getString("language", "en"))); + bStats.addCustomChart(new Metrics.SimplePie("radius_and_distance", + () -> String.format("(%d,%d)", Settings.island_radius, Settings.island_distance))); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 08012c327..d7e13b402 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -139,6 +139,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private LimitLogic limitLogic; /* MANAGERS */ + private MetricsManager metricsManager; private WorldManager worldManager; private IslandGenerator islandGenerator; @@ -164,7 +165,6 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private volatile boolean maintenanceMode = false; private BlockLimitLogic blockLimitLogic; - private Metrics metrics; public uSkyBlock() { } @@ -235,14 +235,8 @@ public void run() { log(Level.INFO, getVersionInfo(false)); } }, getConfig().getLong("init.initDelay", 50L)); - try { - metrics = new Metrics(this); - metrics.addCustomChart(new Metrics.SimplePie("language", () -> getConfig().getString("language", "en"))); - metrics.addCustomChart(new Metrics.SimplePie("radius_and_distance", () -> String.format("(%d,%d)", Settings.island_radius, Settings.island_distance))); - } catch (Exception e) { - log(Level.WARNING, "Failed to submit metrics data", e); - } + metricsManager = new MetricsManager(this); PaperLib.suggestPaper(this); } From 28c74fa72c2d4abc33fb1cc2742e129dc251132a Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 15 May 2020 19:41:45 +0100 Subject: [PATCH 006/190] Measure PlayerDB type usage in preperation of new storage system --- .../java/us/talabrek/ultimateskyblock/MetricsManager.java | 4 ++++ .../ultimateskyblock/storage/yml/IslandInfoYml.java | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/storage/yml/IslandInfoYml.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java index 507d12280..36cd0b6f4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java @@ -28,5 +28,9 @@ private void setupMetrics(int pluginId) { () -> plugin.getConfig().getString("language", "en"))); bStats.addCustomChart(new Metrics.SimplePie("radius_and_distance", () -> String.format("(%d,%d)", Settings.island_radius, Settings.island_distance))); + + // Temp. chart to measure storage usage for (legacy) uuid.PlayerDB. + bStats.addCustomChart(new Metrics.SimplePie("playerdb_type", + () -> plugin.getConfig().getString("options.advanced.playerdb.storage", "yml"))); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/storage/yml/IslandInfoYml.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/storage/yml/IslandInfoYml.java deleted file mode 100644 index 7a9c5176f..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/storage/yml/IslandInfoYml.java +++ /dev/null @@ -1,7 +0,0 @@ -package us.talabrek.ultimateskyblock.storage.yml; - -/** - * Created by R4zorax on 18-12-2016. - */ -public class IslandInfoYml { -} From b411def92e88aee780ef355f775c468e93097ad0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 20 May 2020 23:50:30 +0100 Subject: [PATCH 007/190] Move Vault economy to new plugin hook system (draft!) --- .../challenge/ChallengeLogic.java | 23 ++++--- .../handler/VaultHandler.java | 27 -------- .../hook/HookFailedException.java | 7 +++ .../ultimateskyblock/hook/HookManager.java | 62 +++++++++++++++++++ .../ultimateskyblock/hook/PluginHook.java | 54 ++++++++++++++++ .../hook/economy/EconomyHook.java | 43 +++++++++++++ .../hook/economy/VaultEconomy.java | 58 +++++++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 22 ++++--- 8 files changed, 254 insertions(+), 42 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookFailedException.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/PluginHook.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 7ed34661c..c3c56c7df 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -20,6 +20,7 @@ import us.talabrek.ultimateskyblock.api.event.MemberJoinedEvent; import us.talabrek.ultimateskyblock.block.BlockCollection; import us.talabrek.ultimateskyblock.handler.VaultHandler; +import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.Perk; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -350,12 +351,6 @@ private boolean giveReward(Player player, Challenge challenge) { } else { reward = challenge.getRepeatReward(); } - float rewBonus = 1; - if (defaults.enableEconomyPlugin && VaultHandler.hasEcon()) { - Perk perk = plugin.getPerkLogic().getPerk(player); - rewBonus += perk.getRewBonus(); - VaultHandler.depositPlayer(player, reward.getCurrencyReward() * rewBonus); - } player.giveExp(reward.getXpReward()); boolean wasBroadcast = false; if (defaults.broadcastCompletion && isFirstCompletion) { @@ -364,8 +359,20 @@ private boolean giveReward(Player player, Challenge challenge) { } player.sendMessage(tr("\u00a7eItem reward(s): \u00a7f{0}", reward.getRewardText())); player.sendMessage(tr("\u00a7eExp reward: \u00a7f{0,number,#.#}", reward.getXpReward())); - if (defaults.enableEconomyPlugin && VaultHandler.hasEcon()) { - player.sendMessage(tr("\u00a7eCurrency reward: \u00a7f{0,number,###.##} {1} \u00a7a ({2,number,##.##})%", reward.getCurrencyReward() * rewBonus, VaultHandler.getEcon().currencyNamePlural(), (rewBonus - 1.0) * 100.0)); + if (defaults.enableEconomyPlugin) { + float rewBonus = 1; + Perk perk = plugin.getPerkLogic().getPerk(player); + rewBonus += perk.getRewBonus(); + float currencyReward = reward.getCurrencyReward() * rewBonus; + double percentage = (rewBonus - 1.0) * 100.0; + + plugin.getHookManager().getHook("Economy").ifPresent((hook) -> { + EconomyHook economyHook = (EconomyHook) hook; + economyHook.depositPlayer(player, currencyReward); + + player.sendMessage(tr("\u00a7eCurrency reward: \u00a7f{0,number,###.##} {1} \u00a7a ({2,number,##.##})%", + currencyReward, economyHook.getCurrenyName(), percentage)); + }); } if (reward.getPermissionReward() != null) { List perms = Arrays.asList(reward.getPermissionReward().trim().split(" ")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java index 9cce3a6b2..ee171a893 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java @@ -1,7 +1,6 @@ package us.talabrek.ultimateskyblock.handler; import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.permission.Permission; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -10,11 +9,9 @@ public enum VaultHandler {; private static Permission perms; - private static Economy econ; static { perms = null; - econ = null; } public static void addPermission(final Player player, final String perk) { @@ -37,32 +34,8 @@ public static boolean setupPermissions() { return perms != null; } - public static boolean setupEconomy() { - if (uSkyBlock.getInstance().getServer().getPluginManager().getPlugin("Vault") == null) { - return false; - } - final RegisteredServiceProvider rsp = (RegisteredServiceProvider) uSkyBlock.getInstance().getServer().getServicesManager().getRegistration((Class) Economy.class); - if (rsp == null) { - return false; - } - econ = rsp.getProvider(); - return econ != null; - } - public static String getItemName(ItemStack stack) { return ItemStackUtil.getItemName(stack); } - public static boolean hasEcon() { - return econ != null; - } - - public static void depositPlayer(Player player, double v) { - econ.depositPlayer(player, v); - } - - public static Economy getEcon() { - return econ; - } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookFailedException.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookFailedException.java new file mode 100644 index 000000000..e8c30d3a6 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookFailedException.java @@ -0,0 +1,7 @@ +package us.talabrek.ultimateskyblock.hook; + +public class HookFailedException extends RuntimeException { + public HookFailedException(String message) { + super(message); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java new file mode 100644 index 000000000..83741ab3b --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java @@ -0,0 +1,62 @@ +package us.talabrek.ultimateskyblock.hook; + +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class HookManager { + private final uSkyBlock plugin; + private Map hooks = new ConcurrentHashMap<>(); + + public HookManager(@NotNull uSkyBlock plugin) { + this.plugin = plugin; + } + + /** + * Gets a {@link List} of all enabled hooks. + * @return List of all enabled hooks. + */ + public @NotNull List getEnabledHooks() { + return new ArrayList<>(hooks.keySet()); + } + + /** + * Returns an {@link Optional} containing the requested {@link PluginHook}, or null if the hook is not available. + * @param hook Name of the requested hook. + * @return Optional containing the requested PluginHook, or null if unavailable. + */ + public Optional getHook(String hook) { + return Optional.ofNullable(hooks.get(hook)); + } + + /** + * Returns the requested {@link PluginHook}. Throws a {@link NullPointerException} if the hook is not available. + * This method is designed to be used for hooks that we check on load, e.g. WorldEdit. + * @param hook Name of the requested hook. + * @return Requested PluginHook + * @throws NullPointerException If the requested hook is unavailable. + */ + public @NotNull PluginHook getRequiredHook(String hook) throws NullPointerException { + PluginHook foundHook = hooks.get(hook); + if (foundHook == null) { + throw new NullPointerException("No required hook found for: " + hook); + } + return foundHook; + } + + /** + * Tries to enable the hook in the given {@link PluginHook}. Adds the plugin hook to the list of enabled hooks + * if successfull. Throws a {@link HookFailedException} otherwise. + * @param hook Hook to enable and register. + * @throws HookFailedException if hooking into the plugin failes. + */ + public void registerHook(PluginHook hook) throws HookFailedException { + hook.onHook(); + hooks.put(hook.getHookName(), hook); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/PluginHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/PluginHook.java new file mode 100644 index 000000000..ac1fe308e --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/PluginHook.java @@ -0,0 +1,54 @@ +package us.talabrek.ultimateskyblock.hook; + +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public abstract class PluginHook { + protected final uSkyBlock plugin; + private final String hookName; + private final String implementing; + + /** + * PluginHook constructor. + * @param plugin uSkyBlock instance + * @param hookName The name of this plugin hook. + * @param implementing The name of the actual plugin that this hook will implement. + */ + public PluginHook(@NotNull uSkyBlock plugin, @NotNull String hookName, @NotNull String implementing) { + this.plugin = plugin; + this.hookName = hookName; + this.implementing = implementing; + } + + /** + * Called when the hook is enabled. Throws {@link HookFailedException} if the hooking fails. + * @throws HookFailedException if hooking fails. + */ + public void onHook() throws HookFailedException { + + } + + /** + * Called when the hook is disabled. Throws {@link HookFailedException} if the unhooking fails. + * @throws HookFailedException if unhooking fails. + */ + public void onUnhook() throws HookFailedException { + + } + + /** + * Gets the configured name of this hook. + * @return Hook name + */ + public @NotNull String getHookName() { + return hookName; + } + + /** + * Gets the name of the plugin that this hook implements. + * @return Name of the plugin that this hook implements. + */ + public @NotNull String getImplementing() { + return implementing; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java new file mode 100644 index 000000000..8902f1293 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java @@ -0,0 +1,43 @@ +package us.talabrek.ultimateskyblock.hook.economy; + +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.hook.PluginHook; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public abstract class EconomyHook extends PluginHook { + public EconomyHook(@NotNull uSkyBlock plugin, @NotNull String implementing) { + super(plugin, "Economy", implementing); + } + + /** + * Gets balance of an {@link OfflinePlayer} + * @param player of the player + * @return Amount currently held in players account + */ + public abstract double getBalance(@NotNull OfflinePlayer player); + + /** + * Deposit an amount to an {@link OfflinePlayer} - DO NOT USE NEGATIVE AMOUNTS + * @param player to deposit to + * @param amount Amount to deposit + * @return Detailed response of transaction + */ + public abstract boolean depositPlayer(@NotNull OfflinePlayer player, double amount); + + /** + * Withdraw an amount from an {@link OfflinePlayer} - DO NOT USE NEGATIVE AMOUNTS + * @param player to withdraw from + * @param amount Amount to withdraw + * @return Detailed response of transaction + */ + public abstract boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount); + + /** + * Returns the icon or name of the currency in plural form. Defaults to $. + * @return icon or of the currency + */ + public @NotNull String getCurrenyName() { + return "$"; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java new file mode 100644 index 000000000..159fc9835 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -0,0 +1,58 @@ +package us.talabrek.ultimateskyblock.hook.economy; + +import net.milkbowl.vault.economy.Economy; +import org.bukkit.OfflinePlayer; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.Optional; + +public class VaultEconomy extends EconomyHook { + private Economy economy; + + public VaultEconomy(@NotNull uSkyBlock plugin) { + super(plugin, "Vault"); + setupEconomy().ifPresent((economy) -> this.economy = economy); + } + + private Optional setupEconomy() { + RegisteredServiceProvider rsp = + plugin.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp != null) { + economy = rsp.getProvider(); + return Optional.of(economy); + } + + return Optional.empty(); + } + + @Override + public @NotNull String getCurrenyName() { + return economy.currencyNamePlural(); + } + + @Override + public double getBalance(@NotNull OfflinePlayer player) { + if (economy != null) { + return economy.getBalance(player); + } + return 0; + } + + @Override + public boolean depositPlayer(@NotNull OfflinePlayer player, double amount) { + if (economy != null) { + return economy.depositPlayer(player, amount).transactionSuccess(); + } + return false; + } + + @Override + public boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount) { + if (economy != null) { + return economy.depositPlayer(player, amount).transactionSuccess(); + } + return false; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index d7e13b402..7e4f6170f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -10,7 +10,6 @@ import dk.lockfuglsang.minecraft.util.VersionUtil; import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import io.papermc.lib.PaperLib; -import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Biome; @@ -63,6 +62,9 @@ import us.talabrek.ultimateskyblock.handler.VaultHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; +import us.talabrek.ultimateskyblock.hook.HookManager; +import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; +import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandGenerator; @@ -139,6 +141,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private LimitLogic limitLogic; /* MANAGERS */ + private HookManager hookManager; private MetricsManager metricsManager; private WorldManager worldManager; @@ -216,9 +219,6 @@ public void run() { if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { return; } - if (VaultHandler.setupEconomy()) { - log(Level.INFO, "Hooked into Vault Economy"); - } if (VaultHandler.setupPermissions()) { log(Level.INFO, "Hooked into Vault Permissions"); } @@ -445,8 +445,11 @@ public void clearPlayerInventory(Player player) { if (getConfig().getBoolean("options.restart.clearEnderChest", true)) { player.getEnderChest().clear(); } - if (getConfig().getBoolean("options.restart.clearCurrency", false) && VaultHandler.hasEcon()) { - VaultHandler.getEcon().withdrawPlayer(player, VaultHandler.getEcon().getBalance(player)); + if (getConfig().getBoolean("options.restart.clearCurrency", false)) { + getHookManager().getHook("Economy").ifPresent((hook) -> { + EconomyHook economyHook = (EconomyHook) hook; + economyHook.withdrawPlayer(player, economyHook.getBalance(player)); + }); } getLogger().exiting(CN, "clearPlayerInventory"); } @@ -739,6 +742,7 @@ public void reloadConfig() { private void reloadConfigs() { createFolders(); HandlerList.unregisterAll(this); + hookManager = new HookManager(this); if (challengeLogic != null) { challengeLogic.shutdown(); } @@ -749,7 +753,7 @@ private void reloadConfigs() { islandLogic.shutdown(); } PlaceholderHandler.unregister(this); - VaultHandler.setupEconomy(); + hookManager.registerHook(new VaultEconomy(this)); VaultHandler.setupPermissions(); if (Settings.loadPluginConfig(getConfig())) { saveConfig(); @@ -1080,6 +1084,10 @@ public IslandGenerator getIslandGenerator() { return islandGenerator; } + public HookManager getHookManager() { + return hookManager; + } + public WorldManager getWorldManager() { return worldManager; } From b11f8abd95df19ed110325d5e3c55216ad16cc07 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 23 May 2020 11:57:20 +0100 Subject: [PATCH 008/190] Add permissionshook and vault perms hook implementation --- .../challenge/ChallengeLogic.java | 7 +- .../handler/VaultHandler.java | 31 ------- .../ultimateskyblock/hook/HookManager.java | 82 ++++++++++++++----- .../hook/permissions/PermissionsHook.java | 38 +++++++++ .../hook/permissions/VaultPermissions.java | 39 +++++++++ .../ultimateskyblock/player/PlayerInfo.java | 26 ++++-- .../ultimateskyblock/player/PlayerLogic.java | 4 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 12 +-- 8 files changed, 164 insertions(+), 75 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/PermissionsHook.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index c3c56c7df..1c01a723f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -366,12 +366,11 @@ private boolean giveReward(Player player, Challenge challenge) { float currencyReward = reward.getCurrencyReward() * rewBonus; double percentage = (rewBonus - 1.0) * 100.0; - plugin.getHookManager().getHook("Economy").ifPresent((hook) -> { - EconomyHook economyHook = (EconomyHook) hook; - economyHook.depositPlayer(player, currencyReward); + plugin.getHookManager().getEconomyHook().ifPresent((hook) -> { + hook.depositPlayer(player, currencyReward); player.sendMessage(tr("\u00a7eCurrency reward: \u00a7f{0,number,###.##} {1} \u00a7a ({2,number,##.##})%", - currencyReward, economyHook.getCurrenyName(), percentage)); + currencyReward, hook.getCurrenyName(), percentage)); }); } if (reward.getPermissionReward() != null) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java index ee171a893..f8b42d666 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java @@ -1,41 +1,10 @@ package us.talabrek.ultimateskyblock.handler; import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import net.milkbowl.vault.permission.Permission; -import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.RegisteredServiceProvider; -import us.talabrek.ultimateskyblock.uSkyBlock; public enum VaultHandler {; - private static Permission perms; - - static { - perms = null; - } - - public static void addPermission(final Player player, final String perk) { - perms.playerAdd(player, perk); - } - - public static void removePermission(final Player player, final String perk) { - perms.playerRemove(player, perk); - } - - public static boolean hasPermission(final Player player, final String perk) { - return perms.playerHas(player, perk); - } - - public static boolean setupPermissions() { - final RegisteredServiceProvider rsp = (RegisteredServiceProvider) uSkyBlock.getInstance().getServer().getServicesManager().getRegistration((Class) Permission.class); - if (rsp.getProvider() != null) { - perms = rsp.getProvider(); - } - return perms != null; - } - public static String getItemName(ItemStack stack) { return ItemStackUtil.getItemName(stack); } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java index 83741ab3b..b3a90632f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java @@ -1,6 +1,10 @@ package us.talabrek.ultimateskyblock.hook; import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; +import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; +import us.talabrek.ultimateskyblock.hook.permissions.PermissionsHook; +import us.talabrek.ultimateskyblock.hook.permissions.VaultPermissions; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.ArrayList; @@ -11,42 +15,35 @@ public class HookManager { private final uSkyBlock plugin; - private Map hooks = new ConcurrentHashMap<>(); + private final Map hooks = new ConcurrentHashMap<>(); public HookManager(@NotNull uSkyBlock plugin) { this.plugin = plugin; } - /** - * Gets a {@link List} of all enabled hooks. - * @return List of all enabled hooks. - */ - public @NotNull List getEnabledHooks() { - return new ArrayList<>(hooks.keySet()); - } - /** * Returns an {@link Optional} containing the requested {@link PluginHook}, or null if the hook is not available. * @param hook Name of the requested hook. * @return Optional containing the requested PluginHook, or null if unavailable. */ - public Optional getHook(String hook) { + public Optional getHook(String hook) { return Optional.ofNullable(hooks.get(hook)); } /** - * Returns the requested {@link PluginHook}. Throws a {@link NullPointerException} if the hook is not available. - * This method is designed to be used for hooks that we check on load, e.g. WorldEdit. - * @param hook Name of the requested hook. - * @return Requested PluginHook - * @throws NullPointerException If the requested hook is unavailable. + * Short method for {@link #getHook(String)} to get the optional {@link EconomyHook}. + * @return optional of EconomyHook. */ - public @NotNull PluginHook getRequiredHook(String hook) throws NullPointerException { - PluginHook foundHook = hooks.get(hook); - if (foundHook == null) { - throw new NullPointerException("No required hook found for: " + hook); - } - return foundHook; + public Optional getEconomyHook() { + return Optional.ofNullable((EconomyHook) getHook("Economy").orElse(null)); + } + + /** + * Short method for {@link #getHook(String)} to get the optional {@link PermissionsHook}. + * @return optional of PermissionsHook. + */ + public Optional getPermissionsHook() { + return Optional.ofNullable((PermissionsHook) getHook("Permissions").orElse(null)); } /** @@ -59,4 +56,47 @@ public void registerHook(PluginHook hook) throws HookFailedException { hook.onHook(); hooks.put(hook.getHookName(), hook); } + + /** + * Checks and hooks if there are compatible Economy plugins available. + * @return True if a compatible Economy plugin has been found and hooking succeeded, false otherwise. + */ + public boolean setupEconomyHook() { + try { + if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { + VaultEconomy vault = new VaultEconomy(plugin); + registerHook(vault); + plugin.getLogger().info("Hooked into Vault economy"); + return true; + } + } catch (HookFailedException ex) { + plugin.getLogger().warning("Failed to hook into Vault economy."); + ex.printStackTrace(); + } + + plugin.getLogger().info("Failed to find a compatible economy system. Economy rewards will be disabled."); + return false; + } + + /** + * Checks and hooks if there are compatible Permissions plugins available. + * @return True if a compatible Permissions plugin has geen found and hooking succeeded, false otherwise. + */ + public boolean setupPermissionsHook() { + try { + if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { + VaultPermissions vault = new VaultPermissions(plugin); + registerHook(vault); + plugin.getLogger().info("Hooked into Vault permissions."); + return true; + } + } catch (HookFailedException ex) { + plugin.getLogger().warning("Failed to hook into Vault permissions plugin."); + ex.printStackTrace(); + } + + plugin.getLogger().warning("Failed to find a compatible permissions system. Permission rewards " + + "will be disabled."); + return false; + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/PermissionsHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/PermissionsHook.java new file mode 100644 index 000000000..552b08da2 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/PermissionsHook.java @@ -0,0 +1,38 @@ +package us.talabrek.ultimateskyblock.hook.permissions; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.hook.PluginHook; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public abstract class PermissionsHook extends PluginHook { + public PermissionsHook(@NotNull uSkyBlock plugin, @NotNull String implementing) { + super(plugin, "Permissions", implementing); + } + + /** + * Add permission to a player ONLY for the world the player is currently on. This is a world-specific operation. + * @param player Player Object + * @param perk Permission node + * @return Success or Failure + */ + public abstract boolean addPermission(@NotNull Player player, @NotNull String perk); + + /** + * Remove permission from a player. This is a world-specific operation. + * @param player Player Object + * @param perk Permission node + * @return Success or Failure + */ + public abstract boolean removePermission(@NotNull Player player, @NotNull String perk); + + /** + * Gets the value of the specified permission, if set. If a permission override is not set on this object, + * the default value of the permission will be returned. + * @param perk Name of the permission + * @return Value of the permission + */ + public boolean hasPermission(@NotNull Player player, @NotNull String perk) { + return player.hasPermission(perk); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java new file mode 100644 index 000000000..2e77d6c4f --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -0,0 +1,39 @@ +package us.talabrek.ultimateskyblock.hook.permissions; + +import net.milkbowl.vault.permission.Permission; +import org.bukkit.entity.Player; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.Optional; + +public class VaultPermissions extends PermissionsHook { + private Permission permission; + + public VaultPermissions(@NotNull uSkyBlock plugin) { + super(plugin, "Vault"); + setupPermission().ifPresent((permission) -> this.permission = permission); + } + + private Optional setupPermission() { + RegisteredServiceProvider rsp = + plugin.getServer().getServicesManager().getRegistration(Permission.class); + if (rsp != null) { + permission = rsp.getProvider(); + return Optional.of(permission); + } + + return Optional.empty(); + } + + @Override + public boolean addPermission(@NotNull Player player, @NotNull String perk) { + return permission.playerAdd(player, perk); + } + + @Override + public boolean removePermission(@NotNull Player player, @NotNull String perk) { + return permission.playerRemove(player, perk); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index cb5c917a3..63d39e3ea 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; -import us.talabrek.ultimateskyblock.handler.VaultHandler; +import us.talabrek.ultimateskyblock.hook.permissions.PermissionsHook; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -38,6 +39,7 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private static final Logger log = Logger.getLogger(CN); private static final long serialVersionUID = 1L; private static final int YML_VERSION = 1; + private final uSkyBlock plugin; private String playerName; private String displayName; private UUID uuid; @@ -52,7 +54,8 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private boolean islandGenerating = false; private boolean dirty = false; - public PlayerInfo(String currentPlayerName, UUID playerUUID) { + public PlayerInfo(String currentPlayerName, UUID playerUUID, uSkyBlock plugin) { + this.plugin = plugin; this.uuid = playerUUID; this.playerName = currentPlayerName; // Prefer UUID over Name @@ -432,13 +435,18 @@ public boolean addPermissions(@Nullable List perms) { if (perms == null || perms.isEmpty()) { return true; } + Player target = getPlayer(); - if (target != null && target.isOnline()) { + Optional hook = plugin.getHookManager().getPermissionsHook(); + + if (target != null && target.isOnline() && hook.isPresent()) { List permList = playerData.getStringList("player.perms"); + PermissionsHook pHook = hook.get(); + for (String perm : perms) { - if (!VaultHandler.hasPermission(target, perm)) { + if (pHook.hasPermission(target, perm)) { permList.add(perm); - VaultHandler.addPermission(target, perm); + pHook.addPermission(target, perm); } } playerData.set("player.perms", permList); @@ -458,9 +466,11 @@ public void clearPerms(@NotNull Player target) { final List perms = playerData.getStringList("player.perms"); if (!perms.isEmpty()) { - for (String perm : perms) { - VaultHandler.removePermission(target, perm); - } + plugin.getHookManager().getPermissionsHook().ifPresent((hook) -> { + for (String perm : perms) { + hook.removePermission(target, perm); + } + }); playerData.set("player.perms", null); playerData.set("pending-permissions", null); save(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java index 7253ef6f3..2f1366e8e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java @@ -25,7 +25,7 @@ */ public class PlayerLogic { private static final Logger log = Logger.getLogger(PlayerLogic.class.getName()); - private static final PlayerInfo UNKNOWN_PLAYER = new PlayerInfo(PlayerDB.UNKNOWN_PLAYER_NAME, PlayerDB.UNKNOWN_PLAYER_UUID); + private static final PlayerInfo UNKNOWN_PLAYER = new PlayerInfo(PlayerDB.UNKNOWN_PLAYER_NAME, PlayerDB.UNKNOWN_PLAYER_UUID, uSkyBlock.getInstance()); private final LoadingCache playerCache; private final uSkyBlock plugin; private final BukkitTask saveTask; @@ -88,7 +88,7 @@ private PlayerInfo loadPlayerData(UUID playerUUID, String playerName) { } log.log(Level.FINER, "Loading player data for " + playerUUID + "/" + playerName); - final PlayerInfo playerInfo = new PlayerInfo(playerName, playerUUID); + final PlayerInfo playerInfo = new PlayerInfo(playerName, playerUUID, plugin); final Player onlinePlayer = uSkyBlock.getInstance().getPlayerDB().getPlayer(playerUUID); if (onlinePlayer != null && onlinePlayer.isOnline()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 7e4f6170f..71e9baa52 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -219,9 +219,8 @@ public void run() { if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { return; } - if (VaultHandler.setupPermissions()) { - log(Level.INFO, "Hooked into Vault Permissions"); - } + uSkyBlock.this.getHookManager().setupEconomyHook(); + uSkyBlock.this.getHookManager().setupPermissionsHook(); AsyncWorldEditHandler.onEnable(uSkyBlock.this); WorldGuardHandler.setupGlobal(getWorldManager().getWorld()); if (getWorldManager().getNetherWorld() != null) { @@ -446,10 +445,7 @@ public void clearPlayerInventory(Player player) { player.getEnderChest().clear(); } if (getConfig().getBoolean("options.restart.clearCurrency", false)) { - getHookManager().getHook("Economy").ifPresent((hook) -> { - EconomyHook economyHook = (EconomyHook) hook; - economyHook.withdrawPlayer(player, economyHook.getBalance(player)); - }); + getHookManager().getEconomyHook().ifPresent((hook) -> hook.withdrawPlayer(player, hook.getBalance(player))); } getLogger().exiting(CN, "clearPlayerInventory"); } @@ -753,8 +749,6 @@ private void reloadConfigs() { islandLogic.shutdown(); } PlaceholderHandler.unregister(this); - hookManager.registerHook(new VaultEconomy(this)); - VaultHandler.setupPermissions(); if (Settings.loadPluginConfig(getConfig())) { saveConfig(); } From fd03b2e83692306857deccc9dec9b4eb1b02d694 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 24 May 2020 18:14:43 +0100 Subject: [PATCH 009/190] Remove old VaultHandler --- .../ultimateskyblock/block/BlockCollection.java | 4 ++-- .../talabrek/ultimateskyblock/challenge/Challenge.java | 5 ++--- .../ultimateskyblock/challenge/ChallengeLogic.java | 4 +--- .../ultimateskyblock/command/admin/NBTCommand.java | 3 +-- .../ultimateskyblock/command/island/InfoCommand.java | 6 +++--- .../talabrek/ultimateskyblock/event/PlayerEvents.java | 6 +++--- .../ultimateskyblock/handler/VaultHandler.java | 10 ---------- .../island/level/BlockScoreComparator.java | 4 ++-- .../ultimateskyblock/island/level/BlockScoreImpl.java | 4 ++-- 9 files changed, 16 insertions(+), 30 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java index 68a7e3d6e..d5d2d8fc6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java @@ -1,9 +1,9 @@ package us.talabrek.ultimateskyblock.block; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import java.util.Collection; import java.util.Collections; @@ -41,7 +41,7 @@ public synchronized String diff(Collection itemStacks) { diff = item.getAmount() - count(item.getType()); } if (diff > 0) { - sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, VaultHandler.getItemName(item))); + sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, ItemStackUtil.getItemName(item))); } } if (sb.toString().trim().isEmpty()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java index 03cf2fc21..028ad3b2a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java @@ -3,7 +3,6 @@ import dk.lockfuglsang.minecraft.nbt.NBTUtil; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.FormatUtil; @@ -207,8 +206,8 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr break; } details.add(item.getAmount() > 1 - ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), VaultHandler.getItemName(item)) - : tr("\u00a77{0}", VaultHandler.getItemName(item))); + ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), ItemStackUtil.getItemName(item)) + : tr("\u00a77{0}", ItemStackUtil.getItemName(item))); } } if (requiredEntities != null && !requiredEntities.isEmpty() && wrappedDetails(details).size() < MAX_DETAILS) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 1c01a723f..151a49a94 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -19,8 +19,6 @@ import org.bukkit.inventory.meta.ItemMeta; import us.talabrek.ultimateskyblock.api.event.MemberJoinedEvent; import us.talabrek.ultimateskyblock.block.BlockCollection; -import us.talabrek.ultimateskyblock.handler.VaultHandler; -import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.Perk; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -307,7 +305,7 @@ private boolean tryCompleteOnPlayer(Player player, String challengeName) { boolean hasAll = true; List requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); for (ItemStack required : requiredItems) { - String name = VaultHandler.getItemName(required); + String name = ItemStackUtil.getItemName(required); if (!player.getInventory().containsAtLeast(required, required.getAmount())) { sb.append(tr(" \u00a74{0} \u00a7b{1}", (required.getAmount() - getCountOf(player.getInventory(), required)), name)); hasAll = false; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java index 990947802..a5740a06d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java @@ -6,7 +6,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import java.util.Map; @@ -29,7 +28,7 @@ public boolean execute(CommandSender sender, String alias, Map d if (itemStack != null) { String[] msgs = new String[]{ tr("\u00a7eInfo for \u00a79{0}", ItemStackUtil.asString(itemStack)), - tr("\u00a77 - name: \u00a79{0}", VaultHandler.getItemName(itemStack)), + tr("\u00a77 - name: \u00a79{0}", ItemStackUtil.getItemName(itemStack)), tr("\u00a77 - nbttag: \u00a79{0}", NBTUtil.getNBTTag(itemStack)) }; player.sendMessage(msgs); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java index cb76941ad..1616169a9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java @@ -1,10 +1,10 @@ package us.talabrek.ultimateskyblock.command.island; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.model.BlockScore; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PatienceTester; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -83,7 +83,7 @@ public void run() { for (BlockScore score : getState().getTop((currentPage - 1) * 10, 10)) { player.sendMessage(score.getState().getColor() + tr("{0,number,00.00} {1,number,#} {2}", score.getScore(), score.getCount(), - VaultHandler.getItemName(score.getBlock()))); + ItemStackUtil.getItemName(score.getBlock()))); } player.sendMessage(tr("\u00a7aIsland level is {0,number,###.##}", getState().getScore())); } @@ -103,4 +103,4 @@ public void run() { } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index d4ca5fabc..ae48f2784 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.event; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -27,7 +28,6 @@ import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.event.IslandInfoEvent; import us.talabrek.ultimateskyblock.api.model.IslandScore; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandInfo; @@ -319,7 +319,7 @@ public void onBlockPlaceEvent(BlockPlaceEvent event) final String key = "usb.block-limits"; if (!PatienceTester.isRunning(player, key)) { PatienceTester.startRunning(player, key); - player.sendMessage(tr("\u00a74{0} is limited. \u00a7eScanning your island to see if you are allowed to place more, please be patient", VaultHandler.getItemName(new ItemStack(type)))); + player.sendMessage(tr("\u00a74{0} is limited. \u00a7eScanning your island to see if you are allowed to place more, please be patient", ItemStackUtil.getItemName(new ItemStack(type)))); plugin.fireAsyncEvent(new IslandInfoEvent(player, islandInfo.getIslandLocation(), new Callback() { @Override public void run() { @@ -332,7 +332,7 @@ public void run() { } if (canPlace == BlockLimitLogic.CanPlace.NO) { event.setCancelled(true); - player.sendMessage(tr("\u00a74You''ve hit the {0} limit!\u00a7e You can''t have more of that type on your island!\u00a79 Max: {1,number}", VaultHandler.getItemName(new ItemStack(type)), plugin.getBlockLimitLogic().getLimit(type))); + player.sendMessage(tr("\u00a74You''ve hit the {0} limit!\u00a7e You can''t have more of that type on your island!\u00a79 Max: {1,number}", ItemStackUtil.getItemName(new ItemStack(type)), plugin.getBlockLimitLogic().getLimit(type))); return; } plugin.getBlockLimitLogic().incBlockCount(islandInfo.getIslandLocation(), type); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java deleted file mode 100644 index f8b42d666..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/VaultHandler.java +++ /dev/null @@ -1,10 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import org.bukkit.inventory.ItemStack; - -public enum VaultHandler {; - public static String getItemName(ItemStack stack) { - return ItemStackUtil.getItemName(stack); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java index 6abd61d8d..3e759acae 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.island.level; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import us.talabrek.ultimateskyblock.api.model.BlockScore; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import java.util.Comparator; @@ -16,7 +16,7 @@ public int compare(BlockScore o1, BlockScore o2) { cmp = o2.getCount() - o1.getCount(); } if (cmp == 0) { - cmp = VaultHandler.getItemName(o2.getBlock()).compareTo(VaultHandler.getItemName(o1.getBlock())); + cmp = ItemStackUtil.getItemName(o2.getBlock()).compareTo(ItemStackUtil.getItemName(o1.getBlock())); } return cmp; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java index a6a16f501..f26848283 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.island.level; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.handler.VaultHandler; public class BlockScoreImpl implements us.talabrek.ultimateskyblock.api.model.BlockScore { @@ -21,7 +21,7 @@ public BlockScoreImpl(ItemStack block, int count, double score, State state, Str this.count = count; this.score = score; this.state = state; - this.name = name != null ? name : VaultHandler.getItemName(getBlock()); + this.name = name != null ? name : ItemStackUtil.getItemName(getBlock()); } @Override From ca26e59f6b678a41cfe774b73f36feb668d8e929 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 24 May 2020 18:38:45 +0100 Subject: [PATCH 010/190] Forgot an import... --- .../src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 71e9baa52..10720ea0d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -59,12 +59,9 @@ import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; -import us.talabrek.ultimateskyblock.handler.VaultHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; -import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; -import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandGenerator; From 4655c4ebc82b0039a4d40e1dba5794629289b756 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 25 May 2020 23:00:02 +0100 Subject: [PATCH 011/190] Don't need this abstraction anymore --- .../event/NetherTerraFormEvents.java | 13 +++++---- .../handler/EntitySpawner.java | 29 ------------------- 2 files changed, 7 insertions(+), 35 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/EntitySpawner.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java index 539d90e37..2d8708507 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java @@ -7,9 +7,11 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Fireball; import org.bukkit.entity.PigZombie; import org.bukkit.entity.Player; +import org.bukkit.entity.WitherSkeleton; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -18,7 +20,6 @@ import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; -import us.talabrek.ultimateskyblock.handler.EntitySpawner; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; @@ -48,7 +49,6 @@ public class NetherTerraFormEvents implements Listener { private final boolean spawnEnabled; private final double minPitch; private final double maxPitch; - private final EntitySpawner entitySpawner; public NetherTerraFormEvents(uSkyBlock plugin) { this.plugin = plugin; @@ -83,7 +83,6 @@ public NetherTerraFormEvents(uSkyBlock plugin) { chanceWither = 0.4; chanceSkeleton = 0.1; } - entitySpawner = new EntitySpawner(); } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) @@ -262,11 +261,13 @@ public void onCreatureSpawn(CreatureSpawnEvent e) { e.setCancelled(true); double p = RND.nextDouble(); if (p <= chanceWither && block.getRelative(BlockFace.UP, 3).getType() == Material.AIR) { - entitySpawner.spawnWitherSkeleton(e.getLocation()); + WitherSkeleton mob = (WitherSkeleton) e.getLocation().getWorld().spawnEntity( + e.getLocation(), EntityType.WITHER_SKELETON); + mob.getEquipment().setItemInMainHand(new ItemStack(Material.STONE_SWORD, 1)); } else if (p <= chanceWither+chanceBlaze) { - entitySpawner.spawnBlaze(e.getLocation()); + e.getLocation().getWorld().spawnEntity(e.getLocation(), EntityType.BLAZE); } else if (p <= chanceWither+chanceBlaze+chanceSkeleton) { - entitySpawner.spawnSkeleton(e.getLocation()); + e.getLocation().getWorld().spawnEntity(e.getLocation(), EntityType.SKELETON); } else { e.setCancelled(false); // Spawn PigZombie } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/EntitySpawner.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/EntitySpawner.java deleted file mode 100644 index d99e857c2..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/EntitySpawner.java +++ /dev/null @@ -1,29 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.Blaze; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Skeleton; -import org.bukkit.entity.WitherSkeleton; -import org.bukkit.inventory.ItemStack; - -/** - * Abstraction for spawning entities (cross-version-support) - */ -@SuppressWarnings("UnusedReturnValue") -public class EntitySpawner { - public WitherSkeleton spawnWitherSkeleton(Location location) { - WitherSkeleton mob = (WitherSkeleton) location.getWorld().spawnEntity(location, EntityType.WITHER_SKELETON); - mob.getEquipment().setItemInMainHand(new ItemStack(Material.STONE_SWORD, 1)); - return mob; - } - - public Blaze spawnBlaze(Location location) { - return (Blaze) location.getWorld().spawnEntity(location, EntityType.BLAZE); - } - - public Skeleton spawnSkeleton(Location location) { - return (Skeleton) location.getWorld().spawnEntity(location, EntityType.SKELETON); - } -} From 89554bb6fc80c06204b9ce200bc8ec1686f358a4 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 26 May 2020 00:16:21 +0100 Subject: [PATCH 012/190] Check if lavablock is source by level instead of damage value --- .../ultimateskyblock/event/PlayerEvents.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index ae48f2784..aa74f9620 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -4,6 +4,8 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Levelled; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.EnderPearl; import org.bukkit.entity.Player; @@ -46,6 +48,7 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +@SuppressWarnings("unused") public class PlayerEvents implements Listener { private static final Set FIRE_TRAP = new HashSet<>( Arrays.asList(EntityDamageEvent.DamageCause.LAVA, EntityDamageEvent.DamageCause.FIRE, EntityDamageEvent.DamageCause.FIRE_TICK)); @@ -142,16 +145,20 @@ public boolean testForObsidian(final Block block) { @EventHandler public void onLavaReplace(BlockPlaceEvent event) { if (!protectLava || !plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { - return; // Skip + return; } - if (isLavaSource(event.getBlockReplacedState().getType(), event.getBlockReplacedState().getRawData())) { + if (isLavaSource(event.getBlockReplacedState().getBlockData())) { plugin.notifyPlayer(event.getPlayer(), tr("\u00a74It''s a bad idea to replace your lava!")); event.setCancelled(true); } } - private boolean isLavaSource(Material type, byte data) { - return (type == Material.LAVA) && data == 0; + private boolean isLavaSource(BlockData blockData) { + if (blockData.getMaterial() == Material.LAVA) { + Levelled level = (Levelled) blockData; + return level.getLevel() == 0; + } + return false; } @EventHandler @@ -159,7 +166,7 @@ public void onLavaAbsorption(EntityChangeBlockEvent event) { if (!plugin.getWorldManager().isSkyWorld(event.getBlock().getWorld())) { return; } - if (isLavaSource(event.getBlock().getType(), event.getBlock().getData())) { + if (isLavaSource(event.getBlock().getBlockData())) { if (event.getTo() != Material.LAVA) { event.setCancelled(true); // TODO: R4zorax - 21-07-2018: missing datavalue (might convert stuff - exploit) From 988c178527dfce9a382477c3460b8a654a46ef13 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 27 May 2020 01:02:04 +0100 Subject: [PATCH 013/190] v2.8.8 --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index baf580243..ac082f7a7 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8-SNAPSHOT + 2.8.8 4.0.0 jar diff --git a/pom.xml b/pom.xml index 8a058c765..270b53372 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.8-SNAPSHOT + 2.8.8 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 6a92f060e..3aae1f1cc 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.8-SNAPSHOT + 2.8.8 UTF-8 dev diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 47afacdc6..48ca99d65 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8-SNAPSHOT + 2.8.8 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 32171f6f0..2dd138efe 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8-SNAPSHOT + 2.8.8 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 924a784ea..72457a6f9 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8-SNAPSHOT + 2.8.8 4.0.0 jar From bdd3090f75b47e6cb5969324fc1443e8ac201a2a Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 27 May 2020 01:32:49 +0100 Subject: [PATCH 014/190] Jitpack is horrible --- uSkyBlock-Core/pom.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 48ca99d65..230c68d07 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -98,7 +98,7 @@ org.bstats:* io.papermc:paperlib - net.wesjd:anvilgui + dk.lockfuglsang.minecraft:bukkit-utils dk.lockfuglsang.minecraft:po-utils com.googlecode.json-simple:json-simple @@ -117,10 +117,10 @@ io.papermc.lib us.talabrek.ultimateskyblock.paperlib - - net.wesjd.anvilgui - us.talabrek.ultimateskyblock.anvilgui - + + + + @@ -360,12 +360,12 @@ compile - - com.github.WesJD - AnvilGUI - master-SNAPSHOT - compile - + + + + + + com.onarandombox.multiversecore From be5c5fce91080162355c3040b6ef18f0dc75e37d Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 27 May 2020 16:58:55 +0100 Subject: [PATCH 015/190] v2.8.9-SNAPSHOT --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index ac082f7a7..170603abe 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8 + 2.8.9-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index 270b53372..37621b0d5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.8 + 2.8.9-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 3aae1f1cc..068955421 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.8 + 2.8.9-SNAPSHOT UTF-8 dev diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 230c68d07..165014ab3 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8 + 2.8.9-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 2dd138efe..1ab737b07 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8 + 2.8.9-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 72457a6f9..44214de52 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.8 + 2.8.9-SNAPSHOT 4.0.0 jar From 6092956fbe3d97992ee64f4746b783c1d0afc170 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 29 May 2020 22:15:11 +0100 Subject: [PATCH 016/190] Self-host Vault repo --- pom.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pom.xml b/pom.xml index 37621b0d5..9dd1b532f 100644 --- a/pom.xml +++ b/pom.xml @@ -100,11 +100,6 @@ sk89q-repo https://maven.sk89q.com/repo/ - - - - - CodeMC https://repo.codemc.org/repository/maven-public @@ -113,10 +108,6 @@ mvdw-software https://repo.mvdw-software.com/content/groups/public/ - - jitpack.io - https://jitpack.io - uskyblock-dependencies https://www.uskyblock.ovh/maven/dependencies/ From eba13124afb767e33f0b4609617efdf64faea085 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 2 Jun 2020 01:14:18 +0100 Subject: [PATCH 017/190] Register Service(Un)RegisterEvent listeners for Vault hooks --- .../hook/economy/VaultEconomy.java | 24 ++++++++++++++++++- .../hook/permissions/VaultPermissions.java | 23 +++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java index 159fc9835..c6239f676 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -2,18 +2,23 @@ import net.milkbowl.vault.economy.Economy; import org.bukkit.OfflinePlayer; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServiceRegisterEvent; +import org.bukkit.event.server.ServiceUnregisterEvent; import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Optional; -public class VaultEconomy extends EconomyHook { +public class VaultEconomy extends EconomyHook implements Listener { private Economy economy; public VaultEconomy(@NotNull uSkyBlock plugin) { super(plugin, "Vault"); setupEconomy().ifPresent((economy) -> this.economy = economy); + plugin.getServer().getPluginManager().registerEvents(this, plugin); } private Optional setupEconomy() { @@ -55,4 +60,21 @@ public boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount) { } return false; } + + @EventHandler + @SuppressWarnings("unused") + public void onEconomyRegister(ServiceRegisterEvent event) { + if (event.getProvider().getProvider() instanceof Economy) { + setupEconomy().ifPresent((economy) -> this.economy = economy); + } + } + + @EventHandler + @SuppressWarnings("unused") + public void onEconomyUnregister(ServiceUnregisterEvent event) { + if (event.getProvider().getProvider() instanceof Economy) { + this.economy = null; + setupEconomy().ifPresent((economy) -> this.economy = economy); + } + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java index 2e77d6c4f..bd1e55622 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -2,18 +2,22 @@ import net.milkbowl.vault.permission.Permission; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServiceRegisterEvent; import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Optional; -public class VaultPermissions extends PermissionsHook { +public class VaultPermissions extends PermissionsHook implements Listener { private Permission permission; public VaultPermissions(@NotNull uSkyBlock plugin) { super(plugin, "Vault"); setupPermission().ifPresent((permission) -> this.permission = permission); + plugin.getServer().getPluginManager().registerEvents(this, plugin); } private Optional setupPermission() { @@ -36,4 +40,21 @@ public boolean addPermission(@NotNull Player player, @NotNull String perk) { public boolean removePermission(@NotNull Player player, @NotNull String perk) { return permission.playerRemove(player, perk); } + + @EventHandler + @SuppressWarnings("unused") + public void onPermissionRegister(ServiceRegisterEvent event) { + if (event.getProvider().getProvider() instanceof Permission) { + setupPermission().ifPresent((permission) -> this.permission = permission); + } + } + + @EventHandler + @SuppressWarnings("unused") + public void onPermissionUnregister(ServiceRegisterEvent event) { + if (event.getProvider().getProvider() instanceof Permission) { + this.permission = null; + setupPermission().ifPresent((permission) -> this.permission = permission); + } + } } From ae630cba61652e0c151cf81f1fcb44c158071d12 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 2 Jun 2020 01:15:19 +0100 Subject: [PATCH 018/190] Register, unregister, I'm getting old... --- .../ultimateskyblock/hook/permissions/VaultPermissions.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java index bd1e55622..0783ecfdf 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -5,6 +5,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.server.ServiceRegisterEvent; +import org.bukkit.event.server.ServiceUnregisterEvent; import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -51,7 +52,7 @@ public void onPermissionRegister(ServiceRegisterEvent event) { @EventHandler @SuppressWarnings("unused") - public void onPermissionUnregister(ServiceRegisterEvent event) { + public void onPermissionUnregister(ServiceUnregisterEvent event) { if (event.getProvider().getProvider() instanceof Permission) { this.permission = null; setupPermission().ifPresent((permission) -> this.permission = permission); From 1712a5ff68a3538b8a6866174c74ad162461ae7d Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 3 Jun 2020 19:20:46 +0100 Subject: [PATCH 019/190] Use EnumMap for chat formats --- .../ultimateskyblock/chat/ChatLogic.java | 94 ++++++++++++------- 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java index 790d8f9ee..1d7f2b39b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java @@ -2,8 +2,9 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandInfo; -import us.talabrek.ultimateskyblock.api.event.IslandChatEvent; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -11,55 +12,75 @@ import java.util.Arrays; import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Matcher; +import static us.talabrek.ultimateskyblock.api.event.IslandChatEvent.*; + /** * The primary logic of uSkyBlocks chat-handling */ public class ChatLogic { - private final List ALONE = Arrays.asList( - I18nUtil.tr("But you are ALLLLLLL ALOOOOONE!"), - I18nUtil.tr("But you are Yelling in the wind!"), - I18nUtil.tr("But your fantasy friends are gone!"), - I18nUtil.tr("But you are Talking to your self!") + private static final List ALONE_MESSAGES = Arrays.asList( + I18nUtil.tr("But you are ALLLLLLL ALOOOOONE!"), + I18nUtil.tr("But you are Yelling in the wind!"), + I18nUtil.tr("But your fantasy friends are gone!"), + I18nUtil.tr("But you are Talking to your self!") ); private final uSkyBlock plugin; - private final Map formats = new HashMap<>(); - private final Map toggled = new HashMap<>(); + private final Map formats = new EnumMap<>(Type.class); + private final Map toggled = new HashMap<>(); public ChatLogic(uSkyBlock plugin) { this.plugin = plugin; - formats.put(IslandChatEvent.Type.PARTY, plugin.getConfig().getString("options.party.chat-format", "&9PARTY &r{DISPLAYNAME} &f>&d {MESSAGE}")); - formats.put(IslandChatEvent.Type.ISLAND, plugin.getConfig().getString("options.island.chat-format", "&9SKY &r{DISPLAYNAME} &f>&b {MESSAGE}")); + formats.put(Type.PARTY, + plugin.getConfig().getString("options.party.chat-format", "&9PARTY &r{DISPLAYNAME} &f>&d {MESSAGE}")); + formats.put(Type.ISLAND, + plugin.getConfig().getString("options.island.chat-format", "&9SKY &r{DISPLAYNAME} &f>&b {MESSAGE}")); } - public List getRecipients(Player player, IslandChatEvent.Type chatType) { - if (chatType == IslandChatEvent.Type.PARTY) { - IslandInfo islandInfo = plugin.getIslandInfo(player); - return islandInfo != null ? islandInfo.getOnlineMembers() : Collections.singletonList(player); - } else if (chatType == IslandChatEvent.Type.ISLAND) { - if (plugin.getWorldManager().isSkyWorld(player.getWorld())) { + /** + * Gets a {@link List} containing {@link Player}'s with all the recipients that should receive the given message + * {@link Type} from the sending {@link Player}. Returns an empty list when there are no recipients. + * @param sender Player sending the message. + * @param chatType Message type that the player is sending. + * @return List of all recipients, or an empty list if there are none. + */ + public @NotNull List getRecipients(Player sender, Type chatType) { + if (chatType == Type.PARTY) { + IslandInfo islandInfo = plugin.getIslandInfo(sender); + return islandInfo != null ? islandInfo.getOnlineMembers() : Collections.singletonList(sender); + } else if (chatType == Type.ISLAND) { + if (plugin.getWorldManager().isSkyWorld(sender.getWorld())) { return WorldGuardHandler.getPlayersInRegion(plugin.getWorldManager().getWorld(), - WorldGuardHandler.getIslandRegionAt(player.getLocation())); + WorldGuardHandler.getIslandRegionAt(sender.getLocation())); } return Collections.emptyList(); } return Collections.emptyList(); } - public void sendMessage(Player player, IslandChatEvent.Type type, String message) { + /** + * Sends the given message to all online partymembers or island visitors on the given {@link Player}'s island, + * depending on the given {@link Type}. + * @param sender Player sending the message. + * @param type Message type to send. + * @param message Message to send. + */ + public void sendMessage(Player sender, Type type, String message) { String format = getFormat(type); format = FormatUtil.normalize(format); - format = format.replaceAll("\\{DISPLAYNAME\\}", Matcher.quoteReplacement(player.getDisplayName())); - String msg = format.replaceAll("\\{MESSAGE\\}", Matcher.quoteReplacement(message)); - msg = PlaceholderHandler.replacePlaceholders(player, msg); - List onlineMembers = getRecipients(player, type); + format = format.replaceAll("\\{DISPLAYNAME}", Matcher.quoteReplacement(sender.getDisplayName())); + String msg = format.replaceAll("\\{MESSAGE}", Matcher.quoteReplacement(message)); + msg = PlaceholderHandler.replacePlaceholders(sender, msg); + List onlineMembers = getRecipients(sender, type); if (onlineMembers.size() <= 1) { - player.sendMessage(I18nUtil.tr("\u00a7cSorry! {0}", "\u00a79" + ALONE.get(((int) Math.round(Math.random() * ALONE.size())) % ALONE.size()))); + sender.sendMessage(I18nUtil.tr("\u00a7cSorry! {0}", "\u00a79" + + ALONE_MESSAGES.get(((int) Math.round(Math.random() * ALONE_MESSAGES.size())) % ALONE_MESSAGES.size()))); } else { for (Player member : onlineMembers) { member.sendMessage(msg); @@ -67,18 +88,23 @@ public void sendMessage(Player player, IslandChatEvent.Type type, String message } } - public String getFormat(IslandChatEvent.Type type) { + /** + * Gets the message format for the given {@link Type}. + * @param type Island chat type to lookup. + * @return Message format. + */ + public @NotNull String getFormat(Type type) { return formats.get(type); } /** - * Toggles the chat-type on or off, returns true if it was toggled on. - * @param player - * @param type - * @return + * Toggle the {@link Type} on or off for the given {@link Player}, returns true if it is toggled on. + * @param player Player to toggle the chat type for. + * @param type Chat type to toggle. + * @return True if it is toggled on, false otherwise. */ - public synchronized boolean toggle(Player player, IslandChatEvent.Type type) { - IslandChatEvent.Type oldType = toggled.get(player.getUniqueId()); + public synchronized boolean toggle(Player player, Type type) { + Type oldType = toggled.get(player.getUniqueId()); if (oldType == type) { toggled.remove(player.getUniqueId()); return false; @@ -89,11 +115,11 @@ public synchronized boolean toggle(Player player, IslandChatEvent.Type type) { } /** - * Returns the current toggle, or null if none exists. - * @param player - * @return + * Gets the current {@link Type} toggle for the given {@link Player}, or null if none exists. + * @param player Player to lookup. + * @return The current Type toggle, or null if none exists. */ - public synchronized IslandChatEvent.Type getToggle(Player player) { + public synchronized @Nullable Type getToggle(Player player) { return toggled.get(player.getUniqueId()); } } From 2735bbf46dbf76491e28b93bbbe016dc10d93150 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 4 Jun 2020 15:36:17 +0100 Subject: [PATCH 020/190] Remove unnecessary challenge name lookups while completing --- .../challenge/ChallengeLogic.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 151a49a94..f450a5b34 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -60,7 +61,7 @@ public class ChallengeLogic implements Listener { public final ChallengeDefaults defaults; public final ChallengeCompletionLogic completionLogic; private final ItemStack lockedItem; - private final Map lockedItemMap = new HashMap<>(); + private final Map lockedItemMap = new EnumMap<>(Challenge.Type.class); public ChallengeLogic(FileConfiguration config, uSkyBlock plugin) { this.config = config; @@ -125,7 +126,7 @@ public List getAllChallengeNames() { } public List getChallengesForRank(String rank) { - return ranks.containsKey(rank) ? ranks.get(rank).getChallenges() : Collections.emptyList(); + return ranks.containsKey(rank) ? ranks.get(rank).getChallenges() : Collections.emptyList(); } public void completeChallenge(final Player player, String challengeName) { @@ -213,9 +214,15 @@ public boolean tryComplete(final Player player, final String challenge, final St return false; } + /** + * Try to complete a {@link Challenge} for the given {@link Player} where a minimal island level is a requirement. + * @param player Player to complete the challenge for. + * @param challenge Challenge to complete. + * @return True if the challenge was completed succesfully, false otherwise. + */ private boolean tryCompleteIslandLevel(Player player, Challenge challenge) { if (plugin.getIslandInfo(player).getLevel() >= challenge.getRequiredLevel()) { - giveReward(player, challenge.getName()); + giveReward(player, challenge); return true; } return false; @@ -244,12 +251,19 @@ private boolean islandContains(Player player, List itemStacks, int ra return true; } + /** + * Try to complete a {@link Challenge} on the island of the given {@link Player} where items or entities are + * required to be present on the island. + * @param player Player to complete the challenge for. + * @param challengeName Challenge to complete. + * @return True if the challenge was completed succesfully, false otherwise. + */ private boolean tryCompleteOnIsland(Player player, String challengeName) { Challenge challenge = getChallenge(challengeName); List requiredItems = challenge.getRequiredItems(0); int radius = challenge.getRadius(); if (islandContains(player, requiredItems, radius) && hasEntitiesNear(player, challenge.getRequiredEntities(), radius)) { - giveReward(player, challengeName); + giveReward(player, challenge); return true; } return false; @@ -257,7 +271,7 @@ private boolean tryCompleteOnIsland(Player player, String challengeName) { private boolean hasEntitiesNear(Player player, List requiredEntities, int radius) { Map countMap = new LinkedHashMap<>(); - Map> matchMap = new HashMap<>(); + Map> matchMap = new EnumMap<>(EntityType.class); for (EntityMatch match : requiredEntities) { countMap.put(match, match.getCount()); Set set = matchMap.get(match.getType()); @@ -334,10 +348,6 @@ public int getCountOf(Inventory inventory, ItemStack required) { return count; } - public boolean giveReward(final Player player, final String challengeName) { - return giveReward(player, getChallenge(challengeName)); - } - private boolean giveReward(Player player, Challenge challenge) { String challengeName = challenge.getName(); player.sendMessage(tr("\u00a7aYou have completed the {0} challenge!", challenge.getDisplayName())); From 71f3a8e55dc007815e8c9434efec158434412847 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 4 Jun 2020 16:06:46 +0100 Subject: [PATCH 021/190] Use item name instead of id for default challenge display item --- .../ultimateskyblock/challenge/ChallengeDefaults.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java index 0518670be..9c6b80ea1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java @@ -1,10 +1,8 @@ package us.talabrek.ultimateskyblock.challenge; -/** - */ public class ChallengeDefaults { public final int resetInHours; - public final String displayItem = "160:5"; + public final String displayItem = "LIME_STAINED_GLASS_PANE"; public final boolean requiresPreviousRank; public final String repeatableColor; public final String finishedColor; From e7b71c1688bc024b8e84a14ed65972553708e19b Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 7 Jun 2020 23:30:30 +0100 Subject: [PATCH 022/190] Correctly shade our own po-utils version --- pom.xml | 12 ++++++------ uSkyBlock-Core/pom.xml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 9dd1b532f..e020388f9 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,6 @@ ${project.version} 1.23-SNAPSHOT 1.0.3 - 1.2 1.6 1.7 @@ -157,6 +156,12 @@ dk.lockfuglsang.minecraft bukkit-utils ${bukkit-utils.version} + + + dk.lockfuglsang.minecraft + po-utils + + dk.lockfuglsang.minecraft @@ -165,11 +170,6 @@ test tests - - dk.lockfuglsang.minecraft - po-utils - ${po-utils.version} - net.milkbowl.vault VaultAPI diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 165014ab3..036ffb2f8 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -100,7 +100,7 @@ io.papermc:paperlib dk.lockfuglsang.minecraft:bukkit-utils - dk.lockfuglsang.minecraft:po-utils + uSkyBlock:po-utils com.googlecode.json-simple:json-simple From 87e8a6bf1bfc84da975eb8742c41e252830d55a9 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 8 Jun 2020 23:03:13 +0100 Subject: [PATCH 023/190] Make translations overridable by the user with custom po files (#1233) --- .../lockfuglsang/minecraft/po/I18nUtil.java | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java index 2263853c9..e701b9951 100644 --- a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java +++ b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java @@ -10,10 +10,10 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; +import java.util.Optional; import java.util.Properties; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -148,31 +148,42 @@ public static Locale getLocale(@Nullable String lang) { */ public static class I18n { private final Locale locale; - private List props; + private final Properties translations = new Properties(); I18n(Locale locale) { this.locale = locale; - props = new ArrayList<>(); - addPropsFromPluginFolder(); - addPropsFromJar(); - addPropsFromZipInJar(); + + // Order of these calls is important here, because it specifies the priority of the files (git rlf/1233). + addPropertiesFromZipInJar().ifPresent(properties -> { + translations.putAll(properties); + log.log(Level.INFO, "Added {0} translations from ZIP inside JAR.", properties.size()); + }); + addPropertiesFromJar().ifPresent(properties -> { + translations.putAll(properties); + log.log(Level.INFO, "Added {0} translations from the JAR.", properties.size()); + }); + addPropertiesFromPluginFolder().ifPresent(properties -> { + translations.putAll(properties); + log.log(Level.INFO, "Added {0} translations from the plugin directory.", properties.size()); + }); + + log.log(Level.INFO, "Loaded {0} translations.", translations.size()); } - private void addPropsFromJar() { + private Optional addPropertiesFromJar() { try (InputStream in = getClass().getClassLoader().getResourceAsStream("po/" + locale + ".po")) { if (in == null) { - return; - } - Properties i18nProps = POParser.asProperties(in); - if (i18nProps != null && !i18nProps.isEmpty()) { - props.add(i18nProps); + return Optional.empty(); } + Properties properties = POParser.asProperties(in); + return Optional.ofNullable(properties); } catch (IOException e) { log.info("Unable to read translations from po/" + locale + ".po: " + e); } + return Optional.empty(); } - private void addPropsFromZipInJar() { + private Optional addPropertiesFromZipInJar() { // We zip the .po files, since they are currently half the footprint of the jar. try ( InputStream in = getClass().getClassLoader().getResourceAsStream("i18n.zip"); @@ -182,40 +193,36 @@ private void addPropsFromZipInJar() { do { nextEntry = zin != null ? zin.getNextEntry() : null; if (nextEntry != null && nextEntry.getName().equalsIgnoreCase(locale + ".po")) { - Properties i18nProps = POParser.asProperties(zin); - if (i18nProps != null && !i18nProps.isEmpty()) { - props.add(i18nProps); - } + Properties properties = POParser.asProperties(zin); + return Optional.ofNullable(properties); } } while (nextEntry != null); } catch (IOException e) { log.info("Unable to load translations from i18n.zip!" + locale + ".po: " + e); } + return Optional.empty(); } - private void addPropsFromPluginFolder() { + private Optional addPropertiesFromPluginFolder() { File poFile = new File(dataFolder, "i18n" + File.separator + locale + ".po"); if (poFile.exists()) { try (InputStream in = new FileInputStream(poFile)) { - Properties i18nProps = POParser.asProperties(in); - if (i18nProps != null && !i18nProps.isEmpty()) { - props.add(i18nProps); - } + Properties properties = POParser.asProperties(in); + return Optional.ofNullable(properties); } catch (IOException e) { log.info("Unable to load translations from i18n" + File.separator + locale + ".po: " + e); } } + return Optional.empty(); } public String tr(String key, Object... args) { if (key == null || key.trim().isEmpty()) { return ""; } - for (Properties prop : props) { - String propKey = prop.getProperty(key); - if (propKey != null && prop.containsKey(key) && !propKey.trim().isEmpty()) { - return format(propKey, args); - } + String propKey = translations.getProperty(key); + if (propKey != null && !propKey.trim().isEmpty()) { + return format(propKey, args); } return format(key, args); } From 2a8c7720dbb4d80e148b8d86dd18d2ccfb4aebeb Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 10 Jun 2020 01:43:32 +0100 Subject: [PATCH 024/190] Fix Vault economy currencyName NPE --- .../talabrek/ultimateskyblock/hook/economy/VaultEconomy.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java index c6239f676..33d8db3d4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -34,7 +34,10 @@ private Optional setupEconomy() { @Override public @NotNull String getCurrenyName() { - return economy.currencyNamePlural(); + if (economy != null) { + return economy.currencyNamePlural(); + } + return super.getCurrenyName(); } @Override From 1e6131b6a54c2cb09edae5c1600bf583d23521aa Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 1 Jul 2020 13:03:16 +0100 Subject: [PATCH 025/190] Bump Spigot API to 1.16.1 (not compiling!) --- .travis.yml | 5 +--- pom.xml | 32 ++---------------------- uSkyBlock-API/pom.xml | 24 ++++++------------ uSkyBlock-Core/pom.xml | 56 +++++++++++++++++++++--------------------- uSkyBlock-FAWE/pom.xml | 23 +++++++++++++++-- 5 files changed, 59 insertions(+), 81 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9c751d96c..e3b28a166 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,6 @@ sudo: false cache: directories: - "$HOME/.m2" -env: - matrix: - - MC=1.15 git: submodules: false notifications: @@ -18,7 +15,7 @@ before_install: - cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - install: -- mvn -nsu -Dtravis.buildNumber=${TRAVIS_BUILD_NUMBER} -Pi18n,${MC} clean deploy +- mvn -nsu -Dtravis.buildNumber=${TRAVIS_BUILD_NUMBER} -Pi18n clean deploy before_deploy: - echo '|1|DBFhltHRAVmrfmMZPLbN7FwnS5E=|79CP65+tOIeVNeNNC2R680mpV9o= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK/krqsEUrVoDrYIc7I7nsiSCF0M7Xxr379IqZ2pLUPlxF2Or/MkTTokXzRsyspJazL1W1UrBDmKXHfO6+tyMMw=' diff --git a/pom.xml b/pom.xml index e020388f9..ccdcbfa24 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 19.0.0 ${project.version} 1.23-SNAPSHOT - 1.0.3 + 1.0.4 1.6 1.7 @@ -122,34 +122,6 @@ https://www.uskyblock.ovh/maven/dependencies/ - - - 1.15 - - true - - - - com.sk89q.worldedit - worldedit-bukkit - 7.0.1 - provided - - - com.sk89q.worldguard - worldguard-bukkit - 7.0.1 - provided - - - com.sk89q - worldedit - - - - - - @@ -213,4 +185,4 @@ - \ No newline at end of file + diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 068955421..30c6c8c1e 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -27,6 +27,13 @@ + + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT + provided + + org.jetbrains annotations @@ -69,21 +76,4 @@ - - - 1.15 - - true - - - - org.bukkit - bukkit - 1.15.2-R0.1-SNAPSHOT - true - compile - - - - \ No newline at end of file diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 036ffb2f8..30aaac00b 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -98,7 +98,6 @@ org.bstats:* io.papermc:paperlib - dk.lockfuglsang.minecraft:bukkit-utils uSkyBlock:po-utils com.googlecode.json-simple:json-simple @@ -117,10 +116,6 @@ io.papermc.lib us.talabrek.ultimateskyblock.paperlib - - - - @@ -167,7 +162,7 @@ org.apache.maven.plugins maven-javadoc-plugin - private + public false none @@ -221,21 +216,6 @@ - - 1.15 - - true - - - - org.bukkit - bukkit - 1.15.2-R0.1-SNAPSHOT - true - compile - - - i18n @@ -353,19 +333,19 @@ true + + + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT + provided + io.papermc paperlib compile - - - - - - - com.onarandombox.multiversecore @@ -393,6 +373,26 @@ + + + com.sk89q.worldedit + worldedit-bukkit + 7.0.1 + provided + + + + com.sk89q.worldguard + worldguard-bukkit + 7.0.1 + provided + + + com.sk89q + worldedit + + + org.bstats diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 1ab737b07..f9a6207f9 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -39,6 +39,26 @@ true compile + + + com.sk89q.worldedit + worldedit-bukkit + 7.0.1 + provided + + + + com.sk89q.worldguard + worldguard-bukkit + 7.0.1 + provided + + + com.sk89q + worldedit + + + @@ -82,9 +102,8 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 - private + public false none From 5b36a248d5f975420f8e30f663eda310c0b303b2 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 1 Jul 2020 13:27:27 +0100 Subject: [PATCH 026/190] Make it compile on 1.16.1 --- .../talabrek/ultimateskyblock/command/island/BiomeCommand.java | 2 +- .../us/talabrek/ultimateskyblock/world/ChunkRegenerator.java | 2 +- .../ultimateskyblock/world/SkyBlockNetherChunkGenerator.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index 51537754e..8da9386a0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -26,7 +26,7 @@ public class BiomeCommand extends RequireIslandCommand { { put("ocean", Biome.OCEAN); put("jungle", Biome.JUNGLE); - put("hell", Biome.NETHER); + put("hell", Biome.NETHER_WASTES); put("sky", Biome.THE_END); put("mushroom", Biome.MUSHROOM_FIELDS); put("swampland", Biome.SWAMP); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java index 36056a38a..0a514556f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java @@ -123,7 +123,7 @@ static class DefaultBiomeGrid implements BiomeGrid { defaultBiome = Biome.THE_END; break; case NETHER: - defaultBiome = Biome.NETHER; + defaultBiome = Biome.NETHER_WASTES; break; default: defaultBiome = Biome.OCEAN; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java index 2871e200a..24cc648c8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java @@ -21,7 +21,7 @@ public ChunkData generateChunkData(World world, Random random, int cx, int cz, B for (int x = 0; x <= 15; x++) { for (int z = 0; z <= 15; z++) { for (int y = 0; y < world.getMaxHeight(); y++) { - biome.setBiome(x, y, z, Biome.NETHER); + biome.setBiome(x, y, z, Biome.NETHER_WASTES); } } } From a450c28c4559b2694b0cfcdfdfc7bee5ec5f3cd8 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 1 Jul 2020 14:29:26 +0100 Subject: [PATCH 027/190] It worked on my machine -- welcome to Minecraft dependency land, fun for the whole family! --- uSkyBlock-Core/pom.xml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 30aaac00b..7fb47b0a2 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -332,13 +332,13 @@ VaultAPI true - org.spigotmc spigot-api 1.16.1-R0.1-SNAPSHOT provided + true @@ -379,6 +379,12 @@ worldedit-bukkit 7.0.1 provided + + + org.bukkit + bukkit + + @@ -391,6 +397,10 @@ com.sk89q worldedit + + org.bukkit + bukkit + @@ -413,6 +423,12 @@ ActionBarAPI 1.5.4 provided + + + org.bukkit + bukkit + + be.maximvdw From 503675293d0f6bfb452a59ec2dcbfe38a062e4b1 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 1 Jul 2020 14:42:52 +0100 Subject: [PATCH 028/190] Please? --- pom.xml | 12 ++++++++++++ uSkyBlock-Core/pom.xml | 23 +++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index ccdcbfa24..927027ea0 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,10 @@ dk.lockfuglsang.minecraft po-utils + + org.bukkit + bukkit + @@ -185,4 +189,12 @@ + + + 1.16 + + true + + + diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 7fb47b0a2..ad3c26d81 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -216,6 +216,21 @@ + + 1.16 + + true + + + + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT + compile + true + + + i18n @@ -332,14 +347,6 @@ VaultAPI true - - - org.spigotmc - spigot-api - 1.16.1-R0.1-SNAPSHOT - provided - true - io.papermc From 5fb8abf9c46c38a0070e6444a84e2d53ed52a83e Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 1 Jul 2020 20:05:13 +0100 Subject: [PATCH 029/190] Dependency horror on 1.16 (#1262) * It worked on my machine -- welcome to Minecraft dependency land, fun for the whole family! --- pom.xml | 10 ++++++++++ uSkyBlock-API/pom.xml | 1 + uSkyBlock-Core/pom.xml | 19 ++++++++++++++++++- uSkyBlock-FAWE/pom.xml | 18 ++++++++++++++---- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index ccdcbfa24..9796ea476 100644 --- a/pom.xml +++ b/pom.xml @@ -133,6 +133,10 @@ dk.lockfuglsang.minecraft po-utils + + org.bukkit + bukkit + @@ -147,6 +151,12 @@ VaultAPI true ${vault.version} + + + org.bukkit + bukkit + + com.github.rlf diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 30c6c8c1e..c83d1e63c 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -32,6 +32,7 @@ spigot-api 1.16.1-R0.1-SNAPSHOT provided + true diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 30aaac00b..6a86de270 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -330,15 +330,16 @@ net.milkbowl.vault VaultAPI + provided true - org.spigotmc spigot-api 1.16.1-R0.1-SNAPSHOT provided + true @@ -379,6 +380,12 @@ worldedit-bukkit 7.0.1 provided + + + org.bukkit + bukkit + + @@ -391,6 +398,10 @@ com.sk89q worldedit + + org.bukkit + bukkit + @@ -413,6 +424,12 @@ ActionBarAPI 1.5.4 provided + + + org.bukkit + bukkit + + be.maximvdw diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index f9a6207f9..6bedc11d4 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -33,11 +33,11 @@ uSkyBlock-Core - org.bukkit - bukkit - 1.13.2-R0.1-SNAPSHOT + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT true - compile + provided @@ -45,6 +45,12 @@ worldedit-bukkit 7.0.1 provided + + + org.bukkit + bukkit + + @@ -53,6 +59,10 @@ 7.0.1 provided + + org.bukkit + bukkit + com.sk89q worldedit From c986e29334c51f5cb4b6789e8cd11f5ccdcaceed Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 1 Jul 2020 20:05:13 +0100 Subject: [PATCH 030/190] Dependency horror on 1.16 (#1262) * It worked on my machine -- welcome to Minecraft dependency land, fun for the whole family! --- pom.xml | 14 ++++++-------- uSkyBlock-API/pom.xml | 1 + uSkyBlock-Core/pom.xml | 24 +++++++++--------------- uSkyBlock-FAWE/pom.xml | 18 ++++++++++++++---- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 927027ea0..9796ea476 100644 --- a/pom.xml +++ b/pom.xml @@ -151,6 +151,12 @@ VaultAPI true ${vault.version} + + + org.bukkit + bukkit + + com.github.rlf @@ -189,12 +195,4 @@ - - - 1.16 - - true - - - diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 30c6c8c1e..c83d1e63c 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -32,6 +32,7 @@ spigot-api 1.16.1-R0.1-SNAPSHOT provided + true diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index ad3c26d81..6a86de270 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -216,21 +216,6 @@ - - 1.16 - - true - - - - org.spigotmc - spigot-api - 1.16.1-R0.1-SNAPSHOT - compile - true - - - i18n @@ -345,6 +330,15 @@ net.milkbowl.vault VaultAPI + provided + true + + + + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT + provided true diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index f9a6207f9..6bedc11d4 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -33,11 +33,11 @@ uSkyBlock-Core - org.bukkit - bukkit - 1.13.2-R0.1-SNAPSHOT + org.spigotmc + spigot-api + 1.16.1-R0.1-SNAPSHOT true - compile + provided @@ -45,6 +45,12 @@ worldedit-bukkit 7.0.1 provided + + + org.bukkit + bukkit + + @@ -53,6 +59,10 @@ 7.0.1 provided + + org.bukkit + bukkit + com.sk89q worldedit From 23a517fa809bd5b6ae413fd3a667b555db55645d Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 2 Jul 2020 13:55:56 +0100 Subject: [PATCH 031/190] Update README to 1.16, api-version to 1.16 --- README.md | 2 +- uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe0c1e795..bc730e29a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ We are on [Spigot](https://www.spigotmc.org/resources/uskyblock-revived.66795/). This version depends on the following plugins: -* Bukkit/Spigot 1.15.1-R0.1-SNAPSHOT +* Spigot/Paper 1.16.1-R0.1-SNAPSHOT * Vault 1.7.x * WorldEdit 7.1.0-SNAPSHOT * WorldGuard 7.0.2-SNAPSHOT diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index eccbd1409..066f8ce41 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -17,7 +17,7 @@ softdepend: - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.15 +api-version: 1.16 commands: challenges: From ddf4216afda66f081f95aedbe34f1d69a984785a Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 2 Jul 2020 14:14:44 +0100 Subject: [PATCH 032/190] Update WorldEdit, WorldGuard to their 1.16.1 releases --- pom.xml | 3 +++ uSkyBlock-Core/pom.xml | 10 +++------- uSkyBlock-FAWE/pom.xml | 21 ++------------------- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index 9796ea476..b4818fda2 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,10 @@ 1.23-SNAPSHOT 1.0.4 1.6 + 1.16.1-R0.1-SNAPSHOT 1.7 + 7.2.0-SNAPSHOT + 7.0.4-SNAPSHOT UTF-8 ${project.artifactId} diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 6a86de270..97171889a 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -337,7 +337,7 @@ org.spigotmc spigot-api - 1.16.1-R0.1-SNAPSHOT + ${spigotapi.version} provided true @@ -378,7 +378,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.0.1 + ${worldedit.version} provided @@ -391,17 +391,13 @@ com.sk89q.worldguard worldguard-bukkit - 7.0.1 + ${worldguard.version} provided com.sk89q worldedit - - org.bukkit - bukkit - diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 6bedc11d4..6be812c0a 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -35,7 +35,7 @@ org.spigotmc spigot-api - 1.16.1-R0.1-SNAPSHOT + ${spigotapi.version} true provided @@ -43,7 +43,7 @@ com.sk89q.worldedit worldedit-bukkit - 7.0.1 + ${worldedit.version} provided @@ -52,23 +52,6 @@ - - - com.sk89q.worldguard - worldguard-bukkit - 7.0.1 - provided - - - org.bukkit - bukkit - - - com.sk89q - worldedit - - - From c4046d686cb691e67c104d5926c451c996a8de5f Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 12 Jul 2020 15:42:16 +0100 Subject: [PATCH 033/190] Accept all types of signs for USB signs --- .../ultimateskyblock/menu/SkyBlockMenu.java | 3 -- .../ultimateskyblock/signs/SignEvents.java | 54 ++++++------------- .../ultimateskyblock/signs/SignLogic.java | 7 +-- 3 files changed, 19 insertions(+), 45 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index e66d870c9..a81e0e46d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -46,9 +46,6 @@ public class SkyBlockMenu { public static final Material SIGN_MATERIAL = Material.getMaterial("SIGN") == null ? Material.getMaterial("OAK_SIGN") : Material.getMaterial("SIGN"); - public static final Material WALL_SIGN_MATERIAL = Material.getMaterial("WALL_SIGN") == null - ? Material.getMaterial("OAK_WALL_SIGN") - : Material.getMaterial("WALL_SIGN"); private final Pattern PERM_VALUE_PATTERN = Pattern.compile("(\\[(?(?[!])?[^\\]]+)\\])?(?.*)"); private final Pattern CHALLENGE_PAGE_HEADER = Pattern.compile(tr("Challenge Menu") + ".*\\((?

[0-9]+)/(?[0-9]+)\\)"); private uSkyBlock plugin; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java index 28362b24b..b1d4664c2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java @@ -20,16 +20,12 @@ import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerInteractEvent; -import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.logging.Logger; - /** * Handles USB Signs */ public class SignEvents implements Listener { - private static final Logger log = Logger.getLogger(SignEvents.class.getName()); private final uSkyBlock plugin; private final SignLogic logic; @@ -41,11 +37,9 @@ public SignEvents(uSkyBlock plugin, SignLogic logic) { @EventHandler(priority = EventPriority.HIGH) public void onPlayerHitSign(PlayerInteractEvent e) { if (e.isCancelled() - || e.getPlayer() == null || (e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.LEFT_CLICK_BLOCK) || e.getClickedBlock() == null - || e.getClickedBlock().getType() != SkyBlockMenu.WALL_SIGN_MATERIAL - || !(e.getClickedBlock().getState() instanceof Sign) + || !(e.getClickedBlock().getState().getBlockData() instanceof WallSign) || !e.getPlayer().hasPermission("usb.island.signs.use") || !plugin.getWorldManager().isSkyAssociatedWorld(e.getPlayer().getWorld()) || !(plugin.playerIsOnOwnIsland(e.getPlayer())) @@ -59,21 +53,19 @@ public void onPlayerHitSign(PlayerInteractEvent e) { } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onSignChanged(SignChangeEvent e) { - if (e.isCancelled() || e.getPlayer() == null - || !plugin.getWorldManager().isSkyAssociatedWorld(e.getPlayer().getWorld()) + if (!plugin.getWorldManager().isSkyAssociatedWorld(e.getPlayer().getWorld()) || !e.getLines()[0].equalsIgnoreCase("[usb]") || e.getLines()[1].trim().isEmpty() || !e.getPlayer().hasPermission("usb.island.signs.place") - || !(e.getBlock().getType() == SkyBlockMenu.WALL_SIGN_MATERIAL) || !(e.getBlock().getState() instanceof Sign) ) { return; } Sign sign = (Sign) e.getBlock().getState(); - if(sign.getBlock().getState().getBlockData() instanceof WallSign) { + if (sign.getBlock().getState().getBlockData() instanceof WallSign) { WallSign data = (WallSign) sign.getBlock().getState().getBlockData(); BlockFace attached = data.getFacing().getOppositeFace(); Block wallBlock = sign.getBlock().getRelative(attached); @@ -91,8 +83,7 @@ private boolean isChest(Block wallBlock) { @EventHandler(priority = EventPriority.MONITOR) public void onInventoryMovedEvent(InventoryMoveItemEvent e) { - if (e.getDestination() == null - || e.getDestination().getLocation() == null + if (e.getDestination().getLocation() == null || !plugin.getWorldManager().isSkyAssociatedWorld(e.getDestination().getLocation().getWorld())) { return; } @@ -112,9 +103,7 @@ public void onInventoryMovedEvent(InventoryMoveItemEvent e) { @EventHandler(priority = EventPriority.MONITOR) public void onChestClosed(InventoryCloseEvent e) { - if (e.getPlayer() == null - || e.getPlayer().getLocation() == null - || !plugin.getWorldManager().isSkyAssociatedWorld(e.getPlayer().getLocation().getWorld()) + if (!plugin.getWorldManager().isSkyAssociatedWorld(e.getPlayer().getLocation().getWorld()) || e.getInventory().getType() != InventoryType.CHEST ) { return; @@ -125,47 +114,38 @@ public void onChestClosed(InventoryCloseEvent e) { } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onSignOrChestBreak(BlockBreakEvent e) { - if (e.isCancelled() - || e.getBlock() == null - || (e.getBlock().getType() != SkyBlockMenu.WALL_SIGN_MATERIAL && !(e.getBlock().getType() == Material.CHEST || e.getBlock().getType() == Material.TRAPPED_CHEST)) - || e.getBlock().getLocation() == null + if ((!(e.getBlock().getState().getBlockData() instanceof WallSign) && + !(e.getBlock().getType() == Material.CHEST || e.getBlock().getType() == Material.TRAPPED_CHEST)) || !plugin.getWorldManager().isSkyAssociatedWorld(e.getBlock().getLocation().getWorld()) ) { return; } - if (e.getBlock().getType() == SkyBlockMenu.WALL_SIGN_MATERIAL) { + if (e.getBlock().getState().getBlockData() instanceof WallSign) { logic.removeSign(e.getBlock().getLocation()); } else { logic.removeChest(e.getBlock().getLocation()); } } - private boolean isSign(Material material) { - return material == SkyBlockMenu.WALL_SIGN_MATERIAL || material == SkyBlockMenu.SIGN_MATERIAL; - } - @EventHandler(priority = EventPriority.HIGHEST) public void onBlockHit(PlayerInteractEvent e) { Player player = e.getPlayer(); - if (e.getPlayer() == null - || e.getClickedBlock() == null + if (e.getClickedBlock() == null || e.getAction() != Action.RIGHT_CLICK_BLOCK || e.getPlayer().getGameMode() != GameMode.SURVIVAL - || !isSign(e.getClickedBlock().getType()) + || !(e.getClickedBlock().getState() instanceof Sign) || !player.hasPermission("usb.island.signs.use") || !plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld())) { return; } - if (e.getClickedBlock().getState() instanceof Sign) { - Sign sign = (Sign) e.getClickedBlock().getState(); - String firstLine = FormatUtil.stripFormatting(sign.getLine(0)).trim(); - if (firstLine.startsWith("/")) { - e.setCancelled(true); - player.performCommand(firstLine.substring(1)); - } + Sign sign = (Sign) e.getClickedBlock().getState(); + String firstLine = FormatUtil.stripFormatting(sign.getLine(0)).trim(); + if (firstLine.startsWith("/")) { + e.setCancelled(true); + player.performCommand(firstLine.substring(1)); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java index c3bf54037..0bfa04f64 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java @@ -8,6 +8,7 @@ import org.bukkit.block.BlockState; import org.bukkit.block.Chest; import org.bukkit.block.Sign; +import org.bukkit.block.data.type.WallSign; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -16,7 +17,6 @@ import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; -import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -204,10 +204,7 @@ private void updateSignAsync(final Location chestLoc, String islandName, String private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challenge challenge, List requiredItems, boolean challengeLocked) { Block chestBlock = chestLoc.getBlock(); Block signBlock = signLoc != null ? signLoc.getBlock() : null; - if (chestBlock != null && signBlock != null - && isChest(chestBlock) - && signBlock.getType() == SkyBlockMenu.WALL_SIGN_MATERIAL && signBlock.getState() instanceof Sign - ) { + if (signBlock != null && isChest(chestBlock) && signBlock.getState().getBlockData() instanceof WallSign) { Sign sign = (Sign) signBlock.getState(); Chest chest = (Chest) chestBlock.getState(); int missing = -1; From 7da75c853f8591ec438bcb554681b789ee6fe767 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 16 Jul 2020 13:05:18 +0100 Subject: [PATCH 034/190] Remove obsolete checks for oak sign materialname in gui --- .../ultimateskyblock/menu/SkyBlockMenu.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index a81e0e46d..55542c7b0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -43,14 +43,11 @@ * The UI menu of uSkyBlock (using the inventory UI). */ public class SkyBlockMenu { - public static final Material SIGN_MATERIAL = Material.getMaterial("SIGN") == null - ? Material.getMaterial("OAK_SIGN") - : Material.getMaterial("SIGN"); private final Pattern PERM_VALUE_PATTERN = Pattern.compile("(\\[(?(?[!])?[^\\]]+)\\])?(?.*)"); private final Pattern CHALLENGE_PAGE_HEADER = Pattern.compile(tr("Challenge Menu") + ".*\\((?

[0-9]+)/(?[0-9]+)\\)"); private uSkyBlock plugin; private final ChallengeLogic challengeLogic; - private ItemStack sign = new ItemStack(SIGN_MATERIAL, 1); + private ItemStack sign = new ItemStack(Material.OAK_SIGN, 1); private ItemStack biome = new ItemStack(Material.JUNGLE_SAPLING, 1); private ItemStack lock = new ItemStack(Material.IRON_BARS, 1); private ItemStack warpset = new ItemStack(Material.END_PORTAL_FRAME, 1); @@ -967,7 +964,7 @@ public Inventory createRestartGUI(Player player) { String title = "\u00a79" + tr("Island Restart Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); List lores = new ArrayList<>(); - ItemStack menuItem = new ItemStack(SIGN_MATERIAL, 1); + ItemStack menuItem = new ItemStack(Material.OAK_SIGN, 1); ItemMeta meta = menuItem.getItemMeta(); meta.setDisplayName(tr("\u00a7a\u00a7lReturn to the main menu")); meta.setLore(lores); @@ -1091,7 +1088,7 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, if (slotIndex < 0 || slotIndex > 35) { return; } - if (slotIndex == 0 && currentItem.getType() == SIGN_MATERIAL) { + if (slotIndex == 0 && currentItem.getType() == Material.OAK_SIGN) { p.closeInventory(); p.performCommand("island"); return; @@ -1152,7 +1149,7 @@ private void onClickPermissionMenu(InventoryClickEvent event, ItemStack currentI return; } } - if (currentItem.getType() == SIGN_MATERIAL) { + if (currentItem.getType() == Material.OAK_SIGN) { p.closeInventory(); p.openInventory(displayPartyGUI(p)); } else { @@ -1166,7 +1163,7 @@ private void onClickPartyMenu(InventoryClickEvent event, ItemStack currentItem, if (slotIndex < 0 || slotIndex > 35) { return; } - if (meta == null || currentItem.getType() == SIGN_MATERIAL) { + if (meta == null || currentItem.getType() == Material.OAK_SIGN) { p.closeInventory(); p.performCommand("island"); } else if (skull != null && plugin.getIslandInfo(p).isLeader(p)) { From 0e91bc9184b1650f31a95076d35c79ac16322a6b Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 21 Jul 2020 23:58:20 +0100 Subject: [PATCH 035/190] Delay Multiverse world add and spawn creation to prevent Paper watchdog warnings on first startup --- .../handler/MultiverseCoreHandler.java | 88 ------------------ .../ultimateskyblock/hook/HookManager.java | 30 +++++++ .../hook/world/MultiverseHook.java | 90 +++++++++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 4 + .../ultimateskyblock/world/WorldManager.java | 21 +++-- 5 files changed, 139 insertions(+), 94 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java deleted file mode 100644 index 0c20900a7..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseCoreHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import com.onarandombox.MultiverseCore.MultiverseCore; -import com.onarandombox.MultiverseCore.api.MultiverseWorld; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.WorldType; -import org.bukkit.plugin.Plugin; -import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.util.LocationUtil; - -import static us.talabrek.ultimateskyblock.util.LocationUtil.centerOnBlock; - -/** - * Wrapper for the MVCore plugin. - */ -public enum MultiverseCoreHandler {; - public static MultiverseCore getMultiverseCore() { - Plugin plugin = Bukkit.getPluginManager().getPlugin("Multiverse-Core"); - if (plugin instanceof MultiverseCore) { - return (MultiverseCore)plugin; - } - return null; - } - - public static boolean hasMultiverse() { - Plugin plugin = Bukkit.getPluginManager().getPlugin("Multiverse-Core"); - return plugin != null && plugin.isEnabled(); - } - - public static void importWorld(World skyWorld) { - MultiverseCore core = getMultiverseCore(); - if (core != null) { - Location worldSpawn = new Location(skyWorld, 0.5, Settings.island_height + 0.1, 0.5); - if (!core.getMVWorldManager().isMVWorld(skyWorld)) { - core.getMVWorldManager().addWorld(skyWorld.getName(), World.Environment.NORMAL, "0", WorldType.NORMAL, false, "uSkyBlock", false); - } - MultiverseWorld mvWorld = core.getMVWorldManager().getMVWorld(skyWorld); - mvWorld.setEnvironment(World.Environment.NORMAL); - mvWorld.setScaling(1); - mvWorld.setGenerator("uSkyBlock"); - if (Settings.general_spawnSize > 0) { - if (LocationUtil.isEmptyLocation(mvWorld.getSpawnLocation())) { - mvWorld.setAdjustSpawn(false); - Location spawn = centerOnBlock(worldSpawn); - mvWorld.setSpawnLocation(spawn); - skyWorld.setSpawnLocation(spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()); - } - } - if (!Settings.extras_sendToSpawn) { - mvWorld.setRespawnToWorld(mvWorld.getName()); - } - } else if (hasMultiverse()) { - if (!Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mv import " + skyWorld.getName() + " NORMAL -g uSkyBlock")) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mv import " + skyWorld.getName() + " NORMAL uSkyBlock"); - } - } - } - - public static void importNetherWorld(World skyNetherWorld) { - MultiverseCore core = getMultiverseCore(); - if (core != null) { - Location worldSpawn = new Location(skyNetherWorld, 0.5, Settings.island_height/2.0 + 0.1, 0.5); - if (!core.getMVWorldManager().isMVWorld(skyNetherWorld)) { - core.getMVWorldManager().addWorld(skyNetherWorld.getName(), World.Environment.NETHER, "0", WorldType.NORMAL, false, "uSkyBlock", false); - } - MultiverseWorld mvWorld = core.getMVWorldManager().getMVWorld(skyNetherWorld); - mvWorld.setEnvironment(World.Environment.NETHER); - mvWorld.setScaling(1.0); - mvWorld.setGenerator("uSkyBlock"); - if (Settings.general_spawnSize > 0) { - if (LocationUtil.isEmptyLocation(mvWorld.getSpawnLocation())) { - mvWorld.setAdjustSpawn(false); - mvWorld.setSpawnLocation(centerOnBlock(worldSpawn)); - skyNetherWorld.setSpawnLocation(worldSpawn.getBlockX(), worldSpawn.getBlockY(), worldSpawn.getBlockZ()); - } - } - if (!Settings.extras_sendToSpawn) { - mvWorld.setRespawnToWorld(Settings.general_worldName); - } - } else if (hasMultiverse()) { - if (!Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mv import " + skyNetherWorld.getName() + " NETHER -g uSkyBlock")) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mv import " + skyNetherWorld.getName() + " NETHER uSkyBlock"); - } - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java index b3a90632f..27d79aa91 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java @@ -5,6 +5,7 @@ import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; import us.talabrek.ultimateskyblock.hook.permissions.PermissionsHook; import us.talabrek.ultimateskyblock.hook.permissions.VaultPermissions; +import us.talabrek.ultimateskyblock.hook.world.MultiverseHook; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.ArrayList; @@ -38,6 +39,14 @@ public Optional getEconomyHook() { return Optional.ofNullable((EconomyHook) getHook("Economy").orElse(null)); } + /** + * Short method for {@link #getHook(String)} to get the optional {@link MultiverseHook}. + * @return optional of MultiverseHook. + */ + public Optional getMultiverse() { + return Optional.ofNullable((MultiverseHook) getHook("Multiverse").orElse(null)); + } + /** * Short method for {@link #getHook(String)} to get the optional {@link PermissionsHook}. * @return optional of PermissionsHook. @@ -78,6 +87,27 @@ public boolean setupEconomyHook() { return false; } + /** + * Checks and hooks into Multiverse-Core. + * @return True if hooking succeeded, false otherwise. + */ + public boolean setupMultiverse() { + try { + if (plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Core")) { + MultiverseHook mvHook = new MultiverseHook(plugin); + registerHook(mvHook); + plugin.getLogger().info("Hooked into Multiverse-Core"); + return true; + } + } catch (HookFailedException ex) { + plugin.getLogger().warning("Failed to hook into Multiverse-Core"); + ex.printStackTrace(); + } + + plugin.getLogger().warning("Failed to find Multiverse-Core. Multiworld support will be limited."); + return false; + } + /** * Checks and hooks if there are compatible Permissions plugins available. * @return True if a compatible Permissions plugin has geen found and hooking succeeded, false otherwise. diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java new file mode 100644 index 000000000..3e1502226 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java @@ -0,0 +1,90 @@ +package us.talabrek.ultimateskyblock.hook.world; + +import com.onarandombox.MultiverseCore.MultiverseCore; +import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.WorldType; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.hook.PluginHook; +import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.LocationUtil; + +import java.util.Optional; + +public class MultiverseHook extends PluginHook { + private MultiverseCore mvCore; + + private static final String GENERATOR_NAME = "uSkyBlock"; + + public MultiverseHook(@NotNull uSkyBlock plugin) { + super(plugin, "Multiverse", "Multiverse"); + setupCore().ifPresent(mvPlugin -> this.mvCore = mvPlugin); + } + + private Optional setupCore() { + Plugin mvPlugin = plugin.getServer().getPluginManager().getPlugin("Multiverse-Core"); + if (mvPlugin instanceof MultiverseCore) { + return Optional.of((MultiverseCore) mvPlugin); + } + + return Optional.empty(); + } + + /** + * Registers the given {@link World} to {@link MultiverseCore} as the skyblock overworld (skyworld). + * @param world World to register. + */ + public void registerOverworld(@NotNull World world) { + if (!mvCore.getMVWorldManager().isMVWorld(world)) { + mvCore.getMVWorldManager().addWorld(world.getName(), World.Environment.NORMAL, + "0", WorldType.NORMAL, false, GENERATOR_NAME, false); + } + + MultiverseWorld mvWorld = mvCore.getMVWorldManager().getMVWorld(world); + mvWorld.setEnvironment(World.Environment.NORMAL); + mvWorld.setScaling(1.0); + mvWorld.setGenerator(GENERATOR_NAME); + + if (Settings.general_spawnSize > 0 && LocationUtil.isEmptyLocation(mvWorld.getSpawnLocation())) { + Location spawn = LocationUtil.centerOnBlock( + new Location(world, 0.5, Settings.island_height + 0.1, 0.5)); + mvWorld.setAdjustSpawn(false); + mvWorld.setSpawnLocation(spawn); + world.setSpawnLocation(spawn); + } + + if (!Settings.extras_sendToSpawn) { + mvWorld.setRespawnToWorld(mvWorld.getName()); + } + } + + /** + * Registers the given {@link World} to {@link MultiverseCore} as the skyblock nether world (skyworld_nether). + * @param world World to register. + */ + public void registerNetherworld(@NotNull World world) { + if (!mvCore.getMVWorldManager().isMVWorld(world)) { + mvCore.getMVWorldManager().addWorld(world.getName(), World.Environment.NETHER, + "0", WorldType.NORMAL, false, GENERATOR_NAME, false); + } + + MultiverseWorld mvWorld = mvCore.getMVWorldManager().getMVWorld(world); + mvWorld.setEnvironment(World.Environment.NETHER); + mvWorld.setScaling(1.0); + mvWorld.setGenerator(GENERATOR_NAME); + if (Settings.general_spawnSize > 0 && LocationUtil.isEmptyLocation(mvWorld.getSpawnLocation())) { + Location spawn = LocationUtil.centerOnBlock( + new Location(world, 0.5, Settings.island_height/2.0 + 0.1, 0.5)); + mvWorld.setAdjustSpawn(false); + mvWorld.setSpawnLocation(spawn); + world.setSpawnLocation(spawn); + } + + if (!Settings.extras_sendToSpawn) { + mvWorld.setRespawnToWorld(plugin.getWorldManager().getWorld().getName()); + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 10720ea0d..8da8f13c4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -59,9 +59,11 @@ import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; +import us.talabrek.ultimateskyblock.handler.MultiverseInventoriesHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; +import us.talabrek.ultimateskyblock.hook.world.MultiverseHook; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandGenerator; @@ -109,6 +111,7 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +import static us.talabrek.ultimateskyblock.Settings.island_height; import static us.talabrek.ultimateskyblock.util.LocationUtil.isSafeLocation; import static us.talabrek.ultimateskyblock.util.LogUtil.log; @@ -216,6 +219,7 @@ public void run() { if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { return; } + uSkyBlock.this.getHookManager().setupMultiverse(); uSkyBlock.this.getHookManager().setupEconomyHook(); uSkyBlock.this.getHookManager().setupPermissionsHook(); AsyncWorldEditHandler.onEnable(uSkyBlock.this); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index 6cb567469..d765e4595 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -17,7 +17,6 @@ import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; -import us.talabrek.ultimateskyblock.handler.MultiverseCoreHandler; import us.talabrek.ultimateskyblock.handler.MultiverseInventoriesHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; @@ -204,9 +203,14 @@ public synchronized World getWorld() { .createWorld(); skyBlockWorld.save(); } - MultiverseCoreHandler.importWorld(skyBlockWorld); - setupWorld(skyBlockWorld, island_height); } + + plugin.getServer().getScheduler().runTaskLater(plugin, () -> + plugin.getHookManager().getMultiverse().ifPresent(hook -> { + hook.registerOverworld(skyBlockWorld); + setupWorld(skyBlockWorld, Settings.island_height); + }), plugin.getConfig().getLong("init.initDelay", 50L) + 40L); + return skyBlockWorld; } @@ -234,10 +238,15 @@ public synchronized World getNetherWorld() { .createWorld(); skyBlockNetherWorld.save(); } - MultiverseCoreHandler.importNetherWorld(skyBlockNetherWorld); - setupWorld(skyBlockNetherWorld, island_height / 2); - MultiverseInventoriesHandler.linkWorlds(getWorld(), skyBlockNetherWorld); } + + plugin.getServer().getScheduler().runTaskLater(plugin, () -> + plugin.getHookManager().getMultiverse().ifPresent(hook -> { + hook.registerNetherworld(skyBlockNetherWorld); + setupWorld(skyBlockNetherWorld, island_height / 2); + MultiverseInventoriesHandler.linkWorlds(getWorld(), skyBlockNetherWorld); + }), plugin.getConfig().getLong("init.initDelay", 50L) + 100L); + return skyBlockNetherWorld; } From c56855fcc2c1544f068309a1c8b68601aa7cc187 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 22 Jul 2020 16:58:42 +0100 Subject: [PATCH 036/190] Move MV-Inventories to new MultiverseHook --- .../handler/MultiverseInventoriesHandler.java | 19 -------- .../MultiverseInventoriesAdaptor.java | 30 ------------- .../hook/world/MultiverseHook.java | 45 +++++++++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 2 - .../ultimateskyblock/world/WorldManager.java | 2 - uSkyBlock-Core/src/main/resources/plugin.yml | 5 ++- 6 files changed, 48 insertions(+), 55 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseInventoriesHandler.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/multiverseinventories/MultiverseInventoriesAdaptor.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseInventoriesHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseInventoriesHandler.java deleted file mode 100644 index 405765457..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/MultiverseInventoriesHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import org.bukkit.Bukkit; -import org.bukkit.World; -import us.talabrek.ultimateskyblock.handler.multiverseinventories.MultiverseInventoriesAdaptor; - -/** - * Handler for accessing Multiverse-Inventories, if enabled. - */ -public enum MultiverseInventoriesHandler {; - public static void linkWorlds(World... worlds) { - if (isMVInv()) { - MultiverseInventoriesAdaptor.linkWorlds(worlds); - } - } - public static boolean isMVInv() { - return Bukkit.getPluginManager().isPluginEnabled("Multiverse-Inventories"); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/multiverseinventories/MultiverseInventoriesAdaptor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/multiverseinventories/MultiverseInventoriesAdaptor.java deleted file mode 100644 index 34bd8e3ed..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/multiverseinventories/MultiverseInventoriesAdaptor.java +++ /dev/null @@ -1,30 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.multiverseinventories; - -import com.onarandombox.multiverseinventories.MultiverseInventories; -import com.onarandombox.multiverseinventories.WorldGroup; -import com.onarandombox.multiverseinventories.profile.WorldGroupManager; -import com.onarandombox.multiverseinventories.share.Sharables; -import org.bukkit.Bukkit; -import org.bukkit.World; - -/** - * Adaptor, so we don't need to rely on MVInv on runtime. - */ -public class MultiverseInventoriesAdaptor { - public static void linkWorlds(World... worlds) { - WorldGroupManager groupManager = getMVInv().getGroupManager(); - WorldGroup worldGroup = groupManager.getGroup("skyblock"); - if (worldGroup == null) { - worldGroup = groupManager.newEmptyGroup("skyblock"); - worldGroup.getShares().addAll(Sharables.ALL_DEFAULT); - } - for (World world : worlds) { - worldGroup.addWorld(world); - } - groupManager.updateGroup(worldGroup); - } - - public static MultiverseInventories getMVInv() { - return (MultiverseInventories) Bukkit.getPluginManager().getPlugin("Multiverse-Inventories"); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java index 3e1502226..3be9643dd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java @@ -2,6 +2,10 @@ import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.onarandombox.multiverseinventories.MultiverseInventories; +import com.onarandombox.multiverseinventories.WorldGroup; +import com.onarandombox.multiverseinventories.profile.WorldGroupManager; +import com.onarandombox.multiverseinventories.share.Sharables; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.WorldType; @@ -12,32 +16,50 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import java.util.Arrays; import java.util.Optional; public class MultiverseHook extends PluginHook { private MultiverseCore mvCore; + private MultiverseInventories mvInventories; private static final String GENERATOR_NAME = "uSkyBlock"; public MultiverseHook(@NotNull uSkyBlock plugin) { super(plugin, "Multiverse", "Multiverse"); setupCore().ifPresent(mvPlugin -> this.mvCore = mvPlugin); + setupInventories().ifPresent(mvPlugin -> this.mvInventories = mvPlugin); } private Optional setupCore() { Plugin mvPlugin = plugin.getServer().getPluginManager().getPlugin("Multiverse-Core"); if (mvPlugin instanceof MultiverseCore) { + plugin.getLogger().info("Found Multiverse-Core."); return Optional.of((MultiverseCore) mvPlugin); } return Optional.empty(); } + private Optional setupInventories() { + Plugin mvPlugin = plugin.getServer().getPluginManager().getPlugin("Multiverse-Inventories"); + if (mvPlugin instanceof MultiverseInventories) { + plugin.getLogger().info("Found Multiverse-Inventories."); + return Optional.of((MultiverseInventories) mvPlugin); + } + + return Optional.empty(); + } + /** * Registers the given {@link World} to {@link MultiverseCore} as the skyblock overworld (skyworld). * @param world World to register. */ public void registerOverworld(@NotNull World world) { + if (mvCore == null) { + return; + } + if (!mvCore.getMVWorldManager().isMVWorld(world)) { mvCore.getMVWorldManager().addWorld(world.getName(), World.Environment.NORMAL, "0", WorldType.NORMAL, false, GENERATOR_NAME, false); @@ -66,6 +88,10 @@ public void registerOverworld(@NotNull World world) { * @param world World to register. */ public void registerNetherworld(@NotNull World world) { + if (mvCore == null) { + return; + } + if (!mvCore.getMVWorldManager().isMVWorld(world)) { mvCore.getMVWorldManager().addWorld(world.getName(), World.Environment.NETHER, "0", WorldType.NORMAL, false, GENERATOR_NAME, false); @@ -86,5 +112,24 @@ public void registerNetherworld(@NotNull World world) { if (!Settings.extras_sendToSpawn) { mvWorld.setRespawnToWorld(plugin.getWorldManager().getWorld().getName()); } + + linkNetherInventory(plugin.getWorldManager().getWorld(), world); + } + + private void linkNetherInventory(@NotNull World... worlds) { + if (mvCore == null || mvInventories == null) { + return; + } + + WorldGroupManager groupManager = mvInventories.getGroupManager(); + WorldGroup worldGroup = groupManager.getGroup("skyblock"); + if (worldGroup == null) { + worldGroup = groupManager.newEmptyGroup("skyblock"); + worldGroup.getShares().addAll(Sharables.ALL_DEFAULT); + } + for (World world : worlds) { + worldGroup.addWorld(world); + } + groupManager.updateGroup(worldGroup); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 8da8f13c4..6db113964 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -59,11 +59,9 @@ import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; -import us.talabrek.ultimateskyblock.handler.MultiverseInventoriesHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; -import us.talabrek.ultimateskyblock.hook.world.MultiverseHook; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandGenerator; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index d765e4595..b0acdc5f4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -17,7 +17,6 @@ import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; -import us.talabrek.ultimateskyblock.handler.MultiverseInventoriesHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; @@ -244,7 +243,6 @@ public synchronized World getNetherWorld() { plugin.getHookManager().getMultiverse().ifPresent(hook -> { hook.registerNetherworld(skyBlockNetherWorld); setupWorld(skyBlockNetherWorld, island_height / 2); - MultiverseInventoriesHandler.linkWorlds(getWorld(), skyBlockNetherWorld); }), plugin.getConfig().getLong("init.initDelay", 50L) + 100L); return skyBlockNetherWorld; diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 066f8ce41..5b524b824 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -6,12 +6,13 @@ author: R4zorax (and more) load: STARTUP softdepend: # mandatory dependencies - - Vault - WorldEdit - WorldGuard - - Multiverse-Core # optional dependencies - ActionBarAPI + - Multiverse-Core + - Multiverse-Inventories + - Vault # WE/AWE - FastAsyncWorldEdit - AsyncWorldEdit From bc81758abe5873299c6d44e1e0c8a8c3fe60fddd Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 22 Jul 2020 21:20:02 +0100 Subject: [PATCH 037/190] Version 2.8.9 for MC1.16.1 --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 170603abe..dfe964f22 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9-SNAPSHOT + 2.8.9 4.0.0 jar diff --git a/pom.xml b/pom.xml index b4818fda2..eb3f5a6f7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.9-SNAPSHOT + 2.8.9 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index c83d1e63c..301470bc7 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.9-SNAPSHOT + 2.8.9 UTF-8 dev diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 97171889a..ac92ad767 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9-SNAPSHOT + 2.8.9 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 6be812c0a..dbd5cf920 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9-SNAPSHOT + 2.8.9 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 44214de52..cf706ae08 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9-SNAPSHOT + 2.8.9 4.0.0 jar From a693011556747be9cf4feb3760edcf62cc50d992 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 22 Jul 2020 22:21:34 +0100 Subject: [PATCH 038/190] Hotfix for Multiverse NoClassDef --- .../ultimateskyblock/hook/world/MultiverseHook.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java index 3be9643dd..9881894b9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/world/MultiverseHook.java @@ -16,7 +16,6 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import java.util.Arrays; import java.util.Optional; public class MultiverseHook extends PluginHook { @@ -27,8 +26,13 @@ public class MultiverseHook extends PluginHook { public MultiverseHook(@NotNull uSkyBlock plugin) { super(plugin, "Multiverse", "Multiverse"); - setupCore().ifPresent(mvPlugin -> this.mvCore = mvPlugin); - setupInventories().ifPresent(mvPlugin -> this.mvInventories = mvPlugin); + + if (plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Core")) { + setupCore().ifPresent(mvPlugin -> this.mvCore = mvPlugin); + } + if (plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Inventories")) { + setupInventories().ifPresent(mvPlugin -> this.mvInventories = mvPlugin); + } } private Optional setupCore() { From 7237e4a98dc8eee943e212da84a551613d7b3c9b Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 23 Jul 2020 11:41:39 +0100 Subject: [PATCH 039/190] Version to 2.8.10-SNAPSHOT --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index dfe964f22..59c05202b 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9 + 2.8.10-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index eb3f5a6f7..359bee023 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.9 + 2.8.10-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 301470bc7..ea77dedaa 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.9 + 2.8.10-SNAPSHOT UTF-8 dev diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index ac92ad767..2c3756153 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9 + 2.8.10-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index dbd5cf920..41f199810 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9 + 2.8.10-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index cf706ae08..bc6ed0705 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.9 + 2.8.10-SNAPSHOT 4.0.0 jar From 60fd03c21ae1bab5150120c986130abf51a23e45 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 23 Jul 2020 23:20:21 +0100 Subject: [PATCH 040/190] Fix deprecation in NBT command --- .../command/admin/NBTCommand.java | 62 +++++++++---------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java index a5740a06d..82e46a32f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java @@ -24,17 +24,17 @@ public NBTCommand() { public boolean execute(CommandSender sender, String alias, Map data, String... args) { if (sender instanceof Player) { Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInHand(); - if (itemStack != null) { - String[] msgs = new String[]{ - tr("\u00a7eInfo for \u00a79{0}", ItemStackUtil.asString(itemStack)), - tr("\u00a77 - name: \u00a79{0}", ItemStackUtil.getItemName(itemStack)), - tr("\u00a77 - nbttag: \u00a79{0}", NBTUtil.getNBTTag(itemStack)) - }; - player.sendMessage(msgs); - } else { + ItemStack itemStack = player.getInventory().getItemInMainHand(); + if (!itemStack.getType().isItem()) { player.sendMessage(tr("\u00a7cNo item in hand!")); + return true; } + String[] msgs = new String[]{ + tr("\u00a7eInfo for \u00a79{0}", ItemStackUtil.asString(itemStack)), + tr("\u00a77 - name: \u00a79{0}", ItemStackUtil.getItemName(itemStack)), + tr("\u00a77 - nbttag: \u00a79{0}", NBTUtil.getNBTTag(itemStack)) + }; + player.sendMessage(msgs); return true; } sender.sendMessage(tr("\u00a7eCan only be executed as a player")); @@ -44,20 +44,18 @@ public boolean execute(CommandSender sender, String alias, Map d add(new AbstractCommand("set|s", null, "nbttag", marktr("sets the NBTTag on the currently held item")) { @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (sender instanceof Player) { - if (args.length > 0) { - Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInHand(); - if (itemStack != null) { - String nbtTag = join(args); - itemStack = NBTUtil.setNBTTag(itemStack, nbtTag); - player.getInventory().setItemInHand(itemStack); - player.sendMessage(tr("\u00a7eSet \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); - } else { - player.sendMessage(tr("\u00a7cNo item in hand!")); - } + if (sender instanceof Player && args.length > 0) { + Player player = (Player) sender; + ItemStack itemStack = player.getInventory().getItemInMainHand(); + if (!itemStack.getType() .isItem()) { + player.sendMessage(tr("\u00a7cNo item in hand!")); return true; } + String nbtTag = join(args); + itemStack = NBTUtil.setNBTTag(itemStack, nbtTag); + player.getInventory().setItemInMainHand(itemStack); + player.sendMessage(tr("\u00a7eSet \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); + return true; } sender.sendMessage(tr("\u00a7eCan only be executed as a player")); return false; @@ -66,20 +64,18 @@ public boolean execute(CommandSender sender, String alias, Map d add(new AbstractCommand("add|a", null, "nbttag", marktr("adds the NBTTag on the currently held item")) { @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (sender instanceof Player) { - if (args.length > 0) { - Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInHand(); - if (itemStack != null) { - String nbtTag = join(args); - itemStack = NBTUtil.addNBTTag(itemStack, nbtTag); - player.getInventory().setItemInHand(itemStack); - player.sendMessage(tr("\u00a7eAdded \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); - } else { - player.sendMessage(tr("\u00a7cNo item in hand!")); - } + if (sender instanceof Player && args.length > 0) { + Player player = (Player) sender; + ItemStack itemStack = player.getInventory().getItemInMainHand(); + if (!itemStack.getType().isItem()) { + player.sendMessage(tr("\u00a7cNo item in hand!")); return true; } + String nbtTag = join(args); + itemStack = NBTUtil.addNBTTag(itemStack, nbtTag); + player.getInventory().setItemInMainHand(itemStack); + player.sendMessage(tr("\u00a7eAdded \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); + return true; } sender.sendMessage(tr("\u00a7eCan only be executed as a player")); return false; From 74ec972c5af14bdd008f0f43e9e3fa42a534e0e0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 23 Jul 2020 23:30:37 +0100 Subject: [PATCH 041/190] Bail out when sender isn't a player in GotoIslandCommand --- .../ultimateskyblock/command/admin/GotoIslandCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java index 181956aa8..3e6422cae 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java @@ -24,6 +24,7 @@ public GotoIslandCommand(uSkyBlock plugin) { protected void doExecute(final CommandSender sender, final PlayerInfo playerInfo) { if (!(sender instanceof Player)) { sender.sendMessage(I18nUtil.tr("\u00a74Only supported for players")); + return; } final Player player = (Player) sender; if (!playerInfo.getHasIsland()) { @@ -38,4 +39,4 @@ protected void doExecute(final CommandSender sender, final PlayerInfo playerInfo sender.sendMessage(I18nUtil.tr("\u00a74That player does not have an island!")); } } -} \ No newline at end of file +} From 846e8848127275affe4a83eb6eb816805ad3e4b0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 24 Jul 2020 00:17:36 +0100 Subject: [PATCH 042/190] Handle /is sethome command in it's own class --- .../command/island/SetHomeCommand.java | 20 ++++++++++++++++++- .../talabrek/ultimateskyblock/uSkyBlock.java | 20 ------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java index 5dddcf15a..3f91f07fd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java @@ -4,10 +4,12 @@ import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.LocationUtil; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class SetHomeCommand extends RequireIslandCommand { public SetHomeCommand(uSkyBlock plugin) { @@ -16,6 +18,22 @@ public SetHomeCommand(uSkyBlock plugin) { @Override protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandInfo island, Map data, String... args) { - return plugin.homeSet(player); + if (!player.getWorld().getName().equalsIgnoreCase(plugin.getWorldManager().getWorld().getName())) { + player.sendMessage(tr("\u00a74You must be closer to your island to set your skyblock home!")); + return true; + } + if (!plugin.playerIsOnOwnIsland(player)) { + player.sendMessage(tr("\u00a74You must be closer to your island to set your skyblock home!")); + return true; + } + if (pi == null || !LocationUtil.isSafeLocation(player.getLocation())) { + player.sendMessage(tr("\u00a74Your current location is not a safe home-location.")); + return true; + } + + pi.setHomeLocation(player.getLocation()); + pi.save(); + player.sendMessage(tr("\u00a7aYour skyblock home has been set to your current location.")); + return true; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 6db113964..f98bfa42d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -492,26 +492,6 @@ public synchronized boolean devSetPlayerIsland(final Player sender, final Locati return true; } - public boolean homeSet(final Player player) { - if (!player.getWorld().getName().equalsIgnoreCase(getWorldManager().getWorld().getName())) { - player.sendMessage(tr("\u00a74You must be closer to your island to set your skyblock home!")); - return true; - } - if (playerIsOnOwnIsland(player)) { - PlayerInfo playerInfo = playerLogic.getPlayerInfo(player); - if (playerInfo != null && isSafeLocation(player.getLocation())) { - playerInfo.setHomeLocation(player.getLocation()); - playerInfo.save(); - player.sendMessage(tr("\u00a7aYour skyblock home has been set to your current location.")); - } else { - player.sendMessage(tr("\u00a74Your current location is not a safe home-location.")); - } - return true; - } - player.sendMessage(tr("\u00a74You must be closer to your island to set your skyblock home!")); - return true; - } - public boolean playerIsOnIsland(final Player player) { return playerIsOnOwnIsland(player) || playerIsTrusted(player); From 842100f4565b179178ffba94e55ae5f4ecb25dcc Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 27 Jul 2020 14:33:38 +0100 Subject: [PATCH 043/190] Change default chest items from SIGN to OAK_SIGN --- uSkyBlock-Core/src/main/resources/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index bc429e80f..c3c496e54 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -57,7 +57,7 @@ options: - BROWN_MUSHROOM:1 - PUMPKIN_SEEDS:1 - SUGAR_CANE:1 - - SIGN:1 + - OAK_SIGN:1 addExtraItems: true islandTeleportDelay: 2 allowPvP: deny @@ -454,7 +454,7 @@ placeholder: servercommandplaceholder: false # DO NOT TOUCH THE FIELDS BELOW -version: 106 +version: 107 force-replace: options.party.invite-timeout: 100 options.island.islandTeleportDelay: 5 From d3c691af3ffffa91dab8cf89094b44454dbe3c1d Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 29 Jul 2020 21:57:53 +0100 Subject: [PATCH 044/190] Remove obsolete datavalue checks in ToolMenuEvents --- .../event/ToolMenuEvents.java | 26 ++++++++----------- uSkyBlock-Core/src/main/resources/config.yml | 2 +- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java index fd18b147e..4dc3c2569 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java @@ -21,7 +21,6 @@ * Events triggering the tool-menu */ public class ToolMenuEvents implements Listener { - public static final String COMPLETE_CHALLENGE_CMD = "challenges complete "; private final uSkyBlock plugin; private final ItemStack tool; @@ -29,7 +28,7 @@ public class ToolMenuEvents implements Listener { public ToolMenuEvents(uSkyBlock plugin) { this.plugin = plugin; - tool = ItemStackUtil.createItemStack(plugin.getConfig().getString("tool-menu.tool", "SAPLING")); + tool = ItemStackUtil.createItemStack(plugin.getConfig().getString("tool-menu.tool", Material.OAK_SAPLING.toString())); registerChallenges(); registerCommands(); } @@ -61,8 +60,8 @@ private void registerChallenges() { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onBlockHit(PlayerInteractEvent e) { - if (e == null || e.getClickedBlock() == null - || e.getAction() != Action.LEFT_CLICK_BLOCK || e.getPlayer().getGameMode() != GameMode.SURVIVAL) { + if (e.getClickedBlock() == null || e.getAction() != Action.LEFT_CLICK_BLOCK || + e.getPlayer().getGameMode() != GameMode.SURVIVAL) { return; } Player player = e.getPlayer(); @@ -72,16 +71,8 @@ public void onBlockHit(PlayerInteractEvent e) { // We are in a skyworld, a block has been hit, with the tool Material block = e.getClickedBlock().getType(); - short data = e.getClickedBlock().getData(); - String itemId = ItemStackUtil.asString(new ItemStack(block, 1, data)); - if (commandMap.containsKey(itemId)) { - doCmd(e, player, itemId); - } - if (!e.isCancelled()) { - itemId = ItemStackUtil.asString(new ItemStack(block, 1)); - if (commandMap.containsKey(itemId)) { - doCmd(e, player, itemId); - } + if (commandMap.containsKey(block.toString())) { + doCmd(e, player, block.toString()); } } @@ -99,7 +90,12 @@ private void doCmd(PlayerInteractEvent e, Player player, String itemId) { } } + /** + * Checks if the given {@link ItemStack} is the configured tool for the tool menu. + * @param item ItemStack to check. + * @return True if it is the configured tool, false otherwise. + */ private boolean isTool(ItemStack item) { - return item != null && tool != null && item.getType() == tool.getType() && item.getDurability() == tool.getDurability(); + return item != null && tool != null && item.getType() == tool.getType(); } } diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index c3c496e54..5fdfde480 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -424,7 +424,7 @@ nether: blaze: 0.2 tool-menu: enabled: true - tool: SAPLING + tool: OAK_SAPLING commands: CHEST: island BEDROCK: island spawn From 137e757c9d0e2a6ad8785f4a4e917d309b20e048 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 31 Jul 2020 11:34:41 +0100 Subject: [PATCH 045/190] Re-add Asyncworldedit support (#1264) * Re-add AWE330 module as AWE370 * Use AWE to paste schematics --- pom.xml | 6 + uSkyBlock-AWE370/README.md | 5 + uSkyBlock-AWE370/pom.xml | 57 ++++++ .../handler/asyncworldedit/AWE370Adaptor.java | 193 ++++++++++++++++++ .../handler/AsyncWorldEditHandler.java | 19 +- uSkyBlock-Plugin/pom.xml | 6 +- uSkyBlock-Plugin/src/assembly/plugin.xml | 3 +- 7 files changed, 282 insertions(+), 7 deletions(-) create mode 100644 uSkyBlock-AWE370/README.md create mode 100644 uSkyBlock-AWE370/pom.xml create mode 100644 uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java diff --git a/pom.xml b/pom.xml index 359bee023..422dae602 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ uSkyBlock-Core uSkyBlock-Plugin uSkyBlock-FAWE + uSkyBlock-AWE370 @@ -176,6 +177,11 @@ uSkyBlock-FAWE ${project.version} + + uSkyBlock + uSkyBlock-AWE370 + ${project.version} + uSkyBlock po-utils diff --git a/uSkyBlock-AWE370/README.md b/uSkyBlock-AWE370/README.md new file mode 100644 index 000000000..acc7ad06e --- /dev/null +++ b/uSkyBlock-AWE370/README.md @@ -0,0 +1,5 @@ +# uSkyBlock-AsyncWorldEdit 3.7.0 + +This module holds the AWE 3.7.0 dependent integration (AsyncWorldEdit-API 2.2.0). + +It is a separate module, so we are able to compile (and test) it in a controlled manner (side by side the AWE211 integration). diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml new file mode 100644 index 000000000..1b148bc85 --- /dev/null +++ b/uSkyBlock-AWE370/pom.xml @@ -0,0 +1,57 @@ + + + + uSkyBlock + uSkyBlock + 2.8.10-SNAPSHOT + + 4.0.0 + uSkyBlock-AWE370 + + + false + + + + + org.primesoft.asyncworldedit + AsyncWorldEdit-API + [2.2.0-rc-01, 2.2.0) + jar + + + uSkyBlock + uSkyBlock-Core + + + org.spigotmc + spigot-api + ${spigotapi.version} + true + provided + + + + com.sk89q.worldedit + worldedit-bukkit + ${worldedit.version} + provided + + + org.bukkit + bukkit + + + + + + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo + + + diff --git a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java new file mode 100644 index 000000000..3df010212 --- /dev/null +++ b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java @@ -0,0 +1,193 @@ +package us.talabrek.ultimateskyblock.handler.asyncworldedit; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.world.World; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; +import org.primesoft.asyncworldedit.api.IAsyncWorldEdit; +import org.primesoft.asyncworldedit.api.blockPlacer.IBlockPlacerPlayer; +import org.primesoft.asyncworldedit.api.playerManager.IPlayerEntry; +import org.primesoft.asyncworldedit.api.playerManager.IPlayerManager; +import org.primesoft.asyncworldedit.api.utils.IFuncParamEx; +import org.primesoft.asyncworldedit.api.worldedit.IAsyncEditSessionFactory; +import org.primesoft.asyncworldedit.api.worldedit.ICancelabeEditSession; +import org.primesoft.asyncworldedit.api.worldedit.IThreadSafeEditSession; +import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; +import us.talabrek.ultimateskyblock.player.PlayerPerk; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Adaptor depending on AWE 3.7.x classes + */ +public class AWE370Adaptor implements AWEAdaptor { + private static final Logger log = Logger.getLogger(AWE370Adaptor.class.getName()); + static long progressEveryMs = 3000; // 2 seconds + static double progressEveryPct = 20; + private static final Set pendingJobs = Collections.synchronizedSet(new LinkedHashSet<>()); + + private static void updateProgress(IPlayerEntry playerEntry, int queuedBlocks, int maxQueuedBlocks) { + if (maxQueuedBlocks <= 1) { + return; // Not the "real" number of blocks... just ignore... + } + if (playerEntry != null && playerEntry.isUnknown() && playerEntry.getAweMode()) { + synchronized (pendingJobs) { + if (queuedBlocks == maxQueuedBlocks) { + // Either a fresh job, or a new merge + markJobs(maxQueuedBlocks, 0); + } + int blocksPlaced = maxQueuedBlocks - queuedBlocks; + boolean isFirst = true; + for (Iterator it = pendingJobs.iterator(); it.hasNext(); ) { + PlayerJob job = it.next(); + int left = job.progress(blocksPlaced); + if (left > 0 && isFirst && pendingJobs.size() > 1) { + it.remove(); + markJobs(blocksPlaced + left, queuedBlocks - left); + } + isFirst = false; + } + } + } + } + + private BukkitTask timerTask; + + private static void markJobs(int maxQueuedBlocks, int startOffset) { + synchronized (pendingJobs) { + int rest = maxQueuedBlocks; + for (PlayerJob job : pendingJobs) { + int missing = job.mark(rest, startOffset); + rest -= missing; + startOffset += missing; + } + } + } + + private static IAsyncWorldEdit getAWE() { + return (IAsyncWorldEdit) Bukkit.getPluginManager().getPlugin("AsyncWorldEdit"); + } + + @Override + public void onEnable(Plugin plugin) { + progressEveryMs = plugin.getConfig().getInt("asyncworldedit.progressEveryMs", 3000); + progressEveryPct = plugin.getConfig().getDouble("asyncworldedit.progressEveryPct", 20); + } + + @Override + public void registerCompletion(Player player) { + PlayerJob newJob = new PlayerJob(player, progressEveryMs, progressEveryPct); + pendingJobs.remove(newJob); + pendingJobs.add(newJob); + } + + @Override + public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { + final IAsyncWorldEdit awe = getAWE(); + BukkitWorld bukkitWorld = new BukkitWorld(origin.getWorld()); + Player player = Bukkit.getPlayer(playerPerk.getPlayerInfo().getUniqueId()); + int maxBlocks = (255 * Settings.island_protectionRange * Settings.island_protectionRange); + IPlayerManager pm = awe.getPlayerManager(); + final IPlayerEntry playerEntry = pm.getUnknownPlayer(); + IThreadSafeEditSession tsSession = (IThreadSafeEditSession) createEditSession(bukkitWorld, maxBlocks); + IFuncParamEx action = new PasteAction(origin, file); + registerCompletion(player); + awe.getBlockPlacer().performAsAsyncJob(tsSession, playerEntry, "loadIslandSchematic:"+playerPerk.getPlayerInfo().getPlayerName(), action); + if (timerTask != null) { + timerTask.cancel(); + } + timerTask = uSkyBlock.getInstance().async(new Runnable() { + int maxSize = -1; + @Override + public void run() { + IBlockPlacerPlayer playerEvents = awe.getBlockPlacer().getPlayerEvents(playerEntry); + if (playerEvents != null) { + int size = playerEvents.getQueue().size(); + if (maxSize == -1 || size > maxSize) { + maxSize = size; + } + updateProgress(playerEntry, size, maxSize); + } else { + updateProgress(playerEntry, 0, maxSize); + timerTask.cancel(); + } + } + }, 500, 500); + } + + public EditSession createEditSession(World bukkitWorld, int maxBlocks) { + WorldEdit worldEdit = WorldEdit.getInstance(); + IAsyncEditSessionFactory sessionFactory = (IAsyncEditSessionFactory) worldEdit.getEditSessionFactory(); + return (EditSession) sessionFactory.getThreadSafeEditSession(bukkitWorld, maxBlocks, null, getAWE().getPlayerManager().getUnknownPlayer()); + } + + @Override + public void regenerate(Region region, Runnable onCompletion) { + AsyncWorldEditHandler.NULL_ADAPTOR.regenerate(region, onCompletion); + } + + @Override + public void onDisable(Plugin plugin) { + } + + private static class PasteAction implements IFuncParamEx { + private final Location origin; + private final File file; + + public PasteAction(Location origin, File file) { + this.origin = origin; + this.file = file; + } + + public Integer execute(ICancelabeEditSession editSession) { + ClipboardFormat format = ClipboardFormats.findByFile(file); + if (format == null) { + log.log(Level.SEVERE, "Unable to find schematic format for file {}", file); + return null; + } + + try (InputStream inStream = new FileInputStream(file)) { + Clipboard clipboard = format.getReader(inStream).read(); + ClipboardHolder holder = new ClipboardHolder(clipboard); + editSession.enableQueue(); + + BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); + final Operation operation = holder + .createPaste(editSession) + .to(to) + .ignoreAirBlocks(true) + .build(); + Operations.completeBlindly(operation); + editSession.flushSession(); + } catch (IOException ex) { + log.log(Level.WARNING, "Error while pasting schematic", ex); + } + return 32768; + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 2f56ed9c8..87267e338 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -55,17 +55,26 @@ public static AWEAdaptor getAWEAdaptor() { } Plugin fawe = getFAWE(); Plugin awe = getAWE(); - String className = null; + String className; if (fawe != null) { VersionUtil.Version version = VersionUtil.getVersion(fawe.getDescription().getVersion()); className = "us.talabrek.ultimateskyblock.handler.asyncworldedit.FAWEAdaptor"; try { - adaptor = (AWEAdaptor) Class.forName(className).newInstance(); - log(Level.INFO, "Hooked into FAWE " + version); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoClassDefFoundError e) { - log(Level.WARNING, "Unable to locate FAWE adaptor for version " + version + ": " + e); + adaptor = (AWEAdaptor) Class.forName(className).getDeclaredConstructor().newInstance(); + log(Level.INFO, "Hooked into FAWE version " + version); + } catch (Exception ex) { + log(Level.WARNING, "Unable to locate FAWE adaptor for version " + version + ": " + ex); adaptor = NULL_ADAPTOR; } + } else if (awe != null) { + VersionUtil.Version version = VersionUtil.getVersion(awe.getDescription().getVersion()); + className = "us.talabrek.ultimateskyblock.handler.asyncworldedit.AWE370Adaptor"; + try { + adaptor = (AWEAdaptor) Class.forName(className).getDeclaredConstructor().newInstance(); + log(Level.INFO, "Hooked into AWE version " + version); + } catch (Exception ex) { + log(Level.WARNING, "Unable to locale AWE adaptor for version " + version, ex); + } } else { adaptor = NULL_ADAPTOR; } diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index bc6ed0705..af0af1365 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -59,5 +59,9 @@ uSkyBlock uSkyBlock-FAWE + + uSkyBlock + uSkyBlock-AWE370 + - \ No newline at end of file + diff --git a/uSkyBlock-Plugin/src/assembly/plugin.xml b/uSkyBlock-Plugin/src/assembly/plugin.xml index 531cc37a4..37176911f 100644 --- a/uSkyBlock-Plugin/src/assembly/plugin.xml +++ b/uSkyBlock-Plugin/src/assembly/plugin.xml @@ -12,8 +12,9 @@ com.github.rlf:uSkyBlock-API uSkyBlock:uSkyBlock-Core uSkyBlock:uSkyBlock-FAWE + uSkyBlock:uSkyBlock-AWE370 true - \ No newline at end of file + From 42bfb7067e14b626977373914ca0690f2209a8f4 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 1 Aug 2020 16:44:22 +0100 Subject: [PATCH 046/190] FAWE 1.16.1 (#1265) * Update FAWE api to 1.16.1 * Update FAWE requirement to v1.16.1 --- .../talabrek/ultimateskyblock/uSkyBlock.java | 4 +-- uSkyBlock-FAWE/pom.xml | 10 ++++---- .../handler/asyncworldedit/FAWEAdaptor.java | 25 +++++++++++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index f98bfa42d..534323a94 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -109,8 +109,6 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static us.talabrek.ultimateskyblock.Settings.island_height; -import static us.talabrek.ultimateskyblock.util.LocationUtil.isSafeLocation; import static us.talabrek.ultimateskyblock.util.LogUtil.log; public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManager.RequirementChecker { @@ -119,7 +117,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage new String[]{"Vault", "1.7.0", "optional"}, new String[]{"WorldEdit", "7.0", "optionalIf", "FastAsyncWorldEdit"}, new String[]{"WorldGuard", "7.0"}, - new String[]{"FastAsyncWorldEdit", "1.13", "optional"}, + new String[]{"FastAsyncWorldEdit", "1.16.1", "optional"}, new String[]{"Multiverse-Core", "2.5", "optional"}, new String[]{"Multiverse-Portals", "2.5", "optional"}, new String[]{"Multiverse-NetherPortals", "2.5", "optional"}, diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 41f199810..54baf2930 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -16,16 +16,16 @@ - fawe-jenkins - https://ci.athion.net/job/FastAsyncWorldEdit-Breaking/ws/mvn + IntellectualSites + https://mvn.intellectualsites.com/content/repositories/releases/ - com.boydti - fawe-api - latest + com.intellectualsites.fawe + FAWE-Bukkit + 1.16-306 provided diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index 566c18af0..bb9d14e57 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -3,6 +3,7 @@ import com.boydti.fawe.util.EditSessionBuilder; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -12,7 +13,6 @@ import org.bukkit.plugin.Plugin; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.LogUtil; import java.io.File; import java.io.IOException; @@ -29,7 +29,6 @@ public class FAWEAdaptor implements AWEAdaptor { @Override public void onEnable(Plugin plugin) { this.plugin = (uSkyBlock) plugin; - log.finer("- FAWE debugging: Location of WorldEdit EditSession: " + EditSession.class.getResource('/' + EditSession.class.getName().replace('.', '/') + ".class")); } @Override @@ -44,20 +43,26 @@ public synchronized void registerCompletion(Player player) { @Override public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { plugin.async(() -> { - log.finer("Trying to load schematic " + file); if (file == null || !file.exists() || !file.canRead()) { - LogUtil.log(Level.WARNING, "Unable to load schematic " + file); + log.log(Level.WARNING, "Unable to load schematic {}", file); + return; } + + ClipboardFormat format = ClipboardFormats.findByFile(file); + if (format == null) { + log.log(Level.SEVERE, "Unable to find schematic format for file {}", file); + return; + } + BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); EditSession editSession = getEditSession(playerPerk, origin); try { - ClipboardFormats - .findByFile(file) - .load(file) - .paste(editSession, to, false); + format + .load(file) + .paste(editSession, to, false); editSession.flushQueue(); - } catch (IOException e) { - log.log(Level.INFO, "Unable to paste schematic " + file, e); + } catch (IOException ex) { + log.log(Level.INFO, "Unable to paste schematic " + file, ex); } }); } From 00cb3712b5af633851d0117f1b30dd222ac7e351 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 1 Aug 2020 20:53:44 +0100 Subject: [PATCH 047/190] Add AWE370 to build scripts (please Travis, I always break something here, be nice for me tonight) --- .gitignore | 9 +++++--- .travis.yml | 15 ++---------- deploy_rsa.enc | Bin 3248 -> 3392 bytes scripts/deploy-release.sh | 47 +++++++++++++++++++++++--------------- scripts/deploy-staging.sh | 47 +++++++++++++++++++++++--------------- uSkyBlock-FAWE/pom.xml | 17 -------------- 6 files changed, 64 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 355e4d4d2..98e1d962f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ .settings .classpath bin -/dependency-reduced-pom.xml # Package Files # *.jar *.war @@ -14,5 +13,9 @@ bin **/*.iml **/*~ .idea -**/target -**/*.mo \ No newline at end of file +**/*.mo + +*.DS_Store + +dependency-reduced-pom.xml +deploy_rsa \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index e3b28a166..b7ad96985 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,11 +17,8 @@ before_install: install: - mvn -nsu -Dtravis.buildNumber=${TRAVIS_BUILD_NUMBER} -Pi18n clean deploy before_deploy: - - echo '|1|DBFhltHRAVmrfmMZPLbN7FwnS5E=|79CP65+tOIeVNeNNC2R680mpV9o= ecdsa-sha2-nistp256 - AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK/krqsEUrVoDrYIc7I7nsiSCF0M7Xxr379IqZ2pLUPlxF2Or/MkTTokXzRsyspJazL1W1UrBDmKXHfO6+tyMMw=' - >> $HOME/.ssh/known_hosts - - openssl aes-256-cbc -K $encrypted_77431b0955a8_key -iv $encrypted_77431b0955a8_iv - -in deploy_rsa.enc -out deploy_rsa -d + - openssl aes-256-cbc -K $encrypted_a65247dffca0_key -iv $encrypted_a65247dffca0_iv + -in deploy_rsa.enc -out ./deploy_rsa -d - eval "$(ssh-agent -s)" - chmod 600 deploy_rsa - ssh-add deploy_rsa @@ -38,11 +35,3 @@ deploy: script: bash scripts/deploy-release.sh on: tags: true -after_success: - - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - - chmod +x send.sh - - ./send.sh success $WEBHOOK_URL -after_failure: - - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - - chmod +x send.sh - - ./send.sh failure $WEBHOOK_URL diff --git a/deploy_rsa.enc b/deploy_rsa.enc index d337096628deec5844611c674ce1c4125493b8bc..487019aab865e0970a8c3d00bff2140d5fb8d8e6 100644 GIT binary patch literal 3392 zcmV-G4ZrdNEXTIL-RNq%Hr1-3X(7_!5$Z5P?1B6RH+V;LadIcgf5!RM5!LSArzk*@ zFTluo6PV0s+Q+(|suzi8-2bFIdUC>s|70cCR#xs|ksp2fNuBmDh0acWcAIMfg~FPz^k*N8YV4p6UeZ`E<Oeten$gITff+xpBt~217iZYwdrLbX! zEc+#%>5N3a%M@jntEOY=5u!?!ag%*9uMyZxUzF=(j6!i8&p01r;d_Ylz2+`RuAIM3Os9 zVF1aqsvJ=P19UCqMSGuT=5z{7&rzJ{s#ciS&9K6b#G^+WLv`)C@` zy0O1SSlh5XOQO4m88C+(k!LqcCUc>O@XY9FiLQNhTIk;; z-}i1&%n?!`HuMeeHw{EaxuRTC)CFyYpjeO9Saz?kymbxKYL&E}LBMeOz-5jQZ#k${w-p&9rXCPy zBaH4CV4eNJp#tac@6F-b>%+`$%}@<%K^y{4sx0{XCReDg36p@~e3&~ZW&A!mHPr4o z?@rwCI-?gYvV~49Y|d&}`yy@vs7JZUcThz|un(J3f}eQN5%HSv_uW zuFZQPALb9R{2pJI>2+bM^V64_+%Z#puLd#&I3D5JmsH?X*`fntz3iF|m*p0o!|#65 z>@AbgImzZ|C@Zbk+lsUxc4a!>vSb#-VPXf0u-L$28$ZYF%|V= z-Sf&Yv6w1%{v@a7tV~Z%u|+g>LW;BKitz%Vf9BHbtJh*YDN3cMXB?9mP}1+YcVWkZ zoe?v?N{(wFpWg!!6pDzMjO2(eoNzC1pibn$aFfd20mk3^$`|&Kq%8Gu~?aABjcIHqElVZ|~ zJ0vfNQ8tQkJ0evY;P3%)+1k*%KV;j}!LlnS)3NaH@1?=zD=r-5_!5Gh@P}XBF-GcA z8T7L9`9r`<*1tk+?4{0Ruu}pXm|*i!&;L8j>G)UDYwa(=@WFOXFuAX-p+UjBW08<6 zIcilBA@biK_E5@L3>1#TrSQJjr)yxFFs67P-Ei%KXJR>Lep(|6pI~77<3xlQijNFV zI`qows0NIRw_&pxziWHri`B`X);lM$1GzDr@^Z>pt9v88!mH(?fRd@+*P+jIm_9k9 z*9NK8GO_4`8+Nk@)6~Ev8Nd1Ay%THWj@SQ*jh*#ON1g>jm5?c^Q#O6%{=~@gmN6ex zAVb}BxTWqe8)=*#)&K>*0t0n0p=6yrL;=ztYV(BI70$hTzS8VFuE5cAz#Ia_o&hRU z#k4)0kYHpZI08{s9wdt3d!n?%ksa^5RL<(P&10B-YWLAFmOzT)@up%Ie`X&$2|dbH zj*XdsjGG_g9GC>;r5Oh;SA&3)Wba}ou2?y!(1@D8549k8luTDQ)a*?IroxHRtr^?+ z#-PtU_(m#-Bb0ftDq-ZX`4%l3O942VwZmA~YoVet@2{`H*LYDnC@`#-qk*6t5+xus zE{pIj77~&-y#%Uyv)$pd?ec|OvD!Gr$8-~2V6Hz7TYx^DQ~suK!US^$;7Av<-tYZUt!xjYlH z88%6$PlPur?+uwN=`70W=-*i7{8%fivumiuOjh{!LlL*pM~iSDHkBz+lSxPTAwS{?_tvD>>%ZtdUIPqTV8_GjBgc#aH5 zzo0lWSU`#cJOi4V*r-QG%FzkK^7mAZk`b@Th>BZpDf8sR)4H`+L2#6y%8>o% zt_}$v$bPKN5r)Ii7npY2k8xe?c=Q-;rtDb%HfSZ3XjAr8_nWjbe?(a;$LIksiU~Pr zbKsU;zfnwJ2(YvnP&Ra6&;;Or>3jg2*9ijlDJ!V8s1i3Vbd-~Dn1pjOMQ49xf<-0} zEc~`I5x2@SSUd4q^ULJ#kmm*VVmn-bP>{StoLYbC%$ zuG@)sbFsR7jThEr2HpN;w4dfW5+7^JFj?+7-q&}!^{h+a zK75k7oeWPpga+>XC+tR6d}5+0VdbuZd9`iblEYXu%+cDod}U znOe&1z@_kx)3_cp?GD)o%H}Hid7~3?j;dW}gAJZ|=Bq2XTB_iKKcrc=$fnV$NE8Gsh@0~TwOu)}ci=P=UBsBtx`1fr(=c)_P zU9D;iHo-5}m<5)6XAU_Hmu46zRh|_hXq-fCa*1}7!cv5RChPk=5Et}YoS*?&2<5y- zVWRMe>(5HF=Ss)7$tUkvAe+53IU10hz{VX}na!g3+?&?nw!w@h1^w+t%-=9{9o4Um z{9Tm|Q{)O@jdqXZGyX;e%mK|4*0a;Nmy^qqUJO_4G-hKS_ZM8E$sk+E2!$o7I|(Xh zv{_@Z&iuG)8glE+u)s#N+@Z!T>hT|eQiiRihQW%)jsz6(mfDQ$>P>J#uh;UF_xYuu z5uH+G%`Sro;h;;J-W zK%wJO3sKnpU4JJu%OgNh%KA3mdWip83!0-z`MBgxjA6-!b3Arb!; zTcbGa=isiKagL&p+HK4=DL=qL?Nj6gcyb{I=FKB9Njm*6@UsyQc5NGOtocrNeA#=s z)9`_G6jbrADP*U z{9$^l?**jkC%e*-_goW2Q3@+fB$OI)hff@!kY3b}Jl&b0BR2Mzz;YXp{SWM^j9by< z#llCbc#@EpfoJy6I8p@KI9+y)8FxY!*PrrKnc~4$9z0&7UNzcdqN2G5R$`diMhPzN zCdmqga!Elp#p*C$(~~EoqJCMCS-MQ-yf8FMPX=5l(?JeTvK&t%blCU9k`$6Kvd1gi zp@pVq@)WD@>drDN91V~8vkitexqPC{xGm2xV*|7Q-oGrm>61?y?PKDBjH9Tno8WK< ze>weG!FLcm*10F=d|;Kc(7o`%brf9q{WQM$KaiRS;8zi>YqoGx6mwh_M|*N$F0T!U26yq~N5}l98Gt4$sI2}d5$b%A WwdT#TyKRkpj89SbtnOITr!##~G`@}i literal 3248 zcmV;h3{Uf&^{p~`r}u-H&Ul8Vr|GgbcIAxG-tZq2PfpbtTpj@%hy!Iy<4Q=ueXpUE z&oN2gu3!R0fYDn?fhUc--)vgBpB!*<#i4GTRbaJ{ z1Hc<#r7h9$pEMSSM4~<%WEP-*E)C0GB=VRKi4cb?7%{N3JBsP~T(Fi>3{3diX?FjG z^(d>wJM5>Bapj;N!AHl9Lv!futiO80JL>wbT0@|lxpAelVd+`F=)%Z_wuB;Ps0`mG zWNvn&Y~6PmS#!MRXjubofyd&u=B|!2NDvgRvj~9|V^z50HI({aumJb^Dn}SYa7$O_ zP=hqj|0=^}BOi?t=xo85+HS8t1^?g6HDMeeP`9&%E(Pn3WQyp9N=Z1RRp<+3`a{+j z_d)8$rdfWFKf>#EY}Ga1yI%!?Qp-^buNZ>dVX%I}IjOv(0!<8{^=*Pka(w}i9zeoe zWT@zi@q|NfP6DV_xw`llAVog{&u|#l=ag|Kw1q}0mIc~cLj$(~&=q#BcjMvi*Kje7 zq;>}a@hbD`lMEgfy&xKNC^%A^4A!>gNZZl5yV}NQS%^<;Fs$p1i~W>Q$ts)-@CKCd zV4k__E3F@MW)4Adp4a42JQ6q|UHx>I33&)Brmb@Yvuq`@j7PGr{DwGgLGY4EXw#v@ z4)3Fgt8smxJ*?rqt{L-z+Ue;N8f=gt#95=hkg*L+AW418SPQp#t8WeeAujCMDu{GJ zmx+`w455}RlWbRqf`ZvA)XAb<8NTl{0dry`+Q^-=frI^txgsACAZu# za8!yw)=;m}$ZfpV8}s0}eY)isNl4F`i;E3)aM~BEX*NJY{Sav5N4Scx=RH$=msfm5 z>tl2@Scmia6ke9YW;hwlFs2t)!4V3P%pKod;@{w_e;hwx?h96TXLNc>-<9}YP>16_ zj`~_U+T=wqzAu>LbsoyD+9UP;mjDD{uuyouQ2@Xlw&6mwTOx5Oqb3jQ{|(2{5(aQt zAGZ$4rr?^?cVJA@x)4{q^!g+Kb$svdf>cCv$}t~PXZYUfOGQYN+NtPHl56y3qLnio z0FGR8DaPZ`aKB=c5I-!GpWpP;q)`RjK1arhOi3z1yjwuEvrA$(a3gq^)8enXx}meK zx$T9hi9P!*0dVl$Gy~QR;8(W%4$h3lAob;dZBu@uKdW5W25?^8mKohHu#g7oc{^H* z&3>H6f~h?KqckXBgm>n7AZ2dK4Dcm3V4uv7?&bZ4;B z(TFhGho0-CIYu&K=9`G_82yRML&OjUMdjX$-Y_S*Y@y~NCX~V;{A8~4W4N+tT+h_f z7QEz_+ESX(CLeB;7vD>a*@zK+%)Y7rFgo!D#cvT{Z2gTen$58(viFaPVB71}(^2KNH&(|Vs`(XB`3VW)o$6MPe0H|{zv#+Gb4Ezs!qKR` zMgPT`2Q>x`#E=`&Vfbz70stE5YEp&PbMbIBz@9KWHpAP-Ha&xZfiz9$caTG~|xJ&5Isz>0_fRj}7jObwz-AF+%BTER4(+@vpP=RA#0KCR)q{L1_T#m&CSRl% z=lPtqJ^xYYB(GCGIMLQTE8s*j?pkSa%pT{`z4bJ@A!<7ljR|j->Ta+;%-Dk1Q>dq) zU;BaZu~4X(G4@dNP&Pud_Ka@-N=V|eM4I?shO>&TXtNp=cVs)S>lKL5nBh}{b; zZrIG_UJ$dD3$p~f_asW&XNJIIe4d7U_q_PH?KiZ{-|%Zf*LKGM)w@ovHo7{kk7W-o zG^1pRh@6KyU)w!#V9KG~@?*&eZ-6_?1L>B@iWF!)-#o~UN)c*hpZ&@OQ8vKy(pi~V zHTD4-PcYur&=#SYVB0Yaaxi*|-Te=#>mA(;tEZVYcV;i9_dezU1+akHrnAQ|WITxC zLk-LtKRpMEUCI~Aw(=qFxj^UT7oIDr8WmawOqg_~?3e_1Gik<>5Eu#t_a3cbM2cef z;9!91*lI$lx|rg{caENPIe>LZiC4mZ<5-tu1N!k_^Y>)tjVJ!MZsrT8ls6*xdmj(U zK?fS8bWd@rnat*aiI!I^8&j=cH&8yA-EGq+$VQW?epZwc50WAA)%8rJCF_MqmhceY zYtZ{njB5TT(oq7T-WU_0119E;!(?=Xy7(}T_}^BFvSg48IedgC%j&Py2VYG_>vz9; zR;9GAt^H&>PEpWN;3%Tj;PrA+V5vQto9or|flyw6RC=Lmyvz)@Rqg{~KA)8I=zy%w z7a}+{v0QG9-NkZ)fRw%XIZ8w-W&{XmA@&`@+ahfvbc7IHVn5``&9kaDRN}_OCs>Im z7=VXMJDS&wgO>#EQFu`xVu2b{z3o3&^?wKj7QlL$=@_)^(@9FEh-!rS0> zDmsW7g1B^S#pK`BPh`(q4a-+mW)HglT=$o|lRNDnvtjQ@xC}U6T$`G>QMIxSen6 zYr8=VKg%P;z$FOAH&0Z=r4Rev63kPHy7MzD2Dt}UTLUXUTh_dO?c?EUCivEgr@iVKm$m7h~UR4Dgg~JCVlM{IUZOQ}s97$2RQpu^O z%KzUTIlDr7875{T?r90QTlD}=RQv`XPVSv}2UBxaJX^5$Q5zc+GGv~*_aI!ewFFya zjk8yKK}bk65DR!Rcqf5=)l!mQwdo9mto zBiJ?qF~hwm+3L-{2*R3X$aLR?$m2$8Eizhfg!iuqkH?dsw+367d4xr*#9JXG5@i*| zBGwst*4j)>nk2NgF8EX{1?vv~rTRPUVZp-RKDuypK$pj!8JpxG=yd?8i;_%BwY};S z$2`SE z{W2aCsrL9=58W!;u<0Ed8&C`{nD48m7T)$xq(ZV>nFQv7&LXz7#YOMBRpoY)TBe~V z7Zn@=(8Nz8_zoCTmZR;xJ}KO2Q;J@4T-wpMk0#Mb2V7>r?4Gdu>m(k!S~Jyr~(M&At#xHaeM;~qac0N zp - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - - javadoc - - deploy - - - \ No newline at end of file From 3684b3bb76029edb1573f4a46e063738551bf872 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 1 Aug 2020 21:24:18 +0100 Subject: [PATCH 048/190] Mhm, can't blaim Travis for this to be fair --- scripts/deploy-release.sh | 18 +++++++++--------- scripts/deploy-staging.sh | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/deploy-release.sh b/scripts/deploy-release.sh index 197db4946..fc9b7b659 100644 --- a/scripts/deploy-release.sh +++ b/scripts/deploy-release.sh @@ -6,43 +6,43 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then echo -e "Publishing javadocs and artifacts...\n" cd $HOME - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ echo -e "Publishing javadocs...\n" - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/release/po-utils/ - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-API/ - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-Core/ echo -e "Publishing final plugin release...\n" - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ travis@travis.internetpolice.eu:WWW-USB/downloads/release/uSkyBlock/ diff --git a/scripts/deploy-staging.sh b/scripts/deploy-staging.sh index 50431b442..f8454e19f 100644 --- a/scripts/deploy-staging.sh +++ b/scripts/deploy-staging.sh @@ -6,43 +6,43 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then echo -e "Publishing javadocs and artifacts...\n" cd $HOME - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ echo -e "Publishing javadocs...\n" - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/po-utils/ - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ - rsync -r --delete --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ echo -e "Publishing final plugin release...\n" - rsync -r --quiet "ssh -p 2222 -o StrictHostKeyChecking=no" \ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ From 507a44eb1ff8217f3a4c8b34880608bb4f665362 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 3 Aug 2020 17:32:40 +0100 Subject: [PATCH 049/190] Remove obsolete datavalue check on leave break, and document why this handler exists --- .../ultimateskyblock/event/PlayerEvents.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index aa74f9620..2a331d332 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -289,27 +289,31 @@ public void onTeleport(PlayerTeleportEvent event) { } } + /** + * This EventHandler handles {@link BlockBreakEvent} to detect if a player broke OAK_LEAVES in the skyworld, + * and will drop an OAK_SAPLING if so. This will prevent cases where the default generated oak tree on a new + * island drops no saplings. + * @param event BlockBreakEvent to handle. + */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onLeafBreak(BlockBreakEvent event) { if (!plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { return; } - if (event.getBlock().getType() != Material.OAK_LEAVES || (event.getBlock().getData() & 0x3) != 0) { + if (event.getBlock().getType() != Material.OAK_LEAVES) { return; } - // Ok, a player broke an OAK LEAF in the Skyworld + String islandName = WorldGuardHandler.getIslandNameAt(event.getPlayer().getLocation()); IslandInfo islandInfo = plugin.getIslandInfo(islandName); if (islandInfo != null && islandInfo.getLeafBreaks() == 0) { - // Add an oak-sapling event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), new ItemStack(Material.OAK_SAPLING, 1)); islandInfo.setLeafBreaks(islandInfo.getLeafBreaks() + 1); } } @EventHandler(ignoreCancelled = true) - public void onBlockPlaceEvent(BlockPlaceEvent event) - { + public void onBlockPlaceEvent(BlockPlaceEvent event) { final Player player = event.getPlayer(); if (!blockLimitsEnabled || !plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld())) { return; // Skip From 5daf3b4facac2b59972988895c1a51e3bfda838f Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 3 Aug 2020 21:27:44 +0100 Subject: [PATCH 050/190] Fix deprecated calls to WorldEdit EditSession#setFastMode --- .../ultimateskyblock/handler/AsyncWorldEditHandler.java | 3 ++- .../us/talabrek/ultimateskyblock/handler/WorldEditHandler.java | 3 ++- .../talabrek/ultimateskyblock/handler/task/WorldEditClear.java | 3 ++- .../handler/task/WorldEditClearFlatlandTask.java | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 87267e338..0363c792f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -2,6 +2,7 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.World; import dk.lockfuglsang.minecraft.util.VersionUtil; import org.bukkit.Bukkit; @@ -128,7 +129,7 @@ public void run() { try { final EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), region.getArea() * 255); editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); - editSession.setFastMode(true); + editSession.setSideEffectApplier(SideEffectSet.defaults()); editSession.getWorld().regenerate(region, editSession); editSession.flushSession(); } finally { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java index 048f4f114..d2237cd03 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java @@ -14,6 +14,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.apache.commons.lang.Validate; import org.bukkit.Chunk; @@ -49,7 +50,7 @@ public static void loadIslandSchematic(final File file, final Location origin, P boolean noAir = false; BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(origin.getWorld()), -1); - editSession.setFastMode(true); + editSession.setSideEffectApplier(SideEffectSet.none()); ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(origin); if (region != null) { editSession.setMask(new RegionMask(getRegion(origin.getWorld(), region))); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java index fa5388acc..9e19a049b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java @@ -6,6 +6,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.block.BlockTypes; import org.bukkit.World; import us.talabrek.ultimateskyblock.async.IncrementalRunnable; @@ -75,7 +76,7 @@ protected boolean execute() { final EditSession editSession = WorldEditHandler.createEditSession( new BukkitWorld(world), region.getArea() * 255); editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); - editSession.setFastMode(true); + editSession.setSideEffectApplier(SideEffectSet.defaults()); try { editSession.setBlocks(region, BlockTypes.AIR.getDefaultState()); } catch (MaxChangedBlocksException e) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java index a2459617a..d371250eb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import dk.lockfuglsang.minecraft.util.TimeUtil; @@ -59,7 +60,7 @@ public boolean execute() { Iterator border = borderRegions.iterator(); while (!isComplete()) { EditSession editSession = AsyncWorldEditHandler.createEditSession(bukkitWorld, maxBlocks); - editSession.setFastMode(true); + editSession.setSideEffectApplier(SideEffectSet.defaults()); editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); if (inner.hasNext()) { BlockVector2 chunk = inner.next(); From 10e1deb6ec8a0bd3f447ef597c76ba84d28dc30b Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 11 Aug 2020 13:43:53 +0100 Subject: [PATCH 051/190] Bail-out early in getNetherWorld if nether is disabled --- .../us/talabrek/ultimateskyblock/world/WorldManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index b0acdc5f4..cfbd8453d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -220,7 +220,11 @@ public synchronized World getWorld() { */ @Nullable public synchronized World getNetherWorld() { - if (skyBlockNetherWorld == null && Settings.nether_enabled) { + if (!Settings.nether_enabled) { + return null; + } + + if (skyBlockNetherWorld == null) { skyBlockNetherWorld = Bukkit.getWorld(Settings.general_worldName + "_nether"); ChunkGenerator skyGenerator = getNetherGenerator(); ChunkGenerator worldGenerator = skyBlockNetherWorld != null ? skyBlockNetherWorld.getGenerator() : null; From d3e6ac929e449e1e8f6728a37ddb21b0cd288459 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 20 Aug 2020 16:06:46 +0100 Subject: [PATCH 052/190] Invalidate caches after delayed initialization task finished running --- .../src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 1 + 1 file changed, 1 insertion(+) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 534323a94..1335c691d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -228,6 +228,7 @@ public void run() { Bukkit.getConsoleSender().sendMessage(tr("Converting data to UUID, this make take a while!")); getImporter().importUSB(Bukkit.getConsoleSender(), "name2uuid"); } + getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 log(Level.INFO, getVersionInfo(false)); } }, getConfig().getLong("init.initDelay", 50L)); From a6c39fde39da01b127f82dda77d0386ec852802d Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 8 Sep 2020 12:07:10 +0100 Subject: [PATCH 053/190] Log Vault provider name --- .../ultimateskyblock/hook/economy/VaultEconomy.java | 9 ++++----- .../hook/permissions/VaultPermissions.java | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java index 33d8db3d4..3523848ee 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -17,7 +17,7 @@ public class VaultEconomy extends EconomyHook implements Listener { public VaultEconomy(@NotNull uSkyBlock plugin) { super(plugin, "Vault"); - setupEconomy().ifPresent((economy) -> this.economy = economy); + setupEconomy().ifPresent(vaultPlugin -> this.economy = vaultPlugin); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @@ -26,6 +26,7 @@ private Optional setupEconomy() { plugin.getServer().getServicesManager().getRegistration(Economy.class); if (rsp != null) { economy = rsp.getProvider(); + plugin.getLogger().info("Using " + rsp.getProvider().getName() + " as economy provider."); return Optional.of(economy); } @@ -65,19 +66,17 @@ public boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount) { } @EventHandler - @SuppressWarnings("unused") public void onEconomyRegister(ServiceRegisterEvent event) { if (event.getProvider().getProvider() instanceof Economy) { - setupEconomy().ifPresent((economy) -> this.economy = economy); + setupEconomy().ifPresent(vaultPlugin -> this.economy = vaultPlugin); } } @EventHandler - @SuppressWarnings("unused") public void onEconomyUnregister(ServiceUnregisterEvent event) { if (event.getProvider().getProvider() instanceof Economy) { this.economy = null; - setupEconomy().ifPresent((economy) -> this.economy = economy); + setupEconomy().ifPresent(vaultPlugin -> this.economy = vaultPlugin); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java index 0783ecfdf..59f711a10 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -17,7 +17,7 @@ public class VaultPermissions extends PermissionsHook implements Listener { public VaultPermissions(@NotNull uSkyBlock plugin) { super(plugin, "Vault"); - setupPermission().ifPresent((permission) -> this.permission = permission); + setupPermission().ifPresent(vaultPlugin -> this.permission = vaultPlugin); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @@ -26,6 +26,7 @@ private Optional setupPermission() { plugin.getServer().getServicesManager().getRegistration(Permission.class); if (rsp != null) { permission = rsp.getProvider(); + plugin.getLogger().info("Using " + rsp.getProvider().getName() + " as permission provider."); return Optional.of(permission); } @@ -43,19 +44,17 @@ public boolean removePermission(@NotNull Player player, @NotNull String perk) { } @EventHandler - @SuppressWarnings("unused") public void onPermissionRegister(ServiceRegisterEvent event) { if (event.getProvider().getProvider() instanceof Permission) { - setupPermission().ifPresent((permission) -> this.permission = permission); + setupPermission().ifPresent(vaultPlugin -> this.permission = vaultPlugin); } } @EventHandler - @SuppressWarnings("unused") public void onPermissionUnregister(ServiceUnregisterEvent event) { if (event.getProvider().getProvider() instanceof Permission) { this.permission = null; - setupPermission().ifPresent((permission) -> this.permission = permission); + setupPermission().ifPresent(vaultPlugin -> this.permission = vaultPlugin); } } } From 760d044ffcae65599e7077932401aa6b53f92f48 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 8 Sep 2020 12:19:42 +0100 Subject: [PATCH 054/190] Check if hasPermission is false, not true... --- .../java/us/talabrek/ultimateskyblock/player/PlayerInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 63d39e3ea..05bbb2afb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -444,7 +444,7 @@ public boolean addPermissions(@Nullable List perms) { PermissionsHook pHook = hook.get(); for (String perm : perms) { - if (pHook.hasPermission(target, perm)) { + if (!pHook.hasPermission(target, perm)) { permList.add(perm); pHook.addPermission(target, perm); } From 834dfc0558ffca7e5232afb6fc998c86dab41a62 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 28 Oct 2020 16:56:17 +0000 Subject: [PATCH 055/190] Few additional deprecated material names --- .editorconfig | 25 ++++++++++++++++--- .../ultimateskyblock/player/PerkLogic.java | 7 +++--- uSkyBlock-Core/src/main/resources/config.yml | 4 +-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/.editorconfig b/.editorconfig index 210d3ca85..716779f35 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,23 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + [*.java] -charset=utf-8 end_of_line=lf -insert_final_newline=true -indent_style=space -indent_size=4 + +[*.json] +indent_size = 2 + +[*.{yml,yaml}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[*.sh] +end_of_line = lf diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java index 90271cbc9..e622913f4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.player; +import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -63,7 +64,7 @@ public PerkLogic(uSkyBlock plugin, IslandGenerator islandGenerator) { .extraItems(ItemStackUtil.createItemList(config.getStringList("extraItems"))) .build(); ItemStack itemStack = ItemStackUtil.createItemStack( - config.getString("displayItem", "SAPLING"), + config.getString("displayItem", Material.OAK_SAPLING.toString()), schemeName, config.getString("description", null) ); @@ -75,7 +76,7 @@ public PerkLogic(uSkyBlock plugin, IslandGenerator islandGenerator) { Perk perk = new PerkBuilder(defaultPerk).schematics(schemeName).build(); if (!islandPerks.containsKey(schemeName)) { islandPerks.put(schemeName, new IslandPerk(schemeName, "usb.schematic." + schemeName, - ItemStackUtil.createItemStack("SAPLING", schemeName, null), perk, + ItemStackUtil.createItemStack(Material.OAK_SAPLING.toString(), schemeName, null), perk, 1d, 0d)); } } @@ -104,7 +105,7 @@ public IslandPerk getIslandPerk(String schemeName) { return islandPerks.get(schemeName); } return new IslandPerk(schemeName, "usb.schematic." + schemeName, - ItemStackUtil.createItemStack("GRASS", schemeName, null), defaultPerk); + ItemStackUtil.createItemStack(Material.GRASS_BLOCK.toString(), schemeName, null), defaultPerk); } private Perk createPerk(Player player) { diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index 5fdfde480..8d820f526 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -427,8 +427,8 @@ tool-menu: tool: OAK_SAPLING commands: CHEST: island + CRAFTING_TABLE: challenges BEDROCK: island spawn - WORKBENCH: challenges # Placeholders - enable these to get placeholder substitution # usb_version @@ -465,4 +465,4 @@ move-nodes: options.party.leave.confirmation: confirmation.is leave options.island.hopperlimit: options.island.block-limits.hopper options.island.spawnerlimit: options.island.block-limits.mob_spawner - options.island.block-limits.mob_spawner: options.island.block-limits.spawner \ No newline at end of file + options.island.block-limits.mob_spawner: options.island.block-limits.spawner From 13aa9868fd67e63e90f3554976131af0f670bc42 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 28 Oct 2020 17:16:55 +0000 Subject: [PATCH 056/190] Bump FAWE-API version --- uSkyBlock-FAWE/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 4c77913cf..e5230b07a 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -25,7 +25,7 @@ com.intellectualsites.fawe FAWE-Bukkit - 1.16-306 + 1.16-412 provided @@ -94,4 +94,4 @@ - \ No newline at end of file + From cfe076056db74ed27bb1ddf7b008eeb6ced63b2f Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 28 Oct 2020 19:00:49 +0000 Subject: [PATCH 057/190] Allow loadIslandSchematic PlayerPerk to be null in AWE370 adaptor --- .../handler/asyncworldedit/AWE370Adaptor.java | 12 +++++++++--- .../handler/asyncworldedit/AWEAdaptor.java | 3 ++- .../ultimateskyblock/world/WorldManager.java | 3 +++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java index 3df010212..43101be7d 100644 --- a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java +++ b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java @@ -110,14 +110,20 @@ public void registerCompletion(Player player) { public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { final IAsyncWorldEdit awe = getAWE(); BukkitWorld bukkitWorld = new BukkitWorld(origin.getWorld()); - Player player = Bukkit.getPlayer(playerPerk.getPlayerInfo().getUniqueId()); int maxBlocks = (255 * Settings.island_protectionRange * Settings.island_protectionRange); IPlayerManager pm = awe.getPlayerManager(); final IPlayerEntry playerEntry = pm.getUnknownPlayer(); IThreadSafeEditSession tsSession = (IThreadSafeEditSession) createEditSession(bukkitWorld, maxBlocks); IFuncParamEx action = new PasteAction(origin, file); - registerCompletion(player); - awe.getBlockPlacer().performAsAsyncJob(tsSession, playerEntry, "loadIslandSchematic:"+playerPerk.getPlayerInfo().getPlayerName(), action); + + String jobName = "loadIslandSchematic"; + if (playerPerk != null) { + Player player = Bukkit.getPlayer(playerPerk.getPlayerInfo().getUniqueId()); + registerCompletion(player); + jobName = jobName.concat(":" + playerPerk.getPlayerInfo().getPlayerName()); + } + + awe.getBlockPlacer().performAsAsyncJob(tsSession, playerEntry, jobName, action); if (timerTask != null) { timerTask.cancel(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java index f78a5d03e..3a21eafaa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java @@ -6,6 +6,7 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.player.PlayerPerk; import java.io.File; @@ -18,7 +19,7 @@ public interface AWEAdaptor { void onDisable(Plugin plugin); - void loadIslandSchematic(File file, Location origin, PlayerPerk playerPerk); + void loadIslandSchematic(File file, Location origin, @Nullable PlayerPerk playerPerk); void registerCompletion(Player player); EditSession createEditSession(World world, int maxBlocks); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index cfbd8453d..e474fa86f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -97,6 +97,9 @@ private void setupWorld(@NotNull World world, int islandHeight) { Location spawnLocation = world.getSpawnLocation(); if (!LocationUtil.isSafeLocation(spawnLocation)) { + // Warn the user why we're doing this, because it's a FAQ on the forums: + plugin.getLogger().warning("Spawn location in " + world.getName() + " is considered unsafe. " + + "Placing default spawn. This check can be disabled in config.yml, option manageSpawn."); createSpawn(spawnLocation); } } From cd77b7a4be4b359a9ce84291bec182f65d2b7b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bodick=C3=BD?= Date: Wed, 2 Dec 2020 23:40:15 +0100 Subject: [PATCH 058/190] FIxing Terraform for netherite tools (#10) * Added support for Netherite tools Material * Added support for Red Sand and Concrete Powders * Add Netherite tool to config.yml --- .../java/us/talabrek/ultimateskyblock/util/MaterialUtil.java | 4 +++- uSkyBlock-Core/src/main/resources/config.yml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java index 150e2da6d..47cdd748f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java @@ -17,12 +17,13 @@ public enum MaterialUtil { ; private static final Pattern MATERIAL_PROBABILITY = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?\\s*(?[A-Z_0-9]+)"); - private static final Collection SANDS = Arrays.asList(Material.SAND, Material.GRAVEL); + private static final Collection SANDS = Arrays.asList(Material.SAND, Material.RED_SAND, Material.GRAVEL, Material.WHITE_CONCRETE_POWDER, Material.ORANGE_CONCRETE_POWDER, Material.MAGENTA_CONCRETE_POWDER, Material.LIGHT_BLUE_CONCRETE_POWDER, Material.YELLOW_CONCRETE_POWDER, Material.LIME_CONCRETE_POWDER, Material.PINK_CONCRETE_POWDER, Material.GRAY_CONCRETE_POWDER, Material.LIGHT_GRAY_CONCRETE_POWDER, Material.CYAN_CONCRETE_POWDER, Material.PURPLE_CONCRETE_POWDER, Material.BLUE_CONCRETE_POWDER, Material.BROWN_CONCRETE_POWDER, Material.GREEN_CONCRETE_POWDER, Material.RED_CONCRETE_POWDER, Material.BLACK_CONCRETE_POWDER); private static final Collection WOOD_TOOLS = Arrays.asList(Material.WOODEN_AXE, Material.WOODEN_HOE, Material.WOODEN_PICKAXE, Material.WOODEN_SHOVEL, Material.WOODEN_SWORD); private static final Collection STONE_TOOLS = Arrays.asList(Material.STONE_AXE, Material.STONE_HOE, Material.STONE_PICKAXE, Material.STONE_SHOVEL, Material.STONE_SWORD); private static final Collection IRON_TOOLS = Arrays.asList(Material.IRON_AXE, Material.IRON_HOE, Material.IRON_PICKAXE, Material.IRON_SHOVEL, Material.IRON_SWORD); private static final Collection GOLD_TOOLS = Arrays.asList(Material.GOLDEN_AXE, Material.GOLDEN_HOE, Material.GOLDEN_PICKAXE, Material.GOLDEN_SHOVEL, Material.GOLDEN_SWORD); private static final Collection DIAMOND_TOOLS = Arrays.asList(Material.DIAMOND_AXE, Material.DIAMOND_HOE, Material.DIAMOND_PICKAXE, Material.DIAMOND_SHOVEL, Material.DIAMOND_SWORD); + private static final Collection NETHERITE_TOOLS = Arrays.asList(Material.NETHERITE_AXE, Material.NETHERITE_HOE, Material.NETHERITE_PICKAXE, Material.NETHERITE_SHOVEL, Material.NETHERITE_SWORD); private static final Collection TOOLS = new ArrayList<>(); static { TOOLS.addAll(WOOD_TOOLS); @@ -30,6 +31,7 @@ public enum MaterialUtil { TOOLS.addAll(IRON_TOOLS); TOOLS.addAll(GOLD_TOOLS); TOOLS.addAll(DIAMOND_TOOLS); + TOOLS.addAll(NETHERITE_TOOLS); } public static boolean isTool(Material type) { diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index 8d820f526..829732e18 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -415,6 +415,7 @@ nether: IRON: 0.9 GOLD: 1.5 DIAMOND: 0.2 + NETHERITE: 1.2 # The chances of changing a pigzombie when spawned on a netherbrick spawn-chances: From fe989420edeb906278512806e718ed56a91169d9 Mon Sep 17 00:00:00 2001 From: waseric Date: Tue, 22 Dec 2020 19:28:18 -0500 Subject: [PATCH 059/190] topchef requires GOLDEN_APPLE instead of LAPIS_BLOCK presumably 1.12 migration error (322:0:1 should be golden_apple, not lapis_block). --- uSkyBlock-Core/src/main/resources/challenges.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/resources/challenges.yml b/uSkyBlock-Core/src/main/resources/challenges.yml index 24aa1d83b..8079178f1 100644 --- a/uSkyBlock-Core/src/main/resources/challenges.yml +++ b/uSkyBlock-Core/src/main/resources/challenges.yml @@ -1250,7 +1250,7 @@ ranks: - TROPICAL_FISH:1 - COOKED_PORKCHOP:1 - COOKIE:1 - - LAPIS_BLOCK:1 + - GOLDEN_APPLE:1 - GOLDEN_CARROT:1 - MUSHROOM_STEW:1 - PUMPKIN_PIE:1 From 03d26be91050cd7e272894d8c8c993c1247bea86 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 22 Jan 2021 01:26:59 +0000 Subject: [PATCH 060/190] Also deploy parent and plugin pom --- po-utils/pom.xml | 14 +------------- pom.xml | 17 +++++++++++------ scripts/deploy-release.sh | 10 +++++++++- scripts/deploy-staging.sh | 10 +++++++++- uSkyBlock-API/pom.xml | 9 +++++---- uSkyBlock-AWE370/pom.xml | 12 ------------ uSkyBlock-Core/pom.xml | 12 ------------ uSkyBlock-FAWE/pom.xml | 12 ------------ uSkyBlock-Plugin/pom.xml | 5 ----- 9 files changed, 35 insertions(+), 66 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 59c05202b..e9688c5ed 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -11,18 +11,6 @@ jar po-utils - - false - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - org.jetbrains @@ -98,4 +86,4 @@ - \ No newline at end of file + diff --git a/pom.xml b/pom.xml index 422dae602..430326aec 100644 --- a/pom.xml +++ b/pom.xml @@ -28,9 +28,6 @@ 1.8 1.8 - - true - 2.1 4.12 @@ -49,11 +46,19 @@ - scm:git:git://github.com/rlf/uSkyBlock.git - scm:git:git://github.com/rlf/uSkyBlock.git - https://github.com/rlf/uSkyBlock.git + scm:git:git://github.com/uskyblock/uSkyBlock.git + scm:git:git://github.com/uskyblock/uSkyBlock.git + https://github.com/uskyblock/uSkyBlock.git + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo + + + ${finalName} diff --git a/scripts/deploy-release.sh b/scripts/deploy-release.sh index fc9b7b659..02235caf8 100644 --- a/scripts/deploy-release.sh +++ b/scripts/deploy-release.sh @@ -10,10 +10,18 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + $HOME/build/uskyblock/uSkyBlock/target/mvn-repo/ \ + travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ + travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ @@ -23,7 +31,7 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ + $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ echo -e "Publishing javadocs...\n" diff --git a/scripts/deploy-staging.sh b/scripts/deploy-staging.sh index f8454e19f..d415b97d2 100644 --- a/scripts/deploy-staging.sh +++ b/scripts/deploy-staging.sh @@ -10,10 +10,18 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + $HOME/build/uskyblock/uSkyBlock/target/mvn-repo/ \ + travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ + travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ @@ -23,7 +31,7 @@ if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ + $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ echo -e "Publishing javadocs...\n" diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index ea77dedaa..0caa1cacb 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -7,12 +7,11 @@ com.github.rlf uSkyBlock-API 2.8.10-SNAPSHOT + UTF-8 - dev - github - false + internal.repo @@ -20,12 +19,14 @@ file://${project.build.directory}/mvn-repo + spigotmc.org https://hub.spigotmc.org/nexus/content/repositories/public + org.spigotmc @@ -77,4 +78,4 @@ - \ No newline at end of file + diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 1b148bc85..8e9527dc4 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -10,10 +10,6 @@ 4.0.0 uSkyBlock-AWE370 - - false - - org.primesoft.asyncworldedit @@ -46,12 +42,4 @@ - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 2c3756153..f1bdf7248 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -11,18 +11,6 @@ jar uSkyBlock-Core - - false - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index e5230b07a..3ced4c628 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -10,10 +10,6 @@ 4.0.0 uSkyBlock-FAWE - - false - - IntellectualSites @@ -54,14 +50,6 @@ - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index af0af1365..aa29d7631 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -11,11 +11,6 @@ jar uSkyBlock-Plugin - - github - true - - uSkyBlock-${project.version} From f8b9b274ac293646de3f4eac9849379748eea3ef Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 22 Jan 2021 01:37:22 +0000 Subject: [PATCH 061/190] Release v2.8.10 --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index e9688c5ed..a629e1ad9 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10-SNAPSHOT + 2.8.10 4.0.0 jar diff --git a/pom.xml b/pom.xml index 430326aec..fe240549c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.10-SNAPSHOT + 2.8.10 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 0caa1cacb..5558b3435 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.10-SNAPSHOT + 2.8.10 UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 8e9527dc4..9a3487e4c 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10-SNAPSHOT + 2.8.10 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index f1bdf7248..6b03d7fba 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10-SNAPSHOT + 2.8.10 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 3ced4c628..58b0ea2b0 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10-SNAPSHOT + 2.8.10 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index aa29d7631..ba44376e4 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10-SNAPSHOT + 2.8.10 4.0.0 jar From 0ce0f3948b298d3e8a7c18a2a5d5744d6014a949 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 22 Jan 2021 01:56:31 +0000 Subject: [PATCH 062/190] Version to 2.9.0-SNAPSHOT --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index a629e1ad9..d282f8dd0 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10 + 2.9.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index fe240549c..0323ef243 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.8.10 + 2.9.0-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 5558b3435..6c9e779a4 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.8.10 + 2.9.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 9a3487e4c..49d4920d1 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10 + 2.9.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 6b03d7fba..2bbdb9ee9 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10 + 2.9.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 58b0ea2b0..3e4720a2d 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10 + 2.9.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index ba44376e4..61e5bf501 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.8.10 + 2.9.0-SNAPSHOT 4.0.0 jar From 20b7f8a2e69b6f959267751b86ed75b02ad7fe4a Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 24 Jan 2021 23:45:51 +0000 Subject: [PATCH 063/190] Downgrade FAWE requirement to 1.16 --- .../src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 1335c691d..91bb321d1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -117,7 +117,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage new String[]{"Vault", "1.7.0", "optional"}, new String[]{"WorldEdit", "7.0", "optionalIf", "FastAsyncWorldEdit"}, new String[]{"WorldGuard", "7.0"}, - new String[]{"FastAsyncWorldEdit", "1.16.1", "optional"}, + new String[]{"FastAsyncWorldEdit", "1.16", "optional"}, new String[]{"Multiverse-Core", "2.5", "optional"}, new String[]{"Multiverse-Portals", "2.5", "optional"}, new String[]{"Multiverse-NetherPortals", "2.5", "optional"}, From a5c5f3dbcce4db81d24b243eb816070b2188ab6b Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 27 Jan 2021 03:57:30 +0000 Subject: [PATCH 064/190] Use our bukkit-utils repo as submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 65af88c30..108b7e38b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "bukkit-utils"] path = bukkit-utils - url = git@github.com:rlf/bukkit-utils.git + url = git@github.com:uskyblock/bukkit-utils.git From a0b10e5bb61e773ce0fd057e8bfab4808b341c80 Mon Sep 17 00:00:00 2001 From: BradBouquio Date: Thu, 28 Jan 2021 22:30:36 -0500 Subject: [PATCH 065/190] Fixed the cursor location being reset upon menu click. (#13) * Fixed the cursor location being reset upon menu click. --- .../ultimateskyblock/menu/SkyBlockMenu.java | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 55542c7b0..3d2c0a05a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -805,14 +805,12 @@ public void onClick(InventoryClickEvent event) { private void onClickRestartMenu(final InventoryClickEvent event, final Player p, ItemMeta meta, int slotIndex, ItemStack currentItem) { event.setCancelled(true); if (slotIndex == 0) { - p.closeInventory(); p.openInventory(createMainMenu(p)); } else if (currentItem != null && meta != null && meta.getDisplayName() != null) { String schemeName = stripFormatting(meta.getDisplayName()); IslandPerk islandPerk = plugin.getPerkLogic().getIslandPerk(schemeName); if (plugin.getPerkLogic().getSchemes(p).contains(schemeName) && p.hasPermission(islandPerk.getPermission())) { if (plugin.getConfirmHandler().millisLeft(p, "/is restart") > 0) { - p.closeInventory(); p.performCommand("island restart " + schemeName); } else { p.performCommand("island restart " + schemeName); @@ -839,18 +837,14 @@ private void updateRestartMenuTimer(final Player p, final Inventory inventory) { private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta meta, int slotIndex, int menuSize) { event.setCancelled(true); if (slotIndex == 0) { - p.closeInventory(); p.performCommand("island create"); } else if (slotIndex == menuSize-2) { - p.closeInventory(); p.performCommand("island spawn"); } else if (slotIndex == menuSize-1) { - p.closeInventory(); p.performCommand("island accept"); } else if (meta != null && meta.getDisplayName() != null) { String schemeName = stripFormatting(meta.getDisplayName()); if (plugin.getPerkLogic().getSchemes(p).contains(schemeName)) { - p.closeInventory(); p.performCommand("island create " + schemeName); } else { p.sendMessage(tr("\u00a7eYou do not have access to that island-schematic!")); @@ -866,53 +860,39 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P PlayerInfo playerInfo = plugin.getPlayerInfo(p); IslandInfo islandInfo = plugin.getIslandInfo(playerInfo); if (currentItem.getType() == Material.JUNGLE_SAPLING) { - p.closeInventory(); p.performCommand("island biome"); } else if (currentItem.getType() == Material.PLAYER_HEAD) { - p.closeInventory(); p.performCommand("island party"); } else if (currentItem.getType() == Material.RED_BED) { - p.closeInventory(); p.performCommand("island sethome"); p.performCommand("island"); } else if (currentItem.getType() == Material.GRASS) { - p.closeInventory(); p.performCommand("island spawn"); } else if (currentItem.getType() == Material.HOPPER) { - p.closeInventory(); p.performCommand("island setwarp"); p.performCommand("island"); } else if (currentItem.getType() == Material.WRITABLE_BOOK) { - p.closeInventory(); p.performCommand("island log"); } else if (currentItem.getType() == Material.OAK_DOOR) { - p.closeInventory(); p.performCommand("island home"); } else if (currentItem.getType() == Material.EXPERIENCE_BOTTLE) { - p.closeInventory(); p.performCommand("island level"); } else if (currentItem.getType() == Material.DIAMOND_ORE) { - p.closeInventory(); p.performCommand("c"); } else if (currentItem.getType() == Material.END_STONE || currentItem.getType() == Material.END_PORTAL_FRAME) { - p.closeInventory(); p.performCommand("island togglewarp"); p.performCommand("island"); } else if (currentItem.getType() == Material.IRON_BARS && islandInfo.isLocked()) { - p.closeInventory(); p.performCommand("island unlock"); p.performCommand("island"); } else if (currentItem.getType() == Material.IRON_BARS && !islandInfo.isLocked()) { - p.closeInventory(); p.performCommand("island lock"); p.performCommand("island"); } else if (slotIndex == 17) { if (islandInfo.isLeader(p) && plugin.getConfig().getBoolean("island-schemes-enabled", true)) { - p.closeInventory(); p.openInventory(createRestartGUI(p)); } else { if (plugin.getConfirmHandler().millisLeft(p, "/is leave") > 0) { - p.closeInventory(); p.performCommand("island leave"); } else { p.performCommand("island leave"); @@ -921,7 +901,6 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P } } else { if (!isExtraMenuAction(p, currentItem)) { - p.closeInventory(); p.performCommand("island"); } } @@ -1019,7 +998,6 @@ private void onClickLogMenu(InventoryClickEvent event, Player p, int slotIndex) if (slotIndex < 0 || slotIndex > 35) { return; } - p.closeInventory(); p.performCommand("island"); } @@ -1046,7 +1024,6 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt && currentItem != null && currentItem.getType() != Material.AIR) { // Pagination - p.closeInventory(); p.openInventory(displayChallengeGUI(p, currentItem.getAmount(), playerName)); return; } @@ -1055,7 +1032,6 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt return; } if ((slotIndex % 9) > 0) { // 0,9... are the rank-headers... - p.closeInventory(); if (currentItem.getItemMeta() != null) { String challenge = currentItem.getItemMeta().getDisplayName(); String challengeName = stripFormatting(challenge); @@ -1063,7 +1039,6 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt } p.openInventory(displayChallengeGUI(p, page, playerName)); } else { - p.closeInventory(); if (slotIndex < (CHALLENGE_PAGESIZE/2)) { // Upper half if (page > 1) { p.openInventory(displayChallengeGUI(p, page - 1, playerName)); @@ -1089,7 +1064,6 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, return; } if (slotIndex == 0 && currentItem.getType() == Material.OAK_SIGN) { - p.closeInventory(); p.performCommand("island"); return; } @@ -1115,7 +1089,6 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, ItemStack menuIcon = biomeMenu.getIcon(); if (currentItem.getType() == menuIcon.getType() && currentItem.getDurability() == menuIcon.getDurability()) { String radius = PlayerUtil.getMetadata(p, "biome.radius", "all"); - p.closeInventory(); p.performCommand("island biome " + biomeMenu.getId() + " " + radius); return; } @@ -1129,7 +1102,6 @@ private void onClickPermissionMenu(InventoryClickEvent event, ItemStack currentI } IslandInfo islandInfo = plugin.getIslandInfo(p); if (!plugin.getIslandInfo(p).isLeader(p)) { - p.closeInventory(); p.openInventory(displayPartyGUI(p)); } String[] playerPerm = inventoryName.split(" "); @@ -1143,17 +1115,14 @@ private void onClickPermissionMenu(InventoryClickEvent event, ItemStack currentI } for (PartyPermissionMenuItem item : permissionMenuItems) { if (currentItem.getType() == item.getIcon().getType()) { - p.closeInventory(); islandInfo.togglePerm(pname, item.getPerm()); p.openInventory(displayPartyPlayerGUI(p, pname)); return; } } if (currentItem.getType() == Material.OAK_SIGN) { - p.closeInventory(); p.openInventory(displayPartyGUI(p)); } else { - p.closeInventory(); p.openInventory(displayPartyPlayerGUI(p, pname)); } } @@ -1164,10 +1133,8 @@ private void onClickPartyMenu(InventoryClickEvent event, ItemStack currentItem, return; } if (meta == null || currentItem.getType() == Material.OAK_SIGN) { - p.closeInventory(); p.performCommand("island"); } else if (skull != null && plugin.getIslandInfo(p).isLeader(p)) { - p.closeInventory(); p.openInventory(displayPartyPlayerGUI(p, skull.getOwner())); } } From 1d77893656d18e7200d62e2621479cf372de7cd3 Mon Sep 17 00:00:00 2001 From: BradBouquio Date: Sun, 31 Jan 2021 10:26:43 -0500 Subject: [PATCH 066/190] Better calculation for challenge pages (#15) * Better calculation for challenge pages --- .../challenge/ChallengeLogic.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index f450a5b34..92f54e88f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -470,24 +470,37 @@ public void populateChallengeRank(Inventory menu, PlayerInfo pi, int page, boole private List getRanksForPage(int page, List ranksOnPage) { int rowsToSkip = (page - 1) * ROWS_OF_RANKS; - for (Iterator it = ranksOnPage.iterator(); it.hasNext(); ) { - Rank rank = it.next(); - int rowsInRank = getRows(rank); - if (rowsToSkip <= 0 || ((rowsToSkip - rowsInRank) < 0)) { + List allRanks = new ArrayList<>(ranksOnPage); + + int i = 1; + for (Iterator it = ranksOnPage.iterator(); it.hasNext(); i++) { + it.next(); + int rowsInRanks = calculateRows(allRanks.subList(0,i)); + if (rowsToSkip <= 0 || ((rowsToSkip - rowsInRanks) < 0)) { return ranksOnPage; } - rowsToSkip -= rowsInRank; it.remove(); } return ranksOnPage; } private int calculateRows(List ranksOnPage) { - int row = 0; + int totalRows = 0; + int previousRowsOnPage = 0; + int currentRows; + for (Rank rank : ranksOnPage) { - row += getRows(rank); + currentRows = getRows(rank); + totalRows += currentRows; + + if (previousRowsOnPage < 5 && (currentRows + previousRowsOnPage) > 5) { + totalRows = totalRows + (5 - previousRowsOnPage); + previousRowsOnPage = currentRows; + } else { + previousRowsOnPage = previousRowsOnPage + currentRows; + } } - return row; + return totalRows; } private int getRows(Rank rank) { From 870bddb479e5bc8ed67ee1c650eb1dcc371622e7 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 22 Feb 2021 13:49:05 +0000 Subject: [PATCH 067/190] Remove suggest Paper --- .../src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 1 - 1 file changed, 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 91bb321d1..0b974816f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -234,7 +234,6 @@ public void run() { }, getConfig().getLong("init.initDelay", 50L)); metricsManager = new MetricsManager(this); - PaperLib.suggestPaper(this); } public synchronized boolean isRequirementsMet(CommandSender sender, Command command, String... args) { From f30c031e0d5bf6e31af648eb8a9dc68797d32088 Mon Sep 17 00:00:00 2001 From: Treppenhaus <53356121+Treppenhaus@users.noreply.github.com> Date: Mon, 22 Feb 2021 14:50:23 +0100 Subject: [PATCH 068/190] small german language update (de.po) (#1281) * small german language update I did some changes to messages which would be used often * small german language fixes (de.po) * Update de.po / even more changes --- uSkyBlock-Core/src/main/po/de.po | 307 +++++++++++++++++-------------- 1 file changed, 169 insertions(+), 138 deletions(-) diff --git a/uSkyBlock-Core/src/main/po/de.po b/uSkyBlock-Core/src/main/po/de.po index 4aa4e30b4..c31f836e4 100644 --- a/uSkyBlock-Core/src/main/po/de.po +++ b/uSkyBlock-Core/src/main/po/de.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: 1.5\n" "Report-Msgid-Bugs-To: \n" "PO-Revision-Date: 2016-10-16 17:54+0200\n" -"Last-Translator: I9hdkill I9hdkill@spigotmc.org\n" +"Last-Translator: Treppenhaus\n" "Language-Team: DE \n" "Language: de\n" "MIME-Version: 1.0\n" @@ -93,19 +93,19 @@ msgid "{0}''s Wither" msgstr "{0}''s Wither" msgid "§eYou can not use another island''s portals!" -msgstr "" +msgstr "§eDu kannst keine Portale auf fremden Inseln benutzen!" msgid "§eVillager-trading isn't allowed." -msgstr "" +msgstr "§eDas Handeln mit Dorfbewohnern ist nicht erlaubt." msgid "§eTrading isn't allowed on other islands. Do it in spawn." msgstr "§eHandeln ist auf fremden Inseln nicht erlaubt. Handel am Spawn" msgid "§eRiding is only allowed on your own island!" -msgstr "" +msgstr "§eDu kannst nur auf deiner eigenen Insel reiten!" msgid "§eYou cannot break vehicles while being a visitor!" -msgstr "" +msgstr "§eAls Besucher kannst du keine Fahrzeuge zerstören!" msgid "§4You can only convert obsidian once every 10 seconds" msgstr "§4Du kannst Obsidian nur alle 10 Sekunden konvertieren" @@ -120,11 +120,10 @@ msgid "§4It''s a bad idea to replace your lava!" msgstr "§4Es ist eine schlechte Idee deine Lava zu ersetzen!" msgid "§eYou cannot hurt island-members." -msgstr "§eDu kannst keine Island Mitglieder angreifen" +msgstr "§eDu kannst keine Insel-Mitglieder angreifen" msgid "§4That player has forbidden you from teleporting to their island." -msgstr "" -"§4Dieser Spieler hat dir Verboten sich auf seine Insel zu Teleportieren." +msgstr "§4Dieser Spieler hat dir verboten, dich zu seiner Insel zu teleportieren!" msgid "§4That island is §clocked.§e No teleporting to the island." msgstr "§4Diese Insel ist gesperrt. Kein Teleport zu dieser Insel" @@ -134,21 +133,24 @@ msgid "" "§4{0} is limited. §eScanning your island to see if you are allowed to place " "more, please be patient" msgstr "" +"§4{0} sind begrenzt. §eDeine Insel wird gescannt, um zu sehen, ob du mehr davon platzieren kannst." +"Bitte Gedulde dich einen Moment..." msgid "§e... Scanning complete, you can try again" -msgstr "" +msgstr "§e... Scan abgeschlossen! Du kannst es erneut versuchen." #, java-format msgid "" "§4You''ve hit the {0} limit!§e You can''t have more of that type on your " "island!§9 Max: {1,number}" -msgstr "" +msgstr "§4Du hast das Limit an {0} erreicht!" +"§9 Max: {1,number}" msgid "§eYou can only use spawn-eggs on your own island." -msgstr "§eDu kannst Spawn-Eier nur auf Deiner eigenen Insel nutzen" +msgstr "§eDu kannst Spawneggs nur auf deiner eigenen Insel nutzen" msgid "§cYou have reached your spawn-limit for your island." -msgstr "§cDas Spawnlimit für Deine Insel wurde erreicht" +msgstr "§cDas Spawnlimit für deine Insel wurde erreicht" msgid "§eVisitors can't drop items!" msgstr "§eBesucher können keine Items droppen" @@ -167,11 +169,10 @@ msgid "§cLocked:§e That island is locked! No entry allowed." msgstr "§cAbgeschloßen:§e Diese Insel ist geschlossen, kein Eintritt möglich" msgid "Something went wrong saving the island and/or party data!" -msgstr "Etwas ist Schiefgelaufen beim speichern der Insel/Spieler Daten...!" +msgstr "Beim speichern deiner Insel/Spieler-Daten ist etwas schief gelaufen...!" msgid "Converting data to UUID, this make take a while!" -msgstr "" -"Die Daten werden in das UUID Format konvertiert. Dies kann lange dauern!" +msgstr "Die Daten werden in das UUID Format konvertiert. Dies kann lange dauern!" msgid "§cMAINTENANCE:§e uSkyBlock is currently in maintenance mode" msgstr "§cWARTUNGSMODUS:§e uSkyBlock ist derzeit im Wartungsmodus" @@ -193,12 +194,10 @@ msgid "§4Player is already assigned to this island!" msgstr "§4Dieser Spieler gehört bereits zu deiner Insel!" msgid "§4You must be closer to your island to set your skyblock home!" -msgstr "" -"§4Du musst Dich näher an Deiner Insel befinden, um dein SkyBlock Home zu " -"setzen!" +msgstr "§4Du musst Dich näher an deiner Insel befinden, um dein SkyBlock Home zu setzen!" msgid "§aYour skyblock home has been set to your current location." -msgstr "§aDein SkyBlock Home wurde an Deine aktuelle Position gesetzt." +msgstr "§aDein SkyBlock Home wurde an deine aktuelle Position gesetzt." msgid "§4Your current location is not a safe home-location." msgstr "§4Deine jetztige Home-Position ist nicht sicher" @@ -226,7 +225,7 @@ msgstr "§cDieses Kommando ist derzeit deaktiviert!" #, java-format msgid " §f{0}x §7{1}" -msgstr "" +msgstr " §f{0}x §7{1}" #, java-format msgid "§eStill the following blocks short: {0}" @@ -342,12 +341,16 @@ msgid "" "members to teleport to\n" "the island." msgstr "" +"setze den Insel-Warp,\n" +"welcher nicht-Gruppenmitgliedern\n" +"erlaubt, sich zu der Insel\n" +"zu teleportieren." msgid "Toggle Island Warp" msgstr "Schaltet den Insel Warp an und aus" msgid "toggle the island''s warp." -msgstr "kann den Insel Warp aktivieren und deaktivieren" +msgstr "den Insel Warp aktivieren und deaktivieren" msgid "" "toggle the island''s warp,\n" @@ -355,12 +358,16 @@ msgid "" "on or off at anytime, but\n" "not set the location." msgstr "" +"erlaubt, den Inselwarp zu,\n" +"de-/aktivieren, aber nicht\n" +"die Position zu setzen." + msgid "Invite Players" msgstr "Spieler einladen" msgid "invite others to the island." -msgstr "kann andere Spieler auf die Insel einladen" +msgstr "andere Spieler auf die Insel einladen" msgid "" "invite\n" @@ -370,13 +377,13 @@ msgid "" msgstr "" "Lade noch andere Spieler\n" "auf Deine Insel ein\n" -"Es ist noch mehr Platz!" +"Hier ist genug Platz!" msgid "Kick Players" msgstr "Spieler kicken" msgid "kick others from the island." -msgstr "kann andere von der Insel entfernen" +msgstr "andere von der Insel entfernen" msgid "" "kick\n" @@ -385,9 +392,9 @@ msgid "" "the island leader." msgstr "" "Rauswerfen\n" -"Kann anderen Mitglieder rauswerfen\n" -"aber können nicht den \n" -"Besitzer rauswerfen" +"andere Mitglieder rauswerfen\n" +"aber nicht den\n" +"Besitzer." msgid "Ocean" msgstr "Ocean" @@ -443,7 +450,7 @@ msgid "" "spawn. Hostile mobs will\n" "spawn normally." msgstr "" -"Das Dschungel biom ist farbenfroh\n" +"Das Dschungelbiom ist farbenfroh\n" "Passive Tiere (Inklusive Katzen) spawnen\n" "Monster spawnen normal" @@ -550,7 +557,7 @@ msgstr "" "spawnen normal" msgid "Flower Forest" -msgstr "" +msgstr "Blumenwald" msgid "" "The flower forest biome.\n" @@ -558,7 +565,7 @@ msgid "" "normally and hostile\n" "mobs will spawn." msgstr "" -"The flower forest biome.\n" +"The Blumenwald-Biom.\n" "normale und passive Mobs\n" "spawnen normal" @@ -579,14 +586,14 @@ msgstr "" "spawnen normal" msgid "Ice Plains" -msgstr "" +msgstr "Ice Plains" msgid "" "The ice-plains biome is an advanced biome.\n" "Mobs will spawn naturally.\n" "including polar-bears" msgstr "" -"The ice-plains biome is an advanced biome.\n" +"Das Ice-Plains Biom ist ein besonderes Biom.\n" "Mobs spawnen normal.\n" "inklusiv Polarbären" @@ -615,9 +622,10 @@ msgid "" "§ea permission. Change the\n" "§epermission by clicking it." msgstr "" -"§eZeige auf ein Icon um die \n" +"§eFahre mit der Maus\n" +"§eüber ein Icon um die \n" "§eRechte zu sehen. Klicke\n" -"§edarauf um diese zu ändern." +"§edarauf, um diese zu ändern." msgid "§fThis player §acan" msgstr "§fDieser Spieler §akann" @@ -650,6 +658,11 @@ msgid "" "§eleader can change permissions\n" "§eby clicking a player''s icon." msgstr "" +"§eFahre mit der Maus über\n" +"§edas Icon eines Spielers, um seine\n" +"§eRechte einzusehen. Der Inselbesitzer" +"§ekann die Rechte ändern, indem er\n" +"§edas Icon anklickt." #, java-format msgid "§e{0}''s§9 Permissions" @@ -673,7 +686,7 @@ msgid "§e" msgstr "§e" msgid "Island Log" -msgstr "Insel Log" +msgstr "Insel Logbuch" msgid "" "§eClick here to return to\n" @@ -686,7 +699,7 @@ msgid "§e§lIsland Log" msgstr "§e§lInsel Logbuch" msgid "Island Biome" -msgstr "Insel Biome" +msgstr "Insel Biom" #, java-format msgid "Biome: {0}" @@ -696,7 +709,7 @@ msgid "§2§lThis is your current biome." msgstr "§2§lDas ist dein aktuelles Biom." msgid "§e§lClick to change to this biome." -msgstr "§e§lKlick hier um zu diesem Biom zu wechseln" +msgstr "§e§lKlicke hier, um zu diesem Biom zu wechseln" msgid "You cannot use this biome." msgstr "Du kannst dieses Biom nicht nutzen" @@ -715,17 +728,17 @@ msgid "§c-" msgstr "" msgid "Decrease radius of biome-change" -msgstr "" +msgstr "Verringert den Radius des Biomwechsels" #, java-format msgid "Current radius: {0}" -msgstr "" +msgstr "Aktueller Radius: {0}" msgid "§2+" msgstr "" msgid "Increase radius of biome-change" -msgstr "" +msgstr "Vergrößert den Radius des Biomwechsels" msgid "§7Current page" msgstr "§7Derzeitige Seite" @@ -777,10 +790,10 @@ msgstr "" "§7({0})" msgid "§a§lReturn to Spawn" -msgstr "" +msgstr "§a§lZum Spawn zurückkehren" msgid "Teleport to the spawn area." -msgstr "" +msgstr "Zum Spawnbereich teleportieren" msgid "§a§lJoin an Island" msgstr "§a§lTrete einer Insel bei" @@ -795,6 +808,14 @@ msgid "" "§e§lClick here to accept an invite!\n" "§e§l(You must be invited first)" msgstr "" +"WMöchtest du der Insel eines anderen\n" +"Spielers beitreten, anstatt deine\n" +"eigene zu starten? Wenn dich ein\n" +"Spieler zu seiner Insel einlädt,\n" +"kannst du hier klicken, oder\n" +"§e/island accept§f nutzen, um beizutreten.\n" +"§e§lKlicke hier, um eine Einladung anzunehmen!\n" +"§e§l(Du musst eine Einladung erhalten haben)" msgid "Island Menu" msgstr "Insel Menü" @@ -809,6 +830,10 @@ msgid "" "island using §b/island sethome\n" "§e§lClick here to return home." msgstr "" +"Kehre zu deinem Insel-Home zurück.\n" +"Du kannst deinen Home-Punkt jederzeit ändern:\n" +"§b/island sethome\n" +"§e§lKlicke hier, um zum Home-Punkt zurückzukehren" msgid "§a§lChallenges" msgstr "§a§lAufgaben" @@ -820,11 +845,11 @@ msgid "" "and titles." msgstr "" "Zeigt eine Liste von §9Aufgaben§f, die\n" -"Du auf Deiner Insel abschliessen kannst\n" -"um Insel Level, Items und Titel freizuschalten" +"Du auf Deiner Insel abschliessen kannst.\n" +"Dafür erhälst du Insel-Level, Items und Titel!" msgid "§e§lClick here to view challenges." -msgstr "§e§lKlick hier um die Aufgaben anzuzeigen" +msgstr "§e§lKlicke hier, um die Aufgaben anzuzeigen" msgid "§4§lChallenges disabled." msgstr "§4§lAufgaben deaktiviert." @@ -848,7 +873,7 @@ msgstr "" "Deine Skyblock Insel vergrößerst und\n" "indem bestimmte Aufgaben abschliesst\n" "Seltene Blöcke fügen mehr Insel Level hinzu\n" -"§e§lKlick hier um das Level zu aktualiseren.\n" +"§e§lKlicek hier, um das Level zu aktualiseren.\n" "§e§l(Muss auf Deiner Insel ausgeführt werden)" msgid "Island Group" @@ -891,7 +916,7 @@ msgid "§e§lClick here to change biomes." msgstr "§e§lKlick hier um das Biom zu ändern." msgid "§c§lYou can't change the biome." -msgstr "§c§lDu kannst das Biome nicht ändern." +msgstr "§c§lDu kannst das Biom nicht ändern." msgid "§a§lIsland Lock" msgstr "§a§lInsel Sperre" @@ -908,10 +933,10 @@ msgstr "" "§fDu können die Insel betreten." msgid "§e§lClick here to unlock your island." -msgstr "§e§lKlick hier um Deine Insel zu entsperren." +msgstr "§e§lKlicke hier, um Deine Insel zu entsperren." msgid "§c§lYou can't change the lock." -msgstr "§c§lDu kannst die Insel nicht Ent,-Sperren" +msgstr "§c§lDu kannst die Sperr-Einstellungen nicht ändern." msgid "" "§eLock Status: §8Inactive\n" @@ -927,7 +952,7 @@ msgstr "" "§fDu dürfen auf der Insel bauen." msgid "§e§lClick here to lock your island." -msgstr "§e§lKlick hier um Deine Insel zu sperren." +msgstr "§e§lKlicke hier, um Deine Insel zu sperren." msgid "§a§lIsland Warp" msgstr "§a§lInsel Warp" @@ -944,7 +969,7 @@ msgstr "" "§fDu kannst ihn mit §d/island setwarp §fsetzen." msgid "§e§lClick here to deactivate." -msgstr "§e§lKlick hier zum Deaktivieren." +msgstr "§e§lKlicke hier zum Deaktivieren." msgid "§c§lYou can't change the warp." msgstr "§c§lDu kannst den Warppunkt nicht verändern." @@ -980,7 +1005,7 @@ msgstr "" "§e§lKlick hier um den Log zu öffnen" msgid "§a§lChange Home Location" -msgstr "§a§lWechsel die Home Position" +msgstr "§a§lÄnderel die Home Position" msgid "" "When you teleport to your\n" @@ -1001,9 +1026,13 @@ msgid "" "this point when they teleport\n" "to your island." msgstr "" +"Wenn der Warp aktiviert ist,\n" +"werden andere Spieler zu diesem\n" +"Punkt gebracht, wenn sie sich zu\n" +"deiner Insel teleportieren." msgid "§e§lClick here to change." -msgstr "§e§lKlick hier zum ändern." +msgstr "§e§lKlicke hier zum ändern." msgid "§c§lRestart Island" msgstr "§c§lInsel neustarten" @@ -1013,7 +1042,7 @@ msgid "" "§4WARNING! §cwill remove your items and island!" msgstr "" "Startet die Insel neu\n" -"§4ACHTUNG! §centfernt alle Deine Items und Deine Insel!" +"§4ACHTUNG! §cDeine Insel und alle Items werden vernichtet!" msgid "§c§lLeave Island" msgstr "§c§lInsel verlassen" @@ -1023,7 +1052,7 @@ msgid "" "§4WARNING! §cwill remove all your items!" msgstr "" "Verlässt Deine Insel.\n" -"§4ACHTUNG! §cDies entfernt alle Items!" +"§4ACHTUNG! §cDies entfernt all deine Items!" msgid "§cClick to leave" msgstr "§cKlicke um zu verlassen" @@ -1044,7 +1073,7 @@ msgstr "§a§lKehre zum Hauptmenü zurück" #, java-format msgid "§cClick within §9{0}§c to restart!" msgstr "" -"§cKlicke innerhalb von §9{0}§c,\n" +"§cKlicke innerhalb von §9{0}§c,\n" "§cwenn Du wirklich neu starten möchtest!" msgid "§aClick to restart!" @@ -1199,7 +1228,7 @@ msgid "§b{0}§d locked the island." msgstr "§b{0}§d hat die Insel gesperrt." msgid "§4Since your island is locked, your incoming warp has been deactivated." -msgstr "§4Seit deine Insel gesperrt ist, ist dein Warp deaktiviert." +msgstr "§4Weil deine Insel gesperrt ist, ist dein Warp deaktiviert." #, java-format msgid "§b{0}§d deactivated the island warp." @@ -1281,7 +1310,7 @@ msgstr "" #, java-format msgid "§eWALL OF FAME (page {0} of {1}):" -msgstr "§eRangliste der Inseln sortiert nach Insel Leveln (Seite {0} von {1}):" +msgstr "§eRangliste der Inseln sortiert nach Insel Level (Seite {0} von {1}):" #, java-format msgid "§4Top ten list is empty! Only islands above level {0} is considered." @@ -1296,7 +1325,7 @@ msgid "§a#%2d §7(%5.2f): §e%s §7%s" msgstr "§a#%2d §7(%5.2f): §e%s §7%s" msgid "Click to warp to the island!" -msgstr "" +msgstr "Klicke, um dich zur Insel zu teleportieren" #, java-format msgid "§eYour rank is: §f{0}" @@ -1315,7 +1344,7 @@ msgstr "um diesen Rang freizuschalten" #, java-format msgid "§4You can complete this {0} more time(s)." -msgstr "" +msgstr "§4Kann noch {0} mal abgeschlossen werden!" #, java-format msgid "§4Requirements will reset in {0} days." @@ -1330,19 +1359,19 @@ msgid "§4Requirements will reset in {0} minutes." msgstr "§4Anforderungen werden in {0} Minuten zurückgesetzt." msgid "§4This challenge is currently unavailable." -msgstr "" +msgstr "§4Diese Challenge ist momentan nicht verfügbar." #, java-format msgid "§4You can complete this again in {0} days." -msgstr "" +msgstr "§4Kann in {0} Tagen erneut abgeschlossen werden." #, java-format msgid "§4You can complete this again in {0} hours." -msgstr "" +msgstr "§4Kann in {0} Stunden erneut abgeschlossen werden." #, java-format msgid "§4You can complete this again in {0} minutes." -msgstr "" +msgstr "§4Kann in {0} Minuten erneut abgeschlossen werden." msgid "§eThis challenge requires:" msgstr "§eDiese Aufgabe erfordert:" @@ -1355,18 +1384,18 @@ msgstr "§eItems werden gegen die Belohnung eingetauscht." #, java-format msgid "§eMust be within {0} meters." -msgstr "§eMuss innerhalb von {0} Meter befinden." +msgstr "§eMuss sich innerhalb von {0} Meter befinden." msgid "§6Item Reward: §a" -msgstr "§6Gegenstandsbelohnung: §a" +msgstr "§6Item-Belohnungg: §a" #, java-format msgid "§6Currency Reward: §a{0}" -msgstr "§6Währungsbelohnung: §a{0}" +msgstr "§6Geld-Belohnung: §a{0}" #, java-format msgid "§6Exp Reward: §a{0}" -msgstr "§6Erfahrungsbelohnung: §a{0}" +msgstr "§6Erfahrungs-Belohnung: §a{0}" #, java-format msgid "§dTotal times completed: §f{0}" @@ -1389,7 +1418,7 @@ msgstr "§4Diese {0} Aufgabe kannst du nicht Wiederholen!" #, java-format msgid "§4You cannot complete the {0} challenge again yet!" -msgstr "" +msgstr "§4Die Challenge {0} kann noch nicht wieder abgeschlossen werden" #, java-format msgid "§eTrying to complete challenge §a{0}" @@ -1402,7 +1431,7 @@ msgstr "§4{0}" #, java-format msgid "§4You must be standing within {0} blocks of all required items." msgstr "" -"§4Du musst in {0} Blöcke Abstand von den benötigten Gegenständen stehen." +"§4Du musst innerhalb {0} Blöcke Abstand von den benötigten Gegenständen stehen." #, java-format msgid "§4Your island must be level {0} to complete this challenge!" @@ -1429,15 +1458,15 @@ msgstr "§eDir fehlen:{0}" #, java-format msgid "§aYou have completed the {0} challenge!" -msgstr "§aDu hast die {0} Aufgabe beendet!" +msgstr "§aDu hast die Aufgabe {0} beendet!" #, java-format msgid "§9{0}§f has completed the §9{1}§f challenge!" -msgstr "§9{0}§f hat die §9{1}§f Aufgabe abgeschlossen!" +msgstr "§9{0}§f hat §9{1}§f Aufgabe abgeschlossen!" #, java-format msgid "§eItem reward(s): §f{0}" -msgstr "§eGegenstandsbelohnung: §f{0}" +msgstr "§eItembelohnung: §f{0}" #, java-format msgid "§eExp reward: §f{0,number,#.#}" @@ -1451,7 +1480,7 @@ msgid "§eYour inventory is §4full§e. Items dropped on the ground." msgstr "§eDein Inventar ist §4voll§e. Die Gegenstände fallen auf den Boden!" msgid "§e§lClick to complete this challenge." -msgstr "§e§lKlick hier um die Aufgabe zu beenden!" +msgstr "§e§lKlicek hier, um die Aufgabe zu beenden!" msgid "§4§lYou can't repeat this challenge." msgstr "§4§lDu kannst diese Aufgabe nicht wiederholen!" @@ -1467,16 +1496,16 @@ msgid "§fthis rank to unlock the next rank." msgstr "§fdiesem Rang, um den nächsten Rang freizuschalten." msgid "§eClick here to show previous page" -msgstr "§eKlick hier um zur vorherigen Seite zu gelangen." +msgstr "§eKlicke hier, um zur vorherigen Seite zu gelangen." msgid "§eClick here to show next page" -msgstr "§eKlick hier um zur nächsten Seite zu gelangen." +msgstr "§eKlicke hier, um zur nächsten Seite zu gelangen." msgid "But you are ALLLLLLL ALOOOOONE!" msgstr "Du bist ALLLLLEEEEEEIIIIINE!" msgid "But you are Yelling in the wind!" -msgstr "But you are Yelling in the wind!" +msgstr "Aber du rufst dem Wind entgegen!" msgid "But your fantasy friends are gone!" msgstr "Deine Fantasiefreunde sind weg!" @@ -1489,7 +1518,7 @@ msgid "§cSorry! {0}" msgstr "§cTschuldigung! {0}" msgid "Either send a message directly to your group, or toggle it on/off." -msgstr "Sende eine Nachricht an deine Gruppe oder schalte es an oder aus." +msgstr "Sende eine Nachricht an deine Gruppe oder schalte Nachrichten an oder aus." msgid "party" msgstr "Party" @@ -1499,7 +1528,7 @@ msgstr "Insel" #, java-format msgid "§cToggled chat to {0} §aON" -msgstr "§cSchaltet den Chat zu {0} §aON" +msgstr "§cSchaltet den Chat zu {0} §aAN" #, java-format msgid "§cRepeat §9{0}§c to toggle it off" @@ -1513,19 +1542,19 @@ msgid "§cCommand only available to players" msgstr "§cKommando nur für Spieler verfügbar" msgid "talk to your island party" -msgstr "redet mit deinen Insel Mitgliedern" +msgstr "rede mit deinen Insel-Mitgliedern" msgid "talk to players on your island" msgstr "rede zu Spielern auf deiner Insel" msgid "manually update the top 10 list" -msgstr "Aktualisiere manuell die 10 Besten Liste!" +msgstr "Aktualisiere die Bestenliste!" msgid "§eGenerating the Top Ten list" -msgstr "§eErstellt die 10 Besten Liste" +msgstr "§eErstell die Bestenliste" msgid "§eFinished generation of the Top Ten list" -msgstr "§eDie 10 Besten Liste wurde erfolgreich erstellt" +msgstr "§eDie Bestenliste wurde erfolgreich erstellt" msgid "purges all abandoned islands" msgstr "Löscht alle verlassenen Inseln" @@ -1534,29 +1563,31 @@ msgid "§4You must provide the age in days to purge!" msgstr "§4Du musst die Zeit für die Säuberung in Tagen angeben!" msgid "§4The level must be a valid number" -msgstr "" +msgstr "§4Das Level muss eine Zahl sein" #, java-format msgid "" "§eFinding all islands that have been abandoned for more than {0} days below " "level {1}" msgstr "" +"§eSuche alle Inseln, die fpr {0} oder mehr Tage verlassen sind" +"level {1}" #, java-format msgid "§4PURGE:§e Do §9usb purge confirm§e within {0} to accept." -msgstr "" +msgstr "§4PURGE:§e Schreibe erneu §9usb purge confirm§einnerhalb {0} um zu akzeptieren." msgid "§4Trying to abort purge" msgstr "§4Versuche Purge abzubrechen" msgid "§4Purge aborted!" -msgstr "" +msgstr "§4Säuberung abgebrochen" msgid "§4A purge is already running.§e Either §9confirm§e or §9stop§e it." -msgstr "" +msgstr "§4Doe Säuberung läft bereits. §9Du kannst sie bestätigen oder abbrechen." msgid "§4Starting purge..." -msgstr "§4Starte Purge" +msgstr "§4Starte Säuberung" msgid "Controls player-cooldowns" msgstr "Kontrolliert Spieler-Abklingzeiten" @@ -1700,7 +1731,7 @@ msgstr "§eDerzeit sind keine verwaisten Inseln registriert" #, java-format msgid "§eOrphans ({0}/{1}): {2}" -msgstr "" +msgstr §eOrphans ({0}/{1}): {2}"" msgid "transfer leadership to another player" msgstr "Übergib die Führung an einen anderen Spieler" @@ -1719,13 +1750,13 @@ msgstr "" #, java-format msgid "§bLeadership transferred by {0}§b to {1}" -msgstr "§bFührung übergeben von {0}§b an {1}" +msgstr "§bDie Leitung von {0}§b an {1} übergeben" msgid "open GUI for config" msgstr "Öffne Konfigurations Menü" msgid "searches config for a specific key" -msgstr "" +msgstr "durchsucht die config nach einem bestimmten Wert" #, java-format msgid "§c{0}§9" @@ -1737,7 +1768,7 @@ msgstr "" #, java-format msgid "Found the following matching {0}:" -msgstr "" +msgstr "Folgende Treffer gefunden: {0}:" msgid "§a

" msgstr "" @@ -1833,7 +1864,7 @@ msgid "§eNo currently shown regions for this player" msgstr "§eFür diesen Spieler werden derzeit keine Regionen gezeigt" msgid "set the ticks between animations" -msgstr "" +msgstr "setze den Cooldown zwischen den Animationen in Ticks" #, java-format msgid "§eAnimation-tick changed to {0}." @@ -1843,15 +1874,16 @@ msgid "§eAnimation-tick must be a valid integer." msgstr "§eAnimation-tick muss ein gültiger Integer sein." msgid "refreshes the existing animations" -msgstr "" +msgstr "aktualisiert die bereits existierenden Animationen" #, java-format msgid "" "- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}" msgstr "" +"- SÄUBERT: {0,number,##}% ({1}/{2}), verstrichen {3}, geschätzte Vervollständigung ~{4}" msgid "§4PURGE:§9 Finished purging abandoned islands." -msgstr "§4PURGE:§9 Verlassene Inseln wurde entfernt." +msgstr "§4PURGE:§9 Verlassene Inseln wurden entfernt." msgid "§4PURGE:§9 Aborted purging abandoned islands." msgstr "§4SÄUBERUNG:§9 Das säubern von verlassenen Inseln wurde abgebrochen." @@ -1868,6 +1900,7 @@ msgid "" "§4PURGE:§9 Scanning done, found {0} candidates, below level {1}, ready for " "purgatory." msgstr "" +"§4SÄUBERUNG:§9 Scan abgeschlossen, {0} Inseln gefunden, die unter Level {1} sind." msgid "§cABORTED:§e Protect-All was aborted!" msgstr "§cABGEBROCHEN:§e Protect-All wurde unterbrochen!" @@ -1875,7 +1908,7 @@ msgstr "§cABGEBROCHEN:§e Protect-All wurde unterbrochen!" #, java-format msgid "§eCompleted protect-all in {0}, {1} new regions were created!" msgstr "" -"§eCompleted wurde in {0} $eabgeschlossen, {1} neue Regionen wurden erstellt!" +"§eProtect-All wurde in {0} $eabgeschlossen, {1} neue Regionen wurden erstellt!" msgid "control debugging" msgstr "Steuert Fehlerüberprüfung" @@ -2025,43 +2058,43 @@ msgid "§4No rank named {0} was found!" msgstr "§4Kein Rang namens {0} wurde gefunden" msgid "various chunk commands" -msgstr "" +msgstr "verschiedene Chunk-Befehle" msgid "regenerate current chunk" -msgstr "" +msgstr "regeneriere aktuellen Chunk" #, java-format msgid "successfully regenerated chunk at {0},{1}" -msgstr "" +msgstr "Chunk bei {0},{1} erfolgreich regeneriert" #, java-format msgid "§4FAILED!§e could not regenerate chunk at {0},{1}" -msgstr "" +msgstr "§4FEHLER!§e Chunk bei {0},{1} konnte nicht regeneriert werden!" msgid "unload current chunk" -msgstr "" +msgstr "aktuellen Chunk unloaden" #, java-format msgid "successfully unloaded chunk at {0},{1}" -msgstr "" +msgstr "Der Chunk bei {0},{1} wurde erfolgreich geunloaded!" #, java-format msgid "§4FAILED!§e could not unload chunk at {0},{1}" -msgstr "" +msgstr "§4FEHLER!§e Chunk bei {0},{1} konnte nicht geunloaded werden!" msgid "load current chunk" -msgstr "" +msgstr "lade aktuellen Chunk" #, java-format msgid "loaded chunk at {0},{1}" -msgstr "" +msgstr "Chunk bei {0},{1} wurde geladen" msgid "only available for players" -msgstr "" +msgstr "Nur für Spieler verfügbar" #, java-format msgid "§4ERROR:§e {0}" -msgstr "" +msgstr "§4FEHLER:§e {0}" msgid "protects all islands (time consuming)" msgstr "Schützt alle Inseln (Zeitaufwändig)" @@ -2101,7 +2134,7 @@ msgid "" "§4Island at this location has members!\n" "§eUse §9/usb island delete §e to delete it." msgstr "" -"§4Die Insel an ihrem Standort hat Mitglieder!\n" +"§4Die Insel an diesem Standort hat Mitglieder!\n" "§eBenutze §9/usb island delete §e um die Insel zu löschen." msgid "removes the player from the island" @@ -2208,10 +2241,10 @@ msgid "imports players and islands from other formats" msgstr "Importiere Spieler und Inseln aus anderen Formaten" msgid "shows perk-information" -msgstr "" +msgstr "zeigt Perk-Informationen" msgid "shows a specific players perks" -msgstr "" +msgstr "zeigt die Perks eines bestimmten Spielers" #, java-format msgid "additional perks {0}" @@ -2318,19 +2351,19 @@ msgid "general island command" msgstr "Allgemeine Insel Befehle" msgid "allows user to bypass cooldowns" -msgstr "" +msgstr "erlaubt, gegen Cooldowns immum zu sein" msgid "allows user to bypass visitor-protections" -msgstr "" +msgstr "erlaubt, trotz der Besucher-Protection abzubauen" msgid "allows user to bypass teleport-delay" -msgstr "" +msgstr "erlaubt, gegen das Teleport-Delay immun zu sein" msgid "allows user to use [usb] signs" -msgstr "" +msgstr "erlaubt, [usb] Schilder zu benutzen" msgid "allows user to place [usb] signs" -msgstr "" +msgstr "erlaubt [usb] Schilder zu platzieren" msgid "complete and list challenges" msgstr "vervollständige und zeige Aufgaben an" @@ -2585,24 +2618,23 @@ msgid "" "§cYour island is in the process of generating, you cannot teleport home " "right now." msgstr "" -"§cDeine Insel wird gerade erstellt. Du kannst dich jetzt nicht auf sie " -"teleportieren" +"§cDeine Insel wird gerade erstellt. Du kannst dich jetzt nicht teleportieren" msgid "§4This command can only be executed by a player" msgstr "§4Dieser Befehl kann nur von Spielern ausgeführt werden" msgid "transfer leadership to another member" -msgstr "Übertrage die Führerrolle zu einem anderen Spieler" +msgstr "Übertrage die Leitung einem anderen Spieler" msgid "§4You can only transfer ownership to party-members!" -msgstr "§4Du kannst die Führerschaft nur auf Gruppenmitglieder übertragen!" +msgstr "§4Du kannst die Leitung nur auf Gruppenmitglieder übertragen!" #, java-format msgid "{0}§e is already leader of your island!" msgstr "{0}§e ist bereits der Anführer der Insel!" msgid "§4Only leader can transfer leadership!" -msgstr "§4Nur Anführer können die Führerschaft übertragen!" +msgstr "§4Nur Anführer können die Leitung übertragen!" #, java-format msgid "{0} tried to take over the island!" @@ -2634,7 +2666,7 @@ msgid "allows user to see others island info" msgstr "erlaubt den Spieler Infos von anderen Insel anzugucken" msgid "§4Hold your horses! §eYou have to be patient..." -msgstr "" +msgstr "§4Gedulde dich doch einmal..." #, java-format msgid "§eBlocks on {0}s Island (page {1,number} of {2,number}):" @@ -2687,7 +2719,7 @@ msgid "delete your island and start a new one." msgstr "Löscht deine Insel und startet eine neue." msgid "exempt player from restart-cooldown" -msgstr "" +msgstr "befreit einen Spieler vom restart-cooldown" msgid "" "§4Only the owner may restart this island. Leave this island in order to " @@ -2860,13 +2892,13 @@ msgstr "" #, java-format msgid "§ePermissions for §9{0}§e:" -msgstr "" +msgstr "§eRechte für §9{0}§e:" msgid "§aON" -msgstr "" +msgstr "§aAN" msgid "§cOFF" -msgstr "" +msgstr "§cAUS" #, java-format msgid "§7 - §6{0}§7 : {1}" @@ -2888,22 +2920,21 @@ msgid "set the island-home" msgstr "Setze dein Home" msgid "show the islands limits" -msgstr "" +msgstr "zeige die Insel-Begrenzungen" msgid "enable/disable warping to your island." msgstr "Aktiviere/Deaktiviere Warping zu deiner Insel." msgid "§4Your island is locked. You must unlock it before enabling your warp." msgstr "" -"§4Deine Insel ist gesperrt. Du musst sie entsperren um das warpen freizu " -"schalten." +"§4Deine Insel ist gesperrt. Du musst sie entsperren um das warpen freizuschalten." #, java-format msgid "§b{0}§d activated the island warp." msgstr "§b{0}§d hat den Insel Warp aktiviert" msgid "§cYou do not have permission to enable/disable your island''s warp!" -msgstr "" +msgstr "§cDu hast keine Rechte den Inselwarp zu de-/aktivieren!" msgid "try to complete a challenge" msgstr "versucht eine Aufgabe abzuschliessen" @@ -2943,35 +2974,35 @@ msgid "§eThe island has been §cLOCKED§e." msgstr "§eDie Insel wurde §cGESPERRT§e." msgid "§9Hold your horses! You have to be patient..." -msgstr "" +msgstr "§9Gedulde dich doch einmal..." msgid "§9Not really patient, are you?" -msgstr "" +msgstr "§9Du bist nicht wirklich ausdauernd, oder?" msgid "§9Be patient, young padawan" -msgstr "" +msgstr "§9Gedulde dich, junger Padawan" msgid "§9Patience you MUST have, young padawan" -msgstr "" +msgstr "§9Du must geduldig sein, junger Padawan!" msgid "§9The two most powerful warriors are patience and time." -msgstr "" +msgstr §9Die zwei stärksten Krieger sind Geduld und Zeit."" msgid "§4Unable to find a safe home-location on your island!" msgstr "§4Es konnte kein sicherer Ort für dein Home gefunden werden!" msgid "§cWARNING: §eTeleporting you to mid-air." -msgstr "§cWARNUNG: §eDu wirst in die Luft geportet." +msgstr "§cWARNUNG: §eDu wirst in die Luft teleportiert." msgid "§aTeleporting you to your island." -msgstr "§aDu wirst zu Deiner Insel teleportiert." +msgstr "§aDu wirst zu deiner Insel teleportiert." #, java-format msgid "§aYou will be teleported in {0} seconds." -msgstr "§aDu wirst in {0} Sekunden Teleportiert." +msgstr "§aDu wirst in {0} Sekunden teleportiert." msgid "§4Unable to warp you to that player''s island!" -msgstr "§4Es ist nicht möglich Dich zu der Insel von dem Spieler zu Warpen!" +msgstr "§4Es ist nicht möglich, dich zur Insel von diesem Spieler zu Warpen!" #, java-format msgid "§aTeleporting you to {0}''s island." From 7a4a5318ea6195da7940dfc181c0f5d705a8da7a Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 13 Mar 2021 22:58:17 +0000 Subject: [PATCH 069/190] Update Crowdin configuration file --- crowdin.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 000000000..93a2ec281 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,3 @@ +files: + - source: /uSkyBlock-Core/src/main/po/keys.pot + translation: /uSkyBlock-Core/src/main/po/%locale_with_underscore%.po From 8a5ef00760c52172b27d7084f3e11a9a1be83b79 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 14 Mar 2021 00:11:24 +0000 Subject: [PATCH 070/190] Fix German po file --- uSkyBlock-Core/src/main/po/de.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/po/de.po b/uSkyBlock-Core/src/main/po/de.po index c31f836e4..d0c2ea510 100644 --- a/uSkyBlock-Core/src/main/po/de.po +++ b/uSkyBlock-Core/src/main/po/de.po @@ -133,7 +133,7 @@ msgid "" "§4{0} is limited. §eScanning your island to see if you are allowed to place " "more, please be patient" msgstr "" -"§4{0} sind begrenzt. §eDeine Insel wird gescannt, um zu sehen, ob du mehr davon platzieren kannst." +"§4{0} sind begrenzt. §eDeine Insel wird gescannt, um zu sehen, ob du mehr davon platzieren kannst." "Bitte Gedulde dich einen Moment..." msgid "§e... Scanning complete, you can try again" @@ -1731,7 +1731,7 @@ msgstr "§eDerzeit sind keine verwaisten Inseln registriert" #, java-format msgid "§eOrphans ({0}/{1}): {2}" -msgstr §eOrphans ({0}/{1}): {2}"" +msgstr "§eOrphans ({0}/{1}): {2}" msgid "transfer leadership to another player" msgstr "Übergib die Führung an einen anderen Spieler" @@ -2986,7 +2986,7 @@ msgid "§9Patience you MUST have, young padawan" msgstr "§9Du must geduldig sein, junger Padawan!" msgid "§9The two most powerful warriors are patience and time." -msgstr §9Die zwei stärksten Krieger sind Geduld und Zeit."" +msgstr "§9Die zwei stärksten Krieger sind Geduld und Zeit." msgid "§4Unable to find a safe home-location on your island!" msgstr "§4Es konnte kein sicherer Ort für dein Home gefunden werden!" From de708a8a032fbe41a570ead8ef098c499ff8746a Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 14 Mar 2021 01:47:43 +0000 Subject: [PATCH 071/190] Update keys.pot --- uSkyBlock-Core/src/main/po/keys.pot | 2264 +++++++++++++-------------- 1 file changed, 1130 insertions(+), 1134 deletions(-) diff --git a/uSkyBlock-Core/src/main/po/keys.pot b/uSkyBlock-Core/src/main/po/keys.pot index e649725e9..0d6aa0fe1 100644 --- a/uSkyBlock-Core/src/main/po/keys.pot +++ b/uSkyBlock-Core/src/main/po/keys.pot @@ -16,30 +16,6 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -msgid "d" -msgstr "" - -msgid "h" -msgstr "" - -msgid "m" -msgstr "" - -msgid "s" -msgstr "" - -#, java-format -msgid "{0,number,0}:{1,number,00}.{2,number,000}" -msgstr "" - -#, java-format -msgid "§f{0}x §7{1}" -msgstr "" - -#, java-format -msgid "§7{0}" -msgstr "" - #, java-format msgid "§eYou do not have access (§4{0}§e)" msgstr "" @@ -48,15 +24,6 @@ msgstr "" msgid "§eInvalid command: {0}" msgstr "" -msgid "Command" -msgstr "" - -msgid "Permission" -msgstr "" - -msgid "Description" -msgstr "" - #, java-format msgid "§7Usage: {0}" msgstr "" @@ -80,2674 +47,2703 @@ msgstr "" msgid "§4Error writing documentation: {0}" msgstr "" -msgid "§cWither Despawned!§e It wandered too far from your island." +msgid "changes the language of the plugin, and reloads" msgstr "" #, java-format -msgid "{0}''s Wither" +msgid "§aSuccessfully changed language to §e{0}" msgstr "" -msgid "§eYou can not use another island''s portals!" +#, java-format +msgid "§cFailed to change language to §e{0}" msgstr "" -msgid "§eVillager-trading isn't allowed." +msgid "§9Supported Languages:\n" msgstr "" -msgid "§eTrading isn't allowed on other islands. Do it in spawn." +#, java-format +msgid "§f{0} §7{1} §9 by {2} §7{3}\n" msgstr "" -msgid "§eRiding is only allowed on your own island!" +msgid "§cUnable to locate any languages." msgstr "" -msgid "§eYou cannot break vehicles while being a visitor!" +msgid "Command" msgstr "" -msgid "§4You can only convert obsidian once every 10 seconds" +msgid "Permission" msgstr "" -msgid "§eChanging your obsidian back into lava. Be careful!" +msgid "Description" msgstr "" -msgid "§eYour inventory must have another empty space!" +#, java-format +msgid "§f{0}x §7{1}" msgstr "" -msgid "§4It''s a bad idea to replace your lava!" +#, java-format +msgid "§7{0}" msgstr "" -msgid "§eYou cannot hurt island-members." +msgid "d" msgstr "" -msgid "§4That player has forbidden you from teleporting to their island." +msgid "h" msgstr "" -msgid "§4That island is §clocked.§e No teleporting to the island." +msgid "m" msgstr "" -#, java-format -msgid "" -"§4{0} is limited. §eScanning your island to see if you are allowed to place " -"more, please be patient" +msgid "s" msgstr "" -msgid "§e... Scanning complete, you can try again" +#, java-format +msgid "{0,number,0}:{1,number,00}.{2,number,000}" msgstr "" #, java-format -msgid "" -"§4You''ve hit the {0} limit!§e You can''t have more of that type on your " -"island!§9 Max: {1,number}" +msgid " §f{0}x §7{1}" msgstr "" -msgid "§eYou can only use spawn-eggs on your own island." +#, java-format +msgid "§eStill the following blocks short: {0}" msgstr "" -msgid "§cYou have reached your spawn-limit for your island." +#, java-format +msgid "§4You can complete this {0} more time(s)." msgstr "" -msgid "§eVisitors can't drop items!" +#, java-format +msgid "§4Requirements will reset in {0} days." msgstr "" #, java-format -msgid "Owner: {0}" +msgid "§4Requirements will reset in {0} hours." msgstr "" -msgid "You cannot pick up other players' loot when you are a visitor!" +#, java-format +msgid "§4Requirements will reset in {0} minutes." msgstr "" -msgid "§cBanned:§e You are banned from this island." +msgid "§4This challenge is currently unavailable." msgstr "" -msgid "§cLocked:§e That island is locked! No entry allowed." +#, java-format +msgid "§4You can complete this again in {0} days." msgstr "" -msgid "Something went wrong saving the island and/or party data!" +#, java-format +msgid "§4You can complete this again in {0} hours." msgstr "" -msgid "Converting data to UUID, this make take a while!" +#, java-format +msgid "§4You can complete this again in {0} minutes." msgstr "" -msgid "§cMAINTENANCE:§e uSkyBlock is currently in maintenance mode" +msgid "§eThis challenge requires:" msgstr "" -#, java-format -msgid "" -"§buSkyBlock§e depends on §9{0}§e >= §av{1}§e but only §cv{2}§e was found!\n" +msgid "§7and more..." msgstr "" -#, java-format -msgid "§buSkyBlock§e depends on §9{0}§e >= §av{1}" +msgid "§eItems will be traded for reward." msgstr "" -msgid "§eYou do not have access to that island-schematic!" +#, java-format +msgid "§eMust be within {0} meters." msgstr "" -msgid "§4Player is already assigned to this island!" +msgid "§6Item Reward: §a" msgstr "" -msgid "§4You must be closer to your island to set your skyblock home!" +#, java-format +msgid "§6Currency Reward: §a{0}" msgstr "" -msgid "§aYour skyblock home has been set to your current location." +#, java-format +msgid "§6Exp Reward: §a{0}" msgstr "" -msgid "§4Your current location is not a safe home-location." +#, java-format +msgid "§dTotal times completed: §f{0}" msgstr "" #, java-format -msgid "" -"§7The pixies are busy changing the biome of your island to §9{0}§7, be " -"patient." +msgid "§7Requires {0}" msgstr "" -msgid "§cYour island is in the process of generating, you cannot create now." +#, java-format +msgid "§4No challenge named {0} found" msgstr "" -msgid "Could not create your Island. Please contact a server moderator." +msgid "§4You must be on your island to do that!" msgstr "" -msgid "§eGetting your island ready, please be patient, it can take a while." +#, java-format +msgid "§4The {0} challenge is not available yet!" msgstr "" -msgid "§cCommand is currently disabled!" +#, java-format +msgid "§4The {0} challenge is not repeatable!" msgstr "" #, java-format -msgid " §f{0}x §7{1}" +msgid "§4You cannot complete the {0} challenge again yet!" msgstr "" #, java-format -msgid "§eStill the following blocks short: {0}" +msgid "§eTrying to complete challenge §a{0}" msgstr "" #, java-format -msgid "§9{0}§7 timed out" +msgid "§4{0}" msgstr "" #, java-format -msgid "" -"§eDoing §9{0}§e is §cRISKY§e. Repeat the command within §a{1}§e seconds to " -"accept!" +msgid "§4You must be standing within {0} blocks of all required items." msgstr "" -msgid "§4** You are entering a protected - but abandoned - island area." +#, java-format +msgid "§4Your island must be level {0} to complete this challenge!" msgstr "" #, java-format -msgid "§d** You are entering §b{0}''s §disland." +msgid "§4Unknown type of challenge: {0}" msgstr "" -msgid "§4** You are leaving an abandoned island." +#, java-format +msgid "" +"§eStill the following entities short:\n" +"{0}" msgstr "" #, java-format -msgid "§d** You are leaving §b{0}''s §disland." +msgid " §4{0} §b{1}" msgstr "" -msgid "§eYour island is now locked. Only your party members may enter." +#, java-format +msgid "§eYou are the following items short:{0}" msgstr "" -msgid "§4You must be the party leader to lock your island!" +#, java-format +msgid "§aYou have completed the {0} challenge!" msgstr "" -msgid "" -"§eYour island is unlocked and anyone may enter, however only you and your " -"party members may build or remove blocks." +#, java-format +msgid "§9{0}§f has completed the §9{1}§f challenge!" msgstr "" -msgid "§4You must be the party leader to unlock your island!" +#, java-format +msgid "§eItem reward(s): §f{0}" msgstr "" #, java-format -msgid "§eWaiting for our turn §c{0,number,###}%" +msgid "§eExp reward: §f{0,number,#.#}" msgstr "" #, java-format -msgid "§9Creating island...§e{0,number,###}%" +msgid "§eCurrency reward: §f{0,number,###.##} {1} §a ({2,number,##.##})%" msgstr "" -msgid "N/A" +msgid "§eYour inventory is §4full§e. Items dropped on the ground." msgstr "" -msgid "§4§lLocked Challenge" +msgid "§e§lClick to complete this challenge." msgstr "" -msgid "READY" +msgid "§4§lYou can't repeat this challenge." msgstr "" #, java-format -msgid "§4The {0} challenge is not available yet!" +msgid "Rank: {0}" msgstr "" -msgid "" -"§cWARNING:§e Could not transfer all the required items to your inventory!" +msgid "§fComplete most challenges in" msgstr "" -msgid "§cNot enough items in chest to complete challenge!" +msgid "§fthis rank to unlock the next rank." msgstr "" -msgid "true" +msgid "§eClick here to show previous page" msgstr "" -msgid "false" +msgid "§eClick here to show next page" msgstr "" -msgid "Challenge Menu" +msgid "§4§lLocked Challenge" msgstr "" -msgid "Change Biome" +#, java-format +msgid "§7Complete {0} more {1} §7challenges" msgstr "" -msgid "change the island''s biome." +#, java-format +msgid "§7Complete {0}" msgstr "" -msgid "Toggle Island Lock" +msgid "to unlock this rank" msgstr "" -msgid "toggle the island''s lock." +msgid "But you are ALLLLLLL ALOOOOONE!" msgstr "" -msgid "Set Island Warp" +msgid "But you are Yelling in the wind!" msgstr "" -msgid "set the island''s warp." +msgid "But your fantasy friends are gone!" msgstr "" -msgid "" -"set the island''s warp,\n" -"which allows non-group\n" -"members to teleport to\n" -"the island." +msgid "But you are Talking to your self!" msgstr "" -msgid "Toggle Island Warp" +#, java-format +msgid "§cSorry! {0}" msgstr "" -msgid "toggle the island''s warp." +msgid "Either send a message directly to your group, or toggle it on/off." msgstr "" -msgid "" -"toggle the island''s warp,\n" -"allowing them to turn it\n" -"on or off at anytime, but\n" -"not set the location." +msgid "party" msgstr "" -msgid "Invite Players" +msgid "island" msgstr "" -msgid "invite others to the island." +#, java-format +msgid "§cToggled chat to {0} §aON" msgstr "" -msgid "" -"invite\n" -"other players to the island if\n" -"there is enough room for more\n" -"members" +#, java-format +msgid "§cRepeat §9{0}§c to toggle it off" msgstr "" -msgid "Kick Players" +#, java-format +msgid "§aToggled chat §cOFF§a for {0}" msgstr "" -msgid "kick others from the island." +msgid "§cCommand only available to players" msgstr "" -msgid "" -"kick\n" -"other players from the island,\n" -"but they are unable to kick\n" -"the island leader." +msgid "talk to players on your island" msgstr "" -msgid "Ocean" +msgid "talk to your island party" msgstr "" -msgid "" -"The ocean biome is the basic\n" -"starting biome for all islands.\n" -"passive mobs like animals will\n" -"not spawn. Hostile mobs will\n" -"spawn normally." +#, java-format +msgid "§ePlayer {0} has no island!" msgstr "" -msgid "Forest" +#, java-format +msgid "§eInvalid player {0} supplied." msgstr "" -msgid "" -"The forest biome will allow\n" -"your island to spawn passive.\n" -"mobs like animals (including\n" -"wolves). Hostile mobs will\n" -"spawn normally." +msgid "Manage challenges for a player" msgstr "" -msgid "Desert" +msgid "resets the challenge for the player" msgstr "" -msgid "" -"The desert biome makes it so\n" -"that there is no rain or snow\n" -"on your island. Passive mobs\n" -"won't spawn. Hostile mobs will\n" -"spawn normally." +msgid "§4Challenge has never been completed" msgstr "" -msgid "Jungle" +#, java-format +msgid "§echallenge: {0} has been reset for {1}" msgstr "" -msgid "" -"The jungle biome is bright\n" -"and colorful. Passive mobs\n" -"(including ocelots) will\n" -"spawn. Hostile mobs will\n" -"spawn normally." +msgid "resets all challenges for the player" msgstr "" -msgid "Swampland" +#, java-format +msgid "§e{0} has had all challenges reset." msgstr "" -msgid "" -"The swamp biome is dark\n" -"and dull. Passive mobs\n" -"will spawn normally and\n" -"slimes have a small chance\n" -"to spawn at night depending\n" -"on the moon phase." +msgid "complete all challenges in the rank" msgstr "" -msgid "Taiga" +#, java-format +msgid "§4No player named {0} was found!" msgstr "" -msgid "" -"The taiga biome has snow\n" -"instead of rain. Passive\n" -"mobs will spawn normally\n" -"(including wolves) and\n" -"hostile mobs will spawn." +#, java-format +msgid "§4Challenge {0} has already been completed" msgstr "" -msgid "Mushroom" +#, java-format +msgid "§eChallenge {0} has been completed for {1}" msgstr "" -msgid "" -"The mushroom biome is\n" -"bright and colorful.\n" -"Mooshrooms are the only\n" -"mobs that will spawn.\n" -"No other passive or\n" -"hostile mobs will spawn." +#, java-format +msgid "§4No challenge named {0} was found!" msgstr "" -msgid "Hell" +#, java-format +msgid "§4No rank named {0} was found!" msgstr "" -msgid "" -"The hell biome looks\n" -"dark and dead. Some\n" -"mobs from the nether will\n" -"spawn in this biome\n" -"(excluding ghasts and\n" -"blazes)." +msgid "manage islands" msgstr "" -msgid "Sky" +msgid "protects the island" msgstr "" -msgid "" -"The sky biome gives your\n" -"island a special dark sky.\n" -"Only endermen will spawn\n" -"in this biome." +msgid "delete the island (removes the blocks)" msgstr "" -msgid "Plains" +msgid "§9Deleted abandoned island at your current location." msgstr "" msgid "" -"The plains biome has rain\n" -"instead of snow. Passive\n" -"mobs will spawn normally\n" -"(including horses) and\n" -"hostile mobs will spawn." +"§4Island at this location has members!\n" +"§eUse §9/usb island delete §e to delete it." msgstr "" -msgid "Extreme Hills" +msgid "removes the player from the island" msgstr "" -msgid "" -"The extreme hills biome.\n" -"Passive mobs will spawn \n" -"normally and hostile\n" -"mobs will spawn." +msgid "adds the player to the island" msgstr "" -msgid "Flower Forest" +#, java-format +msgid "§b{0}§d has joined your island group." +msgstr "" + +#, java-format +msgid "§4No player named {0} found!" msgstr "" msgid "" -"The flower forest biome.\n" -"Passive mobs will spawn \n" -"normally and hostile\n" -"mobs will spawn." +"§4No valid island provided, either stand within one, or provide an island " +"name" msgstr "" -msgid "Deep Ocean" +msgid "print out info about the island" msgstr "" -msgid "" -"The deep-ocean biome is an advanced\n" -"biome. Passive mobs like animals will\n" -"not spawn. Hostile mobs \n" -"(including Guardians) will\n" -"spawn normally." +msgid "sets the biome of the island" msgstr "" -msgid "Ice Plains" +msgid "§4That player has no island." msgstr "" -msgid "" -"The ice-plains biome is an advanced biome.\n" -"Mobs will spawn naturally.\n" -"including polar-bears" +msgid "§4No valid island at your location" msgstr "" -msgid "Permissions" +msgid "purges the island" msgstr "" -#, java-format -msgid "{0} <{1}>" +msgid "§4Error! §9No valid island found for purging." msgstr "" -msgid "§9Player Permissions" +#, java-format +msgid "§cPURGE: §9Purged island at {0}" msgstr "" -msgid "" -"§eClick here to return to\n" -"§eyour island group''s info." +msgid "toggles the islands ignore status" msgstr "" #, java-format -msgid "§e{0}''§9s Permissions" +msgid "§cSet {0}s island to be ignored on top-ten and purge." msgstr "" +#, java-format msgid "" -"§eHover over an icon to view\n" -"§ea permission. Change the\n" -"§epermission by clicking it." +"§cRemoved ignore-flag of {0}s island, it will now show up on top-ten and " +"purge." msgstr "" -msgid "§fThis player §acan" +msgid "§4No valid player-name supplied." msgstr "" -msgid "Click here to remove this permission." +#, java-format +msgid "Removing {0} from island" msgstr "" -msgid "§fThis player §ccannot" +#, java-format +msgid "§eChanged biome of {0}s island to {1}." msgstr "" -msgid "Click here to grant this permission." +#, java-format +msgid "§eChanged biome of {0}s island to OCEAN." msgstr "" -msgid "Island Group Members" +msgid "§aYou may need to go to spawn, or relog, to see the changes." msgstr "" #, java-format -msgid "Group Members: §2{0}§7/§e{1}" +msgid "§e{0} has had their biome changed to {1}." msgstr "" -msgid "§aMore players can be invited to this island." +#, java-format +msgid "§e{0} has had their biome changed to OCEAN." msgstr "" -msgid "§cThis island is full." +#, java-format +msgid "§eRemoving {0}''s island." msgstr "" -msgid "" -"§eHover over a player''s icon to\n" -"§eview their permissions. The\n" -"§eleader can change permissions\n" -"§eby clicking a player''s icon." +msgid "Error: That player does not have an island!" msgstr "" #, java-format -msgid "§e{0}''s§9 Permissions" +msgid "§e{0}s island at {1} has been protected" msgstr "" -msgid "Leader" +#, java-format +msgid "§4{0}s island at {1} was already protected" msgstr "" -msgid "Member" +msgid "various chunk commands" msgstr "" -#, java-format -msgid "Can {0}" +msgid "regenerate current chunk" msgstr "" #, java-format -msgid "Cannot {0}" +msgid "successfully regenerated chunk at {0},{1}" msgstr "" -msgid "§e" +msgid "unload current chunk" msgstr "" -msgid "Island Log" +#, java-format +msgid "successfully unloaded chunk at {0},{1}" msgstr "" -msgid "" -"§eClick here to return to\n" -"§ethe main island screen." +#, java-format +msgid "§4FAILED!§e could not unload chunk at {0},{1}" msgstr "" -msgid "§e§lIsland Log" +msgid "load current chunk" msgstr "" -msgid "Island Biome" +#, java-format +msgid "loaded chunk at {0},{1}" msgstr "" -#, java-format -msgid "Biome: {0}" +msgid "only available for players" msgstr "" -msgid "§2§lThis is your current biome." +#, java-format +msgid "§4ERROR:§e {0}" msgstr "" -msgid "§e§lClick to change to this biome." +msgid "open GUI for config" msgstr "" -msgid "You cannot use this biome." +msgid "searches config for a specific key" msgstr "" -msgid "§2chunk" +#, java-format +msgid "§c{0}§9" msgstr "" -msgid "§call" +#, java-format +msgid "§9{0}§8: §e{1}" msgstr "" #, java-format -msgid "§e{0}" +msgid "Found the following matching {0}:" msgstr "" -msgid "§c-" +msgid "§a
" msgstr "" -msgid "Decrease radius of biome-change" +#, java-format +msgid "§3{0,number,#.##}" msgstr "" #, java-format -msgid "Current radius: {0}" +msgid "§2{0}" msgstr "" -msgid "§2+" +msgid "§eInvalid configuration name" msgstr "" -msgid "Increase radius of biome-change" +msgid "Controls player-cooldowns" msgstr "" -msgid "§7Current page" +msgid "clears the cooldown on a command (* = all)" +msgstr "" + +msgid "§eThe player is not currently online" msgstr "" #, java-format -msgid "§7Page {0}" +msgid "Cleared cooldown on {0} for {1}" msgstr "" -msgid "§7First Page" +#, java-format +msgid "No active cooldown on {0} for {1} detected!" msgstr "" -msgid "§7Last Page" +msgid "Invalid command supplied, only restart and biome supported!" msgstr "" -msgid "Island Create Menu" +msgid "restarts the cooldown on the command" msgstr "" -msgid "§a§lStart an Island" +#, java-format +msgid "§eReset cooldown on {0} for {1}§e to {2} seconds" msgstr "" -msgid "" -"Start your skyblock journey\n" -"by starting your own island.\n" -"Complete challenges to earn\n" -"items and skybucks to help\n" -"expand your skyblock. You can\n" -"invite others to join in\n" -"building your island empire!\n" -"§e§lClick here to start!" +msgid "lists all the active cooldowns" msgstr "" -msgid "§aClick to create!" +msgid "§eCmd Cooldown" msgstr "" #, java-format -msgid "" -"§cNo access!\n" -"§7({0})" +msgid "§a{0} §c{1}" msgstr "" -msgid "§a§lReturn to Spawn" +#, java-format +msgid "§eNo active cooldowns for §9{0}§e found." msgstr "" -msgid "Teleport to the spawn area." +msgid "control debugging" msgstr "" -msgid "§a§lJoin an Island" +msgid "set debug-level" msgstr "" -msgid "" -"Want to join another player''s\n" -"island instead of starting\n" -"your own? If another player\n" -"invites you to their island\n" -"you can click here or use\n" -"§e/island accept§f to join them.\n" -"§e§lClick here to accept an invite!\n" -"§e§l(You must be invited first)" +msgid "toggle debug-logging" msgstr "" -msgid "Island Menu" +msgid "§4Logging wasn't active, so you can't disable it!" msgstr "" -msgid "§a§lReturn Home" +msgid "flush current content of the logger to file." msgstr "" -msgid "" -"Return to your island''s home\n" -"point. You can change your home\n" -"point to any location on your\n" -"island using §b/island sethome\n" -"§e§lClick here to return home." +msgid "§eLog-file has been flushed." msgstr "" -msgid "§a§lChallenges" +msgid "§4Logging is not enabled, use §d/usb debug enable" msgstr "" -msgid "" -"View a list of §9challenges that\n" -"you can complete on your island\n" -"to earn skybucks, items, perks,\n" -"and titles." +msgid "§4Invalid argument, try INFO, FINE, FINER, FINEST" msgstr "" -msgid "§e§lClick here to view challenges." +msgid "§eLogging disabled!" msgstr "" -msgid "§4§lChallenges disabled." +msgid "tries to fix the the area of flatland." msgstr "" -msgid "§a§lIsland Level" +msgid "§4No valid island found" msgstr "" #, java-format -msgid "§eCurrent Level: §a{0,number,##.#}" +msgid "§4No flatland detected at {0}''s island!" +msgstr "" + +msgid "flushes all caches to files" msgstr "" +#, java-format msgid "" -"Gain island levels by expanding\n" -"your skyblock and completing\n" -"certain challenges. Rarer blocks\n" -"will add more to your level.\n" -"§e§lClick here to refresh.\n" -"§e§l(must be on island)" +"§eFlushed §a{0} islands§e, §b{1} players and §6{2} challenge-completions." msgstr "" -msgid "Island Group" +msgid "manually update the top 10 list" msgstr "" -#, java-format -msgid "§eMembers: §2{0}/{1}" +msgid "§eGenerating the Top Ten list" msgstr "" -msgid "" -"View the members of your island\n" -"group and their permissions. If\n" -"you are the island leader, you\n" -"can change the member permissions.\n" -"§e§lClick here to view or change." +msgid "§eFinished generation of the Top Ten list" msgstr "" -msgid "Change Island Biome" +msgid "advanced command for getting island-data" msgstr "" #, java-format -msgid "§eCurrent Biome: §b{0}" +msgid "§eCurrent value for {0} is ''{1}''" msgstr "" -msgid "" -"The island biome affects things\n" -"like grass color and spawning\n" -"of both animals and monsters." +#, java-format +msgid "§cUnable to get state for {0}" msgstr "" -msgid "§e§lClick here to change biomes." +#, java-format +msgid "§eValid fields are {0}" msgstr "" -msgid "§c§lYou can't change the biome." +msgid "teleport to another players island" msgstr "" -msgid "§a§lIsland Lock" +msgid "§4Only supported for players" msgstr "" -msgid "" -"§eLock Status: §aActive\n" -"§fYour island is currently §clocked.\n" -"§fPlayers outside of your group\n" -"§fare unable to enter your island." +msgid "§4That player does not have an island!" msgstr "" -msgid "§e§lClick here to unlock your island." +#, java-format +msgid "§aTeleporting to {0}''s island." msgstr "" -msgid "§c§lYou can't change the lock." +msgid "imports players and islands from other formats" msgstr "" -msgid "" -"§eLock Status: §8Inactive\n" -"§fYour island is currently §aunlocked.\n" -"§fAll players are able to enter your\n" -"§fisland, but only you and your group\n" -"§fmembers may build there." +msgid "controls async jobs" msgstr "" -msgid "§e§lClick here to lock your island." +msgid "§9Job Statistics" msgstr "" -msgid "§a§lIsland Warp" +msgid "§7----------------" msgstr "" -msgid "" -"§eWarp Status: §aActive\n" -"§fOther players may warp to your\n" -"§fisland at anytime to the point\n" -"§fyou set using §d/island setwarp." +msgid "#" msgstr "" -msgid "§e§lClick here to deactivate." +msgid "ms/job" msgstr "" -msgid "§c§lYou can't change the warp." +msgid "ms/tick" msgstr "" -msgid "" -"§eWarp Status: §8Inactive\n" -"§fOther players can't warp to your\n" -"§fisland. Set a warp point using\n" -"§d/island setwarp §fbefore activating." +msgid "ticks" msgstr "" -msgid "§e§lClick here to activate." +msgid "act" msgstr "" -msgid "§a§lIsland Log" +msgid "time" msgstr "" -msgid "" -"View a log of events from\n" -"your island such as member,\n" -"biome, and warp changes.\n" -"§e§lClick to view the log." +msgid "name" msgstr "" -msgid "§a§lChange Home Location" +msgid "transfer leadership to another player" msgstr "" -msgid "" -"When you teleport to your\n" -"island you will be taken to\n" -"this location.\n" -"§e§lClick here to change." +#, java-format +msgid "§4Player {0} has no island to transfer!" msgstr "" -msgid "§a§lChange Warp Location" +#, java-format +msgid "" +"§ePlayer §d{0}§e already has an island.§eUse §d/usb island remove §e " +"to remove him first." msgstr "" -msgid "" -"When your warp is activated,\n" -"other players will be taken to\n" -"this point when they teleport\n" -"to your island." +#, java-format +msgid "§bLeadership transferred by {0}§b to {1}" msgstr "" -msgid "§e§lClick here to change." +msgid "advanced info about NBT stuff" msgstr "" -msgid "§c§lRestart Island" +msgid "shows the NBTTag for the currently held item" msgstr "" -msgid "" -"Restarts your island.\n" -"§4WARNING! §cwill remove your items and island!" +msgid "§cNo item in hand!" msgstr "" -msgid "§c§lLeave Island" +#, java-format +msgid "§eInfo for §9{0}" msgstr "" -msgid "" -"Leaves your island.\n" -"§4WARNING! §cwill remove all your items!" +#, java-format +msgid "§7 - name: §9{0}" msgstr "" -msgid "§cClick to leave" +#, java-format +msgid "§7 - nbttag: §9{0}" msgstr "" -msgid "Island Restart Menu" +msgid "§eCan only be executed as a player" msgstr "" -msgid "Config:" +msgid "sets the NBTTag on the currently held item" msgstr "" #, java-format -msgid "§cClick within §9{0}§c to leave!" +msgid "§eSet §9{0}§e to §c{1}" msgstr "" -msgid "§a§lReturn to the main menu" +msgid "adds the NBTTag on the currently held item" msgstr "" #, java-format -msgid "§cClick within §9{0}§c to restart!" +msgid "§eAdded §9{0}§e to §c{1}" msgstr "" -msgid "§aClick to restart!" +msgid "manage orphans" msgstr "" -#, java-format -msgid "§c{0,number,#}" +msgid "count orphans" msgstr "" #, java-format -msgid "§a+{0,number,#}" +msgid "§e{0} old island locations will be used before new ones." msgstr "" -#, java-format -msgid "§a{0,number,#}" +msgid "clear orphans" msgstr "" -#, java-format -msgid "&aLeft:&7 Increment with {0}" +msgid "§eClearing all old (empty) island locations." msgstr "" -#, java-format -msgid "&cRight-Click:&7 Set to {0}" +msgid "list orphans" +msgstr "" + +msgid "§eNo orphans currently registered." msgstr "" -msgid "Return" +#, java-format +msgid "§eOrphans ({0}/{1}): {2}" msgstr "" -msgid "§9Integer Editor" +msgid "shows perk-information" msgstr "" -msgid "Caps On" +msgid "shows a specific players perks" msgstr "" -msgid "§9Text Editor" +#, java-format +msgid "additional perks {0}" msgstr "" -msgid "§eConfiguration saved and reloaded." +msgid "protects all islands (time consuming)" msgstr "" -msgid "§cError! §9Unable to save config file!" +msgid "§cTrying to abort protect-all task." msgstr "" -msgid "§3First Page" +msgid "" +"§4Sorry!§e A protect-all is already running. Let it complete first, or use " +"§9usb protectall §cstop" msgstr "" -msgid "§3Last Page" +msgid "§eStarting a protect-all task. It will take a while." msgstr "" -msgid "§cSave & Reload config" +msgid "purges all abandoned islands" msgstr "" -msgid "" -"§7Saves the settings to\n" -"§7file & reloads again.\n" -"§cNote: §7Use with care!" +msgid "§4You must provide the age in days to purge!" msgstr "" -msgid "§7 (readonly)" +msgid "§4The level must be a valid number" msgstr "" #, java-format msgid "" -"§eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) " -"~ {6}" +"§eFinding all islands that have been abandoned for more than {0} days below " +"level {1}" msgstr "" #, java-format -msgid "§4No importer named §e{0}§4 found" +msgid "§4PURGE:§e Do §9usb purge confirm§e within {0} to accept." msgstr "" -#, java-format -msgid "§eConverted {0}/{1} files in {2}" +msgid "§4Trying to abort purge" msgstr "" -#, java-format -msgid "§7PlayerDB: Filtering {0} players from uuid2name.yml" +msgid "§4Purge aborted!" msgstr "" -#, java-format -msgid "§7 - {0,number,##}% ({1}/{2}) ~ {3}" +msgid "§4A purge is already running.§e Either §9confirm§e or §9stop§e it." msgstr "" -#, java-format -msgid "§7PlayerDB: Filtered {0} names" +msgid "§4Starting purge..." msgstr "" -#, java-format -msgid "" -"§7 - MojangAPI:{4}: {0,number,##}% ({1}/{2}, failed:{3} ~ {5,number,##}%), " -"{6}" +msgid "region manipulations" msgstr "" -#, java-format -msgid "§7MojangAPI: Trying to fetch {0} players from Mojang" +msgid "shows the borders of the current island" msgstr "" -msgid "SUCCESS" +msgid "§eNo island found at your current location" msgstr "" -msgid "FAILED" +msgid "shows the borders of the current chunk" msgstr "" -#, java-format -msgid "§7 - MojangAPI:§aCOMPLETED: {0}" +msgid "shows the borders of the inner-chunks" msgstr "" -#, java-format -msgid "§7 - MojangAPI:§cERROR: {0}" +msgid "shows the non-chunk-aligned borders" msgstr "" -#, java-format -msgid "Too many requests for Mojangs API ({0} within {1}), sleeping {2}" +msgid "shows the borders of the outer-chunks" msgstr "" -msgid "North" +msgid "hides the regions again" msgstr "" -msgid "North-East" +msgid "§eStopped displaying regions" msgstr "" -msgid "East" +msgid "§eNo currently shown regions for this player" msgstr "" -msgid "South-East" +msgid "set the ticks between animations" msgstr "" -msgid "South" +#, java-format +msgid "§eAnimation-tick changed to {0}." msgstr "" -msgid "South-West" +msgid "§eAnimation-tick must be a valid integer." msgstr "" -msgid "West" +msgid "refreshes the existing animations" msgstr "" -msgid "North-West" +msgid "set a player''s island to your location" msgstr "" -msgid "The island has been created." +#, java-format +msgid "§aSet {0}''s island to the current island." msgstr "" -#, java-format -msgid "§b{0}§d locked the island." +msgid "§4Island not found: unable to set the island!" msgstr "" -msgid "§4Since your island is locked, your incoming warp has been deactivated." +msgid "reload configuration from file." msgstr "" -#, java-format -msgid "§b{0}§d deactivated the island warp." +msgid "§eConfiguration reloaded from file." +msgstr "" + +msgid "advanced command for setting island-data" msgstr "" #, java-format -msgid "§b{0}§d unlocked the island." +msgid "§c{0} was set to ''{1}''" msgstr "" #, java-format -msgid "§cSKY §f> §7 {0}" +msgid "§cUnable to set field {0} to ''{1}''" msgstr "" #, java-format -msgid "§b{0}§d has been removed from the island group." +msgid "§cUnable to set field {0} to ''{1}'', a number was expected" msgstr "" #, java-format -msgid "§9{1} §7- {0}" +msgid "§cInvalid field {0}" msgstr "" -msgid "§9Creating an island at your location" +msgid "toggles maintenance mode" msgstr "" -#, java-format -msgid "§9Creating an island §7{0}§9 of you" +msgid "§cMAINTENANCE: §aActivated§e all uSkyBlock features currently disabled." msgstr "" -msgid "§aCongratulations! §eYour island has appeared." +msgid "" +"§cMAINTENANCE: §4Deactivated§e all uSkyBlock features back to operational." msgstr "" -msgid "§cNote:§e Construction might still be ongoing." +msgid "§cMaintenance mode can only be changed from console!" msgstr "" -msgid "Use §9/is h§r or the §9/is§r menu to go there." +msgid "§cABORTED:§e Protect-All was aborted!" msgstr "" #, java-format -msgid "Unable to locate schematic {0}, contact a server-admin" +msgid "§eCompleted protect-all in {0}, {1} new regions were created!" msgstr "" #, java-format -msgid "§cWatchdog!§9 Unable to locate a chest within {0}, bailing out." +msgid "§7- SCANNING: {0,number,##}% ({1}/{2} failed: {3}) ~ {4}" msgstr "" -msgid "UNKNOWN" +msgid "§4PURGE:§9 Scanning aborted." msgstr "" -msgid "ANIMAL" +#, java-format +msgid "" +"§4PURGE:§9 Scanning done, found {0} candidates, below level {1}, ready for " +"purgatory." msgstr "" -msgid "MONSTER" +#, java-format +msgid "" +"- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}" msgstr "" -msgid "VILLAGER" +msgid "§4PURGE:§9 Finished purging abandoned islands." msgstr "" -msgid "GOLEM" +msgid "§4PURGE:§9 Aborted purging abandoned islands." msgstr "" -#, java-format -msgid "§c{0}" +msgid "displays version information" msgstr "" -#, java-format -msgid "§7{0}: §a{1}§7 (max. {2})" +msgid "various WorldGuard utilities" msgstr "" -msgid "" -"§cThe island owning this piece of nether is being deleted! Sending you to " -"spawn." +msgid "refreshes the chunks around the player" msgstr "" -msgid "§cThe island you are on is being deleted! Sending you to spawn." +msgid "§eResending chunks to the client" msgstr "" -#, java-format -msgid "§eWALL OF FAME (page {0} of {1}):" +msgid "load the region chunks" msgstr "" #, java-format -msgid "§4Top ten list is empty! Only islands above level {0} is considered." +msgid "§eLoading chunks at {0}" msgstr "" -msgid "§4Island level has been disabled, contact an administrator." +#, java-format +msgid "§eUnloading chunks at {0}" msgstr "" -msgid "§a#%2d §7(%5.2f): §e%s §7%s" +msgid "update the WG regions" msgstr "" -msgid "Click to warp to the island!" +#, java-format +msgid "§eIsland world-guard regions updated for {0}" msgstr "" -#, java-format -msgid "§eYour rank is: §f{0}" +msgid "§eNo island found at your location!" msgstr "" -#, java-format -msgid "§7Complete {0} more {1} §7challenges" +msgid "refreshes the chunk around the player" msgstr "" -#, java-format -msgid "§7Complete {0}" +msgid "Ultimate SkyBlock Admin" msgstr "" -msgid "to unlock this rank" +msgid "show player-information" msgstr "" -#, java-format -msgid "§4You can complete this {0} more time(s)." +msgid "try to complete a challenge" msgstr "" -#, java-format -msgid "§4Requirements will reset in {0} days." +msgid "§cCommand only available for players." msgstr "" -#, java-format -msgid "§4Requirements will reset in {0} hours." +msgid "show information about the challenge" msgstr "" -#, java-format -msgid "§4Requirements will reset in {0} minutes." +msgid "§eRank: " msgstr "" -msgid "§4This challenge is currently unavailable." +msgid "§4This Challenge is not repeatable!" msgstr "" -#, java-format -msgid "§4You can complete this again in {0} days." +msgid "§4You will lose all required items when you complete this challenge!" msgstr "" #, java-format -msgid "§4You can complete this again in {0} hours." +msgid "" +"§4All required items must be placed on your island, within {0} blocks of you." msgstr "" #, java-format -msgid "§4You can complete this again in {0} minutes." +msgid "§eTo complete this challenge, use §f/c c {0}" msgstr "" -msgid "§eThis challenge requires:" +msgid "§4Invalid challenge name! Use /c help for more information" msgstr "" -msgid "§7and more..." +msgid "complete and list challenges" msgstr "" -msgid "§eItems will be traded for reward." +msgid "§eChallenges has been disabled. Contact an administrator." msgstr "" -#, java-format -msgid "§eMust be within {0} meters." +msgid "§4You can only submit challenges in the skyblock world!" msgstr "" -msgid "§6Item Reward: §a" +msgid "§4You can only submit challenges when you have an island!" msgstr "" -#, java-format -msgid "§6Currency Reward: §a{0}" +msgid "" +"§4Your island is full, or you have too many pending invites. You can't " +"invite anyone else." msgstr "" -#, java-format -msgid "§6Exp Reward: §a{0}" +msgid "§4That player is already leader on another island." msgstr "" #, java-format -msgid "§dTotal times completed: §f{0}" +msgid "§e{0}§e tried to invite you, but you are already in a party." msgstr "" #, java-format -msgid "§7Requires {0}" +msgid "§aInvite sent to {0}" msgstr "" #, java-format -msgid "§4No challenge named {0} found" +msgid "{0}§e has invited you to join their island!" msgstr "" -msgid "§4You must be on your island to do that!" +msgid "§f/island [accept/reject]§e to accept or reject the invite." msgstr "" -#, java-format -msgid "§4The {0} challenge is not repeatable!" +msgid "§4WARNING: You will lose your current island if you accept!" msgstr "" #, java-format -msgid "§4You cannot complete the {0} challenge again yet!" +msgid "{0}§d invited {1}" msgstr "" #, java-format -msgid "§eTrying to complete challenge §a{0}" +msgid "{0}§e has rejected the invitation." msgstr "" -#, java-format -msgid "§4{0}" +msgid "§4You can't use that command right now. Leave your current party first." msgstr "" -#, java-format -msgid "§4You must be standing within {0} blocks of all required items." +msgid "" +"§aYou have joined an island! Use /island party to see the other members." msgstr "" #, java-format -msgid "§4Your island must be level {0} to complete this challenge!" +msgid "§eInvitation for {0}§e has timedout or been cancelled." msgstr "" #, java-format -msgid "§4Unknown type of challenge: {0}" +msgid "§eInvitation for {0}''s island has timedout or been cancelled." msgstr "" -#, java-format -msgid "" -"§eStill the following entities short:\n" -"{0}" +msgid "§eYou have accepted the invitation to join an island." msgstr "" -#, java-format -msgid " §4{0} §b{1}" +msgid "§4You haven't been invited." msgstr "" -#, java-format -msgid "§eYou are the following items short:{0}" +msgid "§eYou have rejected the invitation to join an island." msgstr "" -#, java-format -msgid "§aYou have completed the {0} challenge!" +msgid "accept/reject an invitation." msgstr "" -#, java-format -msgid "§9{0}§f has completed the §9{1}§f challenge!" +msgid "teleports you to your island (or create one)" msgstr "" -#, java-format -msgid "§eItem reward(s): §f{0}" +msgid "ban/unban a player from your island." msgstr "" -#, java-format -msgid "§eExp reward: §f{0,number,#.#}" +msgid "exempts user from being banned" msgstr "" -#, java-format -msgid "§eCurrency reward: §f{0,number,###.##} {1} §a ({2,number,##.##})%" +msgid "§eThe following players are banned from warping to your island:" msgstr "" -msgid "§eYour inventory is §4full§e. Items dropped on the ground." +msgid "§eTo ban/unban from your island, use /island ban " msgstr "" -msgid "§e§lClick to complete this challenge." +msgid "§4You can't ban members. Remove them first!" msgstr "" -msgid "§4§lYou can't repeat this challenge." +msgid "§4You do not have permission to kick/ban players." msgstr "" #, java-format -msgid "Rank: {0}" +msgid "§eUnable to ban unknown player {0}" msgstr "" -msgid "§fComplete most challenges in" +#, java-format +msgid "§4{0} tried to ban you from their island!" msgstr "" -msgid "§fthis rank to unlock the next rank." +#, java-format +msgid "§4{0} is exempt from being banned." msgstr "" -msgid "§eClick here to show previous page" +#, java-format +msgid "§eYou have banned §4{0}§e from warping to your island." msgstr "" -msgid "§eClick here to show next page" +#, java-format +msgid "§eYou have been §cBANNED§e from {0}§e''s island." msgstr "" -msgid "But you are ALLLLLLL ALOOOOONE!" +#, java-format +msgid "§eYou have unbanned §a{0}§e from warping to your island." msgstr "" -msgid "But you are Yelling in the wind!" +#, java-format +msgid "§eYou have been §aUNBANNED§e from {0}§e''s island." msgstr "" -msgid "But your fantasy friends are gone!" +msgid "change the biome of the island" msgstr "" -msgid "But you are Talking to your self!" +msgid "exempt player from biome-cooldown" msgstr "" #, java-format -msgid "§cSorry! {0}" +msgid "Let the player change their islands biome to {0}" msgstr "" -msgid "Either send a message directly to your group, or toggle it on/off." +msgid "" +"§cYou do not have permission to change the biome of your current island." msgstr "" -msgid "party" +msgid "§4You do not have permission to change the biome of this island!" msgstr "" -msgid "island" +msgid "§eYou must be on your island to change the biome!" msgstr "" #, java-format -msgid "§cToggled chat to {0} §aON" +msgid "§cYou have misspelled the biome name. Must be one of {0}" msgstr "" #, java-format -msgid "§cRepeat §9{0}§c to toggle it off" +msgid "§eYou can change your biome again in {0,number,#} minutes." +msgstr "" + +msgid "§cYou do not have permission to change your biome to that type." msgstr "" #, java-format -msgid "§aToggled chat §cOFF§a for {0}" +msgid "" +"§7The pixies are busy changing the biome near you to §9{0}§7, be patient." msgstr "" -msgid "§cCommand only available to players" +#, java-format +msgid "" +"§7The pixies are busy changing the biome in your current chunk to §9{0}§7, " +"be patient." msgstr "" -msgid "talk to your island party" +#, java-format +msgid "" +"§7The pixies are busy changing the biome of your island to §9{0}§7, be " +"patient." msgstr "" -msgid "talk to players on your island" +#, java-format +msgid "§eInvalid biome {0} supplied!" msgstr "" -msgid "manually update the top 10 list" +#, java-format +msgid "§aYou have changed your island''s biome to {0}" msgstr "" -msgid "§eGenerating the Top Ten list" +#, java-format +msgid "{0} changed the island biome to {1}" msgstr "" -msgid "§eFinished generation of the Top Ten list" +#, java-format +msgid "§aYou have changed {0} blocks around you to the {1} biome" msgstr "" -msgid "purges all abandoned islands" +#, java-format +msgid "{0} created an area with {1} biome" msgstr "" -msgid "§4You must provide the age in days to purge!" +msgid "create an island" msgstr "" -msgid "§4The level must be a valid number" +msgid "exempt player from create-cooldown" msgstr "" -#, java-format msgid "" -"§eFinding all islands that have been abandoned for more than {0} days below " -"level {1}" +"§4Island found!§e You already have an island. If you want a fresh island, " +"type§b /is restart§e to get one" msgstr "" -#, java-format -msgid "§4PURGE:§e Do §9usb purge confirm§e within {0} to accept." +msgid "" +"§4Island found!§e You are already a member of an island. To start your own, " +"first§b /is leave" msgstr "" -msgid "§4Trying to abort purge" +#, java-format +msgid "§eYou can create a new island in {0,number,#} seconds." msgstr "" -msgid "§4Purge aborted!" +msgid "teleport to the island home" msgstr "" -msgid "§4A purge is already running.§e Either §9confirm§e or §9stop§e it." +msgid "" +"§cYour island is in the process of generating, you cannot teleport home " +"right now." msgstr "" -msgid "§4Starting purge..." +msgid "check your or another''s island info" msgstr "" -msgid "Controls player-cooldowns" +msgid "allows user to see others island info" msgstr "" -msgid "clears the cooldown on a command (* = all)" +msgid "§4Island level has been disabled, contact an administrator." msgstr "" -msgid "§eThe player is not currently online" +msgid "§4Hold your horses! §eYou have to be patient..." msgstr "" -#, java-format -msgid "Cleared cooldown on {0} for {1}" +msgid "§eYou must be on your island to use this command." msgstr "" -#, java-format -msgid "No active cooldown on {0} for {1} detected!" +msgid "§4You do not have an island!" msgstr "" -msgid "Invalid command supplied, only restart and biome supported!" +msgid "§4You do not have access to that command!" msgstr "" -msgid "restarts the cooldown on the command" +msgid "§4That player is invalid or does not have an island!" msgstr "" #, java-format -msgid "§eReset cooldown on {0} for {1}§e to {2} seconds" +msgid "§eBlocks on {0}s Island (page {1,number} of {2,number}):" msgstr "" -msgid "lists all the active cooldowns" +msgid "Score Count Block" msgstr "" -msgid "§eCmd Cooldown" +#, java-format +msgid "{0,number,00.00} {1,number,#} {2}" msgstr "" #, java-format -msgid "§a{0} §c{1}" +msgid "§aIsland level is {0,number,###.##}" msgstr "" -#, java-format -msgid "§eNo active cooldowns for §9{0}§e found." +msgid "invite a player to your island" msgstr "" -msgid "toggles maintenance mode" +msgid "" +"§eUse§f /island invite §e to invite a player to your island." msgstr "" -msgid "§cMAINTENANCE: §aActivated§e all uSkyBlock features currently disabled." +msgid "§4Only the island''s owner can invite!" msgstr "" -msgid "" -"§cMAINTENANCE: §4Deactivated§e all uSkyBlock features back to operational." +#, java-format +msgid "§aYou can invite {0} more players." msgstr "" -msgid "§cMaintenance mode can only be changed from console!" +msgid "§4You can't invite any more players." msgstr "" -msgid "controls async jobs" +msgid "§4You do not have permission to invite others to this island!" msgstr "" -msgid "§9Job Statistics" +msgid "§4That player is offline or doesn't exist." msgstr "" -msgid "§7----------------" +msgid "§4You can't invite yourself!" msgstr "" -msgid "#" +msgid "§4That player is the leader of your island!" msgstr "" -msgid "ms/job" +msgid "remove a member from your island." msgstr "" -msgid "ms/tick" +msgid "§4You do not have permission to kick others from this island!" msgstr "" -msgid "ticks" +msgid "§4You can't remove the leader from the Island!" msgstr "" -msgid "act" +msgid "§4Stop kickin' yourself!" msgstr "" -msgid "time" +#, java-format +msgid "§4{0} has removed you from their island!" msgstr "" -msgid "name" +#, java-format +msgid "§4{0} has been removed from the island." msgstr "" #, java-format -msgid "§ePlayer {0} has no island!" +msgid "§4{0} tried to kick you from their island!" msgstr "" #, java-format -msgid "§eInvalid player {0} supplied." +msgid "§4{0} is exempt from being kicked." msgstr "" -msgid "flushes all caches to files" +#, java-format +msgid "§4{0} has kicked you from their island!" msgstr "" #, java-format -msgid "" -"§eFlushed §a{0} islands§e, §b{1} players and §6{2} challenge-completions." +msgid "§4{0} has been kicked from the island." msgstr "" -msgid "tries to fix the the area of flatland." +msgid "§4That player is not part of your island group, and not on your island!" msgstr "" -msgid "§4No valid island found" +msgid "leave your party" msgstr "" -#, java-format -msgid "§4No flatland detected at {0}''s island!" +msgid "" +"§4You can't leave your island if you are the only person. Try using /island " +"restart if you want a new one!" msgstr "" -msgid "manage orphans" +msgid "§eYou own this island, use /island remove instead." msgstr "" -msgid "count orphans" +msgid "§eYou have left the island and returned to the player spawn." msgstr "" #, java-format -msgid "§e{0} old island locations will be used before new ones." +msgid "§4{0} has left your island!" msgstr "" -msgid "clear orphans" +msgid "§4You must be in the skyblock world to leave your party!" msgstr "" -msgid "§eClearing all old (empty) island locations." +msgid "check your or anothers island level" msgstr "" -msgid "list orphans" +msgid "allows user to query for others levels" msgstr "" -msgid "§eNo orphans currently registered." +#, java-format +msgid "§eInformation about {0}''s Island:" msgstr "" #, java-format -msgid "§eOrphans ({0}/{1}): {2}" +msgid "§9Rank is {0}" msgstr "" -msgid "transfer leadership to another player" +#, java-format +msgid "§4Could not locate rank of {0}" msgstr "" -#, java-format -msgid "§4Player {0} has no island to transfer!" +msgid "lock your island to non-party members." msgstr "" -#, java-format -msgid "" -"§ePlayer §d{0}§e already has an island.§eUse §d/usb island remove §e " -"to remove him first." +msgid "§4You do not have permission to lock your island!" msgstr "" -#, java-format -msgid "§bLeadership transferred by {0}§b to {1}" +msgid "§4You don't have access to this command!" msgstr "" -msgid "open GUI for config" +msgid "§4You do not have permission to unlock your island!" msgstr "" -msgid "searches config for a specific key" +msgid "display log" msgstr "" -#, java-format -msgid "§c{0}§9" +msgid "transfer leadership to another member" msgstr "" -#, java-format -msgid "§9{0}§8: §e{1}" +msgid "§4You can only transfer ownership to party-members!" msgstr "" #, java-format -msgid "Found the following matching {0}:" +msgid "{0}§e is already leader of your island!" msgstr "" -msgid "§a
" +msgid "§4Only leader can transfer leadership!" msgstr "" #, java-format -msgid "§3{0,number,#.##}" +msgid "{0} tried to take over the island!" msgstr "" -#, java-format -msgid "§2{0}" +msgid "show the islands limits" msgstr "" -msgid "§eInvalid configuration name" +msgid "show party information" msgstr "" -msgid "teleport to another players island" +msgid "shows information about your party" msgstr "" -msgid "§4Only supported for players" +msgid "show pending invites" msgstr "" -msgid "§4That player does not have an island!" +msgid "§eNo pending invites" msgstr "" -#, java-format -msgid "§aTeleporting to {0}''s island." +msgid "withdraw an invite" msgstr "" -msgid "various WorldGuard utilities" +msgid "§4You don't have permissions to uninvite players." msgstr "" -msgid "refreshes the chunks around the player" +msgid "§4This command can only be executed by a player" msgstr "" -msgid "§eResending chunks to the client" +msgid "§4No Island. §eUse §b/is create§e to get one" msgstr "" -msgid "load the region chunks" +msgid "changes a members island-permissions" msgstr "" #, java-format -msgid "§eLoading chunks at {0}" +msgid "§ePermissions for §9{0}§e:" msgstr "" -#, java-format -msgid "§eUnloading chunks at {0}" +msgid "§aON" msgstr "" -msgid "update the WG regions" +msgid "§cOFF" msgstr "" #, java-format -msgid "§eIsland world-guard regions updated for {0}" +msgid "§7 - §6{0}§7 : {1}" msgstr "" -msgid "§eNo island found at your location!" +#, java-format +msgid "§cInvalid permission {0}. Must be one of {1}" msgstr "" -msgid "refreshes the chunk around the player" +#, java-format +msgid "§eToggled permission §9{0}§e for §9{1}§e to {2}" msgstr "" -msgid "region manipulations" +#, java-format +msgid "§eUnable to toggle permission §9{0}§e for §9{1}" msgstr "" -msgid "shows the borders of the current island" +msgid "delete your island and start a new one." msgstr "" -msgid "§eNo island found at your current location" +msgid "exempt player from restart-cooldown" msgstr "" -msgid "§eCan only be executed as a player" +msgid "" +"§4Only the owner may restart this island. Leave this island in order to " +"start your own (/island leave)." msgstr "" -msgid "shows the borders of the current chunk" +msgid "" +"§eYou must remove all players from your island before you can restart it (/" +"island kick ). See a list of players currently part of your island " +"using /island party." msgstr "" -msgid "shows the borders of the inner-chunks" +#, java-format +msgid "§cYou can restart your island in {0} seconds." msgstr "" -msgid "shows the non-chunk-aligned borders" +msgid "§cYour island is in the process of generating, you cannot restart now." msgstr "" -msgid "shows the borders of the outer-chunks" +msgid "§eNOTE: Your entire island and all your belongings will be RESET!" msgstr "" -msgid "hides the regions again" +msgid "set the island-home" msgstr "" -msgid "§eStopped displaying regions" +msgid "§4You must be closer to your island to set your skyblock home!" msgstr "" -msgid "§eNo currently shown regions for this player" +msgid "§4Your current location is not a safe home-location." msgstr "" -msgid "set the ticks between animations" +msgid "§aYour skyblock home has been set to your current location." msgstr "" -#, java-format -msgid "§eAnimation-tick changed to {0}." +msgid "set your island''s warp location" msgstr "" -msgid "§eAnimation-tick must be a valid integer." +msgid "§cYou do not have permission to set your island''s warp point!" msgstr "" -msgid "refreshes the existing animations" +msgid "§cYou need to be on your own island to set the warp!" msgstr "" #, java-format -msgid "" -"- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}" +msgid "§b{0}§d changed the island warp location." msgstr "" -msgid "§4PURGE:§9 Finished purging abandoned islands." +msgid "teleports you to the skyblock spawn" msgstr "" -msgid "§4PURGE:§9 Aborted purging abandoned islands." +msgid "enable/disable warping to your island." msgstr "" -#, java-format -msgid "§7- SCANNING: {0,number,##}% ({1}/{2} failed: {3}) ~ {4}" +msgid "§4Your island is locked. You must unlock it before enabling your warp." msgstr "" -msgid "§4PURGE:§9 Scanning aborted." +#, java-format +msgid "§b{0}§d activated the island warp." msgstr "" #, java-format -msgid "" -"§4PURGE:§9 Scanning done, found {0} candidates, below level {1}, ready for " -"purgatory." +msgid "§b{0}§d deactivated the island warp." msgstr "" -msgid "§cABORTED:§e Protect-All was aborted!" +msgid "§cYou do not have permission to enable/disable your island''s warp!" msgstr "" -#, java-format -msgid "§eCompleted protect-all in {0}, {1} new regions were created!" +msgid "display the top10 of islands" msgstr "" -msgid "control debugging" +msgid "enables user to all-ways generate top-ten (no caching)" msgstr "" -msgid "set debug-level" +msgid "trust/untrust a player to help on your island." msgstr "" -msgid "toggle debug-logging" +msgid "§eThe following players are trusted on your island:" msgstr "" -msgid "§4Logging wasn't active, so you can't disable it!" +msgid "§eThe following leaders trusts you:" msgstr "" -msgid "flush current content of the logger to file." +msgid "§eTo trust/untrust from your island, use /island trust " msgstr "" -msgid "§eLog-file has been flushed." +msgid "§4Members are already trusted!" msgstr "" -msgid "§4Logging is not enabled, use §d/usb debug enable" +#, java-format +msgid "§4Unknown player {0}" msgstr "" -msgid "§4Invalid argument, try INFO, FINE, FINER, FINEST" +#, java-format +msgid "§eYou are now trusted on §4{0}''s §eisland." msgstr "" -msgid "§eLogging disabled!" +#, java-format +msgid "§a{0} trusted {1} on the island" msgstr "" -msgid "advanced command for setting island-data" +#, java-format +msgid "§eYou are no longer trusted on §4{0}''s §eisland." msgstr "" #, java-format -msgid "§c{0} was set to ''{1}''" +msgid "§c{0} revoked trust in {1} on the island" msgstr "" -#, java-format -msgid "§cUnable to set field {0} to ''{1}''" +msgid "warp to another player''s island" msgstr "" -#, java-format -msgid "§cUnable to set field {0} to ''{1}'', a number was expected" +msgid "§aYour incoming warp is active, players may warp to your island." msgstr "" -#, java-format -msgid "§cInvalid field {0}" +msgid "§4Your incoming warp is inactive, players may not warp to your island." msgstr "" -#, java-format -msgid "§eCurrent value for {0} is ''{1}''" +msgid "§fSet incoming warp to your current location using §e/island setwarp" msgstr "" -#, java-format -msgid "§cUnable to get state for {0}" +msgid "§fToggle your warp on/off using §e/island togglewarp" msgstr "" -#, java-format -msgid "§eValid fields are {0}" +msgid "§4You do not have permission to create a warp on your island!" msgstr "" -msgid "set a player''s island to your location" +msgid "§fWarp to another island using §e/island warp " msgstr "" -#, java-format -msgid "§aSet {0}''s island to the current island." +msgid "§4You do not have permission to warp to other islands!" msgstr "" -msgid "§4Island not found: unable to set the island!" +msgid "" +"§cYour island is in the process of generating, you cannot warp to other " +"players islands right now." msgstr "" -msgid "advanced info about NBT stuff" +msgid "§4That player does not exist!" msgstr "" -msgid "shows the NBTTag for the currently held item" +msgid "§4That player does not have an active warp." msgstr "" -#, java-format -msgid "§eInfo for §9{0}" +msgid "" +"§cThat players island is in the process of generating, you cannot warp to it " +"right now." msgstr "" #, java-format -msgid "§7 - name: §9{0}" +msgid "§cWARNING: §9{0}§e is warping to your island!" msgstr "" -#, java-format -msgid "§7 - nbttag: §9{0}" +msgid "§4That player has forbidden you from warping to their island." msgstr "" -msgid "§cNo item in hand!" +msgid "general island command" msgstr "" -msgid "sets the NBTTag on the currently held item" +msgid "allows user to bypass cooldowns" msgstr "" -#, java-format -msgid "§eSet §9{0}§e to §c{1}" +msgid "allows user to bypass visitor-protections" msgstr "" -msgid "adds the NBTTag on the currently held item" +msgid "allows user to bypass teleport-delay" msgstr "" -#, java-format -msgid "§eAdded §9{0}§e to §c{1}" +msgid "allows user to use [usb] signs" msgstr "" -msgid "Manage challenges for a player" +msgid "allows user to place [usb] signs" msgstr "" -msgid "resets the challenge for the player" +msgid "§eYou can not use another island''s portals!" msgstr "" -msgid "§4Challenge has never been completed" +msgid "§eVillager-trading isn't allowed." msgstr "" -#, java-format -msgid "§echallenge: {0} has been reset for {1}" +msgid "§eTrading isn't allowed on other islands. Do it in spawn." msgstr "" -msgid "resets all challenges for the player" +msgid "§eRiding is only allowed on your own island!" msgstr "" -#, java-format -msgid "§e{0} has had all challenges reset." +msgid "§eYou cannot break vehicles while being a visitor!" msgstr "" -msgid "complete all challenges in the rank" +msgid "§cWither Despawned!§e It wandered too far from your island." msgstr "" #, java-format -msgid "§4No player named {0} was found!" +msgid "{0}''s Wither" msgstr "" -#, java-format -msgid "§4Challenge {0} has already been completed" +msgid "§eVisitors can't drop items!" msgstr "" #, java-format -msgid "§eChallenge {0} has been completed for {1}" +msgid "Owner: {0}" msgstr "" -#, java-format -msgid "§4No challenge named {0} was found!" +msgid "You cannot pick up other players' loot when you are a visitor!" msgstr "" -#, java-format -msgid "§4No rank named {0} was found!" +msgid "§4You can only convert obsidian once every 10 seconds" msgstr "" -msgid "various chunk commands" +msgid "§eChanging your obsidian back into lava. Be careful!" msgstr "" -msgid "regenerate current chunk" +msgid "§eYour inventory must have another empty space!" msgstr "" -#, java-format -msgid "successfully regenerated chunk at {0},{1}" +msgid "§4It''s a bad idea to replace your lava!" msgstr "" -#, java-format -msgid "§4FAILED!§e could not regenerate chunk at {0},{1}" +msgid "§eYou cannot hurt island-members." msgstr "" -msgid "unload current chunk" +msgid "§4That player has forbidden you from teleporting to their island." msgstr "" -#, java-format -msgid "successfully unloaded chunk at {0},{1}" +msgid "§4That island is §clocked.§e No teleporting to the island." msgstr "" #, java-format -msgid "§4FAILED!§e could not unload chunk at {0},{1}" +msgid "" +"§4{0} is limited. §eScanning your island to see if you are allowed to place " +"more, please be patient" msgstr "" -msgid "load current chunk" +msgid "§e... Scanning complete, you can try again" msgstr "" #, java-format -msgid "loaded chunk at {0},{1}" +msgid "" +"§4You''ve hit the {0} limit!§e You can''t have more of that type on your " +"island!§9 Max: {1,number}" msgstr "" -msgid "only available for players" +msgid "§eYou can only use spawn-eggs on your own island." +msgstr "" + +msgid "§cYou have reached your spawn-limit for your island." +msgstr "" + +msgid "§cBanned:§e You are banned from this island." +msgstr "" + +msgid "§cLocked:§e That island is locked! No entry allowed." msgstr "" #, java-format -msgid "§4ERROR:§e {0}" +msgid "§eWaiting for our turn §c{0,number,###}%" msgstr "" -msgid "protects all islands (time consuming)" +#, java-format +msgid "§9Creating island...§e{0,number,###}%" msgstr "" -msgid "§cTrying to abort protect-all task." +#, java-format +msgid "§9{0}§7 timed out" msgstr "" +#, java-format msgid "" -"§4Sorry!§e A protect-all is already running. Let it complete first, or use " -"§9usb protectall §cstop" +"§eDoing §9{0}§e is §cRISKY§e. Repeat the command within §a{1}§e seconds to " +"accept!" msgstr "" -msgid "§eStarting a protect-all task. It will take a while." +msgid "N/A" msgstr "" -msgid "reload configuration from file." +msgid "§4** You are entering a protected - but abandoned - island area." msgstr "" -msgid "§eConfiguration reloaded from file." +#, java-format +msgid "§d** You are entering §b{0}''s §disland." msgstr "" -msgid "manage islands" +msgid "§4** You are leaving an abandoned island." msgstr "" -msgid "protects the island" +#, java-format +msgid "§d** You are leaving §b{0}''s §disland." msgstr "" -msgid "delete the island (removes the blocks)" +msgid "§eYour island is now locked. Only your party members may enter." msgstr "" -msgid "§9Deleted abandoned island at your current location." +msgid "§4You must be the party leader to lock your island!" +msgstr "" + +msgid "" +"§eYour island is unlocked and anyone may enter, however only you and your " +"party members may build or remove blocks." msgstr "" -msgid "" -"§4Island at this location has members!\n" -"§eUse §9/usb island delete §e to delete it." +msgid "§4You must be the party leader to unlock your island!" msgstr "" -msgid "removes the player from the island" +#, java-format +msgid "§7PlayerDB: Filtering {0} players from uuid2name.yml" msgstr "" -msgid "adds the player to the island" +#, java-format +msgid "§7 - {0,number,##}% ({1}/{2}) ~ {3}" msgstr "" #, java-format -msgid "§b{0}§d has joined your island group." +msgid "§7PlayerDB: Filtered {0} names" msgstr "" #, java-format -msgid "§4No player named {0} found!" +msgid "" +"§7 - MojangAPI:{4}: {0,number,##}% ({1}/{2}, failed:{3} ~ {5,number,##}%), " +"{6}" msgstr "" -msgid "" -"§4No valid island provided, either stand within one, or provide an island " -"name" +#, java-format +msgid "§7MojangAPI: Trying to fetch {0} players from Mojang" msgstr "" -msgid "print out info about the island" +msgid "SUCCESS" msgstr "" -msgid "sets the biome of the island" +msgid "FAILED" msgstr "" -msgid "§4That player has no island." +#, java-format +msgid "§7 - MojangAPI:§aCOMPLETED: {0}" msgstr "" -msgid "§4No valid island at your location" +#, java-format +msgid "§7 - MojangAPI:§cERROR: {0}" msgstr "" -msgid "purges the island" +#, java-format +msgid "" +"§eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) " +"~ {6}" msgstr "" -msgid "§4Error! §9No valid island found for purging." +#, java-format +msgid "§4No importer named §e{0}§4 found" msgstr "" #, java-format -msgid "§cPURGE: §9Purged island at {0}" +msgid "§eConverted {0}/{1} files in {2}" msgstr "" -msgid "toggles the islands ignore status" +msgid "The island has been created." msgstr "" #, java-format -msgid "§cSet {0}s island to be ignored on top-ten and purge." +msgid "§b{0}§d locked the island." msgstr "" -#, java-format -msgid "" -"§cRemoved ignore-flag of {0}s island, it will now show up on top-ten and " -"purge." +msgid "§4Since your island is locked, your incoming warp has been deactivated." msgstr "" -msgid "§4No valid player-name supplied." +#, java-format +msgid "§b{0}§d unlocked the island." msgstr "" #, java-format -msgid "Removing {0} from island" +msgid "§cSKY §f> §7 {0}" msgstr "" #, java-format -msgid "§eChanged biome of {0}s island to {1}." +msgid "§b{0}§d has been removed from the island group." msgstr "" #, java-format -msgid "§eChanged biome of {0}s island to OCEAN." +msgid "§9{1} §7- {0}" msgstr "" -msgid "§aYou may need to go to spawn, or relog, to see the changes." +msgid "§9Creating an island at your location" msgstr "" #, java-format -msgid "§e{0} has had their biome changed to {1}." +msgid "§9Creating an island §7{0}§9 of you" +msgstr "" + +msgid "" +"§cThe island owning this piece of nether is being deleted! Sending you to " +"spawn." +msgstr "" + +msgid "§cThe island you are on is being deleted! Sending you to spawn." msgstr "" #, java-format -msgid "§e{0} has had their biome changed to OCEAN." +msgid "§eWALL OF FAME (page {0} of {1}):" msgstr "" #, java-format -msgid "§eRemoving {0}''s island." +msgid "§4Top ten list is empty! Only islands above level {0} is considered." msgstr "" -msgid "Error: That player does not have an island!" +msgid "§a#%2d §7(%5.2f): §e%s §7%s" msgstr "" -#, java-format -msgid "§e{0}s island at {1} has been protected" +msgid "Click to warp to the island!" msgstr "" #, java-format -msgid "§4{0}s island at {1} was already protected" +msgid "§eYour rank is: §f{0}" msgstr "" -msgid "displays version information" +msgid "UNKNOWN" msgstr "" -msgid "imports players and islands from other formats" +msgid "ANIMAL" msgstr "" -msgid "shows perk-information" +msgid "MONSTER" msgstr "" -msgid "shows a specific players perks" +msgid "VILLAGER" msgstr "" -#, java-format -msgid "additional perks {0}" +msgid "GOLEM" msgstr "" -msgid "changes the language of the plugin, and reloads" +#, java-format +msgid "§c{0}" msgstr "" #, java-format -msgid "§aSuccessfully changed language to §e{0}" +msgid "§7{0}: §a{1}§7 (max. {2})" msgstr "" #, java-format -msgid "§cFailed to change language to §e{0}" +msgid "Unable to locate schematic {0}, contact a server-admin" msgstr "" -msgid "§9Supported Languages:\n" +msgid "§aCongratulations! §eYour island has appeared." msgstr "" -#, java-format -msgid "§f{0} §7{1} §9 by {2} §7{3}\n" +msgid "§cNote:§e Construction might still be ongoing." msgstr "" -msgid "§cUnable to locate any languages." +msgid "Use §9/is h§r or the §9/is§r menu to go there." msgstr "" -msgid "advanced command for getting island-data" +#, java-format +msgid "§cWatchdog!§9 Unable to locate a chest within {0}, bailing out." msgstr "" -msgid "Ultimate SkyBlock Admin" +#, java-format +msgid "§7Page {0}" msgstr "" -msgid "show player-information" +#, java-format +msgid "§c{0,number,#}" msgstr "" -msgid "" -"§4Your island is full, or you have too many pending invites. You can't " -"invite anyone else." +#, java-format +msgid "§a+{0,number,#}" msgstr "" -msgid "§4That player is already leader on another island." +#, java-format +msgid "§a{0,number,#}" msgstr "" #, java-format -msgid "§e{0}§e tried to invite you, but you are already in a party." +msgid "&aLeft:&7 Increment with {0}" msgstr "" #, java-format -msgid "§aInvite sent to {0}" +msgid "&cRight-Click:&7 Set to {0}" msgstr "" -#, java-format -msgid "{0}§e has invited you to join their island!" +msgid "Return" msgstr "" -msgid "§f/island [accept/reject]§e to accept or reject the invite." +msgid "Config:" msgstr "" -msgid "§4WARNING: You will lose your current island if you accept!" +msgid "§9Integer Editor" msgstr "" -#, java-format -msgid "{0}§d invited {1}" +msgid "§eConfiguration saved and reloaded." msgstr "" -#, java-format -msgid "{0}§e has rejected the invitation." +msgid "§cError! §9Unable to save config file!" msgstr "" -msgid "§4You can't use that command right now. Leave your current party first." +msgid "§3First Page" msgstr "" -msgid "" -"§aYou have joined an island! Use /island party to see the other members." +msgid "§3Last Page" msgstr "" -#, java-format -msgid "§eInvitation for {0}§e has timedout or been cancelled." +msgid "§cSave & Reload config" msgstr "" -#, java-format -msgid "§eInvitation for {0}''s island has timedout or been cancelled." +msgid "" +"§7Saves the settings to\n" +"§7file & reloads again.\n" +"§cNote: §7Use with care!" msgstr "" -msgid "§eYou have accepted the invitation to join an island." +msgid "§7 (readonly)" msgstr "" -msgid "§4You haven't been invited." +msgid "true" msgstr "" -msgid "§eYou have rejected the invitation to join an island." +msgid "false" msgstr "" -msgid "general island command" +msgid "Challenge Menu" msgstr "" -msgid "allows user to bypass cooldowns" +msgid "Change Biome" msgstr "" -msgid "allows user to bypass visitor-protections" +msgid "change the island''s biome." msgstr "" -msgid "allows user to bypass teleport-delay" +msgid "Toggle Island Lock" msgstr "" -msgid "allows user to use [usb] signs" +msgid "toggle the island''s lock." msgstr "" -msgid "allows user to place [usb] signs" +msgid "Set Island Warp" msgstr "" -msgid "complete and list challenges" +msgid "set the island''s warp." msgstr "" -msgid "§cCommand only available for players." +msgid "" +"set the island''s warp,\n" +"which allows non-group\n" +"members to teleport to\n" +"the island." msgstr "" -msgid "§eChallenges has been disabled. Contact an administrator." +msgid "Toggle Island Warp" msgstr "" -msgid "§4You can only submit challenges in the skyblock world!" +msgid "toggle the island''s warp." msgstr "" -msgid "§4You can only submit challenges when you have an island!" +msgid "" +"toggle the island''s warp,\n" +"allowing them to turn it\n" +"on or off at anytime, but\n" +"not set the location." msgstr "" -msgid "warp to another player''s island" +msgid "Invite Players" msgstr "" -msgid "§aYour incoming warp is active, players may warp to your island." +msgid "invite others to the island." msgstr "" -msgid "§4Your incoming warp is inactive, players may not warp to your island." +msgid "" +"invite\n" +"other players to the island if\n" +"there is enough room for more\n" +"members" msgstr "" -msgid "§fSet incoming warp to your current location using §e/island setwarp" +msgid "Kick Players" msgstr "" -msgid "§fToggle your warp on/off using §e/island togglewarp" +msgid "kick others from the island." msgstr "" -msgid "§4You do not have permission to create a warp on your island!" +msgid "" +"kick\n" +"other players from the island,\n" +"but they are unable to kick\n" +"the island leader." msgstr "" -msgid "§fWarp to another island using §e/island warp " +msgid "Ocean" msgstr "" -msgid "§4You do not have permission to warp to other islands!" +msgid "" +"The ocean biome is the basic\n" +"starting biome for all islands.\n" +"passive mobs like animals will\n" +"not spawn. Hostile mobs will\n" +"spawn normally." +msgstr "" + +msgid "Forest" msgstr "" msgid "" -"§cYour island is in the process of generating, you cannot warp to other " -"players islands right now." +"The forest biome will allow\n" +"your island to spawn passive.\n" +"mobs like animals (including\n" +"wolves). Hostile mobs will\n" +"spawn normally." msgstr "" -msgid "§4That player does not exist!" +msgid "Desert" msgstr "" -msgid "§4That player does not have an active warp." +msgid "" +"The desert biome makes it so\n" +"that there is no rain or snow\n" +"on your island. Passive mobs\n" +"won't spawn. Hostile mobs will\n" +"spawn normally." +msgstr "" + +msgid "Jungle" msgstr "" msgid "" -"§cThat players island is in the process of generating, you cannot warp to it " -"right now." +"The jungle biome is bright\n" +"and colorful. Passive mobs\n" +"(including ocelots) will\n" +"spawn. Hostile mobs will\n" +"spawn normally." msgstr "" -#, java-format -msgid "§cWARNING: §9{0}§e is warping to your island!" +msgid "Swampland" msgstr "" -msgid "§4That player has forbidden you from warping to their island." +msgid "" +"The swamp biome is dark\n" +"and dull. Passive mobs\n" +"will spawn normally and\n" +"slimes have a small chance\n" +"to spawn at night depending\n" +"on the moon phase." msgstr "" -msgid "§4No Island. §eUse §b/is create§e to get one" +msgid "Taiga" msgstr "" -msgid "accept/reject an invitation." +msgid "" +"The taiga biome has snow\n" +"instead of rain. Passive\n" +"mobs will spawn normally\n" +"(including wolves) and\n" +"hostile mobs will spawn." msgstr "" -msgid "leave your party" +msgid "Mushroom" msgstr "" msgid "" -"§4You can't leave your island if you are the only person. Try using /island " -"restart if you want a new one!" +"The mushroom biome is\n" +"bright and colorful.\n" +"Mooshrooms are the only\n" +"mobs that will spawn.\n" +"No other passive or\n" +"hostile mobs will spawn." msgstr "" -msgid "§eYou own this island, use /island remove instead." +msgid "Hell" msgstr "" -msgid "§eYou have left the island and returned to the player spawn." +msgid "" +"The hell biome looks\n" +"dark and dead. Some\n" +"mobs from the nether will\n" +"spawn in this biome\n" +"(excluding ghasts and\n" +"blazes)." msgstr "" -#, java-format -msgid "§4{0} has left your island!" +msgid "Sky" msgstr "" -msgid "§4You must be in the skyblock world to leave your party!" +msgid "" +"The sky biome gives your\n" +"island a special dark sky.\n" +"Only endermen will spawn\n" +"in this biome." msgstr "" -msgid "check your or anothers island level" +msgid "Plains" msgstr "" -msgid "allows user to query for others levels" +msgid "" +"The plains biome has rain\n" +"instead of snow. Passive\n" +"mobs will spawn normally\n" +"(including horses) and\n" +"hostile mobs will spawn." msgstr "" -msgid "§eYou must be on your island to use this command." +msgid "Extreme Hills" msgstr "" -msgid "§4You do not have an island!" +msgid "" +"The extreme hills biome.\n" +"Passive mobs will spawn \n" +"normally and hostile\n" +"mobs will spawn." msgstr "" -msgid "§4You do not have access to that command!" +msgid "Flower Forest" msgstr "" -msgid "§4That player is invalid or does not have an island!" +msgid "" +"The flower forest biome.\n" +"Passive mobs will spawn \n" +"normally and hostile\n" +"mobs will spawn." msgstr "" -#, java-format -msgid "§eInformation about {0}''s Island:" +msgid "Deep Ocean" msgstr "" -#, java-format -msgid "§aIsland level is {0,number,###.##}" +msgid "" +"The deep-ocean biome is an advanced\n" +"biome. Passive mobs like animals will\n" +"not spawn. Hostile mobs \n" +"(including Guardians) will\n" +"spawn normally." msgstr "" -#, java-format -msgid "§9Rank is {0}" +msgid "Ice Plains" msgstr "" -#, java-format -msgid "§4Could not locate rank of {0}" +msgid "" +"The ice-plains biome is an advanced biome.\n" +"Mobs will spawn naturally.\n" +"including polar-bears" msgstr "" -msgid "create an island" +msgid "Permissions" msgstr "" -msgid "exempt player from create-cooldown" +#, java-format +msgid "{0} <{1}>" msgstr "" -msgid "" -"§4Island found!§e You already have an island. If you want a fresh island, " -"type§b /is restart§e to get one" +msgid "§9Player Permissions" msgstr "" msgid "" -"§4Island found!§e You are already a member of an island. To start your own, " -"first§b /is leave" +"§eClick here to return to\n" +"§eyour island group''s info." msgstr "" #, java-format -msgid "§eYou can create a new island in {0,number,#} seconds." -msgstr "" - -msgid "invite a player to your island" +msgid "§e{0}''§9s Permissions" msgstr "" msgid "" -"§eUse§f /island invite §e to invite a player to your island." -msgstr "" - -msgid "§4Only the island''s owner can invite!" +"§eHover over an icon to view\n" +"§ea permission. Change the\n" +"§epermission by clicking it." msgstr "" -#, java-format -msgid "§aYou can invite {0} more players." +msgid "§fThis player §acan" msgstr "" -msgid "§4You can't invite any more players." +msgid "Click here to remove this permission." msgstr "" -msgid "§4You do not have permission to invite others to this island!" +msgid "§fThis player §ccannot" msgstr "" -msgid "§4That player is offline or doesn't exist." +msgid "Click here to grant this permission." msgstr "" -msgid "§4You can't invite yourself!" +msgid "Island Group Members" msgstr "" -msgid "§4That player is the leader of your island!" +#, java-format +msgid "Group Members: §2{0}§7/§e{1}" msgstr "" -msgid "lock your island to non-party members." +msgid "§aMore players can be invited to this island." msgstr "" -msgid "§4You do not have permission to lock your island!" +msgid "§cThis island is full." msgstr "" -msgid "§4You don't have access to this command!" +msgid "" +"§eHover over a player''s icon to\n" +"§eview their permissions. The\n" +"§eleader can change permissions\n" +"§eby clicking a player''s icon." msgstr "" -msgid "§4You do not have permission to unlock your island!" +#, java-format +msgid "§e{0}''s§9 Permissions" msgstr "" -msgid "display the top10 of islands" +msgid "Leader" msgstr "" -msgid "enables user to all-ways generate top-ten (no caching)" +msgid "Member" msgstr "" -msgid "remove a member from your island." +#, java-format +msgid "Can {0}" msgstr "" -msgid "§4You do not have permission to kick others from this island!" +#, java-format +msgid "Cannot {0}" msgstr "" -msgid "§4You can't remove the leader from the Island!" +msgid "§e" msgstr "" -msgid "§4Stop kickin' yourself!" +msgid "Island Log" msgstr "" -#, java-format -msgid "§4{0} has removed you from their island!" +msgid "" +"§eClick here to return to\n" +"§ethe main island screen." msgstr "" -#, java-format -msgid "§4{0} has been removed from the island." +msgid "§e§lIsland Log" msgstr "" -#, java-format -msgid "§4{0} tried to kick you from their island!" +msgid "Island Biome" msgstr "" #, java-format -msgid "§4{0} is exempt from being kicked." +msgid "Biome: {0}" msgstr "" -#, java-format -msgid "§4{0} has kicked you from their island!" +msgid "§2§lThis is your current biome." msgstr "" -#, java-format -msgid "§4{0} has been kicked from the island." +msgid "§e§lClick to change to this biome." msgstr "" -msgid "§4That player is not part of your island group, and not on your island!" +msgid "You cannot use this biome." msgstr "" -msgid "teleport to the island home" +msgid "§2chunk" msgstr "" -msgid "" -"§cYour island is in the process of generating, you cannot teleport home " -"right now." +msgid "§call" msgstr "" -msgid "§4This command can only be executed by a player" +#, java-format +msgid "§e{0}" msgstr "" -msgid "transfer leadership to another member" +msgid "§c-" msgstr "" -msgid "§4You can only transfer ownership to party-members!" +msgid "Decrease radius of biome-change" msgstr "" #, java-format -msgid "{0}§e is already leader of your island!" +msgid "Current radius: {0}" msgstr "" -msgid "§4Only leader can transfer leadership!" +msgid "§2+" msgstr "" -#, java-format -msgid "{0} tried to take over the island!" +msgid "Increase radius of biome-change" msgstr "" -msgid "show party information" +msgid "§7Current page" msgstr "" -msgid "shows information about your party" +msgid "§7First Page" msgstr "" -msgid "show pending invites" +msgid "§7Last Page" msgstr "" -msgid "§eNo pending invites" +msgid "Island Create Menu" msgstr "" -msgid "withdraw an invite" +msgid "§a§lStart an Island" msgstr "" -msgid "§4You don't have permissions to uninvite players." +msgid "" +"Start your skyblock journey\n" +"by starting your own island.\n" +"Complete challenges to earn\n" +"items and skybucks to help\n" +"expand your skyblock. You can\n" +"invite others to join in\n" +"building your island empire!\n" +"§e§lClick here to start!" msgstr "" -msgid "check your or another''s island info" +msgid "§aClick to create!" msgstr "" -msgid "allows user to see others island info" +#, java-format +msgid "" +"§cNo access!\n" +"§7({0})" msgstr "" -msgid "§4Hold your horses! §eYou have to be patient..." +msgid "§a§lReturn to Spawn" msgstr "" -#, java-format -msgid "§eBlocks on {0}s Island (page {1,number} of {2,number}):" +msgid "Teleport to the spawn area." msgstr "" -msgid "Score Count Block" +msgid "§a§lJoin an Island" msgstr "" -#, java-format -msgid "{0,number,00.00} {1,number,#} {2}" +msgid "" +"Want to join another player''s\n" +"island instead of starting\n" +"your own? If another player\n" +"invites you to their island\n" +"you can click here or use\n" +"§e/island accept§f to join them.\n" +"§e§lClick here to accept an invite!\n" +"§e§l(You must be invited first)" msgstr "" -msgid "trust/untrust a player to help on your island." +msgid "Island Menu" msgstr "" -msgid "§eThe following players are trusted on your island:" +msgid "§a§lReturn Home" msgstr "" -msgid "§eThe following leaders trusts you:" +msgid "" +"Return to your island''s home\n" +"point. You can change your home\n" +"point to any location on your\n" +"island using §b/island sethome\n" +"§e§lClick here to return home." msgstr "" -msgid "§eTo trust/untrust from your island, use /island trust " +msgid "§a§lChallenges" msgstr "" -msgid "§4Members are already trusted!" +msgid "" +"View a list of §9challenges that\n" +"you can complete on your island\n" +"to earn skybucks, items, perks,\n" +"and titles." msgstr "" -#, java-format -msgid "§4Unknown player {0}" +msgid "§e§lClick here to view challenges." msgstr "" -#, java-format -msgid "§eYou are now trusted on §4{0}''s §eisland." +msgid "§4§lChallenges disabled." msgstr "" -#, java-format -msgid "§a{0} trusted {1} on the island" +msgid "§a§lIsland Level" msgstr "" #, java-format -msgid "§eYou are no longer trusted on §4{0}''s §eisland." +msgid "§eCurrent Level: §a{0,number,##.#}" msgstr "" -#, java-format -msgid "§c{0} revoked trust in {1} on the island" +msgid "" +"Gain island levels by expanding\n" +"your skyblock and completing\n" +"certain challenges. Rarer blocks\n" +"will add more to your level.\n" +"§e§lClick here to refresh.\n" +"§e§l(must be on island)" msgstr "" -msgid "delete your island and start a new one." +msgid "Island Group" msgstr "" -msgid "exempt player from restart-cooldown" +#, java-format +msgid "§eMembers: §2{0}/{1}" msgstr "" msgid "" -"§4Only the owner may restart this island. Leave this island in order to " -"start your own (/island leave)." +"View the members of your island\n" +"group and their permissions. If\n" +"you are the island leader, you\n" +"can change the member permissions.\n" +"§e§lClick here to view or change." msgstr "" -msgid "" -"§eYou must remove all players from your island before you can restart it (/" -"island kick ). See a list of players currently part of your island " -"using /island party." +msgid "Change Island Biome" msgstr "" #, java-format -msgid "§cYou can restart your island in {0} seconds." +msgid "§eCurrent Biome: §b{0}" msgstr "" -msgid "§cYour island is in the process of generating, you cannot restart now." +msgid "" +"The island biome affects things\n" +"like grass color and spawning\n" +"of both animals and monsters." msgstr "" -msgid "§eNOTE: Your entire island and all your belongings will be RESET!" +msgid "§e§lClick here to change biomes." msgstr "" -msgid "teleports you to the skyblock spawn" +msgid "§c§lYou can't change the biome." msgstr "" -msgid "change the biome of the island" +msgid "§a§lIsland Lock" msgstr "" -msgid "exempt player from biome-cooldown" +msgid "" +"§eLock Status: §aActive\n" +"§fYour island is currently §clocked.\n" +"§fPlayers outside of your group\n" +"§fare unable to enter your island." msgstr "" -#, java-format -msgid "Let the player change their islands biome to {0}" +msgid "§e§lClick here to unlock your island." msgstr "" -msgid "" -"§cYou do not have permission to change the biome of your current island." +msgid "§c§lYou can't change the lock." msgstr "" -msgid "§4You do not have permission to change the biome of this island!" +msgid "" +"§eLock Status: §8Inactive\n" +"§fYour island is currently §aunlocked.\n" +"§fAll players are able to enter your\n" +"§fisland, but only you and your group\n" +"§fmembers may build there." msgstr "" -msgid "§eYou must be on your island to change the biome!" +msgid "§e§lClick here to lock your island." msgstr "" -#, java-format -msgid "§cYou have misspelled the biome name. Must be one of {0}" +msgid "§a§lIsland Warp" msgstr "" -#, java-format -msgid "§eYou can change your biome again in {0,number,#} minutes." +msgid "" +"§eWarp Status: §aActive\n" +"§fOther players may warp to your\n" +"§fisland at anytime to the point\n" +"§fyou set using §d/island setwarp." msgstr "" -msgid "§cYou do not have permission to change your biome to that type." +msgid "§e§lClick here to deactivate." msgstr "" -#, java-format -msgid "" -"§7The pixies are busy changing the biome near you to §9{0}§7, be patient." +msgid "§c§lYou can't change the warp." msgstr "" -#, java-format msgid "" -"§7The pixies are busy changing the biome in your current chunk to §9{0}§7, " -"be patient." -msgstr "" - -#, java-format -msgid "§eInvalid biome {0} supplied!" +"§eWarp Status: §8Inactive\n" +"§fOther players can't warp to your\n" +"§fisland. Set a warp point using\n" +"§d/island setwarp §fbefore activating." msgstr "" -#, java-format -msgid "§aYou have changed your island''s biome to {0}" +msgid "§e§lClick here to activate." msgstr "" -#, java-format -msgid "{0} changed the island biome to {1}" +msgid "§a§lIsland Log" msgstr "" -#, java-format -msgid "§aYou have changed {0} blocks around you to the {1} biome" +msgid "" +"View a log of events from\n" +"your island such as member,\n" +"biome, and warp changes.\n" +"§e§lClick to view the log." msgstr "" -#, java-format -msgid "{0} created an area with {1} biome" +msgid "§a§lChange Home Location" msgstr "" -msgid "set your island''s warp location" +msgid "" +"When you teleport to your\n" +"island you will be taken to\n" +"this location.\n" +"§e§lClick here to change." msgstr "" -msgid "§cYou do not have permission to set your island''s warp point!" +msgid "§a§lChange Warp Location" msgstr "" -msgid "§cYou need to be on your own island to set the warp!" +msgid "" +"When your warp is activated,\n" +"other players will be taken to\n" +"this point when they teleport\n" +"to your island." msgstr "" -#, java-format -msgid "§b{0}§d changed the island warp location." +msgid "§e§lClick here to change." msgstr "" -msgid "teleports you to your island (or create one)" +msgid "§c§lRestart Island" msgstr "" -msgid "ban/unban a player from your island." +msgid "" +"Restarts your island.\n" +"§4WARNING! §cwill remove your items and island!" msgstr "" -msgid "exempts user from being banned" +msgid "§c§lLeave Island" msgstr "" -msgid "§eThe following players are banned from warping to your island:" +msgid "" +"Leaves your island.\n" +"§4WARNING! §cwill remove all your items!" msgstr "" -msgid "§eTo ban/unban from your island, use /island ban " +msgid "§cClick to leave" msgstr "" -msgid "§4You can't ban members. Remove them first!" +msgid "Island Restart Menu" msgstr "" -msgid "§4You do not have permission to kick/ban players." +msgid "§eYou do not have access to that island-schematic!" msgstr "" #, java-format -msgid "§eUnable to ban unknown player {0}" +msgid "§cClick within §9{0}§c to leave!" msgstr "" -#, java-format -msgid "§4{0} tried to ban you from their island!" +msgid "§a§lReturn to the main menu" msgstr "" #, java-format -msgid "§4{0} is exempt from being banned." +msgid "§cClick within §9{0}§c to restart!" msgstr "" -#, java-format -msgid "§eYou have banned §4{0}§e from warping to your island." +msgid "§aClick to restart!" msgstr "" -#, java-format -msgid "§eYou have been §cBANNED§e from {0}§e''s island." +msgid "Caps On" msgstr "" -#, java-format -msgid "§eYou have unbanned §a{0}§e from warping to your island." +msgid "§9Text Editor" msgstr "" #, java-format -msgid "§eYou have been §aUNBANNED§e from {0}§e''s island." +msgid "Too many requests for Mojangs API ({0} within {1}), sleeping {2}" msgstr "" -msgid "display log" +msgid "§9Hold your horses! You have to be patient..." msgstr "" -msgid "changes a members island-permissions" +msgid "§9Not really patient, are you?" msgstr "" -#, java-format -msgid "§ePermissions for §9{0}§e:" +msgid "§9Be patient, young padawan" msgstr "" -msgid "§aON" +msgid "§9Patience you MUST have, young padawan" msgstr "" -msgid "§cOFF" +msgid "§9The two most powerful warriors are patience and time." msgstr "" -#, java-format -msgid "§7 - §6{0}§7 : {1}" +msgid "§eSending you to spawn." msgstr "" -#, java-format -msgid "§cInvalid permission {0}. Must be one of {1}" +msgid "§eThe island has been §cLOCKED§e." msgstr "" -#, java-format -msgid "§eToggled permission §9{0}§e for §9{1}§e to {2}" +msgid "§4Unable to find a safe home-location on your island!" msgstr "" -#, java-format -msgid "§eUnable to toggle permission §9{0}§e for §9{1}" +msgid "§cWARNING: §eTeleporting you to mid-air." msgstr "" -msgid "set the island-home" +msgid "§aTeleporting you to your island." msgstr "" -msgid "show the islands limits" +#, java-format +msgid "§aYou will be teleported in {0} seconds." msgstr "" -msgid "enable/disable warping to your island." +msgid "§4Unable to warp you to that player''s island!" msgstr "" -msgid "§4Your island is locked. You must unlock it before enabling your warp." +#, java-format +msgid "§aTeleporting you to {0}''s island." msgstr "" -#, java-format -msgid "§b{0}§d activated the island warp." +msgid "§7Teleport cancelled" msgstr "" -msgid "§cYou do not have permission to enable/disable your island''s warp!" +msgid "READY" msgstr "" -msgid "try to complete a challenge" +msgid "" +"§cWARNING:§e Could not transfer all the required items to your inventory!" msgstr "" -msgid "show information about the challenge" +msgid "§cNot enough items in chest to complete challenge!" msgstr "" -msgid "§eRank: " +msgid "Something went wrong saving the island and/or party data!" msgstr "" -msgid "§4This Challenge is not repeatable!" +msgid "Converting data to UUID, this make take a while!" msgstr "" -msgid "§4You will lose all required items when you complete this challenge!" +msgid "§cMAINTENANCE:§e uSkyBlock is currently in maintenance mode" msgstr "" #, java-format msgid "" -"§4All required items must be placed on your island, within {0} blocks of you." +"§buSkyBlock§e depends on §9{0}§e >= §av{1}§e but only §cv{2}§e was found!\n" msgstr "" #, java-format -msgid "§eTo complete this challenge, use §f/c c {0}" -msgstr "" - -msgid "§4Invalid challenge name! Use /c help for more information" -msgstr "" - -msgid "§eSending you to spawn." +msgid "§buSkyBlock§e depends on §9{0}§e >= §av{1}" msgstr "" -msgid "§eThe island has been §cLOCKED§e." +msgid "§4Player is already assigned to this island!" msgstr "" -msgid "§9Hold your horses! You have to be patient..." +msgid "§cYour island is in the process of generating, you cannot create now." msgstr "" -msgid "§9Not really patient, are you?" +msgid "Could not create your Island. Please contact a server moderator." msgstr "" -msgid "§9Be patient, young padawan" +msgid "§eGetting your island ready, please be patient, it can take a while." msgstr "" -msgid "§9Patience you MUST have, young padawan" +msgid "§cCommand is currently disabled!" msgstr "" -msgid "§9The two most powerful warriors are patience and time." +msgid "North" msgstr "" -msgid "§4Unable to find a safe home-location on your island!" +msgid "North-East" msgstr "" -msgid "§cWARNING: §eTeleporting you to mid-air." +msgid "East" msgstr "" -msgid "§aTeleporting you to your island." +msgid "South-East" msgstr "" -#, java-format -msgid "§aYou will be teleported in {0} seconds." +msgid "South" msgstr "" -msgid "§4Unable to warp you to that player''s island!" +msgid "South-West" msgstr "" -#, java-format -msgid "§aTeleporting you to {0}''s island." +msgid "West" msgstr "" -msgid "§7Teleport cancelled" +msgid "North-West" msgstr "" From 11a2ea63c17de8c8573d92e989e4475d758fdc75 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 14 Mar 2021 01:57:57 +0000 Subject: [PATCH 072/190] Update crowdin.yml --- crowdin.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crowdin.yml b/crowdin.yml index 93a2ec281..22256eadf 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,3 +1,16 @@ +commit_message: "[ci skip]" files: - source: /uSkyBlock-Core/src/main/po/keys.pot translation: /uSkyBlock-Core/src/main/po/%locale_with_underscore%.po + languages_mapping: + locale_with_underscore: + cs: cs + da: da + de: de + es-ES: es + fr: fr + it: it + ko: ko + nl: nl + ru: ru + sv: sv From a954f4946d90e378553e9818e7a7714c91f20ea4 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 20 Jul 2021 12:16:58 +0100 Subject: [PATCH 073/190] Bukkit 1.17 (#20) * Java 16 * Spigot 1.17 * Bump FAWE to 1.17 beta * Use bukkit-utils 1.25-SNAPSHOT * Deploy 1.17 builds for testing * [CI SKIP] Bump minimal dependency versions * Bump WorldEdit, WorldGuard versions * Only run setupWorld when the world isn't configured yet * Fix deprecated newInstance calls in worldmanager --- .travis.yml | 8 +++- README.md | 2 +- pom.xml | 30 ++++++++------- scripts/deploy-117.sh | 14 +++++++ uSkyBlock-API/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 29 +++++++-------- .../talabrek/ultimateskyblock/uSkyBlock.java | 14 +++---- .../ultimateskyblock/world/WorldManager.java | 37 +++++++++++-------- uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- uSkyBlock-FAWE/pom.xml | 5 +-- .../handler/asyncworldedit/FAWEAdaptor.java | 2 +- 11 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 scripts/deploy-117.sh diff --git a/.travis.yml b/.travis.yml index b7ad96985..e22b7df8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: java jdk: -- openjdk8 +- openjdk16 sudo: false cache: directories: @@ -24,6 +24,7 @@ before_deploy: - ssh-add deploy_rsa - chmod +x scripts/deploy-staging.sh - chmod +x scripts/deploy-release.sh + - chmod +x scripts/deploy-117.sh deploy: - provider: script skip_cleanup: true @@ -35,3 +36,8 @@ deploy: script: bash scripts/deploy-release.sh on: tags: true + - provider: script + skip_cleanup: true + script: bash scripts/deploy-117.sh + on: + branch: "bukkit-1.17" diff --git a/README.md b/README.md index bc730e29a..b73a6219d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ We are on [Spigot](https://www.spigotmc.org/resources/uskyblock-revived.66795/). This version depends on the following plugins: -* Spigot/Paper 1.16.1-R0.1-SNAPSHOT +* Spigot/Paper 1.17-R0.1-SNAPSHOT * Vault 1.7.x * WorldEdit 7.1.0-SNAPSHOT * WorldGuard 7.0.2-SNAPSHOT diff --git a/pom.xml b/pom.xml index 0323ef243..d8095fc9b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,13 +10,13 @@ 19.0.0 ${project.version} - 1.23-SNAPSHOT + 1.25-SNAPSHOT 1.0.4 1.6 - 1.16.1-R0.1-SNAPSHOT + 1.17-R0.1-SNAPSHOT 1.7 - 7.2.0-SNAPSHOT - 7.0.4-SNAPSHOT + 7.2.6-SNAPSHOT + 7.0.6-SNAPSHOT UTF-8 ${project.artifactId} @@ -24,16 +24,12 @@ dev msgfmt msgmerge - - 1.8 - 1.8 2.1 4.12 5.5.1 - 3.0.0 - 2.0.2 + 3.11.0 @@ -68,19 +64,23 @@ maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 16 org.apache.maven.plugins maven-jar-plugin - 3.1.2 + 3.2.0 org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 + 3.3.0 + + + org.apache.maven.plugins + maven-shade-plugin + 3.3.0-SNAPSHOT org.apache.maven.plugins @@ -126,6 +126,10 @@ + + apache-snapshots + https://repository.apache.org/snapshots/ + uskyblock-dependencies https://www.uskyblock.ovh/maven/dependencies/ diff --git a/scripts/deploy-117.sh b/scripts/deploy-117.sh new file mode 100644 index 000000000..5223828fe --- /dev/null +++ b/scripts/deploy-117.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then + + echo -e "Running 1.17 test release script...\n" + cd $HOME + + echo -e "Publishing final plugin release...\n" + + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ + travis@travis.internetpolice.eu:WWW-USB/downloads/testbuilds/1.17/ + +fi diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 6c9e779a4..30c4046d2 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -31,7 +31,7 @@ org.spigotmc spigot-api - 1.16.1-R0.1-SNAPSHOT + 1.17-R0.1-SNAPSHOT provided true diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 2bbdb9ee9..6b0a89e1b 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -17,8 +17,7 @@ org.apache.maven.plugins maven-compiler-plugin - 1.8 - 1.8 + 16 utf-8 @@ -72,7 +71,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.1.0 package @@ -105,13 +103,24 @@ us.talabrek.ultimateskyblock.paperlib + + + *:* + + META-INF/*.MF + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + maven-clean-plugin - 2.6.1 + 3.1.0 @@ -480,17 +489,5 @@ ${mockito.version} test - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 0b974816f..fad54c346 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -114,13 +114,13 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManager.RequirementChecker { private static final String CN = uSkyBlock.class.getName(); private static final String[][] depends = new String[][]{ - new String[]{"Vault", "1.7.0", "optional"}, - new String[]{"WorldEdit", "7.0", "optionalIf", "FastAsyncWorldEdit"}, - new String[]{"WorldGuard", "7.0"}, - new String[]{"FastAsyncWorldEdit", "1.16", "optional"}, - new String[]{"Multiverse-Core", "2.5", "optional"}, - new String[]{"Multiverse-Portals", "2.5", "optional"}, - new String[]{"Multiverse-NetherPortals", "2.5", "optional"}, + new String[]{"Vault", "1.7.1", "optional"}, + new String[]{"WorldEdit", "7.2.6", "optionalIf", "FastAsyncWorldEdit"}, + new String[]{"WorldGuard", "7.0.6"}, + new String[]{"FastAsyncWorldEdit", "1.17", "optional"}, + new String[]{"Multiverse-Core", "4.3.0", "optional"}, + new String[]{"Multiverse-Portals", "4.2.1", "optional"}, + new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, }; private static String missingRequirements = null; private static final Random RND = new Random(System.currentTimeMillis()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index e474fa86f..6f4eae20c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -21,6 +21,7 @@ import us.talabrek.ultimateskyblock.util.LocationUtil; import java.io.File; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; @@ -137,12 +138,14 @@ private ChunkGenerator getOverworldGenerator() { try { String clazz = plugin.getConfig().getString("options.advanced.chunk-generator", "us.talabrek.ultimateskyblock.world.SkyBlockChunkGenerator"); - Object generator = Class.forName(clazz).newInstance(); + Object generator = Class.forName(clazz).getDeclaredConstructor().newInstance(); if (generator instanceof ChunkGenerator) { return (ChunkGenerator) generator; } - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ex) { + } catch (ClassNotFoundException ex) { logger.log(Level.WARNING, "Invalid overworld chunk-generator configured: " + ex); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex) { + plugin.getLogger().log(Level.WARNING, "Unable to instantiate overworld chunk-generator: " + ex); } return new SkyBlockChunkGenerator(); } @@ -156,12 +159,14 @@ private ChunkGenerator getNetherGenerator() { try { String clazz = plugin.getConfig().getString("nether.chunk-generator", "us.talabrek.ultimateskyblock.world.SkyBlockNetherChunkGenerator"); - Object generator = Class.forName(clazz).newInstance(); + Object generator = Class.forName(clazz).getDeclaredConstructor().newInstance(); if (generator instanceof ChunkGenerator) { return (ChunkGenerator) generator; } - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ex) { + } catch (ClassNotFoundException ex) { logger.log(Level.WARNING, "Invalid nether chunk-generator configured: " + ex); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex) { + plugin.getLogger().log(Level.WARNING, "Unable to instantiate nether chunk-generator: " + ex); } return new SkyBlockNetherChunkGenerator(); } @@ -205,13 +210,13 @@ public synchronized World getWorld() { .createWorld(); skyBlockWorld.save(); } - } - plugin.getServer().getScheduler().runTaskLater(plugin, () -> - plugin.getHookManager().getMultiverse().ifPresent(hook -> { - hook.registerOverworld(skyBlockWorld); - setupWorld(skyBlockWorld, Settings.island_height); - }), plugin.getConfig().getLong("init.initDelay", 50L) + 40L); + plugin.getServer().getScheduler().runTaskLater(plugin, () -> + plugin.getHookManager().getMultiverse().ifPresent(hook -> { + hook.registerOverworld(skyBlockWorld); + setupWorld(skyBlockWorld, Settings.island_height); + }), plugin.getConfig().getLong("init.initDelay", 50L) + 40L); + } return skyBlockWorld; } @@ -244,13 +249,13 @@ public synchronized World getNetherWorld() { .createWorld(); skyBlockNetherWorld.save(); } - } - plugin.getServer().getScheduler().runTaskLater(plugin, () -> - plugin.getHookManager().getMultiverse().ifPresent(hook -> { - hook.registerNetherworld(skyBlockNetherWorld); - setupWorld(skyBlockNetherWorld, island_height / 2); - }), plugin.getConfig().getLong("init.initDelay", 50L) + 100L); + plugin.getServer().getScheduler().runTaskLater(plugin, () -> + plugin.getHookManager().getMultiverse().ifPresent(hook -> { + hook.registerNetherworld(skyBlockNetherWorld); + setupWorld(skyBlockNetherWorld, island_height / 2); + }), plugin.getConfig().getLong("init.initDelay", 50L) + 100L); + } return skyBlockNetherWorld; } diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 5b524b824..afdf9b078 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -18,7 +18,7 @@ softdepend: - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.16 +api-version: 1.17 commands: challenges: diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 3e4720a2d..26bf3e5c3 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -19,9 +19,9 @@ - com.intellectualsites.fawe + com.fastasyncworldedit FAWE-Bukkit - 1.16-412 + 1.17-6 provided @@ -55,7 +55,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 package diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index bb9d14e57..7604a3077 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -1,6 +1,6 @@ package us.talabrek.ultimateskyblock.handler.asyncworldedit; -import com.boydti.fawe.util.EditSessionBuilder; +import com.fastasyncworldedit.core.util.EditSessionBuilder; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; From 44e099e22aeae47ffb66139b45f304b9ef22cff5 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 20 Jul 2021 12:19:58 +0100 Subject: [PATCH 074/190] Update submodule --- bukkit-utils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bukkit-utils b/bukkit-utils index f4b494106..0d460c7d6 160000 --- a/bukkit-utils +++ b/bukkit-utils @@ -1 +1 @@ -Subproject commit f4b494106b4c748c1f60404a65a62c03165dd162 +Subproject commit 0d460c7d652ea90444284484082a566c38fd2b95 From 2663f811e80916454b1cd00f3fdd853b4e741cfa Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 20 Jul 2021 12:27:43 +0100 Subject: [PATCH 075/190] Remove DeluxeChat PlaceholderAPI --- pom.xml | 6 --- uSkyBlock-Core/pom.xml | 4 -- .../placeholder/DeluxeChatPlaceholderAPI.java | 50 ------------------- .../placeholder/PlaceholderHandler.java | 1 - uSkyBlock-Core/src/main/resources/config.yml | 3 -- 5 files changed, 64 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/DeluxeChatPlaceholderAPI.java diff --git a/pom.xml b/pom.xml index d8095fc9b..fedd50682 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,6 @@ ${project.version} 1.25-SNAPSHOT 1.0.4 - 1.6 1.17-R0.1-SNAPSHOT 1.7 7.2.6-SNAPSHOT @@ -196,11 +195,6 @@ po-utils ${project.version} - - me.clip.deluxechat - DeluxeChatPlaceholderAPI - ${deluxechat.version} - org.jetbrains annotations diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 6b0a89e1b..bd578196e 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -437,10 +437,6 @@ - - me.clip.deluxechat - DeluxeChatPlaceholderAPI - org.jetbrains diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/DeluxeChatPlaceholderAPI.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/DeluxeChatPlaceholderAPI.java deleted file mode 100644 index 5d77bb786..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/DeluxeChatPlaceholderAPI.java +++ /dev/null @@ -1,50 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.placeholder; - -import me.clip.deluxechat.placeholders.DeluxePlaceholderHook; -import me.clip.deluxechat.placeholders.PlaceholderHandler; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; - -/** - * DeluxeChatPlaceholder integration - */ -public class DeluxeChatPlaceholderAPI implements PlaceholderAPI { - private uSkyBlock plugin; - private PlaceholderReplacer replacer; - - @Override - public boolean registerPlaceholder(uSkyBlock plugin, PlaceholderReplacer replacer) { - this.plugin = plugin; - this.replacer = replacer; - if (Bukkit.getPluginManager().isPluginEnabled("DeluxeChat")) { - Hook hook = new Hook(); - me.clip.deluxechat.placeholders.PlaceholderHandler.registerPlaceholderHook(plugin, hook); - return true; - } - return false; - } - - @Override - public void unregisterPlaceholder(uSkyBlock plugin, PlaceholderReplacer placeholderReplacer) { - if (Bukkit.getPluginManager().isPluginEnabled("DeluxeChat")) { - PlaceholderHandler.unregisterPlaceholderHook(plugin); - } - } - - @Override - public String replacePlaceholders(Player player, String message) { - return PlaceholderHandler.setPlaceholders(player, message); - } - - private class Hook extends DeluxePlaceholderHook { - @Override - public String onPlaceholderRequest(Player player, String placeholder) { - String usbPlaceholder = "usb_" + placeholder; - if (replacer.getPlaceholders().contains(usbPlaceholder)) { - return replacer.replace(player, player, usbPlaceholder); - } - return null; - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java index e9204b8a8..377ca08ed 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java @@ -13,7 +13,6 @@ public class PlaceholderHandler { ChatPlaceholder.class.getName(), ServerCommandPlaceholder.class.getName(), "us.talabrek.ultimateskyblock.handler.placeholder.MVdWPlaceholderAPI", - "us.talabrek.ultimateskyblock.handler.placeholder.DeluxeChatPlaceholderAPI" }; private static PlaceholderAPI.PlaceholderReplacer replacer; diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index 829732e18..d53d13e7b 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -442,9 +442,6 @@ tool-menu: # usb_island_golems, usb_island_monsters, usb_island_animals, usb_island_villagers placeholder: - # Hooks directly into DeluxeChatPlaceholderAPI - deluxechatplaceholderapi: false - # Hooks into MVdWPlaceholderAPI mvdwplaceholderapi: false From 7cf840c28d5ec5f3f9222f8da9be1d410ca9b1f3 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 20 Jul 2021 16:02:54 +0100 Subject: [PATCH 076/190] Version to 2.9.0 for release --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index d282f8dd0..15de53848 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0-SNAPSHOT + 2.9.0 4.0.0 jar diff --git a/pom.xml b/pom.xml index fedd50682..b8fa8b8ef 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.9.0-SNAPSHOT + 2.9.0 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 30c4046d2..187448704 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.9.0-SNAPSHOT + 2.9.0 UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 49d4920d1..5b36c13f9 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0-SNAPSHOT + 2.9.0 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index bd578196e..efaf9b334 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0-SNAPSHOT + 2.9.0 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 26bf3e5c3..fe8f6a8a5 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0-SNAPSHOT + 2.9.0 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 61e5bf501..5953d9efc 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0-SNAPSHOT + 2.9.0 4.0.0 jar From d4b1841d8b83e0e4be3dba9738a95c2cd844fcb4 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 20 Jul 2021 17:21:03 +0100 Subject: [PATCH 077/190] Version to 2.10.0-SNAPSHOT, build using GH Actions too --- .github/workflows/build.yml | 36 ++++++++++++++++++++++++++++++++++++ po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 8 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..2435ff173 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: Maven build + +on: + push: + branches: [ gh-actions ] + pull_request: + branches: [ gh-actions ] + +jobs: + build_and_test: + if: github.repository_owner == 'Muspah' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Checkout submodules + run: | + sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules + git submodule update --init --recursive + - name: Generate additional language files + run: | + cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - + cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - + - name: JDK 16 + uses: actions/setup-java@v1 + with: + java-version: '16' + distribution: 'adopt' + - name: Cache Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + - name: Build with Maven + run: mvn -U -Pi18n clean deploy diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 15de53848..edb126758 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0 + 2.10.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index b8fa8b8ef..d46066805 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.9.0 + 2.10.0-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 187448704..b80ec6f51 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.9.0 + 2.10.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 5b36c13f9..197e8a3c5 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0 + 2.10.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index efaf9b334..a52672910 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0 + 2.10.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index fe8f6a8a5..3a78bea99 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0 + 2.10.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 5953d9efc..29aae91ff 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.9.0 + 2.10.0-SNAPSHOT 4.0.0 jar From bc2dddfcf06eac2d829a5f671c7c168c224ffa83 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 20 Jul 2021 17:23:41 +0100 Subject: [PATCH 078/190] Stupid copy/pasta, time to stop for today --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2435ff173..6cac5b8aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,13 +2,13 @@ name: Maven build on: push: - branches: [ gh-actions ] + branches: [ master ] pull_request: - branches: [ gh-actions ] + branches: [ master ] jobs: build_and_test: - if: github.repository_owner == 'Muspah' + if: github.repository_owner == 'uskyblock' runs-on: ubuntu-latest steps: - name: Checkout repository From 6dce0bc6227a2478befac44b18a4485e27129271 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 26 Jul 2021 21:52:24 +0100 Subject: [PATCH 079/190] Replace outdated ActionbarAPI with Kyori's Adventure --- pom.xml | 16 ++++++ .../handler/asyncworldedit/AWE370Adaptor.java | 11 ++-- uSkyBlock-Core/pom.xml | 42 ++++++++------- .../handler/ActionBarHandler.java | 37 ------------- .../handler/AsyncWorldEditHandler.java | 4 +- .../actionbarapi/ActionBarAPIAdaptor.java | 13 ----- .../handler/asyncworldedit/AWEAdaptor.java | 5 +- .../handler/asyncworldedit/PlayerJob.java | 9 ++-- .../player/NotificationManager.java | 52 +++++++++++++++++++ .../ultimateskyblock/player/PlayerLogic.java | 8 +++ .../talabrek/ultimateskyblock/uSkyBlock.java | 2 +- .../handler/asyncworldedit/FAWEAdaptor.java | 6 +-- 12 files changed, 119 insertions(+), 86 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ActionBarHandler.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/actionbarapi/ActionBarAPIAdaptor.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java diff --git a/pom.xml b/pom.xml index d46066805..963f15f04 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,8 @@ Ultimate SkyBlock + 4.8.1 + 4.0.0-SNAPSHOT 19.0.0 ${project.version} 1.25-SNAPSHOT @@ -107,6 +109,10 @@ sk89q-repo https://maven.sk89q.com/repo/ + + sonatype-oss-snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + CodeMC https://repo.codemc.org/repository/maven-public @@ -205,6 +211,16 @@ paperlib ${paperlib.version} + + net.kyori + adventure-api + ${adventure-api.version} + + + net.kyori + adventure-platform-bukkit + ${adventure-bukkit.version} + diff --git a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java index 43101be7d..c102563ed 100644 --- a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java +++ b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java @@ -16,7 +16,6 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitTask; import org.primesoft.asyncworldedit.api.IAsyncWorldEdit; import org.primesoft.asyncworldedit.api.blockPlacer.IBlockPlacerPlayer; @@ -50,6 +49,7 @@ public class AWE370Adaptor implements AWEAdaptor { static long progressEveryMs = 3000; // 2 seconds static double progressEveryPct = 20; private static final Set pendingJobs = Collections.synchronizedSet(new LinkedHashSet<>()); + private uSkyBlock plugin; private static void updateProgress(IPlayerEntry playerEntry, int queuedBlocks, int maxQueuedBlocks) { if (maxQueuedBlocks <= 1) { @@ -94,14 +94,15 @@ private static IAsyncWorldEdit getAWE() { } @Override - public void onEnable(Plugin plugin) { + public void onEnable(uSkyBlock plugin) { + this.plugin = plugin; progressEveryMs = plugin.getConfig().getInt("asyncworldedit.progressEveryMs", 3000); progressEveryPct = plugin.getConfig().getDouble("asyncworldedit.progressEveryPct", 20); } @Override public void registerCompletion(Player player) { - PlayerJob newJob = new PlayerJob(player, progressEveryMs, progressEveryPct); + PlayerJob newJob = new PlayerJob(player, progressEveryMs, progressEveryPct, plugin); pendingJobs.remove(newJob); pendingJobs.add(newJob); } @@ -127,7 +128,7 @@ public void loadIslandSchematic(final File file, final Location origin, final Pl if (timerTask != null) { timerTask.cancel(); } - timerTask = uSkyBlock.getInstance().async(new Runnable() { + timerTask = plugin.async(new Runnable() { int maxSize = -1; @Override public void run() { @@ -158,7 +159,7 @@ public void regenerate(Region region, Runnable onCompletion) { } @Override - public void onDisable(Plugin plugin) { + public void onDisable(uSkyBlock plugin) { } private static class PasteAction implements IFuncParamEx { diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index a52672910..e7f253489 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -82,18 +82,15 @@ true - org.bstats:* - io.papermc:paperlib + com.googlecode.json-simple:json-simple dk.lockfuglsang.minecraft:bukkit-utils + io.papermc:paperlib + net.kyori:* + org.bstats:* uSkyBlock:po-utils - com.googlecode.json-simple:json-simple - - org.bstats - us.talabrek.ultimateskyblock.metrics - dk.lockfuglsang.minecraft us.talabrek.ultimateskyblock.utils @@ -102,6 +99,14 @@ io.papermc.lib us.talabrek.ultimateskyblock.paperlib + + net.kyori + us.talabrek.ultimateskyblock.kyori + + + org.bstats + us.talabrek.ultimateskyblock.metrics + @@ -411,19 +416,6 @@ 21.0 provided - - - com.connorlinfoot.actionbarapi - ActionBarAPI - 1.5.4 - provided - - - org.bukkit - bukkit - - - be.maximvdw MVdWPlaceholderAPI @@ -437,6 +429,16 @@ + + net.kyori + adventure-api + compile + + + net.kyori + adventure-platform-bukkit + compile + org.jetbrains diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ActionBarHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ActionBarHandler.java deleted file mode 100644 index d524f079a..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ActionBarHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.handler.actionbarapi.ActionBarAPIAdaptor; - -/** - * Static handler allowing for soft-depend. - */ -public enum ActionBarHandler {; - public static boolean isEnabled() { - return isActionBarAPI(); - } - - public static boolean isActionBarAPI() { - return Bukkit.getPluginManager().isPluginEnabled("ActionBarAPI"); - } - - public static void sendActionBar(Player player, String message) { - try { - if (isActionBarAPI()) { - ActionBarAPIAdaptor.sendActionBar(player, message); - } else { - sendFallback(player, message); - } - } catch (Exception e) { - // Suppress incompatibilities - this is just a "best-effort" approach. - sendFallback(player, message); - } - } - - private static void sendFallback(Player player, String message) { - if (player != null) { - player.sendMessage(message); - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 0363c792f..cddcad072 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -97,7 +97,7 @@ public static Plugin getAWE() { public static final AWEAdaptor NULL_ADAPTOR = new AWEAdaptor() { @Override - public void onEnable(Plugin plugin) { + public void onEnable(uSkyBlock plugin) { } @@ -112,7 +112,7 @@ public void loadIslandSchematic(File file, Location origin, PlayerPerk playerPer } @Override - public void onDisable(Plugin plugin) { + public void onDisable(uSkyBlock plugin) { } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/actionbarapi/ActionBarAPIAdaptor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/actionbarapi/ActionBarAPIAdaptor.java deleted file mode 100644 index cabd286ff..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/actionbarapi/ActionBarAPIAdaptor.java +++ /dev/null @@ -1,13 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.actionbarapi; - -import com.connorlinfoot.actionbarapi.ActionBarAPI; -import org.bukkit.entity.Player; - -/** - * Runtime adaptor. - */ -public enum ActionBarAPIAdaptor {; - public static void sendActionBar(Player player, String message) { - ActionBarAPI.sendActionBar(player, message); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java index 3a21eafaa..959e57e1b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWEAdaptor.java @@ -8,6 +8,7 @@ import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.player.PlayerPerk; +import us.talabrek.ultimateskyblock.uSkyBlock; import java.io.File; @@ -15,9 +16,9 @@ * Interface for various AWE version-adaptors. */ public interface AWEAdaptor { - void onEnable(Plugin plugin); + void onEnable(uSkyBlock plugin); - void onDisable(Plugin plugin); + void onDisable(uSkyBlock plugin); void loadIslandSchematic(File file, Location origin, @Nullable PlayerPerk playerPerk); void registerCompletion(Player player); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java index 4c24f52c5..9f32b0031 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java @@ -2,7 +2,7 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.handler.ActionBarHandler; +import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.logging.Logger; @@ -17,6 +17,7 @@ class PlayerJob { private long lastProgressMs; private double percentage; private double lastProgressPct; + private final uSkyBlock plugin; /** * The number of blocks placed in previous jobs @@ -26,8 +27,10 @@ class PlayerJob { private int maxQueuedBlocks; private int startOffset; - PlayerJob(Player player, long progressEveryMs, double progressEveryPct) { + PlayerJob(Player player, long progressEveryMs, double progressEveryPct, uSkyBlock plugin) { this.player = player; + this.plugin = plugin; + this.progressEveryMs = progressEveryMs; this.progressEveryPct = progressEveryPct; lastProgressMs = System.currentTimeMillis(); @@ -65,7 +68,7 @@ public int progress(int blocksPlaced) { private void showProgress(String message) { long t = System.currentTimeMillis(); if (t > (lastProgressMs + progressEveryMs) || percentage > (lastProgressPct + progressEveryPct)) { - ActionBarHandler.sendActionBar(player, message); + plugin.getPlayerLogic().getNotificationManager().sendActionBar(player, message); lastProgressMs = t; lastProgressPct = Math.floor(percentage/ progressEveryPct) * progressEveryPct; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java new file mode 100644 index 000000000..48b864048 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java @@ -0,0 +1,52 @@ +package us.talabrek.ultimateskyblock.player; + +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public class NotificationManager { + private final uSkyBlock plugin; + private final BukkitAudiences audiences; + private LegacyComponentSerializer legacySerializer; + + public NotificationManager(uSkyBlock plugin) { + this.plugin = plugin; + audiences = BukkitAudiences.create(plugin); + } + + /** + * Gets a {@link LegacyComponentSerializer} configured for uSkyBlock's (translatable) messages. + * @return LegacyComponentSerializer configured for uSkyblock's (translatable) messages. + */ + public @NotNull LegacyComponentSerializer getLegacySerializer() { + if (legacySerializer == null) { + legacySerializer = LegacyComponentSerializer.builder().character('\u00a7').build(); + } + return legacySerializer; + } + + /** + * Sends the given {@link String} as message to the {@link Player}'s ActionBar. + * @param player Player to send the given message to + * @param message Message to send to the given player + */ + public void sendActionBar(@NotNull Player player, @NotNull String message) { + sendActionBar(player, getLegacySerializer().deserialize(message)); + } + + /** + * Sends the given {@link Component} as message to the {@link Player}'s ActionBar. + * @param player Player to send the given message to + * @param component Component to send to the given player + */ + public void sendActionBar(@NotNull Player player, @NotNull Component component) { + audiences.player(player).sendActionBar(component); + } + + public void shutdown() { + audiences.close(); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java index 2f1366e8e..9a6f9a5c5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java @@ -7,6 +7,7 @@ import com.google.common.cache.RemovalNotification; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -30,6 +31,7 @@ public class PlayerLogic { private final uSkyBlock plugin; private final BukkitTask saveTask; private final PlayerDB playerDB; + private final NotificationManager notificationManager; public PlayerLogic(uSkyBlock plugin) { this.plugin = plugin; @@ -61,6 +63,7 @@ public void run() { saveDirtyToFiles(); } }, every, every); + notificationManager = new NotificationManager(plugin); } private void saveDirtyToFiles() { @@ -168,6 +171,7 @@ public void removeActivePlayer(PlayerInfo pi) { public void shutdown() { saveTask.cancel(); flushCache(); + notificationManager.shutdown(); } public long flushCache() { @@ -180,4 +184,8 @@ public int getSize() { String[] list = plugin.directoryPlayers.list(); return list != null ? list.length : 0; } + + public @NotNull NotificationManager getNotificationManager() { + return notificationManager; + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index fad54c346..c3f8f3763 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -9,7 +9,6 @@ import dk.lockfuglsang.minecraft.util.TimeUtil; import dk.lockfuglsang.minecraft.util.VersionUtil; import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Biome; @@ -79,6 +78,7 @@ import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.IslandPerk; +import us.talabrek.ultimateskyblock.player.NotificationManager; import us.talabrek.ultimateskyblock.player.PerkLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.player.PlayerLogic; diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index 7604a3077..3b5a00a11 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -27,12 +27,12 @@ public class FAWEAdaptor implements AWEAdaptor { private uSkyBlock plugin; @Override - public void onEnable(Plugin plugin) { - this.plugin = (uSkyBlock) plugin; + public void onEnable(uSkyBlock plugin) { + this.plugin = plugin; } @Override - public void onDisable(Plugin plugin) { + public void onDisable(uSkyBlock plugin) { this.plugin = null; } From ee129e146b4cc8f0d3d7dd389cbdfb3e6478f01f Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 5 Aug 2021 17:32:57 +0100 Subject: [PATCH 080/190] Update LevelConfig (#21) * LevelConfig version to 101 * ANVIL/0-2 * DIRT/0-2 * Colored wools * Chipped and Damage anvil as additionBlocks for ANVIL * LOGS, LEAVES * Pressure plates * (GLAZED_)TERRACOTTA * More WOOD items to separate wood types * (RED)SAND(STONE) * SKULL0/4 * double_step (2) doesn't exist anymore, doubles are regular with different blockstate * SPONGE/1 -> WET_SPONGE * STONE/0-8 * STEP/0-8 * PRISMARINE/0-2 and slabs * gold/iron/stone plate * SIGN_POST, WALL_SIGN * Stationairy lava/water is meta for regular lava/water now * STAINED_GLASS into separate colors * STAINED_GLASS_PANE * BED_BLOCK * STANDING_BANNER, WALL_BANNER, separate colors * REDSTONE_LAMP ON/OFF * New air, command blocks * Shulker box, carpet, concrete, concrete powder * Remove old LOGS * (Polished) Andesite/Diorite/Granite slab/stairs/wall * Small corrections * Add new flowers with dim.returns=100 * Additional ocean monument blocks * Missing stone variants * Add new 1.14 villager workstations * Infested stones * (New) nether blocks and stuff * Cleanup * Incorporate marcbal's suggestions * 1.17: Azalea * Add a test for deprecated/invalid Materials in levelConfig * 1.17 namechanges * Add regular test resources too... * Add 1.17 blocks --- uSkyBlock-Core/pom.xml | 15 + .../src/main/resources/levelConfig.yml | 1353 ++++++++++++++--- .../island/level/LevelConfigFileTest.java | 28 + 3 files changed, 1178 insertions(+), 218 deletions(-) create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/LevelConfigFileTest.java diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index e7f253489..e06b3a5f2 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -215,6 +215,21 @@ + + + . + src/test/resources + false + + + imported + src/main/resources + true + + levelConfig.yml + + + diff --git a/uSkyBlock-Core/src/main/resources/levelConfig.yml b/uSkyBlock-Core/src/main/resources/levelConfig.yml index 69f56ef16..ef24b430f 100644 --- a/uSkyBlock-Core/src/main/resources/levelConfig.yml +++ b/uSkyBlock-Core/src/main/resources/levelConfig.yml @@ -26,25 +26,77 @@ blocks: diminishingReturns: 100 ACACIA_STAIRS: score: 15.0 + ACACIA_TRAPDOOR: + score: 30.0 + ACACIA_WOOD: + additionalBlocks: + - STRIPPED_ACACIA_WOOD + diminishingReturns: 10000 ACTIVATOR_RAIL: score: 20.0 AIR: + additionalBlocks: + - CAVE_AIR + - VOID_AIR score: 0.0 limit: 0 - ANVIL/0-2: + ALLIUM: + diminishingReturns: 100 + AMETHYST_BLOCK: + score: 50.0 + ANCIENT_DEBRIS: + score: 500.0 + ANDESITE: + score: 12.5 + diminishingReturns: 10000 + ANDESITE_SLAB: + score: 6.5 + diminishingReturns: 10000 + ANDESITE_STAIRS: + score: 15.0 + diminishingReturns: 5000 + ANDESITE_WALL: + score: 12.5 + diminishingReturns: 5000 + ANVIL: + additionalBlocks: + - CHIPPED_ANVIL + - DAMAGED_ANVIL score: 150.0 limit: 5 + AZALEA: + diminishingReturns: 100 + AZURE_BLUET: + diminishingReturns: 100 + BAMBOO: + additionalBlocks: + - BAMBOO_SAPLING + limit: 1000 + BARREL: + score: 12.5 BARRIER: score: 0.0 + BASALT: + limit: 10000 BEACON: score: 2000.0 limit: 10 negativeReturns: 15 BEDROCK: score: 0.0 - BED_BLOCK: - score: 1000.0 - limit: 1 + BEEHIVE: + additionalBlocks: + - BEE_NEST + score: 30.0 + limit: 200 + BEETROOTS: + score: 0.0 + BELL: + score: 50.0 + BIG_DRIPLEAF: + additionalBlocks: + - SMALL_DRIPLEAF + diminishingReturns: 100 BIRCH_DOOR: score: 20.0 BIRCH_FENCE: @@ -53,52 +105,238 @@ blocks: BIRCH_FENCE_GATE: score: 40.0 diminishingReturns: 100 - BIRCH_WOOD_STAIRS: + BIRCH_STAIRS: + score: 15.0 + BIRCH_TRAPDOOR: + score: 30.0 + BIRCH_WOOD: + additionalBlocks: + - STRIPPED_BIRCH_WOOD + diminishingReturns: 10000 + BLACKSTONE: + limit: 10000 + BLACKSTONE_SLAB: + score: 5.0 + diminishingReturns: 10000 + BLACKSTONE_STAIRS: score: 15.0 + diminishingReturns: 5000 + BLACKSTONE_WALL: + diminishingReturns: 5000 + BLAST_FURNACE: + score: 50.0 + limit: 250 + BLUE_ICE: + score: 50.0 + BLUE_ORCHID: + diminishingReturns: 100 BOOKSHELF: score: 50.0 BREWING_STAND: score: 30.0 limit: 10 - BRICK: - score: 50.0 + BRICK_SLAB: + score: 25.0 + diminishingReturns: 10000 BRICK_STAIRS: score: 75.0 diminishingReturns: 5000 + BRICK_WALL: + score: 50.0 + diminishingReturns: 5000 + BRICKS: + score: 50.0 BROWN_MUSHROOM: diminishingReturns: 100 + BROWN_MUSHROOM_BLOCK: + diminishingReturns: 100 CACTUS: score: 0.0 - CAKE_BLOCK: + CAKE: score: 50.0 - CARPET: + CALCITE: score: 20.0 - diminishingReturns: 5000 - CARROT: + CAMPFIRE: + score: 15.0 + limit: 250 + CARTOGRAPHY_TABLE: + score: 15.0 + limit: 250 + CARROTS: score: 0.0 CAULDRON: + additionalBlocks: + - LAVA_CAULDRON + - WATER_CAULDRON + - POWDER_SNOW_CAULDRON score: 155.0 limit: 10 + CHAIN: + score: 20.0 + limit: 1000 + CHEST: + score: 15.0 + CHISELED_DEEPSLATE: + score: 17.5 + diminishingReturns: 10000 + CHISELED_NETHER_BRICKS: + score: 20.0 + diminishingReturns: 10000 + CHISELED_POLISHED_BLACKSTONE: + score: 12.0 + diminishingReturns: 10000 + CHISELED_RED_SANDSTONE: + score: 25.0 + diminishingReturns: 10000 + CHISELED_SANDSTONE: + score: 80.0 + diminishingReturns: 10000 + CHISELED_STONE_BRICKS: + additionalBlocks: + - INFESTED_CHISELED_STONE_BRICKS + score: 12.0 + diminishingReturns: 10000 CLAY: score: 50.0 COAL_BLOCK: score: 500.0 diminishingReturns: 100 COAL_ORE: + additionalBlocks: + - DEEPSLATE_COAL_ORE score: 200.0 + COBWEB: + score: 20.0 + COARSE_DIRT: + score: 25.0 + diminishingReturns: 10000 + COBBLED_DEEPSLATE: + diminishingReturns: 10000 + COBBLED_DEEPSLATE_SLAB: + score: 5.0 + diminishingReturns: 10000 + COBBLED_DEEPSLATE_STAIRS: + score: 15.0 + diminishingReturns: 5000 + COBBLED_DEEPSLATE_WALL: + diminishingReturns: 5000 COBBLESTONE: + additionalBlocks: + - INFESTED_COBBLESTONE limit: 10000 + COBBLESTONE_SLAB: + score: 5.0 + diminishingReturns: 10000 COBBLESTONE_STAIRS: score: 15.0 diminishingReturns: 5000 - COBBLE_WALL: + COBBLESTONE_WALL: diminishingReturns: 5000 COCOA: score: 0.0 - COMMAND: + COMMAND_BLOCK: + additionalBlocks: + - CHAIN_COMMAND_BLOCK + - REPEATING_COMMAND_BLOCK + - STRUCTURE_BLOCK + - STRUCTURE_VOID + score: 0.0 + COMPARATOR: + score: 15.0 + COMPOSTER: + limit: 250 + CONDUIT: + score: 2000.0 + limit: 10 + negativeReturns: 15 + COPPER_BLOCK: + additionalBlocks: + - EXPOSED_COPPER + - WEATHERED_COPPER + - OXIDIZED_COPPER + score: 300.0 + COPPER_ORE: + additionalBlocks: + - DEEPSLATE_COPPER_ORE + score: 200.0 + CORNFLOWER: + diminishingReturns: 100 + CRACKED_DEEPSLATE_BRICKS: + score: 17.5 + diminishingReturns: 10000 + CRACKED_DEEPSLATE_TILES: + score: 17.5 + diminishingReturns: 10000 + CRACKED_NETHER_BRICKS: + score: 22.5 + diminishingReturns: 10000 + CRACKED_POLISHED_BLACKSTONE_BRICKS: + score: 12.0 + diminishingReturns: 10000 + CRACKED_STONE_BRICKS: + additionalBlocks: + - INFESTED_CRACKED_STONE_BRICKS + score: 15.0 + diminishingReturns: 10000 + CRIMSON_DOOR: + score: 20.0 + CRIMSON_FENCE: + score: 17.5 + diminishingReturns: 5000 + CRIMSON_FENCE_GATE: + score: 40.0 + diminishingReturns: 100 + CRIMSON_FUNGUS: score: 0.0 - CROPS: + CRIMSON_HYPHAE: + additionalBlocks: + - STRIPPED_CRIMSON_HYPHAE + diminishingReturns: 10000 + CRIMSON_NYLIUM: + score: 15.0 + diminishingReturns: 10000 + CRIMSON_ROOTS: score: 0.0 + CRIMSON_STAIRS: + score: 15.0 + CRIMSON_STEM: + additionalBlocks: + - STRIPPED_CRIMSON_STEM + diminishingReturns: 100 + CRIMSON_TRAPDOOR: + score: 30.0 + CRYING_OBSIDIAN: + score: 100.0 + CUT_COPPER: + additionalBlocks: + - EXPOSED_CUT_COPPER + - WEATHERED_CUT_COPPER + - OXIDIZED_CUT_COPPER + score: 300.0 + CUT_COPPER_SLAB: + additionalBlocks: + - EXPOSED_CUT_COPPER_SLAB + - WEATHERED_CUT_COPPER_SLAB + - OXIDIZED_CUT_COPPER_SLAB + score: 150.0 + CUT_COPPER_STAIRS: + additionalBlocks: + - EXPOSED_CUT_COPPER_STAIRS + - WEATHERED_CUT_COPPER_STAIRS + - OXIDIZED_CUT_COPPER_STAIRS + score: 175.0 + CUT_RED_SANDSTONE: + score: 25.0 + CUT_RED_SANDSTONE_SLAB: + score: 12.5 + diminishingReturns: 10000 + CUT_SANDSTONE: + score: 80.0 + CUT_SANDSTONE_SLAB: + score: 40.0 + diminishingReturns: 10000 + DANDELION: + diminishingReturns: 100 DARK_OAK_DOOR: score: 20.0 DARK_OAK_FENCE: @@ -109,118 +347,183 @@ blocks: diminishingReturns: 100 DARK_OAK_STAIRS: score: 15.0 - DAYLIGHT_DETECTOR: - score: 200.0 - DAYLIGHT_DETECTOR_INVERTED: - score: 200.0 - DETECTOR_RAIL: - score: 20.0 - DIAMOND_BLOCK: - score: 5000.0 - DIAMOND_ORE: - score: 400.0 - DIRT: - score: 20.0 + DARK_OAK_TRAPDOOR: + score: 30.0 + DARK_OAK_WOOD: + additionalBlocks: + - STRIPPED_DARK_OAK_WOOD diminishingReturns: 10000 - DIRT/1: - score: 25.0 + DARK_PRISMARINE: + score: 50.0 diminishingReturns: 10000 - DIRT/2: + DARK_PRISMARINE_SLAB: score: 25.0 diminishingReturns: 10000 - DOUBLE_STEP/0: + DARK_PRISMARINE_STAIRS: + score: 75.0 + diminishingReturns: 5000 + DAYLIGHT_DETECTOR: + score: 200.0 + DEEPSLATE: + additionalBlocks: + - INFESTED_DEEPSLATE + score: 15.0 + diminishingReturns: 10000 + DEEPSLATE_BRICK_SLAB: + score: 8.5 diminishingReturns: 10000 - DOUBLE_STEP/1: + DEEPSLATE_BRICK_STAIRS: score: 20.0 + diminishingReturns: 5000 + DEEPSLATE_BRICK_WALL: + score: 17.5 + diminishingReturns: 5000 + DEEPSLATE_BRICKS: + score: 17.5 diminishingReturns: 10000 - DOUBLE_STEP/2: + DEEPSLATE_TILE_SLAB: + score: 8.5 diminishingReturns: 10000 - DOUBLE_STEP/3: + DEEPSLATE_TILE_STAIRS: + score: 20.0 + diminishingReturns: 5000 + DEEPSLATE_TILE_WALL: + score: 17.5 + diminishingReturns: 5000 + DEEPSLATE_TILES: + score: 17.5 diminishingReturns: 10000 - DOUBLE_STEP/4: - score: 50.0 + DETECTOR_RAIL: + score: 20.0 + DIAMOND_BLOCK: + score: 5000.0 + DIAMOND_ORE: + additionalBlocks: + - DEEPSLATE_DIAMOND_ORE + score: 400.0 + DIORITE: + score: 12.5 diminishingReturns: 10000 - DOUBLE_STEP/5: - score: 15.0 + DIORITE_SLAB: + score: 6.5 diminishingReturns: 10000 - DOUBLE_STEP/6: + DIORITE_STAIRS: + score: 15.0 + diminishingReturns: 5000 + DIORITE_WALL: + score: 12.5 + diminishingReturns: 5000 + DIRT: + additionalBlocks: + - FARMLAND + - ROOTED_DIRT score: 20.0 diminishingReturns: 10000 - DOUBLE_STEP/7: - score: 100.0 - diminishingReturns: 10000 - DOUBLE_STONE_SLAB2: + DIRT_PATH: score: 20.0 - diminishingReturns: 20000 + diminishingReturns: 5000 DRAGON_EGG: score: 5000.0 limit: 2 + DRIED_KELP_BLOCK: + score: 20.0 + DRIPSTONE_BLOCK: + score: 15.0 EMERALD_BLOCK: score: 1000.0 EMERALD_ORE: + additionalBlocks: + - DEEPSLATE_EMERALD_ORE score: 200.0 - ENCHANTMENT_TABLE: + ENCHANTING_TABLE: score: 150.0 - ENDER_CHEST: - score: 2000.0 - limit: 3 - ENDER_PORTAL: - score: 0.0 - ENDER_PORTAL_FRAME: + END_PORTAL: + additionalBlock: + - END_PORTAL_FRAME score: 0.0 - ENDER_STONE: + END_STONE: score: 15.0 limit: 10000 - FENCE: - score: 17.5 + END_STONE_BRICK_SLAB: + score: 7.5 + diminishingReturns: 10000 + END_STONE_BRICK_STAIRS: + score: 20.0 diminishingReturns: 5000 - FENCE_GATE: - score: 40.0 + END_STONE_BRICK_WALL: + score: 15.0 + diminishingReturns: 5000 + END_STONE_BRICKS: + score: 15.0 + limit: 10000 + ENDER_CHEST: + score: 2000.0 + limit: 3 + FERN: diminishingReturns: 100 FIRE: score: 0.0 + FLETCHING_TABLE: + score: 15.0 + limit: 250 + FROSTED_ICE: + score: 0.0 + GILDED_BLACKSTONE: + score: 50.0 GLASS: score: 50.0 + GLASS_PANE: + score: 10.0 GLOWSTONE: score: 20.0 + GLOW_LICHEN: + diminishingReturns: 100 GOLD_BLOCK: score: 1500.0 diminishingReturns: 100 GOLD_ORE: + additionalBlocks: + - DEEPSLATE_GOLD_ORE score: 500.0 - GOLD_PLATE: - score: 115.0 - GRASS: + GRANITE: + score: 12.5 + diminishingReturns: 10000 + GRANITE_SLAB: + score: 6.5 + diminishingReturns: 10000 + GRANITE_STAIRS: + score: 15.0 + diminishingReturns: 5000 + GRANITE_WALL: + score: 12.5 + diminishingReturns: 5000 + GRASS_BLOCK: score: 20.0 diminishingReturns: 10000 GRAVEL: score: 20.0 - HARD_CLAY: - score: 20.0 + GRINDSTONE: + limit: 250 HAY_BLOCK: score: 20.0 + HEAVY_WEIGHTED_PRESSURE_PLATE: + score: 50.0 HOPPER: score: 125.0 limit: 10 negativeReturns: 5 - HUGE_MUSHROOM_1: - score: 100.0 - diminishingReturns: 30 - HUGE_MUSHROOM_2: - score: 100.0 - diminishingReturns: 30 ICE: score: 50.0 + IRON_BARS: + score: 12.5 IRON_BLOCK: score: 300.0 - IRON_DOOR_BLOCK: + IRON_DOOR: score: 200.0 - IRON_FENCE: - score: 12.5 IRON_ORE: + additionalBlocks: + - DEEPSLATE_IRON_ORE score: 200.0 - IRON_PLATE: - score: 50.0 IRON_TRAPDOOR: score: 20.0 diminishingReturns: 10 @@ -236,150 +539,521 @@ blocks: JUNGLE_FENCE_GATE: score: 40.0 diminishingReturns: 100 - JUNGLE_WOOD_STAIRS: + JUNGLE_STAIRS: score: 15.0 + JUNGLE_TRAPDOOR: + score: 30.0 + JUNGLE_WOOD: + additionalBlocks: + - STRIPPED_JUNGLE_WOOD + diminishingReturns: 10000 + KELP: + additionalBlocks: + - KELP_PLANT + score: 0.0 LADDER: score: 0.0 + LANTERN: + score: 25.0 LAPIS_BLOCK: score: 500.0 LAPIS_ORE: + additionalBlocks: + - DEEPSLATE_LAPIS_ORE score: 300.0 LAVA: score: 0.0 - LEAVES/0-3: - score: 0.0 - LEAVES_2/0-1: - score: 0.0 - LOG/0-5: - additionalBlocks: - - LOG_2 - diminishingReturns: 100 - LOG_2: - diminishingReturns: 100 - LOG_2/1: + LECTERN: + score: 55.0 + limit: 250 + LEVER: + score: 5.0 + limit: 250 + LIGHT_WEIGHTED_PRESSURE_PLATE: + score: 115.0 + LILAC: diminishingReturns: 100 - LONG_GRASS: + LILY_OF_THE_VALLEY: diminishingReturns: 100 - MELON_BLOCK: + LODESTONE: + score: 500.0 + limit: 5 + LOOM: + limit: 250 + MAGMA_BLOCK: + score: 15.0 + MELON: score: 0.0 MELON_STEM: + additionalBlocks: + - ATTACHED_MELON_STEM score: 0.0 - MOSSY_COBBLESTONE: - score: 30.0 - MYCEL: + MOSS_BLOCK: score: 20.0 diminishingReturns: 10000 - NETHERRACK: - limit: 10000 - NETHER_BRICK_SLAB: - score: 10.0 - diminishingReturns: 20000 - NETHER_BRICK_FENCE: + MOSS_CARPET: + score: 15.0 + diminishingReturns: 5000 + MOSSY_COBBLESTONE: score: 30.0 + MOSSY_COBBLESTONE_SLAB: + score: 15.0 diminishingReturns: 10000 - NETHER_BRICKS: + MOSSY_COBBLESTONE_STAIRS: score: 20.0 - diminishingReturns: 20000 - NETHER_BRICK_STAIRS: + diminishingReturns: 5000 + MOSSY_COBBLESTONE_WALL: score: 30.0 diminishingReturns: 5000 - NETHER_FENCE: - score: 60.0 + MOSSY_STONE_BRICK_SLAB: + score: 16.0 + diminishingReturns: 10000 + MOSSY_STONE_BRICK_STAIRS: + score: 21.0 diminishingReturns: 5000 - NOTE_BLOCK: + MOSSY_STONE_BRICK_WALL: + score: 32.0 + diminishingReturns: 5000 + MOSSY_STONE_BRICKS: + additionalBlocks: + - INFESTED_MOSSY_STONE_BRICKS + score: 32.0 + MUSHROOM_STEM: + diminishingReturns: 100 + MYCELIUM: score: 20.0 - OBSIDIAN: + diminishingReturns: 10000 + NETHER_BRICK_FENCE: + score: 30.0 + diminishingReturns: 10000 + NETHER_BRICK_SLAB: + score: 10.0 + diminishingReturns: 20000 + NETHER_BRICK_STAIRS: + score: 30.0 + diminishingReturns: 5000 + NETHER_BRICK_WALL: + score: 20.0 + diminishingReturns: 5000 + NETHER_BRICKS: + score: 20.0 + diminishingReturns: 20000 + NETHER_GOLD_ORE: + score: 500.0 + NETHER_PORTAL: + score: 0.0 + NETHER_QUARTZ_ORE: + score: 50.0 + NETHER_WART: + score: 0.0 + NETHERITE_BLOCK: + score: 5000.0 + NETHERRACK: + limit: 10000 + NOTE_BLOCK: + score: 20.0 + OAK_DOOR: + score: 20.0 + OAK_FENCE: + score: 17.5 + diminishingReturns: 5000 + OAK_FENCE_GATE: + score: 40.0 + diminishingReturns: 100 + OAK_LEAVES: + additionalBlocks: + - ACACIA_LEAVES + - BIRCH_LEAVES + - DARK_OAK_LEAVES + - JUNGLE_LEAVES + - SPRUCE_LEAVES + - AZALEA_LEAVES + - FLOWERING_AZALEA_LEAVES + score: 0.0 + OAK_LOG: + additionalBlocks: + - ACACIA_LOG + - BIRCH_LOG + - DARK_OAK_LOG + - JUNGLE_LOG + - SPRUCE_LOG + diminishingReturns: 100 + OAK_PRESSURE_PLATE: + additionalBlocks: + - ACACIA_PRESSURE_PLATE + - BIRCH_PRESSURE_PLATE + - CRIMSON_PRESSURE_PLATE + - DARK_OAK_PRESSURE_PLATE + - JUNGLE_PRESSURE_PLATE + - SPRUCE_PRESSURE_PLATE + - WARPED_PRESSURE_PLATE + score: 0.0 + OAK_SAPLING: + additionalBlocks: + - ACACIA_SAPLING + - BIRCH_SAPLING + - DARK_OAK_SAPLING + - JUNGLE_SAPLING + - SPRUCE_SAPLING + - AZALEA + score: 0.0 + OAK_SIGN: + additionalBlocks: + - ACACIA_SIGN + - ACACIA_WALL_SIGN + - BIRCH_SIGN + - BIRCH_WALL_SIGN + - CRIMSON_SIGN + - CRIMSON_WALL_SIGN + - DARK_OAK_SIGN + - DARK_OAK_WALL_SIGN + - JUNGLE_SIGN + - JUNGLE_WALL_SIGN + - OAK_WALL_SIGN + - SPRUCE_SIGN + - SPRUCE_WALL_SIGN + - WARPED_SIGN + - WARPED_WALL_SIGN + score: 0.0 + OAK_SLAB: + additionalBlocks: + - ACACIA_SLAB + - BIRCH_SLAB + - CRIMSON_SLAB + - DARK_OAK_SLAB + - JUNGLE_SLAB + - SPRUCE_SLAB + - WARPED_SLAB + score: 5.0 + diminishingReturns: 15000 + OAK_STAIRS: + score: 15.0 + OAK_TRAPDOOR: + score: 30.0 + OAK_WOOD: + additionalBlocks: + - STRIPPED_OAK_WOOD + diminishingReturns: 10000 + OBSERVER: + score: 15.0 + OBSIDIAN: score: 200.0 diminishingReturns: 50 + ORANGE_TULIP: + diminishingReturns: 100 + OXEYE_DAISY: + diminishingReturns: 100 PACKED_ICE: score: 15.0 - PISTON_BASE: + PEONY: + diminishingReturns: 100 + PINK_TULIP: + diminishingReturns: 100 + PISTON: score: 40.0 - PISTON_EXTENSION: + PISTON_HEAD: + additionalBlocks: + - MOVING_PISTON score: 0.0 - PISTON_MOVING_PIECE: + PODZOL: + score: 25.0 + diminishingReturns: 10000 + POLISHED_ANDESITE: + score: 15.0 + diminishingReturns: 10000 + POLISHED_ANDESITE_SLAB: + score: 7.5 + diminishingReturns: 10000 + POLISHED_ANDESITE_STAIRS: + score: 17.5 + diminishingReturns: 5000 + POLISHED_BASALT: + score: 12.0 + diminishingReturns: 20000 + POLISHED_BLACKSTONE: + score: 12.0 + diminishingReturns: 20000 + POLISHED_BLACKSTONE_BRICK_SLAB: + score: 6.0 + diminishingReturns: 10000 + POLISHED_BLACKSTONE_BRICK_STAIRS: + score: 18.0 + diminishingReturns: 5000 + POLISHED_BLACKSTONE_BRICK_WALL: + score: 12.0 + diminishingReturns: 5000 + POLISHED_BLACKSTONE_BRICKS: + score: 12.0 + diminishingReturns: 20000 + POLISHED_BLACKSTONE_BUTTON: score: 0.0 - PISTON_STICKY_BASE: - score: 60.0 - PORTAL: + POLISHED_BLACKSTONE_PRESSURE_PLATE: score: 0.0 - POTATO: + POLISHED_BLACKSTONE_SLAB: + score: 6.0 + diminishingReturns: 10000 + POLISHED_BLACKSTONE_STAIRS: + score: 18.0 + diminishingReturns: 5000 + POLISHED_BLACKSTONE_WALL: + score: 12.0 + diminishingReturns: 5000 + POLISHED_DEEPSLATE: + score: 17.5 + diminishingReturns: 10000 + POLISHED_DEEPSLATE_SLAB: + score: 8.5 + diminishingReturns: 10000 + POLISHED_DEEPSLATE_STAIRS: + score: 20.0 + diminishingReturns: 5000 + POLISHED_DEEPSLATE_WALL: + score: 17.5 + diminishingReturns: 5000 + POLISHED_DIORITE: + score: 15.0 + diminishingReturns: 10000 + POLISHED_DIORITE_SLAB: + score: 7.5 + diminishingReturns: 10000 + POLISHED_DIORITE_STAIRS: + score: 17.5 + diminishingReturns: 5000 + POLISHED_GRANITE: + score: 15.0 + diminishingReturns: 10000 + POLISHED_GRANITE_SLAB: + score: 7.5 + diminishingReturns: 10000 + POLISHED_GRANITE_STAIRS: + score: 17.5 + diminishingReturns: 5000 + POPPY: + diminishingReturns: 100 + POTATOES: score: 0.0 POWERED_RAIL: score: 20.0 PRISMARINE: score: 50.0 - PRISMARINE/1: + diminishingReturns: 10000 + PRISMARINE_BRICK_SLAB: + score: 25.0 + diminishingReturns: 10000 + PRISMARINE_BRICK_STAIRS: + score: 75.0 + diminishingReturns: 5000 + PRISMARINE_BRICKS: score: 50.0 - PRISMARINE/2: + diminishingReturns: 10000 + PRISMARINE_SLAB: + score: 25.0 + diminishingReturns: 10000 + PRISMARINE_STAIRS: + score: 75.0 + diminishingReturns: 5000 + PRISMARINE_WALL: score: 50.0 + diminishingReturns: 5000 + PUMPKIN: + score: 0.0 PUMPKIN_STEM: + additionalBlocks: + - ATTACHED_PUMPKIN_STEM score: 0.0 - QUARTZ_BLOCK/0-2: + PURPUR_BLOCK: + score: 15.0 + diminishingReturns: 10000 + PURPUR_PILLAR: + score: 15.0 + diminishingReturns: 5000 + PURPUR_SLAB: + score: 7.5 + diminishingReturns: 10000 + PURPUR_STAIRS: + score: 22.5 + diminishingReturns: 5000 + QUARTZ_BLOCK: + additionalBlocks: + - CHISELED_QUARTZ_BLOCK + - QUARTZ_BRICKS + - QUARTZ_PILLAR score: 100.0 diminishingReturns: 5000 - QUARTZ_ORE: + QUARTZ_SLAB: score: 50.0 + diminishingReturns: 10000 QUARTZ_STAIRS: score: 150.0 diminishingReturns: 5000 - REDSTONE_BLOCK: - score: 150.0 - REDSTONE_LAMP_OFF: - score: 20.0 - REDSTONE_LAMP_ON: - score: 20.0 - REDSTONE_WIRE: - score: 0.0 + RAW_COPPER_BLOCK: + score: 250.0 + RAW_GOLD_BLOCK: + score: 750.0 + RAW_IRON_BLOCK: + score: 250.0 RED_MUSHROOM: diminishingReturns: 100 - RED_ROSE: + RED_MUSHROOM_BLOCK: diminishingReturns: 100 - RED_SANDSTONE/0-2: - score: 25.0 - RED_SANDSTONE_STAIRS: + RED_NETHER_BRICK_SLAB: + score: 10.0 + diminishingReturns: 10000 + RED_NETHER_BRICK_STAIRS: + score: 30.0 + diminishingReturns: 5000 + RED_NETHER_BRICK_WALL: score: 20.0 - SAND/0: + diminishingReturns: 5000 + RED_NETHER_BRICKS: score: 20.0 diminishingReturns: 10000 - SAND/1: + RED_SAND: score: 22.5 diminishingReturns: 10000 - SANDSTONE/0-2: + RED_SANDSTONE: + score: 25.0 + RED_SANDSTONE_SLAB: + score: 12.5 + diminishingReturns: 10000 + RED_SANDSTONE_STAIRS: + score: 20.0 + diminishingReturns: 5000 + RED_SANDSTONE_WALL: + score: 25.0 + diminishingReturns: 5000 + RED_TULIP: + diminishingReturns: 100 + REDSTONE_BLOCK: + score: 150.0 + REDSTONE_LAMP: + score: 20.0 + REDSTONE_ORE: + additionalBlocks: + - DEEPSLATE_REDSTONE_ORE + score: 25.0 + REDSTONE_WIRE: + score: 0.0 + REPEATER: + score: 15.0 + RESPAWN_ANCHOR: + score: 300.0 + limit: 1 + ROSE_BUSH: + diminishingReturns: 100 + SAND: + score: 20.0 + diminishingReturns: 10000 + SANDSTONE: score: 80.0 + SANDSTONE_SLAB: + score: 40.0 + diminishingReturns: 10000 SANDSTONE_STAIRS: score: 120.0 diminishingReturns: 5000 - SAPLING: - score: 0.0 + SANDSTONE_WALL: + score: 80.0 + diminishingReturns: 5000 SEA_LANTERN: score: 50.0 - SIGN_POST: - score: 0.0 - SKULL/0-4: + SEA_PICKLE: + limit: 100 + SHULKER_BOX: + additionalBlocks: + - BLACK_SHULKER_BOX + - BLUE_SHULKER_BOX + - BROWN_SHULKER_BOX + - CYAN_SHULKER_BOX + - GRAY_SHULKER_BOX + - GREEN_SHULKER_BOX + - LIGHT_BLUE_SHULKER_BOX + - LIGHT_GRAY_SHULKER_BOX + - LIME_SHULKER_BOX + - MAGENTA_SHULKER_BOX + - ORANGE_SHULKER_BOX + - PINK_SHULKER_BOX + - PURPLE_SHULKER_BOX + - RED_SHULKER_BOX + - WHITE_SHULKER_BOX + - YELLOW_SHULKER_BOX + score: 500.0 + SHROOMLIGHT: + score: 20.0 + SKELETON_SKULL: + additionalBlocks: + - CREEPER_HEAD + - CREEPER_WALL_HEAD + - DRAGON_HEAD + - DRAGON_WALL_HEAD + - PLAYER_HEAD + - PLAYER_WALL_HEAD + - SKELETON_WALL_SKULL + - ZOMBIE_HEAD + - ZOMBIE_WALL_HEAD score: 1000.0 + diminishingReturns: 10 SLIME_BLOCK: - score: 250.0 + score: 50.0 diminishingReturns: 100 - SMOOTH_BRICK: - score: 12.0 - diminishingReturns: 20000 - SMOOTH_STAIRS: + SMITHING_TABLE: score: 20.0 + limit: 250 + SMOKER: + score: 15.0 + limit: 250 + SMOOTH_BASALT: + score: 12.5 + limit: 10000 + SMOOTH_QUARTZ: + score: 100.0 + diminishingReturns: 5000 + SMOOTH_QUARTZ_SLAB: + score: 50.0 + diminishingReturns: 10000 + SMOOTH_QUARTZ_STAIRS: + score: 150.0 + diminishingReturns: 5000 + SMOOTH_RED_SANDSTONE: + score: 25.0 + SMOOTH_RED_SANDSTONE_SLAB: + score: 12.5 + diminishingReturns: 10000 + SMOOTH_RED_SANDSTONE_STAIRS: + score: 37.5 diminishingReturns: 5000 + SMOOTH_SANDSTONE: + score: 80.0 + SMOOTH_SANDSTONE_SLAB: + score: 40.0 + diminishingReturns: 10000 + SMOOTH_SANDSTONE_STAIRS: + score: 120.0 + diminishingReturns: 5000 + SMOOTH_STONE: + score: 12.0 + SMOOTH_STONE_SLAB: + score: 6.0 + diminishingReturns: 10000 SNOW: score: 0.0 SNOW_BLOCK: score: 50.0 - SOIL: - score: 40.0 + SOUL_CAMPFIRE: + score: 15.0 + SOUL_FIRE: + score: 0.0 + SOUL_LANTERN: + score: 25.0 SOUL_SAND: limit: 10000 + SOUL_SOIL: + limit: 10000 SPONGE: score: 50.0 limit: 20 - SPONGE/1: - score: 50.0 + SPORE_BLOSSOM: + diminishingReturns: 100 SPRUCE_DOOR: score: 20.0 SPRUCE_FENCE: @@ -388,103 +1062,346 @@ blocks: SPRUCE_FENCE_GATE: score: 40.0 diminishingReturns: 100 - SPRUCE_WOOD_STAIRS: + SPRUCE_STAIRS: score: 15.0 - STAINED_CLAY: - score: 50.0 - STAINED_GLASS: - score: 25.0 - STANDING_BANNER: - score: 20.0 - diminishingReturns: 20 - STATIONARY_LAVA: - score: 0.0 - STATIONARY_WATER: - score: 0.0 - STEP/0: - score: 5.0 + SPRUCE_TRAPDOOR: + score: 30.0 + SPRUCE_WOOD: + additionalBlocks: + - STRIPPED_SPRUCE_WOOD diminishingReturns: 10000 - STEP/1: - score: 40.0 + STICKY_PISTON: + score: 60.0 + STONE: + additionalBlocks: + - INFESTED_STONE diminishingReturns: 10000 - STEP/2: - score: 5.0 + STONE_BRICK_SLAB: + score: 6.0 diminishingReturns: 10000 - STEP/3: + STONE_BRICK_STAIRS: + score: 18.0 + diminishingReturns: 5000 + STONE_BRICK_WALL: + score: 12.0 + diminishingReturns: 5000 + STONE_BRICKS: + additionalBlocks: + - INFESTED_STONE_BRICKS + score: 12.0 + diminishingReturns: 20000 + STONE_PRESSURE_PLATE: + score: 0.0 + STONE_SLAB: score: 5.0 diminishingReturns: 10000 - STEP/4: - score: 25.0 - diminishingReturns: 10000 - STEP/5: - score: 7.0 - diminishingReturns: 10000 - STEP/6: - score: 20.0 - diminishingReturns: 10000 - STEP/7: - score: 50.0 - diminishingReturns: 10000 - STONE/0: - diminishingReturns: 10000 - STONE/1: - score: 12.5 - diminishingReturns: 10000 - STONE/2: - score: 15.0 - diminishingReturns: 10000 - STONE/3: - score: 12.5 - diminishingReturns: 10000 - STONE/4: - score: 15.0 - diminishingReturns: 10000 - STONE/5: - score: 12.5 - diminishingReturns: 10000 - STONE/6: + STONECUTTER: score: 15.0 - diminishingReturns: 10000 - STONE_PLATE: - score: 0.0 - STONE_SLAB2: - score: 12.5 - diminishingReturns: 20000 - SUGAR_CANE_BLOCK: + limit: 250 + SUGAR_CANE: score: 0.0 + SUNFLOWER: + diminishingReturns: 100 + SWEET_BERRY_BUSH: + diminishingReturns: 100 + TERRACOTTA: + additionalBlocks: + - BLACK_TERRACOTTA + - BLUE_TERRACOTTA + - BROWN_TERRACOTTA + - CYAN_TERRACOTTA + - GRAY_TERRACOTTA + - GREEN_TERRACOTTA + - LIGHT_BLUE_TERRACOTTA + - LIGHT_GRAY_TERRACOTTA + - LIME_TERRACOTTA + - MAGENTA_TERRACOTTA + - ORANGE_TERRACOTTA + - PINK_TERRACOTTA + - PURPLE_TERRACOTTA + - RED_TERRACOTTA + - WHITE_TERRACOTTA + - YELLOW_TERRACOTTA + score: 20.0 + TINTED_GLASS: + score: 75.0 TNT: score: 80.0 TRAPPED_CHEST: score: 20.0 - TRAP_DOOR: - score: 30.0 + TRIPWIRE: + score: 0.0 + TRIPWIRE_HOOK: + score: 15.0 + limit: 250 + TUFF: + score: 15.0 + diminishingReturns: 10000 + TWISTING_VINES: + additionalBlocks: + - TWISTING_VINES_PLANT + limit: 25 VINE: + additionalBlocks: + - CAVE_VINES + - CAVE_VINES_PLANT limit: 25 - WALL_BANNER: + WARPED_DOOR: score: 20.0 - diminishingReturns: 20 - WALL_SIGN: - score: 0.0 - WATER: + WARPED_FENCE: + score: 17.5 + diminishingReturns: 5000 + WARPED_FENCE_GATE: + score: 40.0 + diminishingReturns: 100 + WARPED_FUNGUS: score: 0.0 - WEB: - score: 20.0 - WOOD: + WARPED_HYPHAE: + additionalBlocks: + - STRIPPED_WARPED_HYPHAE diminishingReturns: 10000 - WOODEN_DOOR: - score: 20.0 - WOOD_DOUBLE_STEP/0-5: + WARPED_NYLIUM: + score: 15.0 diminishingReturns: 10000 - WOOD_PLATE: + WARPED_ROOTS: score: 0.0 - WOOD_STAIRS: + WARPED_STAIRS: score: 15.0 - WOOD_STEP/0-5: - score: 5.0 - diminishingReturns: 10000 - WOOL: + WARPED_STEM: + additionalBlocks: + - STRIPPED_WARPED_STEM + diminishingReturns: 100 + WARPED_TRAPDOOR: + score: 30.0 + WATER: + additionalBlocks: + - BUBBLE_COLUMN + score: 0.0 + WAXED_COPPER_BLOCK: + additionalBlocks: + - WAXED_EXPOSED_COPPER + - WAXED_WEATHERED_COPPER + - WAXED_OXIDIZED_COPPER + score: 300.0 + WAXED_CUT_COPPER: + additionalBlocks: + - WAXED_EXPOSED_CUT_COPPER + - WAXED_WEATHERED_CUT_COPPER + - WAXED_OXIDIZED_CUT_COPPER + score: 300.0 + WAXED_CUT_COPPER_STAIRS: + additionalBlocks: + - WAXED_EXPOSED_CUT_COPPER_STAIRS + - WAXED_WEATHERED_CUT_COPPER_STAIRS + - WAXED_OXIDIZED_CUT_COPPER_STAIRS + score: 175.0 + WAXED_CUT_COPPER_SLAB: + additionalBlocks: + - WAXED_EXPOSED_CUT_COPPER_SLAB + - WAXED_WEATHERED_CUT_COPPER_SLAB + - WAXED_OXIDIZED_CUT_COPPER_SLAB + score: 150.0 + WEEPING_VINES: + additionalBlocks: + - WEEPING_VINES_PLANT + limit: 25 + WET_SPONGE: + score: 50.0 + limit: 20 + WHEAT: + score: 0.0 + WHITE_BANNER: + additionalBlocks: + - BLACK_BANNER + - BLUE_BANNER + - BROWN_BANNER + - CYAN_BANNER + - GRAY_BANNER + - GREEN_BANNER + - LIGHT_BLUE_BANNER + - LIGHT_GRAY_BANNER + - LIME_BANNER + - MAGENTA_BANNER + - ORANGE_BANNER + - PINK_BANNER + - PURPLE_BANNER + - RED_BANNER + - YELLOW_BANNER + score: 20.0 + diminishingReturns: 20 + WHITE_BED: + additionalBlocks: + - BLACK_BED + - BLUE_BED + - BROWN_BED + - CYAN_BED + - GRAY_BED + - GREEN_BED + - LIGHT_BLUE_BED + - LIGHT_GRAY_BED + - LIME_BED + - MAGENTA_BED + - ORANGE_BED + - PINK_BED + - PURPLE_BED + - RED_BED + - YELLOW_BED + score: 1000.0 + limit: 1 + WHITE_CARPET: + additionalBlocks: + - BLACK_CARPET + - BLUE_CARPET + - BROWN_CARPET + - CYAN_CARPET + - GRAY_CARPET + - GREEN_CARPET + - LIGHT_BLUE_CARPET + - LIGHT_GRAY_CARPET + - LIME_CARPET + - MAGENTA_CARPET + - ORANGE_CARPET + - PINK_CARPET + - PURPLE_CARPET + - RED_CARPET + - YELLOW_CARPET + score: 20.0 + diminishingReturns: 5000 + WHITE_CONCRETE: + additionalBlocks: + - BLACK_CONCRETE + - BLUE_CONCRETE + - BROWN_CONCRETE + - CYAN_CONCRETE + - GRAY_CONCRETE + - GREEN_CONCRETE + - LIGHT_BLUE_CONCRETE + - LIGHT_GRAY_CONCRETE + - LIME_CONCRETE + - MAGENTA_CONCRETE + - ORANGE_CONCRETE + - PINK_CONCRETE + - PURPLE_CONCRETE + - RED_CONCRETE + - YELLOW_CONCRETE + score: 50.0 + WHITE_CONCRETE_POWDER: + additionalBlocks: + - BLACK_CONCRETE_POWDER + - BLUE_CONCRETE_POWDER + - BROWN_CONCRETE_POWDER + - CYAN_CONCRETE_POWDER + - GRAY_CONCRETE_POWDER + - GREEN_CONCRETE_POWDER + - LIGHT_BLUE_CONCRETE_POWDER + - LIGHT_GRAY_CONCRETE_POWDER + - LIME_CONCRETE_POWDER + - MAGENTA_CONCRETE_POWDER + - ORANGE_CONCRETE_POWDER + - PINK_CONCRETE_POWDER + - PURPLE_CONCRETE_POWDER + - RED_CONCRETE_POWDER + - YELLOW_CONCRETE_POWDER + score: 40.0 + WHITE_GLAZED_TERRACOTTA: + additionalBlocks: + - BLACK_GLAZED_TERRACOTTA + - BLUE_GLAZED_TERRACOTTA + - BROWN_GLAZED_TERRACOTTA + - CYAN_GLAZED_TERRACOTTA + - GRAY_GLAZED_TERRACOTTA + - GREEN_GLAZED_TERRACOTTA + - LIGHT_BLUE_GLAZED_TERRACOTTA + - LIGHT_GRAY_GLAZED_TERRACOTTA + - LIME_GLAZED_TERRACOTTA + - MAGENTA_GLAZED_TERRACOTTA + - ORANGE_GLAZED_TERRACOTTA + - PINK_GLAZED_TERRACOTTA + - PURPLE_GLAZED_TERRACOTTA + - RED_GLAZED_TERRACOTTA + - YELLOW_GLAZED_TERRACOTTA + score: 20.0 + WHITE_STAINED_GLASS: + additionalBlocks: + - BLACK_STAINED_GLASS + - BLUE_STAINED_GLASS + - BROWN_STAINED_GLASS + - CYAN_STAINED_GLASS + - GRAY_STAINED_GLASS + - GREEN_STAINED_GLASS + - LIGHT_BLUE_STAINED_GLASS + - LIGHT_GRAY_STAINED_GLASS + - LIME_STAINED_GLASS + - MAGENTA_STAINED_GLASS + - ORANGE_STAINED_GLASS + - PINK_STAINED_GLASS + - PURPLE_STAINED_GLASS + - RED_STAINED_GLASS + - YELLOW_STAINED_GLASS + score: 50.0 + WHITE_STAINED_GLASS_PANE: + additionalBlocks: + - BLACK_STAINED_GLASS_PANE + - BLUE_STAINED_GLASS_PANE + - BROWN_STAINED_GLASS_PANE + - CYAN_STAINED_GLASS_PANE + - GRAY_STAINED_GLASS_PANE + - GREEN_STAINED_GLASS_PANE + - LIGHT_BLUE_STAINED_GLASS_PANE + - LIGHT_GRAY_STAINED_GLASS_PANE + - LIME_STAINED_GLASS_PANE + - MAGENTA_STAINED_GLASS_PANE + - ORANGE_STAINED_GLASS_PANE + - PINK_STAINED_GLASS_PANE + - PURPLE_STAINED_GLASS_PANE + - RED_STAINED_GLASS_PANE + - YELLOW_STAINED_GLASS_PANE + score: 20.0 + WHITE_TULIP: + diminishingReturns: 100 + WHITE_WALL_BANNER: + additionalBlocks: + - BLACK_WALL_BANNER + - BLUE_WALL_BANNER + - BROWN_WALL_BANNER + - CYAN_WALL_BANNER + - GRAY_WALL_BANNER + - GREEN_WALL_BANNER + - LIGHT_BLUE_WALL_BANNER + - LIGHT_GRAY_WALL_BANNER + - LIME_WALL_BANNER + - MAGENTA_WALL_BANNER + - ORANGE_WALL_BANNER + - PINK_WALL_BANNER + - PURPLE_WALL_BANNER + - RED_WALL_BANNER + - YELLOW_WALL_BANNER + score: 20.0 + diminishingReturns: 20 + WHITE_WOOL: + additionalBlocks: + - BLACK_WOOL + - BLUE_WOOL + - BROWN_WOOL + - CYAN_WOOL + - GRAY_WOOL + - GREEN_WOOL + - LIGHT_BLUE_WOOL + - LIGHT_GRAY_WOOL + - LIME_WOOL + - MAGENTA_WOOL + - ORANGE_WOOL + - PINK_WOOL + - PURPLE_WOOL + - RED_WOOL + - YELLOW_WOOL score: 50.0 diminishingReturns: 64 - YELLOW_FLOWER: + WITHER_ROSE: diminishingReturns: 100 -version: 100 + WITHER_SKELETON_SKULL: + additionalBlocks: + - WITHER_SKELETON_WALL_SKULL + score: 500.0 + limit: 5 +version: 101 diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/LevelConfigFileTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/LevelConfigFileTest.java new file mode 100644 index 000000000..a048802ff --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/LevelConfigFileTest.java @@ -0,0 +1,28 @@ +package us.talabrek.ultimateskyblock.island.level; + +import org.bukkit.Material; +import org.bukkit.configuration.file.YamlConfiguration; +import org.junit.Test; + +import java.io.InputStream; +import java.io.InputStreamReader; + +import static org.junit.Assert.assertNotNull; + +public class LevelConfigFileTest { + @Test + public void testForInvalidMaterials() { + InputStream levelResource = getClass().getClassLoader().getResourceAsStream("imported/levelConfig.yml"); + YamlConfiguration levelConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(levelResource)); + + for (String key : levelConfig.getConfigurationSection("blocks").getKeys(false)) { + assertNotNull(Material.getMaterial(key)); + + if (levelConfig.getConfigurationSection("blocks").getConfigurationSection(key).contains("additionalBlocks")) { + for (String additionalKey : levelConfig.getConfigurationSection("blocks").getConfigurationSection(key).getStringList("additionalBlocks")) { + assertNotNull(Material.getMaterial(additionalKey)); + } + } + } + } +} From 6926d42c96c57758735b5f73ab254c367a550f59 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 16 Aug 2021 21:08:15 +0100 Subject: [PATCH 081/190] Use Challenge displayName when broadcasting completion (#25) --- .../ultimateskyblock/challenge/ChallengeLogic.java | 2 +- .../command/admin/AdminChallengeCommand.java | 3 ++- .../us/talabrek/ultimateskyblock/player/PlayerInfo.java | 8 +++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 92f54e88f..69be5eae6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -412,7 +412,7 @@ private boolean giveReward(Player player, Challenge challenge) { command = command.replaceAll("\\{challengeName\\}", Matcher.quoteReplacement(challenge.getDisplayName())); plugin.execCommand(player, command, true); } - playerInfo.completeChallenge(challengeName, wasBroadcast); + playerInfo.completeChallenge(challenge, wasBroadcast); return true; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java index 234973e12..6b7eab6aa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java @@ -91,11 +91,12 @@ public boolean execute(CommandSender commandSender, String alias, Map 0) { sender.sendMessage(I18nUtil.tr("\u00a74Challenge {0} has already been completed", challengeName)); } else { - playerInfo.completeChallenge(challengeName, true); + playerInfo.completeChallenge(challenge, true); playerInfo.save(); sender.sendMessage(I18nUtil.tr("\u00a7eChallenge {0} has been completed for {1}", challengeName, playerInfo.getPlayerName())); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 05bbb2afb..63fff2f2e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -12,6 +12,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; import us.talabrek.ultimateskyblock.hook.permissions.PermissionsHook; import us.talabrek.ultimateskyblock.island.IslandInfo; @@ -162,14 +163,15 @@ public void setJoinParty(final Location l) { this.homeLocation = l != null ? l.clone() : null; } - public void completeChallenge(final String challenge, boolean silent) { - uSkyBlock.getInstance().getChallengeLogic().completeChallenge(this, challenge); + public void completeChallenge(Challenge challenge, boolean silent) { + uSkyBlock.getInstance().getChallengeLogic().completeChallenge(this, challenge.getName()); if (silent) { return; } IslandInfo island = getIslandInfo(); if (island != null) { - island.sendMessageToOnlineMembers(tr("\u00a79{0}\u00a7f has completed the \u00a79{1}\u00a7f challenge!", getPlayerName(), challenge)); + island.sendMessageToOnlineMembers(tr("\u00a79{0}\u00a7f has completed the \u00a79{1}\u00a7f challenge!", + getPlayerName(), challenge.getDisplayName())); } } From ab193ba0784d473f848c3d36f311a27d658519b3 Mon Sep 17 00:00:00 2001 From: BlackBeltPanda Date: Sat, 18 Dec 2021 10:25:12 -0500 Subject: [PATCH 082/190] Biome Improvements (#26) * Biome Improvements Adds all biome types except Custom Expand island biome size if available to mitigate noise Fixes biome range when bounds fall outside region Update Adventure-API * Update pom.xml Make sure adventure-bukkit platform is snapshot version * Enable Default Biome --- bukkit-utils | 2 +- pom.xml | 2 +- .../talabrek/ultimateskyblock/Settings.java | 10 +++++ .../command/island/BiomeCommand.java | 45 +++++++------------ .../imports/wolfwork/WolfWorkUSBImporter.java | 3 +- .../ultimateskyblock/island/IslandInfo.java | 2 +- .../world/ChunkRegenerator.java | 3 +- .../world/SkyBlockChunkGenerator.java | 2 +- 8 files changed, 34 insertions(+), 35 deletions(-) diff --git a/bukkit-utils b/bukkit-utils index 0d460c7d6..d4017e246 160000 --- a/bukkit-utils +++ b/bukkit-utils @@ -1 +1 @@ -Subproject commit 0d460c7d652ea90444284484082a566c38fd2b95 +Subproject commit d4017e24652d3b28a4d4e7b1812a5732b0fba71c diff --git a/pom.xml b/pom.xml index 963f15f04..669be5f56 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ Ultimate SkyBlock - 4.8.1 + 4.9.1 4.0.0-SNAPSHOT 19.0.0 ${project.version} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index c4dfb4d71..d6f78d8ea 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -3,6 +3,7 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; +import us.talabrek.ultimateskyblock.command.island.BiomeCommand; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -30,6 +31,7 @@ public class Settings { public static int general_cooldownInfo; public static int general_cooldownRestart; public static int general_biomeChange; + public static String general_defaultBiome; public static boolean extras_sendToSpawn; public static boolean extras_obsidianToLava; public static String island_schematicName; @@ -83,6 +85,14 @@ public static boolean loadPluginConfig(FileConfiguration config) { } catch (Exception e) { general_biomeChange = 3600; } + try { + general_defaultBiome = config.getString("options.general.defaultBiome"); + if (!BiomeCommand.biomeExists(general_defaultBiome)) { + general_defaultBiome = "OCEAN"; + } + } catch (Exception e) { + general_defaultBiome = "OCEAN"; + } try { general_cooldownRestart = config.getInt("options.general.cooldownRestart"); if (general_cooldownRestart < 0) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index 8da9386a0..04eb9dfff 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -19,30 +19,14 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static us.talabrek.ultimateskyblock.util.BiomeUtil.getBiome; public class BiomeCommand extends RequireIslandCommand { - public static final Map BIOMES = new HashMap() { + public static final Map BIOMES = new HashMap<>() { { - put("ocean", Biome.OCEAN); - put("jungle", Biome.JUNGLE); - put("hell", Biome.NETHER_WASTES); - put("sky", Biome.THE_END); - put("mushroom", Biome.MUSHROOM_FIELDS); - put("swampland", Biome.SWAMP); - put("taiga", Biome.SNOWY_TAIGA); - put("desert", Biome.DESERT); - put("forest", Biome.FOREST); - put("plains", Biome.PLAINS); - put("extreme_hills", Biome.DARK_FOREST_HILLS); - put("deep_ocean", Biome.DEEP_OCEAN); - Biome b = getBiome("ICE_PLAINS"); - if (b != null) { - put("ice_plains", b); - } - b = getBiome("FLOWER_FOREST"); - if (b != null) { - put("flower_forest", b); + for (Biome biome : Biome.values()) { + if (!biome.name().equalsIgnoreCase("custom")) { + put(biome.name().toLowerCase(), biome); + } } } }; @@ -93,16 +77,19 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi } BlockVector3 minP = region.getMinimumPoint(); BlockVector3 maxP = region.getMaximumPoint(); + if (Settings.island_distance > Settings.island_protectionRange) { + int buffer = (Settings.island_distance - Settings.island_protectionRange) / 2; + minP.subtract(buffer, 0, buffer); + maxP.add(buffer, 0, buffer); + } if (args.length == 2 && args[1].matches("[0-9]+")) { int radius = Integer.parseInt(args[1], 10); - Location loc = location.clone().add(-radius, 0, -radius); - if (region.contains(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) { - minP = BlockVector3.at(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - } - loc = location.clone().add(radius, 0, radius); - if (region.contains(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) { - maxP = BlockVector3.at(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); - } + minP = BlockVector3.at(Math.max(location.getBlockX() - radius, minP.getBlockX()), + Math.max(location.getBlockY() - radius, minP.getBlockY()), + Math.max(location.getBlockZ() - radius, minP.getBlockZ())); + maxP = BlockVector3.at(Math.min(location.getBlockX() + radius, maxP.getBlockX()), + Math.min(location.getBlockY() + radius, maxP.getBlockY()), + Math.min(location.getBlockZ() + radius, maxP.getBlockZ())); player.sendMessage(tr("\u00a77The pixies are busy changing the biome near you to \u00a79{0}\u00a77, be patient.", biome)); } else if (args.length == 2 && args[1].equalsIgnoreCase("chunk")) { Chunk chunk = location.clone().getChunk(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java index 62c6c0f7b..e0947d183 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.imports.wolfwork; +import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.imports.USBImporter; @@ -129,7 +130,7 @@ private void importIsland(uSkyBlock plugin, PlayerInfo playerInfo, us.talabrek.u } // Not really that important - since it's most likely different! islandInfo.setLevel(playerInfo.getIslandLevel()); - islandInfo.setBiome("OCEAN"); + islandInfo.setBiome(Settings.general_defaultBiome); islandInfo.save(); WorldGuardHandler.updateRegion(islandInfo); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 5b1893a7b..268a63cf9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -391,7 +391,7 @@ private boolean hasPerm(UUID uuid, String perm) { @Override public String getBiome() { - return config.getString("general.biome", "OCEAN").toUpperCase(); + return config.getString("general.biome", Settings.general_defaultBiome).toUpperCase(); } public void setBiome(@NotNull String biome) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java index 0a514556f..20007d69c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java @@ -13,6 +13,7 @@ import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Arrays; @@ -126,7 +127,7 @@ static class DefaultBiomeGrid implements BiomeGrid { defaultBiome = Biome.NETHER_WASTES; break; default: - defaultBiome = Biome.OCEAN; + defaultBiome = Biome.valueOf(Settings.general_defaultBiome); break; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java index dc3e85149..b0c60005e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java @@ -20,7 +20,7 @@ public ChunkData generateChunkData(World world, Random random, int cx, int cz, B for (int x = 0; x <= 15; x++) { for (int z = 0; z <= 15; z++) { for (int y = 0; y < world.getMaxHeight(); y++) { - biome.setBiome(x, y, z, Biome.OCEAN); + biome.setBiome(x, y, z, Biome.valueOf(Settings.general_defaultBiome)); } } } From a9cf47bf5b3fbe6e4595125a8568b23f0abf023f Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Dec 2021 15:31:39 +0000 Subject: [PATCH 083/190] Fix Adventure dependencies --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 669be5f56..7cfff4371 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,8 @@ Ultimate SkyBlock - 4.9.1 - 4.0.0-SNAPSHOT + 4.9.3 + 4.0.0 19.0.0 ${project.version} 1.25-SNAPSHOT From c7241165c12d451a59831f6095659461f42b52ab Mon Sep 17 00:00:00 2001 From: BlackBeltPanda Date: Sat, 18 Dec 2021 10:40:13 -0500 Subject: [PATCH 084/190] Add respawn at island option and fix some bugs (#30) * Add respawnAtHome config option Cleanup and bugfix PlayerEvents * Fix obsidian to lava re-placing lava Fix some pvp logic --- .../talabrek/ultimateskyblock/Settings.java | 2 + .../ultimateskyblock/event/PlayerEvents.java | 302 ++++++++++-------- uSkyBlock-Core/src/main/resources/config.yml | 6 +- 3 files changed, 170 insertions(+), 140 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index d6f78d8ea..bc608917c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -33,6 +33,7 @@ public class Settings { public static int general_biomeChange; public static String general_defaultBiome; public static boolean extras_sendToSpawn; + public static boolean extras_respawnAtIsland; public static boolean extras_obsidianToLava; public static String island_schematicName; public static long island_topTenTimeout; @@ -137,6 +138,7 @@ public static boolean loadPluginConfig(FileConfiguration config) { island_useIslandLevel = config.getBoolean("options.island.useIslandLevel"); island_extraPermissions = permissionList.toArray(new String[0]); extras_sendToSpawn = config.getBoolean("options.extras.sendToSpawn"); + extras_respawnAtIsland = config.getBoolean("options.extras.respawnAtIsland"); island_useTopTen = config.getBoolean("options.island.useTopTen"); general_worldName = config.getString("options.general.worldName", "skyworld"); island_removeCreaturesByTeleport = config.getBoolean("options.island.removeCreaturesByTeleport"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index 2a331d332..c1016c7ae 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -15,11 +15,10 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.entity.*; +import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; @@ -29,29 +28,24 @@ import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.event.IslandInfoEvent; -import us.talabrek.ultimateskyblock.api.model.IslandScore; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PatienceTester; -import us.talabrek.ultimateskyblock.player.Perk; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.LocationUtil; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.WeakHashMap; +import java.util.*; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -@SuppressWarnings("unused") public class PlayerEvents implements Listener { - private static final Set FIRE_TRAP = new HashSet<>( - Arrays.asList(EntityDamageEvent.DamageCause.LAVA, EntityDamageEvent.DamageCause.FIRE, EntityDamageEvent.DamageCause.FIRE_TICK)); + private static final Set FIRE_TRAP = new HashSet<>(Arrays.asList( + EntityDamageEvent.DamageCause.LAVA, + EntityDamageEvent.DamageCause.FIRE, + EntityDamageEvent.DamageCause.FIRE_TICK, + EntityDamageEvent.DamageCause.HOT_FLOOR)); private static final Random RANDOM = new Random(); private static final int OBSIDIAN_SPAM = 10000; // Max once every 10 seconds. @@ -62,6 +56,13 @@ public class PlayerEvents implements Listener { private final boolean protectLava; private final Map obsidianClick = new WeakHashMap<>(); private final boolean blockLimitsEnabled; + private final Map leafSaplings = Map.of( + Material.OAK_LEAVES, Material.OAK_SAPLING, + Material.SPRUCE_LEAVES, Material.SPRUCE_SAPLING, + Material.BIRCH_LEAVES, Material.BIRCH_SAPLING, + Material.ACACIA_LEAVES, Material.ACACIA_SAPLING, + Material.JUNGLE_LEAVES, Material.JUNGLE_SAPLING, + Material.DARK_OAK_LEAVES, Material.DARK_OAK_SAPLING); public PlayerEvents(uSkyBlock plugin) { this.plugin = plugin; @@ -73,52 +74,50 @@ public PlayerEvents(uSkyBlock plugin) { blockLimitsEnabled = config.getBoolean("options.island.block-limits.enabled", false); } - @EventHandler(priority = EventPriority.NORMAL) + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerFoodChange(final FoodLevelChangeEvent event) { - if (event.getEntity() instanceof Player && plugin.getWorldManager().isSkyWorld(event.getEntity().getWorld())) { - Player hungerman = (Player) event.getEntity(); - float randomNum = RANDOM.nextFloat(); - if (plugin.getWorldManager().isSkyWorld(hungerman.getWorld()) - && hungerman.getFoodLevel() > event.getFoodLevel() - && plugin.playerIsOnIsland(hungerman)) { - Perk perk = plugin.getPerkLogic().getPerk(hungerman); - if (randomNum <= perk.getHungerReduction()) { + if (event.getEntity() instanceof Player player) { + if (player.getFoodLevel() > event.getFoodLevel() && plugin.playerIsOnIsland(player)) { + if (RANDOM.nextFloat() <= plugin.getPerkLogic().getPerk(player).getHungerReduction()) { event.setCancelled(true); } } } } - @EventHandler(priority = EventPriority.NORMAL) + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onClickOnObsidian(final PlayerInteractEvent event) { - if (!plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { - return; - } - long now = System.currentTimeMillis(); Player player = event.getPlayer(); - PlayerInventory inventory = player.getInventory(); Block block = event.getClickedBlock(); - Long lastClick = obsidianClick.get(player.getUniqueId()); - if (lastClick != null && (lastClick + OBSIDIAN_SPAM) >= now) { - plugin.notifyPlayer(player, tr("\u00a74You can only convert obsidian once every 10 seconds")); - return; - } - if (Settings.extras_obsidianToLava && plugin.playerIsOnIsland(player) - && plugin.getWorldManager().isSkyWorld(player.getWorld()) - && event.getAction() == Action.RIGHT_CLICK_BLOCK - && player.getItemInHand() != null - && player.getItemInHand().getType() == Material.BUCKET - && block != null - && block.getType() == Material.OBSIDIAN - && !testForObsidian(block)) { + if (plugin.playerIsOnIsland(player) + && Settings.extras_obsidianToLava + && event.hasBlock() + && event.hasItem() + && event.getAction() == Action.RIGHT_CLICK_BLOCK + && event.getMaterial() == Material.BUCKET + && block != null + && block.getType() == Material.OBSIDIAN + && !testForObsidian(block)) { + long now = System.currentTimeMillis(); + Long lastClick = obsidianClick.get(player.getUniqueId()); + if (lastClick != null && (lastClick + OBSIDIAN_SPAM) >= now) { + plugin.notifyPlayer(player, tr("\u00a74You can only convert obsidian once every 10 seconds")); + return; + } + PlayerInventory inventory = player.getInventory(); if (inventory.firstEmpty() != -1) { - obsidianClick.put(player.getUniqueId(), now); - player.sendMessage(tr("\u00a7eChanging your obsidian back into lava. Be careful!")); - inventory.removeItem(new ItemStack(Material.BUCKET, 1)); - inventory.addItem(new ItemStack(Material.LAVA_BUCKET, 1)); - player.updateInventory(); - block.setType(Material.AIR); - event.setCancelled(true); // Don't execute the click anymore (since that would re-place the lava). + HashMap leftover = inventory.removeItem(new ItemStack(Material.BUCKET)); + if (leftover.isEmpty()) { + obsidianClick.put(player.getUniqueId(), now); + player.sendMessage(tr("\u00a7eChanging your obsidian back into lava. Be careful!")); + leftover = inventory.addItem(new ItemStack(Material.LAVA_BUCKET)); + // Just in case, drop the item if their inventory somehow filled before we could add it + if (!leftover.isEmpty()) { + player.getWorld().dropItem(block.getLocation(), new ItemStack(Material.LAVA_BUCKET)); + } + block.setType(Material.AIR); + event.setCancelled(true); + } } else { player.sendMessage(tr("\u00a7eYour inventory must have another empty space!")); } @@ -142,7 +141,19 @@ public boolean testForObsidian(final Block block) { return false; } - @EventHandler + // Prevent re-placing lava that was picked up in the last tick + @EventHandler(ignoreCancelled = true) + public void onLavaPlace(final PlayerBucketEmptyEvent event) { + if (Settings.extras_obsidianToLava && event.getBucket() == Material.LAVA_BUCKET) { + long now = System.currentTimeMillis(); + Long lastClick = obsidianClick.get(event.getPlayer().getUniqueId()); + if (lastClick != null && (now - lastClick < 50)) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) public void onLavaReplace(BlockPlaceEvent event) { if (!protectLava || !plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { return; @@ -154,122 +165,117 @@ public void onLavaReplace(BlockPlaceEvent event) { } private boolean isLavaSource(BlockData blockData) { - if (blockData.getMaterial() == Material.LAVA) { - Levelled level = (Levelled) blockData; - return level.getLevel() == 0; - } - return false; + return (blockData.getMaterial() == Material.LAVA + && blockData instanceof Levelled level + && level.getLevel() == 0); } + // If an entity, such as an Enderman, attempts to replace a lava source block then cancel it and drop the item instead @EventHandler public void onLavaAbsorption(EntityChangeBlockEvent event) { - if (!plugin.getWorldManager().isSkyWorld(event.getBlock().getWorld())) { + Block block = event.getBlock(); + if (!protectLava || !plugin.getWorldManager().isSkyWorld(block.getWorld())) { return; } - if (isLavaSource(event.getBlock().getBlockData())) { + if (isLavaSource(block.getBlockData())) { if (event.getTo() != Material.LAVA) { event.setCancelled(true); - // TODO: R4zorax - 21-07-2018: missing datavalue (might convert stuff - exploit) - ItemStack item = new ItemStack(event.getTo(), 1); - Location above = event.getBlock().getLocation().add(0, 1, 0); - event.getBlock().getWorld().dropItemNaturally(above, item); + // Drop the item diagonally above to reduce the risk of the item falling into the lava + block.getWorld().dropItemNaturally(block.getLocation().add(1, 1, 1), new ItemStack(event.getTo())); } } } - // TODO 2018-11-09 Muspah: Move (parts) to new EntityDamageByEntityEvent-handler - @EventHandler(priority = EventPriority.HIGHEST) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onVisitorDamage(final EntityDamageEvent event) { - // Only protect things in the Skyworld. - if (!plugin.getWorldManager().isSkyWorld(event.getEntity().getWorld())) { - return; - } - - // Only protect visitors against damage if pvp is disabled: - if (Settings.island_allowPvP) { - return; - } - - // This protection only applies to players: - if (!(event.getEntity() instanceof Player)) { - return; - } - - // Don't protect players on their own islands: - if (plugin.playerIsOnIsland((Player) event.getEntity())) { - return; + if (event.getEntity() instanceof Player player + && plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld()) + && !plugin.playerIsOnIsland(player)) { + if ((visitorFireProtected && FIRE_TRAP.contains(event.getCause())) + || (visitorFallProtected && (event.getCause() == EntityDamageEvent.DamageCause.FALL))) { + event.setDamage(-event.getDamage()); + event.setCancelled(true); + } } + } - if ((visitorFireProtected && FIRE_TRAP.contains(event.getCause())) - || (visitorFallProtected && (event.getCause() == EntityDamageEvent.DamageCause.FALL)) - || (visitorMonsterProtected && - (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_ATTACK + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVisitorDamageByEntity(final EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player player + && plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld()) + && !plugin.playerIsOnIsland(player) + && !(event.getDamager() instanceof Player && Settings.island_allowPvP)) { + if (visitorMonsterProtected && + (event.getCause() == EntityDamageEvent.DamageCause.ENTITY_ATTACK || event.getCause() == EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK || event.getCause() == EntityDamageEvent.DamageCause.ENTITY_EXPLOSION || event.getCause() == EntityDamageEvent.DamageCause.PROJECTILE || event.getCause() == EntityDamageEvent.DamageCause.MAGIC - || event.getCause() == EntityDamageEvent.DamageCause.POISON))) { - event.setDamage(-event.getDamage()); - event.setCancelled(true); + || event.getCause() == EntityDamageEvent.DamageCause.POISON)) { + event.setDamage(-event.getDamage()); + event.setCancelled(true); + } } } @EventHandler(priority = EventPriority.HIGHEST) public void onSpawnDamage(final EntityDamageEvent event) { - if (!plugin.getWorldManager().isSkyWorld(event.getEntity().getWorld())) { - return; - } - if (event.getEntity() instanceof Player && plugin.playerIsInSpawn((Player) event.getEntity()) && event.getCause() == EntityDamageEvent.DamageCause.VOID) { + if (event.getEntity() instanceof Player player && plugin.playerIsInSpawn(player) && event.getCause() == EntityDamageEvent.DamageCause.VOID) { event.setDamage(-event.getDamage()); event.setCancelled(true); - plugin.getTeleportLogic().spawnTeleport((Player) event.getEntity(), true); + player.setFallDistance(0); + plugin.getTeleportLogic().spawnTeleport(player, true); } } - @EventHandler + @EventHandler(ignoreCancelled = true) public void onMemberDamage(final EntityDamageByEntityEvent event) { - if (!plugin.getWorldManager().isSkyAssociatedWorld(event.getEntity().getWorld())) { - return; - } - if (!(event.getEntity() instanceof Player)) { - return; - } - Player p2 = (Player) event.getEntity(); - if (event.getDamager() instanceof Player) { - Player p1 = (Player) event.getDamager(); - cancelMemberDamage(p1, p2, event); - } else if (event.getDamager() instanceof Projectile - && !(event.getDamager() instanceof EnderPearl)) { - ProjectileSource shooter = ((Projectile) event.getDamager()).getShooter(); - if (shooter instanceof Player) { - Player p1 = (Player) shooter; - cancelMemberDamage(p1, p2, event); + if (event.getEntity() instanceof Player victim && plugin.getWorldManager().isSkyAssociatedWorld(victim.getWorld())) { + if (event.getDamager() instanceof Player attacker) { + cancelMemberDamage(attacker, victim, event); + } + else if (event.getDamager() instanceof Projectile && !(event.getDamager() instanceof EnderPearl)) { + ProjectileSource shooter = ((Projectile) event.getDamager()).getShooter(); + if (shooter instanceof Player attacker) { + cancelMemberDamage(attacker, victim, event); + } } } } - private void cancelMemberDamage(Player p1, Player p2, EntityDamageByEntityEvent event) { - IslandInfo is1 = plugin.getIslandInfo(p1); - IslandInfo is2 = plugin.getIslandInfo(p2); + private void cancelMemberDamage(Player attacker, Player victim, EntityDamageByEntityEvent event) { + IslandInfo is1 = plugin.getIslandInfo(attacker); + IslandInfo is2 = plugin.getIslandInfo(victim); if (is1 != null && is2 != null && is1.getName().equals(is2.getName())) { - plugin.notifyPlayer(p1, tr("\u00a7eYou cannot hurt island-members.")); + plugin.notifyPlayer(attacker, tr("\u00a7eYou cannot hurt island-members.")); event.setCancelled(true); } } @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerRespawn(PlayerRespawnEvent event) { - if (Settings.extras_sendToSpawn) { - return; + if (Settings.extras_respawnAtIsland) { + PlayerInfo playerInfo = plugin.getPlayerInfo(event.getPlayer()); + if (playerInfo.getHasIsland()) { + Location homeLocation = LocationUtil.findNearestSafeLocation(playerInfo.getHomeLocation(), null); + if (homeLocation == null) { + homeLocation = LocationUtil.findNearestSafeLocation(playerInfo.getIslandLocation(), null); + } + // If homeLocation is somehow still null, we intentionally fallthrough + if (homeLocation != null) { + event.setRespawnLocation(homeLocation); + return; + } + } } - if (plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { + if (!Settings.extras_sendToSpawn && plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { event.setRespawnLocation(plugin.getWorldManager().getWorld().getSpawnLocation()); } } @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onTeleport(PlayerTeleportEvent event) { - if (event.getTo() != null || !plugin.getWorldManager().isSkyWorld(event.getTo().getWorld())) { + if (event.getTo() == null || !plugin.getWorldManager().isSkyWorld(event.getTo().getWorld())) { return; } final Player player = event.getPlayer(); @@ -290,28 +296,22 @@ public void onTeleport(PlayerTeleportEvent event) { } /** - * This EventHandler handles {@link BlockBreakEvent} to detect if a player broke OAK_LEAVES in the skyworld, - * and will drop an OAK_SAPLING if so. This will prevent cases where the default generated oak tree on a new + * This EventHandler handles {@link BlockBreakEvent} to detect if a player broke leaves in the skyworld, + * and will drop a sapling if so. This will prevent cases where the default generated tree on a new * island drops no saplings. * @param event BlockBreakEvent to handle. */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onLeafBreak(BlockBreakEvent event) { - if (!plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { - return; - } - if (event.getBlock().getType() != Material.OAK_LEAVES) { - return; - } - - String islandName = WorldGuardHandler.getIslandNameAt(event.getPlayer().getLocation()); - IslandInfo islandInfo = plugin.getIslandInfo(islandName); - if (islandInfo != null && islandInfo.getLeafBreaks() == 0) { - event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), new ItemStack(Material.OAK_SAPLING, 1)); - islandInfo.setLeafBreaks(islandInfo.getLeafBreaks() + 1); + if (plugin.playerIsOnIsland(event.getPlayer()) && leafSaplings.containsKey(event.getBlock().getType())) { + IslandInfo islandInfo = plugin.getIslandInfo(event.getBlock().getLocation()); + if (islandInfo != null && islandInfo.getLeafBreaks() == 0) { + event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), new ItemStack(leafSaplings.get(event.getBlock().getType()))); + islandInfo.setLeafBreaks(1); + } } } - + @EventHandler(ignoreCancelled = true) public void onBlockPlaceEvent(BlockPlaceEvent event) { final Player player = event.getPlayer(); @@ -331,7 +331,7 @@ public void onBlockPlaceEvent(BlockPlaceEvent event) { if (!PatienceTester.isRunning(player, key)) { PatienceTester.startRunning(player, key); player.sendMessage(tr("\u00a74{0} is limited. \u00a7eScanning your island to see if you are allowed to place more, please be patient", ItemStackUtil.getItemName(new ItemStack(type)))); - plugin.fireAsyncEvent(new IslandInfoEvent(player, islandInfo.getIslandLocation(), new Callback() { + plugin.fireAsyncEvent(new IslandInfoEvent(player, islandInfo.getIslandLocation(), new Callback<>() { @Override public void run() { player.sendMessage(tr("\u00a7e... Scanning complete, you can try again")); @@ -348,10 +348,10 @@ public void run() { } plugin.getBlockLimitLogic().incBlockCount(islandInfo.getIslandLocation(), type); } - + @EventHandler(ignoreCancelled = true) - public void onHopperDestroy(BlockBreakEvent event){ - if (!blockLimitsEnabled || !plugin.getWorldManager().isSkyAssociatedWorld(event.getPlayer().getWorld())) { + public void onBlockBreak(BlockBreakEvent event){ + if (!blockLimitsEnabled || !plugin.getWorldManager().isSkyAssociatedWorld(event.getBlock().getWorld())) { return; // Skip } IslandInfo islandInfo = plugin.getIslandInfo(event.getBlock().getLocation()); @@ -360,4 +360,28 @@ public void onHopperDestroy(BlockBreakEvent event){ } plugin.getBlockLimitLogic().decBlockCount(islandInfo.getIslandLocation(), event.getBlock().getType()); } + + @EventHandler(ignoreCancelled = true) + public void onBlockExplode(EntityExplodeEvent event) { + if (blockLimitsEnabled && plugin.getWorldManager().isSkyAssociatedWorld(event.getLocation().getWorld())) { + IslandInfo islandInfo = plugin.getIslandInfo(event.getLocation()); + if (islandInfo != null) { + for (Block block : event.blockList()) { + plugin.getBlockLimitLogic().decBlockCount(islandInfo.getIslandLocation(), block.getType()); + } + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onBlockExplodeUnknown(BlockExplodeEvent event) { + if (blockLimitsEnabled && plugin.getWorldManager().isSkyAssociatedWorld(event.getBlock().getWorld())) { + IslandInfo islandInfo = plugin.getIslandInfo(event.getBlock().getLocation()); + if (islandInfo != null) { + for (Block block : event.blockList()) { + plugin.getBlockLimitLogic().decBlockCount(islandInfo.getIslandLocation(), block.getType()); + } + } + } + } } diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index d53d13e7b..8458a300f 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -109,7 +109,11 @@ options: # NOTE: Requires EssentialsSpawn or another plugin with the "/spawn" command sendToSpawn: false - # [true/false] If true, a player can right-click on a block of obsidian on their island while holding an empty bucket to remove the obsidian and fill the bucket with lava. This is useful for people that accidently + # [true/false] If true, when a player respawns they will respawn on their island. Will first attempt to respawn them at the closest safe location to their island home, then their island spawn, then the server spawn. + # NOTE: If this is true, sendToSpawn is ignored unless the player has no island or no viable island home or spawn location. + respawnAtIsland: true + + # [true/false] If true, a player can right-click on a block of obsidian on their island while holding an empty bucket to remove the obsidian and fill the bucket with lava. This is useful for people that accidentally # turn their lava into obsidian with a bad cobblestone generator design. Will only work on the player's island and if there are no other obsidian blocks nearby (so can't be used on portals). obsidianToLava: true From ba6d2e03c8845ebb2f7bb8b507a31b62c78259d1 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Dec 2021 15:51:33 +0000 Subject: [PATCH 085/190] USB to 2.11.0-SNAPSHOT, Spigot API to 1.18.1 --- po-utils/pom.xml | 2 +- pom.xml | 10 +++++----- uSkyBlock-API/pom.xml | 6 +++--- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index edb126758..30800c54f 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index 7cfff4371..98dce0b7c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,20 +4,20 @@ uSkyBlock uSkyBlock pom - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT Ultimate SkyBlock 4.9.3 4.0.0 - 19.0.0 + 22.0.0 ${project.version} 1.25-SNAPSHOT 1.0.4 - 1.17-R0.1-SNAPSHOT + 1.18.1-R0.1-SNAPSHOT 1.7 - 7.2.6-SNAPSHOT - 7.0.6-SNAPSHOT + 7.2.8 + 7.0.6 UTF-8 ${project.artifactId} diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index b80ec6f51..09a693ccb 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT UTF-8 @@ -31,7 +31,7 @@ org.spigotmc spigot-api - 1.17-R0.1-SNAPSHOT + 1.18.1-R0.1-SNAPSHOT provided true @@ -39,7 +39,7 @@ org.jetbrains annotations - 19.0.0 + 22.0.0 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 197e8a3c5..3cd0edd4e 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index e06b3a5f2..a19d7b430 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 3a78bea99..fb193e677 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 29aae91ff..5c4530751 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.10.0-SNAPSHOT + 2.11.0-SNAPSHOT 4.0.0 jar From d994dd2b17a33a9b537df7f7ce63497d00e45f9d Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Dec 2021 16:01:14 +0000 Subject: [PATCH 086/190] Make it compile at least --- uSkyBlock-Core/pom.xml | 5 +++-- .../java/us/talabrek/ultimateskyblock/MetricsManager.java | 7 ++++--- .../us/talabrek/ultimateskyblock/event/SpawnEvents.java | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index a19d7b430..4c9f52bc1 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -421,14 +421,15 @@ org.bstats bstats-bukkit - 1.7 + 2.2.1 compile + com.google.guava guava - 21.0 + 31.0.1-jre provided diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java index 36cd0b6f4..8d3ec64c4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock; import org.bstats.bukkit.Metrics; +import org.bstats.charts.SimplePie; import java.util.logging.Level; @@ -24,13 +25,13 @@ public MetricsManager(uSkyBlock plugin) { private void setupMetrics(int pluginId) { Metrics bStats = new Metrics(plugin, pluginId); - bStats.addCustomChart(new Metrics.SimplePie("language", + bStats.addCustomChart(new SimplePie("language", () -> plugin.getConfig().getString("language", "en"))); - bStats.addCustomChart(new Metrics.SimplePie("radius_and_distance", + bStats.addCustomChart(new SimplePie("radius_and_distance", () -> String.format("(%d,%d)", Settings.island_radius, Settings.island_distance))); // Temp. chart to measure storage usage for (legacy) uuid.PlayerDB. - bStats.addCustomChart(new Metrics.SimplePie("playerdb_type", + bStats.addCustomChart(new SimplePie("playerdb_type", () -> plugin.getConfig().getString("options.advanced.playerdb.storage", "yml"))); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index b7bbcd139..ea2e8087f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -120,7 +120,7 @@ private boolean isPrismarineRoof(Location loc) { } private boolean isDeepOceanBiome(Location loc) { - List deepOceans = Arrays.asList(Biome.DEEP_OCEAN, Biome.DEEP_COLD_OCEAN, Biome.DEEP_FROZEN_OCEAN, Biome.DEEP_LUKEWARM_OCEAN, Biome.DEEP_WARM_OCEAN); + List deepOceans = Arrays.asList(Biome.DEEP_OCEAN, Biome.DEEP_COLD_OCEAN, Biome.DEEP_FROZEN_OCEAN, Biome.DEEP_LUKEWARM_OCEAN); return deepOceans.contains(loc.getWorld().getBiome(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); } From 268d328c7809f25051d2d231e8079e66665d7612 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Dec 2021 16:10:05 +0000 Subject: [PATCH 087/190] We're Java 17 now --- .github/workflows/build.yml | 4 ++-- .travis.yml | 8 +------- po-utils/pom.xml | 3 +-- pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6cac5b8aa..d21c3b732 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,10 +21,10 @@ jobs: run: | cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - - - name: JDK 16 + - name: JDK 17 uses: actions/setup-java@v1 with: - java-version: '16' + java-version: '17' distribution: 'adopt' - name: Cache Maven repository uses: actions/cache@v2 diff --git a/.travis.yml b/.travis.yml index e22b7df8d..9ab25e459 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: java jdk: -- openjdk16 +- openjdk17 sudo: false cache: directories: @@ -24,7 +24,6 @@ before_deploy: - ssh-add deploy_rsa - chmod +x scripts/deploy-staging.sh - chmod +x scripts/deploy-release.sh - - chmod +x scripts/deploy-117.sh deploy: - provider: script skip_cleanup: true @@ -36,8 +35,3 @@ deploy: script: bash scripts/deploy-release.sh on: tags: true - - provider: script - skip_cleanup: true - script: bash scripts/deploy-117.sh - on: - branch: "bukkit-1.17" diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 30800c54f..330f8360e 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -48,8 +48,7 @@ maven-compiler-plugin - 1.8 - 1.8 + 17 utf-8 diff --git a/pom.xml b/pom.xml index 98dce0b7c..ed5420c8d 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ maven-compiler-plugin 3.8.1 - 16 + 17 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 4c9f52bc1..7ed2e2662 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -17,7 +17,7 @@ org.apache.maven.plugins maven-compiler-plugin - 16 + 17 utf-8 From adbaee3a9b584dbc76f264578dc2d4629df21ee0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 19 Dec 2021 15:51:03 +0000 Subject: [PATCH 088/190] Bump some dependencies --- pom.xml | 42 ++++++++++++++++++++++++++++++++---------- uSkyBlock-FAWE/pom.xml | 2 +- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index ed5420c8d..b0585b2d5 100644 --- a/pom.xml +++ b/pom.xml @@ -9,11 +9,11 @@ 4.9.3 - 4.0.0 - 22.0.0 + 4.0.1 + 23.0.0 ${project.version} 1.25-SNAPSHOT - 1.0.4 + 1.0.7 1.18.1-R0.1-SNAPSHOT 1.7 7.2.8 @@ -27,10 +27,10 @@ msgmerge - 2.1 - 4.12 - 5.5.1 - 3.11.0 + 2.2 + 4.13.2 + 5.8.2 + 3.12.4 @@ -76,7 +76,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.0 + 3.3.1 org.apache.maven.plugins @@ -86,15 +86,37 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.2 + 3.0.0-M5 org.apache.maven.plugins maven-failsafe-plugin - 2.22.2 + 3.0.0-M5 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0 + + + enforce-maven + + enforce + + + + + 3.8.1 + + + + + + + diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index fb193e677..2ffc3a942 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -21,7 +21,7 @@ com.fastasyncworldedit FAWE-Bukkit - 1.17-6 + 1.17-268 provided From 12420d44fb9a8fe520c29b0b67981050f9665d82 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 19 Dec 2021 17:29:14 +0000 Subject: [PATCH 089/190] Travis use Focal (when are we dropping Travis?) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9ab25e459..1700848b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: java jdk: - openjdk17 +dist: focal sudo: false cache: directories: From 9258bb4b016670f1848444ab3fb5794637cfa727 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 21 Dec 2021 14:22:02 +0000 Subject: [PATCH 090/190] GH Actions deploy test #1 --- .github/deploy-staging.sh | 53 +++++++++++++++++++++++++++++++++++++ .github/workflows/build.yml | 17 ++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/deploy-staging.sh diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh new file mode 100644 index 000000000..0e8ae7f79 --- /dev/null +++ b/.github/deploy-staging.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +echo -e "Running staging script...\n" +echo -e "Publishing javadocs and artifacts...\n" +cd $HOME + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +echo -e "Publishing javadocs...\n" + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/master/po-utils/ + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ + +echo -e "Publishing final plugin release...\n" + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ +travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d21c3b732..8838744a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,3 +34,20 @@ jobs: restore-keys: ${{ runner.os }}-m2 - name: Build with Maven run: mvn -U -Pi18n clean deploy + + # Install our SSH key: + - name: Install SSH key + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_PRIVATE_KEY }} + known_hosts: ${{ secrets.SSH_KNOWN_HOST }} + + # Mark our scripts runnable: + - name: Mark deploy scripts runnable + run: | + chmod +x "${GITHUB_WORKSPACE}/.github/deploy-staging.sh" + + # Deploy from master branch (staging release): + - name: Run deploy script for staging release + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + run: "${GITHUB_WORKSPACE}/.github/deploy-staging.sh" From 6c21e3059d15fbed26e8e44440589ce3b90b2fe6 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 21 Dec 2021 14:32:00 +0000 Subject: [PATCH 091/190] Take #2 --- .github/deploy-staging.sh | 22 +++++++++++----------- .github/workflows/build.yml | 4 +++- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh index 0e8ae7f79..fc1f5559a 100644 --- a/.github/deploy-staging.sh +++ b/.github/deploy-staging.sh @@ -5,49 +5,49 @@ echo -e "Publishing javadocs and artifacts...\n" cd $HOME rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/po-utils/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ echo -e "Publishing javadocs...\n" rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ +$HOME/work/uSkyBlock/uSkyBlock/po-utils/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/po-utils/ rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ echo -e "Publishing final plugin release...\n" rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8838744a5..7987a648a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,9 @@ jobs: uses: actions/setup-java@v1 with: java-version: '17' - distribution: 'adopt' + distribution: 'temurin' + - name: Install gettext + run: sudo apt-get install -y gettext - name: Cache Maven repository uses: actions/cache@v2 with: From 4d6815ab759996f92f643d41e57064cd3992c718 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 21 Dec 2021 14:48:57 +0000 Subject: [PATCH 092/190] Add deploy release script --- .github/deploy-release.sh | 53 +++++++++++++++++++++++++++++++++++++ .github/workflows/build.yml | 7 +++++ 2 files changed, 60 insertions(+) create mode 100644 .github/deploy-release.sh diff --git a/.github/deploy-release.sh b/.github/deploy-release.sh new file mode 100644 index 000000000..bdedfcd98 --- /dev/null +++ b/.github/deploy-release.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +echo -e "Running release script...\n" +echo -e "Publishing javadocs and artifacts...\n" +cd $HOME + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/po-utils/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + +echo -e "Publishing javadocs...\n" + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/po-utils/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/release/po-utils/ + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-API/ + +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-Core/ + +echo -e "Publishing final plugin release...\n" + +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ +travis@travis.internetpolice.eu:WWW-USB/downloads/release/uSkyBlock/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7987a648a..4beba0565 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,7 @@ name: Maven build on: push: branches: [ master ] + tags: [ 'v*' ] pull_request: branches: [ master ] @@ -48,8 +49,14 @@ jobs: - name: Mark deploy scripts runnable run: | chmod +x "${GITHUB_WORKSPACE}/.github/deploy-staging.sh" + chmod +x "${GITHUB_WORKSPACE}/.github/deploy-release.sh" # Deploy from master branch (staging release): - name: Run deploy script for staging release if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} run: "${GITHUB_WORKSPACE}/.github/deploy-staging.sh" + + # Deploy from tag create (plugin release): + - name: Run deploy script for plugin release + if: ${{ github.event_name == 'push' && startsWith( github.ref, 'refs/tags/' }} + run: "${GITHUB_WORKSPACE}/.github/deploy-release.sh" From 62816131d81180fea42894938e582e11722795f0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 21 Dec 2021 14:49:59 +0000 Subject: [PATCH 093/190] Add missing ) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4beba0565..ffbe9b340 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,5 +58,5 @@ jobs: # Deploy from tag create (plugin release): - name: Run deploy script for plugin release - if: ${{ github.event_name == 'push' && startsWith( github.ref, 'refs/tags/' }} + if: ${{ github.event_name == 'push' && startsWith( github.ref, 'refs/tags/') }} run: "${GITHUB_WORKSPACE}/.github/deploy-release.sh" From 6715899ea6d5ddcb39e561b4541f678a8bbfa520 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 23 Dec 2021 16:00:44 +0000 Subject: [PATCH 094/190] Remove datavalues from level calculation (#23) --- .../island/level/BlockCountCollection.java | 8 +-- .../island/level/BlockKey.java | 17 ++---- .../island/level/BlockLevelConfig.java | 8 +-- .../island/level/BlockLevelConfigBuilder.java | 6 --- .../island/level/BlockLevelConfigMap.java | 16 ++---- .../island/level/BlockMatch.java | 45 ++-------------- .../island/level/BlockScoreImpl.java | 1 - .../island/level/ChunkSnapshotLevelLogic.java | 7 +-- .../island/level/IslandScore.java | 2 - .../level/yml/LevelConfigYmlReader.java | 37 ++----------- .../level/yml/LevelConfigYmlWriter.java | 54 ------------------- .../island/level/BlockLevelConfigMapTest.java | 5 +- 12 files changed, 28 insertions(+), 178 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlWriter.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockCountCollection.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockCountCollection.java index d19f97184..10bc41350 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockCountCollection.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockCountCollection.java @@ -21,16 +21,16 @@ public BlockCountCollection(BlockLevelConfigMap configMap) { countMap = new ConcurrentHashMap<>(); } - public int add(Material type, byte dataValue, int blockCount) { - BlockLevelConfig blockLevelConfig = configMap.get(type, dataValue); + public int add(Material type, int blockCount) { + BlockLevelConfig blockLevelConfig = configMap.get(type); BlockMatch key = blockLevelConfig.getKey(); LongAdder count = countMap.computeIfAbsent(key, k -> new LongAdder()); count.add(blockCount); return count.intValue(); } - public int add(Material type, byte dataValue) { - return add(type, dataValue, 1); + public int add(Material type) { + return add(type, 1); } public List calculateScore(double pointsPerLevel) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockKey.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockKey.java index f9c6f96cd..70dc1fb83 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockKey.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockKey.java @@ -5,39 +5,32 @@ import java.util.Objects; public class BlockKey implements Comparable { - private Material type; - private byte dataValue; + private final Material type; - public BlockKey(Material type, byte dataValue) { + public BlockKey(Material type) { this.type = type; - this.dataValue = dataValue; } public Material getType() { return type; } - public byte getDataValue() { - return dataValue; - } - @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BlockKey blockKey = (BlockKey) o; - return dataValue == blockKey.dataValue && - type == blockKey.type; + return type == blockKey.type; } @Override public int hashCode() { - return Objects.hash(type, dataValue); + return Objects.hash(type); } @Override public String toString() { - return type.name() + (dataValue != 0 ? "/" + dataValue : ""); + return type.name(); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java index f445ae997..82e998577 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java @@ -40,12 +40,8 @@ public BlockLevelConfig(BlockMatch baseBlock, Set additionalBlocks, this.negativeReturns = negativeReturns; } - public boolean matches(Material material, byte dataValue) { - return baseBlock.matches(material, dataValue) || additionalBlocks.stream().anyMatch(b -> b.matches(material, dataValue)); - } - - public BlockScore calculateScore(int count) { - return calculateScore(count, 1); + public boolean matches(Material material) { + return baseBlock.matches(material) || additionalBlocks.stream().anyMatch(b -> b.matches(material)); } public BlockScore calculateScore(int count, double pointsPerLevel) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigBuilder.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigBuilder.java index 305a2b7b8..c22f2ee24 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigBuilder.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigBuilder.java @@ -23,11 +23,6 @@ public BlockLevelConfigBuilder base(Material baseBlock) { return this; } - public BlockLevelConfigBuilder base(Material baseBlock, byte dataValue) { - this.baseBlock = new BlockMatch(baseBlock, dataValue); - return this; - } - public BlockLevelConfigBuilder base(BlockMatch baseBlock) { this.baseBlock = baseBlock; return this; @@ -75,7 +70,6 @@ public BlockLevelConfig build() { // merge any additionalBlocks of the same type as baseBlock into the baseblock additionalBlocks.forEach(c -> { if (baseBlock.getType() == c.getType()) { - baseBlock.getDataValues().addAll(c.getDataValues()); } }); additionalBlocks = additionalBlocks.stream().filter(f -> f.getType() != baseBlock.getType()).collect(Collectors.toSet()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMap.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMap.java index f2d6937f9..515268f14 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMap.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMap.java @@ -25,7 +25,7 @@ public synchronized BlockLevelConfig get(BlockMatch blockMatch) { } private BlockKey asBlockKey(BlockMatch blockMatch) { - return new BlockKey(blockMatch.getType(), blockMatch.getDataValues().isEmpty() ? (byte) 0 : blockMatch.getDataValues().iterator().next()); + return new BlockKey(blockMatch.getType()); } public synchronized BlockLevelConfig get(BlockKey key) { @@ -35,7 +35,7 @@ public synchronized BlockLevelConfig get(BlockKey key) { if (existing != null) { return existing; } - BlockLevelConfig newConfig = defaultBuilder.copy().base(new BlockMatch(key.getType(), key.getDataValue())).build(); + BlockLevelConfig newConfig = defaultBuilder.copy().base(new BlockMatch(key.getType())).build(); searchSet.add(newConfig); searchMap.put(key.getType(), searchSet); return newConfig; @@ -43,7 +43,7 @@ public synchronized BlockLevelConfig get(BlockKey key) { private BlockLevelConfig search(Set searchSet, BlockKey key) { List match = searchSet.stream() - .filter(p -> p.matches(key.getType(), key.getDataValue())) + .filter(p -> p.matches(key.getType())) .distinct() .sorted((a,b) -> -a.getKey().compareTo(b.getKey())) // best match = longest string = desc ordering .collect(Collectors.toList()); @@ -57,16 +57,8 @@ public synchronized BlockLevelConfig get(Material type) { return get(createKey(type)); } - public synchronized BlockLevelConfig get(Material type, byte dataValue) { - return get(createKey(type, dataValue)); - } - - private BlockKey createKey(Material material, byte dataValue) { - return new BlockKey(material, dataValue); - } - private BlockKey createKey(Material material) { - return createKey(material, (byte)0); + return new BlockKey(material); } public BlockLevelConfig getDefault() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java index 7145860be..8fb14ddc6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java @@ -1,56 +1,28 @@ package us.talabrek.ultimateskyblock.island.level; -import com.google.common.primitives.Bytes; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; - /** * Holds the identification of a unit to be matched against a block */ public class BlockMatch implements Comparable { - private Material type; - private Set dataValues; + private final Material type; public BlockMatch(Material type) { - this(type, new byte[0]); - } - - public BlockMatch(Material type, byte dataValue) { - this(type, new byte[]{dataValue}); - } - - public BlockMatch(Material type, byte[] dataValues) { this.type = type; - this.dataValues = dataValues != null && dataValues.length > 0 ? new TreeSet<>(Bytes.asList(dataValues)) : Collections.emptySet(); } public Material getType() { return type; } - public Set getDataValues() { - return dataValues; - } - public ItemStack asItemStack() { - if (dataValues.size() == 1) { - return new ItemStack(type, 1, dataValues.iterator().next()); - } return new ItemStack(type, 1); } - public boolean matches(Material material, byte dataValue) { - if (this.type != material) { - return false; - } - if (!dataValues.isEmpty()) { - return dataValues.contains(dataValue); - } - return true; + public boolean matches(Material material) { + return this.type == material; } public void accept(BlockMatchVisitor visitor) { @@ -59,16 +31,7 @@ public void accept(BlockMatchVisitor visitor) { @Override public String toString() { - String dvString = ""; - if (dataValues.size() > 1) { - dvString = String.format("/%d-%d", dataValues.stream().min(Byte::compareTo).get(), dataValues.stream().max(Byte::compareTo).get()); - } else if (!dataValues.isEmpty()){ - dvString = String.format("/%d", dataValues.iterator().next()); - } - if (dvString.equals("/0-15")) { - dvString = ""; - } - return type.name() + dvString; + return type.name(); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java index f26848283..1d8def7ab 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java @@ -5,7 +5,6 @@ public class BlockScoreImpl implements us.talabrek.ultimateskyblock.api.model.BlockScore { - private final ItemStack block; private final int count; private final double score; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java index 7e4fedc10..a251abfc4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java @@ -82,8 +82,7 @@ private IslandScore calculateScore(ProtectedRegion region, List s if (blockType == Material.AIR) { continue; } - byte blockData = (byte) (chunk.getData(cx, y, cz) & 0xff); - counts.add(blockType, blockData); + counts.add(blockType); } } } @@ -109,8 +108,7 @@ private IslandScore calculateScore(ProtectedRegion region, List s if (blockType == Material.AIR) { continue; } - byte blockData = (byte) (chunk.getData(cx, y, cz) & 0xff); - counts.add(blockType, blockData); + counts.add(blockType); } } } @@ -127,5 +125,4 @@ private static ChunkSnapshot getChunkSnapshot(int x, int z, List } return null; } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java index 486aa5476..149ab4bd3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java @@ -47,7 +47,6 @@ private BlockScoreImpl add(BlockScore score, BlockScore existing) { score.getScore() + existing.getScore(), state, score.getName()); } - @Override public double getScore() { return score; @@ -81,5 +80,4 @@ public List getTop(int offset, int num) { public int getSize() { return top.size(); } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlReader.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlReader.java index ef91afdec..0c7e34126 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlReader.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlReader.java @@ -14,11 +14,10 @@ import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; public class LevelConfigYmlReader { - private static final Pattern BLOCK_KEY_PATTERN = Pattern.compile("(?[A-Z0-9_]+)(/(?[0-9\\-]+))?"); - + private static final Pattern BLOCK_KEY_PATTERN = Pattern.compile("(?[A-Z0-9_]+)?"); + public BlockLevelConfigMap readLevelConfig(FileConfiguration config) { double defaultScore = config.getDouble("general.default", 10d); int defaultLimit = config.getInt("general.limit", Integer.MAX_VALUE); @@ -62,7 +61,7 @@ private BlockLevelConfig readBlockSection(ConfigurationSection section, BlockMat } List additionBlocks = section.getStringList("additionalBlocks"); if (!additionBlocks.isEmpty()) { - builder.additionalBlocks(additionBlocks.stream().map(s -> getBlockMatch(s)).collect(Collectors.toList()).toArray(new BlockMatch[0])); + builder.additionalBlocks(additionBlocks.stream().map(this::getBlockMatch).toArray(BlockMatch[]::new)); } return builder.build(); } @@ -70,7 +69,7 @@ private BlockLevelConfig readBlockSection(ConfigurationSection section, BlockMat private BlockMatch getBlockMatch(String blockKey) { Matcher m = BLOCK_KEY_PATTERN.matcher(blockKey); if (m.matches()) { - Material material = null; + Material material; String materialName = m.group("type"); material = Material.matchMaterial(materialName); if (material == null) { @@ -80,41 +79,15 @@ private BlockMatch getBlockMatch(String blockKey) { LogUtil.log(Level.WARNING, "Invalid key '" + blockKey + "' in levelConfig, could not lookup Material"); return null; } - byte[] dataValues = getDataValues(m.group("sub")); - return new BlockMatch(material, dataValues); + return new BlockMatch(material); } else { LogUtil.log(Level.WARNING, "Invalid key '" + blockKey + "' in levelConfig"); } return null; } - private byte[] getDataValues(String sub) { - if (sub == null) { - return new byte[0]; - } - if (sub.equalsIgnoreCase("*") || sub.equalsIgnoreCase("0-15")) { - return new byte[0]; - } else if (!sub.isEmpty()) { - String[] split = sub.split("-"); - if (split.length == 1) { - return new byte[]{(byte) (Integer.parseInt(split[0]) & 0x0f)}; - } else { - int min = Integer.parseInt(split[0]); - int max = Integer.parseInt(split[1]); - byte[] data = new byte[max - min + 1]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) ((min + i) & 0x0f); - } - return data; - } - } - return new byte[0]; - } - private void addDefaults(List blocks, BlockLevelConfigBuilder defaultBuilder) { BlockLevelConfigBuilder nullScore = defaultBuilder.copy().scorePerBlock(0).limit(0); blocks.add(nullScore.base(Material.AIR).build()); - blocks.add(nullScore.base(Material.LEGACY_AIR).build()); } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlWriter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlWriter.java deleted file mode 100644 index 1b983a08b..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/yml/LevelConfigYmlWriter.java +++ /dev/null @@ -1,54 +0,0 @@ -package us.talabrek.ultimateskyblock.island.level.yml; - -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.ConfigurationSection; -import us.talabrek.ultimateskyblock.island.level.BlockLevelConfig; -import us.talabrek.ultimateskyblock.island.level.BlockLevelConfigMap; - -import java.util.Comparator; -import java.util.stream.Collectors; - -public class LevelConfigYmlWriter { - - public YmlConfiguration writeToConfig(YmlConfiguration config, BlockLevelConfigMap map) { - Configuration root = config.getRoot(); - ConfigurationSection blocks = root.createSection("blocks"); - BlockLevelConfig mapDefault = map.getDefault(); - map.values().stream() - .distinct() - .filter(f -> !isDefaultValues(f, mapDefault)) - .sorted(Comparator.comparing(BlockLevelConfig::getKey)) - .forEach(e -> writeToSection(blocks.createSection(createSectionKey(e)), e, mapDefault)); - return config; - } - - private String createSectionKey(BlockLevelConfig e) { - return e.getKey().toString(); - } - - private static boolean isDefaultValues(BlockLevelConfig c1, BlockLevelConfig c2) { - return c1.getLimit() == c2.getLimit() - && c1.getScorePerBlock() == c2.getScorePerBlock() - && c1.getDiminishingReturns() == c2.getDiminishingReturns() - && c1.getNegativeReturns() == c2.getNegativeReturns(); - } - - private void writeToSection(ConfigurationSection section, BlockLevelConfig config, BlockLevelConfig mapDefault) { - if (!config.getAdditionalBlocks().isEmpty()) { - section.set("additionalBlocks", config.getAdditionalBlocks().stream().distinct().map(m -> m.toString()).collect(Collectors.toList())); - } - if (config.getScorePerBlock() >= 0 && config.getScorePerBlock() != mapDefault.getScorePerBlock()) { - section.set("score", config.getScorePerBlock()); - } - if (config.getLimit() >= 0 && config.getLimit() != mapDefault.getLimit()) { - section.set("limit", config.getLimit()); - } - if (config.getDiminishingReturns() > 0 && config.getLimit() != mapDefault.getDiminishingReturns()) { - section.set("diminishingReturns", config.getDiminishingReturns()); - } - if (config.getNegativeReturns() > 0 && config.getLimit() != mapDefault.getNegativeReturns()) { - section.set("negativeReturns", config.getNegativeReturns()); - } - } -} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMapTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMapTest.java index 7c328fd0d..baa28dca3 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMapTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfigMapTest.java @@ -18,11 +18,10 @@ public void get() { collection.add(defaultBuilder.copy().base(Material.AIR).scorePerBlock(0).build()); collection.add(defaultBuilder.copy().base(Material.STONE).scorePerBlock(12).build()); collection.add(defaultBuilder.copy().base(Material.OAK_WOOD).scorePerBlock(9) - .additionalBlocks(new BlockMatch(Material.OAK_LOG, new byte[] {0,1,2,3,4})) + .additionalBlocks(new BlockMatch(Material.OAK_LOG)) .build()); BlockLevelConfigMap map = new BlockLevelConfigMap(collection, defaultBuilder); assertThat(map.get(Material.AIR).getScorePerBlock(), is(0d)); - assertThat(map.get(Material.AIR, (byte) 1).getScorePerBlock(), is(0d)); } -} \ No newline at end of file +} From 79dcfdf25bb8bfab6a275feaa2e132422643d5a0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 28 Dec 2021 16:49:46 +0000 Subject: [PATCH 095/190] Bump README dependencies --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b73a6219d..1734afba9 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ We are on [Spigot](https://www.spigotmc.org/resources/uskyblock-revived.66795/). This version depends on the following plugins: -* Spigot/Paper 1.17-R0.1-SNAPSHOT +* Spigot/Paper 1.18.1-R0.1-SNAPSHOT * Vault 1.7.x -* WorldEdit 7.1.0-SNAPSHOT -* WorldGuard 7.0.2-SNAPSHOT +* WorldEdit 7.2.8 +* WorldGuard 7.0.6 ## Releases [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/rlf/uSkyBlock.svg)](http://isitmaintained.com/project/rlf/uSkyBlock "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/rlf/uSkyBlock.svg)](http://isitmaintained.com/project/rlf/uSkyBlock "Percentage of issues still open") From f21abb6b2810d8264f645ab6a5002096438ed103 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 28 Dec 2021 16:55:58 +0000 Subject: [PATCH 096/190] Remove Travis-related files --- .travis.yml | 38 ------------------------- deploy_rsa.enc | Bin 3392 -> 0 bytes scripts/deploy-117.sh | 14 ---------- scripts/deploy-release.sh | 57 -------------------------------------- scripts/deploy-staging.sh | 57 -------------------------------------- 5 files changed, 166 deletions(-) delete mode 100644 .travis.yml delete mode 100644 deploy_rsa.enc delete mode 100644 scripts/deploy-117.sh delete mode 100644 scripts/deploy-release.sh delete mode 100644 scripts/deploy-staging.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1700848b6..000000000 --- a/.travis.yml +++ /dev/null @@ -1,38 +0,0 @@ -language: java -jdk: -- openjdk17 -dist: focal -sudo: false -cache: - directories: - - "$HOME/.m2" -git: - submodules: false -notifications: - email: false -before_install: -- sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules -- git submodule update --init --recursive -- cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - -- cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - -install: -- mvn -nsu -Dtravis.buildNumber=${TRAVIS_BUILD_NUMBER} -Pi18n clean deploy -before_deploy: - - openssl aes-256-cbc -K $encrypted_a65247dffca0_key -iv $encrypted_a65247dffca0_iv - -in deploy_rsa.enc -out ./deploy_rsa -d - - eval "$(ssh-agent -s)" - - chmod 600 deploy_rsa - - ssh-add deploy_rsa - - chmod +x scripts/deploy-staging.sh - - chmod +x scripts/deploy-release.sh -deploy: - - provider: script - skip_cleanup: true - script: bash scripts/deploy-staging.sh - on: - branch: "master" - - provider: script - skip_cleanup: true - script: bash scripts/deploy-release.sh - on: - tags: true diff --git a/deploy_rsa.enc b/deploy_rsa.enc deleted file mode 100644 index 487019aab865e0970a8c3d00bff2140d5fb8d8e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3392 zcmV-G4ZrdNEXTIL-RNq%Hr1-3X(7_!5$Z5P?1B6RH+V;LadIcgf5!RM5!LSArzk*@ zFTluo6PV0s+Q+(|suzi8-2bFIdUC>s|70cCR#xs|ksp2fNuBmDh0acWcAIMfg~FPz^k*N8YV4p6UeZ`E<Oeten$gITff+xpBt~217iZYwdrLbX! zEc+#%>5N3a%M@jntEOY=5u!?!ag%*9uMyZxUzF=(j6!i8&p01r;d_Ylz2+`RuAIM3Os9 zVF1aqsvJ=P19UCqMSGuT=5z{7&rzJ{s#ciS&9K6b#G^+WLv`)C@` zy0O1SSlh5XOQO4m88C+(k!LqcCUc>O@XY9FiLQNhTIk;; z-}i1&%n?!`HuMeeHw{EaxuRTC)CFyYpjeO9Saz?kymbxKYL&E}LBMeOz-5jQZ#k${w-p&9rXCPy zBaH4CV4eNJp#tac@6F-b>%+`$%}@<%K^y{4sx0{XCReDg36p@~e3&~ZW&A!mHPr4o z?@rwCI-?gYvV~49Y|d&}`yy@vs7JZUcThz|un(J3f}eQN5%HSv_uW zuFZQPALb9R{2pJI>2+bM^V64_+%Z#puLd#&I3D5JmsH?X*`fntz3iF|m*p0o!|#65 z>@AbgImzZ|C@Zbk+lsUxc4a!>vSb#-VPXf0u-L$28$ZYF%|V= z-Sf&Yv6w1%{v@a7tV~Z%u|+g>LW;BKitz%Vf9BHbtJh*YDN3cMXB?9mP}1+YcVWkZ zoe?v?N{(wFpWg!!6pDzMjO2(eoNzC1pibn$aFfd20mk3^$`|&Kq%8Gu~?aABjcIHqElVZ|~ zJ0vfNQ8tQkJ0evY;P3%)+1k*%KV;j}!LlnS)3NaH@1?=zD=r-5_!5Gh@P}XBF-GcA z8T7L9`9r`<*1tk+?4{0Ruu}pXm|*i!&;L8j>G)UDYwa(=@WFOXFuAX-p+UjBW08<6 zIcilBA@biK_E5@L3>1#TrSQJjr)yxFFs67P-Ei%KXJR>Lep(|6pI~77<3xlQijNFV zI`qows0NIRw_&pxziWHri`B`X);lM$1GzDr@^Z>pt9v88!mH(?fRd@+*P+jIm_9k9 z*9NK8GO_4`8+Nk@)6~Ev8Nd1Ay%THWj@SQ*jh*#ON1g>jm5?c^Q#O6%{=~@gmN6ex zAVb}BxTWqe8)=*#)&K>*0t0n0p=6yrL;=ztYV(BI70$hTzS8VFuE5cAz#Ia_o&hRU z#k4)0kYHpZI08{s9wdt3d!n?%ksa^5RL<(P&10B-YWLAFmOzT)@up%Ie`X&$2|dbH zj*XdsjGG_g9GC>;r5Oh;SA&3)Wba}ou2?y!(1@D8549k8luTDQ)a*?IroxHRtr^?+ z#-PtU_(m#-Bb0ftDq-ZX`4%l3O942VwZmA~YoVet@2{`H*LYDnC@`#-qk*6t5+xus zE{pIj77~&-y#%Uyv)$pd?ec|OvD!Gr$8-~2V6Hz7TYx^DQ~suK!US^$;7Av<-tYZUt!xjYlH z88%6$PlPur?+uwN=`70W=-*i7{8%fivumiuOjh{!LlL*pM~iSDHkBz+lSxPTAwS{?_tvD>>%ZtdUIPqTV8_GjBgc#aH5 zzo0lWSU`#cJOi4V*r-QG%FzkK^7mAZk`b@Th>BZpDf8sR)4H`+L2#6y%8>o% zt_}$v$bPKN5r)Ii7npY2k8xe?c=Q-;rtDb%HfSZ3XjAr8_nWjbe?(a;$LIksiU~Pr zbKsU;zfnwJ2(YvnP&Ra6&;;Or>3jg2*9ijlDJ!V8s1i3Vbd-~Dn1pjOMQ49xf<-0} zEc~`I5x2@SSUd4q^ULJ#kmm*VVmn-bP>{StoLYbC%$ zuG@)sbFsR7jThEr2HpN;w4dfW5+7^JFj?+7-q&}!^{h+a zK75k7oeWPpga+>XC+tR6d}5+0VdbuZd9`iblEYXu%+cDod}U znOe&1z@_kx)3_cp?GD)o%H}Hid7~3?j;dW}gAJZ|=Bq2XTB_iKKcrc=$fnV$NE8Gsh@0~TwOu)}ci=P=UBsBtx`1fr(=c)_P zU9D;iHo-5}m<5)6XAU_Hmu46zRh|_hXq-fCa*1}7!cv5RChPk=5Et}YoS*?&2<5y- zVWRMe>(5HF=Ss)7$tUkvAe+53IU10hz{VX}na!g3+?&?nw!w@h1^w+t%-=9{9o4Um z{9Tm|Q{)O@jdqXZGyX;e%mK|4*0a;Nmy^qqUJO_4G-hKS_ZM8E$sk+E2!$o7I|(Xh zv{_@Z&iuG)8glE+u)s#N+@Z!T>hT|eQiiRihQW%)jsz6(mfDQ$>P>J#uh;UF_xYuu z5uH+G%`Sro;h;;J-W zK%wJO3sKnpU4JJu%OgNh%KA3mdWip83!0-z`MBgxjA6-!b3Arb!; zTcbGa=isiKagL&p+HK4=DL=qL?Nj6gcyb{I=FKB9Njm*6@UsyQc5NGOtocrNeA#=s z)9`_G6jbrADP*U z{9$^l?**jkC%e*-_goW2Q3@+fB$OI)hff@!kY3b}Jl&b0BR2Mzz;YXp{SWM^j9by< z#llCbc#@EpfoJy6I8p@KI9+y)8FxY!*PrrKnc~4$9z0&7UNzcdqN2G5R$`diMhPzN zCdmqga!Elp#p*C$(~~EoqJCMCS-MQ-yf8FMPX=5l(?JeTvK&t%blCU9k`$6Kvd1gi zp@pVq@)WD@>drDN91V~8vkitexqPC{xGm2xV*|7Q-oGrm>61?y?PKDBjH9Tno8WK< ze>weG!FLcm*10F=d|;Kc(7o`%brf9q{WQM$KaiRS;8zi>YqoGx6mwh_M|*N$F0T!U26yq~N5}l98Gt4$sI2}d5$b%A WwdT#TyKRkpj89SbtnOITr!##~G`@}i diff --git a/scripts/deploy-117.sh b/scripts/deploy-117.sh deleted file mode 100644 index 5223828fe..000000000 --- a/scripts/deploy-117.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then - - echo -e "Running 1.17 test release script...\n" - cd $HOME - - echo -e "Publishing final plugin release...\n" - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ - travis@travis.internetpolice.eu:WWW-USB/downloads/testbuilds/1.17/ - -fi diff --git a/scripts/deploy-release.sh b/scripts/deploy-release.sh deleted file mode 100644 index 02235caf8..000000000 --- a/scripts/deploy-release.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then - - echo -e "Running release script...\n" - echo -e "Publishing javadocs and artifacts...\n" - cd $HOME - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - echo -e "Publishing javadocs...\n" - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/release/po-utils/ - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-API/ - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-Core/ - - echo -e "Publishing final plugin release...\n" - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ - travis@travis.internetpolice.eu:WWW-USB/downloads/release/uSkyBlock/ - -fi diff --git a/scripts/deploy-staging.sh b/scripts/deploy-staging.sh deleted file mode 100644 index d415b97d2..000000000 --- a/scripts/deploy-staging.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env bash - -if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then - - echo -e "Running staging script...\n" - echo -e "Publishing javadocs and artifacts...\n" - cd $HOME - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/po-utils/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ - travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - - echo -e "Publishing javadocs...\n" - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/po-utils/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/master/po-utils/ - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ - - rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ - travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ - - echo -e "Publishing final plugin release...\n" - - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ - $HOME/build/uskyblock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ - travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ - -fi From f5b676ce238d0f2f4dc11fd9d63cb789c45cefcf Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 31 Dec 2021 11:02:41 +0000 Subject: [PATCH 097/190] Remove Wolfwork, Name2UUID importers --- .../imports/USBImporterExecutor.java | 4 - .../imports/name2uuid/Name2UUIDImporter.java | 335 ---------------- .../imports/wolfwork/PlayerInfo.java | 361 ------------------ .../wolfwork/SerializableLocation.java | 31 -- .../wolfwork/WolfWorkObjectInputStream.java | 22 -- .../imports/wolfwork/WolfWorkUSBImporter.java | 168 -------- .../imports/wolfwork/PlayerInfoTest.java | 23 -- 7 files changed, 944 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/name2uuid/Name2UUIDImporter.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfo.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/SerializableLocation.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkObjectInputStream.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java delete mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfoTest.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java index bb3e34e75..7afa135ed 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java @@ -5,9 +5,7 @@ import org.bukkit.command.CommandSender; import us.talabrek.ultimateskyblock.imports.challenges.ConfigPre113Importer; import us.talabrek.ultimateskyblock.imports.fixuuidleader.UUIDLeaderImporter; -import us.talabrek.ultimateskyblock.imports.name2uuid.Name2UUIDImporter; import us.talabrek.ultimateskyblock.imports.update.USBUpdateImporter; -import us.talabrek.ultimateskyblock.imports.wolfwork.WolfWorkUSBImporter; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.ProgressTracker; @@ -52,10 +50,8 @@ public List getImporterNames() { private List getImporters() { if (importers == null) { importers = new ArrayList<>(); - importers.add(new WolfWorkUSBImporter()); importers.add(new UUIDLeaderImporter()); importers.add(new USBUpdateImporter()); - importers.add(new Name2UUIDImporter()); importers.add(new ConfigPre113Importer()); ServiceLoader serviceLoader = ServiceLoader.load(USBImporter.class, getClass().getClassLoader()); for (Iterator it = serviceLoader.iterator(); it.hasNext(); ) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/name2uuid/Name2UUIDImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/name2uuid/Name2UUIDImporter.java deleted file mode 100644 index d67a8329f..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/name2uuid/Name2UUIDImporter.java +++ /dev/null @@ -1,335 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.name2uuid; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.Bukkit; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; -import us.talabrek.ultimateskyblock.imports.USBImporter; -import us.talabrek.ultimateskyblock.mojang.MojangAPI; -import us.talabrek.ultimateskyblock.mojang.NameUUIDConsumer; -import us.talabrek.ultimateskyblock.mojang.ProgressCallback; -import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.ProgressTracker; -import dk.lockfuglsang.minecraft.util.TimeUtil; -import us.talabrek.ultimateskyblock.util.UUIDUtil; -import us.talabrek.ultimateskyblock.uuid.PlayerDB; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.logging.FileHandler; -import java.util.logging.Formatter; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -/** - * Converts from name-based files to UUID based. - */ -public class Name2UUIDImporter implements USBImporter { - - private Logger log; - - public static final FilenameFilter YML_FILES = new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - // Don't include UUID converted files - return name != null && name.endsWith(".yml") && !name.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}.yml"); - } - }; - - private uSkyBlock plugin; - private FileHandler handler; - private PlayerDB playerDB; - private File[] playerFiles; - private File playerErrorFolder; - private File islandErrorFolder; - private Set invalidNames = new HashSet<>(); - - @Override - public String getName() { - return "name2uuid"; - } - - @Override - public void init(uSkyBlock plugin) { - this.plugin = plugin; - playerDB = plugin.getPlayerDB(); - plugin.setMaintenanceMode(true); - log = plugin.getLogger(); - try { - if (handler == null) { - handler = new FileHandler(plugin.getDataFolder() + File.separator + "name2uuid-report.log", true); - handler.setFormatter(new SingleLineFormatter()); - } else { - log.removeHandler(handler); - } - log.addHandler(handler); - log.setUseParentHandlers(false); - } catch (IOException e) { - log.severe("Unable to create file-logging to a report.log file"); - } - log.info("==================================="); - log.info("=== Running name2uuid importer"); - log.info("==================================="); - } - - @Override - public Boolean importFile(File file) { - if (file.getParentFile().getName().equalsIgnoreCase("players")) { - return importPlayer(file); - } else if (file.getParentFile().getName().equalsIgnoreCase("islands")){ - return importIsland(file); - } else if (file.getName().equalsIgnoreCase("uuid2name.yml")) { - return importPlayerDB(); - } - return null; - } - - private Boolean importPlayerDB() { - final long tStart = System.currentTimeMillis(); - double progressEveryPct = plugin.getConfig().getDouble("importer.progressEveryPct", 10); - long progressEveryMs = plugin.getConfig().getLong("importer.progressEveryMs", 30000); - - List names = new ArrayList<>(); - for (File f : playerFiles) { - names.add(FileUtil.getBasename(f)); - } - final PlayerDB playerDB = plugin.getPlayerDB(); - Bukkit.getConsoleSender().sendMessage(tr("\u00a77PlayerDB: Filtering {0} players from uuid2name.yml", names.size())); - ProgressTracker dbtracker = new ProgressTracker(Bukkit.getConsoleSender(), - marktr("\u00a77 - {0,number,##}% ({1}/{2}) ~ {3}"), - progressEveryPct, progressEveryMs); - int cnt = 0; - int total = names.size(); - for (Iterator it = names.iterator(); it.hasNext(); ) { - String name = it.next(); - if (playerDB.getUUIDFromName(name, false) != null) { - cnt++; - it.remove(); - } - if (cnt % 20 == 0) { - dbtracker.progressUpdate(cnt, total, TimeUtil.millisAsString(System.currentTimeMillis()-tStart)); - } - } - Bukkit.getConsoleSender().sendMessage(tr("\u00a77PlayerDB: Filtered {0} names", cnt)); - - final ProgressTracker tracker = new ProgressTracker(Bukkit.getConsoleSender(), - marktr("\u00a77 - MojangAPI:{4}: {0,number,##}% ({1}/{2}, failed:{3} ~ {5,number,##}%), {6}"), - progressEveryPct, progressEveryMs); - MojangAPI mojangAPI = new MojangAPI(); - Bukkit.getConsoleSender().sendMessage(tr("\u00a77MojangAPI: Trying to fetch {0} players from Mojang", names.size())); - - // This call blocks - good thing we are in Async mode - mojangAPI.fetchUUIDs(names, new NameUUIDConsumer() { - @Override - public void success(Map names) { - for (Map.Entry entry : names.entrySet()) { - playerDB.updatePlayer(entry.getValue(), entry.getKey(), null); - } - } - - @Override - public void renamed(String oldName, String newName, UUID id) { - playerDB.updatePlayer(id, oldName, null); - playerDB.updatePlayer(id, newName, null); - } - - @Override - public void unknown(List unknownNames) { - invalidNames.addAll(unknownNames); - } - }, new ProgressCallback() { - @Override - public void progress(int progress, int failed, int total, String message) { - tracker.progressUpdate(progress, total, failed, message, - 100f*failed/(progress > 0 ? progress : 1), TimeUtil.millisAsString(System.currentTimeMillis()-tStart)); - } - - @Override - public void complete(boolean success) { - Bukkit.getConsoleSender().sendMessage(tr("\u00a77 - MojangAPI:\u00a7aCOMPLETED: {0}", success ? tr("SUCCESS") : tr("FAILED"))); - } - - @Override - public void error(String message) { - Bukkit.getConsoleSender().sendMessage(tr("\u00a77 - MojangAPI:\u00a7cERROR: {0}", message)); - } - }); - return true; - } - - private Boolean importPlayer(File file) { - log.info("Importing " + file); - String name = FileUtil.getBasename(file); - FileConfiguration config = new YamlConfiguration(); - FileUtil.readConfig(config, file); - UUID uniqueId; - if (invalidNames.contains(name)) { - uniqueId = UUIDUtil.fromString(config.getString("player.uuid", null)); - if (uniqueId != null) { - invalidNames.remove(name); - playerDB.updatePlayer(uniqueId, name, null); - } - } else { - uniqueId = playerDB.getUUIDFromName(name); - } - if (uniqueId == null) { - log.info("No UUID found for " + name); - file.renameTo(new File(playerErrorFolder, file.getName())); - return false; - } - File newConfig = new File(plugin.getDataFolder() + File.separator + "players", uniqueId.toString() + ".yml"); - if (file.renameTo(newConfig)) { - FileUtil.readConfig(config, newConfig); - config.set("player.name", name); - config.set("player.uuid", UUIDUtil.asString(uniqueId)); - try { - config.save(newConfig); - if (!newConfig.getName().equals(file.getName())) { - if (file.exists() && !file.delete()) { - file.deleteOnExit(); - } - } - return true; - } catch (IOException e) { - log.log(Level.SEVERE, "Failed!", e); - return false; - } - } else if (newConfig.exists()) { - log.info("Unable to move " + file + " to " + newConfig + " since it already exists!"); - file.renameTo(new File(newConfig.getParent(), newConfig.getName() + ".old")); - } - return false; - } - - private Boolean importIsland(File file) { - log.info("Importing " + file); - FileConfiguration config = new YamlConfiguration(); - FileUtil.readConfig(config, file); - if (config.getInt("version", 0) >= 3) { - log.info("- island already converted, version is " + config.getInt("version")); - return null; - } - if (config.contains("party.leader")) { - String leaderName = config.getString("party.leader", null); - if (invalidNames.contains(leaderName)) { - log.info("Island leader had no UUID, removing island " + file); - file.renameTo(new File(islandErrorFolder, file.getName())); - String islandName = FileUtil.getBasename(file); - plugin.getOrphanLogic().addOrphan(islandName); - WorldGuardHandler.removeIslandRegion(islandName); - return false; - } - config.set("party.leader-uuid", getUUIDString(leaderName)); - } - ConfigurationSection members = config.getConfigurationSection("party.members"); - if (members != null) { - for (String member : members.getKeys(false)) { - ConfigurationSection section = members.getConfigurationSection(member); - members.set(member, null); - String uuid = getUUIDString(member); - if (uuid != null) { - members.createSection(uuid, section.getValues(true)); - members.set(uuid + ".name", member); - } - } - } - List bans = config.getStringList("banned.list"); - List newBans = new ArrayList<>(); - for (String name : bans) { - String uuid = getUUIDString(name); - if (uuid != null) { - newBans.add(uuid); - } - } - config.set("banned.list", newBans); - List trusts = config.getStringList("trust.list"); - List newTrusts = new ArrayList<>(); - for (String name : trusts) { - String uuid = getUUIDString(name); - if (uuid != null) { - newTrusts.add(uuid); - } - } - config.set("trust.list", newTrusts); - config.set("version", 3); - try { - config.save(file); - return true; - } catch (IOException e) { - log.log(Level.SEVERE, "Failed to import " + file, e); - return false; - } - } - - @Override - public File[] getFiles() { - File playerFolder = new File(plugin.getDataFolder(), "players"); - playerErrorFolder = new File(playerFolder, "errors"); - if (!playerErrorFolder.exists()) { - playerErrorFolder.mkdirs(); - } - playerFiles = playerFolder.listFiles(YML_FILES); - File islandFolder = new File(plugin.getDataFolder(), "islands"); - islandErrorFolder = new File(islandFolder, "errors"); - if (!islandErrorFolder.exists()) { - islandErrorFolder.mkdirs(); - } - File[] islandFiles = islandFolder.listFiles(YML_FILES); - File[] files = new File[islandFiles.length + playerFiles.length + 1]; - files[0] = new File(plugin.getDataFolder(), "uuid2name.yml"); - System.arraycopy(playerFiles, 0, files, 1, playerFiles.length); - System.arraycopy(islandFiles, 0, files, playerFiles.length+1, islandFiles.length); - return files; - } - - @Override - public void completed(int success, int failed, int skipped) { - if (handler != null) { - handler.close(); - log.removeHandler(handler); - log.setUseParentHandlers(true); - } - plugin.setMaintenanceMode(false); - } - - private String getUUIDString(String name) { - return invalidNames.contains(name) ? null : UUIDUtil.asString(getUUID(name)); - } - - private UUID getUUID(String playerName) { - return playerDB.getUUIDFromName(playerName); - } - - public static class SingleLineFormatter extends Formatter { - @Override - public String format(LogRecord record) { - try { - return String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %2$5s : %3$s\n", - new Date(record.getMillis()), - record.getLevel().getName(), - record.getMessage()); - } catch (IllegalArgumentException e) { - return String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %2$s : %3$s\n", - new Date(record.getMillis()), - record.getLevel().getName(), - MessageFormat.format(record.getMessage(), record.getParameters())); - } - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfo.java deleted file mode 100644 index 9c5bbb9d3..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfo.java +++ /dev/null @@ -1,361 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.wolfwork; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * Mirror of the PlayerInfo in wolfwork/uSkyBlock - */ -public class PlayerInfo implements Serializable { - private static final long serialVersionUID = 1L; - private String playerName; - private boolean hasIsland; - private boolean hasParty; - private boolean warpActive; - private List members; - private List banned; - private String partyLeader; - private String partyIslandLocation; - private String islandLocation; - private String homeLocation; - private String warpLocation; - private String deathWorld; - private HashMap challengeList; - private float islandExp; - private int islandLevel; - - public PlayerInfo(final String playerName) { - this.playerName = playerName; - members = new ArrayList(); - banned = new ArrayList(); - hasIsland = false; - warpActive = false; - islandLocation = null; - homeLocation = null; - warpLocation = null; - deathWorld = null; - hasParty = false; - partyLeader = null; - partyIslandLocation = null; - islandExp = 0.0F; - challengeList = new HashMap(); - islandLevel = 0; - } - - public void startNewIsland(Location l) { - hasIsland = true; - setIslandLocation(l); - islandLevel = 0; - islandExp = 0.0F; - partyIslandLocation = null; - partyLeader = null; - hasParty = false; - homeLocation = null; - warpLocation = null; - warpActive = false; - members = new ArrayList(); - } - - public void removeFromIsland() { - hasIsland = false; - setIslandLocation(null); - islandLevel = 0; - islandExp = 0.0F; - partyIslandLocation = null; - partyLeader = null; - hasParty = false; - homeLocation = null; - warpLocation = null; - warpActive = false; - members = new ArrayList(); - } - - public void toggleWarpActive() { - if (!this.warpActive) - warpActive = true; - else - warpActive = false; - } - - public void warpOn() { - warpActive = true; - } - - public void warpOff() { - warpActive = true; - } - - public boolean isWarpActive() { - return warpActive; - } - - public void setWarpLocation(Location l) { - warpLocation = getStringLocation(l); - } - - public Location getWarpLocation() { - return getLocationString(warpLocation); - } - - public List getBanned() { - if (banned == null) - banned = new ArrayList(); - return banned; - } - - public void addBan(String player) { - getBanned().add(player); - } - - public void removeBan(String player) { - getBanned().remove(player); - } - - public boolean isBanned(String player) { - return getBanned().contains(player); - } - - public void addMember(final String member) { - members.add(member); - } - - public void clearChallenges() { - challengeList.clear(); - } - - public void buildChallengeList() { - // Disabled - } - - public boolean challengeExists(final String challenge) { - if (challengeList.containsKey(challenge.toLowerCase())) { - return true; - } - return false; - } - - public boolean checkChallenge(final String challenge) { - if (challengeList.containsKey(challenge.toLowerCase())) { - return challengeList.get(challenge.toLowerCase()).booleanValue(); - } - - return false; - } - - public void completeChallenge(final String challenge) { - if (challengeList.containsKey(challenge)) { - challengeList.remove(challenge); - challengeList.put(challenge, Boolean.valueOf(true)); - } - } - - public void displayChallengeList() { - // Does nothing - } - - public String getDeathWorld() { - return deathWorld; - } - - public boolean getHasIsland() { - return hasIsland; - } - - public boolean getHasParty() { - if (members == null) { - members = new ArrayList(); - } - return hasParty; - } - - public Location getHomeLocation() { - return getLocationString(homeLocation); - } - - public float getIslandExp() { - return islandExp; - } - - public int getIslandLevel() { - return islandLevel; - } - - public Location getIslandLocation() { - return getLocationString(islandLocation); - } - - private Location getLocationString(final String s) { - if (s == null || s.trim() == "") { - return null; - } - final String[] parts = s.split(":"); - if (parts.length == 4) { - final World w = Bukkit.getServer().getWorld(parts[0]); - final int x = Integer.parseInt(parts[1]); - final int y = Integer.parseInt(parts[2]); - final int z = Integer.parseInt(parts[3]); - return new Location(w, x, y, z); - } - return null; - } - - public List getMembers() { - return members; - } - - public Location getPartyIslandLocation() { - return getLocationString(partyIslandLocation); - } - - public String getPartyLeader() { - return partyLeader; - } - - public Player getPlayer() { - //noinspection deprecation - return Bukkit.getPlayerExact(playerName); - } - - public String getPlayerName() { - return playerName; - } - - private String getStringLocation(final Location l) { - if (l == null) { - return ""; - } - return l.getWorld().getName() + ":" + l.getBlockX() + ":" + l.getBlockY() + ":" + l.getBlockZ(); - } - - public void ListData() { - // Do nothing - } - - public void removeMember(final String member) { - members.remove(member); - } - - public void resetAllChallenges() { - challengeList = null; - buildChallengeList(); - } - - public void resetChallenge(final String challenge) { - if (challengeList.containsKey(challenge)) { - challengeList.remove(challenge); - challengeList.put(challenge, Boolean.valueOf(false)); - } - } - - public void setDeathWorld(final String dw) { - deathWorld = dw; - } - - public void setHasIsland(final boolean b) { - hasIsland = b; - } - - public void setHomeLocation(final Location l) { - homeLocation = getStringLocation(l); - } - - public void setIslandExp(final float i) { - islandExp = i; - } - - public void setIslandLevel(final int i) { - islandLevel = i; - } - - public void setIslandLocation(final Location l) { - islandLocation = getStringLocation(l); - } - - public void setJoinParty(final String leader, final Location l) { - hasParty = true; - partyLeader = leader; - partyIslandLocation = getStringLocation(l); - } - - public void setLeaveParty() { - hasParty = false; - partyLeader = null; - islandLevel = 0; - partyIslandLocation = null; - members = new ArrayList(); - } - - public void setMembers(final List newMembers) { - members = newMembers; - } - - public void setPartyIslandLocation(final Location l) { - partyIslandLocation = getStringLocation(l); - } - - public void setPartyLeader(final String leader) { - partyLeader = leader; - } - - public void setPlayerName(final String s) { - playerName = s; - } - - public Location getTeleportLocation() { - Location target = getHomeLocation(); - if (target == null) { - if (getIslandLocation() == null && getHasParty()) - target = getPartyIslandLocation(); - else if (getIslandLocation() != null) - target = getIslandLocation(); - } - - return target; - } - - public boolean teleportHome(Player player) { - // Do nothing - return false; - } - - public boolean teleportWarp(Player player) { - // Do nothing - return false; - } - - public void recalculateLevel(final Runnable callback) { - // Do nothing - } - - public void save() { - // Do nothing - } - - @Override - public String toString() { - return "PlayerInfo{" + - "playerName='" + playerName + '\'' + - ", hasIsland=" + hasIsland + - ", hasParty=" + hasParty + - ", warpActive=" + warpActive + - ", members=" + members + - ", banned=" + banned + - ", partyLeader='" + partyLeader + '\'' + - ", partyIslandLocation='" + partyIslandLocation + '\'' + - ", islandLocation='" + islandLocation + '\'' + - ", homeLocation='" + homeLocation + '\'' + - ", warpLocation='" + warpLocation + '\'' + - ", deathWorld='" + deathWorld + '\'' + - ", challengeList=" + challengeList + - ", islandExp=" + islandExp + - ", islandLevel=" + islandLevel + - '}'; - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/SerializableLocation.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/SerializableLocation.java deleted file mode 100644 index df576a49c..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/SerializableLocation.java +++ /dev/null @@ -1,31 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.wolfwork; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; - -import java.io.Serializable; - -public class SerializableLocation implements Serializable { - private static final long serialVersionUID = 23L; - private final String world; - private final double x; - private final double y; - private final double z; - - public SerializableLocation(final Location loc) { - x = loc.getX(); - y = loc.getY(); - z = loc.getZ(); - world = loc.getWorld().getName(); - } - - public Location getLocation() { - final World w = Bukkit.getWorld(world); - if (w == null) { - return null; - } - final Location toRet = new Location(w, x, y, z); - return toRet; - } -} \ No newline at end of file diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkObjectInputStream.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkObjectInputStream.java deleted file mode 100644 index 2677dfaa8..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkObjectInputStream.java +++ /dev/null @@ -1,22 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.wolfwork; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectStreamClass; - -public class WolfWorkObjectInputStream extends ObjectInputStream { - public WolfWorkObjectInputStream(InputStream in) throws IOException { - super(in); - } - - @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - if (desc.getName().equals("us.talabrek.ultimateskyblock.PlayerInfo")) { - return PlayerInfo.class; - } else if (desc.getName().equals("us.talabrek.ultimateskyblock.SerializableLocation")) { - return SerializableLocation.class; - } - return super.resolveClass(desc); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java deleted file mode 100644 index e0947d183..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/wolfwork/WolfWorkUSBImporter.java +++ /dev/null @@ -1,168 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.wolfwork; - -import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; -import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; -import us.talabrek.ultimateskyblock.imports.USBImporter; -import us.talabrek.ultimateskyblock.island.IslandInfo; -import us.talabrek.ultimateskyblock.uSkyBlock; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Stack; -import java.util.logging.Level; - -import static us.talabrek.ultimateskyblock.util.LogUtil.log; - -/** - * An importer for the wolfwork branch. - */ -public class WolfWorkUSBImporter implements USBImporter { - - private uSkyBlock plugin; - - @Override - public String getName() { - return "wolfwork"; - } - - @Override - public void init(uSkyBlock plugin) { - this.plugin = plugin; - } - - @Override - public Boolean importFile(File file) { - try { - if (file != null && file.getName().equals("orphanedIslands.bin")) { - if (file.exists()) { - importOrphanedIslands(plugin, file); - return true; - } - return false; - } - PlayerInfo playerInfo = readPlayerInfo(file); - if (playerInfo == null) { - return false; - } - us.talabrek.ultimateskyblock.player.PlayerInfo pi = importPlayerInfo(plugin, playerInfo); - importIsland(plugin, playerInfo, pi); - plugin.getPlayerLogic().removeActivePlayer(pi); - if (!file.delete()) { - file.deleteOnExit(); - } - return true; - } catch (Exception e) { - log(Level.WARNING, "Unable to import " + file, e); - return false; - } - } - - private int importOrphanedIslands(uSkyBlock plugin, File orphanFile) { - try (ObjectInputStream in = new WolfWorkObjectInputStream(new FileInputStream(orphanFile))) { - Object stackObj = in.readObject(); - if (stackObj instanceof Stack) { - int countOrphan = 0; - Stack stack = (Stack) stackObj; - while (!stack.isEmpty()) { - SerializableLocation remove = stack.remove(0); - plugin.getOrphanLogic().addOrphan(remove.getLocation()); - countOrphan++; - } - if (!orphanFile.delete()) { - orphanFile.deleteOnExit(); - } - return countOrphan; - } - } catch (IOException | ClassNotFoundException e) { - log(Level.WARNING, "Unable to read the orphanedIslands.bin file", e); - } - return 0; - } - - private us.talabrek.ultimateskyblock.player.PlayerInfo importPlayerInfo(uSkyBlock plugin, PlayerInfo playerInfo) { - // Copy PlayerInfo - us.talabrek.ultimateskyblock.player.PlayerInfo pi = plugin.getPlayerInfo(playerInfo.getPlayerName()); - if (playerInfo.getIslandLocation() != null) { - pi.setIslandLocation(playerInfo.getIslandLocation()); - } else if (playerInfo.getPartyIslandLocation() != null) { - pi.setIslandLocation(playerInfo.getPartyIslandLocation()); - } - pi.setHomeLocation(playerInfo.getHomeLocation()); - // Challenges - long now = System.currentTimeMillis(); - for (us.talabrek.ultimateskyblock.api.ChallengeCompletion challengeApi : pi.getChallenges()) { - if (challengeApi instanceof ChallengeCompletion) { - ChallengeCompletion challenge = (ChallengeCompletion) challengeApi; - if (playerInfo.checkChallenge(challenge.getName())) { - challenge.setCooldownUntil(now); - challenge.setTimesCompleted(1); - } else { - challenge.setTimesCompleted(0); - } - } - } - pi.save(); - return pi; - } - - private void importIsland(uSkyBlock plugin, PlayerInfo playerInfo, us.talabrek.ultimateskyblock.player.PlayerInfo pi) { - // Copy IslandInfo - IslandInfo islandInfo = plugin.getIslandInfo(pi); - if (islandInfo != null) { - if (playerInfo.getPartyLeader() != null) { - islandInfo.setupPartyLeader(playerInfo.getPartyLeader()); - } else { - islandInfo.setupPartyLeader(playerInfo.getPlayerName()); - } - for (String member : playerInfo.getMembers()) { - islandInfo.setupPartyMember(uSkyBlock.getInstance().getPlayerInfo(member)); - } - islandInfo.setWarp(playerInfo.isWarpActive()); - islandInfo.setWarpLocation(playerInfo.getWarpLocation()); - for (String banned : playerInfo.getBanned()) { - islandInfo.banPlayer(plugin.getPlayerDB().getUUIDFromName(banned)); - } - // Not really that important - since it's most likely different! - islandInfo.setLevel(playerInfo.getIslandLevel()); - islandInfo.setBiome(Settings.general_defaultBiome); - islandInfo.save(); - WorldGuardHandler.updateRegion(islandInfo); - } - } - - private PlayerInfo readPlayerInfo(File playerFile) { - try (ObjectInputStream in = new WolfWorkObjectInputStream(new FileInputStream(playerFile))) { - Object o = in.readObject(); - if (o instanceof PlayerInfo) { - return (PlayerInfo) o; - } - } catch (ClassNotFoundException|IOException e) { - // Ignore... - } - return null; - } - - @Override - public File[] getFiles() { - ArrayList fileList = new ArrayList<>(); - fileList.add(new File(plugin.getDataFolder(), "orphanedIslands.bin")); - fileList.addAll(Arrays.asList(plugin.directoryPlayers.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name != null && !name.endsWith(".yml"); - } - }))); - return fileList.toArray(new File[fileList.size()]); - } - - @Override - public void completed(int success, int failed, int skipped) { - // Do nothing - } -} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfoTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfoTest.java deleted file mode 100644 index 236a9951e..000000000 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/wolfwork/PlayerInfoTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.wolfwork; - -import org.junit.Test; - -import java.io.ObjectInputStream; - -import static org.hamcrest.core.IsNull.notNullValue; -import static org.junit.Assert.assertThat; - -public class PlayerInfoTest { - - @Test - public void testDeserialization() throws Exception { - for (String playerName : new String[]{"Block_Busta_7", "Moctezuma309", "solukkajr", - "xFreakyPVPx", "matt9959", "xXMasterOfPvpXx", "pi4music"}) { - try (ObjectInputStream in = new WolfWorkObjectInputStream(getClass().getClassLoader().getResourceAsStream(playerName))) { - final PlayerInfo p = (PlayerInfo) in.readObject(); - assertThat(p, notNullValue()); - System.out.println(p); - } - } - } -} \ No newline at end of file From 231271114964c2e770c2c54b9b1254bfb8f04cd3 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 31 Dec 2021 11:13:39 +0000 Subject: [PATCH 098/190] Remove pre-1.13 config importer -- if anyone ever needs to upgrade from a pre-1.13 release, use USB 2.10.0 (MC 1.17) as intermediate step --- uSkyBlock-AWE370/pom.xml | 6 + .../imports/USBImporterExecutor.java | 23 +- .../challenges/ConfigPre113Importer.java | 197 ------------------ .../challenges/ConfigPre113ImporterTest.java | 58 ------ 4 files changed, 13 insertions(+), 271 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113Importer.java delete mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113ImporterTest.java diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 3cd0edd4e..fcc057f41 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -16,6 +16,12 @@ AsyncWorldEdit-API [2.2.0-rc-01, 2.2.0) jar + + + com.sk89q.worldedit + * + + uSkyBlock diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java index 7afa135ed..176196686 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java @@ -3,7 +3,6 @@ import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import us.talabrek.ultimateskyblock.imports.challenges.ConfigPre113Importer; import us.talabrek.ultimateskyblock.imports.fixuuidleader.UUIDLeaderImporter; import us.talabrek.ultimateskyblock.imports.update.USBUpdateImporter; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -11,7 +10,6 @@ import java.io.File; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; import java.util.logging.Level; @@ -52,10 +50,9 @@ private List getImporters() { importers = new ArrayList<>(); importers.add(new UUIDLeaderImporter()); importers.add(new USBUpdateImporter()); - importers.add(new ConfigPre113Importer()); - ServiceLoader serviceLoader = ServiceLoader.load(USBImporter.class, getClass().getClassLoader()); - for (Iterator it = serviceLoader.iterator(); it.hasNext(); ) { - importers.add(it.next()); + ServiceLoader serviceLoader = ServiceLoader.load(USBImporter.class, getClass().getClassLoader()); + for (USBImporter usbImporter : serviceLoader) { + importers.add(usbImporter); } } return importers; @@ -79,12 +76,7 @@ public void importUSB(final CommandSender sender, String name) { sender.sendMessage(tr("\u00a74No importer named \u00a7e{0}\u00a74 found", name)); return; } - Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - doImport(sender, importer); - } - }); + Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, () -> doImport(sender, importer)); } private void doImport(CommandSender sender, USBImporter importer) { @@ -104,8 +96,7 @@ private void doImport(CommandSender sender, USBImporter importer) { private void doImport(final CommandSender sender, final USBImporter importer, final File[] files) { try { - for (int i = 0; i < files.length; i++) { - File file = files[i]; + for (File file : files) { try { Boolean status = importer.importFile(file); if (status == null) { @@ -123,8 +114,8 @@ private void doImport(final CommandSender sender, final USBImporter importer, fi log(Level.WARNING, "Could not import file " + file, t); } progressTracker.progressUpdate(countSuccess + countFailed + countSkip, files.length, - countSuccess, countFailed, countSkip, - TimeUtil.millisAsString(System.currentTimeMillis()-tStart)); + countSuccess, countFailed, countSkip, + TimeUtil.millisAsString(System.currentTimeMillis() - tStart)); } } finally { complete(sender, importer); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113Importer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113Importer.java deleted file mode 100644 index 0c80e20f4..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113Importer.java +++ /dev/null @@ -1,197 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.challenges; - -import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.imports.USBImporter; -import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.LogUtil; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static dk.lockfuglsang.minecraft.file.FileUtil.readConfig; - -public class ConfigPre113Importer implements USBImporter { - private static final Pattern REQ_PATTERN = Pattern.compile("(?(?[0-9A-Z_]+)(:(?[0-9]+))?)(?\\{.*\\})?:(?[0-9]+)(;(?[+\\-*\\^])(?[0-9]+))?"); - private static final Pattern ITEM_AMOUNT_PATTERN = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?(?(?[0-9A-Z_]+)(:(?[0-9]+))?):(?[0-9]+)\\s*(?\\{.*\\})?"); - private static final Pattern ITEM_PATTERN = Pattern.compile("(?(?[0-9A-Z_]+)(:(?[0-9]+))?)\\s*(?\\{.*\\})?"); - - private uSkyBlock plugin; - - @Override - public String getName() { - return "config-1-13"; - } - - @Override - public void init(uSkyBlock plugin) { - this.plugin = plugin; - plugin.setMaintenanceMode(true); - } - - @Override - public Boolean importFile(File file) { - FileConfiguration config = new YmlConfiguration(); - readConfig(config, file); - try { - config.save(new File(file.getParentFile(), file.getName() + ".org")); - } catch (IOException e) { - e.printStackTrace(); - } - if (file.getName().equals("challenges.yml")) { - convertChallenges(config); - } else if (file.getName().equals("config.yml")) { - config = plugin.getConfig(); - convertConfig(config); - } - - try { - config.save(file); - } catch (IOException e) { - e.printStackTrace(); - } - return true; - } - - private void convertConfig(FileConfiguration config) { - Set keys = config.getKeys(true); - // displayItems (and lockedDisplayItem) - for (String key : keys.stream().filter(f -> f.toLowerCase().endsWith("displayitem")).collect(Collectors.toList())) { - try { - config.set(key, convertItem(config.getString(key))); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert config.yml:" + key + ":" + e.getMessage()); - } - } - // chestItems - for (String key : keys.stream().filter(f -> f.endsWith(".chestItems") || f.endsWith(".extraItems")).collect(Collectors.toList())) { - try { - List value = new ArrayList<>(); - value.addAll(convertItemAmountList(config.getStringList(key))); - config.set(key, value); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert config.yml:" + key + ":" + e.getMessage()); - } - } - // extraPermissions - ConfigurationSection extraPerms = config.getConfigurationSection("options.island.extraPermissions"); - if (extraPerms != null) { - for (String key : extraPerms.getKeys(false)) { - try { - extraPerms.set(key, convertItemAmountList(extraPerms.getStringList(key))); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert config.yml:" + key + ":" + e.getMessage()); - } - } - } - } - - private void convertChallenges(FileConfiguration config) { - // Convert all requiredItems - Set keys = config.getKeys(true); - for (String key : keys.stream().filter(f -> f.endsWith(".requiredItems")).collect(Collectors.toList())) { - try { - List value = new ArrayList<>(); - value.addAll(convertRequiredItemsList(config.getStringList(key))); - config.set(key, value); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert challenges.yml:" + key + ":" + e.getMessage()); - } - } - // Rewards (.items) - for (String key : keys.stream().filter(f -> f.endsWith(".items")).collect(Collectors.toList())) { - try { - List value = new ArrayList<>(); - value.addAll(convertItemAmountList(config.getStringList(key))); - config.set(key, value); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert challenges.yml:" + key + ":" + e.getMessage()); - } - } - // displayItems (and lockedDisplayItem) - for (String key : keys.stream().filter(f -> f.toLowerCase().endsWith("displayitem")).collect(Collectors.toList())) { - try { - config.set(key, convertItem(config.getString(key))); - } catch (Exception e) { - LogUtil.log(Level.WARNING, "Unable to convert challenges.yml:" + key + ":" + e.getMessage()); - } - } - } - - private Collection convertItemAmountList(List stringList) { - List values = new ArrayList<>(); - for (String value : stringList) { - values.add(convertItemAmount(value)); - } - return values.stream().filter(f -> f != null).collect(Collectors.toList()); - } - - private Collection convertRequiredItemsList(List stringList) { - List values = new ArrayList<>(); - for (String value : stringList) { - values.add(convertRequiredItems(value)); - } - return values.stream().filter(f -> f != null).collect(Collectors.toList()); - } - - private String convertRequiredItems(String value) { - Matcher m = REQ_PATTERN.matcher(value); - if (m.matches()) { - String itemstack = m.group("itemstack"); - ItemStack itemStack = ItemStackUtil.createItemStack(itemstack); - String newItemStack = itemStack.getType().name() + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : ""); - return replaceItemStack(m, value, newItemStack); - } - return null; - } - - private String convertItemAmount(String reward) { - Matcher m = ITEM_AMOUNT_PATTERN.matcher(reward); - if (!m.matches()) { - throw new IllegalArgumentException("Unknown item: '" + reward + "'"); - } - String itemstack = m.group("itemstack"); - ItemStack itemStack = ItemStackUtil.createItemStack(itemstack); - String newItemStack = itemStack.getType().name() + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : ""); - return replaceItemStack(m, reward, newItemStack); - } - - private String convertItem(String displayItem) { - Matcher m = ITEM_PATTERN.matcher(displayItem); - if (!m.matches()) { - throw new IllegalArgumentException("Unknown displayItem: '" + displayItem + "'"); - } - String itemstack = m.group("itemstack"); - ItemStack itemStack = ItemStackUtil.createItemStack(itemstack); - String newItemStack = itemStack.getType().name() + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : ""); - return replaceItemStack(m, displayItem, newItemStack); - } - - private String replaceItemStack(Matcher m, String original, String replacement) { - return original.substring(0, m.start("itemstack")) + replacement + original.substring(m.end("itemstack")); - } - - @Override - public File[] getFiles() { - return new File[]{ - new File(plugin.getDataFolder(), "challenges.yml"), - new File(plugin.getDataFolder(), "config.yml"), - }; - } - - @Override - public void completed(int success, int failed, int skipped) { - plugin.setMaintenanceMode(false); - } -} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113ImporterTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113ImporterTest.java deleted file mode 100644 index 43550a593..000000000 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/challenges/ConfigPre113ImporterTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package us.talabrek.ultimateskyblock.imports.challenges; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.Material; -import org.bukkit.Server; -import org.bukkit.UnsafeValues; -import org.junit.BeforeClass; -import org.junit.Test; -import us.talabrek.ultimateskyblock.uSkyBlock; - -import java.io.File; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.util.logging.Logger; - -import static dk.lockfuglsang.minecraft.util.BukkitServerMock.setupServerMock; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ConfigPre113ImporterTest { - - @BeforeClass - public static void SetupAll() throws Exception { - Server server = setupServerMock(); - UnsafeValues unsafeMock = mock(UnsafeValues.class); - when(unsafeMock.fromLegacy((Material) any())).thenAnswer(a -> a.getArguments()[0]); - when(server.getUnsafe()).thenReturn(unsafeMock); - } - - @Test - public void importFile_Default_ConfigYml() throws Exception { - File configFile = File.createTempFile("config", ".dir"); - configFile.delete(); - configFile.deleteOnExit(); - configFile = new File(configFile, "config.yml"); - configFile.deleteOnExit(); - configFile.getParentFile().mkdirs(); - InputStream resourceAsStream = ConfigPre113Importer.class.getClassLoader().getResourceAsStream("config.yml"); - FileUtil.copy(resourceAsStream, configFile); - YmlConfiguration config = new YmlConfiguration(); - FileUtil.readConfig(config, configFile); - - uSkyBlock plugin = mock(uSkyBlock.class); - when(plugin.getConfig()).thenReturn(config); - when(plugin.getLogger()).thenReturn(Logger.getGlobal()); - Field instanceField = uSkyBlock.class.getDeclaredField("instance"); - instanceField.setAccessible(true); - instanceField.set(null, plugin); - instanceField.setAccessible(false); - ConfigPre113Importer sut = new ConfigPre113Importer(); - sut.init(plugin); - assertThat(sut.importFile(configFile), is(true)); - } -} \ No newline at end of file From a35a556d88e0863620d20f285199b5442e4def4b Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 1 Jan 2022 17:31:31 +0000 Subject: [PATCH 099/190] Dont try to add our SSH key when testing a PR --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffbe9b340..3a966ad53 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,12 +41,14 @@ jobs: # Install our SSH key: - name: Install SSH key uses: shimataro/ssh-key-action@v2 + if: ${{ github.event_name == 'push' }} with: key: ${{ secrets.SSH_PRIVATE_KEY }} known_hosts: ${{ secrets.SSH_KNOWN_HOST }} # Mark our scripts runnable: - name: Mark deploy scripts runnable + if: ${{ github.event_name == 'push' }} run: | chmod +x "${GITHUB_WORKSPACE}/.github/deploy-staging.sh" chmod +x "${GITHUB_WORKSPACE}/.github/deploy-release.sh" From b81bbcc41ce75bd1c27ab37bf71d889618eb3135 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 2 Jan 2022 20:56:16 +0000 Subject: [PATCH 100/190] Replace json-simple with gson, shade our own version (#31) --- pom.xml | 6 + uSkyBlock-Core/pom.xml | 24 +- .../challenge/ChallengeFactory.java | 2 +- .../challenge/EntityMatch.java | 10 +- .../ultimateskyblock/mojang/MojangAPI.java | 219 ------------------ .../mojang/NameUUIDConsumer.java | 31 --- .../mojang/ProgressCallback.java | 10 - .../ultimateskyblock/util/MetaUtil.java | 26 +-- .../ultimateskyblock/util/MetaUtilTest.java | 17 ++ 9 files changed, 58 insertions(+), 287 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/MojangAPI.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/NameUUIDConsumer.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/ProgressCallback.java create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MetaUtilTest.java diff --git a/pom.xml b/pom.xml index b0585b2d5..186cc4d83 100644 --- a/pom.xml +++ b/pom.xml @@ -10,6 +10,7 @@ 4.9.3 4.0.1 + 2.8.9 23.0.0 ${project.version} 1.25-SNAPSHOT @@ -243,6 +244,11 @@ adventure-platform-bukkit ${adventure-bukkit.version} + + com.google.code.gson + gson + ${gson.version} + diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 7ed2e2662..d4116610b 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -82,7 +82,7 @@ true - com.googlecode.json-simple:json-simple + com.google.code.gson:gson dk.lockfuglsang.minecraft:bukkit-utils io.papermc:paperlib net.kyori:* @@ -107,6 +107,10 @@ org.bstats us.talabrek.ultimateskyblock.metrics + + com.google.code.gson + us.talabrek.ultimateskyblock.gson + @@ -357,6 +361,12 @@ ${spigotapi.version} provided true + + + com.google.code.gson + gson + + @@ -432,6 +442,12 @@ 31.0.1-jre provided + + + com.google.code.gson + gson + compile + be.maximvdw MVdWPlaceholderAPI @@ -466,12 +482,6 @@ 2.6 provided - - - com.googlecode.json-simple - json-simple - 1.1.1 - org.hamcrest diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index ba7e2172e..9c70dc77a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -86,7 +86,7 @@ private static List createEntities(List requiredEntities) { int count = countStr != null ? Integer.parseInt(countStr, 10) : 1; EntityType entityType = EntityType.fromName(type); Map map = meta != null ? MetaUtil.createMap(meta.substring(1)) : new HashMap(); // skip the leading ':' - if (entityType != null && map != null) { + if (entityType != null) { entities.add(new EntityMatch(entityType, map, count)); } else { throw new IllegalArgumentException("Malformed requiredEntities: " + entityString); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java index f2eada7d0..a1629fb3d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java @@ -1,8 +1,8 @@ package us.talabrek.ultimateskyblock.challenge; +import com.google.gson.Gson; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import org.json.simple.JSONObject; import us.talabrek.ultimateskyblock.util.EntityUtil; import java.lang.reflect.Field; @@ -15,6 +15,8 @@ * Data object holding values for matching an entity against a challenge. */ public class EntityMatch { + private static final Gson gson = new Gson(); + /** * @see @link http://minecraft.gamepedia.com/Data_values#Wool.2C_Stained_Clay.2C_Stained_Glass_and_Carpet */ @@ -43,7 +45,7 @@ public class EntityMatch { public EntityMatch(EntityType type, Map meta, int count) { this.type = type; - this.meta = meta != null ? meta : new HashMap(); + this.meta = meta != null ? meta : new HashMap<>(); this.count = count; } @@ -110,7 +112,7 @@ private boolean matchValues(Object entityValue, Object value) { @Override public String toString() { - return type.name() + (meta.isEmpty() ? "" : ":" + JSONObject.toJSONString(meta)); + return type.name() + (meta.isEmpty() ? "" : ":" + gson.toJson(meta)); } public String getDisplayName() { @@ -124,7 +126,7 @@ public String getDisplayName() { extra.remove(key); } if (!extra.isEmpty()) { - sb.append(":").append(JSONObject.toJSONString(extra)); + sb.append(":").append(gson.toJson(extra)); } return sb.toString(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/MojangAPI.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/MojangAPI.java deleted file mode 100644 index ffa9b9314..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/MojangAPI.java +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Features include: - *
- *     * Mojang API auto-throttling when receiving HTTP 429 (TOO MANY REQUESTS)
- *     * Incremental consumer strategy (consume each response, instead of blocking for everything).
- * 
- * - * Inspired by https://gist.github.com/evilmidget38/26d70114b834f71fb3b4 - */ -package us.talabrek.ultimateskyblock.mojang; - - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import dk.lockfuglsang.minecraft.util.TimeUtil; -import us.talabrek.ultimateskyblock.util.UUIDUtil; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Logger; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -public class MojangAPI { - private static final Logger log = Logger.getLogger(MojangAPI.class.getName()); - private static final int PROFILES_PER_REQUEST = 100; - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private static final String NAME_URL = "https://api.mojang.com/users/profiles/minecraft/{0}?at=0"; - private static final int MAX_RETRIES = 3; - // Mojang API has a cap at 600 requests per 10 minutes (1 per second). - private static final long THROTTLE_SUCCESS = 200L; - private static final long THROTTLE_CONSERVATIVE = 1000L; - private static final long THROTTLE_FAILURE = 3000L; - private static final int BAD_REQUEST = 400; - private static final int TOO_MANY_REQUESTS = 429; - private static final long FAILURE_WINDOW = 60000; - - private static long tStart = 0; - private static long numRequests = 0; - - private final JSONParser jsonParser = new JSONParser(); - - private int failuresInRow = 0; - private long lastFailure = 0; - - public MojangAPI() { - } - - public void fetchUUIDs(List names, NameUUIDConsumer consumer, ProgressCallback callback) { - if (consumer == null) { - throw new IllegalArgumentException("consumer cannot be null"); - } - if (isOnlineMode()) { - try { - fetchCurrent(names, consumer, callback); - callback.complete(true); - } catch (Exception e) { - callback.error("" + e); - callback.complete(false); - } - } else { - fetchOfflineMode(names, consumer, callback); - } - } - - private boolean isOnlineMode() { - return Bukkit.getOnlineMode(); - } - - private void fetchOfflineMode(List names, NameUUIDConsumer consumer, ProgressCallback callback) { - int failed = 0; - int success = 0; - int total = names.size(); - for (String name : names) { - //noinspection deprecation - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name); - Map map = new HashMap<>(); - map.put(offlinePlayer.getName(), offlinePlayer.getUniqueId()); - consumer.success(map); - success++; - if (callback != null) { - callback.progress(success+failed, failed, total, "OfflineMode"); - } - } - if (callback != null) { - callback.complete(true); - } - } - - private void fetchCurrent(List names, NameUUIDConsumer consumer, ProgressCallback callback) throws Exception { - int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - int failed = 0; - for (int i = 0; i < requests; i++) { - int fromIndex = i * PROFILES_PER_REQUEST; - int toIndex = Math.min((i + 1) * 100, names.size()); - List segment = names.subList(fromIndex, toIndex); - HttpURLConnection connection = createPostConnection(); - String body = JSONArray.toJSONString(segment); - writeBody(connection, body); - int responseCode = connection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { - Map tempMap = new HashMap<>(); - JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); - for (Object profile : array) { - JSONObject jsonProfile = (JSONObject) profile; - String id = (String) jsonProfile.get("id"); - String name = (String) jsonProfile.get("name"); - UUID uuid = getUUID(id); - tempMap.put(name, uuid); - } - int missing = segment.size() - tempMap.size(); - consumer.success(tempMap); - if (missing > 0) { - List unknown = new ArrayList<>(segment); - unknown.removeAll(tempMap.keySet()); - consumer.unknown(unknown); - } - if (callback != null) { - failed += missing; - callback.progress(toIndex, failed, names.size(), "Online"); - } - } else if (responseCode == TOO_MANY_REQUESTS) { - i--; - } else if (responseCode == BAD_REQUEST) { - if (callback != null) { - callback.error(connection.getResponseMessage()); - } - if (consumer != null) { - consumer.unknown(segment); - } - log.warning(connection.getResponseMessage() + "\nBODY:\n" + body); - } else { - i--; // retry segment - if (callback != null) { - callback.error(connection.getResponseMessage()); - } - } - throttle(responseCode, i != requests - 1, callback); - } - } - - private void throttle(int responseCode, boolean hasMore, ProgressCallback callback) throws InterruptedException { - if (!hasMore) { - return; - } - long now = System.currentTimeMillis(); - if (responseCode == TOO_MANY_REQUESTS) { - lastFailure = now; - failuresInRow++; - long throttle = THROTTLE_FAILURE*failuresInRow; - callback.error(tr("Too many requests for Mojangs API ({0} within {1}), sleeping {2}", - numRequests, - TimeUtil.millisAsString(now -tStart), - TimeUtil.millisAsShort(throttle))); - Thread.sleep(throttle); - } else { - if (lastFailure > now - FAILURE_WINDOW) { - Thread.sleep(THROTTLE_CONSERVATIVE); - } else { - Thread.sleep(THROTTLE_SUCCESS); - } - failuresInRow = 0; - } - } - - private static HttpURLConnection createGetConnection(String name) throws IOException { - URL url = new URL(MessageFormat.format(NAME_URL, name)); - stat(); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(false); - return connection; - } - - private static HttpURLConnection createPostConnection() throws Exception { - URL url = new URL(PROFILE_URL); - stat(); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - return connection; - } - - private static void stat() { - if (tStart == 0) { - tStart = System.currentTimeMillis(); - } - numRequests++; - } - - private static void writeBody(HttpURLConnection connection, String body) throws Exception { - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes("UTF-8")); - stream.flush(); - stream.close(); - } - - private static UUID getUUID(String id) { - return UUIDUtil.fromString(id); - } -} \ No newline at end of file diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/NameUUIDConsumer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/NameUUIDConsumer.java deleted file mode 100644 index 2c426c68b..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/NameUUIDConsumer.java +++ /dev/null @@ -1,31 +0,0 @@ -package us.talabrek.ultimateskyblock.mojang; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * Consumer for Mojang API queries for Name-UUID pairs. - * This allows for async. querying, and updating/caching of large data-sets. - */ -public interface NameUUIDConsumer { - /** - * Map from name to UUID - * @param names Map from name to UUID - */ - void success(Map names); - - /** - * A player that was renamed. - * @param oldName The old-name (the one queried). - * @param newName The new-name (the current). - * @param id The UUID. - */ - void renamed(String oldName, String newName, UUID id); - - /** - * List of names unknown to Mojang. - * @param unknownNames List of names unknown to Mojang. - */ - void unknown(List unknownNames); -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/ProgressCallback.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/ProgressCallback.java deleted file mode 100644 index cfa7cddc5..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/mojang/ProgressCallback.java +++ /dev/null @@ -1,10 +0,0 @@ -package us.talabrek.ultimateskyblock.mojang; - -/** - * A simple progress callback interface. - */ -public interface ProgressCallback { - void progress(int progress, int failed, int total, String message); - void complete(boolean success); - void error(String message); -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MetaUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MetaUtil.java index 9da7da164..a73d9ed28 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MetaUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MetaUtil.java @@ -1,30 +1,26 @@ package us.talabrek.ultimateskyblock.util; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; +import org.jetbrains.annotations.NotNull; -import java.io.IOException; -import java.io.StringReader; +import java.lang.reflect.Type; import java.util.Collections; import java.util.Map; -/** - */ public enum MetaUtil {; + private static final Gson gson = new Gson(); - public static Map createMap(String mapString) { + public static @NotNull Map createMap(String mapString) { if (mapString == null || mapString.isEmpty()) { return Collections.emptyMap(); } try { - Object parse = new JSONParser().parse(new StringReader(mapString)); - if (parse instanceof Map) { - return (Map)parse; - } - } catch (IOException | ParseException e) { - throw new IllegalArgumentException("Not a valid map: " + mapString, e); + Type mapType = new TypeToken>() {}.getType(); + return gson.fromJson(mapString, mapType); + } catch (JsonSyntaxException ex) { + throw new IllegalArgumentException("Not a valid map: " + mapString, ex); } - throw new IllegalArgumentException("Not a map: " + mapString); } - } diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MetaUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MetaUtilTest.java new file mode 100644 index 000000000..82fd17c88 --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MetaUtilTest.java @@ -0,0 +1,17 @@ +package us.talabrek.ultimateskyblock.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Map; + +public class MetaUtilTest { + @Test + public void testSingleMapParse() throws Exception { + String inputMap = "{\"Color\":8}"; + + Map outputMap = MetaUtil.createMap(inputMap); + Assert.assertEquals(1, outputMap.size()); + Assert.assertEquals(8.0, outputMap.get("Color")); + } +} From 23b5eb918e4d16b165c484146e82a5db23dc0738 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 3 Jan 2022 16:41:02 +0000 Subject: [PATCH 101/190] EntityMatch: use DyeColor enum for entity color (#32) * EntityMatch: use DyeColor enum for entity color * Update challenges.yml to use new entity color values --- .../challenge/EntityMatch.java | 148 ++++++++++++------ .../src/main/resources/challenges.yml | 34 ++-- .../challenge/EntityMatchTest.java | 58 +++++++ 3 files changed, 174 insertions(+), 66 deletions(-) create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/EntityMatchTest.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java index a1629fb3d..4896aeb06 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java @@ -1,8 +1,14 @@ package us.talabrek.ultimateskyblock.challenge; import com.google.gson.Gson; +import org.apache.commons.lang.WordUtils; +import org.bukkit.DyeColor; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.material.Colorable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.EntityUtil; import java.lang.reflect.Field; @@ -16,31 +22,11 @@ */ public class EntityMatch { private static final Gson gson = new Gson(); + private final uSkyBlock server = uSkyBlock.getInstance(); - /** - * @see @link http://minecraft.gamepedia.com/Data_values#Wool.2C_Stained_Clay.2C_Stained_Glass_and_Carpet - */ - private static final byte[] DV_2_COLOR_MAP = { - 0xf, // 0 -> white - 0x6, // 1 -> orange (gold) - 0xd, // 2 -> magenta (light purple) - 0x9, // 3 -> light blue - 0xe, // 4 -> yellow - 0xa, // 5 -> lime - 0xc, // 6 -> pink (red) - 0x8, // 7 -> gray (dark gray) - 0x7, // 8 -> light gray (gray) - 0xb, // 9 -> cyan (aqua) - 0x5, // 10 -> purple (dark purple) - 0x1, // 11 -> blue (dark blue) - 0x6, // 12 -> brown (no brown! we re-use gold) - 0x2, // 13 -> green (dark green) - 0x4, // 14 -> red (dark red) - 0x0 // 15 -> black - }; private static final String[] COLOR_KEYS = {"Color", "color"}; private final EntityType type; - private final Map meta; + private final Map meta; private final int count; public EntityMatch(EntityType type, Map meta, int count) { @@ -57,16 +43,29 @@ public int getCount() { return count; } - public boolean matches(Entity entity) { - if (entity != null && entity.getType() == type) { - for (String key : meta.keySet()) { - if (!matchFieldGetter(entity, key, meta.get(key))) { - return false; + /** + * Try to match the given {@link Entity} to this EntityMatch configuration. + * @param entity Entity to match. + * @return True if matches, false otherwise. + */ + public boolean matches(@Nullable Entity entity) { + if (entity == null || entity.getType() != type) { + return false; + } + + for (String key : meta.keySet()) { + if (key.equalsIgnoreCase("color")) { + if (entity instanceof Colorable) { + return ((Colorable) entity).getColor() == getColor(meta.get(key)); } + return true; + } + + if (!matchFieldGetter(entity, key, meta.get(key))) { + return false; } - return true; } - return false; + return true; } private boolean matchFieldGetter(Entity entity, String key, Object value) { @@ -117,36 +116,87 @@ public String toString() { public String getDisplayName() { StringBuilder sb = new StringBuilder(); - String name = EntityUtil.getEntityDisplayName(type); - String color = getColorCode(meta); - sb.append(color); - sb.append(name); - Map extra = new HashMap<>(meta); + Map extra = new HashMap<>(meta); for (String key : COLOR_KEYS) { - extra.remove(key); + if (meta.containsKey(key)) { + String color = WordUtils.capitalizeFully(getColor(meta.get(key)).toString().replace("_", " ")); + sb.append(color).append(" "); + extra.remove(key); + } } + + String name = EntityUtil.getEntityDisplayName(type); + sb.append(name); + if (!extra.isEmpty()) { sb.append(":").append(gson.toJson(extra)); } return sb.toString(); } - private String getColorCode(Map meta) { - // TODO: 30/01/2016 - R4zorax: Support more entities? - for (String key : COLOR_KEYS) { - if (meta.containsKey(key)) { - try { - int colorcode = Integer.parseInt("" + meta.get(key)); - return dataValueToFormattingCode(colorcode); - } catch (NumberFormatException e) { - // ignore - } - } + /** + * Converts the given String to the corresponding {@link DyeColor}. + * Defaults to {@link DyeColor#WHITE} on invalid or NULL input. + * @param input DyeColor enum value. + * @return Corresponding DyeColor, defaults to WHITE on invalid or NULL input. + */ + private @NotNull DyeColor getColor(@Nullable String input) { + try { + return DyeColor.valueOf(input); + } catch (IllegalArgumentException ex) { + server.getLogger().warning("Invalid DyeColor value: " + input); + server.getLogger().warning("See https://hub.spigotmc.org/javadocs/spigot/org/bukkit/DyeColor.html#enum-constant-summary for valid colors."); } - return ""; + + return DyeColor.WHITE; } - private String dataValueToFormattingCode(int colorcode) { - return "\u00a7" + Integer.toHexString(DV_2_COLOR_MAP[colorcode & 0xf]); + /** + * Converts the given legacy integer value to the corresponsing {@link DyeColor}. + * Defaults to {@link DyeColor#WHITE} on invalid or NULL input. + * @param input Legacy DyeColor integer value. + * @return Corresponding DyeColor, defaults to WHITE on invalid or NULL input. + * @deprecated To be used for legacy challenge configs only, use {@link EntityMatch#getColor(String)}. + */ + private @NotNull DyeColor getColor(@Nullable Number input) { + if (input == null) { + return DyeColor.WHITE; + } + + return switch (input.intValue()) { + case 0 -> DyeColor.WHITE; + case 1 -> DyeColor.ORANGE; + case 2 -> DyeColor.MAGENTA; + case 3 -> DyeColor.LIGHT_BLUE; + case 4 -> DyeColor.YELLOW; + case 5 -> DyeColor.LIME; + case 6 -> DyeColor.PINK; + case 7 -> DyeColor.GRAY; + case 8 -> DyeColor.LIGHT_GRAY; + case 9 -> DyeColor.CYAN; + case 10 -> DyeColor.PURPLE; + case 11 -> DyeColor.BLUE; + case 12 -> DyeColor.BROWN; + case 13 -> DyeColor.GREEN; + case 14 -> DyeColor.RED; + case 15 -> DyeColor.BLACK; + default -> DyeColor.WHITE; + }; + } + + /** + * Convenience method to translate a meta String or Number to the corresponding {@link DyeColor}. + * See {@link EntityMatch#getColor(String)} for more info. + * @param input Meta String or Number. + * @return Corresponding DyeColor, defaults to WHITE. + */ + private @NotNull DyeColor getColor(@Nullable Object input) { + if (input instanceof String) { + return getColor((String) input); + } else if (input instanceof Number) { + return getColor((Number) input); + } + + return DyeColor.WHITE; } } diff --git a/uSkyBlock-Core/src/main/resources/challenges.yml b/uSkyBlock-Core/src/main/resources/challenges.yml index 8079178f1..d9974839d 100644 --- a/uSkyBlock-Core/src/main/resources/challenges.yml +++ b/uSkyBlock-Core/src/main/resources/challenges.yml @@ -1079,22 +1079,22 @@ ranks: - Cow:8 - Pig:8 - Chicken:16 - - Sheep:{"Color":0} - - Sheep:{"Color":1} - - Sheep:{"Color":2} - - Sheep:{"Color":3} - - Sheep:{"Color":4} - - Sheep:{"Color":5} - - Sheep:{"Color":6} - - Sheep:{"Color":7} - - Sheep:{"Color":8} - - Sheep:{"Color":9} - - Sheep:{"Color":10} - - Sheep:{"Color":11} - - Sheep:{"Color":12} - - Sheep:{"Color":13} - - Sheep:{"Color":14} - - Sheep:{"Color":15} + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} reward: text: 1 horse, 1 iron horse armor, 5% chance horse armor items: @@ -1764,4 +1764,4 @@ ranks: # All commented settings (#) in the above challenges (not the explanation) can be removed to clean up the challenges.yml. # # DO NOT CHANGE! -version: 105 +version: 106 diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/EntityMatchTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/EntityMatchTest.java new file mode 100644 index 000000000..105f63ed6 --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/EntityMatchTest.java @@ -0,0 +1,58 @@ +package us.talabrek.ultimateskyblock.challenge; + +import org.bukkit.DyeColor; +import org.bukkit.entity.Cow; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Sheep; +import org.bukkit.material.Colorable; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class EntityMatchTest { + @Test + public void testMatchColoredSheep() { + EntityMatch matcher = new EntityMatch(EntityType.SHEEP, Map.of("Color", "RED"), 1); + + Sheep fakeSheep = mock(Sheep.class, withSettings().extraInterfaces(Colorable.class)); + when(fakeSheep.getColor()).thenReturn(DyeColor.RED); + when(fakeSheep.getType()).thenReturn(EntityType.SHEEP); + + assertEquals("Red Sheep", matcher.getDisplayName()); + assertEquals(1, matcher.getCount()); + assertTrue(matcher.matches(fakeSheep)); + + when(fakeSheep.getColor()).thenReturn(DyeColor.WHITE); + assertFalse(matcher.matches(fakeSheep)); + } + + @Test + public void testMatchLegacyColoredSheep() { + EntityMatch matcher = new EntityMatch(EntityType.SHEEP, Map.of("color", 4.0), 9); + + Sheep fakeSheep = mock(Sheep.class, withSettings().extraInterfaces(Colorable.class)); + when(fakeSheep.getColor()).thenReturn(DyeColor.YELLOW); + when(fakeSheep.getType()).thenReturn(EntityType.SHEEP); + + assertEquals("Yellow Sheep", matcher.getDisplayName()); + assertEquals(9, matcher.getCount()); + assertTrue(matcher.matches(fakeSheep)); + + when(fakeSheep.getColor()).thenReturn(DyeColor.BLACK); + assertFalse(matcher.matches(fakeSheep)); + } + + @Test + public void testMatchColoredCow() { + EntityMatch matcher = new EntityMatch(EntityType.COW, Map.of("Color", "RED"), 1); + + Cow fakeCow = mock(Cow.class); + when(fakeCow.getType()).thenReturn(EntityType.COW); + + assertEquals("Red Cow", matcher.getDisplayName()); + assertTrue(matcher.matches(fakeCow)); + } +} From 7115825aac7b41d6d74438ae3d89b866be78cce0 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 3 Jan 2022 17:13:54 +0000 Subject: [PATCH 102/190] Publish version.json on deploy --- .github/deploy-release.sh | 4 ++++ .github/deploy-staging.sh | 4 ++++ uSkyBlock-Core/pom.xml | 2 ++ uSkyBlock-Plugin/pom.xml | 16 ++++++++++++++++ uSkyBlock-Plugin/src/main/resources/version.json | 1 + 5 files changed, 27 insertions(+) create mode 100644 uSkyBlock-Plugin/src/main/resources/version.json diff --git a/.github/deploy-release.sh b/.github/deploy-release.sh index bdedfcd98..e28f212d1 100644 --- a/.github/deploy-release.sh +++ b/.github/deploy-release.sh @@ -51,3 +51,7 @@ echo -e "Publishing final plugin release...\n" rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ travis@travis.internetpolice.eu:WWW-USB/downloads/release/uSkyBlock/ + +rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/classes/version.json \ +travis@travis.internetpolice.eu:WWW-USB/versions/release.json diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh index fc1f5559a..0c52006c5 100644 --- a/.github/deploy-staging.sh +++ b/.github/deploy-staging.sh @@ -51,3 +51,7 @@ echo -e "Publishing final plugin release...\n" rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ + +rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/classes/version.json \ +travis@travis.internetpolice.eu:WWW-USB/versions/staging.json diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index d4116610b..6b8076638 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -120,6 +120,8 @@ META-INF/*.SF META-INF/*.DSA META-INF/*.RSA + module-info.class + META-INF.*
diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 5c4530751..f0fcf8bd0 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -39,6 +39,22 @@
+ + + src/main/resources + true + + **/version.json + + + + src/main/resources + false + + **/version.json + + + diff --git a/uSkyBlock-Plugin/src/main/resources/version.json b/uSkyBlock-Plugin/src/main/resources/version.json new file mode 100644 index 000000000..7ffc630da --- /dev/null +++ b/uSkyBlock-Plugin/src/main/resources/version.json @@ -0,0 +1 @@ +{"version":"${project.version}"} From 99a4af361c43a27ce03f4c63d1ddad62407c01b8 Mon Sep 17 00:00:00 2001 From: Muspah Date: Mon, 3 Jan 2022 17:16:50 +0000 Subject: [PATCH 103/190] GH Actions: use setup-java@v2 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a966ad53..a07ac9832 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - - name: JDK 17 - uses: actions/setup-java@v1 + uses: actions/setup-java@v2 with: java-version: '17' distribution: 'temurin' From 4d19287dca04f74e0bba449e5be8134867b7e634 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 5 Jan 2022 14:02:31 +0000 Subject: [PATCH 104/190] Add update checker (#33) --- pom.xml | 12 ++ .../ultimateskyblock/api/UpdateChecker.java | 50 ++++++++ uSkyBlock-Core/pom.xml | 29 ++++- .../ultimateskyblock/SkyUpdateChecker.java | 115 ++++++++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 19 ++- uSkyBlock-Core/src/main/resources/config.yml | 8 +- 6 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/UpdateChecker.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java diff --git a/pom.xml b/pom.xml index 186cc4d83..856459581 100644 --- a/pom.xml +++ b/pom.xml @@ -10,8 +10,10 @@ 4.9.3 4.0.1 + 4.5.13 2.8.9 23.0.0 + 3.8.4 ${project.version} 1.25-SNAPSHOT 1.0.7 @@ -249,6 +251,16 @@ gson ${gson.version} + + org.apache.httpcomponents + httpclient + ${apache-http.version} + + + org.apache.maven + maven-artifact + ${maven-artifact.version} + diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/UpdateChecker.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/UpdateChecker.java new file mode 100644 index 000000000..35a27242b --- /dev/null +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/UpdateChecker.java @@ -0,0 +1,50 @@ +package us.talabrek.ultimateskyblock.api; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +public interface UpdateChecker { + URI URL_RELEASE = URI.create("https://www.uskyblock.ovh/versions/release.json"); + URI URL_STAGING = URI.create("https://www.uskyblock.ovh/versions/staging.json"); + + /** + * Compares the current version and latest version (if available) to see if there is a new version available. + * @return True if new version is available, false otherwise (no new version available or version info unavailable). + */ + boolean isUpdateAvailable(); + + /** + * Gets the latest release of uSkyBlock. Returns NULL if the version info hasn't been fetched yet or is unavailable. + * @return Latest release of uSkyBlock, NULL when unavailable. + */ + @Nullable String getLatestVersion(); + + /** + * Gets the current version of uSkyBlock running on the server. + * @return Current version of uSkyBlock. + */ + @NotNull String getCurrentVersion(); + + /** + * Fetches the latest version info from the uSkyBlock website. Returns a {@link CompletableFuture }, + * completes the HTTP request async. The CompletableFuture will contain NULL when version info cannot be obtained. + * @param uri URI to use for the HTTP request, official links are + * {@link UpdateChecker#URL_RELEASE} and {@link UpdateChecker#URL_STAGING}. + * @return CompletableFuture with the latest version info. + */ + CompletableFuture fetchLatestVersion(URI uri); + + /** + * Compares two version numbers. Returns a negative integer, zero, or a positive integer as this + * object is less than, equal to, or greater than the specified object. + * @see Comparable#compareTo(Object). + * @param currentVersion Current version number (may contain -SNAPSHOT). + * @param newVersion New version number (may contain -SNAPSHOT). + * @return Negative integer, zero, or a positive integer as this object is less than, + * equal to, or greater than the specified object. + */ + boolean isNewerVersion(String currentVersion, String newVersion); +} diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 6b8076638..45b193938 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -86,11 +86,17 @@ dk.lockfuglsang.minecraft:bukkit-utils io.papermc:paperlib net.kyori:* + org.apache.httpcomponents:httpclient + org.apache.maven:maven-artifact org.bstats:* uSkyBlock:po-utils + + com.google.code.gson + us.talabrek.ultimateskyblock.gson + dk.lockfuglsang.minecraft us.talabrek.ultimateskyblock.utils @@ -104,12 +110,16 @@ us.talabrek.ultimateskyblock.kyori - org.bstats - us.talabrek.ultimateskyblock.metrics + org.apache.httpcomponents + us.talabrek.ultimateskyblock.apache.httpcomponents - com.google.code.gson - us.talabrek.ultimateskyblock.gson + org.apache.maven + us.talabrek.ultimateskyblock.apache.maven + + + org.bstats + us.talabrek.ultimateskyblock.metrics @@ -484,6 +494,17 @@ 2.6 provided + + + org.apache.httpcomponents + httpclient + compile + + + org.apache.maven + maven-artifact + compile + org.hamcrest diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java new file mode 100644 index 000000000..35ff12c9e --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java @@ -0,0 +1,115 @@ +package us.talabrek.ultimateskyblock; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.apache.maven.artifact.versioning.ComparableVersion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.api.UpdateChecker; + +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +public class SkyUpdateChecker implements UpdateChecker { + private String latestVersion; + + private final Gson gson = new Gson(); + private final uSkyBlock plugin; + + public SkyUpdateChecker(uSkyBlock plugin) { + this.plugin = plugin; + } + + /** + * Triggers an update of the latest version info from the uSkyBlock website, and will log an INFO message if + * an update is available. + */ + public void checkForUpdates() { + URI uri = URL_RELEASE; + + if (plugin.getConfig().getString("plugin-updates.branch", "RELEASE").equalsIgnoreCase("STAGING")) { + uri = URL_STAGING; + } + + fetchLatestVersion(uri).thenAccept(version -> { + latestVersion = version; + if (latestVersion == null) { + plugin.getLogger().info("Failed to check for new uSkyBlock versions."); + } + + if (isUpdateAvailable()) { + plugin.getLogger().info("There is a new version of uSkyBlock available: " + getLatestVersion()); + plugin.getLogger().info("Visit https://www.uskyblock.ovh/get to download."); + } + }); + } + + public boolean isUpdateAvailable() { + if (latestVersion != null) { + return isNewerVersion(getCurrentVersion(), getLatestVersion()); + } + return false; + } + + public @Nullable String getLatestVersion() { + return latestVersion; + } + + public @NotNull String getCurrentVersion() { + return plugin.getDescription().getVersion(); + } + + public CompletableFuture fetchLatestVersion(URI uri) { + CompletableFuture future = new CompletableFuture<>(); + future.completeAsync(() -> { + try { + String userAgent = "uSkyBlock-Plugin/v" + getCurrentVersion() + " (www.uskyblock.ovh)"; + HttpClient httpclient = HttpClients.custom().setUserAgent(userAgent).build(); + + int CONNECTION_TIMEOUT_MS = 10 * 1000; // Timeout in millis. + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(CONNECTION_TIMEOUT_MS) + .setConnectTimeout(CONNECTION_TIMEOUT_MS) + .setSocketTimeout(CONNECTION_TIMEOUT_MS) + .build(); + + HttpGet request = new HttpGet(uri); + request.setConfig(requestConfig); + HttpResponse response = httpclient.execute(request); + HttpEntity entity = response.getEntity(); + + int status = response.getStatusLine().getStatusCode(); + if (status < 200 || status >= 300) { + return null; + } + + if (entity != null) { + JsonObject obj = gson.fromJson(EntityUtils.toString(entity), JsonObject.class); + if (obj.has("version")) { + return obj.get("version").getAsString(); + } + } + } catch (Exception ex) { + plugin.getLogger().warning("Exception while trying to fetch latest plugin version."); + ex.printStackTrace(); + } + + return null; + }); + + return future; + } + + public boolean isNewerVersion(String currentVersion, String newVersion) { + ComparableVersion current = new ComparableVersion(currentVersion); + ComparableVersion target = new ComparableVersion(newVersion); + return target.compareTo(current) > 0; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index c3f8f3763..98842afdb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -78,7 +78,6 @@ import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.IslandPerk; -import us.talabrek.ultimateskyblock.player.NotificationManager; import us.talabrek.ultimateskyblock.player.PerkLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.player.PlayerLogic; @@ -165,6 +164,8 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private volatile boolean maintenanceMode = false; private BlockLimitLogic blockLimitLogic; + private SkyUpdateChecker updateChecker; + public uSkyBlock() { } @@ -228,11 +229,17 @@ public void run() { Bukkit.getConsoleSender().sendMessage(tr("Converting data to UUID, this make take a while!")); getImporter().importUSB(Bukkit.getConsoleSender(), "name2uuid"); } + getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 log(Level.INFO, getVersionInfo(false)); } }, getConfig().getLong("init.initDelay", 50L)); + updateChecker = new SkyUpdateChecker(this); + // Runs every 4 hours + // noinspection deprecation + getServer().getScheduler().scheduleAsyncRepeatingTask(this, () -> getUpdateChecker().checkForUpdates(), 0L, 288000L); + metricsManager = new MetricsManager(this); } @@ -998,6 +1005,12 @@ public String getVersionInfo(boolean checkEnabled) { } } msg += pre("\u00a77------------------------------\n"); + + if (getConfig().getBoolean("plugin-updates.check", true) && getUpdateChecker().isUpdateAvailable()) { + msg += pre("\u00a7bA new update of uSkyBlock is available: \u00a7f{0}\n", getUpdateChecker().getLatestVersion()); + msg += pre("\u00a7fVisit {0} to download.\n", "https://www.uskyblock.ovh/get"); + } + return msg; } @@ -1059,6 +1072,10 @@ public HookManager getHookManager() { return hookManager; } + public SkyUpdateChecker getUpdateChecker() { + return updateChecker; + } + public WorldManager getWorldManager() { return worldManager; } diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index 8458a300f..9e6ad6657 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -435,6 +435,12 @@ tool-menu: CRAFTING_TABLE: challenges BEDROCK: island spawn +plugin-updates: + # Should we check for updates and log a message if an update is available + check: true + # Possible options: RELEASE or STAGING + branch: RELEASE + # Placeholders - enable these to get placeholder substitution # usb_version # usb_island_level, usb_island_level_int @@ -456,7 +462,7 @@ placeholder: servercommandplaceholder: false # DO NOT TOUCH THE FIELDS BELOW -version: 107 +version: 108 force-replace: options.party.invite-timeout: 100 options.island.islandTeleportDelay: 5 From 98baad710a0c23b210b69da2833ea217fb3cd018 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 5 Jan 2022 14:35:18 +0000 Subject: [PATCH 105/190] Update dependencies in uSkyBlock.class, switch FAWE to basic integration --- .../ultimateskyblock/handler/AsyncWorldEditHandler.java | 3 ++- .../main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index cddcad072..6ce4d308b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -54,7 +54,8 @@ public static AWEAdaptor getAWEAdaptor() { if (!uSkyBlock.getInstance().getConfig().getBoolean("asyncworldedit.enabled", true)) { return NULL_ADAPTOR; } - Plugin fawe = getFAWE(); + //Plugin fawe = getFAWE(); + Plugin fawe = null; // Disabled b/c 1.18.1 releases Plugin awe = getAWE(); String className; if (fawe != null) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 98842afdb..998f68007 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -114,10 +114,10 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private static final String CN = uSkyBlock.class.getName(); private static final String[][] depends = new String[][]{ new String[]{"Vault", "1.7.1", "optional"}, - new String[]{"WorldEdit", "7.2.6", "optionalIf", "FastAsyncWorldEdit"}, + new String[]{"WorldEdit", "7.2.8", "optionalIf", "FastAsyncWorldEdit"}, new String[]{"WorldGuard", "7.0.6"}, - new String[]{"FastAsyncWorldEdit", "1.17", "optional"}, - new String[]{"Multiverse-Core", "4.3.0", "optional"}, + new String[]{"FastAsyncWorldEdit", "2.0.0", "optional"}, + new String[]{"Multiverse-Core", "4.3.1", "optional"}, new String[]{"Multiverse-Portals", "4.2.1", "optional"}, new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, }; From beb8d1329d2d0c3f9b4f632cd138dafac61166f7 Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 5 Jan 2022 15:32:08 +0000 Subject: [PATCH 106/190] API version 1.18 --- uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index afdf9b078..4f43f072c 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -18,7 +18,7 @@ softdepend: - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.17 +api-version: 1.18 commands: challenges: From c9678bee425f89988204d488c7f2467da8e5aa1c Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 5 Jan 2022 15:36:39 +0000 Subject: [PATCH 107/190] Version to 2.11.0 for release --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 330f8360e..cf0a53792 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0-SNAPSHOT + 2.11.0 4.0.0 jar diff --git a/pom.xml b/pom.xml index 856459581..13368619c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.11.0-SNAPSHOT + 2.11.0 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 09a693ccb..539ac186c 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.11.0-SNAPSHOT + 2.11.0 UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index fcc057f41..3e81b6013 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0-SNAPSHOT + 2.11.0 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 45b193938..f4e49fa76 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0-SNAPSHOT + 2.11.0 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 2ffc3a942..c76904253 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0-SNAPSHOT + 2.11.0 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index f0fcf8bd0..a580c956e 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0-SNAPSHOT + 2.11.0 4.0.0 jar From 61d604636081d305530be52bec3346c1e542b5ed Mon Sep 17 00:00:00 2001 From: Muspah Date: Wed, 5 Jan 2022 15:56:58 +0000 Subject: [PATCH 108/190] Back to snapshots, v2.12.0-SNAPSHOT --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index cf0a53792..b1747d1bb 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0 + 2.12.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index 13368619c..e05fabbb1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ uSkyBlock uSkyBlock pom - 2.11.0 + 2.12.0-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 539ac186c..220a919b2 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.11.0 + 2.12.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 3e81b6013..fa17bb50e 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0 + 2.12.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index f4e49fa76..e3d5e0e87 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0 + 2.12.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index c76904253..ff91ce8da 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0 + 2.12.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index a580c956e..16abb3e07 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock uSkyBlock - 2.11.0 + 2.12.0-SNAPSHOT 4.0.0 jar From fd17baf4d1a85344a5a80623337b8e2fa4c89351 Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 7 Jan 2022 15:57:45 +0000 Subject: [PATCH 109/190] Add Minecraft version to version.json --- uSkyBlock-Plugin/src/main/resources/version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Plugin/src/main/resources/version.json b/uSkyBlock-Plugin/src/main/resources/version.json index 7ffc630da..5dc94a354 100644 --- a/uSkyBlock-Plugin/src/main/resources/version.json +++ b/uSkyBlock-Plugin/src/main/resources/version.json @@ -1 +1 @@ -{"version":"${project.version}"} +{"version": "${project.version}", "build": "${env.GITHUB_RUN_NUMBER}", "minecraft-version": "${spigotapi.version}"} From 21cb27dec10e193fa915063e24bf6fcecf50f9f4 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 8 Jan 2022 16:22:05 +0000 Subject: [PATCH 110/190] uSkyBlock-APIv2 (#34) * Change Maven groupId, introduce APIv2 module * Add basic API provider (based off of LuckPerms) * PluginInfo API (mainly to start testing) * Update readme, version to 3.0.0-SNAPSHOT --- README.md | 26 +++++ po-utils/pom.xml | 4 +- pom.xml | 18 ++-- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-APIv2/pom.xml | 95 +++++++++++++++++++ .../api/UltimateSkyblock.java | 12 +++ .../api/UltimateSkyblockProvider.java | 46 +++++++++ .../api/plugin/PluginInfo.java | 21 ++++ .../api/plugin/UpdateChecker.java | 50 ++++++++++ uSkyBlock-AWE370/pom.xml | 6 +- uSkyBlock-Core/pom.xml | 12 ++- .../ultimateskyblock/SkyUpdateChecker.java | 2 +- .../api/impl/UltimateSkyblockApi.java | 32 +++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 28 +++++- uSkyBlock-FAWE/pom.xml | 6 +- uSkyBlock-Plugin/pom.xml | 10 +- uSkyBlock-Plugin/src/assembly/plugin.xml | 7 +- 17 files changed, 348 insertions(+), 29 deletions(-) create mode 100644 uSkyBlock-APIv2/pom.xml create mode 100644 uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblock.java create mode 100644 uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblockProvider.java create mode 100644 uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/PluginInfo.java create mode 100644 uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/UpdateChecker.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/impl/UltimateSkyblockApi.java diff --git a/README.md b/README.md index 1734afba9..a08fafa9c 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,32 @@ Pre-releases will end in -SNAPSHOT, and is considered **unsafe** for production Releases have a clean version number, has been tested, and should be safe for production servers. +# New Maven group/artifactId +Starting with version 3.0.0-SNAPSHOT, we've changed our Maven groupId's for all submodules except uSkyBlock-API. +If you're using uSkyBlock-Core or po-utils as dependency in your project, update your +dependencies to: + +```xml + + ovh.uskyblock + uSkyBlock-Core + 3.0.0-SNAPSHOT + +``` + +We're moving new API features towards APIv2, which is available as: + +```xml + + ovh.uskyblock + uSkyBlock-APIv2 + 3.0.0-SNAPSHOT + +``` + +Feel free to use any of the new APIv2 functions on servers running uSkyBlock 3.0.0+. The old API-methods will +be deprecated and removed in the upcoming plugin releases. + ### Bukkit/Spigot 1.7.9/10 Releases We provide pre-compiled versions (no support) [here](http://rlf.github.io/uSkyBlock): diff --git a/po-utils/pom.xml b/po-utils/pom.xml index b1747d1bb..b9d4a156d 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> uSkyBlock - uSkyBlock - 2.12.0-SNAPSHOT + ovh.uskyblock + 3.0.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index e05fabbb1..6900c0477 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,10 @@ 4.0.0 - uSkyBlock + ovh.uskyblock uSkyBlock pom - 2.12.0-SNAPSHOT + 3.0.0-SNAPSHOT Ultimate SkyBlock @@ -39,6 +39,7 @@ po-utils uSkyBlock-API + uSkyBlock-APIv2 uSkyBlock-Core uSkyBlock-Plugin uSkyBlock-FAWE @@ -207,22 +208,27 @@ ${api.version} - uSkyBlock + ovh.uskyblock + uSkyBlock-APIv2 + ${project.version} + + + ovh.uskyblock uSkyBlock-Core ${project.version} - uSkyBlock + ovh.uskyblock uSkyBlock-FAWE ${project.version} - uSkyBlock + ovh.uskyblock uSkyBlock-AWE370 ${project.version} - uSkyBlock + ovh.uskyblock po-utils ${project.version} diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 220a919b2..e0adee020 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 2.12.0-SNAPSHOT + 3.0.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml new file mode 100644 index 000000000..f7cbcfa3f --- /dev/null +++ b/uSkyBlock-APIv2/pom.xml @@ -0,0 +1,95 @@ + + + + uSkyBlock + ovh.uskyblock + 3.0.0-SNAPSHOT + + 4.0.0 + jar + uSkyBlock-APIv2 + + + + org.spigotmc + spigot-api + ${spigotapi.version} + provided + true + + + org.jetbrains + annotations + + + + junit + junit + ${junit.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-vintage-engine.version} + test + + + org.hamcrest + hamcrest + ${hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${hamcrest.version} + test + + + + + + + maven-compiler-plugin + + 17 + utf-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + public + false + none + + + + + javadoc + + deploy + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + diff --git a/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblock.java b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblock.java new file mode 100644 index 000000000..27f6593e5 --- /dev/null +++ b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblock.java @@ -0,0 +1,12 @@ +package us.talabrek.ultimateskyblock.api; + +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.api.plugin.PluginInfo; + +public interface UltimateSkyblock { + /** + * Gets the {@link PluginInfo}, providing general information about this Ultimate Skyblock instance. + * @return General plugin information. + */ + @NotNull PluginInfo getPluginInfo(); +} diff --git a/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblockProvider.java b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblockProvider.java new file mode 100644 index 000000000..dbcc6573e --- /dev/null +++ b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/UltimateSkyblockProvider.java @@ -0,0 +1,46 @@ +package us.talabrek.ultimateskyblock.api; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +public final class UltimateSkyblockProvider { + private static UltimateSkyblock instance = null; + + /** + * Gets the API instance of {@link UltimateSkyblock}, will throw {@link IllegalStateException} when the + * API isn't loaded yet. + * + * Convenience method, using Bukkit's {@link org.bukkit.plugin.ServicesManager} is the preferred way to get + * an API instance. + * @return UltimateSkyblock API instance. + * @throws IllegalStateException when the API isn't loaded yet. + */ + public static @NotNull UltimateSkyblock getInstance() { + if (instance == null) { + throw new IllegalStateException("UltimateSkyblock isn't loaded yet!"); + } + return instance; + } + + /** + * Internal method - Registers the uSkyBlock plugin instance with the API provider. + * @param instance uSkyBlock plugin instance + */ + @ApiStatus.Internal + public static void registerPlugin(UltimateSkyblock instance) { + UltimateSkyblockProvider.instance = instance; + } + + /** + * Internal method - Deregisters the uSkyBlock plugin instance with the API provider. + */ + @ApiStatus.Internal + public static void deregisterPlugin() { + UltimateSkyblockProvider.instance = null; + } + + /** + * No instance of this class should exist. + */ + private UltimateSkyblockProvider() {} +} diff --git a/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/PluginInfo.java b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/PluginInfo.java new file mode 100644 index 000000000..fe8fc4d97 --- /dev/null +++ b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/PluginInfo.java @@ -0,0 +1,21 @@ +package us.talabrek.ultimateskyblock.api.plugin; + +import org.jetbrains.annotations.NotNull; + +/** + * Provides general information about the Ultimate Skyblock plugin instance running. + */ +public interface PluginInfo { + /** + * Gets the plugin version running on the server. + * @return Plugin version running. + */ + @NotNull String getPluginVersion(); + + /** + * Gets the {@link UpdateChecker}, which provides various information about the current and latest + * Ultimate Skyblock releases. + * @return Update checker for Ultimate Skyblock. + */ + @NotNull UpdateChecker getUpdateChecker(); +} diff --git a/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/UpdateChecker.java b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/UpdateChecker.java new file mode 100644 index 000000000..39d874389 --- /dev/null +++ b/uSkyBlock-APIv2/src/main/java/us/talabrek/ultimateskyblock/api/plugin/UpdateChecker.java @@ -0,0 +1,50 @@ +package us.talabrek.ultimateskyblock.api.plugin; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +public interface UpdateChecker { + URI URL_RELEASE = URI.create("https://www.uskyblock.ovh/versions/release.json"); + URI URL_STAGING = URI.create("https://www.uskyblock.ovh/versions/staging.json"); + + /** + * Compares the current version and latest version (if available) to see if there is a new version available. + * @return True if new version is available, false otherwise (no new version available or version info unavailable). + */ + boolean isUpdateAvailable(); + + /** + * Gets the latest release of uSkyBlock. Returns NULL if the version info hasn't been fetched yet or is unavailable. + * @return Latest release of uSkyBlock, NULL when unavailable. + */ + @Nullable String getLatestVersion(); + + /** + * Gets the current version of uSkyBlock running on the server. + * @return Current version of uSkyBlock. + */ + @NotNull String getCurrentVersion(); + + /** + * Fetches the latest version info from the uSkyBlock website. Returns a {@link CompletableFuture }, + * completes the HTTP request async. The CompletableFuture will contain NULL when version info cannot be obtained. + * @param uri URI to use for the HTTP request, official links are + * {@link UpdateChecker#URL_RELEASE} and {@link UpdateChecker#URL_STAGING}. + * @return CompletableFuture with the latest version info. + */ + CompletableFuture fetchLatestVersion(URI uri); + + /** + * Compares two version numbers. Returns a negative integer, zero, or a positive integer as this + * object is less than, equal to, or greater than the specified object. + * @see Comparable#compareTo(Object). + * @param currentVersion Current version number (may contain -SNAPSHOT). + * @param newVersion New version number (may contain -SNAPSHOT). + * @return Negative integer, zero, or a positive integer as this object is less than, + * equal to, or greater than the specified object. + */ + boolean isNewerVersion(String currentVersion, String newVersion); +} diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index fa17bb50e..2a6577358 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> uSkyBlock - uSkyBlock - 2.12.0-SNAPSHOT + ovh.uskyblock + 3.0.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 @@ -24,7 +24,7 @@ - uSkyBlock + ovh.uskyblock uSkyBlock-Core diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index e3d5e0e87..fadf7ad6b 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> uSkyBlock - uSkyBlock - 2.12.0-SNAPSHOT + ovh.uskyblock + 3.0.0-SNAPSHOT 4.0.0 jar @@ -89,7 +89,7 @@ org.apache.httpcomponents:httpclient org.apache.maven:maven-artifact org.bstats:* - uSkyBlock:po-utils + ovh.uskyblock:po-utils @@ -353,13 +353,17 @@ tests - uSkyBlock + ovh.uskyblock po-utils com.github.rlf uSkyBlock-API + + ovh.uskyblock + uSkyBlock-APIv2 + net.milkbowl.vault VaultAPI diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java index 35ff12c9e..c85ff6718 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java @@ -12,7 +12,7 @@ import org.apache.maven.artifact.versioning.ComparableVersion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import us.talabrek.ultimateskyblock.api.UpdateChecker; +import us.talabrek.ultimateskyblock.api.plugin.UpdateChecker; import java.net.URI; import java.util.concurrent.CompletableFuture; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/impl/UltimateSkyblockApi.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/impl/UltimateSkyblockApi.java new file mode 100644 index 000000000..49f6b33e5 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/impl/UltimateSkyblockApi.java @@ -0,0 +1,32 @@ +package us.talabrek.ultimateskyblock.api.impl; + +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.api.UltimateSkyblock; +import us.talabrek.ultimateskyblock.api.plugin.PluginInfo; +import us.talabrek.ultimateskyblock.api.plugin.UpdateChecker; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public class UltimateSkyblockApi implements UltimateSkyblock, PluginInfo { + private final uSkyBlock plugin; + + public UltimateSkyblockApi(uSkyBlock plugin) { + this.plugin = plugin; + } + + @Override + public @NotNull PluginInfo getPluginInfo() { + return this; + } + + /* PluginInfo impl */ + + @Override + public @NotNull String getPluginVersion() { + return plugin.getUpdateChecker().getCurrentVersion(); + } + + @Override + public @NotNull UpdateChecker getUpdateChecker() { + return plugin.getUpdateChecker(); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 998f68007..ca8414083 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -22,6 +22,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -29,10 +30,13 @@ import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandLevel; import us.talabrek.ultimateskyblock.api.IslandRank; +import us.talabrek.ultimateskyblock.api.UltimateSkyblock; +import us.talabrek.ultimateskyblock.api.UltimateSkyblockProvider; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.event.EventLogic; import us.talabrek.ultimateskyblock.api.event.uSkyBlockEvent; import us.talabrek.ultimateskyblock.api.event.uSkyBlockScoreChangedEvent; +import us.talabrek.ultimateskyblock.api.impl.UltimateSkyblockApi; import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.chat.ChatEvents; @@ -164,6 +168,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private volatile boolean maintenanceMode = false; private BlockLimitLogic blockLimitLogic; + private UltimateSkyblockApi api; private SkyUpdateChecker updateChecker; public uSkyBlock() { @@ -171,6 +176,9 @@ public uSkyBlock() { @Override public void onDisable() { + deregisterApi(api); + api = null; + HandlerList.unregisterAll(this); Bukkit.getScheduler().cancelTasks(this); try { @@ -206,9 +214,11 @@ public void onEnable() { FileUtil.setDataFolder(getDataFolder()); FileUtil.setAllwaysOverwrite("levelConfig.yml"); I18nUtil.setDataFolder(getDataFolder()); - reloadConfigs(); + api = new UltimateSkyblockApi(this); + registerApi(api); + getServer().getScheduler().runTaskLater(getInstance(), new Runnable() { @Override public void run() { @@ -1145,4 +1155,20 @@ public void execCommands(Player player, List cmdList) { execCommand(player, cmd, false); } } + + /** + * Register this uSkyBlock instance with our API provider and Bukkit's ServicesManager. + */ + private void registerApi(UltimateSkyblock api) { + UltimateSkyblockProvider.registerPlugin(api); + getServer().getServicesManager().register(UltimateSkyblock.class, api, this, ServicePriority.Normal); + } + + /** + * Deregister this uSkyBlock instance with our API provider and Bukkit's ServicesManager. + */ + private void deregisterApi(UltimateSkyblock api) { + UltimateSkyblockProvider.deregisterPlugin(); + getServer().getServicesManager().unregister(api); + } } diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index ff91ce8da..26d15f20c 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> uSkyBlock - uSkyBlock - 2.12.0-SNAPSHOT + ovh.uskyblock + 3.0.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE @@ -25,7 +25,7 @@ provided - uSkyBlock + ovh.uskyblock uSkyBlock-Core diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 16abb3e07..470e15d9e 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> uSkyBlock - uSkyBlock - 2.12.0-SNAPSHOT + ovh.uskyblock + 3.0.0-SNAPSHOT 4.0.0 jar @@ -63,15 +63,15 @@ uSkyBlock-API - uSkyBlock + ovh.uskyblock uSkyBlock-Core - uSkyBlock + ovh.uskyblock uSkyBlock-FAWE - uSkyBlock + ovh.uskyblock uSkyBlock-AWE370 diff --git a/uSkyBlock-Plugin/src/assembly/plugin.xml b/uSkyBlock-Plugin/src/assembly/plugin.xml index 37176911f..f930bae34 100644 --- a/uSkyBlock-Plugin/src/assembly/plugin.xml +++ b/uSkyBlock-Plugin/src/assembly/plugin.xml @@ -10,9 +10,10 @@ com.github.rlf:uSkyBlock-API - uSkyBlock:uSkyBlock-Core - uSkyBlock:uSkyBlock-FAWE - uSkyBlock:uSkyBlock-AWE370 + ovh.uskyblock:uSkyBlock-APIv2 + ovh.uskyblock:uSkyBlock-Core + ovh.uskyblock:uSkyBlock-FAWE + ovh.uskyblock:uSkyBlock-AWE370 true From c96543beb006838f2f3b1d220a52402dd05d8f7e Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 8 Jan 2022 16:43:46 +0000 Subject: [PATCH 111/190] Add APIv2 to deploy scripts --- .github/deploy-release.sh | 8 +++++++ .github/deploy-staging.sh | 8 +++++++ po-utils/pom.xml | 20 +++++++++++++++-- pom.xml | 5 +++++ uSkyBlock-API/pom.xml | 26 ++++++++++++++++++---- uSkyBlock-APIv2/pom.xml | 47 +++++++++++++-------------------------- uSkyBlock-AWE370/pom.xml | 17 ++++++++++++++ uSkyBlock-Core/pom.xml | 18 +++++++++++++++ uSkyBlock-FAWE/pom.xml | 12 ++++++++++ 9 files changed, 123 insertions(+), 38 deletions(-) diff --git a/.github/deploy-release.sh b/.github/deploy-release.sh index e28f212d1..cc8cdbfe2 100644 --- a/.github/deploy-release.sh +++ b/.github/deploy-release.sh @@ -16,6 +16,10 @@ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ @@ -42,6 +46,10 @@ rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-API/ +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-APIv2/ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-Core/ diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh index 0c52006c5..adc899db5 100644 --- a/.github/deploy-staging.sh +++ b/.github/deploy-staging.sh @@ -16,6 +16,10 @@ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ +travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ @@ -42,6 +46,10 @@ rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ +rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/site/apidocs/ \ +travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-APIv2/ + rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ diff --git a/po-utils/pom.xml b/po-utils/pom.xml index b9d4a156d..57707c709 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -55,18 +55,22 @@ org.apache.maven.plugins maven-jar-plugin - 3.1.2 org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 public false none + + attach-javadocs + + jar + + javadoc @@ -75,6 +79,18 @@ + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/pom.xml b/pom.xml index 6900c0477..55c461416 100644 --- a/pom.xml +++ b/pom.xml @@ -87,6 +87,11 @@ maven-shade-plugin 3.3.0-SNAPSHOT + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + org.apache.maven.plugins maven-surefire-plugin diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index e0adee020..995494255 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -49,25 +49,30 @@ maven-compiler-plugin 3.8.1 - 1.8 - 1.8 + 17 org.apache.maven.plugins maven-jar-plugin - 3.1.2 + 3.2.0 org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 + 3.2.0 public false none + + attach-javadocs + + jar + + javadoc @@ -76,6 +81,19 @@ + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index f7cbcfa3f..8c184c9f5 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -23,31 +23,6 @@ org.jetbrains annotations - - - junit - junit - ${junit.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-vintage-engine.version} - test - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${hamcrest.version} - test - @@ -62,18 +37,22 @@ org.apache.maven.plugins maven-jar-plugin - 3.1.2 org.apache.maven.plugins maven-javadoc-plugin - 3.1.0 public false none + + attach-javadocs + + jar + + javadoc @@ -84,11 +63,15 @@ org.apache.maven.plugins - maven-surefire-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin + maven-source-plugin + + + attach-sources + + jar + + + diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index 2a6577358..bd219534d 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -48,4 +48,21 @@ + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index fadf7ad6b..b2ebf4397 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -185,6 +185,12 @@ none + + attach-javadocs + + jar + + javadoc @@ -193,6 +199,18 @@ + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 26d15f20c..e93248660 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -79,6 +79,18 @@ + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + From c41f1c43bf19ad06fa6ce6cd0fd1e5adba2e3c1d Mon Sep 17 00:00:00 2001 From: Jan Chaloupka Date: Thu, 10 Feb 2022 14:19:58 +0100 Subject: [PATCH 112/190] Update region limits to reflect the new 1.18 world height (#36) * Update region limits to reflect the new 1.18 world height Some of the players on our server are complaining that they cannot build below Y0 after the new 1.18 update. I briefly looked into the code and found that the minimum and maximum region height values are hard coded to the old world limits. I propose to change these values to reflect the new world height limits. * Get WG region height limits from API (removed hardcoded value) * Fixed biome changing Y<0 in 1.18 world * Fixed score calculation in 1.18 worlds * Reworked world height constants to make the code compaible with 1.18 worlds * Fixed off by one maximum height value (returned number is exclusive - 320 souhld be 319) * Fix for FAWE depencency (requires FAWE v2+) --- .../handler/asyncworldedit/AWE370Adaptor.java | 2 +- .../handler/AsyncWorldEditHandler.java | 2 +- .../handler/WorldGuardHandler.java | 9 +++++--- .../handler/task/WorldEditClear.java | 2 +- .../island/level/ChunkSnapshotLevelLogic.java | 5 +++- .../island/task/SetBiomeTask.java | 2 +- uSkyBlock-FAWE/pom.xml | 23 +++++++++++-------- .../handler/asyncworldedit/FAWEAdaptor.java | 5 ++-- 8 files changed, 30 insertions(+), 20 deletions(-) diff --git a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java index c102563ed..ff675a560 100644 --- a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java +++ b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java @@ -111,7 +111,7 @@ public void registerCompletion(Player player) { public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { final IAsyncWorldEdit awe = getAWE(); BukkitWorld bukkitWorld = new BukkitWorld(origin.getWorld()); - int maxBlocks = (255 * Settings.island_protectionRange * Settings.island_protectionRange); + int maxBlocks = ((bukkitWorld.getMaxY() - bukkitWorld.getMinY()) * Settings.island_protectionRange * Settings.island_protectionRange); IPlayerManager pm = awe.getPlayerManager(); final IPlayerEntry playerEntry = pm.getUnknownPlayer(); IThreadSafeEditSession tsSession = (IThreadSafeEditSession) createEditSession(bukkitWorld, maxBlocks); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 6ce4d308b..4e6919993 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -128,7 +128,7 @@ public void regenerate(final Region region, final Runnable onCompletion) { @Override public void run() { try { - final EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), region.getArea() * 255); + final EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), (int) region.getVolume()); editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); editSession.setSideEffectApplier(SideEffectSet.defaults()); editSession.getWorld().regenerate(region, editSession); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index f1e6d64f1..48dcbd27d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -214,11 +214,13 @@ public static void islandUnlock(final CommandSender sender, final String islandN } public static BlockVector3 getProtectionVectorLeft(final Location island) { - return BlockVector3.at(island.getX() + Settings.island_radius - 1, 255.0, island.getZ() + Settings.island_radius - 1); + World world = island.getWorld(); + return BlockVector3.at(island.getX() + Settings.island_radius - 1, world.getMaxHeight() - 1, island.getZ() + Settings.island_radius - 1); } public static BlockVector3 getProtectionVectorRight(final Location island) { - return BlockVector3.at(island.getX() - Settings.island_radius, 0.0, island.getZ() - Settings.island_radius); + World world = island.getWorld(); + return BlockVector3.at(island.getX() - Settings.island_radius, world.getMinHeight(), island.getZ() - Settings.island_radius); } public static String getIslandNameAt(Location location) { @@ -322,7 +324,8 @@ public static boolean isIslandIntersectingSpawn(Location islandLocation) { if (r == 0) { return false; } - ProtectedRegion spawn = new ProtectedCuboidRegion("spawn", BlockVector3.at(-r, 0, -r), BlockVector3.at(r, 255, r)); + World world = islandLocation.getWorld(); + ProtectedRegion spawn = new ProtectedCuboidRegion("spawn", BlockVector3.at(-r, world.getMinHeight(), -r), BlockVector3.at(r, world.getMaxHeight() - 1, r)); ProtectedCuboidRegion islandRegion = getIslandRegion(islandLocation); return !islandRegion.getIntersectingRegions(Collections.singletonList(spawn)).isEmpty(); } catch (Exception e) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java index 9e19a049b..9466aaeb7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java @@ -74,7 +74,7 @@ protected boolean execute() { while (!regions.isEmpty()) { final Region region = regions.remove(0); final EditSession editSession = WorldEditHandler.createEditSession( - new BukkitWorld(world), region.getArea() * 255); + new BukkitWorld(world), (int) region.getVolume()); editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); editSession.setSideEffectApplier(SideEffectSet.defaults()); try { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java index a251abfc4..c9ec97f7a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java @@ -65,8 +65,11 @@ private IslandScore calculateScore(ProtectedRegion region, List s final BlockCountCollection counts = new BlockCountCollection(scoreMap); int minX = region.getMinimumPoint().getBlockX(); int maxX = region.getMaximumPoint().getBlockX(); + int minY = region.getMinimumPoint().getBlockY(); + int maxY = region.getMaximumPoint().getBlockY(); int minZ = region.getMinimumPoint().getBlockZ(); int maxZ = region.getMaximumPoint().getBlockZ(); + for (int x = minX; x <= maxX; ++x) { for (int z = minZ; z <= maxZ; ++z) { ChunkSnapshot chunk = getChunkSnapshot(x >> 4, z >> 4, snapshotsOverworld); @@ -77,7 +80,7 @@ private IslandScore calculateScore(ProtectedRegion region, List s } int cx = (x & 0xf); int cz = (z & 0xf); - for (int y = 0; y <= 255; y++) { + for (int y = minY; y < maxY; y++) { Material blockType = chunk.getBlockType(cx, y, cz); if (blockType == Material.AIR) { continue; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java index b7f36784c..32285da7b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java @@ -77,7 +77,7 @@ protected boolean execute() { } for (int x = cx; x <= mx; x++) { for (int z = cz; z <= mz; z++) { - for (int y = 0; y < world.getMaxHeight(); y++) { + for (int y = world.getMinHeight(); y < world.getMaxHeight(); y++) { world.setBiome(x, y, z, biome); } } diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index e93248660..035024a44 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -10,19 +10,24 @@ 4.0.0 uSkyBlock-FAWE - - - IntellectualSites - https://mvn.intellectualsites.com/content/repositories/releases/ - - - com.fastasyncworldedit - FAWE-Bukkit - 1.17-268 + FastAsyncWorldEdit-Core + 2.0.1 + provided + + + com.fastasyncworldedit + FastAsyncWorldEdit-Bukkit + 2.0.1 provided + + + FastAsyncWorldEdit-Core + * + + ovh.uskyblock diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index 3b5a00a11..5e538560a 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -1,6 +1,6 @@ package us.talabrek.ultimateskyblock.handler.asyncworldedit; -import com.fastasyncworldedit.core.util.EditSessionBuilder; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; @@ -10,7 +10,6 @@ import com.sk89q.worldedit.world.World; import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -72,7 +71,7 @@ private synchronized EditSession getEditSession(PlayerPerk playerPerk, Location } public EditSession createEditSession(World bukkitWorld, int maxBlocks) { - return new EditSessionBuilder(bukkitWorld).fastmode(true).build(); + return WorldEdit.getInstance().newEditSessionBuilder().world(bukkitWorld).fastMode(true).build(); } @Override From 472063dbaaacebc560df003eb49b5955de2f7986 Mon Sep 17 00:00:00 2001 From: Muspah Date: Thu, 10 Feb 2022 13:28:08 +0000 Subject: [PATCH 113/190] Add getPlayerProfile method to NullPlayer --- .../java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java index f31e43674..8c8d903c0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java @@ -6,6 +6,7 @@ import org.bukkit.Statistic; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.profile.PlayerProfile; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -31,6 +32,12 @@ public UUID getUniqueId() { return PlayerDB.UNKNOWN_PLAYER_UUID; } + @NotNull + @Override + public PlayerProfile getPlayerProfile() { + return null; + } + @Override public boolean isBanned() { return false; From 26b4322186be38af2da7299824efad4c3746c9a4 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 13 Aug 2022 12:23:37 +0200 Subject: [PATCH 114/190] Bump to MC 1.19 --- pom.xml | 17 +++++++++-------- uSkyBlock-API/pom.xml | 4 ++-- uSkyBlock-Core/pom.xml | 16 +++++++++++----- .../ultimateskyblock/challenge/EntityMatch.java | 2 +- .../handler/WorldEditHandler.java | 2 +- .../ultimateskyblock/island/IslandInfo.java | 2 +- .../ultimateskyblock/player/PlayerInfo.java | 2 +- .../ultimateskyblock/player/TeleportLogic.java | 2 +- .../ultimateskyblock/util/LocationUtil.java | 2 +- .../ultimateskyblock/uuid/NullPlayer.java | 7 +++++++ .../world/ChunkRegenerator.java | 2 +- .../ultimateskyblock/world/WorldManager.java | 2 +- uSkyBlock-FAWE/pom.xml | 10 ++++++++-- 13 files changed, 45 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 55c461416..be2882d87 100644 --- a/pom.xml +++ b/pom.xml @@ -8,19 +8,19 @@ Ultimate SkyBlock - 4.9.3 - 4.0.1 + 4.11.0 + 4.1.2 4.5.13 2.8.9 23.0.0 - 3.8.4 + 3.8.6 ${project.version} 1.25-SNAPSHOT 1.0.7 - 1.18.1-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT 1.7 - 7.2.8 - 7.0.6 + 7.2.12 + 7.0.8-SNAPSHOT UTF-8 ${project.artifactId} @@ -32,7 +32,7 @@ 2.2 4.13.2 - 5.8.2 + 5.9.0 3.12.4 @@ -138,7 +138,8 @@ sk89q-repo - https://maven.sk89q.com/repo/ + + https://maven.enginehub.org/repo/ sonatype-oss-snapshots diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 995494255..26b09adb3 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -31,7 +31,7 @@ org.spigotmc spigot-api - 1.18.1-R0.1-SNAPSHOT + 1.19-R0.1-SNAPSHOT provided true @@ -39,7 +39,7 @@ org.jetbrains annotations - 22.0.0 + 23.0.0 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index b2ebf4397..3e627f042 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -465,7 +465,7 @@ org.bstats bstats-bukkit - 2.2.1 + 3.0.0 compile @@ -511,10 +511,16 @@ annotations - commons-lang - commons-lang - 2.6 - provided + org.apache.commons + commons-lang3 + 3.12.0 + compile + + + org.apache.commons + commons-text + 1.9 + compile diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java index 4896aeb06..2f1660977 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.challenge; import com.google.gson.Gson; -import org.apache.commons.lang.WordUtils; +import org.apache.commons.text.WordUtils; import org.bukkit.DyeColor; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java index d2237cd03..71a05ed7a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java @@ -16,7 +16,7 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 268a63cf9..8d7140a82 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.island; import dk.lockfuglsang.minecraft.util.TimeUtil; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 63fff2f2e..666eda583 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -2,7 +2,7 @@ import dk.lockfuglsang.minecraft.file.FileUtil; import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.OfflinePlayer; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java index 00bb9c137..9f3140eba 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.player; import io.papermc.lib.PaperLib; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java index 8463f0687..a6c0be86d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/LocationUtil.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.util; import dk.lockfuglsang.minecraft.po.I18nUtil; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.Bukkit; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java index 8c8d903c0..24bdd4d9e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.profile.PlayerProfile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.UUID; @@ -168,6 +169,12 @@ public void setStatistic(@NotNull Statistic statistic, @NotNull EntityType entit } + @Nullable + @Override + public Location getLastDeathLocation() { + return null; + } + @Override public Map serialize() { return null; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java index 20007d69c..15140ab1b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java @@ -1,6 +1,6 @@ package us.talabrek.ultimateskyblock.world; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.block.Biome; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index 6f4eae20c..8e9c75289 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -1,6 +1,6 @@ package us.talabrek.ultimateskyblock.world; -import org.apache.commons.lang.Validate; +import org.apache.commons.lang3.Validate; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 035024a44..88df325ad 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -14,13 +14,19 @@ com.fastasyncworldedit FastAsyncWorldEdit-Core - 2.0.1 + 2.4.3 provided + + + net.kyori + adventure-text-minimessage + + com.fastasyncworldedit FastAsyncWorldEdit-Bukkit - 2.0.1 + 2.4.3 provided From c3ae19c34409de1ce62ee26d80b8ac9ca8fe5be3 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 13 Aug 2022 12:33:12 +0200 Subject: [PATCH 115/190] Maven-shade-plugin to 3.3.1-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index be2882d87..9af28c192 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.apache.maven.plugins From ce74782fd80bb03ead8294809d3920a04108749e Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 13 Aug 2022 12:42:03 +0200 Subject: [PATCH 116/190] Bump GH Actions plugin versions --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a07ac9832..4ecf294d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Checkout submodules run: | sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules @@ -23,14 +23,14 @@ jobs: cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - - name: JDK 17 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' - name: Install gettext run: sudo apt-get install -y gettext - name: Cache Maven repository - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} From 19766d712cc5dd97817f2052023b9519ad135c31 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 13 Aug 2022 16:17:22 +0200 Subject: [PATCH 117/190] Finally, bump dependency checks in plugin and api-version in plugin.yml --- .../main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 6 +++--- uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index ca8414083..cfba262c0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -118,9 +118,9 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private static final String CN = uSkyBlock.class.getName(); private static final String[][] depends = new String[][]{ new String[]{"Vault", "1.7.1", "optional"}, - new String[]{"WorldEdit", "7.2.8", "optionalIf", "FastAsyncWorldEdit"}, - new String[]{"WorldGuard", "7.0.6"}, - new String[]{"FastAsyncWorldEdit", "2.0.0", "optional"}, + new String[]{"WorldEdit", "7.2.12", "optionalIf", "FastAsyncWorldEdit"}, + new String[]{"WorldGuard", "7.0.8"}, + new String[]{"FastAsyncWorldEdit", "2.4.3", "optional"}, new String[]{"Multiverse-Core", "4.3.1", "optional"}, new String[]{"Multiverse-Portals", "4.2.1", "optional"}, new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 4f43f072c..08284986f 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -18,7 +18,7 @@ softdepend: - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.18 +api-version: 1.19 commands: challenges: From e366129c4ab782cc0d3f2c55992a315688a7334a Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Mon, 13 Feb 2023 11:06:20 +0100 Subject: [PATCH 118/190] Fix biome permissions with new Biome IDs (#43) * Fix a biome permission given by a challenge The slimefarmer challenge was giving the permission usb.biome.swampland but the enum value in org.bukkit.block.Biome is named SWAMP (probably changed by a Bukkit API update) * Also update plugin.yml about biome permissions * All biomes are updated in plugin.yml --- .../src/main/resources/challenges.yml | 2 +- uSkyBlock-Core/src/main/resources/plugin.yml | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/uSkyBlock-Core/src/main/resources/challenges.yml b/uSkyBlock-Core/src/main/resources/challenges.yml index d9974839d..daf9b5607 100644 --- a/uSkyBlock-Core/src/main/resources/challenges.yml +++ b/uSkyBlock-Core/src/main/resources/challenges.yml @@ -1055,7 +1055,7 @@ ranks: items: - DIAMOND:1 - EMERALD:1 - permission: usb.biome.swampland + permission: usb.biome.swamp currency: 70 xp: 70 repeatReward: diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 08284986f..4c20f997b 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -174,15 +174,15 @@ permissions: children: usb.biome.deep_ocean: true usb.biome.desert: true - usb.biome.extreme_hills: true + usb.biome.windswept_hills: true usb.biome.forest: true - usb.biome.hell: true + usb.biome.nether_wastes: true usb.biome.jungle: true - usb.biome.mushroom: true + usb.biome.mushroom_fields: true usb.biome.ocean: false # default: true usb.biome.plains: true - usb.biome.sky: true - usb.biome.swampland: true + usb.biome.the_end: true + usb.biome.swamp: true usb.biome.taiga: true usb.exempt.*: @@ -390,25 +390,25 @@ permissions: default: false description: 'Let the player change their islands biome to DESERT' - usb.biome.extreme_hills: + usb.biome.windswept_hills: default: false - description: 'Let the player change their islands biome to EXTREME_HILLS' + description: 'Let the player change their islands biome to WINDSWEPT_HILLS' usb.biome.forest: default: false description: 'Let the player change their islands biome to FOREST' - usb.biome.hell: + usb.biome.nether_wastes: default: false - description: 'Let the player change their islands biome to HELL' + description: 'Let the player change their islands biome to NETHER_WASTES' usb.biome.jungle: default: false description: 'Let the player change their islands biome to JUNGLE' - usb.biome.mushroom: + usb.biome.mushroom_fields: default: false - description: 'Let the player change their islands biome to MUSHROOM' + description: 'Let the player change their islands biome to MUSHROOM_FIELDS' usb.biome.ocean: default: true @@ -418,13 +418,13 @@ permissions: default: false description: 'Let the player change their islands biome to PLAINS' - usb.biome.sky: + usb.biome.the_end: default: false - description: 'Let the player change their islands biome to SKY' + description: 'Let the player change their islands biome to THE_END' - usb.biome.swampland: + usb.biome.swamp: default: false - description: 'Let the player change their islands biome to SWAMPLAND' + description: 'Let the player change their islands biome to SWAMP' usb.biome.taiga: default: false From cd46d2c90423424c0c228f801e334796a76e9885 Mon Sep 17 00:00:00 2001 From: Muspah Date: Tue, 14 Mar 2023 23:56:23 +0100 Subject: [PATCH 119/190] Shade apache commons --- pom.xml | 8 ++++---- uSkyBlock-Core/pom.xml | 7 ++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9af28c192..4658fd7b6 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 17 @@ -75,17 +75,17 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.3.0 org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + 3.4.1 org.apache.maven.plugins maven-shade-plugin - 3.3.1-SNAPSHOT + 3.4.1 org.apache.maven.plugins diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 3e627f042..dfec332d4 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -88,6 +88,7 @@ net.kyori:* org.apache.httpcomponents:httpclient org.apache.maven:maven-artifact + org.apache.commons:* org.bstats:* ovh.uskyblock:po-utils @@ -109,6 +110,10 @@ net.kyori us.talabrek.ultimateskyblock.kyori + + org.apache.commons + us.talabrek.ultimateskyblock.apache.commons + org.apache.httpcomponents us.talabrek.ultimateskyblock.apache.httpcomponents @@ -519,7 +524,7 @@ org.apache.commons commons-text - 1.9 + 1.10.0 compile From 39e88ca50e5454fd2e0318ed97b98c376360385f Mon Sep 17 00:00:00 2001 From: Muspah Date: Fri, 17 Mar 2023 17:35:08 +0100 Subject: [PATCH 120/190] Bump dependencies --- pom.xml | 10 +++++----- uSkyBlock-Core/pom.xml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 4658fd7b6..2d4cb3545 100644 --- a/pom.xml +++ b/pom.xml @@ -8,18 +8,18 @@ Ultimate SkyBlock - 4.11.0 - 4.1.2 - 4.5.13 + 4.13.0 + 4.3.0 + 4.5.14 2.8.9 23.0.0 3.8.6 ${project.version} 1.25-SNAPSHOT - 1.0.7 + 1.0.8 1.19-R0.1-SNAPSHOT 1.7 - 7.2.12 + 7.2.13 7.0.8-SNAPSHOT UTF-8 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index dfec332d4..50976c22e 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -417,7 +417,7 @@ com.onarandombox.multiversecore Multiverse-Core - 4.1.0 + 4.3.1 provided true @@ -430,7 +430,7 @@ com.onarandombox.multiverseinventories Multiverse-Inventories - 3.0.0 + 4.2.3 provided true @@ -470,7 +470,7 @@ org.bstats bstats-bukkit - 3.0.0 + 3.0.1 compile From cdb4ebfc530a31c532d427c067bc9f51c21bcaf0 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 18 Mar 2023 10:48:31 +0100 Subject: [PATCH 121/190] Show correct error message when player is in another party (as member) (#45) --- .../talabrek/ultimateskyblock/command/InviteHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java index 30ddf8b67..568616fad 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java @@ -51,9 +51,10 @@ private synchronized void invite(Player player, final IslandInfo island, Player } if (oPi.getHasIsland()) { us.talabrek.ultimateskyblock.api.IslandInfo oIsland = plugin.getIslandInfo(oPi); - if (oIsland.isParty() && oIsland.isLeader(otherPlayer)) { - player.sendMessage(tr("\u00a74That player is already leader on another island.")); - otherPlayer.sendMessage(tr("\u00a7e{0}\u00a7e tried to invite you, but you are already in a party.", player.getDisplayName())); + if (oIsland.isParty() && !oIsland.isLeader(otherPlayer)) { + player.sendMessage(tr("§4That player is already member on another island. ")); + otherPlayer.sendMessage(tr("§e{0}§e tried to invite you, but you are already in a party." + + "To leave your current party, use: /island leave.", player.getDisplayName())); return; } } From 6710732957a5d2d41540dfe2e3d9f16695a4d10d Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Mar 2023 19:08:05 +0100 Subject: [PATCH 122/190] Version 3.0.0 --- README.md | 14 ++++++-------- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-APIv2/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 9 files changed, 14 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a08fafa9c..af9930c47 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,12 @@ We are on [Spigot](https://www.spigotmc.org/resources/uskyblock-revived.66795/). This version depends on the following plugins: -* Spigot/Paper 1.18.1-R0.1-SNAPSHOT +* Spigot/Paper 1.19-R0.1-SNAPSHOT * Vault 1.7.x -* WorldEdit 7.2.8 -* WorldGuard 7.0.6 - -## Releases -[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/rlf/uSkyBlock.svg)](http://isitmaintained.com/project/rlf/uSkyBlock "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/rlf/uSkyBlock.svg)](http://isitmaintained.com/project/rlf/uSkyBlock "Percentage of issues still open") +* WorldEdit 7.2.13 +* WorldGuard 7.0.8-SNAPSHOT +## Releases https://www.spigotmc.org/resources/uskyblock-revived.66795/history Pre-releases will end in -SNAPSHOT, and is considered **unsafe** for production servers. @@ -31,7 +29,7 @@ dependencies to: ovh.uskyblock uSkyBlock-Core - 3.0.0-SNAPSHOT + 3.0.0 ``` @@ -41,7 +39,7 @@ We're moving new API features towards APIv2, which is available as: ovh.uskyblock uSkyBlock-APIv2 - 3.0.0-SNAPSHOT + 3.0.0 ``` diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 57707c709..fc08818ad 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 jar diff --git a/pom.xml b/pom.xml index 2d4cb3545..094f463a2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ovh.uskyblock uSkyBlock pom - 3.0.0-SNAPSHOT + 3.0.0 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 26b09adb3..d88f102b1 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 3.0.0-SNAPSHOT + 3.0.0 UTF-8 diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index 8c184c9f5..1d517dd29 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 jar diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index bd219534d..e23e62269 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 50976c22e..603dfbbed 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 88df325ad..9cd7a3806 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 470e15d9e..a75b0a17b 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0-SNAPSHOT + 3.0.0 4.0.0 jar From 44739575a05bc66f46cbed78897465669d591a81 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sat, 18 Mar 2023 19:28:54 +0100 Subject: [PATCH 123/190] v3.1.0-SNAPSHOT --- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 2 +- uSkyBlock-APIv2/pom.xml | 2 +- uSkyBlock-AWE370/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 2 +- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/po-utils/pom.xml b/po-utils/pom.xml index fc08818ad..ebe67b21d 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index 094f463a2..10d99982e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ovh.uskyblock uSkyBlock pom - 3.0.0 + 3.1.0-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index d88f102b1..58598ccca 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -6,7 +6,7 @@ com.github.rlf uSkyBlock-API - 3.0.0 + 3.1.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index 1d517dd29..10bd75876 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml index e23e62269..94be33f46 100644 --- a/uSkyBlock-AWE370/pom.xml +++ b/uSkyBlock-AWE370/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 uSkyBlock-AWE370 diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 603dfbbed..20d135d6e 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index 9cd7a3806..aab556bb4 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index a75b0a17b..bd1861267 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.0.0 + 3.1.0-SNAPSHOT 4.0.0 jar From 5e68ef49c87a4935cf43dbc7910babf2ff1dd027 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sun, 7 Apr 2024 21:12:37 +0200 Subject: [PATCH 124/190] Update to 1.20.4 (and also fix some stuff) (#46) * Also update the biome IDs in the biome GUI * Bump to MC 1.20.4 * Fix display.Name item tag in configmenu.yml interfering with I18nUtil.tr in recent version of Paper It is needed to set the display name of an item in Json format to avoid implicit interpretation of the value of the tag. Here, the 2 items was named "'{'" and "'}'", but the resent version of Paper interpreted it as "{" and "}" without the single quotes, messing with the formatter of I18nUtil.tr() method. --- pom.xml | 10 +++--- uSkyBlock-API/pom.xml | 2 +- .../ultimateskyblock/menu/SkyBlockMenu.java | 18 +++++----- .../ultimateskyblock/uuid/NullPlayer.java | 36 +++++++++++++++++++ .../src/main/resources/configmenu.yml | 6 ++-- .../ultimateskyblock/util/BlockUtilTest.java | 2 +- 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 10d99982e..e6e3562b1 100644 --- a/pom.xml +++ b/pom.xml @@ -8,19 +8,19 @@ Ultimate SkyBlock - 4.13.0 + 4.15.0 4.3.0 4.5.14 - 2.8.9 + 2.10.1 23.0.0 3.8.6 ${project.version} 1.25-SNAPSHOT 1.0.8 - 1.19-R0.1-SNAPSHOT + 1.20.4-R0.1-SNAPSHOT 1.7 - 7.2.13 - 7.0.8-SNAPSHOT + 7.2.19 + 7.0.9 UTF-8 ${project.artifactId} diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 58598ccca..339148212 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -31,7 +31,7 @@ org.spigotmc spigot-api - 1.19-R0.1-SNAPSHOT + 1.20.4-R0.1-SNAPSHOT provided true diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 3d2c0a05a..ac1e3441f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -96,7 +96,7 @@ public class SkyBlockMenu { tr("The jungle biome is bright\nand colorful. Passive mobs\n(including ocelots) will\nspawn. Hostile mobs will\nspawn normally.") ), new BiomeMenuItem(new ItemStack(Material.LILY_PAD, 1), - "swampland", tr("Swampland"), + "swamp", tr("Swampland"), tr("The swamp biome is dark\nand dull. Passive mobs\nwill spawn normally and\nslimes have a small chance\nto spawn at night depending\non the moon phase.") ), new BiomeMenuItem(new ItemStack(Material.SNOW, 1), @@ -104,15 +104,15 @@ public class SkyBlockMenu { tr("The taiga biome has snow\ninstead of rain. Passive\nmobs will spawn normally\n(including wolves) and\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.RED_MUSHROOM, 1), - "mushroom", tr("Mushroom"), + "mushroom_fields", tr("Mushroom"), tr("The mushroom biome is\nbright and colorful.\nMooshrooms are the only\nmobs that will spawn.\nNo other passive or\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.NETHER_BRICK, 1), - "hell", tr("Hell"), + "nether_wastes", tr("Hell"), tr("The hell biome looks\ndark and dead. Some\nmobs from the nether will\nspawn in this biome\n(excluding ghasts and\nblazes).") ), new BiomeMenuItem(new ItemStack(Material.ENDER_EYE, 1), - "sky", tr("Sky"), + "the_end", tr("Sky"), tr("The sky biome gives your\nisland a special dark sky.\nOnly endermen will spawn\nin this biome.") ), new BiomeMenuItem(new ItemStack(Material.TALL_GRASS, 1), @@ -120,7 +120,7 @@ public class SkyBlockMenu { tr("The plains biome has rain\ninstead of snow. Passive\nmobs will spawn normally\n(including horses) and\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.EMERALD_ORE, 1), - "extreme_hills", tr("Extreme Hills"), + "windswept_hills", tr("Extreme Hills"), tr("The extreme hills biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.ROSE_BUSH, 1), @@ -136,7 +136,7 @@ public class SkyBlockMenu { "spawn normally.") ), new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), - "ice_plains", tr("Ice Plains"), + "snowy_plains", tr("Ice Plains"), tr("The ice-plains biome is an advanced biome.\nMobs will spawn naturally.\nincluding polar-bears") ) ); @@ -552,7 +552,7 @@ private Inventory createInitMenu(Player player) { } lores.clear(); - menuItem = new ItemStack(Material.GRASS, 1); + menuItem = new ItemStack(Material.SHORT_GRASS, 1); meta = menuItem.getItemMeta(); meta.setDisplayName(tr("\u00a7a\u00a7lReturn to Spawn")); addLore(lores, "\u00a7f", tr("Teleport to the spawn area.")); @@ -698,7 +698,7 @@ private Inventory createMainMenu(Player player) { menu.addItem(menuItem); lores.clear(); - menuItem = new ItemStack(Material.GRASS, 1); + menuItem = new ItemStack(Material.SHORT_GRASS, 1); meta4 = menuItem.getItemMeta(); meta4.setDisplayName(tr("\u00a7a\u00a7lReturn to Spawn")); addLore(lores, "\u00a7f", tr("Teleport to the spawn area.")); @@ -866,7 +866,7 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P } else if (currentItem.getType() == Material.RED_BED) { p.performCommand("island sethome"); p.performCommand("island"); - } else if (currentItem.getType() == Material.GRASS) { + } else if (currentItem.getType() == Material.SHORT_GRASS) { p.performCommand("island spawn"); } else if (currentItem.getType() == Material.HOPPER) { p.performCommand("island setwarp"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java index 24bdd4d9e..b83fc740d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.uuid; +import org.bukkit.BanEntry; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; @@ -10,6 +11,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; import java.util.Map; import java.util.UUID; @@ -44,6 +48,24 @@ public boolean isBanned() { return false; } + @Nullable + @Override + public BanEntry ban(@Nullable String s, @Nullable Date date, @Nullable String s1) { + return null; + } + + @Nullable + @Override + public BanEntry ban(@Nullable String s, @Nullable Instant instant, @Nullable String s1) { + return null; + } + + @Nullable + @Override + public BanEntry ban(@Nullable String s, @Nullable Duration duration, @Nullable String s1) { + return null; + } + @Override public boolean isWhitelisted() { return true; @@ -79,6 +101,12 @@ public Location getBedSpawnLocation() { return null; } + @Nullable + @Override + public Location getRespawnLocation() { + return null; + } + @Override public void incrementStatistic(@NotNull Statistic statistic) throws IllegalArgumentException { @@ -175,6 +203,12 @@ public Location getLastDeathLocation() { return null; } + @Nullable + @Override + public Location getLocation() { + return null; + } + @Override public Map serialize() { return null; @@ -189,4 +223,6 @@ public boolean isOp() { public void setOp(boolean b) { } + + } diff --git a/uSkyBlock-Core/src/main/resources/configmenu.yml b/uSkyBlock-Core/src/main/resources/configmenu.yml index eeb4c1c32..7d44d7537 100644 --- a/uSkyBlock-Core/src/main/resources/configmenu.yml +++ b/uSkyBlock-Core/src/main/resources/configmenu.yml @@ -111,11 +111,11 @@ keyboard: 1: '{display:{Name:"+"},SkullOwner:{Id:"80e287ca-69a7-4a03-8811-324a469079b9",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWUzOTVlNzVlMmViOGM0YjcyNDRkY2RiNzVjNTdhNmQ3YWRmMzc1NTNmMjFkNDRlZmM3YmQ3MTQxODQzNDVkIn19fQ=="}]}}}' 7: '{display:{Name:"("},SkullOwner:{Id:"dc61f26c-79f0-45b8-be4c-fad9fef6e0d1",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA3MWNiMTc3ZDQ1OTdkNGY1MWE2NjM3NWVmOWIwMTQyY2Q2OGMzZTljNjRhZWJiNjJmMTZlM2MzOTAxNDJmIn19fQ=="}]}}}' 8: '{display:{Name:")"},SkullOwner:{Id:"d9d19efe-cb96-4e6a-a7a0-29aed68e958c",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNjNzJlZjBlOTQ0MmM1YjY3YTUwYTY5YjI5ZWUxMDRmODExZmFkYTZiZmVkZTJlY2RiM2I1YjU1NTAifX19"}]}}}' - 16: '{display:{Name:"''{''"},SkullOwner:{Id:"5e1368b1-c858-4748-b2bb-e92c76700554",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5OTMyY2ZhZTc1ZDM4ZjdjNzFmN2Y5NTNkMThmNmI2MGZjYjg4NThkMWQ5YjQ5YTE1ZDc2NmJjY2IyNThmNiJ9fX0="}]}}}' - 17: '{display:{Name:"''}''"},SkullOwner:{Id:"4fbb057e-7eeb-4cfb-8cfc-ad2739fddedf",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiOGIxMWQ2NWUwZDA2OGQzYTk0OWM0MWVmNGQxMmUxODNjZmFlZWE0NGZmYzY4ZWM0MzliNWQ5NzcxMjcifX19"}]}}}' + 16: '{display:{Name:"{\"text\":\"''{''\"}"},SkullOwner:{Id:"5e1368b1-c858-4748-b2bb-e92c76700554",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5OTMyY2ZhZTc1ZDM4ZjdjNzFmN2Y5NTNkMThmNmI2MGZjYjg4NThkMWQ5YjQ5YTE1ZDc2NmJjY2IyNThmNiJ9fX0="}]}}}' + 17: '{display:{Name:"{\"text\":\"''}''\"}"},SkullOwner:{Id:"4fbb057e-7eeb-4cfb-8cfc-ad2739fddedf",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiOGIxMWQ2NWUwZDA2OGQzYTk0OWM0MWVmNGQxMmUxODNjZmFlZWE0NGZmYzY4ZWM0MzliNWQ5NzcxMjcifX19"}]}}}' 25: '{display:{Name:"["},SkullOwner:{Id:"68f2f3b4-e105-4887-9765-68200e7a831b",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTM0YTlmYTlkMmNlNTY4YWUyYjIxZWRhMGNiMzM5NGZlNTJkNjc4M2I0ZmViYWFhOTFmMjg2ZmY5MzMyIn19fQ=="}]}}}' 26: '{display:{Name:"]"},SkullOwner:{Id:"00962524-4195-4480-9a1b-f9e67178dca9",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTQ4YjY5ZWMxNTViMTg3Mzc2Yjg4YmMwMzg0ZDI1NTM4ZGRlZDlkYjgzOWVhYmI1OWU0NjE4ZWE0NiJ9fX0="}]}}}' 31: '{display:{Name:"*"},SkullOwner:{Id:"0fa2efdb-cfca-4853-8335-9f0ae1e70b49",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwZThlZmExY2QwNzI4Mjk3NDdhNjk3NzM3OTE2OTVmODBjZmFlOGJmYTg3MmZiMWIyOGEyMTFlZDAzMSJ9fX0="}]}}}' 47: '{display:{Name:">"},SkullOwner:{Id:"6d6a08e5-e1ad-4c81-b4cc-e7fbee8766db",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzEwZTE0OWI2NTE2MzgyZTM2ZGQ2YzRjOTk3ZDg4OWQwNDZkMTNiNTQzM2Y1YWZlYjNiYTVmYjlkYWI0MmY5In19fQ=="}]}}}' # DO NOT TOUCH THESE -version: 2 \ No newline at end of file +version: 2 diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java index 854dc4d33..8d311ea87 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java @@ -14,7 +14,7 @@ public void testIsBreathable() throws Exception { Mockito.when(fakeBlock.getType()).thenReturn(Material.DIRT); Assert.assertFalse(BlockUtil.isBreathable(fakeBlock)); - Mockito.when(fakeBlock.getType()).thenReturn(Material.GRASS); + Mockito.when(fakeBlock.getType()).thenReturn(Material.SHORT_GRASS); Assert.assertTrue(BlockUtil.isBreathable(fakeBlock)); Mockito.when(fakeBlock.getType()).thenReturn(Material.WATER); From f957d08323ca47692727789b8643b2b811a2cfb3 Mon Sep 17 00:00:00 2001 From: Matthew Gajownik Date: Mon, 8 Apr 2024 16:00:58 +1000 Subject: [PATCH 125/190] Don't hijack respawn event in unrelated worlds (#52) --- .../talabrek/ultimateskyblock/event/PlayerEvents.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index c1016c7ae..cc230a133 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -3,6 +3,7 @@ import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Levelled; @@ -35,6 +36,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.*; @@ -254,6 +256,12 @@ private void cancelMemberDamage(Player attacker, Player victim, EntityDamageByEn @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerRespawn(PlayerRespawnEvent event) { + WorldManager wm = plugin.getWorldManager(); + World pWorld = event.getPlayer().getWorld(); + if (!wm.isSkyAssociatedWorld(pWorld)) { + return; + } + if (Settings.extras_respawnAtIsland) { PlayerInfo playerInfo = plugin.getPlayerInfo(event.getPlayer()); if (playerInfo.getHasIsland()) { @@ -268,7 +276,7 @@ public void onPlayerRespawn(PlayerRespawnEvent event) { } } } - if (!Settings.extras_sendToSpawn && plugin.getWorldManager().isSkyWorld(event.getPlayer().getWorld())) { + if (!Settings.extras_sendToSpawn && wm.isSkyWorld(pWorld)) { event.setRespawnLocation(plugin.getWorldManager().getWorld().getSpawnLocation()); } } From 518f3faa975bfce731c8653d88d0d01a092dd925 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 28 Apr 2024 22:03:40 +0200 Subject: [PATCH 126/190] Load libraries via plugin.yml --- pom.xml | 7 ++- uSkyBlock-Core/pom.xml | 46 +++++--------------- uSkyBlock-Core/src/main/resources/plugin.yml | 9 ++++ 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index e6e3562b1..7be220632 100644 --- a/pom.xml +++ b/pom.xml @@ -8,10 +8,13 @@ Ultimate SkyBlock - 4.15.0 - 4.3.0 + 4.16.0 + 4.3.2 + 3.14.0 + 1.12.0 4.5.14 2.10.1 + 33.1.0-jre 23.0.0 3.8.6 ${project.version} diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 20d135d6e..5c4f99687 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -82,22 +82,13 @@ true - com.google.code.gson:gson dk.lockfuglsang.minecraft:bukkit-utils io.papermc:paperlib - net.kyori:* - org.apache.httpcomponents:httpclient - org.apache.maven:maven-artifact - org.apache.commons:* org.bstats:* ovh.uskyblock:po-utils - - com.google.code.gson - us.talabrek.ultimateskyblock.gson - dk.lockfuglsang.minecraft us.talabrek.ultimateskyblock.utils @@ -106,22 +97,6 @@ io.papermc.lib us.talabrek.ultimateskyblock.paperlib - - net.kyori - us.talabrek.ultimateskyblock.kyori - - - org.apache.commons - us.talabrek.ultimateskyblock.apache.commons - - - org.apache.httpcomponents - us.talabrek.ultimateskyblock.apache.httpcomponents - - - org.apache.maven - us.talabrek.ultimateskyblock.apache.maven - org.bstats us.talabrek.ultimateskyblock.metrics @@ -474,18 +449,17 @@ compile - com.google.guava guava - 31.0.1-jre + ${guava.version} provided com.google.code.gson gson - compile + provided be.maximvdw @@ -503,12 +477,12 @@ net.kyori adventure-api - compile + provided net.kyori adventure-platform-bukkit - compile + provided @@ -518,25 +492,25 @@ org.apache.commons commons-lang3 - 3.12.0 - compile + ${apache-commons.version} + provided org.apache.commons commons-text - 1.10.0 - compile + ${apache-commons-text.version} + provided org.apache.httpcomponents httpclient - compile + provided org.apache.maven maven-artifact - compile + provided diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 4c20f997b..023391409 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -19,6 +19,15 @@ softdepend: # placeholders - MVdWPlaceholderAPI api-version: 1.19 +libraries: + - com.google.code.gson:gson:${gson.version} + - com.google.guava:guava:${guava.version} + - net.kyori:adventure-api:${adventure-api.version} + - net.kyori:adventure-platform-bukkit:${adventure-bukkit.version} + - org.apache.commons:commons-lang3:${apache-commons.version} + - org.apache.commons:commons-text:${apache-commons-text.version} + - org.apache.httpcomponents:httpclient:${apache-http.version} + - org.apache.maven:maven-artifact:${maven-artifact.version} commands: challenges: From 01c389447838be2a483f191575ae3e719b3c5355 Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 27 Jun 2024 08:24:34 +0200 Subject: [PATCH 127/190] Merge bukkit utils into main repository (#54) * Initial commit * Moved to bukkit-utils from rlf/uSkyBlock * v1.11 * UUIDUtil and more * CRLF vs LF.... sigh * LocationUtil * ItemStackUtil * fix test data to CRLF * TimeUtil added * Fix minor error in PlainTextCommandVisitor * Added sorting to AbstractTabCompleter and two player completers * Make EntitySpawner 1.8 compliant and add 1.11 support to Travis * Add VersionUtil * Bump version of Vault and Bukkit * Bump various versions and quick-fix Issues #1059, #1057 * JDK 1.8 * bump version * what-evs * expose mocking * Fix issue #1064 - challenge chests * Fix issue #1064 - challenge chests * move to using marktr instead of tr for commands * Update mockito and add backdoor for plugin-owners * Also allow permission-override on abstract commands * add github.global property * Paginate only commands the player has access to * block tab-listing when no permissions * Improve the reading of stringlists to support space separated lists * Improve createItemStack for 1.13 detection given 1.12 item-names * Update ReflectionUtil to be used by StructureAPI * Improve LocationUtil and add LanguageCommand * Version to 1.24, fix tests on non-Windows/CRLF, auto deploy via Travis * First 1.14.2 build * Attempt to fix deployment #1 * Openjdk8, not oraclejdk9 * 1.25-SNAPSHOT, MC1.16.1 * Java 16, Spigot 1.17 * Add apache snapshots plugin repo * Hard-code MojangsonParser package name * Remove JSONSimple dependency (#2) * Remove JSONUtil * Use Gson for NBTUtil test * [ci-skip] Remove unused and outdated PermissionUtil * NBT map field is now called x * Deploy using GH Actions * Remove Travis * Integrate bukkit-util as maven module * Update custom yaml handler to not duplicate comments --------- Co-authored-by: Razorax Co-authored-by: Muspah <43544407+Muspah@users.noreply.github.com> Co-authored-by: Muspah --- bukkit-utils | 1 - bukkit-utils/.editorconfig | 23 ++ bukkit-utils/.github/workflows/build.yml | 48 +++ bukkit-utils/.gitignore | 4 + bukkit-utils/README.md | 48 +++ bukkit-utils/pom.xml | 166 ++++++++ .../minecraft/animation/Animation.java | 14 + .../minecraft/animation/AnimationHandler.java | 116 ++++++ .../minecraft/animation/BlockAnimation.java | 65 +++ .../animation/ParticleAnimation.java | 47 +++ .../minecraft/animation/PlayerHandler.java | 61 +++ .../minecraft/command/AbstractCommand.java | 141 +++++++ .../command/BaseCommandExecutor.java | 46 +++ .../minecraft/command/Command.java | 89 +++++ .../minecraft/command/CommandComparator.java | 13 + .../minecraft/command/CommandManager.java | 31 ++ .../minecraft/command/CommandVisitor.java | 8 + .../minecraft/command/CompositeCommand.java | 365 +++++++++++++++++ .../minecraft/command/DocumentCommand.java | 79 ++++ .../minecraft/command/DocumentWriter.java | 10 + .../minecraft/command/LanguageCommand.java | 64 +++ .../command/PlainTextCommandVisitor.java | 66 +++ .../command/PluginYamlCommandVisitor.java | 266 +++++++++++++ .../lockfuglsang/minecraft/command/README.md | 73 ++++ .../minecraft/command/RowCommandVisitor.java | 90 +++++ .../completion/AbstractTabCompleter.java | 43 ++ .../completion/CompositeTabCompleter.java | 26 ++ .../completion/OfflinePlayerTabCompleter.java | 24 ++ .../completion/OnlinePlayerTabCompleter.java | 24 ++ .../lockfuglsang/minecraft/file/FileUtil.java | 334 ++++++++++++++++ .../dk/lockfuglsang/minecraft/file/README.md | 47 +++ .../minecraft/gui/package-info.java | 4 + .../minecraft/nbt/CraftBukkitNBTTagger.java | 100 +++++ .../minecraft/nbt/NBTItemStackTagger.java | 33 ++ .../lockfuglsang/minecraft/nbt/NBTUtil.java | 63 +++ .../dk/lockfuglsang/minecraft/nbt/README.md | 5 + .../minecraft/reflection/ReflectionUtil.java | 356 +++++++++++++++++ .../minecraft/util/FormatUtil.java | 180 +++++++++ .../minecraft/util/ItemStackUtil.java | 375 ++++++++++++++++++ .../minecraft/util/LocationUtil.java | 74 ++++ .../lockfuglsang/minecraft/util/TimeUtil.java | 92 +++++ .../lockfuglsang/minecraft/util/UUIDUtil.java | 32 ++ .../minecraft/util/VersionUtil.java | 75 ++++ .../dk/lockfuglsang/minecraft/yml/README.md | 13 + .../minecraft/yml/YmlCommentParser.java | 215 ++++++++++ .../minecraft/yml/YmlConfiguration.java | 50 +++ .../command/BaseCommandExecutorTest.java | 87 ++++ .../command/CompositeCommandTest.java | 178 +++++++++ .../command/PluginYamlCommandVisitorTest.java | 55 +++ .../minecraft/file/FileUtilTest.java | 23 ++ .../minecraft/nbt/NBTUtilTest.java | 38 ++ .../minecraft/util/BukkitServerMock.java | 135 +++++++ .../minecraft/util/FormatUtilTest.java | 67 ++++ .../minecraft/util/ItemStackMatcher.java | 58 +++ .../minecraft/util/ItemStackUtilTest.java | 254 ++++++++++++ .../minecraft/util/LocationUtilTest.java | 64 +++ .../minecraft/yml/YmlCommentParserTest.java | 37 ++ .../minecraft/yml/YmlConfigurationTest.java | 53 +++ .../src/test/resources/yml/.gitattributes | 1 + .../resources/yml/pluginyml_featuremap.yml | 50 +++ .../test/resources/yml/pluginyml_simple.yml | 46 +++ .../src/test/resources/yml/simple.yml | 25 ++ .../test/resources/yml/simple_expected.yml | 37 ++ pom.xml | 24 +- uSkyBlock-Core/pom.xml | 14 +- 65 files changed, 5315 insertions(+), 30 deletions(-) delete mode 160000 bukkit-utils create mode 100644 bukkit-utils/.editorconfig create mode 100644 bukkit-utils/.github/workflows/build.yml create mode 100644 bukkit-utils/.gitignore create mode 100644 bukkit-utils/README.md create mode 100644 bukkit-utils/pom.xml create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/Animation.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/AnimationHandler.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutor.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/Command.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandComparator.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandManager.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandVisitor.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CompositeCommand.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentWriter.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PlainTextCommandVisitor.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitor.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/README.md create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/RowCommandVisitor.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/README.md create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/LocationUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/VersionUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java create mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java create mode 100644 bukkit-utils/src/test/resources/yml/.gitattributes create mode 100644 bukkit-utils/src/test/resources/yml/pluginyml_featuremap.yml create mode 100644 bukkit-utils/src/test/resources/yml/pluginyml_simple.yml create mode 100644 bukkit-utils/src/test/resources/yml/simple.yml create mode 100644 bukkit-utils/src/test/resources/yml/simple_expected.yml diff --git a/bukkit-utils b/bukkit-utils deleted file mode 160000 index d4017e246..000000000 --- a/bukkit-utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d4017e24652d3b28a4d4e7b1812a5732b0fba71c diff --git a/bukkit-utils/.editorconfig b/bukkit-utils/.editorconfig new file mode 100644 index 000000000..716779f35 --- /dev/null +++ b/bukkit-utils/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.java] +end_of_line=lf + +[*.json] +indent_size = 2 + +[*.{yml,yaml}] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[*.sh] +end_of_line = lf diff --git a/bukkit-utils/.github/workflows/build.yml b/bukkit-utils/.github/workflows/build.yml new file mode 100644 index 000000000..21604b115 --- /dev/null +++ b/bukkit-utils/.github/workflows/build.yml @@ -0,0 +1,48 @@ +name: Maven build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build_and_test: + if: github.repository_owner == 'uskyblock' + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: JDK 16 + uses: actions/setup-java@v1 + with: + java-version: '16' + distribution: 'adopt' + - name: Cache Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + - name: Build with Maven + run: mvn -U clean deploy + + # Deploy steps when pushed to master + - name: Install SSH key + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_PRIVATE_KEY }} + known_hosts: ${{ secrets.SSH_KNOWN_HOST }} + - name: Rsync deploy mvn repo + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + run: | + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + target/mvn-repo/ \ + travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ + - name: Rsync deploy javadocs + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + run: | + rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ + target/site/apidocs \ + travis@travis.internetpolice.eu:WWW-USB/javadocs/dependencies/bukkit-utils/ diff --git a/bukkit-utils/.gitignore b/bukkit-utils/.gitignore new file mode 100644 index 000000000..520582144 --- /dev/null +++ b/bukkit-utils/.gitignore @@ -0,0 +1,4 @@ +/.idea +**/*.iml +/target +deploy_rsa diff --git a/bukkit-utils/README.md b/bukkit-utils/README.md new file mode 100644 index 000000000..b142362fa --- /dev/null +++ b/bukkit-utils/README.md @@ -0,0 +1,48 @@ +# bukkit-utils + +This module holds general Bukkit Utilities enabling easier Bukkit Plugin creation. + +## Utilities + +* [FileUtil](src/main/java/dk/lockfuglsang/minecraft/file/README.md) - UTF-8, Locale and merging config files from jar +* [YmlConfiguration](src/main/java/dk/lockfuglsang/minecraft/yml/README.md) - Support for comments in yml-files +* [Commands](src/main/java/dk/lockfuglsang/minecraft/command/README.md) - Framework for easy command-creation + +# License + +This module is copyrighted by the authors, and licensed for re-use as Apache License 2.0. + +# Usage + +Put this in your `pom.xml`: + +``` + + + uSkyBlock-mvn-repo + https://raw.github.com/rlf/mvn-repo/master + + + + + dk.lockfuglsang.minecraft + bukkit-utils + 1.22 + + +``` + +# Version History + +## 1.22 - Bukkit 1.13 compatible + +## 1.21 - Bukkit 1.12 compatible + +## v1.1 + +* FileUtil, I18nUtil + +## v1.0 +Initial release, extracted from the source-code used in uSkyBlock + +* YmlConfiguration, Commands \ No newline at end of file diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml new file mode 100644 index 000000000..80da364b5 --- /dev/null +++ b/bukkit-utils/pom.xml @@ -0,0 +1,166 @@ + + + 4.0.0 + + + uSkyBlock + ovh.uskyblock + 3.1.0-SNAPSHOT + + bukkit-utils + + + 1.7 + + UTF-8 + + + + scm:git:git://github.com/uskyblock/bukkit-utils.git + scm:git:git://github.com/uskyblock/bukkit-utils.git + https://github.com/uskyblock/bukkit-utils.git + + + + + internal.repo + Temporary Staging Repository + file://${project.build.directory}/mvn-repo + + + + + + spigotmc.org + https://hub.spigotmc.org/nexus/content/repositories/public + + + uskyblock-dependencies + https://www.uskyblock.ovh/maven/dependencies/ + + + + + + apache-snapshots + https://repository.apache.org/snapshots/ + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 16 + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + test-jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.3.0 + + public + false + none + + + + + javadoc + + deploy + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + + + + + ovh.uskyblock + po-utils + 3.1.0-SNAPSHOT + + + org.spigotmc + spigot-api + ${spigotapi.version} + true + compile + + + net.milkbowl.vault + VaultAPI + ${vaultapi.version} + true + + + + + + + + + + org.hamcrest + hamcrest-core + 1.3 + test + + + org.hamcrest + hamcrest-library + 1.3 + test + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.28.2 + test + + + com.google.code.gson + gson + 2.8.7 + test + + + diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/Animation.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/Animation.java new file mode 100644 index 000000000..42b643ee9 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/Animation.java @@ -0,0 +1,14 @@ +package dk.lockfuglsang.minecraft.animation; + +import org.bukkit.entity.Player; + +/** + * Common interface for animations + */ +public interface Animation { + boolean show(); + + boolean hide(); + + Player getPlayer(); +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/AnimationHandler.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/AnimationHandler.java new file mode 100644 index 000000000..47f13220c --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/AnimationHandler.java @@ -0,0 +1,116 @@ +package dk.lockfuglsang.minecraft.animation; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Handles particles and per-player block-animations + */ +public class AnimationHandler { + private final Map> animations = new ConcurrentHashMap<>(); + private final Map animationTasks = new ConcurrentHashMap<>(); + private final Plugin plugin; + + private int animTick; + + public AnimationHandler(Plugin plugin) { + this.plugin = plugin; + animTick = plugin.getConfig().getInt("animations.tick", 20); + } + + public void setAnimTick(int animTick) { + this.animTick = animTick; + plugin.getConfig().set("animations.tick", animTick); + } + + public synchronized void addAnimation(Animation animation) { + if (!animations.containsKey(animation.getPlayer().getUniqueId())) { + animations.put(animation.getPlayer().getUniqueId(), new HashSet()); + } + animations.get(animation.getPlayer().getUniqueId()).add(animation); + start(); + } + + public synchronized boolean removeAnimations(Player player) { + Set animSet = animations.remove(player.getUniqueId()); + if (animSet == null) { + return false; + } + for (Animation animation : animSet) { + animation.hide(); + } + return true; + } + + public synchronized void start() { + for (UUID uuid : animations.keySet()) { + AnimationTask animationTask = animationTasks.get(uuid); + if (animationTask == null && animations.get(uuid) != null && !animations.get(uuid).isEmpty()) { + animationTask = new AnimationTask(uuid); + animationTask.runTaskTimerAsynchronously(plugin, 0, animTick); + animationTasks.put(uuid, animationTask); + } + } + } + + public synchronized void stop() { + for (UUID uuid : animations.keySet()) { + AnimationTask animationTask = animationTasks.get(uuid); + if (animationTask != null) { + animationTask.cancel(); + animationTasks.remove(uuid); + } + } + if (plugin.isEnabled()) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + @Override + public void run() { + Collection> anims = new ArrayList<>(animations.values()); + for (Set animSet : anims) { + for (Animation animation : animSet) { + animation.hide(); + } + } + } + }); + } + } + + private class AnimationTask extends BukkitRunnable { + private final UUID uniqueId; + public AnimationTask(UUID uniqueId) { + this.uniqueId = uniqueId; + } + + @Override + public void run() { + // Copy - to avoid ConcurrentModificationException + Set animSet = animations.get(uniqueId); + Set animCopy = (animSet != null) ? new HashSet<>(animSet) : Collections.emptySet(); + for (Animation animation : animCopy) { + if (!animation.show()) { + UUID uuid = animation.getPlayer().getUniqueId(); + animations.get(uuid).remove(animation); + if (animations.get(uuid).isEmpty()) { + animations.remove(uuid); + } + } + } + if (animations.get(uniqueId) == null) { + cancel(); + animationTasks.remove(uniqueId); + } + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java new file mode 100644 index 000000000..1d478ff5b --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java @@ -0,0 +1,65 @@ +package dk.lockfuglsang.minecraft.animation; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.List; + +/** + * Sends (bogus) block-info to the player + */ +public class BlockAnimation implements Animation { + private final Player player; + private final List points; + private final Material material; + private final byte data; + private volatile boolean shown; + + public BlockAnimation(Player player, List points, Material material, byte data) { + this.player = player; + this.points = points; + this.material = material; + this.data = data; + shown = false; + } + + @Override + public boolean show() { + if (shown) { + return true; + } + if (!player.isOnline()) { + return false; + } + for (Location loc : points) { + if (!PlayerHandler.sendBlockChange(player, loc, material, data)) { + return false; + } + } + shown = true; + return true; + } + + @Override + public boolean hide() { + try { + if (shown) { + for (Location loc : points) { + if (!PlayerHandler.sendBlockChange(player, loc, loc.getBlock().getType(), loc.getBlock().getData())) { + return false; + } + } + return true; + } + return false; + } finally { + shown = false; + } + } + + @Override + public Player getPlayer() { + return player; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java new file mode 100644 index 000000000..c9d10e407 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java @@ -0,0 +1,47 @@ +package dk.lockfuglsang.minecraft.animation; + +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +import java.util.List; + +/** + * An animation using particles (requires refreshes). + */ +public class ParticleAnimation implements Animation { + private final Player player; + private final Particle particle; + private final List points; + private final int animCount; + + public ParticleAnimation(Player player, List points, Particle particle, int animCount) { + this.player = player; + this.particle = particle; + this.points = points; + this.animCount = animCount; + } + + @Override + public boolean show() { + if (!player.isOnline()) { + return false; + } + for (Location loc : points) { + if (!PlayerHandler.spawnParticle(player, particle, loc, animCount)) { + return false; + } + } + return true; + } + + @Override + public boolean hide() { + return true; + } + + @Override + public Player getPlayer() { + return player; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java new file mode 100644 index 000000000..8c9d968d6 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java @@ -0,0 +1,61 @@ +package dk.lockfuglsang.minecraft.animation; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Particle; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.logging.Logger; + +/** + * Common handler across servers for sending particles and other packages to a player. + */ +public enum PlayerHandler {; + private static final Logger log = Logger.getLogger(PlayerHandler.class.getName()); + + public static boolean spawnParticle(Player player, Particle particle, Location loc, int count) { + try { + Method playMethod = getMethod(player, "spawnParticle", new Class[]{Particle.class, Location.class, Integer.TYPE}); + if (playMethod != null) { + playMethod.invoke(player, particle, loc, count); + return true; + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + log.finest("Unable to spawnParticle for player " + player + ": " + e); + } + return false; + } + + public static boolean sendBlockChange(Player player, Location location, Material material, byte data) { + try { + Method method = getMethod(player, "sendBlockChange", new Class[]{Location.class, Material.class, Byte.TYPE}); + if (method != null) { + method.invoke(player, location, material, data); + return true; + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + log.finest("Unable to sendBlockChange to player " + player + ": " + e); + } + return false; + } + + public static boolean playEffect(Player player, Location loc, Effect effect, int data) { + try { + Method playMethod = getMethod(player, "playEffect", new Class[]{Location.class, Effect.class, Integer.TYPE}); + if (playMethod != null) { + playMethod.invoke(player, loc, effect, data); + return true; + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + log.finest("Unable to playEffect for player " + player + ": " + e); + } + return false; + } + + private static Method getMethod(Object player, String methodName, Class[] paramClasses) throws NoSuchMethodException { + return player.getClass().getMethod(methodName, paramClasses); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java new file mode 100644 index 000000000..930da6f0d --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java @@ -0,0 +1,141 @@ +package dk.lockfuglsang.minecraft.command; + +import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * Convenience implementation of the Command + */ +public abstract class AbstractCommand implements Command { + private final String[] aliases; + private final String permission; + private final String description; + private final String usage; + private final String[] params; + private CompositeCommand parent; + private final Map featurePerms = new HashMap<>(); + private final Set permissionOverride; + + public AbstractCommand(String name, String permission, String params, String description, String usage, UUID... permissionOverride) { + this.aliases = name.split("\\|"); + this.permission = permission; + this.description = I18nUtil.tr(description); + this.usage = I18nUtil.tr(usage); + this.params = params != null && !params.trim().isEmpty() ? params.split(" ") : new String[0]; + this.permissionOverride = new HashSet<>(Arrays.asList(permissionOverride)); + } + + public AbstractCommand(String name, String permission, String params, String description) { + this(name, permission, params, description, null); + } + + public AbstractCommand(String name, String permission, String description) { + this(name, permission, null, description, null); + } + + public AbstractCommand(String name, String description) { + this(name, null, null, description, null); + } + + @Override + public String getName() { + return aliases[0]; + } + + public String[] getAliases() { + return aliases; + } + + @Override + public String getPermission() { + return permission; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getUsage() { + return usage; + } + + @Override + public String[] getParams() { + return params; + } + + @Override + public TabCompleter getTabCompleter() { + return null; + } + + @Override + public CompositeCommand getParent() { + return parent; + } + + @Override + public void setParent(CompositeCommand parent) { + this.parent = parent; + } + + @Override + public void accept(CommandVisitor visitor) { + if (visitor != null) { + visitor.visit(this); + } + } + + public void addFeaturePermission(String perm, String description) { + featurePerms.put(perm, description); + } + + @Override + public Map getFeaturePermissions() { + return Collections.unmodifiableMap(featurePerms); + } + + /** + * Convenience method until we can fully rely on everybody running JRE 8. + * @param args A list of arguments + * @param delim Delimiter to join them + * @return A string containing the arguments concatenated. + */ + public static String join(String[] args, String delim) { + String res = ""; + if (args != null && args.length > 0) { + for (String arg : args) { + res += (res.isEmpty() ? "" : delim) + arg; + } + } + return res; + } + + public static String join(String[] args) { + return join(args, " "); + } + + public boolean hasPermissionOverride(CommandSender sender) { + if (sender instanceof Player) { + return permissionOverride.contains(((Player) sender).getUniqueId()) || (parent != null && parent.hasPermissionOverride(sender)); + } + return false; + } + + @Override + public boolean hasPermission(CommandSender sender, String permission) { + return hasPermissionOverride(sender) || sender.hasPermission(permission); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutor.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutor.java new file mode 100644 index 000000000..26fc68308 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutor.java @@ -0,0 +1,46 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import java.util.HashMap; +import java.util.UUID; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Command delegator. + */ +public class BaseCommandExecutor extends CompositeCommand implements CommandExecutor { + + public BaseCommandExecutor(String name, String permission, String description) { + super(name, permission, description); + } + + public BaseCommandExecutor(String name, String permission, String params, String description) { + super(name, permission, params, description); + } + public BaseCommandExecutor(String name, String permission, String params, String description, UUID... permissionOverrides) { + super(name, permission, params, description, permissionOverrides); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { + if (!CommandManager.isRequirementsMet(sender, this, args)) { + return true; + } + dk.lockfuglsang.minecraft.command.Command cmd = this; + if (!hasAccess(cmd, sender)) { + if (cmd != null) { + sender.sendMessage(tr("\u00a7eYou do not have access (\u00a74{0}\u00a7e)", cmd.getPermission())); + } else { + sender.sendMessage(tr("\u00a7eInvalid command: {0}", alias)); + } + showUsage(sender, 1); + } else { + return execute(sender, alias, new HashMap(), args); + } + return true; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/Command.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/Command.java new file mode 100644 index 000000000..58c21b2a2 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/Command.java @@ -0,0 +1,89 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +import java.util.Map; + +/** + * An abstraction for supporting nesting of commands. + * This is a light-weight version of the BukkitCommand abstraction. + */ +public interface Command { + /** + * Returns the name of the sub-command. + */ + String getName(); + + /** + * The permission of the command. Can be null. + */ + String getPermission(); + + /** + * A short description of the sub-command. + * Used when listing the commands with others. + */ + String getDescription(); + + /** + * A more verbatim description of the command. + * Used when /command help is executed. + */ + String getUsage(); + + /** + * The list of parameters accepted by the command. + * Can be empty, not null. + */ + String[] getParams(); + + /** + * Returns aliases for the command. + * Can be empty, cannot be null. + */ + String[] getAliases(); + + /** + * Executes the command. + */ + boolean execute(CommandSender sender, String alias, Map data, String... args); + + /** + * Optional TabCompleter to override the default ones. + * Can be null + */ + TabCompleter getTabCompleter(); + + /** + * Returns the parent command (if one such is available). + * May return null. + */ + CompositeCommand getParent(); + + /** + * Assigns a parent command. + * @param parent + */ + void setParent(CompositeCommand parent); + + /** + * Visitor pattern. + * @param visitor A visitor for this node. + */ + void accept(CommandVisitor visitor); + + /** + * Returns a map of feature-toggling permissions supporte by this command. + * @return A map of permission-node as key, and description as value. + */ + Map getFeaturePermissions(); + + /** + * Allows for other than permission checking + * @param sender The commandSender requesting permission + * @param permission The permission + * @return true if the sender can execute this command + */ + boolean hasPermission(CommandSender sender, String permission); +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandComparator.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandComparator.java new file mode 100644 index 000000000..e015dd07b --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandComparator.java @@ -0,0 +1,13 @@ +package dk.lockfuglsang.minecraft.command; + +import java.util.Comparator; + +/** + * Comparator for sorting sub-commands + */ +public class CommandComparator implements Comparator { + @Override + public int compare(Command o1, Command o2) { + return o1.getName().compareTo(o2.getName()); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandManager.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandManager.java new file mode 100644 index 000000000..6d345ef8c --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandManager.java @@ -0,0 +1,31 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandSender; + +/** + * Static singleton manager for controlling common requirements. + */ +public enum CommandManager {; + private static RequirementChecker checker; + + public static void registerRequirements(RequirementChecker reqs) { + checker = reqs; + } + + public static boolean isRequirementsMet(CommandSender sender, Command command, String... args) { + if (checker != null) { + return checker.isRequirementsMet(sender, command, args); + } + return true; + } + + public interface RequirementChecker { + /** + * Checks whether the requirements for the command has been met. + * @param sender A sender to send detailed feedback to. + * @param args + * @return true iff the command can proceed. + */ + boolean isRequirementsMet(CommandSender sender, Command command, String... args); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandVisitor.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandVisitor.java new file mode 100644 index 000000000..e0dc42910 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CommandVisitor.java @@ -0,0 +1,8 @@ +package dk.lockfuglsang.minecraft.command; + +/** + * Simple visitor for the USBCommands + */ +public interface CommandVisitor { + void visit(Command cmd); +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CompositeCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CompositeCommand.java new file mode 100644 index 000000000..0c18f174c --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/CompositeCommand.java @@ -0,0 +1,365 @@ +package dk.lockfuglsang.minecraft.command; + +import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Command with nested commandMap inside. + */ +public class CompositeCommand extends AbstractTabCompleter implements Command, TabCompleter { + + public static final String HELP_PATTERN = "(?iu)help|\\?"; + private static final int MAX_PER_PAGE = 10; + + private final String name; + private final String[] aliases; + private final String permission; + private final String description; + private final String[] params; + private CompositeCommand parent; + private final Map commandMap; + private final Map aliasMap; + private final Map tabMap; + private final Map featurePerms; + private final Set permissionOverride; + + public CompositeCommand(String name, String permission, String description) { + this(name, permission, null, description); + } + + public CompositeCommand(String name, String permission, String params, String description, UUID... permissionOverride) { + this.aliases = name.split("\\|"); + this.name = aliases[0]; + this.permission = permission; + this.description = description; + this.params = params != null ? params.split(" ") : new String[0]; + commandMap = new HashMap<>(); + aliasMap = new HashMap<>(); + tabMap = new HashMap<>(); + featurePerms = new HashMap<>(); + this.permissionOverride = new HashSet<>(Arrays.asList(permissionOverride)); + } + + public CompositeCommand add(Command... cmds) { + for (Command cmd : cmds) { + commandMap.put(cmd.getName(), cmd); + for (String alias : cmd.getAliases()) { + aliasMap.put(alias, cmd); + } + cmd.setParent(this); + } + return this; + } + + public CompositeCommand addTab(String arg, TabCompleter tab) { + tabMap.put(arg, tab); + return this; + } + + @Override + public String getName() { + return name; + } + + @Override + public String[] getAliases() { + return aliases; + } + + @Override + public String getPermission() { + return permission != null && !permission.isEmpty() ? permission : null; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getUsage() { + return null; + } + + @Override + public String[] getParams() { + return params; + } + + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + if (!CommandManager.isRequirementsMet(sender, this, args)) { + return true; + } + if (args.length == 0 || (args.length == 1 && args[0].matches(HELP_PATTERN))) { + showUsage(sender, 1); + } else if (args.length > 1 && args[0].matches(HELP_PATTERN)) { + showUsage(sender, args[1]); + } else if (args.length > params.length && hasAccess(this, sender)) { + String cmdName = args[params.length].toLowerCase(); + Command cmd = aliasMap.get(cmdName); + String[] subArgs = new String[args.length - 1 - params.length]; + System.arraycopy(args, 1 + params.length, subArgs, 0, subArgs.length); + int ix = 0; + for (String p : params) { + data.put(p, args[ix++]); + } + if (!hasAccess(cmd, sender)) { + if (cmd != null) { + sender.sendMessage(tr("\u00a7eYou do not have access (\u00a74{0}\u00a7e)", cmd.getPermission())); + } else { + sender.sendMessage(tr("\u00a7eInvalid command: {0}", cmdName)); + } + showUsage(sender, args[0]); + } else if (!cmd.execute(sender, cmdName, data, subArgs)) { + showUsage(sender, args[0]); + } + } else { + showUsage(sender, 1); + } + return true; + } + + public void showUsage(CommandSender sender, int page) { + String msg = tr("\u00a77Usage: {0}", getShortDescription(sender, this)); + if (!hasAccess(this, sender)) { + sender.sendMessage(msg.split("\n")); + return; + } + if (getUsage() != null && !getUsage().isEmpty()) { + msg += "\u00a77" + getUsage(); + } + List cmds = new ArrayList<>(commandMap.keySet()); + Collections.sort(cmds); + cmds = cmds.stream().filter(f -> hasAccess(commandMap.get(f), sender)).collect(Collectors.toList()); + int realPage = 0; + int maxPage = 0; + if (cmds.size() > MAX_PER_PAGE) { + msg = msg.substring(0, msg.length() - 1); // Remove \n + maxPage = (int) Math.round(Math.ceil(cmds.size() * 1f / MAX_PER_PAGE)); + realPage = Math.max(1, Math.min(maxPage, page)); + msg += " \u00a77[" + realPage + "/" + maxPage + "]\n"; + cmds = cmds.subList((realPage - 1) * MAX_PER_PAGE, Math.min(realPage * MAX_PER_PAGE, cmds.size())); + } + for (String key : cmds) { + Command cmd = commandMap.get(key); + if (hasAccess(cmd, sender)) { + msg += " " + getShortDescription(sender, cmd); + } + } + if (realPage > 0 && maxPage > realPage) { + msg += tr("\u00a77Use \u00a73/{0} ? {1}\u00a77 to display next page\n", getName(), (realPage + 1)); + } else if (realPage > 0 && maxPage == realPage) { + msg += tr("\u00a77Use \u00a73/{0} ? {1} \u00a77 to display previous page\n", getName(), (realPage - 1)); + } + sender.sendMessage(msg.split("\n")); + } + + protected void showUsage(CommandSender sender, String arg) { + String cmdName = arg.toLowerCase(); + Command cmd = cmdName.isEmpty() ? this : aliasMap.get(cmdName); + if (cmd != null && hasAccess(cmd, sender)) { + String msg = tr("\u00a77Usage: {0}", name) + " \u00a7e"; + msg += getShortDescription(sender, cmd); + if (cmd.getUsage() != null && !cmd.getUsage().isEmpty()) { + msg += "\u00a77" + cmd.getUsage(); + } + sender.sendMessage(msg.split("\n")); + } else if (cmdName.matches("[0-9]+")) { + showUsage(sender, Integer.parseInt(cmdName)); + } else { + List cmds = filter(new ArrayList<>(aliasMap.keySet()), cmdName); + if (cmds.isEmpty()) { + showUsage(sender, 1); + } else { + String msg = tr("\u00a77Usage: {0}", getShortDescription(sender, this)); + if (hasAccess(this, sender)) { + for (String key : cmds) { + Command scmd = commandMap.get(key); + if (scmd != null && hasAccess(scmd, sender)) { + msg += " " + getShortDescription(sender, scmd); + } + } + } + sender.sendMessage(msg.split("\n")); + } + } + } + + private String getShortDescription(CommandSender sender, Command cmd) { + String msg = "\u00a73" + cmd.getName(); + String[] aliases = cmd.getAliases(); + if (aliases.length > 1) { + msg += "\u00a77"; + for (int i = 1; i < aliases.length; i++) { + msg += " | " + aliases[i]; + } + } + msg += "\u00a7a"; + msg += getParamsAsString(cmd); + if (cmd instanceof CompositeCommand) { + msg += " [command|help]"; + } + msg += "\u00a77 - \u00a7e"; + msg += cmd.getDescription(); + if (sender.isOp() && cmd.getPermission() != null) { + msg += " \u00a7c(" + cmd.getPermission() + ")"; + } + msg += "\n"; + return msg; + } + + public static String getParamsAsString(Command cmd) { + String msg = ""; + for (String param : cmd.getParams()) { + if (param.startsWith("?")) { + msg += " [" + param.substring(1) + "]"; + } else { + msg += " <" + param + ">"; + } + } + return msg; + } + + public boolean hasAccess(Command cmd, CommandSender sender) { + return cmd != null && (cmd.getPermission() == null || cmd.hasPermission(sender, cmd.getPermission())); + } + + @Override + protected List getTabList(CommandSender commandSender, String term) { + ArrayList strings = new ArrayList<>(); + if (!hasAccess(this, commandSender)) { + return strings; + } + for (Command cmd : commandMap.values()) { + if (hasAccess(cmd, commandSender)) { + strings.addAll(Arrays.asList(cmd.getAliases())); + } + } + strings.add("help"); + return strings; + } + + protected TabCompleter getTabCompleter(Command cmd, int argNum) { + argNum = argNum >= 0 ? argNum : 0; + if (cmd.getParams().length > argNum) { + String paramName = cmd.getParams()[argNum]; + if (paramName != null && paramName.startsWith("?")) { + paramName = paramName.substring(1); + } + if (tabMap.containsKey(paramName)) { + return tabMap.get(paramName); + } else if (getParent() != null) { + TabCompleter tab = getParent().getTabCompleter(cmd, argNum); + if (tab != null) { + return tab; + } + } + } + if (cmd.getTabCompleter() != null) { + return cmd.getTabCompleter(); + } + return null; + } + + @Override + public List onTabComplete(CommandSender sender, org.bukkit.command.Command command, String alias, String[] args) { + if (args.length <= params.length && args.length > 0) { + TabCompleter tab = getTabCompleter(this, args.length - 1); + if (tab != null && tab != this) { + return tab.onTabComplete(sender, command, alias, args); + } else if (tab == this) { + return getTabList(sender, args[args.length - 1]); + } + } else if (args.length > params.length + 1) { // Sub-commands + String cmdName = args[params.length].toLowerCase(); + Command cmd = aliasMap.get(cmdName); + if (cmd != null && (args.length - params.length) > 1) { // Go deeper + String[] subArgs = new String[args.length - 1 - params.length]; + System.arraycopy(args, 1 + params.length, subArgs, 0, subArgs.length); + TabCompleter tab = getTabCompleter(cmd, subArgs.length - 1); + if (tab != null) { + return tab.onTabComplete(sender, command, alias, subArgs); + } + } else { + return super.onTabComplete(sender, command, alias, args); + } + } else { + return super.onTabComplete(sender, command, alias, args); + } + return Collections.emptyList(); + } + + @Override + public TabCompleter getTabCompleter() { + return this; + } + + @Override + public CompositeCommand getParent() { + return parent; + } + + @Override + public void setParent(CompositeCommand parent) { + this.parent = parent; + } + + public List getChildren() { + ArrayList list = new ArrayList<>(commandMap.values()); + Collections.sort(list, new CommandComparator()); + return Collections.unmodifiableList(list); + } + + @Override + public void accept(CommandVisitor visitor) { + if (visitor != null) { + visitor.visit(this); + for (Command child : getChildren()) { + child.accept(visitor); + } + } + } + + public void addFeaturePermission(String perm, String description) { + featurePerms.put(perm, description); + } + + @Override + public Map getFeaturePermissions() { + return Collections.unmodifiableMap(featurePerms); + } + + private boolean hasPermissionOverride(UUID uuid) { + return permissionOverride.contains(uuid) || (getParent() != null && getParent().hasPermissionOverride(uuid)); + } + + public boolean hasPermissionOverride(CommandSender sender) { + if (sender instanceof Player) { + return hasPermissionOverride(((Player) sender).getUniqueId()); + } + return false; + } + + public boolean hasPermission(CommandSender sender, String permission) { + if (sender instanceof Player) { + return hasPermissionOverride(((Player) sender).getUniqueId()) || sender.hasPermission(permission); + } + return sender.hasPermission(permission); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java new file mode 100644 index 000000000..28be5cb92 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java @@ -0,0 +1,79 @@ +package dk.lockfuglsang.minecraft.command; + +import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.TabCompleter; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Command that traverses all the commands in a plugin, and generates documentation for them. + */ +public class DocumentCommand extends AbstractCommand { + public static final List FORMATS = Arrays.asList("text", "yml"); + private final JavaPlugin plugin; + private TabCompleter tabCompleter; + + public DocumentCommand(JavaPlugin plugin, String name, String permission) { + super(name, permission, "?format ?arg", marktr("saves documentation of the commands to a file")); + this.plugin = plugin; + tabCompleter = new AbstractTabCompleter() { + @Override + protected List getTabList(CommandSender commandSender, String term) { + return FORMATS; + } + }; + } + + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + if (args.length == 0 || args[0].equalsIgnoreCase("text")) { + int lineWidth = args.length > 1 && args[1].matches("\\d+") ? Integer.parseInt(args[1], 10) : 130; + return writeToFile(sender, new PlainTextCommandVisitor(lineWidth), getName() + ".txt"); + } else if (args[0].equalsIgnoreCase("yml")) { + int groupDepth = args.length > 1 && args[1].matches("\\d+") ? Integer.parseInt(args[1], 10) : 2; + return writeToFile(sender, new PluginYamlCommandVisitor(groupDepth), getName() + ".yml"); + } + return false; + } + + private boolean writeToFile(CommandSender sender, DocumentWriter visitor, String filename) { + List commands = new ArrayList<>(plugin.getDescription().getCommands().keySet()); + Collections.sort(commands); + for (String cmd : commands) { + PluginCommand pluginCommand = plugin.getCommand(cmd); + if (pluginCommand.getExecutor() instanceof Command) { + ((Command) pluginCommand.getExecutor()).accept(visitor); + } + } + File docFile = new File(plugin.getDataFolder(), filename); + try (FileOutputStream fos = new FileOutputStream(docFile); + PrintStream ps = new PrintStream(fos, true, "UTF-8")) + { + visitor.writeTo(ps); + sender.sendMessage(tr("Wrote documentation to {0}", docFile)); + return true; + } catch (IOException e) { + sender.sendMessage(tr("\u00a74Error writing documentation: {0}", e.getMessage())); + } + return false; + } + + @Override + public TabCompleter getTabCompleter() { + return tabCompleter; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentWriter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentWriter.java new file mode 100644 index 000000000..e26cf2d5d --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentWriter.java @@ -0,0 +1,10 @@ +package dk.lockfuglsang.minecraft.command; + +import java.io.PrintStream; + +/** + * Common interface for the DocumentCommand-visitors + */ +public interface DocumentWriter extends CommandVisitor { + void writeTo(PrintStream ps); +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java new file mode 100644 index 000000000..35cbdf108 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java @@ -0,0 +1,64 @@ +package dk.lockfuglsang.minecraft.command; + +import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Locale; +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +public class LanguageCommand extends AbstractCommand { + private JavaPlugin plugin; + + public LanguageCommand(JavaPlugin plugin, String name, String permission) { + super(name, permission, "language", marktr("changes the language of the plugin, and reloads")); + this.plugin = plugin; + } + + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + if (args.length == 1) { + Locale loc = I18nUtil.getLocale(args[0]); + I18nUtil.clearCache(); + plugin.getConfig().set("language", args[0]); + plugin.saveConfig(); + plugin.reloadConfig(); + if (I18nUtil.getLocale().equals(I18nUtil.getI18n().getLocale())) { + sender.sendMessage(tr("\u00a7aSuccessfully changed language to \u00a7e{0}", loc)); + } else { + sender.sendMessage(tr("\u00a7cFailed to change language to \u00a7e{0}", loc)); + } + return true; + } else if (args.length == 0) { + try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("gettext-report.txt"); + BufferedReader rdr = new BufferedReader(new InputStreamReader(inputStream))) { + String line = null; + boolean header = true; + StringBuilder sb = new StringBuilder(); + sb.append(tr("\u00a79Supported Languages:\n")); + while ((line = rdr.readLine()) != null) { + if (line.startsWith("---")) { + header = false; + } else if (!header && line.contains("|")) { + String parts[] = line.split("\\|"); + if (parts.length == 7) { + sb.append(tr("\u00a7f{0} \u00a77{1} \u00a79 by {2} \u00a77{3}\n", parts[1].trim(), parts[0].trim(), parts[6].trim(), parts[2].trim())); + } + } + } + sender.sendMessage(sb.toString().split("\n")); + } catch (IOException e) { + sender.sendMessage(tr("\u00a7cUnable to locate any languages.")); + } + return true; + } + return false; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PlainTextCommandVisitor.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PlainTextCommandVisitor.java new file mode 100644 index 000000000..16b6b48d2 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PlainTextCommandVisitor.java @@ -0,0 +1,66 @@ +package dk.lockfuglsang.minecraft.command; + +import dk.lockfuglsang.minecraft.util.FormatUtil; + +import java.io.PrintStream; +import java.util.List; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Simple visitor for generating plain-text documentation of an Command-hierarchy. + */ +public class PlainTextCommandVisitor extends RowCommandVisitor implements DocumentWriter { + private final int linewidth; + + public PlainTextCommandVisitor(int linewidth) { + this.linewidth = linewidth; + } + + public void writeTo(PrintStream out) { + int[] colWidths = new int[3]; + for (Row row : getRows()) { + if (row != null) { + if (row.getCommand().length() > colWidths[0]) { + colWidths[0] = row.getCommand().length(); + } + if (row.getPermission().length() > colWidths[1]) { + colWidths[1] = row.getPermission().length(); + } + if (row.getDescription().length() > colWidths[2]) { + colWidths[2] = row.getDescription().length(); + } + } + } + colWidths[0]++; // make room for the '/' + if (colWidths[0] + colWidths[1] + colWidths[2] > linewidth && colWidths[0] + colWidths[1] < linewidth) { + // truncate description column + colWidths[2] = linewidth - colWidths[0] - colWidths[1]; + } + String rowFormat = ""; + String separator = ""; + for (int i = 0; i < colWidths.length; i++) { + if (i != 0) { + rowFormat += " | "; + separator += "-+-"; + } + rowFormat += "%-" + colWidths[i] + "s"; + separator += String.format("%" + colWidths[i] + "s", "").replaceAll(" ", "-"); + } + out.println(String.format(rowFormat, tr("Command"), tr("Permission"), tr("Description"))); + for (Row row : getRows()) { + if (row == null) { + out.println(separator); + } else { + String cmd = row.getCommand().isEmpty() ? "" : "/" + row.getCommand(); + String description = row.getDescription(); + List strings = FormatUtil.wordWrapStrict(description, colWidths[2]); + out.println(String.format(rowFormat, cmd, row.getPermission(), strings.size() > 0 ? strings.get(0) : "")); + for (int i = 1; i < strings.size(); i++) { + out.println(String.format(rowFormat, "", "", strings.get(i))); + } + } + } + } + +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitor.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitor.java new file mode 100644 index 000000000..2b34d29d6 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitor.java @@ -0,0 +1,266 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandExecutor; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Generates a yml-file following the syntax define in http://wiki.bukkit.org/Plugin_YAML + * @since 1.8 + */ +public class PluginYamlCommandVisitor implements DocumentWriter { + private final int groupDepth; + + List topLevel = new ArrayList<>(); + PermissionNode rootNode; + + PluginYamlCommandVisitor() { + this(2); + } + + PluginYamlCommandVisitor(int groupDepth) { + this.groupDepth = groupDepth; + rootNode = new PermissionNode(""); + } + + public void writeTo(PrintStream out) { + out.println("commands:"); + for (Command cmd : topLevel) { + out.println(" " + cmd.getName() + ":"); + out.println(" description: '" + cmd.getDescription().replaceAll("'", "''") + "'"); + if (cmd.getAliases().length > 1) { + String[] copy = new String[cmd.getAliases().length-1]; + System.arraycopy(cmd.getAliases(), 1, copy, 0, copy.length); + out.println(" aliases: " + Arrays.toString(copy)); + } + if (cmd.getPermission() != null && !cmd.getPermission().isEmpty()) { + out.println(" permission: " + cmd.getPermission()); + } + } + out.println("permissions:"); + out.println(" #"); + out.println(" # Permission Groups"); + out.println(" # ================="); + for (PermissionNode node : rootNode.getRoots()) { + if (!node.permission.isEmpty()) { + if (node.permission.split("\\.").length > groupDepth) { + continue; // Skip + } + out.println(" " + node.permission + ".*:"); + out.println(" children:"); + for (String p : node.getChildPermissions()) { + out.println(" " + p + ": true"); + } + out.println(); + } + } + out.println(" #"); + out.println(" # Permission Descriptions"); + out.println(" # ======================="); + for (PermissionNode node : rootNode.getLeafs()) { + if (!node.permission.isEmpty()) { + out.println(" " + node.permission + ":"); + String desc = node.getDescription(); + if (desc != null) { + out.println(" description: " + desc); + } + out.println(); + } + } + } + + private static String getCmdDescription(Command cmd) { + return "/" + getCommandPath(cmd) + " - " + cmd.getDescription(); + } + + private static String getCommandPath(Command cmd) { + String path = cmd.getParent() != null ? getCommandPath(cmd.getParent()) + " " : ""; + return path + cmd.getName() + CompositeCommand.getParamsAsString(cmd); + } + + @Override + public void visit(Command cmd) { + if (cmd instanceof CommandExecutor) { + topLevel.add(cmd); + } + String permission = getPermission(cmd); + rootNode.add(permission, cmd); + for (Map.Entry entry : cmd.getFeaturePermissions().entrySet()) { + rootNode.add(entry.getKey(), entry.getValue()); + } + } + + private String getPermission(Command cmd) { + if (cmd.getPermission() == null && cmd.getParent() != null) { + return getPermission(cmd.getParent()); + } else if (cmd.getPermission() != null) { + return cmd.getPermission(); + } + return null; + } + + static class PermissionNode implements Comparable { + String permission; + String description; // Used for feature perms + List children = new ArrayList<>(); + List commands = new ArrayList<>(); + + PermissionNode(String permission) { + this.permission = permission; + } + + PermissionNode(String permission, Command cmd) { + this.permission = permission; + commands.add(cmd); + } + + void add(String perm, Command cmd) { + if (permission.equalsIgnoreCase(perm) || perm == null) { + commands.add(cmd); + } else if (perm.startsWith(permission)) { + for (PermissionNode child : children) { + if (isSub(child, perm)) { + child.add(perm, cmd); + return; + } + } + String[] parts = !permission.isEmpty() + ? perm.substring(permission.length() + 1).split("\\.") + : perm.split("\\."); + String parentPerm = !permission.isEmpty() + ? permission + "." + parts[0] + : parts[0]; + PermissionNode n = new PermissionNode(parentPerm); + children.add(n); + for (int i = 1; i < parts.length; i++) { + parentPerm += "." + parts[i]; + PermissionNode newNode = new PermissionNode(parentPerm); + n.children.add(newNode); + n = newNode; + } + n.commands.add(cmd); + } + } + + private boolean isSub(PermissionNode child, String perm) { + return perm.startsWith(child.permission) + && (child.permission.equalsIgnoreCase(perm) || (perm.length() > child.permission.length() + && perm.charAt(child.permission.length()) == '.') + ); + } + + void add(String perm, String description) { + if (permission.equalsIgnoreCase(perm) || perm == null) { + if (this.description == null) { + this.description = description; + } + } else if (perm.startsWith(permission)) { + for (PermissionNode child : children) { + if (isSub(child, perm)) { + child.add(perm, description); + return; + } + } + String[] parts = !permission.isEmpty() + ? perm.substring(permission.length() + 1).split("\\.") + : perm.split("\\."); + String parentPerm = !permission.isEmpty() + ? permission + "." + parts[0] + : parts[0]; + PermissionNode n = new PermissionNode(parentPerm); + children.add(n); + for (int i = 1; i < parts.length; i++) { + parentPerm += "." + parts[i]; + PermissionNode newNode = new PermissionNode(parentPerm); + n.children.add(newNode); + n = newNode; + } + n.description = description; + } + } + + List getChildPermissions() { + List perms = new ArrayList<>(); + for (PermissionNode child : children) { + perms.add(child.permission); + perms.addAll(child.getChildPermissions()); + } + Collections.sort(perms); + return perms; + } + + void addRoots(List roots) { + if (!children.isEmpty()) { + roots.add(this); + for (PermissionNode node : children) { + node.addRoots(roots); + } + } + } + + List getRoots() { + List roots = new ArrayList<>(); + addRoots(roots); + Collections.sort(roots); + return roots; + } + + void addLeafs(List leafs) { + if (children.isEmpty() || !commands.isEmpty()) { + leafs.add(this); + } + for (PermissionNode node : children) { + node.addLeafs(leafs); + } + } + + List getLeafs() { + List leafs = new ArrayList<>(); + addLeafs(leafs); + Collections.sort(leafs); + return leafs; + } + + String getDescription() { + if (description != null) { + return "'" + description + "'"; + } + if (commands.size() == 1) { + return "'Grants access to " + getCmdDescription(commands.get(0)) + "'"; + } else if (commands.size() > 1) { + String desc = "|" + System.lineSeparator(); + desc += " Grants access to " + getCmdDescription(commands.get(0)); + for (int i = 1; i < commands.size(); i++) { + desc += System.lineSeparator(); + desc += " " + getCmdDescription(commands.get(i)); + } + return desc; + } + return null; + } + + public PermissionNode find(String perm) { + if (permission.equals(perm)) { + return this; + } else if (perm.startsWith(permission)) { + for (PermissionNode n : children) { + PermissionNode r = n.find(perm); + if (r != null) { + return r; + } + } + } + return null; + } + + @Override + public int compareTo(PermissionNode o) { + return permission.compareTo(o.permission); + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/README.md new file mode 100644 index 000000000..10badd268 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/README.md @@ -0,0 +1,73 @@ +# Commands + +This package contains a lot of convenience classes to easily create commands for use with Bukkit. + +It has an in-build help system, with pagination, and permission-control. + +# Usage + +## Getting Started + +To create a composite entry-level command, simply inherit from the `AbstractCommandExecutor` in your main plugin. + +```java +class MyPlugin extends JavaPlugin { + @Override + public void onEnable() { + mycmd = new AbstractCommandExecutor("mycmd", "myplugin.perm.mycmd", "main myplugin command"); + mycmd.add(new AbstractCommand("hello|h", "myplugin.perm.hello", "say hello to the player") { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + sender.sendMessage(new String[]{ + "Hello! and welcome " + sender.getName(), + "I was called with : " + alias, + "I had " + args.length + " arguments: " + Arrays.asList(args) + }); + return true; + } + }); + getCommand("mycmd", mycmd); + } +} +``` + +The above code, will register 2 commands for the plugin. +One is nested within the other. + +Help is automatically generated, so invoking `/mycmd` will show a list of possible options. +Invoking `/mycmd h your momma` will output: + +``` +Hello! and welcome CONSOLE +I was called with : h +I had 2 arguments: [your, momma] +``` + +## Tab-Completion + +All CompositeCommands have automatic tab-completion of their sub-commands. + +If you want to have tab-completion of arguments, you can easily roll your own: + +```java +monsterTab = new AbstractTabCompleter() { + @Override + protected List getTabList(CommandSender commandSender, String term) { + return Arrays.asList("animal", "monster", "villager"); + } +} +``` +The above tab-completer will do filtering automatically. + +Tab-completers can be re-used, if they handle a named argument: + +```java + public class MyCmd extends CompositeCommand { + public MyCmd() { + super("mycmd", "perm.mycmd", "main command"); + add(new AbstractCommand("list", "perm.list", "?monster", "lists a subset") { ... }); + add(new AbstractCommand("spawn", "perm.spawn", "monster", "spawn a monster") { ... }); + addTab("monster", monsterTab); + } + } +``` \ No newline at end of file diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/RowCommandVisitor.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/RowCommandVisitor.java new file mode 100644 index 000000000..3d50a933b --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/RowCommandVisitor.java @@ -0,0 +1,90 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandExecutor; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * A visitor that simply gathers the complete command-hierarchy into a list of rows. + * @since 1.8 + */ +class RowCommandVisitor implements CommandVisitor { + private final List rows = new ArrayList<>(); + + public List getRows() { + return rows; + } + + @Override + public void visit(Command cmd) { + if (cmd instanceof CommandExecutor) { + rows.add(null); // separator + } + String commandPath = getCommandPath(cmd); + String alias = getAliases(cmd); + if (!alias.isEmpty()) { + String shortCmd = getShortestCmd(cmd); + int ix = commandPath.lastIndexOf(" " + shortCmd) + 1; + commandPath = commandPath.substring(0, ix) + cmd.getName() + alias + commandPath.substring(ix+shortCmd.length()); + } + rows.add(new Row(commandPath, cmd.getDescription(), cmd.getPermission())); + List extraPerms = new ArrayList<>(cmd.getFeaturePermissions().keySet()); + Collections.sort(extraPerms); + for (String p : extraPerms) { + rows.add(new Row(null, cmd.getFeaturePermissions().get(p), p)); + } + } + + private String getCommandPath(Command cmd) { + String path = cmd.getParent() != null ? getCommandPath(cmd.getParent()) + " " : ""; + return path + getShortestCmd(cmd) + CompositeCommand.getParamsAsString(cmd); + } + + private String getShortestCmd(Command cmd) { + String cmdName = cmd.getName(); + for (String alias : cmd.getAliases()) { + if (alias.length() < cmdName.length()) { + cmdName = alias; + } + } + return cmdName; + } + + private String getAliases(Command cmd) { + String aliases = ""; + for (int i = 1; i < cmd.getAliases().length; i++) { + aliases += "|" + cmd.getAliases()[i]; + } + return aliases; + } + + static class Row { + private final String command; + private final String description; + private final String permission; + + Row(String command, String description, String permission) { + this.command = command; + this.description = description; + this.permission = permission; + } + + public String getCommand() { + return command != null ? command : ""; + } + + public String getDescription() { + return description != null ? description : ""; + } + + public String getPermission() { + return permission != null ? permission : ""; + } + + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java new file mode 100644 index 000000000..d9227d208 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java @@ -0,0 +1,43 @@ +package dk.lockfuglsang.minecraft.command.completion; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * Common ancestor of the TabCompleters. + * Uses the Template Pattern for sub-classes. + */ +public abstract class AbstractTabCompleter implements TabCompleter { + + abstract protected List getTabList(CommandSender commandSender, String term); + + @Override + public List onTabComplete(CommandSender commandSender, Command command, String alias, String[] args) { + String term = args.length > 0 ? args[args.length-1] : ""; + return filter(getTabList(commandSender, term), term); + } + + public static List filter(List list, String prefix) { + Set filtered = new LinkedHashSet<>(); + if (list != null) { + Collections.sort(list); + String lowerPrefix = prefix.toLowerCase(); + for (String test : list) { + if (test.toLowerCase().startsWith(lowerPrefix)) { + filtered.add(test); + } + } + } + if (filtered.size() > 20) { + return new ArrayList<>(filtered).subList(0, 20); + } + return new ArrayList<>(filtered); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java new file mode 100644 index 000000000..1a31e3e8f --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java @@ -0,0 +1,26 @@ +package dk.lockfuglsang.minecraft.command.completion; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +import java.util.List; + +/** + * TabCompleter that supports multiple tab-completers for different arguments. + */ +public class CompositeTabCompleter implements TabCompleter { + private final TabCompleter[] completers; + + public CompositeTabCompleter(TabCompleter... completers) { + this.completers = completers; + } + + @Override + public List onTabComplete(CommandSender commandSender, Command command, String alias, String[] args) { + if (completers.length <= args.length) { + return completers[args.length-1].onTabComplete(commandSender, command, alias, args); + } + return null; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java new file mode 100644 index 000000000..6e6215824 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java @@ -0,0 +1,24 @@ +package dk.lockfuglsang.minecraft.command.completion; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.List; + +/** + * Convenience implementation of a tab-completer for all offline players + */ +public class OfflinePlayerTabCompleter extends AbstractTabCompleter { + @Override + protected List getTabList(CommandSender commandSender, String term) { + List tabList = new ArrayList<>(); + for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { + if (player != null) { + tabList.add(player.getName()); + } + } + return tabList; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java new file mode 100644 index 000000000..211a51684 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java @@ -0,0 +1,24 @@ +package dk.lockfuglsang.minecraft.command.completion; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +/** + * Convenience implementation of a tab-completer for all online players + */ +public class OnlinePlayerTabCompleter extends AbstractTabCompleter { + @Override + protected List getTabList(CommandSender commandSender, String term) { + List tabList = new ArrayList<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (player != null && player.isOnline()) { + tabList.add(player.getName()); + } + } + return tabList; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java new file mode 100644 index 000000000..35360914c --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java @@ -0,0 +1,334 @@ +package dk.lockfuglsang.minecraft.file; + +import dk.lockfuglsang.minecraft.yml.YmlConfiguration; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.FileConfiguration; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Common file-utilities. + */ +public enum FileUtil {; + private static final Logger log = Logger.getLogger(FileUtil.class.getName()); + private static final Collection allwaysOverwrite = new ArrayList<>(); + private static final Collection neverOverwrite = new ArrayList<>(); + private static final Map configFiles = new ConcurrentHashMap<>(); + private static Locale locale = Locale.getDefault(); + private static File dataFolder; + + public static void setAllwaysOverwrite(String... configs) { + for (String s : configs) { + if (!allwaysOverwrite.contains(s)) { + allwaysOverwrite.add(s); + } + } + } + + public static void setNeverOverwrite(String... configs) { + for (String s : configs) { + if (!neverOverwrite.contains(s)) { + neverOverwrite.add(s); + } + } + } + + public static YmlConfiguration loadConfig(File file) { + YmlConfiguration config = new YmlConfiguration(); + readConfig(config, file); + return config; + } + + public static void readConfig(FileConfiguration config, File file) { + if (file == null) { + log.log(Level.INFO, "No " + file + " found, it will be created"); + return; + } + File configFile = file; + File localeFile = new File(configFile.getParentFile(), getLocaleName(file.getName())); + if (localeFile.exists() && localeFile.canRead()) { + configFile = localeFile; + } + if (!configFile.exists()) { + log.log(Level.INFO, "No " + configFile + " found, it will be created"); + return; + } + try (Reader rdr = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { + config.load(rdr); + } catch (InvalidConfigurationException e) { + log.log(Level.SEVERE, "Unable to read config file " + configFile, e); + if (configFile.exists()) { + try { + Files.copy(Paths.get(configFile.toURI()), Paths.get(configFile.getParent(), configFile.getName() + ".err"), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e1) { + // Ignore - we tried... + } + } + } catch (IOException e) { + log.log(Level.SEVERE, "Unable to read config file " + configFile, e); + } + } + + public static void readConfig(FileConfiguration config, InputStream inputStream) { + if (inputStream == null) { + return; + } + try (Reader rdr = new InputStreamReader(inputStream, "UTF-8")) { + config.load(rdr); + } catch (InvalidConfigurationException | IOException e) { + log.log(Level.SEVERE, "Unable to read configuration", e); + } + } + + public static FilenameFilter createYmlFilenameFilter() { + return new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name != null && name.endsWith(".yml"); + } + }; + } + + public static String getBasename(File file) { + return getBasename(file.getName()); + } + + public static String getBasename(String file) { + String[] lastPart = file.split("(/|\\\\)"); + file = lastPart[lastPart.length-1]; + if (file != null && file.lastIndexOf('.') != -1) { + return file.substring(0, file.lastIndexOf('.')); + } + return file; + } + + public static String getExtension(String fileName) { + if (fileName != null && !fileName.isEmpty()) { + return fileName.substring(getBasename(fileName).length()+1); + } + return ""; + } + + private static File getDataFolder() { + return dataFolder != null ? dataFolder : new File("."); + } + + /** + * System-encoding agnostic config-reader + * Reads and returns the configuration found in: + *
+     *   a) the datafolder
+     *
+     *     a.1) if a config named "config_en.yml" exists - that is read.
+     *
+     *     a.2) otherwise "config.yml" is read (created if need be).
+     *
+     *   b) if the version differs from the same resource on the classpath
+     *
+     *      b.1) all nodes in the jar-file-version is merged* into the local-file
+     *
+     *      b.2) unless the configName is in the allwaysOverwrite - then the jar-version wins
+     *
+     * *merged: using data-conversion of special nodes.
+     * 
+ */ + public static YmlConfiguration getYmlConfiguration(String configName) { + // Caching, for your convenience! (and a bigger memory print!) + + if (!configFiles.containsKey(configName)) { + YmlConfiguration config = new YmlConfiguration(); + try { + // read from datafolder! + File configFile = getConfigFile(configName); + YmlConfiguration configJar = new YmlConfiguration(); + readConfig(config, configFile); + readConfig(configJar, getResource(configName)); + if (!configFile.exists() || config.getInt("version", 0) < configJar.getInt("version", 0)) { + if (configFile.exists()) { + if (neverOverwrite.contains(configName)) { + configFiles.put(configName, config); + return config; + } + File backupFolder = new File(getDataFolder(), "backup"); + backupFolder.mkdirs(); + String bakFile = String.format("%1$s-%2$tY%2$tm%2$td-%2$tH%2$tM.yml", getBasename(configName), new Date()); + log.log(Level.INFO, "Moving existing config " + configName + " to backup/" + bakFile); + Files.move(Paths.get(configFile.toURI()), + Paths.get(new File(backupFolder, bakFile).toURI()), + StandardCopyOption.REPLACE_EXISTING); + if (allwaysOverwrite.contains(configName)) { + FileUtil.copy(getResource(configName), configFile); + config = configJar; + } else { + config = mergeConfig(configJar, config); + config.save(configFile); + config.load(configFile); + } + } else { + config = mergeConfig(configJar, config); + config.save(configFile); + config.load(configFile); + } + } + } catch (Exception e) { + log.log(Level.SEVERE, "Unable to handle config-file " + configName, e); + } + configFiles.put(configName, config); + } + return configFiles.get(configName); + } + + private static InputStream getResource(String configName) { + String resourceName = getLocaleName(configName); + ClassLoader loader = FileUtil.class.getClassLoader(); + InputStream resourceAsStream = loader.getResourceAsStream(resourceName); + if (resourceAsStream != null) { + return resourceAsStream; + } + return loader.getResourceAsStream(configName); + } + + private static String getLocaleName(String fileName) { + String baseName = getBasename(fileName); + return baseName + "_" + locale + fileName.substring(baseName.length()); + } + + public static File getConfigFile(String configName) { + File file = new File(getDataFolder(), getLocaleName(configName)); + if (file.exists()) { + return file; + } + return new File(getDataFolder(), configName); + } + + public static void copy(InputStream stream, File file) throws IOException { + if (stream == null || file == null) { + throw new IOException("Invalid resource for " + file); + } + Files.copy(stream, Paths.get(file.toURI()), StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Merges the important keys from src to destination. + * @param src The source (containing the new values). + * @param dest The destination (containing old-values). + */ + private static YmlConfiguration mergeConfig(YmlConfiguration src, YmlConfiguration dest) { + int existing = dest.getInt("version"); + int version = src.getInt("version", existing); + dest.setDefaults(src); + dest.options().copyDefaults(true); + dest.addComments(src.getComments()); + dest.set("version", version); + dest.options().copyHeader(false); + src.options().copyHeader(false); + removeExcludes(dest); + moveNodes(src, dest); + replaceDefaults(src, dest); + return dest; + } + + /** + * Removes nodes from dest.defaults, that are specifically excluded in the config + */ + private static void removeExcludes(YmlConfiguration dest) { + List keys = dest.getStringList("merge-ignore"); + for (String key : keys) { + dest.getDefaults().set(key, null); + } + } + + private static void replaceDefaults(YmlConfiguration src, YmlConfiguration dest) { + ConfigurationSection forceSection = src.getConfigurationSection("force-replace"); + if (forceSection != null) { + for (String key : forceSection.getKeys(true)) { + Object def = forceSection.get(key, null); + Object value = dest.get(key, def); + Object newDef = src.get(key, null); + if (def != null && def.equals(value)) { + dest.set(key, newDef); + } + } + } + dest.set("force-replace", null); + dest.getDefaults().set("force-replace", null); + } + + private static void moveNodes(YmlConfiguration src, YmlConfiguration dest) { + ConfigurationSection moveSection = src.getConfigurationSection("move-nodes"); + if (moveSection != null) { + List keys = new ArrayList<>(moveSection.getKeys(true)); + Collections.reverse(keys); // Depth first + for (String key : keys) { + if (moveSection.isString(key)) { + String srcPath = key; + String tgtPath = moveSection.getString(key, key); + Object value = dest.get(srcPath); + if (value != null) { + dest.set(tgtPath, value); + dest.set(srcPath, null); + } + } else if (moveSection.isConfigurationSection(key)) { + // Check to see if dest section should be nuked... + if (dest.isConfigurationSection(key) && dest.getConfigurationSection(key).getKeys(false).isEmpty()) { + dest.set(key, null); + } + } + } + } + dest.set("move-nodes", null); + dest.getDefaults().set("move-nodes", null); + } + + public static void setDataFolder(File dataFolder) { + FileUtil.dataFolder = dataFolder; + configFiles.clear(); + } + + public static void setLocale(Locale loc) { + locale = loc != null ? loc : locale; + } + + public static void reload() { + for (Map.Entry e : configFiles.entrySet()) { + File configFile = new File(getDataFolder(), e.getKey()); + readConfig(e.getValue(), configFile); + } + } + + public static Properties readProperties(String fileName) { + File configFile = getConfigFile(fileName); + if (configFile != null && configFile.exists() && configFile.canRead()) { + Properties prop = new Properties(); + try (InputStreamReader in = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { + prop.load(in); + return prop; + } catch (IOException e) { + log.log(Level.WARNING, "Error reading " + fileName, e); + } + } + return null; + } + +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/README.md new file mode 100644 index 000000000..85a8ef49d --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/README.md @@ -0,0 +1,47 @@ +# File Utilities + +The `FileUtil` class simplifies resource reading for Bukkit plugins. + +## Features + +The primary usage of the FileUtil, is to read yml-files from the plugin-datafolder. + +The utility supports the following features: + + * Reading files in UTF-8, regardless of system-encoding. + * Support merging yml files from classpath (jar) with plugin files. + * Support for `version`ing of individual yml files. + * Support for localization of configuration files. + * Support for data-conversion on merges. + * Support caching of configuration objects (only read from disk once). + +## Usage + +```java + @Override + void onEnable() { + FileUtil.setDataFolder(getDataFolder()); // init plugin-data-folder + FileUtil.setLocale(new Locale("en")); // set locale used in locating translated resources + + YmlConfiguration config = FileUtil.getYmlConfiguration("config.yml"); + if (config.getBoolean("feature.enabled", true)) { + // do feature stuff + } + } +``` + +The `config` in the above example is created the following way: + * Read `config.yml` from the data-folder + * if a `config_en.yml` exists - read it + * else if a `config.yml` exist - read it + * Read `config.yml` from the jar-file (classpath) + * if a 'config_en.yml` exists - read it + * else if a `config.yml` exsits - read it + * Compare `version` read from both configs + * if `config.yml` is listed in `allwaysOverwrite` - just use the jar-file + * else if jar-version > file-version or file-version does not exist + * merge nodes from jar into config - preserving node-comments + * ignore nodes listed in `merge-ignore` from the existing config-file + * move nodes listed in `move-nodes` from the jar-file + * replace nodes listed in `replace-nodes` from the jar-file, if they have default values + * set `version` to the jar-file version diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java new file mode 100644 index 000000000..b1a92422c --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java @@ -0,0 +1,4 @@ +/** + * Holds a frame-work for making GUI components (inventory based) in Bukkit Minecraft. + */ +package dk.lockfuglsang.minecraft.gui; \ No newline at end of file diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java new file mode 100644 index 000000000..4b96bfe46 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java @@ -0,0 +1,100 @@ +package dk.lockfuglsang.minecraft.nbt; + +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.logging.Logger; + +import static dk.lockfuglsang.minecraft.reflection.ReflectionUtil.*; + +/** + * An NBTItemStackTagger using reflection for CraftBukkit based servers. + */ +public class CraftBukkitNBTTagger implements NBTItemStackTagger { + private static final Logger log = Logger.getLogger(CraftBukkitNBTTagger.class.getName()); + + @Override + public String getNBTTag(ItemStack itemStack) { + if (itemStack == null) { + return ""; + } + Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); + Object nbtTag = exec(nmsItem, "getTag"); + return nbtTag != null ? "" + nbtTag : ""; + } + + @Override + public ItemStack setNBTTag(ItemStack itemStack, String nbtTagString) { + if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { + return itemStack; + } + Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); + Object nbtTag = execStatic(getNBTTagParser(), "parse", nbtTagString); + exec(nmsItem, "setTag", nbtTag); + Object item = execStatic(getCraftItemStackClass(), "asBukkitCopy", nmsItem); + if (item instanceof ItemStack) { + return (ItemStack) item; + } + return itemStack; + } + + @Override + public ItemStack addNBTTag(ItemStack itemStack, String nbtTagString) { + if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { + return itemStack; + } + Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); + Object nbtTag = exec(nmsItem, "getTag"); + Object nbtTagNew = execStatic(getNBTTagParser(), "parse", nbtTagString); + nbtTag = merge(nbtTagNew, nbtTag); + exec(nmsItem, "setTag", nbtTag); + Object item = execStatic(getCraftItemStackClass(), "asBukkitCopy", nmsItem); + if (item instanceof ItemStack) { + return (ItemStack) item; + } + return itemStack; + } + + /** + * Merges two NBTTagCompound objects + */ + private static Object merge(Object src, Object tgt) { + if (tgt == null) { + return src; + } + try { + Field mapField = src.getClass().getDeclaredField("x"); + mapField.setAccessible(true); + Map map = (Map) mapField.get(src); + Class NBTBase = Class.forName(getPackageName(tgt) + ".NBTBase"); + for (String key : map.keySet()) { + Object val = exec(src, "get", new Class[]{String.class}, key); + exec(tgt, "set", new Class[]{String.class, NBTBase}, key, val); + } + return tgt; + } catch (IllegalAccessException | ClassNotFoundException | NoSuchFieldException e) { + log.info("Unable to transfer NBTTag from " + src + " to " + tgt + ": " + e); + } + return tgt; + } + + private static Class getNBTTagParser() { + try { + return Class.forName("net.minecraft.nbt.MojangsonParser"); + } catch (ClassNotFoundException e) { + log.info("Unable to instantiate MojangsonParser: " + e); + } + return null; + } + + private static Class getCraftItemStackClass() { + String version = getCraftBukkitVersion(); + try { + return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); + } catch (Exception e) { + log.info("Unable to find CraftItemStack: " + e); + } + return null; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java new file mode 100644 index 000000000..21f05d0cd --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java @@ -0,0 +1,33 @@ +package dk.lockfuglsang.minecraft.nbt; + +import org.bukkit.inventory.ItemStack; + +/** + * Interface for allowing depencency injection for testing (and other platforms than CraftBukkit). + */ +public interface NBTItemStackTagger { + /** + * Returns the NBTTag of the itemStack as a string, or the empty-string if none was found. + * @param itemStack A Bukkit ItemStack + * @return the NBTTag + * @since 1.7.2 + */ + String getNBTTag(ItemStack itemStack); + /** + * Returns a copy of the itemStack with the supplied nbtTagString applied. + * @param itemStack A Bukkit ItemStack + * @param tag A valid NBTTag string + * @return a copy of the itemStack + * @since 1.7.2 + */ + ItemStack setNBTTag(ItemStack itemStack, String tag); + + /** + * Returns a copy of the itemStack with the supplied nbtTagString applied. + * @param itemStack A Bukkit ItemStack + * @param tag A valid NBTTag string + * @return a copy of the itemStack + * @since 1.7.2 + */ + ItemStack addNBTTag(ItemStack itemStack, String tag); +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java new file mode 100644 index 000000000..1948b18e3 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java @@ -0,0 +1,63 @@ +package dk.lockfuglsang.minecraft.nbt; + +import org.bukkit.inventory.ItemStack; + +import java.util.logging.Logger; + +/** + * Utility for setting NBTTag data on Bukkit items without NMS (using reflection). + * @since 1.7 + */ +public enum NBTUtil { ; + private static final Logger log = Logger.getLogger(NBTUtil.class.getName()); + + private static NBTItemStackTagger tagger = new CraftBukkitNBTTagger(); + + /** + * Returns the NBTTag of the itemStack as a string, or the empty-string if none was found. + * @param itemStack A Bukkit ItemStack + * @return the NBTTag + * @since 1.7 + */ + public static String getNBTTag(ItemStack itemStack) { + if (itemStack == null) { + return ""; + } + return tagger.getNBTTag(itemStack); + } + + /** + * Returns a copy of the itemStack with the supplied nbtTagString applied. + * @param itemStack A Bukkit ItemStack + * @param nbtTagString A valid NBTTag string + * @return a copy of the itemStack + * @since 1.7 + */ + public static ItemStack setNBTTag(ItemStack itemStack, String nbtTagString) { + if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { + return itemStack; + } + return tagger.setNBTTag(itemStack, nbtTagString); + } + + /** + * Returns a copy of the itemStack with the supplied nbtTagString applied. + * @param itemStack A Bukkit ItemStack + * @param nbtTagString A valid NBTTag string + * @return a copy of the itemStack + * @since 1.7 + */ + public static ItemStack addNBTTag(ItemStack itemStack, String nbtTagString) { + if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { + return itemStack; + } + return tagger.addNBTTag(itemStack, nbtTagString); + } + + public static void setNBTItemStackTagger(NBTItemStackTagger tagger) { + if (tagger == null) { + throw new IllegalArgumentException("tagger cannot be null"); + } + NBTUtil.tagger = tagger; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md new file mode 100644 index 000000000..08e2ece60 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md @@ -0,0 +1,5 @@ +# NBT Utilities + +This package contains utilities to access/tweak the NBTTags when running a Bukkit plugin. + +# License diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java new file mode 100644 index 000000000..7a61606cc --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java @@ -0,0 +1,356 @@ +package dk.lockfuglsang.minecraft.reflection; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * Wrapper methods that allow accesss to reflection for backward compatible code. + * + * @since 1.8 + */ +public class ReflectionUtil { + private static final Logger log = Logger.getLogger(ReflectionUtil.class.getName()); + + /** + * Returns the current version of the Bukkit implementation + * + * @return the current version of the Bukkit implementation + * @since 1.8 + */ + public static String getCraftBukkitVersion() { + return cb().split("\\.")[3]; + } + + /** + * Returns the current version of the net.minecraft.server implementation + * + * @param nmsObject A native object from nms namespace + * @return the current version of the net.minecraft.server implementation + * @since 1.8 + */ + public static String getNMSVersion(Object nmsObject) { + return nmsObject != null ? nmsObject.getClass().getPackage().getName().split("\\.")[3] : ""; + } + + /** + * Returns the NMS version. + * @return the NMS version (i.e. "v1_10"). + * @since 1.9 + */ + public static String getNMSVersion() { + return nms().split("\\.")[3]; + } + + /** + * Returns the real packagename for the net.minecraft.server. + * @return the real packagename for the net.minecraft.server. + * @since 1.9 + */ + public static String nms() { + Object nmsServer = exec(Bukkit.getServer(), "getServer"); + return nmsServer != null ? nmsServer.getClass().getPackage().getName() : "net.minecraft.server"; + } + + /** + * Returns the real packagename for the org.bukkit.craftbukkit package + * @return the real packagename for the org.bukkit.craftbukkit package + * @since 1.9 + */ + public static String cb() { + return Bukkit.getServer().getClass().getPackage().getName(); + } + + /** + * Returns the packagename of the given object. + * + * @param nmsObject An object + * @return the packagename of the given object. + * @since 1.8 + */ + public static String getPackageName(Object nmsObject) { + return nmsObject != null ? nmsObject.getClass().getPackage().getName() : ""; + } + + /** + * Returns the corresponding Bukkit class, given a CraftBukkit implementation object. + * + * @param craftObject A CraftBukkit implementation of a Bukkit class. + * @return the corresponding Bukkit class, given a CraftBukkit implementation object. + * @since 1.8 + */ + public static Class getBukkitClass(Object craftObject) { + Class clazz = craftObject != null ? craftObject.getClass() : null; + while (clazz != null && clazz.getCanonicalName().contains(".craftbukkit.")) { + clazz = clazz.getSuperclass(); + } + return clazz; + } + + /** + * Uses reflection to execute the named method on the supplied class giving the arguments. + * Sinks all exceptions, but log an entry and returns null + * + * @param clazz The class on which to invoke the method + * @param methodName The name of the method to invoke + * @param args The arguments to supply to the method + * @return null or the return-object from the method. + * @since 1.8 + */ + public static T execStatic(Class clazz, String methodName, Object... args) { + try { + Class[] argTypes = new Class[args.length]; + int ix = 0; + for (Object arg : args) { + argTypes[ix++] = getBukkitClass(arg); + } + Method method = getMethod(clazz, methodName, argTypes); + boolean wasAccessible = method.isAccessible(); + method.setAccessible(true); + try { + return (T) method.invoke(null, args); + } finally { + method.setAccessible(wasAccessible); + } + } catch (NoSuchMethodException e) { + log.fine("Unable to locate method " + methodName + " on " + clazz); + } catch (InvocationTargetException | IllegalAccessException e) { + log.log(Level.INFO, "Calling " + methodName + " on " + clazz + " threw an exception", e); + } + return null; + } + + /** + * Uses reflection to execute the named method on the supplied class giving the arguments. + * Sinks all exceptions, but log an entry and returns null + * + * @param obj The object on which to invoke the method + * @param methodName The name of the method to invoke + * @param argTypes An array of argument-types (classes). + * @param args The arguments to supply to the method + * @return null or the return-object from the method. + * @since 1.8 + */ + public static T exec(Object obj, String methodName, Class[] argTypes, Object... args) { + if (obj == null) { + return null; + } + Class aClass = obj.getClass(); + try { + Method method = getMethod(aClass, methodName, argTypes); + boolean wasAccessible = method.isAccessible(); + method.setAccessible(true); + try { + return (T) method.invoke(obj, args); + } finally { + method.setAccessible(wasAccessible); + } + } catch (NoSuchMethodException | AbstractMethodError e) { + log.fine("Unable to locate method " + methodName + "(" + Arrays.asList(argTypes) + ") on " + aClass); + } catch (InvocationTargetException | IllegalAccessException e) { + log.log(Level.INFO, "Calling " + methodName + " on " + obj + " threw an exception", e); + } + return null; + } + + public static Method getMethod(Class aClass, String methodName, Class... argTypes) throws NoSuchMethodException { + try { + // Declared gives access to non-public + return aClass.getDeclaredMethod(methodName, argTypes); + } catch (NoSuchMethodException e) { + return aClass.getMethod(methodName, argTypes); + } + } + + public static Method findMethod(Class aClass, Class returnType, Class... argTypes) throws NoSuchMethodException { + List methods = findMethods(aClass, returnType, argTypes); + if (methods.isEmpty()) { + throw new NoSuchMethodException("No method matching " + returnType + " ?(" + Arrays.toString(argTypes) + ")"); + } + if (methods.size() > 1) { + throw new NoSuchMethodException("More than 1 method matching " + returnType + " ?(" + Arrays.toString(argTypes) + ") : " + methods); + } + return methods.get(0); + } + + public static List findMethods(Class aClass, Class returnType, Class... argTypes) throws NoSuchMethodException { + List methods = new ArrayList<>(); + for (Method m : aClass.getDeclaredMethods()) { + if (m.getReturnType() == returnType && m.getParameterTypes().length == argTypes.length) { + try { + Method mLookup = aClass.getMethod(m.getName(), argTypes); + if (mLookup != null) { + methods.add(mLookup); + } + } catch (NoSuchMethodException e) { + // ignore... + } + } + } + return methods; + } + + /** + * Uses reflection to execute the named method on the supplied class giving the arguments. + * Sinks all exceptions, but log an entry and returns null + * + * @param obj The object on which to invoke the method + * @param methodName The name of the method to invoke + * @param args The arguments to supply to the method + * @return null or the return-object from the method. + * @since 1.8 + */ + public static T exec(Object obj, String methodName, Object... args) { + if (obj == null) { + return null; + } + Class[] argTypes = new Class[args.length]; + int ix = 0; + for (Object arg : args) { + argTypes[ix++] = arg != null ? arg.getClass() : null; + } + return exec(obj, methodName, argTypes, args); + } + + /** + * Returns the value of a field on the object. + * @param obj The object + * @param fieldName The name of the field + * @param The type of field + * @return the value or null + * @since 1.9 + */ + public static T getField(Object obj, String fieldName) { + try { + Field field = getFieldInternal(obj, fieldName); + boolean wasAccessible = field.isAccessible(); + field.setAccessible(true); + try { + return (T) field.get(obj); + } finally { + field.setAccessible(wasAccessible); + } + } catch (NoSuchFieldException | IllegalAccessException e) { + log.fine("Unable to find field " + fieldName + " on " + obj); + } + return null; + } + + private static Field getFieldInternal(Object obj, String fieldName) throws NoSuchFieldException { + return getFieldFromClass(obj.getClass(), fieldName); + } + + private static Field getFieldFromClass(Class aClass, String fieldName) throws NoSuchFieldException { + if (aClass == null) { + throw new NoSuchFieldException("Unable to locate field " + fieldName); + } + try { + return aClass.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + // Ignored + } + try { + return aClass.getField(fieldName); + } catch (NoSuchFieldException e) { + // Ignore + } + return getFieldFromClass(aClass.getSuperclass(), fieldName); + } + + /** + * Sets the value of a field on the object. + * @param obj The object + * @param fieldName The name of the field + * @param field The value to set + * @param The type of field + * @since 1.9 + */ + public static void setField(Object obj, String fieldName, T field) { + try { + Field declaredField = getFieldInternal(obj, fieldName); + boolean wasAccessible = declaredField.isAccessible(); + declaredField.setAccessible(true); + try { + declaredField.set(obj, field); + } finally { + declaredField.setAccessible(wasAccessible); + } + } catch (NoSuchFieldException | IllegalAccessException e) { + log.fine("Unable to find field " + fieldName + " on " + obj); + } + } + + /** + * Instantiates an object. + * @param className The name of the class + * @param argTypes An array of argument-types + * @param args An array of arguments + * @param Return-type + * @return the object, or null. + * @since 1.9 + */ + public static T newInstance(String className, Class[] argTypes, Object... args) { + try { + Class aClass = Class.forName(className); + Constructor constructor = aClass.getDeclaredConstructor(argTypes); + return (T) constructor.newInstance(args); + } catch (InstantiationException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + log.fine("Unable to instantiate object of type " + className + ":" + e); + } + return null; + } + + /** + * Instantiates an object. + * @param className The name of the class + * @param args An array of arguments + * @param Return-type + * @return the object, or null. + * @since 1.9 + */ + public static T newInstance(String className, Object... args) { + Class[] argTypes = new Class[args.length]; + int ix = 0; + for (Object arg : args) { + argTypes[ix++] = arg != null ? arg.getClass() : null; + } + return newInstance(className, argTypes, args); + } + + public static List dumpMethods(Class aClass) { + List methods = Arrays.asList(aClass.getDeclaredMethods()); + List methodDescriptions = new ArrayList<>(); + String version = getNMSVersion(); + for (Method m : methods) { + List parms = Arrays.asList(m.getParameterTypes()).stream().map(f -> f.getName()).collect(Collectors.toList()); + String parmString = Arrays.toString(parms.toArray(new String[0])); + parmString = parmString.substring(1, parmString.length() - 1); + String description = (Modifier.isPublic(m.getModifiers()) ? "public " : Modifier.isPrivate(m.getModifiers()) ? "private " : "") + + (Modifier.isStatic(m.getModifiers()) ? "static " : "") + + m.getReturnType() + " " + m.getName() + + "(" + parmString + ")"; + description = description + .replaceAll("class net.minecraft.server." + version + ".", "") + .replaceAll("net.minecraft.server." + version + ".", "") + .replaceAll("java.lang.", ""); + methodDescriptions.add(description); + } + List list = new ArrayList(); + + list.add(aClass.toString().replaceAll("class net.minecraft.server." + version + ".", "") + .replaceAll("net.minecraft.server." + version + ".", "") + .replaceAll("java.lang.", "") + ":"); + list.addAll(methodDescriptions.stream().sorted(String::compareTo).collect(Collectors.toList())); + return list; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java new file mode 100644 index 000000000..d56334cdc --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java @@ -0,0 +1,180 @@ +package dk.lockfuglsang.minecraft.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Format utility + */ +public enum FormatUtil {; + private static final Pattern FORMATTING = Pattern.compile("^.*(?(\u00a7[0-9a-fklmor])+).*"); + public static String stripFormatting(String format) { + if (format == null || format.trim().isEmpty()) { + return ""; + } + return format.replaceAll("(\u00a7|&)[0-9a-fklmor]", ""); + } + + public static String normalize(String format) { + if (format == null || format.trim().isEmpty()) { + return ""; + } + return format.replaceAll("(\u00a7|&)([0-9a-fklmor])", "\u00a7$2"); + } + + public static List wordWrap(String s, int lineSize) { + return wordWrap(s, lineSize, lineSize); + } + + /** + * Wraps the string rather lazyly around the linesize (over). + * + * I.e. + *
+     *   this is a line of words
+     * 
+ * Will break into the following with linesize of 11: + *
+     *   this is a line
+     *   of words
+     * 
+ * Note that the first line is longer than 11 (14). + */ + public static List wordWrap(String s, int firstSegment, int lineSize) { + String format = getFormat(s); + if (format == null || !s.startsWith(format)) { + format = ""; + } + List words = new ArrayList<>(); + int numChars = firstSegment; + int ix = 0; + int jx = 0; + while (ix < s.length()) { + ix = s.indexOf(' ', ix+1); + if (ix != -1) { + String subString = s.substring(jx, ix).trim(); + String f = getFormat(subString); + int chars = stripFormatting(subString).length() + 1; // remember the space + if (chars >= numChars) { + if (f != null) { + format = f; + } + if (!subString.isEmpty()) { + words.add(withFormat(format, subString)); + numChars = lineSize; + jx = ix + 1; + } + } + } else { + break; + } + } + words.add(withFormat(format, s.substring(jx).trim())); + return words; + } + + public static List wordWrapStrict(String s, int lineLength) { + List lines = new ArrayList<>(); + String format = getFormat(s); + if (format == null || !s.startsWith(format)) { + format = ""; + } + String[] words = s.split(" "); + String line = ""; + for (String word: words) { + String test = stripFormatting(line + " " + word).trim(); + if (test.length() <= lineLength) { + // add word + line += (line.isEmpty() ? "" : " ") + word; + } else if (line.isEmpty() || stripFormatting(word).length() > lineLength) { + // add word truncated + String f = getFormat(word); + String strip = stripFormatting(word); + do { + int len = Math.min(strip.length(), lineLength-line.length()-1); + lines.add(withFormat(format, line + (line.isEmpty() ? "" : " ") + strip.substring(0, len))); + strip = strip.substring(len); + if (f != null) { + format = f; + } + } while (strip.length() > lineLength); + line = strip; + } else { + // add line, then start a new + lines.add(withFormat(format, line)); + String f = getFormat(line); + if (f != null) { + format = f; + } + line = word; + } + } + if (!line.isEmpty()) { + lines.add(withFormat(format, line)); + } + return lines; + } + + private static String withFormat(String format, String subString) { + String sf = null; + if (!subString.startsWith("\u00a7")) { + sf = format + subString; + } else { + sf = subString; + } + return sf; + } + + private static String getFormat(String s) { + Matcher m = FORMATTING.matcher(s); + String format = null; + if (m.matches() && m.group("format") != null) { + format = m.group("format"); + } + return format; + } + + public static String join(List list, String separator) { + String joined = ""; + for (String s : list) { + joined += s + separator; + } + joined = !list.isEmpty() ? joined.substring(0, joined.length() - separator.length()) : joined; + return joined; + } + + public static List prefix(List list, String prefix) { + List prefixed = new ArrayList<>(list.size()); + for (String s : list) { + prefixed.add(prefix + s); + } + return prefixed; + } + + public static String camelcase(String name) { + if (name == null || name.isEmpty()) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (String part : name.split("[ _]")) { + sb.append(Character.toUpperCase(part.charAt(0))); + sb.append(part.substring(1).toLowerCase()); + } + return sb.toString(); + } + + /** + * Escapes formatting by "denormalizing" back to using & instead of §. + * @param formatString A formatstring (formerly normalized). + * @return A non-format string using & instead of §. + * @since 1.10 + */ + public static String escape(String formatString) { + String escaped = normalize(formatString); + escaped = escaped + .replaceAll("\u00a7", "&"); + return escaped; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java new file mode 100644 index 000000000..400e4aa32 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java @@ -0,0 +1,375 @@ +package dk.lockfuglsang.minecraft.util; + +import dk.lockfuglsang.minecraft.nbt.NBTUtil; +import dk.lockfuglsang.minecraft.reflection.ReflectionUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Conversion to ItemStack from strings. + */ +public enum ItemStackUtil { + ; + private static final Pattern ITEM_AMOUNT_PATTERN = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?(?[0-9A-Z_]+)(:(?[0-9]+))?:(?[0-9]+)\\s*(?\\{.*\\})?"); + private static final Pattern ITEM_PATTERN = Pattern.compile("(?[0-9A-Z_]+)(:(?[0-9]+))?\\s*(?\\{.*\\})?"); + + public static List createItemsWithProbabilty(List items) { + List itemProbs = new ArrayList<>(); + for (String reward : items) { + Matcher m = ITEM_AMOUNT_PATTERN.matcher(reward); + if (m.matches()) { + double p = m.group("prob") != null ? Double.parseDouble(m.group("prob")) : 1; + short sub = m.group("sub") != null ? (short) Integer.parseInt(m.group("sub"), 10) : 0; + Material type = getItemType(m, sub); + int amount = Integer.parseInt(m.group("amount"), 10); + ItemStack itemStack = new ItemStack(type, amount, sub < type.getMaxDurability() ? sub : 0); + itemStack = NBTUtil.addNBTTag(itemStack, m.group("meta")); + itemProbs.add(new ItemProbability(p, itemStack)); + } else { + throw new IllegalArgumentException("Unknown item: '" + reward + "' in '" + items + "'"); + } + } + return itemProbs; + } + + private static Material getItemType(Matcher m, short dataValue) { + String id = m.group("id"); + if (id != null && id.matches("[0-9]*")) { + throw new IllegalArgumentException("Bukkit 1.13+ doesn't support Item-IDs, please use Material names instead"); + } else if (id != null) { + Material type = Material.matchMaterial(id); + if (type == null) { + try { + Material legacyType = Material.matchMaterial(id, true); + BlockData blockData = Bukkit.getServer().getUnsafe().fromLegacy(legacyType, (byte) (dataValue & 0x0f)); + type = blockData != null && blockData.getMaterial() != null && blockData.getMaterial() != Material.AIR + ? blockData.getMaterial() + : legacyType; + } catch (NullPointerException e) { + throw new IllegalArgumentException("Bukkit 1.13 does not know the material " + id + "!", e); + } + } + if (type != null) { + return type; + } + } + return Material.BARRIER; + } + + public static List createItemList(List items) { + List itemList = new ArrayList<>(); + for (String reward : items) { + if (reward != null && !reward.isEmpty()) { + itemList.add(createItemStackAmount(reward)); + } + } + return itemList; + } + + private static ItemStack createItemStackAmount(String reward) { + if (reward == null || reward.isEmpty()) { + return null; + } + Matcher m = ITEM_AMOUNT_PATTERN.matcher(reward); + if (m.matches()) { + short sub = m.group("sub") != null ? (short) Integer.parseInt(m.group("sub"), 10) : 0; + Material type = getItemType(m, sub); + int amount = Integer.parseInt(m.group("amount"), 10); + ItemStack itemStack = new ItemStack(type, amount, sub < type.getMaxDurability() ? sub : 0); + if (m.group("meta") != null) { + itemStack = NBTUtil.addNBTTag(itemStack, m.group("meta")); + } + return itemStack; + } else { + throw new IllegalArgumentException("Unknown item: '" + reward + "'"); + } + } + + public static ItemStack[] createItemArray(List items) { + return items != null ? items.toArray(new ItemStack[items.size()]) : new ItemStack[0]; + } + + public static ItemStack createItemStack(String displayItem) { + return createItemStack(displayItem, null, null); + } + + public static ItemStack createItemStackSkull(String texture, String name, String description) { + ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1); + String metaStr = String.format("{display:{Name:\"%s\"},SkullOwner:{Id:\"%s\",Properties:{textures:[{Value:\"%s\"}]}}}", name, createUniqueId(texture, name, description), texture); + itemStack = NBTUtil.addNBTTag(itemStack, metaStr); + ItemMeta meta = itemStack.getItemMeta(); + if (meta != null) { + if (name != null) { + meta.setDisplayName(FormatUtil.normalize(name)); + } + List lore = new ArrayList<>(); + if (description != null) { + lore.addAll(FormatUtil.wordWrap(FormatUtil.normalize(description), 30, 30)); + } + meta.setLore(lore); + itemStack.setItemMeta(meta); + } + return itemStack; + } + + public static UUID createUniqueId(String texture, String name, String description) { + return new UUID(texture.hashCode(), ("" + name + description).hashCode()); + } + + public static ItemStack createItemStack(String displayItem, String name, String description) { + Material type = Material.DIRT; + short sub = 0; + String metaStr = null; + if (displayItem != null) { + Matcher matcher = ITEM_PATTERN.matcher(displayItem); + if (matcher.matches()) { + sub = matcher.group("sub") != null ? (short) Integer.parseInt(matcher.group("sub"), 10) : 0; + type = getItemType(matcher, sub); + metaStr = matcher.group("meta"); + } + } + if (type == null) { + Bukkit.getLogger().warning("Invalid material " + displayItem + " supplied!"); + type = Material.BARRIER; + } + ItemStack itemStack = new ItemStack(type, 1, sub < type.getMaxDurability() ? sub : 0); + ItemMeta meta = itemStack.getItemMeta(); + if (meta != null) { + if (name != null) { + meta.setDisplayName(FormatUtil.normalize(name)); + } + List lore = new ArrayList<>(); + if (description != null) { + lore.addAll(FormatUtil.wordWrap(FormatUtil.normalize(description), 30, 30)); + } + meta.setLore(lore); + itemStack.setItemMeta(meta); + } + itemStack = NBTUtil.addNBTTag(itemStack, metaStr); + return itemStack; + } + + public static List clone(List items) { + if (items == null) { + return null; + } + List copy = new ArrayList<>(); + for (ItemStack item : items) { + copy.add(item.clone()); + } + return copy; + } + + public static boolean isValidInventoryItem(ItemStack itemStack) { + Inventory inventory = Bukkit.createInventory(null, 9); + inventory.setItem(0, itemStack); + return inventory.getItem(0) != null && inventory.getItem(0).getItemMeta() != null && inventory.getItem(0).getData() != null && inventory.getItem(0).getData().toItemStack() != null; + } + + public static Builder builder(ItemStack stack) { + return new Builder(stack); + } + + public static String asString(ItemStack item) { + return item.getType().name() + (item.getDurability() != 0 ? ":" + item.getDurability() : "") + ":" + item.getAmount(); + } + + public static String asShortString(List items) { + List shorts = new ArrayList<>(); + for (ItemStack item : items) { + shorts.add(asShortString(item)); + } + return "[" + FormatUtil.join(shorts, ", ") + "]"; + } + + public static String asShortString(ItemStack item) { + if (item == null) { + return ""; + } + return item.getAmount() > 1 + ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), getItemName(item)) + : tr("\u00a77{0}", getItemName(item)); + } + + public static ItemStack asDisplayItem(ItemStack item) { + ItemStack copy = new ItemStack(item); + ItemMeta itemMeta = copy.getItemMeta(); + // Hide all enchants (if possible). + try { + Class aClass = Class.forName("org.bukkit.inventory.ItemFlag"); + Object allValues = ReflectionUtil.execStatic(aClass, "values"); + ReflectionUtil.exec(itemMeta, "addItemFlags", allValues); + } catch (ClassNotFoundException e) { + // Ignore - only available for 1.9 and above + } + copy.setItemMeta(itemMeta); + return copy; + } + + public static String getItemName(ItemStack stack) { + if (stack != null) { + if (stack.getItemMeta() != null && stack.getItemMeta().getDisplayName() != null && !stack.getItemMeta().getDisplayName().trim().isEmpty()) { + return stack.getItemMeta().getDisplayName(); + } + /* + Vault isn't 1.13 compatible (yet) + ItemInfo itemInfo = Items.itemByStack(stack); + return itemInfo != null ? itemInfo.getName() : "" + stack.getType(); + */ + return tr(FormatUtil.camelcase(stack.getType().name()).replaceAll("([A-Z])", " $1").trim()); + } + return null; + } + + /** + * Builder for ItemStack + */ + public static class Builder { + private ItemStack itemStack; + + public Builder(ItemStack itemStack) { + this.itemStack = itemStack != null ? itemStack.clone() : new ItemStack(Material.AIR); + } + + public Builder type(Material mat) { + itemStack.setType(mat); + return this; + } + + public Builder subType(int subType) { + itemStack.setDurability((short) subType); + return this; + } + + public Builder amount(int amount) { + itemStack.setAmount(amount); + return this; + } + + public Builder displayName(String name) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setDisplayName(name); + itemStack.setItemMeta(itemMeta); + return this; + } + + public Builder enchant(Enchantment enchantment, int level) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.addEnchant(enchantment, level, false); + itemStack.setItemMeta(itemMeta); + return this; + } + + public Builder select(boolean b) { + return b ? select() : deselect(); + } + + public Builder select() { + return enchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1).add(ItemFlag.HIDE_ENCHANTS); + } + + public Builder deselect() { + return remove(Enchantment.PROTECTION_ENVIRONMENTAL).remove(ItemFlag.HIDE_ENCHANTS); + } + + public Builder add(ItemFlag... flags) { + ItemMeta meta = itemStack.getItemMeta(); + meta.addItemFlags(flags); + itemStack.setItemMeta(meta); + return this; + } + + public Builder remove(ItemFlag... flags) { + ItemMeta meta = itemStack.getItemMeta(); + meta.removeItemFlags(flags); + itemStack.setItemMeta(meta); + return this; + } + + private Builder remove(Enchantment enchantment) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.removeEnchant(enchantment); + itemStack.setItemMeta(itemMeta); + return this; + } + + public Builder lore(String lore) { + return lore(Collections.singletonList(FormatUtil.normalize(lore))); + } + + public Builder lore(List lore) { + ItemMeta itemMeta = itemStack.getItemMeta(); + if (itemMeta != null) { + if (itemMeta.getLore() == null) { + itemMeta.setLore(lore); + } else { + List oldLore = itemMeta.getLore(); + oldLore.addAll(lore); + itemMeta.setLore(oldLore); + } + itemStack.setItemMeta(itemMeta); + } + return this; + } + + public ItemStack build() { + return itemStack; + } + } + + public static class ItemProbability { + private final double probability; + private final ItemStack item; + + public ItemProbability(double probability, ItemStack item) { + this.probability = probability; + this.item = item; + } + + public double getProbability() { + return probability; + } + + public ItemStack getItem() { + return item; + } + + @Override + public String toString() { + return "ItemProbability{" + + "probability=" + probability + + ", item=" + item + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ItemProbability that = (ItemProbability) o; + return Double.compare(that.probability, probability) == 0 && + Objects.equals(asString(item), asString(that.item)); + } + + @Override + public int hashCode() { + return Objects.hash(probability, item); + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/LocationUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/LocationUtil.java new file mode 100644 index 000000000..4a0ada285 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/LocationUtil.java @@ -0,0 +1,74 @@ +package dk.lockfuglsang.minecraft.util; + +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Static convenience class for location methods. + */ +public enum LocationUtil { + ; + private static final Pattern LOCATION_PATTERN = Pattern.compile("((?[^:/]+)[:/])?(?[\\-0-9\\.]+),(?[\\-0-9\\.]+),(?[\\-0-9\\.]+)(:(?[\\-0-9\\.]+):(?[\\-0-9\\.]+))?"); + + public static String asString(Location loc) { + if (loc == null) { + return null; + } + String s = ""; + if (loc.getWorld() != null && loc.getWorld().getName() != null) { + s += loc.getWorld().getName() + ":"; + } + s += String.format(Locale.ENGLISH, "%.2f,%.2f,%.2f", loc.getX(), loc.getY(), loc.getZ()); + if (loc.getYaw() != 0f || loc.getPitch() != 0f) { + s += String.format(Locale.ENGLISH, ":%.2f:%.2f", loc.getYaw(), loc.getPitch()); + } + return s; + } + + /** + * Convenience method for when a location is needed as a yml key. + */ + public static String asKey(Location loc) { + return asString(loc).replaceAll(":", "/").replaceAll("\\.", "_"); + } + + public static Location fromString(String locString) { + if (locString == null || locString.isEmpty()) { + return null; + } + Matcher m = LOCATION_PATTERN.matcher(locString.replaceAll("_", "\\.")); + if (m.matches()) { + return new Location(Bukkit.getWorld(m.group("world")), + Double.parseDouble(m.group("x")), + Double.parseDouble(m.group("y")), + Double.parseDouble(m.group("z")), + m.group("yaw") != null ? Float.parseFloat(m.group("yaw")) : 0, + m.group("pitch") != null ? Float.parseFloat(m.group("pitch")) : 0 + ); + } + return null; + } + + public static Location centerOnBlock(Location loc) { + if (loc == null) { + return null; + } + return new Location(loc.getWorld(), + loc.getBlockX() + 0.5, loc.getBlockY() + 0.1, loc.getBlockZ() + 0.5, + loc.getYaw(), loc.getPitch()); + } + + public static Location centerInBlock(Location loc) { + if (loc == null) { + return null; + } + return new Location(loc.getWorld(), + loc.getBlockX() + 0.5, loc.getBlockY() + 0.5, loc.getBlockZ() + 0.5, + loc.getYaw(), loc.getPitch()); + } + +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java new file mode 100644 index 000000000..639cb453f --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java @@ -0,0 +1,92 @@ +package dk.lockfuglsang.minecraft.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +public enum TimeUtil { + ; + private static final Pattern TIME_PATTERN = Pattern.compile("((?[0-9]+)d)?\\s*((?[0-9]+)h)?\\s*((?[0-9]+)m)?\\s*((?[0-9]+)s)?\\s*((?[0-9]+)ms)?"); + private static final long SEC = 1000; + private static final long MIN = 60 * SEC; + private static final long HOUR = 60 * MIN; + private static final long DAYS = 24 * HOUR; + + public static long stringAsMillis(String s) { + Matcher m = TIME_PATTERN.matcher(s); + if (m.matches()) { + long t = 0; + if (m.group("d") != null) { + t += Integer.parseInt(m.group("d"), 10) * DAYS; + } + if (m.group("h") != null) { + t += Integer.parseInt(m.group("h"), 10) * HOUR; + } + if (m.group("m") != null) { + t += Integer.parseInt(m.group("m"), 10) * MIN; + } + if (m.group("s") != null) { + t += Integer.parseInt(m.group("s"), 10) * SEC; + } + if (m.group("ms") != null) { + t += Integer.parseInt(m.group("ms"), 10); + } + return t; + } + return -1; + } + + public static String millisAsString(long millis) { + long d = millis / DAYS; + long h = (millis % DAYS) / HOUR; + long m = (millis % HOUR) / MIN; + long s = (millis % MIN) / SEC; + String str = ""; + if (d > 0) { + str += " " + d + tr("d"); + } + if (h > 0) { + str += " " + h + tr("h"); + } + if (m > 0) { + str += " " + m + tr("m"); + } + if (s > 0 || str.isEmpty()) { + str += " " + s + tr("s"); + } + return str.trim(); + } + + public static String millisAsShort(long millis) { + long m = millis / MIN; + long s = (millis % MIN) / SEC; + long ms = millis % SEC; + return String.format(tr("{0,number,0}:{1,number,00}.{2,number,000}", m, s, ms)); + } + + public static String ticksAsString(int ticks) { + return millisAsString(ticks * 50); + } + + public static long secondsAsTicks(int secs) { + // 20 ticks per second = 50 ms per tick + return (secs * 100) / 5; + } + + public static long secondsAsMillis(long timeout) { + return timeout * 1000; + } + + public static int millisAsSeconds(long millis) { + return (int) Math.ceil(millis / 1000f); + } + + public static long millisAsTicks(long ms) { + return ms / 50; + } + + public static long ticksAsMillis(int ticks) { + return ticks * 50; + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java new file mode 100644 index 000000000..20a988bb6 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java @@ -0,0 +1,32 @@ +package dk.lockfuglsang.minecraft.util; + +import java.util.UUID; +import java.util.logging.Logger; + +/** + * Utility for handling UUIDs. + */ +public enum UUIDUtil {; + private static final Logger log = Logger.getLogger(UUIDUtil.class.getName()); + public static UUID fromString(String id) { + if (id == null || id.isEmpty()) { + return null; + } + if (id.length() == 32) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } + try { + return UUID.fromString(id); + } catch (IllegalArgumentException e) { + // ignore, do logging elsewhere + } + return null; + } + + public static String asString(UUID uuid) { + if (uuid == null) { + return ""; + } + return uuid.toString(); + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/VersionUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/VersionUtil.java new file mode 100644 index 000000000..e04f35d93 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/VersionUtil.java @@ -0,0 +1,75 @@ +package dk.lockfuglsang.minecraft.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility methods for versions + * @since v1.15 + */ +public enum VersionUtil {; + private static final Pattern VERSION_PATTERN = Pattern.compile("v?(?[0-9]+)[\\._](?[0-9]+)(?:[\\._](?[0-9]+))?(?.*)"); + public static Version getVersion(String versionString) { + Matcher m = VERSION_PATTERN.matcher(versionString); + if (m.matches()) { + int major = Integer.parseInt(m.group("major")); + int minor = m.group("minor") != null ? Integer.parseInt(m.group("minor")) : 0; + int micro = m.group("micro") != null ? Integer.parseInt(m.group("micro")) : 0; + return new Version(major, minor, micro, m.group("sub")); + } + return new Version(0,0,0, null); + } + + public static class Version { + private int major; + private int minor; + private int micro; + private String sub; + + public Version(int major, int minor, int micro, String sub) { + this.major = major; + this.minor = minor; + this.micro = micro; + this.sub = sub; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getMicro() { + return micro; + } + + public String getSub() { + return sub; + } + + public boolean isGTE(String version) { + Version other = getVersion(version); + return major > other.major || + major >= other.major && minor > other.minor || + major >= other.major && minor >= other.minor && micro >= other.micro; + } + + public boolean isLT(String version) { + Version other = getVersion(version); + return major < other.major || + major <= other.major && minor < other.minor || + major <= other.major && minor <= other.minor && micro < other.micro; + } + + @Override + public String toString() { + return "v" + major + "." + minor + "." + micro + (sub != null ? "-" + sub : ""); + } + + public String toReleaseString() { + return "v" + major + "_" + minor; + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md new file mode 100644 index 000000000..48af7118e --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md @@ -0,0 +1,13 @@ +# YmlConfiguration + +These classes enables plugins to preserve comments when handling `FileConfiguration` objects in Bukkit. + +## Usage + +``` + FileConfiguration config = new YmlConfiguration(); + config.load(file); + // Do FileConfiguration stuff + + config.save(file); +``` \ No newline at end of file diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java new file mode 100644 index 000000000..d5d2df11a --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java @@ -0,0 +1,215 @@ +package dk.lockfuglsang.minecraft.yml; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A very simplistic yml parser, that only do the following: + *
    + *
  1. Keep track of indentation-levels and sections.
  2. + *
  3. Handle comments.
  4. + *
+ */ +public class YmlCommentParser { + private static final Logger log = Logger.getLogger(YmlCommentParser.class.getName()); + private static final Pattern SECTION_PATTERN = Pattern.compile("^(?\\s*)(?[^ \\-][^:]*):(?[^#]*)?(?#.*)?"); + private static final Pattern COMMENT_PATTERN = Pattern.compile("^(?\\s*)(?#.*)"); + private Map commentMap = new HashMap<>(); + + public Map getCommentMap() { + return Collections.unmodifiableMap(commentMap); + } + + + public void addComment(String path, String comment) { + commentMap.put(path, comment); + } + + public void addComments(Map comments) { + commentMap.putAll(comments); + } + + private void readLines(BufferedReader rdr) throws IOException { + int indentLevel = 0; + Deque
sections = new ArrayDeque<>(); + StringBuilder comments = new StringBuilder(); + String baseKey = null; + sections.add(new Section(null, 0)); + String line; + int lineNum = 1; + boolean isFirstAfterSection = true; + while ((line = rdr.readLine()) != null) { + Matcher commentM = COMMENT_PATTERN.matcher(line); + Matcher sectionM = SECTION_PATTERN.matcher(line); + if (commentM.matches()) { + comments.append(commentM.group("comment") + "\n"); + } else if (sectionM.matches()) { + String comment = sectionM.group("comment"); + if (comment != null && !comment.trim().isEmpty()) { + comments.append(comment + "\n"); + } + String name = sectionM.group("name").trim(); + String value = sectionM.group("value"); + String indent = sectionM.group("indent"); + if (isFirstAfterSection && indent.length() > indentLevel) { + indentLevel = indent.length(); + sections.peek().setIndentation(indentLevel); + } else if (indent.length() < indentLevel) { + while (indent.length() < indentLevel && !sections.isEmpty()) { + sections.pop(); + baseKey = sections.peek().getPath(); + indentLevel = sections.peek().getIndentation(); + isFirstAfterSection = false; + } + } + String path = getPath(baseKey, name); + if (value != null && !value.trim().isEmpty()) { + // Scalar with value + addComments(path, comments); + if (!isFirstAfterSection && indent.length() > indentLevel) { + log.warning("line " + lineNum + ": mixed indentation, expected " + indentLevel + " but got " + indent.length()); + } + isFirstAfterSection = false; + } else if (indent.length() >= indentLevel) { + indentLevel = indent.length(); + sections.push(createSection(path, indentLevel, comments)); + baseKey = path; + isFirstAfterSection = true; + } + } else if (line.trim().isEmpty()) { + // Currently gathered comments are reset - they are "floating", decoupled from sections. + comments.setLength(0); + comments.trimToSize(); + } + lineNum++; + } + } + + private String getPath(String baseKey, String name) { + return baseKey != null ? baseKey + "." + name : name; + } + + private Section createSection(String path, int indentLevel, StringBuilder comments) { + Section section = new Section(path, indentLevel); + addComments(path, comments); + return section; + } + + private void addComments(String path, StringBuilder comments) { + if (comments.length() > 0) { + commentMap.put(path, comments.toString()); + comments.setLength(0); + comments.trimToSize(); + } + } + + public String getComment(String path) { + return commentMap.get(path); + } + + /** + * Merges the comments into the "pure" yml. + * @param ymlPure A YML data-tree, without comments. + * @return A YML data-tree including comments. + */ + public String mergeComments(String ymlPure) { + StringBuilder sb = new StringBuilder(); + boolean isFirstAfterSection = true; + Deque
sections = new ArrayDeque<>(); + sections.push(new Section(null, 0)); + int indentLevel = 0; + String baseKey = null; + int lineNum = 1; + // First section shares comments with the header - so ignore that one + boolean isHeader = true; + for (String line : ymlPure.split("\n")) { + // Skip header + Matcher commentM = COMMENT_PATTERN.matcher(line); + if (isHeader && (commentM.matches() || line.trim().isEmpty())) { + continue; // Skip header + } + isHeader = false; + Matcher sectionM = SECTION_PATTERN.matcher(line); + if (sectionM.matches()) { + String name = sectionM.group("name").trim(); + String value = sectionM.group("value"); + String indent = sectionM.group("indent"); + if (isFirstAfterSection && indent.length() > indentLevel) { + indentLevel = indent.length(); + sections.peek().setIndentation(indentLevel); + } else if (indent.length() < indentLevel) { + while (indent.length() < indentLevel && !sections.isEmpty()) { + sections.pop(); + baseKey = sections.peek().getPath(); + indentLevel = sections.peek().getIndentation(); + isFirstAfterSection = false; + } + } + String path = getPath(baseKey, name); + String comment = getComment(path); + if (comment != null) { + sb.append((lineNum > 1 ? "\n" : "") + comment + .replaceAll("^#", Matcher.quoteReplacement(indent + "#")) + .replaceAll("\n#", Matcher.quoteReplacement("\n" + indent + "#"))); + } + if (value != null && !value.trim().isEmpty()) { + // Scalar with value + isFirstAfterSection = false; + } else if (indent.length() >= indentLevel) { + indentLevel = indent.length(); + sections.push(new Section(path, indentLevel)); + baseKey = path; + isFirstAfterSection = true; + } + } + lineNum++; + sb.append(line + "\n"); + } + return sb.toString().replaceAll("\r\n", "\n").replaceAll("\n\r", "\n").replaceAll("\n", "\r\n"); + } + + public void load(Reader reader) throws IOException { + readLines(new BufferedReader(reader)); + } + + public void loadFromString(String contents) { + try { + readLines(new BufferedReader(new StringReader(contents))); + } catch (IOException e) { + throw new IllegalStateException("Unable to read from string", e); + } + } + + + private static class Section { + private int indentation; + private final String path; + + private Section(String name, int indentation) { + this.indentation = indentation; + this.path = name; + } + + public int getIndentation() { + return indentation; + } + + public String getPath() { + return path; + } + + public void setIndentation(int indentLevel) { + indentation = indentLevel; + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java new file mode 100644 index 000000000..1510dcf8b --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java @@ -0,0 +1,50 @@ +package dk.lockfuglsang.minecraft.yml; + +import com.google.common.collect.Streams; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * A YamlConfiguration that supports comments + *

+ * Note: This includes a VERY SIMPLISTIC Yaml-parser, which sole purpose is to detect and store comments. + */ +@Deprecated(forRemoval = true) // Bukkit YamlConfiguration now preserves comments by default +public class YmlConfiguration extends YamlConfiguration { + + @Deprecated(forRemoval = true) // Use #getComments and #getInlineComments instead + public String getComment(String key) { + String comment = Streams.concat(super.getComments(key).stream(), + super.getInlineComments(key).stream()).collect(Collectors.joining(System.lineSeparator())); + if (comment.isEmpty()) { + return null; + } + return comment.replaceAll("^# ?", "").replaceAll("\n# ?", ""); + } + + @Deprecated(forRemoval = true) // Use #getComments and #getInlineComments instead + public Map getComments() { + Map comments = new LinkedHashMap<>(); + for (String key : getKeys(true)) { + String comment = getComment(key); + if (comment != null) { + comments.put(key, comment); + } + } + return comments; + } + + @Deprecated(forRemoval = true) // Use #setComments and #setInlineComments instead + public void addComment(String path, String comment) { + var comments = new ArrayList<>(super.getComments(path)); + comments.add(comment); + super.setComments(path, comments); + } + + @Deprecated(forRemoval = true) // Use #setComments and #setInlineComments instead + public void addComments(Map comments) { + comments.forEach(this::addComment); + } +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java new file mode 100644 index 000000000..44d9f5700 --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java @@ -0,0 +1,87 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandSender; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + +import java.util.Arrays; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +public class BaseCommandExecutorTest { + StringBuffer messages = new StringBuffer(); + private static BaseCommandExecutor mycmd; + + @BeforeClass + public static void setUp() { + mycmd = new BaseCommandExecutor("mycmd", "myplugin.perm.mycmd", "main myplugin command"); + mycmd.add(new AbstractCommand("hello|h", "myplugin.perm.hello", "say hello to the player") { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + sender.sendMessage(new String[]{ + "Hello! and welcome " + sender.getName(), + "I was called with : " + alias, + "I had " + args.length + " arguments: " + Arrays.asList(args) + }); + return true; + } + }); + } + + @Test + public void testNoPermissions() { + CommandSender sender = createCommandSender(); + mycmd.onCommand(sender, null, "mycmd", new String[]{"mycmd", "h", "your", "momma"}); + assertThat(getMessages(), is("§eYou do not have access (§4myplugin.perm.mycmd§e)\n" + + "§7Usage: §3mycmd§a [command|help]§7 - §emain myplugin command")); + } + + private String getMessages() { + return messages.toString().trim(); + } + + @Test + public void testBasic() { + CommandSender sender = createCommandSender(); + addPerm(sender, "myplugin.perm.mycmd"); + addPerm(sender, "myplugin.perm.hello"); + mycmd.onCommand(sender, null, "mycmd", new String[]{"h", "your", "momma"}); + assertThat(getMessages(), is("Hello! and welcome null\nI was called with : h\nI had 2 arguments: [your, momma]")); + } + + private void addPerm(CommandSender sender, String s) { + when(sender.hasPermission(ArgumentMatchers.isA(String.class))).thenReturn(true); + } + + private void addOp(CommandSender sender) { + when(sender.isOp()).thenReturn(true); + } + + private CommandSender createCommandSender() { + CommandSender mock = Mockito.mock(CommandSender.class); + Answer answer = invocationOnMock -> { + for (Object o : invocationOnMock.getArguments()) { + if (o != null && o.getClass().isArray()) { + for (Object o2 : (Object[]) o) { + messages.append("" + o2 + "\n"); + } + } else { + messages.append("" + o + "\n"); + } + } + return null; + }; + doAnswer(answer).when(mock).sendMessage(anyString()); + doAnswer(answer).when(mock).sendMessage(Matchers.any()); + return mock; + } +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java new file mode 100644 index 000000000..c764f08dd --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java @@ -0,0 +1,178 @@ +package dk.lockfuglsang.minecraft.command; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.hamcrest.Matchers; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.*; + +public class CompositeCommandTest { + private static UUID ownerUUID = UUID.randomUUID(); + private static UUID adminUUID = UUID.randomUUID(); + private static UUID modUUID = UUID.randomUUID(); + private static BaseCommandExecutor executor; + + @BeforeClass + public static void setupAll() { + executor = new BaseCommandExecutor("plugin", "plugin", null, "does stuff", ownerUUID); + CompositeCommand sut = new CompositeCommand("admin", "admin.admin.superadmin", null, "super important admin command", adminUUID) { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + sender.sendMessage("executed admin"); + return super.execute(sender, alias, data, args); + } + }; + sut.add(new AbstractCommand("sub", "perm.sub", "some sub-command") { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + sender.sendMessage("from sub"); + return false; + } + }); + sut.add(new AbstractCommand("sub2", "perm.sub2", "some other sub-command", "yay", null, modUUID) { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + sender.sendMessage("from sub2"); + return false; + } + }); + executor.add(sut); + } + + @Test + public void NoPermOnBase() { + // Arrange + Player player = mock(Player.class); + when(player.hasPermission(anyString())).thenReturn(false); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + verify(player).sendMessage("§eYou do not have access (§4plugin§e)"); + } + + @Test + public void PermOnBase() { + // Arrange + Player player = mock(Player.class); + when(player.hasPermission(anyString())).thenAnswer((Answer) invocationOnMock -> + invocationOnMock.getArguments()[0] == "plugin"); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + verify(player).sendMessage("§eYou do not have access (§4admin.admin.superadmin§e)"); + } + + @Test + public void PermOnAdmin() { + // Arrange + Player player = mock(Player.class); + final List messages = recordMessages(player); + when(player.hasPermission(anyString())).thenAnswer((Answer) invocationOnMock -> + invocationOnMock.getArguments()[0] == "plugin" + || invocationOnMock.getArguments()[0] == "admin.admin.superadmin" + ); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + verify(player).sendMessage("executed admin"); + assertThat(messages, Matchers.contains(new String[]{"executed admin", "§eYou do not have access (§4perm.sub§e)"})); + } + + @Test + public void AllPerms() { + // Arrange + Player player = mock(Player.class); + when(player.hasPermission(anyString())).thenReturn(true); + final List messages = recordMessages(player); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + verify(player).sendMessage("executed admin"); + assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + } + + @Test + public void NoPerm_PermissionOverride() { + // Arrange + Player player = mock(Player.class); + when(player.getUniqueId()).thenReturn(ownerUUID); + final List messages = recordMessages(player); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + } + + @Test + public void NoPerm_PermissionSubOverride() { + // Arrange + Player player = mock(Player.class); + when(player.getUniqueId()).thenReturn(adminUUID); + final List messages = recordMessages(player); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + assertThat(messages, Matchers.contains(new String[]{"§eYou do not have access (§4plugin§e)"})); + } + + @Test + public void BasePerm_PermissionCompositeOverride() { + // Arrange + Player player = mock(Player.class); + when(player.getUniqueId()).thenReturn(adminUUID); + when(player.hasPermission(anyString())).thenAnswer((Answer) invocationOnMock -> + invocationOnMock.getArguments()[0] == "plugin" + ); + final List messages = recordMessages(player); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); + + assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + } + + @Test + public void BasePerm_PermissionAbstractCommandOverride() { + // Arrange + Player player = mock(Player.class); + when(player.getUniqueId()).thenReturn(modUUID); + when(player.hasPermission(anyString())).thenAnswer((Answer) invocationOnMock -> + invocationOnMock.getArguments()[0] == "plugin" + || invocationOnMock.getArguments()[0] == "admin.admin.superadmin" + ); + final List messages = recordMessages(player); + + // Act + executor.onCommand(player, null, "alias", new String[]{"admin", "sub2"}); + + assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub2"})); + } + + private List recordMessages(Player player) { + final List messages = new ArrayList<>(); + Answer voidAnswer = i -> { + messages.add(String.join(" ", Arrays.asList(i.getArguments()).toArray(new String[0]))); + return null; + }; + doAnswer(voidAnswer).when(player).sendMessage(anyString()); + return messages; + } + +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java new file mode 100644 index 000000000..32dcfcb5c --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java @@ -0,0 +1,55 @@ +package dk.lockfuglsang.minecraft.command; + +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class PluginYamlCommandVisitorTest { + @Test + public void writeToSimple() throws Exception { + PluginYamlCommandVisitor visitor = new PluginYamlCommandVisitor(); + BaseCommandExecutor cmd = new BaseCommandExecutor("cmd|c", "plugin.cmd", "player", "some description"); + cmd.add(new CompositeCommand("sub|s", "plugin.sub", "some sub description")); + cmd.add(new CompositeCommand("other", "plugin.cmd.other", "some other command")); + BaseCommandExecutor cmd2 = new BaseCommandExecutor("adm|a", "plugin.adm", "hey jude!"); + cmd2.add(new CompositeCommand("subs|ss", "plugin.sub", "some other sub")); + cmd2.add(new CompositeCommand("t2", "plugin.cmdtest", "?optional mandatory", "test")); + String expected = String.join(System.lineSeparator(), Files.readAllLines( + Paths.get(getClass().getClassLoader().getResource("yml/pluginyml_simple.yml").toURI()))); + + cmd.accept(visitor); + cmd2.accept(visitor); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(baos); + visitor.writeTo(out); + assertThat(baos.toString(), is(expected)); + } + + @Test + public void writeToSimpleFeatureMap() throws Exception { + PluginYamlCommandVisitor visitor = new PluginYamlCommandVisitor(); + BaseCommandExecutor cmd = new BaseCommandExecutor("cmd|c", "plugin.cmd", "some description"); + CompositeCommand sub = new CompositeCommand("sub|s", "plugin.sub", "some sub description"); + cmd.add(sub); + sub.addFeaturePermission("plugin.feature.a", "enables A"); + sub.addFeaturePermission("plugin.feature.b", "enables B"); + sub.addFeaturePermission("plugin.featuresub", "standalone feature"); + cmd.add(new CompositeCommand("other", "plugin.cmd.other", "some other command")); + String expected = String.join(System.lineSeparator(), Files.readAllLines( + Paths.get(getClass().getClassLoader().getResource("yml/pluginyml_featuremap.yml").toURI()))); + + cmd.accept(visitor); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(baos); + visitor.writeTo(out); + assertThat(baos.toString(), is(expected)); + } +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java new file mode 100644 index 000000000..d0697dffd --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java @@ -0,0 +1,23 @@ +package dk.lockfuglsang.minecraft.file; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +/** + * JUnit tests for FileUtil + */ +public class FileUtilTest { + @Test + public void testGetExtension() { + assertThat(FileUtil.getExtension("basename.ext"), is("ext")); + assertThat(FileUtil.getExtension("my file.with.dot.yml"), is("yml")); + } + + @Test + public void testBaseName() { + assertThat(FileUtil.getBasename("dir/something/filename.txt"), is("filename")); + assertThat(FileUtil.getBasename("dir\\something\\filename.txt"), is("filename")); + } +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java new file mode 100644 index 000000000..7a4a034cc --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java @@ -0,0 +1,38 @@ +package dk.lockfuglsang.minecraft.nbt; + +import com.google.gson.Gson; +import org.hamcrest.CoreMatchers; +import org.junit.Test; + +import java.io.StringReader; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Tests the NBTUtil + */ +public class NBTUtilTest { + + /** + * Tests that the JSONMap will return the proper syntax. + */ + @Test + public void testJSONMap() { + String jsonString = "{\"Potion\":\"minecraft:empty\",\"CustomPotionEffects\":[{\"Id\":1},{\"Id\":2}]}"; + Gson gson = new Gson(); + + Map map = (Map) gson.fromJson(new StringReader(jsonString), Map.class); + assertThat(map.get("Potion"), CoreMatchers.is("minecraft:empty")); + assertThat(map.get("CustomPotionEffects"), instanceOf(List.class)); + assertThat(((List)map.get("CustomPotionEffects")).get(0), instanceOf(Map.class)); + } + + @Test + public void testGetGraftBukkitVersion() { + assertThat("net.minecraft.server.v1_10_R1.NBTTagString".split("\\.")[3], is("v1_10_R1")); + } +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java new file mode 100644 index 000000000..d892a39ec --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java @@ -0,0 +1,135 @@ +package dk.lockfuglsang.minecraft.util; + +import dk.lockfuglsang.minecraft.nbt.NBTItemStackTagger; +import dk.lockfuglsang.minecraft.nbt.NBTUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.UnsafeValues; +import org.bukkit.inventory.ItemFactory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; +import org.mockito.stubbing.Answer; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +public class BukkitServerMock { + public static boolean useMetaData; + /** + * Stubbing data, allows for advanced stubbing behaviour for item-meta + */ + protected static Map> itemMetaMap = new HashMap<>(); + private static ItemFactory itemFactoryMock; + + public static Server setupServerMock() throws NoSuchFieldException, IllegalAccessException { + Field server = Bukkit.class.getDeclaredField("server"); + server.setAccessible(true); + Server serverMock = createServerMock(); + server.set(null, serverMock); + server.setAccessible(false); + + NBTUtil.setNBTItemStackTagger(new TestNBTItemStackTagger()); + return serverMock; + } + + public static Server createServerMock() { + Server serverMock = mock(Server.class); + itemFactoryMock = mock(ItemFactory.class); + + when(itemFactoryMock.isApplicable(any(ItemMeta.class), any(Material.class))) + .thenReturn(true); + + when(itemFactoryMock.equals(any(ItemMeta.class), any(ItemMeta.class))) + .thenAnswer((Answer) invocationOnMock -> { + // Better equals for mocks? + return Objects.equals("" + invocationOnMock.getArguments()[0], + "" + invocationOnMock.getArguments()[1]); + }); + + when(itemFactoryMock.getItemMeta(any(Material.class))) + .thenAnswer((Answer) invocationOnMock -> createItemMetaStub()); + + when(itemFactoryMock.asMetaFor(any(ItemMeta.class), any(Material.class))) + .thenAnswer((Answer) invocationOnMock -> invocationOnMock.getArguments()[0] != null + ? (ItemMeta) invocationOnMock.getArguments()[0] + : null); + when(itemFactoryMock.updateMaterial(any(ItemMeta.class), any(Material.class))) + .thenAnswer(i -> i.getArguments()[1]); + when(serverMock.getItemFactory()).thenReturn(itemFactoryMock); + + UnsafeValues unsafeMock = mock(UnsafeValues.class); + when(unsafeMock.fromLegacy(any(Material.class))).thenAnswer(a -> (Material) a.getArguments()[0]); + when(serverMock.getUnsafe()).thenReturn(unsafeMock); + return serverMock; + } + + public static ItemMeta createItemMetaStub() { + if (!useMetaData) { + return null; + } + ItemMeta meta = mock(ItemMeta.class, withSettings().extraInterfaces(Damageable.class)); + when(((Damageable)meta).getDamage()).thenReturn(0); + // Note: This is a HACKY way of stubbing, using mock and toString() + final Map metaData = new TreeMap<>(); + itemMetaMap.put(meta, metaData); + doAnswer((Answer) invocationOnMock -> { + String displayName = "" + invocationOnMock.getArguments()[0]; + if (displayName.isEmpty()) { + metaData.remove("displayName"); + } else { + metaData.put("displayName", "" + displayName); + } + return null; + }).when(meta).setDisplayName(any(String.class)); + doAnswer((Answer) invocationOnMock -> { + List lore = (List) invocationOnMock.getArguments()[0]; + if (lore != null && !lore.isEmpty()) { + metaData.put("lore", "" + lore); + } else { + metaData.remove("lore"); + } + return null; + }).when(meta).setLore(any(List.class)); + when(meta.toString()).thenAnswer((Answer) invocationOnMock -> "" + metaData); + when(meta.clone()).thenReturn(meta); // Don't clone it - we need to verify it + return meta; + } + + public static class TestNBTItemStackTagger implements NBTItemStackTagger { + @Override + public String getNBTTag(ItemStack itemStack) { + if (itemMetaMap.containsKey(itemStack.getItemMeta())) { + Map metaMap = itemMetaMap.get(itemStack.getItemMeta()); + if (metaMap.containsKey("nbt")) { + return metaMap.get("nbt"); + } + } + return ""; + } + + @Override + public ItemStack setNBTTag(ItemStack itemStack, String tag) { + ItemMeta itemMeta = itemStack.getItemMeta(); + if (itemMeta != null && itemMetaMap.containsKey(itemMeta)) { + Map metaMap = itemMetaMap.get(itemMeta); + metaMap.put("nbt", tag); + itemStack.setItemMeta(itemMeta); + } + return itemStack; + } + + @Override + public ItemStack addNBTTag(ItemStack itemStack, String tag) { + return setNBTTag(itemStack, tag); + } + } +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java new file mode 100644 index 000000000..ea3a79d7f --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java @@ -0,0 +1,67 @@ +package dk.lockfuglsang.minecraft.util; + +import org.junit.Test; + +import java.util.Arrays; + +import static dk.lockfuglsang.minecraft.util.FormatUtil.*; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class FormatUtilTest { + + @Test + public void testNormalize() throws Exception { + String input = "pre&00&11&22&33&44&55&66&77&88&99&aa&bb&cc&dd&ee&ff&ggpost"; + String expected = "pre§00§11§22§33§44§55§66§77§88§99§aa§bb§cc§dd§ee§ff&ggpost"; + assertThat(normalize(input), is(expected)); + } + + @Test + public void testWordWrap() throws Exception { + assertThat(wordWrap("asdadfasd asfasdfasd", 9, 12), + is(Arrays.asList( + "asdadfasd", "asfasdfasd"))); + assertThat(wordWrap("§1Hello §2World §3How are you", 4, 10), + is(Arrays.asList("§1Hello", "§2World §3How", "§3are you"))); + + assertThat(wordWrap("§1§2§3§4§5Hello §aWorld §1§2§3§4what happens", 10, 10), is(Arrays.asList( + "§1§2§3§4§5Hello §aWorld", "§1§2§3§4what happens" + ))); + + assertThat(wordWrap("this is a short story of a long sentence withaverylongword in the end", 14, 14), + is(Arrays.asList( + "this is a short", + "story of a long", + "sentence withaverylongword", + "in the end"))); + } + + @Test + public void testWordWrapStrict() { + assertThat(wordWrapStrict("this is a short story of a long sentence withaverylongword in the end", 14), + is(Arrays.asList( + "this is a", + "short story of", + "a long", + "sentence witha", + "verylongword", + "in the end"))); + + assertThat(wordWrapStrict("§1Hello §2World §3How are you", 10), + is(Arrays.asList("§1Hello", "§2World §3How", "§3are you"))); + } + + @Test + public void testCapitalize() throws Exception { + assertThat(camelcase("SAND_CASTLE"), is("SandCastle")); + assertThat(camelcase("SHEEP"), is("Sheep")); + assertThat(camelcase("ender chest"), is("EnderChest")); + } + + @Test + public void testEscape() throws Exception { + String text = "\u00a7eHello World\r\n\u00a7aThis is a \u00a7kmagic\r\n\u00a7lhej"; + assertThat(escape(text), is("&eHello World\r\n&aThis is a &kmagic\r\n&lhej")); + } +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java new file mode 100644 index 000000000..36a9e953f --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java @@ -0,0 +1,58 @@ +package dk.lockfuglsang.minecraft.util; + +import org.bukkit.inventory.ItemStack; +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; + +public class ItemStackMatcher extends TypeSafeDiagnosingMatcher { + + private final String expected; + + public ItemStackMatcher(ItemStack expected) { + this.expected = ItemStackUtil.asString(expected); + } + + @Override + protected boolean matchesSafely(ItemStack itemStack, Description description) { + String other = ItemStackUtil.asString(itemStack); + description.appendText(" was ").appendValue(other); + return expected.equals(other); + } + + @Override + public void describeTo(Description description) { + description.appendText(expected); + } + + @Factory + public static ItemStackMatcher itemStack(ItemStack expected) { + return new ItemStackMatcher(expected); + } + + @Factory + public static Matcher> itemStacks(Collection items) { + return itemStacks(items.toArray(new ItemStack[0])); + } + + @Factory + public static Matcher> itemStacks(ItemStack... items) { + List> matchers = new ArrayList(); + ItemStack[] arr$ = items; + int len$ = items.length; + + for(int i$ = 0; i$ < len$; ++i$) { + ItemStack item = arr$[i$]; + matchers.add(itemStack(item)); + } + + return contains((List)matchers); + } +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java new file mode 100644 index 000000000..f7936ddcb --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java @@ -0,0 +1,254 @@ +package dk.lockfuglsang.minecraft.util; + +import dk.lockfuglsang.minecraft.nbt.NBTItemStackTagger; +import dk.lockfuglsang.minecraft.nbt.NBTUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.inventory.ItemFactory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +import static dk.lockfuglsang.minecraft.util.ItemStackMatcher.itemStack; +import static dk.lockfuglsang.minecraft.util.ItemStackMatcher.itemStacks; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +/** + * Tests the utility methods of ItemStackUtil + */ +public class ItemStackUtilTest extends BukkitServerMock { + + @BeforeClass + public static void setUpClass() throws Exception { + Server server = setupServerMock(); + } + + @Before + public void setUp() { + useMetaData = false; + itemMetaMap.clear(); + } + + @Test(expected = NullPointerException.class) + public void createItemsWithProbabiltyNull() throws Exception { + ItemStackUtil.createItemsWithProbabilty(null); + } + + @Test(expected = IllegalArgumentException.class) + public void createItemsWithProbabiltyInvalid() throws Exception { + ItemStackUtil.createItemsWithProbabilty(Arrays.asList("{p:0.9}10:1")); + } + + @Test + public void createItemsWithProbabilty1() throws Exception { + List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList("{p=0.9}LAVA_BUCKET:1")); + List expected = Arrays.asList( + new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1)) + ); + assertThat(actual, notNullValue()); + assertThat(actual, is(expected)); + } + + @Test + public void createItemsWithProbabiltyN() throws Exception { + List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList( + "{p=0.9}LAVA_BUCKET:1", + "{p=0.2}STONE:2:3", + "{p=0.3}NETHER_BRICK_FENCE:2" + )); + List expected = Arrays.asList( + new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1)), + new ItemStackUtil.ItemProbability(0.2, new ItemStack(Material.STONE, 3, (short) 2)), + new ItemStackUtil.ItemProbability(0.3, new ItemStack(Material.NETHER_BRICK_FENCE, 2)) + ); + assertThat(actual, notNullValue()); + assertThat(actual, is(expected)); + } + + @Test + public void createItemsWithProbabiltyWithNBTTag() throws Exception { + useMetaData = true; + List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList( + "{p=0.9}LAVA_BUCKET:1{Potion:Death}", + "{p=0.2}STONE:2:3 {MyLittle:\"Pony\"}", + "{p=0.3}NETHER_BRICK_FENCE:2\t {meta:{nested:{data:[{},{}]}}}" + )); + List expected = Arrays.asList( + new ItemStackUtil.ItemProbability(0.9, NBTUtil.setNBTTag( + new ItemStack(Material.LAVA_BUCKET, 1), + "{Potion:Death}")), + new ItemStackUtil.ItemProbability(0.2, NBTUtil.setNBTTag( + new ItemStack(Material.STONE, 3, (short) 2), + "{MyLittle:\"Pony\"}")), + new ItemStackUtil.ItemProbability(0.3, NBTUtil.setNBTTag( + new ItemStack(Material.NETHER_BRICK_FENCE, 2), + "{meta:{nested:{data:[{},{}]}}}")) + ); + assertThat(actual, notNullValue()); + assertThat(actual, is(expected)); + assertThat(NBTUtil.getNBTTag(actual.get(2).getItem()), is("{meta:{nested:{data:[{},{}]}}}")); + } + + @Test(expected = NullPointerException.class) + public void createItemListNull() throws Exception { + ItemStackUtil.createItemList((List) null); + } + + @Test + public void createItemListInvalid() throws Exception { + try { + ItemStackUtil.createItemList(Arrays.asList("DART")); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), is("Unknown item: 'DART'")); + } + } + + @Test + public void createItemList() throws Exception { + List actual = ItemStackUtil.createItemList(Arrays.asList( + "LAVA_BUCKET:1", + "STONE:2:3", + "NETHER_BRICK_FENCE:2" + )); + List expected = Arrays.asList( + new ItemStack(Material.LAVA_BUCKET, 1), + new ItemStack(Material.STONE, 3, (short) 2), + new ItemStack(Material.NETHER_BRICK_FENCE, 2) + ); + assertThat(actual, itemStacks(expected)); + } + + @Test + public void createItemListStringAndListWithNBTTags() throws Exception { + useMetaData = true; + List actual = ItemStackUtil.createItemList(Arrays.asList("NETHER_BRICK_FENCE:2{meta2}", "JUNGLE_WOOD:256 {meta3}")); + List expected = Arrays.asList( + NBTUtil.setNBTTag(new ItemStack(Material.NETHER_BRICK_FENCE, 2), "{meta2}"), + NBTUtil.setNBTTag(new ItemStack(Material.JUNGLE_WOOD, 256), "{meta3}") // Jungle Wood Planks + ); + assertThat(actual, is(expected)); + assertThat(actual.get(1).getAmount(), is(256)); + assertThat(NBTUtil.getNBTTag(actual.get(0)), is("{meta2}")); + } + + @Test + public void createItemArrayNull() throws Exception { + ItemStack[] actual = ItemStackUtil.createItemArray(null); + assertThat(actual, is(new ItemStack[0])); + } + + @Test + public void createItemArrayEmpty() throws Exception { + ItemStack[] actual = ItemStackUtil.createItemArray(Collections.emptyList()); + assertThat(actual, is(new ItemStack[0])); + } + + @Test + public void createItemArray() throws Exception { + List expected = Arrays.asList( + new ItemStack(Material.LAVA_BUCKET, 1), + new ItemStack(Material.STONE, 3, (short) 2), + new ItemStack(Material.NETHER_BRICK_FENCE, 2), + new ItemStack(Material.JUNGLE_WOOD, 256) // Jungle Wood Planks + ); + ItemStack[] actual = ItemStackUtil.createItemArray(expected); + assertThat(actual, is(expected.toArray())); + } + + @Test + @Ignore("Bukkit.getUnsafe() is not available in test-runner") + public void createItemStack_LegacyColor() throws Exception { + ItemStack actual = ItemStackUtil.createItemStack("STAINED_GLASS_PANE:14"); + assertThat(actual.getType(), is(Material.RED_STAINED_GLASS_PANE)); + assertThat(actual.getDurability(), is(0)); + } + + @Test + public void createItemStackName() throws Exception { + ItemStack actual = ItemStackUtil.createItemStack("DIRT"); + ItemStack expected = new ItemStack(Material.DIRT, 1); + assertThat(actual, itemStack(expected)); + + actual = ItemStackUtil.createItemStack("STONE:2"); // Diorite + expected = new ItemStack(Material.STONE, 1, (short) 2); + assertThat(actual, itemStack(expected)); + } + + @Test + public void createItemStackWithMeta() throws Exception { + useMetaData = true; + ItemStack actual = ItemStackUtil.createItemStack("STONE:2", "&lMy Title", "Hello &4World"); + ItemStack expected = new ItemStack(Material.STONE, 1, (short) 2); + ItemMeta itemMeta = expected.getItemMeta(); + itemMeta.setDisplayName("\u00a7lMy Title"); + itemMeta.setLore(Arrays.asList("Hello \u00a74World")); + expected.setItemMeta(itemMeta); + + assertThat(actual.getItemMeta(), notNullValue()); + verify(actual.getItemMeta()).setDisplayName("\u00a7lMy Title"); + assertThat(actual, is(expected)); + } + + @Test + public void createItemStackWithMetaNBTTag() throws Exception { + useMetaData = true; + ItemStack actual = ItemStackUtil.createItemStack("STONE {display:{Name:\"Hi mom\"}}", "&lMy Title", "Hello &4World"); + ItemStack expected = new ItemStack(Material.STONE, 1); + ItemMeta itemMeta = expected.getItemMeta(); + itemMeta.setDisplayName("\u00a7lMy Title"); + itemMeta.setLore(Arrays.asList("Hello \u00a74World")); + expected.setItemMeta(itemMeta); + expected = NBTUtil.setNBTTag(expected, "{display:{Name:\"Hi mom\"}}"); + + assertThat(actual.getItemMeta(), notNullValue()); + verify(actual.getItemMeta()).setDisplayName("\u00a7lMy Title"); + assertThat(actual, is(expected)); + // Also verify the string, just to be extra sure + assertThat(actual.toString(), is("ItemStack{STONE x 1, {displayName=\u00a7lMy Title, lore=[Hello \u00a74World], nbt={display:{Name:\"Hi mom\"}}}}")); + } + + @Test + public void testCloneNull() throws Exception { + List clone = ItemStackUtil.clone(null); + assertThat(clone, nullValue()); + } + + @Test + public void testClone() throws Exception { + List orig = new ArrayList<>(Arrays.asList( + new ItemStack(Material.LAVA, 1), + new ItemStack(Material.DIRT, 2), + new ItemStack(Material.STONE, 3) + )); + List clone = ItemStackUtil.clone(orig); + assertThat(clone, itemStacks(orig)); + orig.get(0).setAmount(10); + orig.get(1).setAmount(20); + orig.remove(2); + assertThat(clone, not(orig)); + assertThat(clone.size(), is(3)); + assertThat(clone.get(1).getAmount(), is(2)); + } + +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java new file mode 100644 index 000000000..cf2d39184 --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java @@ -0,0 +1,64 @@ +package dk.lockfuglsang.minecraft.util; + +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class LocationUtilTest { + @BeforeClass + public static void SetupOnce() throws Exception { + Server server = BukkitServerMock.setupServerMock(); + when(server.getWorld(anyString())).thenAnswer((a) -> { + World mock = mock(World.class); + when(mock.getName()).thenReturn(a.getArguments()[0].toString()); + return mock; + }); + } + + @Test + public void asString() { + World world = mock(World.class); + when(world.getName()).thenReturn("world"); + Location loc = new Location(world, 1.12, -34.12, 2.0); + + assertThat(LocationUtil.asString(loc), is("world:1.12,-34.12,2.00")); + } + + @Test + public void asKey() { + World world = mock(World.class); + when(world.getName()).thenReturn("world"); + Location loc = new Location(world, 1.12, -34.12, 2.0); + + assertThat(LocationUtil.asKey(loc), is("world/1_12,-34_12,2_00")); + } + + @Test + public void fromString_asString() { + World world = mock(World.class); + when(world.getName()).thenReturn("world"); + Location loc = new Location(world, 1.12, -34.12, 2.0); + + String str = "world:1.12,-34.12,2.00"; + assertThat(LocationUtil.asString(LocationUtil.fromString(str)), is(LocationUtil.asString(loc))); + } + + @Test + public void fromString_asKey() { + World world = mock(World.class); + when(world.getName()).thenReturn("world"); + Location loc = new Location(world, 1.12, -34.12, 2.0); + + String key = "world/1_12,-34_12,2_00"; + assertThat(LocationUtil.asString(LocationUtil.fromString(key)), is(LocationUtil.asString(loc))); + } + +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java new file mode 100644 index 000000000..a11a356fe --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java @@ -0,0 +1,37 @@ +package dk.lockfuglsang.minecraft.yml; + +import org.junit.Test; + +import java.io.File; +import java.io.FileReader; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +public class YmlCommentParserTest { + + @Test + public void testLoad() throws Exception { + File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); + YmlCommentParser parser = new YmlCommentParser(); + parser.load(new FileReader(simpleYml)); + assertThat(parser.getCommentMap(), notNullValue()); + assertThat(parser.getComment(null), nullValue()); + assertThat(parser.getComment("root"), is("#\n" + + "# This is a simple Yml file\n" + + "#\n" + + "# with multiple comments\n")); + assertThat(parser.getComment("root.child node"), is("# child nodes\n")); + assertThat(parser.getComment("root.a"), nullValue()); + assertThat(parser.getComment("root.a.section"), nullValue()); + assertThat(parser.getComment("root.a.section.deeper"), is("# a comment\n")); + assertThat(parser.getComment("root.a.section.deeper.b"), is("# b comment\n")); + assertThat(parser.getComment("root.child node.some-double"), is("# a number\n")); + } + + @Test + public void testReplaceAll() { + String comment = "# comment\n# and comment \n# and...\n"; + assertThat(comment.replaceAll("^# ?", "").replaceAll("\n# ?", "\n"), is("comment\nand comment \n and...\n")); + } +} \ No newline at end of file diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java new file mode 100644 index 000000000..a1649a6f2 --- /dev/null +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java @@ -0,0 +1,53 @@ +package dk.lockfuglsang.minecraft.yml; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.hamcrest.Matchers; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +/** + * Created by R4zorax on 15/07/2016. + */ +public class YmlConfigurationTest { + @Test + public void saveToString() throws Exception { + File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); + YamlConfiguration config = new YamlConfiguration(); + config.load(simpleYml); + + config.set("root.child node.abe", "lincoln\nwas a wonderful\npresident"); + String expected = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("yml/simple_expected.yml"), StandardCharsets.UTF_8)) + .lines().collect(Collectors.joining(System.lineSeparator())); + config.save(new File(simpleYml.getParent(), "new_actual.yml")); + assertThat(config.saveToString(), is(expected)); + } + + @Test + public void testGetStringList_List() throws Exception { + File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); + YamlConfiguration config = new YamlConfiguration(); + config.load(simpleYml); + + List actual = config.getStringList("root.child node.some-section.another-list"); + assertThat(actual, Matchers.contains("what now", "do you know?")); + } + + @Test + public void testGetStringList_OneLineList() throws Exception { + File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); + YamlConfiguration config = new YamlConfiguration(); + config.load(simpleYml); + + List actual = config.getStringList("root.child node.some-section.section-list"); + assertThat(actual, Matchers.contains("Hej", "Mor")); + } +} diff --git a/bukkit-utils/src/test/resources/yml/.gitattributes b/bukkit-utils/src/test/resources/yml/.gitattributes new file mode 100644 index 000000000..b595ec7f3 --- /dev/null +++ b/bukkit-utils/src/test/resources/yml/.gitattributes @@ -0,0 +1 @@ +*.yml text eol=crlf \ No newline at end of file diff --git a/bukkit-utils/src/test/resources/yml/pluginyml_featuremap.yml b/bukkit-utils/src/test/resources/yml/pluginyml_featuremap.yml new file mode 100644 index 000000000..7f278c483 --- /dev/null +++ b/bukkit-utils/src/test/resources/yml/pluginyml_featuremap.yml @@ -0,0 +1,50 @@ +commands: + cmd: + description: 'some description' + aliases: [c] + permission: plugin.cmd +permissions: + # + # Permission Groups + # ================= + plugin.*: + children: + plugin.cmd: true + plugin.cmd.other: true + plugin.feature: true + plugin.feature.a: true + plugin.feature.b: true + plugin.featuresub: true + plugin.sub: true + + plugin.cmd.*: + children: + plugin.cmd.other: true + + plugin.feature.*: + children: + plugin.feature.a: true + plugin.feature.b: true + + # + # Permission Descriptions + # ======================= + plugin.cmd: + description: 'Grants access to /cmd - some description' + + plugin.cmd.other: + description: 'Grants access to /cmd other - some other command' + + plugin.feature.a: + description: 'enables A' + + plugin.feature.b: + description: 'enables B' + + plugin.featuresub: + description: 'standalone feature' + + plugin.sub: + description: 'Grants access to /cmd sub - some sub description' + + diff --git a/bukkit-utils/src/test/resources/yml/pluginyml_simple.yml b/bukkit-utils/src/test/resources/yml/pluginyml_simple.yml new file mode 100644 index 000000000..cf19c067b --- /dev/null +++ b/bukkit-utils/src/test/resources/yml/pluginyml_simple.yml @@ -0,0 +1,46 @@ +commands: + cmd: + description: 'some description' + aliases: [c] + permission: plugin.cmd + adm: + description: 'hey jude!' + aliases: [a] + permission: plugin.adm +permissions: + # + # Permission Groups + # ================= + plugin.*: + children: + plugin.adm: true + plugin.cmd: true + plugin.cmd.other: true + plugin.cmdtest: true + plugin.sub: true + + plugin.cmd.*: + children: + plugin.cmd.other: true + + # + # Permission Descriptions + # ======================= + plugin.adm: + description: 'Grants access to /adm - hey jude!' + + plugin.cmd: + description: 'Grants access to /cmd - some description' + + plugin.cmd.other: + description: 'Grants access to /cmd other - some other command' + + plugin.cmdtest: + description: 'Grants access to /adm t2 [optional] - test' + + plugin.sub: + description: | + Grants access to /cmd sub - some sub description + /adm subs - some other sub + + diff --git a/bukkit-utils/src/test/resources/yml/simple.yml b/bukkit-utils/src/test/resources/yml/simple.yml new file mode 100644 index 000000000..4eabc61f0 --- /dev/null +++ b/bukkit-utils/src/test/resources/yml/simple.yml @@ -0,0 +1,25 @@ +# +# This is a simple Yml file +# +# with multiple comments +root: + child-value: 10 + + # child nodes + child node: + some-double: 1.34 # a number + some-section: + section-list: [Hej, Mor] + another-list: + - what now + - do you know? + space-list: '13:1 34:3' + # this is a key and a value + key: 'value' + another node: + enabled: true + # a comment + a.section.deeper: + b: # b comment + c: false # should be false +"an.annoying:key this.is:for.sure": hello world \ No newline at end of file diff --git a/bukkit-utils/src/test/resources/yml/simple_expected.yml b/bukkit-utils/src/test/resources/yml/simple_expected.yml new file mode 100644 index 000000000..cd0d1735f --- /dev/null +++ b/bukkit-utils/src/test/resources/yml/simple_expected.yml @@ -0,0 +1,37 @@ +# +# This is a simple Yml file +# +# with multiple comments +root: + child-value: 10 + + # child nodes + child node: + some-double: 1.34 # a number + some-section: + section-list: + - Hej + - Mor + another-list: + - what now + - do you know? + space-list: 13:1 34:3 + # this is a key and a value + key: value + abe: |- + lincoln + was a wonderful + president + another node: + enabled: true + a: + section: + # a comment + deeper: + b: # b comment + c: false # should be false +an: + annoying:key this: + is:for: + sure: hello world + diff --git a/pom.xml b/pom.xml index 7be220632..4c292afe1 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,6 @@ 23.0.0 3.8.6 ${project.version} - 1.25-SNAPSHOT 1.0.8 1.20.4-R0.1-SNAPSHOT 1.7 @@ -41,6 +40,7 @@ po-utils + bukkit-utils uSkyBlock-API uSkyBlock-APIv2 uSkyBlock-Core @@ -177,28 +177,6 @@ - - dk.lockfuglsang.minecraft - bukkit-utils - ${bukkit-utils.version} - - - dk.lockfuglsang.minecraft - po-utils - - - org.bukkit - bukkit - - - - - dk.lockfuglsang.minecraft - bukkit-utils - ${bukkit-utils.version} - test - tests - net.milkbowl.vault VaultAPI diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 5c4f99687..33503cbbb 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -82,7 +82,7 @@ true - dk.lockfuglsang.minecraft:bukkit-utils + ovh.uskyblock:bukkit-utils io.papermc:paperlib org.bstats:* ovh.uskyblock:po-utils @@ -341,14 +341,16 @@ - dk.lockfuglsang.minecraft + ovh.uskyblock bukkit-utils + 3.1.0-SNAPSHOT - - dk.lockfuglsang.minecraft + + ovh.uskyblock bukkit-utils - test - tests + 3.1.0-SNAPSHOT + test-jar + test ovh.uskyblock From ec9887ba1d3adf3db0d08e44ea5fc10c64cb7eef Mon Sep 17 00:00:00 2001 From: minoneer Date: Sun, 28 Jul 2024 18:43:04 +0200 Subject: [PATCH 128/190] Minecraft 1.20.6 Update (#55) * Ignore Tests which don't run with 1.20.6 due to missing server initializations * Update spigot dependency to 1.20.6 * Update item menus to 1.20.5 format Includes code cleanup of left-over pre-1.13 stuff * Refactor ItemUtil class * Make sure bukkit-utils compiles with minecraft 1.20.6 * Remove leftover item and block duration from numeric ID times * Update ItemStackUtil parsing from ItemMeta to Item Components * Update item requirement parsing for challenges - move parsing code to factory & item utils where all the other parsing occurs - decouple requirement amount from stack size. We should not rely on ItemStack being able to have larger amounts than maxStackSize - change parsing to use item components instead of nbt tags - including tests - cleanup code * Change NBT command to display new item component info * Remove the now redundant NBT and Reflection stuff * Use standard Bukkit YamlConfiguration to avoid duplicating comments on every save * Remove redundant FileUtil methods * Implement challenges converter - The converter converts all challenges to the new item format. - Item meta from the default challenges configuration are automatically converted. - Other item meta is moved to the comments and will have to be converted manually. - The explanation is moved to the config header, instead of a comment on the version number. * Read configs as UTF8 to support special characters * Convert config.yml to new item formats * Register item component converter and auto convert on startup * Run converter before config files are loaded * Automatically update material for SIGN and SAPLING to oak variants These were used previously as defaults and may not have been updated. * Handle item type parsing for materials that are not supported by the /give command * Fully convert head components (the paper converter did not fix everything) * fire enchantment is now called fire_aspect * Also convert tool item in config * Properly close WorldEdit sessions * Fix fire_aspect enchantment in default challenges.yml --- bukkit-utils/pom.xml | 4 +- .../lockfuglsang/minecraft/file/FileUtil.java | 98 +- .../minecraft/gui/package-info.java | 4 - .../minecraft/nbt/CraftBukkitNBTTagger.java | 100 - .../minecraft/nbt/NBTItemStackTagger.java | 33 - .../lockfuglsang/minecraft/nbt/NBTUtil.java | 63 - .../dk/lockfuglsang/minecraft/nbt/README.md | 5 - .../minecraft/reflection/ReflectionUtil.java | 356 ---- .../minecraft/util/ItemRequirement.java | 69 + .../minecraft/util/ItemStackUtil.java | 305 ++- .../dk/lockfuglsang/minecraft/yml/README.md | 13 - .../minecraft/yml/YmlCommentParser.java | 215 -- .../minecraft/yml/YmlConfiguration.java | 50 - .../minecraft/util/BukkitServerMock.java | 64 +- .../minecraft/util/ItemStackUtilTest.java | 230 +-- .../minecraft/yml/YmlCommentParserTest.java | 37 - pom.xml | 2 +- .../talabrek/ultimateskyblock/Settings.java | 10 +- .../block/BlockCollection.java | 33 +- .../ultimateskyblock/challenge/Challenge.java | 111 +- .../challenge/ChallengeFactory.java | 56 +- .../challenge/ChallengeLogic.java | 80 +- .../ultimateskyblock/challenge/Reward.java | 4 +- .../command/AdminCommand.java | 4 +- .../command/admin/ConfigCommand.java | 6 +- .../command/admin/ItemInfoCommand.java | 42 + .../command/admin/NBTCommand.java | 85 - .../event/NetherTerraFormEvents.java | 2 +- .../handler/WorldEditHandler.java | 46 +- .../handler/task/WorldEditClear.java | 16 +- .../imports/ItemComponentConverter.java | 341 ++++ .../island/BlockLimitLogic.java | 22 +- .../island/IslandGenerator.java | 3 +- .../island/IslandLocatorLogic.java | 7 +- .../menu/AbstractConfigMenu.java | 54 +- .../menu/BooleanEditMenu.java | 6 +- .../ultimateskyblock/menu/ConfigMenu.java | 7 +- .../menu/IntegerEditMenu.java | 66 +- .../ultimateskyblock/menu/MainConfigMenu.java | 17 +- .../menu/MenuItemFactory.java | 18 +- .../ultimateskyblock/menu/SkyBlockMenu.java | 233 +-- .../ultimateskyblock/menu/StringEditMenu.java | 47 +- .../ultimateskyblock/player/Perk.java | 73 +- .../ultimateskyblock/player/PlayerInfo.java | 10 +- .../ultimateskyblock/signs/SignLogic.java | 83 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 29 +- .../ultimateskyblock/util/FileUtil.java | 293 --- .../ultimateskyblock/util/GuiItemUtil.java | 54 + .../ultimateskyblock/util/MaterialUtil.java | 4 +- .../ultimateskyblock/util/ServerUtil.java | 5 +- .../ultimateskyblock/uuid/FilePlayerDB.java | 10 +- .../src/main/resources/challenges.yml | 1709 ++++++++-------- uSkyBlock-Core/src/main/resources/config.yml | 60 +- .../src/main/resources/configmenu.yml | 179 +- uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- .../challenge/ChallengeFactoryTest.java | 12 +- .../challenge/ChallengeLogicTest.java | 90 - .../imports/ItemComponentConverterTest.java | 78 + .../island/IslandLocatorLogicTest.java | 7 +- .../ultimateskyblock/util/BlockUtilTest.java | 3 + .../imports/old-config-expected.yml | 476 +++++ .../ultimateskyblock/imports/old-config.yml | 476 +++++ .../old-default-challenges-expected.yml | 1791 +++++++++++++++++ .../imports/old-default-challenges.yml | 1767 ++++++++++++++++ .../imports/test-challenges-expected.yml | 181 ++ .../imports/test-challenges.yml | 58 + 66 files changed, 7113 insertions(+), 3301 deletions(-) delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemRequirement.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java delete mode 100644 bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverter.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java delete mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogicTest.java create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config-expected.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges.yml diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml index 80da364b5..7d3bf8e0f 100644 --- a/bukkit-utils/pom.xml +++ b/bukkit-utils/pom.xml @@ -147,13 +147,13 @@ junit junit - 4.12 + ${junit.version} test org.mockito mockito-core - 2.28.2 + ${mockito.version} test diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java index 35360914c..3edcfa212 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java @@ -1,28 +1,15 @@ package dk.lockfuglsang.minecraft.file; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; -import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,11 +17,12 @@ /** * Common file-utilities. */ -public enum FileUtil {; +public enum FileUtil { + ; private static final Logger log = Logger.getLogger(FileUtil.class.getName()); private static final Collection allwaysOverwrite = new ArrayList<>(); private static final Collection neverOverwrite = new ArrayList<>(); - private static final Map configFiles = new ConcurrentHashMap<>(); + private static final Map configFiles = new ConcurrentHashMap<>(); private static Locale locale = Locale.getDefault(); private static File dataFolder; @@ -46,23 +34,9 @@ public static void setAllwaysOverwrite(String... configs) { } } - public static void setNeverOverwrite(String... configs) { - for (String s : configs) { - if (!neverOverwrite.contains(s)) { - neverOverwrite.add(s); - } - } - } - - public static YmlConfiguration loadConfig(File file) { - YmlConfiguration config = new YmlConfiguration(); - readConfig(config, file); - return config; - } - public static void readConfig(FileConfiguration config, File file) { if (file == null) { - log.log(Level.INFO, "No " + file + " found, it will be created"); + log.log(Level.INFO, "No " + file + " found, it will be created"); return; } File configFile = file; @@ -71,7 +45,7 @@ public static void readConfig(FileConfiguration config, File file) { configFile = localeFile; } if (!configFile.exists()) { - log.log(Level.INFO, "No " + configFile + " found, it will be created"); + log.log(Level.INFO, "No " + configFile + " found, it will be created"); return; } try (Reader rdr = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { @@ -101,22 +75,9 @@ public static void readConfig(FileConfiguration config, InputStream inputStream) } } - public static FilenameFilter createYmlFilenameFilter() { - return new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name != null && name.endsWith(".yml"); - } - }; - } - - public static String getBasename(File file) { - return getBasename(file.getName()); - } - public static String getBasename(String file) { String[] lastPart = file.split("(/|\\\\)"); - file = lastPart[lastPart.length-1]; + file = lastPart[lastPart.length - 1]; if (file != null && file.lastIndexOf('.') != -1) { return file.substring(0, file.lastIndexOf('.')); } @@ -125,7 +86,7 @@ public static String getBasename(String file) { public static String getExtension(String fileName) { if (fileName != null && !fileName.isEmpty()) { - return fileName.substring(getBasename(fileName).length()+1); + return fileName.substring(getBasename(fileName).length() + 1); } return ""; } @@ -153,15 +114,15 @@ private static File getDataFolder() { * *merged: using data-conversion of special nodes. * */ - public static YmlConfiguration getYmlConfiguration(String configName) { + public static FileConfiguration getYmlConfiguration(String configName) { // Caching, for your convenience! (and a bigger memory print!) if (!configFiles.containsKey(configName)) { - YmlConfiguration config = new YmlConfiguration(); + FileConfiguration config = new YamlConfiguration(); try { // read from datafolder! File configFile = getConfigFile(configName); - YmlConfiguration configJar = new YmlConfiguration(); + YamlConfiguration configJar = new YamlConfiguration(); readConfig(config, configFile); readConfig(configJar, getResource(configName)); if (!configFile.exists() || config.getInt("version", 0) < configJar.getInt("version", 0)) { @@ -175,8 +136,8 @@ public static YmlConfiguration getYmlConfiguration(String configName) { String bakFile = String.format("%1$s-%2$tY%2$tm%2$td-%2$tH%2$tM.yml", getBasename(configName), new Date()); log.log(Level.INFO, "Moving existing config " + configName + " to backup/" + bakFile); Files.move(Paths.get(configFile.toURI()), - Paths.get(new File(backupFolder, bakFile).toURI()), - StandardCopyOption.REPLACE_EXISTING); + Paths.get(new File(backupFolder, bakFile).toURI()), + StandardCopyOption.REPLACE_EXISTING); if (allwaysOverwrite.contains(configName)) { FileUtil.copy(getResource(configName), configFile); config = configJar; @@ -231,15 +192,15 @@ public static void copy(InputStream stream, File file) throws IOException { /** * Merges the important keys from src to destination. - * @param src The source (containing the new values). + * + * @param src The source (containing the new values). * @param dest The destination (containing old-values). */ - private static YmlConfiguration mergeConfig(YmlConfiguration src, YmlConfiguration dest) { + private static FileConfiguration mergeConfig(FileConfiguration src, FileConfiguration dest) { int existing = dest.getInt("version"); int version = src.getInt("version", existing); dest.setDefaults(src); dest.options().copyDefaults(true); - dest.addComments(src.getComments()); dest.set("version", version); dest.options().copyHeader(false); src.options().copyHeader(false); @@ -252,14 +213,14 @@ private static YmlConfiguration mergeConfig(YmlConfiguration src, YmlConfigurati /** * Removes nodes from dest.defaults, that are specifically excluded in the config */ - private static void removeExcludes(YmlConfiguration dest) { + private static void removeExcludes(FileConfiguration dest) { List keys = dest.getStringList("merge-ignore"); for (String key : keys) { dest.getDefaults().set(key, null); } } - private static void replaceDefaults(YmlConfiguration src, YmlConfiguration dest) { + private static void replaceDefaults(FileConfiguration src, FileConfiguration dest) { ConfigurationSection forceSection = src.getConfigurationSection("force-replace"); if (forceSection != null) { for (String key : forceSection.getKeys(true)) { @@ -275,7 +236,7 @@ private static void replaceDefaults(YmlConfiguration src, YmlConfiguration dest) dest.getDefaults().set("force-replace", null); } - private static void moveNodes(YmlConfiguration src, YmlConfiguration dest) { + private static void moveNodes(FileConfiguration src, FileConfiguration dest) { ConfigurationSection moveSection = src.getConfigurationSection("move-nodes"); if (moveSection != null) { List keys = new ArrayList<>(moveSection.getKeys(true)); @@ -311,24 +272,9 @@ public static void setLocale(Locale loc) { } public static void reload() { - for (Map.Entry e : configFiles.entrySet()) { + for (Map.Entry e : configFiles.entrySet()) { File configFile = new File(getDataFolder(), e.getKey()); readConfig(e.getValue(), configFile); } } - - public static Properties readProperties(String fileName) { - File configFile = getConfigFile(fileName); - if (configFile != null && configFile.exists() && configFile.canRead()) { - Properties prop = new Properties(); - try (InputStreamReader in = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { - prop.load(in); - return prop; - } catch (IOException e) { - log.log(Level.WARNING, "Error reading " + fileName, e); - } - } - return null; - } - } diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java deleted file mode 100644 index b1a92422c..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/gui/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Holds a frame-work for making GUI components (inventory based) in Bukkit Minecraft. - */ -package dk.lockfuglsang.minecraft.gui; \ No newline at end of file diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java deleted file mode 100644 index 4b96bfe46..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/CraftBukkitNBTTagger.java +++ /dev/null @@ -1,100 +0,0 @@ -package dk.lockfuglsang.minecraft.nbt; - -import org.bukkit.inventory.ItemStack; - -import java.lang.reflect.Field; -import java.util.Map; -import java.util.logging.Logger; - -import static dk.lockfuglsang.minecraft.reflection.ReflectionUtil.*; - -/** - * An NBTItemStackTagger using reflection for CraftBukkit based servers. - */ -public class CraftBukkitNBTTagger implements NBTItemStackTagger { - private static final Logger log = Logger.getLogger(CraftBukkitNBTTagger.class.getName()); - - @Override - public String getNBTTag(ItemStack itemStack) { - if (itemStack == null) { - return ""; - } - Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); - Object nbtTag = exec(nmsItem, "getTag"); - return nbtTag != null ? "" + nbtTag : ""; - } - - @Override - public ItemStack setNBTTag(ItemStack itemStack, String nbtTagString) { - if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { - return itemStack; - } - Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); - Object nbtTag = execStatic(getNBTTagParser(), "parse", nbtTagString); - exec(nmsItem, "setTag", nbtTag); - Object item = execStatic(getCraftItemStackClass(), "asBukkitCopy", nmsItem); - if (item instanceof ItemStack) { - return (ItemStack) item; - } - return itemStack; - } - - @Override - public ItemStack addNBTTag(ItemStack itemStack, String nbtTagString) { - if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { - return itemStack; - } - Object nmsItem = execStatic(getCraftItemStackClass(), "asNMSCopy", itemStack); - Object nbtTag = exec(nmsItem, "getTag"); - Object nbtTagNew = execStatic(getNBTTagParser(), "parse", nbtTagString); - nbtTag = merge(nbtTagNew, nbtTag); - exec(nmsItem, "setTag", nbtTag); - Object item = execStatic(getCraftItemStackClass(), "asBukkitCopy", nmsItem); - if (item instanceof ItemStack) { - return (ItemStack) item; - } - return itemStack; - } - - /** - * Merges two NBTTagCompound objects - */ - private static Object merge(Object src, Object tgt) { - if (tgt == null) { - return src; - } - try { - Field mapField = src.getClass().getDeclaredField("x"); - mapField.setAccessible(true); - Map map = (Map) mapField.get(src); - Class NBTBase = Class.forName(getPackageName(tgt) + ".NBTBase"); - for (String key : map.keySet()) { - Object val = exec(src, "get", new Class[]{String.class}, key); - exec(tgt, "set", new Class[]{String.class, NBTBase}, key, val); - } - return tgt; - } catch (IllegalAccessException | ClassNotFoundException | NoSuchFieldException e) { - log.info("Unable to transfer NBTTag from " + src + " to " + tgt + ": " + e); - } - return tgt; - } - - private static Class getNBTTagParser() { - try { - return Class.forName("net.minecraft.nbt.MojangsonParser"); - } catch (ClassNotFoundException e) { - log.info("Unable to instantiate MojangsonParser: " + e); - } - return null; - } - - private static Class getCraftItemStackClass() { - String version = getCraftBukkitVersion(); - try { - return Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); - } catch (Exception e) { - log.info("Unable to find CraftItemStack: " + e); - } - return null; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java deleted file mode 100644 index 21f05d0cd..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTItemStackTagger.java +++ /dev/null @@ -1,33 +0,0 @@ -package dk.lockfuglsang.minecraft.nbt; - -import org.bukkit.inventory.ItemStack; - -/** - * Interface for allowing depencency injection for testing (and other platforms than CraftBukkit). - */ -public interface NBTItemStackTagger { - /** - * Returns the NBTTag of the itemStack as a string, or the empty-string if none was found. - * @param itemStack A Bukkit ItemStack - * @return the NBTTag - * @since 1.7.2 - */ - String getNBTTag(ItemStack itemStack); - /** - * Returns a copy of the itemStack with the supplied nbtTagString applied. - * @param itemStack A Bukkit ItemStack - * @param tag A valid NBTTag string - * @return a copy of the itemStack - * @since 1.7.2 - */ - ItemStack setNBTTag(ItemStack itemStack, String tag); - - /** - * Returns a copy of the itemStack with the supplied nbtTagString applied. - * @param itemStack A Bukkit ItemStack - * @param tag A valid NBTTag string - * @return a copy of the itemStack - * @since 1.7.2 - */ - ItemStack addNBTTag(ItemStack itemStack, String tag); -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java deleted file mode 100644 index 1948b18e3..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/NBTUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -package dk.lockfuglsang.minecraft.nbt; - -import org.bukkit.inventory.ItemStack; - -import java.util.logging.Logger; - -/** - * Utility for setting NBTTag data on Bukkit items without NMS (using reflection). - * @since 1.7 - */ -public enum NBTUtil { ; - private static final Logger log = Logger.getLogger(NBTUtil.class.getName()); - - private static NBTItemStackTagger tagger = new CraftBukkitNBTTagger(); - - /** - * Returns the NBTTag of the itemStack as a string, or the empty-string if none was found. - * @param itemStack A Bukkit ItemStack - * @return the NBTTag - * @since 1.7 - */ - public static String getNBTTag(ItemStack itemStack) { - if (itemStack == null) { - return ""; - } - return tagger.getNBTTag(itemStack); - } - - /** - * Returns a copy of the itemStack with the supplied nbtTagString applied. - * @param itemStack A Bukkit ItemStack - * @param nbtTagString A valid NBTTag string - * @return a copy of the itemStack - * @since 1.7 - */ - public static ItemStack setNBTTag(ItemStack itemStack, String nbtTagString) { - if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { - return itemStack; - } - return tagger.setNBTTag(itemStack, nbtTagString); - } - - /** - * Returns a copy of the itemStack with the supplied nbtTagString applied. - * @param itemStack A Bukkit ItemStack - * @param nbtTagString A valid NBTTag string - * @return a copy of the itemStack - * @since 1.7 - */ - public static ItemStack addNBTTag(ItemStack itemStack, String nbtTagString) { - if (itemStack == null || nbtTagString == null || nbtTagString.isEmpty()) { - return itemStack; - } - return tagger.addNBTTag(itemStack, nbtTagString); - } - - public static void setNBTItemStackTagger(NBTItemStackTagger tagger) { - if (tagger == null) { - throw new IllegalArgumentException("tagger cannot be null"); - } - NBTUtil.tagger = tagger; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md deleted file mode 100644 index 08e2ece60..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/nbt/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# NBT Utilities - -This package contains utilities to access/tweak the NBTTags when running a Bukkit plugin. - -# License diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java deleted file mode 100644 index 7a61606cc..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/reflection/ReflectionUtil.java +++ /dev/null @@ -1,356 +0,0 @@ -package dk.lockfuglsang.minecraft.reflection; - -import org.bukkit.Bukkit; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -/** - * Wrapper methods that allow accesss to reflection for backward compatible code. - * - * @since 1.8 - */ -public class ReflectionUtil { - private static final Logger log = Logger.getLogger(ReflectionUtil.class.getName()); - - /** - * Returns the current version of the Bukkit implementation - * - * @return the current version of the Bukkit implementation - * @since 1.8 - */ - public static String getCraftBukkitVersion() { - return cb().split("\\.")[3]; - } - - /** - * Returns the current version of the net.minecraft.server implementation - * - * @param nmsObject A native object from nms namespace - * @return the current version of the net.minecraft.server implementation - * @since 1.8 - */ - public static String getNMSVersion(Object nmsObject) { - return nmsObject != null ? nmsObject.getClass().getPackage().getName().split("\\.")[3] : ""; - } - - /** - * Returns the NMS version. - * @return the NMS version (i.e. "v1_10"). - * @since 1.9 - */ - public static String getNMSVersion() { - return nms().split("\\.")[3]; - } - - /** - * Returns the real packagename for the net.minecraft.server. - * @return the real packagename for the net.minecraft.server. - * @since 1.9 - */ - public static String nms() { - Object nmsServer = exec(Bukkit.getServer(), "getServer"); - return nmsServer != null ? nmsServer.getClass().getPackage().getName() : "net.minecraft.server"; - } - - /** - * Returns the real packagename for the org.bukkit.craftbukkit package - * @return the real packagename for the org.bukkit.craftbukkit package - * @since 1.9 - */ - public static String cb() { - return Bukkit.getServer().getClass().getPackage().getName(); - } - - /** - * Returns the packagename of the given object. - * - * @param nmsObject An object - * @return the packagename of the given object. - * @since 1.8 - */ - public static String getPackageName(Object nmsObject) { - return nmsObject != null ? nmsObject.getClass().getPackage().getName() : ""; - } - - /** - * Returns the corresponding Bukkit class, given a CraftBukkit implementation object. - * - * @param craftObject A CraftBukkit implementation of a Bukkit class. - * @return the corresponding Bukkit class, given a CraftBukkit implementation object. - * @since 1.8 - */ - public static Class getBukkitClass(Object craftObject) { - Class clazz = craftObject != null ? craftObject.getClass() : null; - while (clazz != null && clazz.getCanonicalName().contains(".craftbukkit.")) { - clazz = clazz.getSuperclass(); - } - return clazz; - } - - /** - * Uses reflection to execute the named method on the supplied class giving the arguments. - * Sinks all exceptions, but log an entry and returns null - * - * @param clazz The class on which to invoke the method - * @param methodName The name of the method to invoke - * @param args The arguments to supply to the method - * @return null or the return-object from the method. - * @since 1.8 - */ - public static T execStatic(Class clazz, String methodName, Object... args) { - try { - Class[] argTypes = new Class[args.length]; - int ix = 0; - for (Object arg : args) { - argTypes[ix++] = getBukkitClass(arg); - } - Method method = getMethod(clazz, methodName, argTypes); - boolean wasAccessible = method.isAccessible(); - method.setAccessible(true); - try { - return (T) method.invoke(null, args); - } finally { - method.setAccessible(wasAccessible); - } - } catch (NoSuchMethodException e) { - log.fine("Unable to locate method " + methodName + " on " + clazz); - } catch (InvocationTargetException | IllegalAccessException e) { - log.log(Level.INFO, "Calling " + methodName + " on " + clazz + " threw an exception", e); - } - return null; - } - - /** - * Uses reflection to execute the named method on the supplied class giving the arguments. - * Sinks all exceptions, but log an entry and returns null - * - * @param obj The object on which to invoke the method - * @param methodName The name of the method to invoke - * @param argTypes An array of argument-types (classes). - * @param args The arguments to supply to the method - * @return null or the return-object from the method. - * @since 1.8 - */ - public static T exec(Object obj, String methodName, Class[] argTypes, Object... args) { - if (obj == null) { - return null; - } - Class aClass = obj.getClass(); - try { - Method method = getMethod(aClass, methodName, argTypes); - boolean wasAccessible = method.isAccessible(); - method.setAccessible(true); - try { - return (T) method.invoke(obj, args); - } finally { - method.setAccessible(wasAccessible); - } - } catch (NoSuchMethodException | AbstractMethodError e) { - log.fine("Unable to locate method " + methodName + "(" + Arrays.asList(argTypes) + ") on " + aClass); - } catch (InvocationTargetException | IllegalAccessException e) { - log.log(Level.INFO, "Calling " + methodName + " on " + obj + " threw an exception", e); - } - return null; - } - - public static Method getMethod(Class aClass, String methodName, Class... argTypes) throws NoSuchMethodException { - try { - // Declared gives access to non-public - return aClass.getDeclaredMethod(methodName, argTypes); - } catch (NoSuchMethodException e) { - return aClass.getMethod(methodName, argTypes); - } - } - - public static Method findMethod(Class aClass, Class returnType, Class... argTypes) throws NoSuchMethodException { - List methods = findMethods(aClass, returnType, argTypes); - if (methods.isEmpty()) { - throw new NoSuchMethodException("No method matching " + returnType + " ?(" + Arrays.toString(argTypes) + ")"); - } - if (methods.size() > 1) { - throw new NoSuchMethodException("More than 1 method matching " + returnType + " ?(" + Arrays.toString(argTypes) + ") : " + methods); - } - return methods.get(0); - } - - public static List findMethods(Class aClass, Class returnType, Class... argTypes) throws NoSuchMethodException { - List methods = new ArrayList<>(); - for (Method m : aClass.getDeclaredMethods()) { - if (m.getReturnType() == returnType && m.getParameterTypes().length == argTypes.length) { - try { - Method mLookup = aClass.getMethod(m.getName(), argTypes); - if (mLookup != null) { - methods.add(mLookup); - } - } catch (NoSuchMethodException e) { - // ignore... - } - } - } - return methods; - } - - /** - * Uses reflection to execute the named method on the supplied class giving the arguments. - * Sinks all exceptions, but log an entry and returns null - * - * @param obj The object on which to invoke the method - * @param methodName The name of the method to invoke - * @param args The arguments to supply to the method - * @return null or the return-object from the method. - * @since 1.8 - */ - public static T exec(Object obj, String methodName, Object... args) { - if (obj == null) { - return null; - } - Class[] argTypes = new Class[args.length]; - int ix = 0; - for (Object arg : args) { - argTypes[ix++] = arg != null ? arg.getClass() : null; - } - return exec(obj, methodName, argTypes, args); - } - - /** - * Returns the value of a field on the object. - * @param obj The object - * @param fieldName The name of the field - * @param The type of field - * @return the value or null - * @since 1.9 - */ - public static T getField(Object obj, String fieldName) { - try { - Field field = getFieldInternal(obj, fieldName); - boolean wasAccessible = field.isAccessible(); - field.setAccessible(true); - try { - return (T) field.get(obj); - } finally { - field.setAccessible(wasAccessible); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - log.fine("Unable to find field " + fieldName + " on " + obj); - } - return null; - } - - private static Field getFieldInternal(Object obj, String fieldName) throws NoSuchFieldException { - return getFieldFromClass(obj.getClass(), fieldName); - } - - private static Field getFieldFromClass(Class aClass, String fieldName) throws NoSuchFieldException { - if (aClass == null) { - throw new NoSuchFieldException("Unable to locate field " + fieldName); - } - try { - return aClass.getDeclaredField(fieldName); - } catch (NoSuchFieldException e) { - // Ignored - } - try { - return aClass.getField(fieldName); - } catch (NoSuchFieldException e) { - // Ignore - } - return getFieldFromClass(aClass.getSuperclass(), fieldName); - } - - /** - * Sets the value of a field on the object. - * @param obj The object - * @param fieldName The name of the field - * @param field The value to set - * @param The type of field - * @since 1.9 - */ - public static void setField(Object obj, String fieldName, T field) { - try { - Field declaredField = getFieldInternal(obj, fieldName); - boolean wasAccessible = declaredField.isAccessible(); - declaredField.setAccessible(true); - try { - declaredField.set(obj, field); - } finally { - declaredField.setAccessible(wasAccessible); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - log.fine("Unable to find field " + fieldName + " on " + obj); - } - } - - /** - * Instantiates an object. - * @param className The name of the class - * @param argTypes An array of argument-types - * @param args An array of arguments - * @param Return-type - * @return the object, or null. - * @since 1.9 - */ - public static T newInstance(String className, Class[] argTypes, Object... args) { - try { - Class aClass = Class.forName(className); - Constructor constructor = aClass.getDeclaredConstructor(argTypes); - return (T) constructor.newInstance(args); - } catch (InstantiationException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - log.fine("Unable to instantiate object of type " + className + ":" + e); - } - return null; - } - - /** - * Instantiates an object. - * @param className The name of the class - * @param args An array of arguments - * @param Return-type - * @return the object, or null. - * @since 1.9 - */ - public static T newInstance(String className, Object... args) { - Class[] argTypes = new Class[args.length]; - int ix = 0; - for (Object arg : args) { - argTypes[ix++] = arg != null ? arg.getClass() : null; - } - return newInstance(className, argTypes, args); - } - - public static List dumpMethods(Class aClass) { - List methods = Arrays.asList(aClass.getDeclaredMethods()); - List methodDescriptions = new ArrayList<>(); - String version = getNMSVersion(); - for (Method m : methods) { - List parms = Arrays.asList(m.getParameterTypes()).stream().map(f -> f.getName()).collect(Collectors.toList()); - String parmString = Arrays.toString(parms.toArray(new String[0])); - parmString = parmString.substring(1, parmString.length() - 1); - String description = (Modifier.isPublic(m.getModifiers()) ? "public " : Modifier.isPrivate(m.getModifiers()) ? "private " : "") - + (Modifier.isStatic(m.getModifiers()) ? "static " : "") - + m.getReturnType() + " " + m.getName() - + "(" + parmString + ")"; - description = description - .replaceAll("class net.minecraft.server." + version + ".", "") - .replaceAll("net.minecraft.server." + version + ".", "") - .replaceAll("java.lang.", ""); - methodDescriptions.add(description); - } - List list = new ArrayList(); - - list.add(aClass.toString().replaceAll("class net.minecraft.server." + version + ".", "") - .replaceAll("net.minecraft.server." + version + ".", "") - .replaceAll("java.lang.", "") + ":"); - list.addAll(methodDescriptions.stream().sorted(String::compareTo).collect(Collectors.toList())); - return list; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemRequirement.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemRequirement.java new file mode 100644 index 000000000..bce668c73 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemRequirement.java @@ -0,0 +1,69 @@ +package dk.lockfuglsang.minecraft.util; + +import org.bukkit.inventory.ItemStack; + +// This class should ideally be located in package us.talabrek.ultimateskyblock.challenge. However, it is not possible +// to move there as it is required by ItemStackUtil in this module. This is a limitation of the current design. +// The parsing logic should eventually be moved to the uSkyBlock-Core module. +public record ItemRequirement(ItemStack type, int amount, Operator operator, double increment) { + + public Integer amountForRepetitions(int repetitions) { + return (int) Math.floor(operator().apply(amount(), increment(), repetitions)); + } + + public enum Operator { + NONE("", 0.0) { + @Override + public double apply(double value, double increment, int repetitions) { + return value; + } + }, + ADD("+", 0.0) { + @Override + public double apply(double value, double increment, int repetitions) { + return value + increment * repetitions; + } + }, + SUBTRACT("-", 0.0) { + @Override + public double apply(double value, double increment, int repetitions) { + return value - increment * repetitions; + } + }, + MULTIPLY("*", 1.0) { + @Override + public double apply(double value, double increment, int repetitions) { + return value * Math.pow(increment, repetitions); + } + }, + DIVIDE("/", 1.0) { + @Override + public double apply(double value, double increment, int repetitions) { + return value / Math.pow(increment, repetitions); + } + }; + + private final String symbol; + private final double neutralElement; + + Operator(String symbol, double neutralElement) { + this.symbol = symbol; + this.neutralElement = neutralElement; + } + + public double getNeutralElement() { + return neutralElement; + } + + public abstract double apply(double value, double increment, int repetitions); + + public static Operator fromSymbol(String symbol) { + for (Operator operator : values()) { + if (operator.symbol.equals(symbol)) { + return operator; + } + } + throw new IllegalArgumentException("Unknown operator: " + symbol); + } + } +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java index 400e4aa32..96a4fce25 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java @@ -1,21 +1,16 @@ package dk.lockfuglsang.minecraft.util; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; -import dk.lockfuglsang.minecraft.reflection.ReflectionUtil; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.data.BlockData; import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,53 +21,75 @@ */ public enum ItemStackUtil { ; - private static final Pattern ITEM_AMOUNT_PATTERN = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?(?[0-9A-Z_]+)(:(?[0-9]+))?:(?[0-9]+)\\s*(?\\{.*\\})?"); - private static final Pattern ITEM_PATTERN = Pattern.compile("(?[0-9A-Z_]+)(:(?[0-9]+))?\\s*(?\\{.*\\})?"); + private static final Pattern ITEM_AMOUNT_PROBABILITY_PATTERN = Pattern.compile( + "(\\{p=(?0\\.\\d+)})?(?(minecraft:)?[0-9A-Za-z_]+(\\[.*])?):(?\\d+)" + ); + private static final Pattern ITEM_TYPE_PATTERN = Pattern.compile( + "(?(minecraft:)?[0-9A-Za-z_]+(\\[.*])?)" + ); + private static final Pattern ITEM_REQUIREMENT_PATTERN = Pattern.compile( + "(?(minecraft:)?[0-9A-Za-z_]+(\\[.*])?):(?\\d+)(;(?[-+*^/])(?\\d+(.\\d+)?))?" + ); + + @NotNull + public static ItemRequirement createItemRequirement(@NotNull String specification) { + Matcher matcher = ITEM_REQUIREMENT_PATTERN.matcher(specification); + if (matcher.matches()) { + ItemStack itemStack = getItemType(matcher); + int amount = Integer.parseInt(matcher.group("amount")); + ItemRequirement.Operator operator = matcher.group("op") != null ? + ItemRequirement.Operator.fromSymbol(matcher.group("op")) : ItemRequirement.Operator.NONE; + double increment = matcher.group("inc") != null ? + Double.parseDouble(matcher.group("inc")) : operator.getNeutralElement(); + return new ItemRequirement(itemStack, amount, operator, increment); + } else { + throw new IllegalArgumentException("Invalid item requirement: '" + specification + "'"); + } + } - public static List createItemsWithProbabilty(List items) { - List itemProbs = new ArrayList<>(); + @NotNull + public static List createItemsWithProbability(@NotNull List items) { + List itemsWithProbability = new ArrayList<>(); for (String reward : items) { - Matcher m = ITEM_AMOUNT_PATTERN.matcher(reward); - if (m.matches()) { - double p = m.group("prob") != null ? Double.parseDouble(m.group("prob")) : 1; - short sub = m.group("sub") != null ? (short) Integer.parseInt(m.group("sub"), 10) : 0; - Material type = getItemType(m, sub); - int amount = Integer.parseInt(m.group("amount"), 10); - ItemStack itemStack = new ItemStack(type, amount, sub < type.getMaxDurability() ? sub : 0); - itemStack = NBTUtil.addNBTTag(itemStack, m.group("meta")); - itemProbs.add(new ItemProbability(p, itemStack)); + Matcher matcher = ITEM_AMOUNT_PROBABILITY_PATTERN.matcher(reward); + if (matcher.matches()) { + double probability = matcher.group("prob") != null ? + Double.parseDouble(matcher.group("prob")) : 1.0; + ItemStack itemStack = getItemType(matcher); + int amount = Integer.parseInt(matcher.group("amount")); + itemStack.setAmount(amount); + itemsWithProbability.add(new ItemProbability(probability, itemStack)); } else { throw new IllegalArgumentException("Unknown item: '" + reward + "' in '" + items + "'"); } } - return itemProbs; + return itemsWithProbability; } - private static Material getItemType(Matcher m, short dataValue) { - String id = m.group("id"); - if (id != null && id.matches("[0-9]*")) { - throw new IllegalArgumentException("Bukkit 1.13+ doesn't support Item-IDs, please use Material names instead"); - } else if (id != null) { - Material type = Material.matchMaterial(id); - if (type == null) { - try { - Material legacyType = Material.matchMaterial(id, true); - BlockData blockData = Bukkit.getServer().getUnsafe().fromLegacy(legacyType, (byte) (dataValue & 0x0f)); - type = blockData != null && blockData.getMaterial() != null && blockData.getMaterial() != Material.AIR - ? blockData.getMaterial() - : legacyType; - } catch (NullPointerException e) { - throw new IllegalArgumentException("Bukkit 1.13 does not know the material " + id + "!", e); - } - } - if (type != null) { - return type; + @NotNull + private static ItemStack getItemType(@NotNull Matcher matcher) { + String type = matcher.group("type"); + ItemStack result; + try { + result = Bukkit.getItemFactory().createItemStack(type.toLowerCase(Locale.ROOT)); + } catch (IllegalArgumentException e) { + // There are some items that are not supported by the /give command and therefore not by the Bukkit API, + // for example minecraft:nether_portal. These should never be used as item requirements/rewards, but the + // item requirements section is also (miss-) used for block requirements. Therefore, we need to handle + // these cases. Ideally we should have a separate class for block requirements. + Material material = Material.matchMaterial(type); + if (material != null) { + result = new ItemStack(material); + } else { + throw e; } } - return Material.BARRIER; + return result; } - public static List createItemList(List items) { + // used for parsing challenge rewards and starter chest items + @NotNull + public static List createItemList(@NotNull List items) { List itemList = new ArrayList<>(); for (String reward : items) { if (reward != null && !reward.isEmpty()) { @@ -82,19 +99,13 @@ public static List createItemList(List items) { return itemList; } - private static ItemStack createItemStackAmount(String reward) { - if (reward == null || reward.isEmpty()) { - return null; - } - Matcher m = ITEM_AMOUNT_PATTERN.matcher(reward); - if (m.matches()) { - short sub = m.group("sub") != null ? (short) Integer.parseInt(m.group("sub"), 10) : 0; - Material type = getItemType(m, sub); - int amount = Integer.parseInt(m.group("amount"), 10); - ItemStack itemStack = new ItemStack(type, amount, sub < type.getMaxDurability() ? sub : 0); - if (m.group("meta") != null) { - itemStack = NBTUtil.addNBTTag(itemStack, m.group("meta")); - } + @NotNull + private static ItemStack createItemStackAmount(@NotNull String reward) { + Matcher matcher = ITEM_AMOUNT_PROBABILITY_PATTERN.matcher(reward); + if (matcher.matches()) { + ItemStack itemStack = getItemType(matcher); + int amount = Integer.parseInt(matcher.group("amount")); + itemStack.setAmount(amount); return itemStack; } else { throw new IllegalArgumentException("Unknown item: '" + reward + "'"); @@ -102,53 +113,19 @@ private static ItemStack createItemStackAmount(String reward) { } public static ItemStack[] createItemArray(List items) { - return items != null ? items.toArray(new ItemStack[items.size()]) : new ItemStack[0]; + return items != null ? items.toArray(new ItemStack[0]) : new ItemStack[0]; } public static ItemStack createItemStack(String displayItem) { return createItemStack(displayItem, null, null); } - public static ItemStack createItemStackSkull(String texture, String name, String description) { - ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1); - String metaStr = String.format("{display:{Name:\"%s\"},SkullOwner:{Id:\"%s\",Properties:{textures:[{Value:\"%s\"}]}}}", name, createUniqueId(texture, name, description), texture); - itemStack = NBTUtil.addNBTTag(itemStack, metaStr); - ItemMeta meta = itemStack.getItemMeta(); - if (meta != null) { - if (name != null) { - meta.setDisplayName(FormatUtil.normalize(name)); - } - List lore = new ArrayList<>(); - if (description != null) { - lore.addAll(FormatUtil.wordWrap(FormatUtil.normalize(description), 30, 30)); - } - meta.setLore(lore); - itemStack.setItemMeta(meta); - } - return itemStack; - } - - public static UUID createUniqueId(String texture, String name, String description) { - return new UUID(texture.hashCode(), ("" + name + description).hashCode()); - } - - public static ItemStack createItemStack(String displayItem, String name, String description) { - Material type = Material.DIRT; - short sub = 0; - String metaStr = null; - if (displayItem != null) { - Matcher matcher = ITEM_PATTERN.matcher(displayItem); - if (matcher.matches()) { - sub = matcher.group("sub") != null ? (short) Integer.parseInt(matcher.group("sub"), 10) : 0; - type = getItemType(matcher, sub); - metaStr = matcher.group("meta"); - } - } - if (type == null) { - Bukkit.getLogger().warning("Invalid material " + displayItem + " supplied!"); - type = Material.BARRIER; + public static ItemStack createItemStack(@NotNull String displayItem, @Nullable String name, @Nullable String description) { + Matcher matcher = ITEM_TYPE_PATTERN.matcher(displayItem); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid item " + displayItem + " supplied!"); } - ItemStack itemStack = new ItemStack(type, 1, sub < type.getMaxDurability() ? sub : 0); + ItemStack itemStack = getItemType(matcher); ItemMeta meta = itemStack.getItemMeta(); if (meta != null) { if (name != null) { @@ -161,25 +138,11 @@ public static ItemStack createItemStack(String displayItem, String name, String meta.setLore(lore); itemStack.setItemMeta(meta); } - itemStack = NBTUtil.addNBTTag(itemStack, metaStr); return itemStack; } - public static List clone(List items) { - if (items == null) { - return null; - } - List copy = new ArrayList<>(); - for (ItemStack item : items) { - copy.add(item.clone()); - } - return copy; - } - - public static boolean isValidInventoryItem(ItemStack itemStack) { - Inventory inventory = Bukkit.createInventory(null, 9); - inventory.setItem(0, itemStack); - return inventory.getItem(0) != null && inventory.getItem(0).getItemMeta() != null && inventory.getItem(0).getData() != null && inventory.getItem(0).getData().toItemStack() != null; + public static @NotNull List clone(@NotNull List items) { + return items.stream().map(ItemStack::clone).toList(); } public static Builder builder(ItemStack stack) { @@ -187,7 +150,15 @@ public static Builder builder(ItemStack stack) { } public static String asString(ItemStack item) { - return item.getType().name() + (item.getDurability() != 0 ? ":" + item.getDurability() : "") + ":" + item.getAmount(); + var itemType = item.getType().getKey().toString(); + var itemMeta = item.getItemMeta(); + if (itemMeta != null) { + var componentString = itemMeta.getAsComponentString(); + if (!componentString.isEmpty() && !componentString.equals("[]")) { + itemType += componentString; + } + } + return itemType + ":" + item.getAmount(); } public static String asShortString(List items) { @@ -195,7 +166,7 @@ public static String asShortString(List items) { for (ItemStack item : items) { shorts.add(asShortString(item)); } - return "[" + FormatUtil.join(shorts, ", ") + "]"; + return "[" + FormatUtil.join(shorts, ", ") + "]"; } public static String asShortString(ItemStack item) { @@ -203,45 +174,57 @@ public static String asShortString(ItemStack item) { return ""; } return item.getAmount() > 1 - ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), getItemName(item)) - : tr("\u00a77{0}", getItemName(item)); + ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), getItemName(item)) + : tr("\u00a77{0}", getItemName(item)); } - public static ItemStack asDisplayItem(ItemStack item) { + @NotNull + public static ItemStack asDisplayItem(@NotNull ItemStack item) { ItemStack copy = new ItemStack(item); ItemMeta itemMeta = copy.getItemMeta(); - // Hide all enchants (if possible). - try { - Class aClass = Class.forName("org.bukkit.inventory.ItemFlag"); - Object allValues = ReflectionUtil.execStatic(aClass, "values"); - ReflectionUtil.exec(itemMeta, "addItemFlags", allValues); - } catch (ClassNotFoundException e) { - // Ignore - only available for 1.9 and above + if (itemMeta != null) { + itemMeta.addItemFlags(ItemFlag.values()); } copy.setItemMeta(itemMeta); return copy; } + @Contract("null -> null; !null -> !null") + @Nullable public static String getItemName(ItemStack stack) { - if (stack != null) { - if (stack.getItemMeta() != null && stack.getItemMeta().getDisplayName() != null && !stack.getItemMeta().getDisplayName().trim().isEmpty()) { - return stack.getItemMeta().getDisplayName(); - } - /* - Vault isn't 1.13 compatible (yet) - ItemInfo itemInfo = Items.itemByStack(stack); - return itemInfo != null ? itemInfo.getName() : "" + stack.getType(); - */ - return tr(FormatUtil.camelcase(stack.getType().name()).replaceAll("([A-Z])", " $1").trim()); + if (stack == null) { + return null; } - return null; + var itemMeta = stack.getItemMeta(); + if (itemMeta != null && itemMeta.hasDisplayName() && !itemMeta.getDisplayName().trim().isEmpty()) { + return stack.getItemMeta().getDisplayName(); + } + return tr(FormatUtil.camelcase(stack.getType().name()).replaceAll("([A-Z])", " $1").trim()); + } + + @Contract(pure = true) + @NotNull + public static ItemStack[] asValidItemStacksWithAmount(@NotNull Map typesWithAmount) { + return typesWithAmount.entrySet().stream().flatMap(entry -> { + ItemStack requiredType = entry.getKey(); + int requiredAmount = entry.getValue(); + List result = new ArrayList<>(); + int remaining = requiredAmount; + while (remaining > 0) { + ItemStack item = requiredType.clone(); + item.setAmount(Math.min(remaining, item.getMaxStackSize())); + remaining -= item.getAmount(); + result.add(item); + } + return result.stream(); + }).toArray(ItemStack[]::new); } /** * Builder for ItemStack */ public static class Builder { - private ItemStack itemStack; + private final ItemStack itemStack; public Builder(ItemStack itemStack) { this.itemStack = itemStack != null ? itemStack.clone() : new ItemStack(Material.AIR); @@ -252,11 +235,6 @@ public Builder type(Material mat) { return this; } - public Builder subType(int subType) { - itemStack.setDurability((short) subType); - return this; - } - public Builder amount(int amount) { itemStack.setAmount(amount); return this; @@ -281,11 +259,11 @@ public Builder select(boolean b) { } public Builder select() { - return enchant(Enchantment.PROTECTION_ENVIRONMENTAL, 1).add(ItemFlag.HIDE_ENCHANTS); + return enchant(Enchantment.PROTECTION, 1).add(ItemFlag.HIDE_ENCHANTS); } public Builder deselect() { - return remove(Enchantment.PROTECTION_ENVIRONMENTAL).remove(ItemFlag.HIDE_ENCHANTS); + return remove(Enchantment.PROTECTION).remove(ItemFlag.HIDE_ENCHANTS); } public Builder add(ItemFlag... flags) { @@ -333,43 +311,6 @@ public ItemStack build() { } } - public static class ItemProbability { - private final double probability; - private final ItemStack item; - - public ItemProbability(double probability, ItemStack item) { - this.probability = probability; - this.item = item; - } - - public double getProbability() { - return probability; - } - - public ItemStack getItem() { - return item; - } - - @Override - public String toString() { - return "ItemProbability{" + - "probability=" + probability + - ", item=" + item + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ItemProbability that = (ItemProbability) o; - return Double.compare(that.probability, probability) == 0 && - Objects.equals(asString(item), asString(that.item)); - } - - @Override - public int hashCode() { - return Objects.hash(probability, item); - } + public record ItemProbability(double probability, ItemStack item) { } } diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md deleted file mode 100644 index 48af7118e..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# YmlConfiguration - -These classes enables plugins to preserve comments when handling `FileConfiguration` objects in Bukkit. - -## Usage - -``` - FileConfiguration config = new YmlConfiguration(); - config.load(file); - // Do FileConfiguration stuff - - config.save(file); -``` \ No newline at end of file diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java deleted file mode 100644 index d5d2df11a..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlCommentParser.java +++ /dev/null @@ -1,215 +0,0 @@ -package dk.lockfuglsang.minecraft.yml; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A very simplistic yml parser, that only do the following: - *

    - *
  1. Keep track of indentation-levels and sections.
  2. - *
  3. Handle comments.
  4. - *
- */ -public class YmlCommentParser { - private static final Logger log = Logger.getLogger(YmlCommentParser.class.getName()); - private static final Pattern SECTION_PATTERN = Pattern.compile("^(?\\s*)(?[^ \\-][^:]*):(?[^#]*)?(?#.*)?"); - private static final Pattern COMMENT_PATTERN = Pattern.compile("^(?\\s*)(?#.*)"); - private Map commentMap = new HashMap<>(); - - public Map getCommentMap() { - return Collections.unmodifiableMap(commentMap); - } - - - public void addComment(String path, String comment) { - commentMap.put(path, comment); - } - - public void addComments(Map comments) { - commentMap.putAll(comments); - } - - private void readLines(BufferedReader rdr) throws IOException { - int indentLevel = 0; - Deque
sections = new ArrayDeque<>(); - StringBuilder comments = new StringBuilder(); - String baseKey = null; - sections.add(new Section(null, 0)); - String line; - int lineNum = 1; - boolean isFirstAfterSection = true; - while ((line = rdr.readLine()) != null) { - Matcher commentM = COMMENT_PATTERN.matcher(line); - Matcher sectionM = SECTION_PATTERN.matcher(line); - if (commentM.matches()) { - comments.append(commentM.group("comment") + "\n"); - } else if (sectionM.matches()) { - String comment = sectionM.group("comment"); - if (comment != null && !comment.trim().isEmpty()) { - comments.append(comment + "\n"); - } - String name = sectionM.group("name").trim(); - String value = sectionM.group("value"); - String indent = sectionM.group("indent"); - if (isFirstAfterSection && indent.length() > indentLevel) { - indentLevel = indent.length(); - sections.peek().setIndentation(indentLevel); - } else if (indent.length() < indentLevel) { - while (indent.length() < indentLevel && !sections.isEmpty()) { - sections.pop(); - baseKey = sections.peek().getPath(); - indentLevel = sections.peek().getIndentation(); - isFirstAfterSection = false; - } - } - String path = getPath(baseKey, name); - if (value != null && !value.trim().isEmpty()) { - // Scalar with value - addComments(path, comments); - if (!isFirstAfterSection && indent.length() > indentLevel) { - log.warning("line " + lineNum + ": mixed indentation, expected " + indentLevel + " but got " + indent.length()); - } - isFirstAfterSection = false; - } else if (indent.length() >= indentLevel) { - indentLevel = indent.length(); - sections.push(createSection(path, indentLevel, comments)); - baseKey = path; - isFirstAfterSection = true; - } - } else if (line.trim().isEmpty()) { - // Currently gathered comments are reset - they are "floating", decoupled from sections. - comments.setLength(0); - comments.trimToSize(); - } - lineNum++; - } - } - - private String getPath(String baseKey, String name) { - return baseKey != null ? baseKey + "." + name : name; - } - - private Section createSection(String path, int indentLevel, StringBuilder comments) { - Section section = new Section(path, indentLevel); - addComments(path, comments); - return section; - } - - private void addComments(String path, StringBuilder comments) { - if (comments.length() > 0) { - commentMap.put(path, comments.toString()); - comments.setLength(0); - comments.trimToSize(); - } - } - - public String getComment(String path) { - return commentMap.get(path); - } - - /** - * Merges the comments into the "pure" yml. - * @param ymlPure A YML data-tree, without comments. - * @return A YML data-tree including comments. - */ - public String mergeComments(String ymlPure) { - StringBuilder sb = new StringBuilder(); - boolean isFirstAfterSection = true; - Deque
sections = new ArrayDeque<>(); - sections.push(new Section(null, 0)); - int indentLevel = 0; - String baseKey = null; - int lineNum = 1; - // First section shares comments with the header - so ignore that one - boolean isHeader = true; - for (String line : ymlPure.split("\n")) { - // Skip header - Matcher commentM = COMMENT_PATTERN.matcher(line); - if (isHeader && (commentM.matches() || line.trim().isEmpty())) { - continue; // Skip header - } - isHeader = false; - Matcher sectionM = SECTION_PATTERN.matcher(line); - if (sectionM.matches()) { - String name = sectionM.group("name").trim(); - String value = sectionM.group("value"); - String indent = sectionM.group("indent"); - if (isFirstAfterSection && indent.length() > indentLevel) { - indentLevel = indent.length(); - sections.peek().setIndentation(indentLevel); - } else if (indent.length() < indentLevel) { - while (indent.length() < indentLevel && !sections.isEmpty()) { - sections.pop(); - baseKey = sections.peek().getPath(); - indentLevel = sections.peek().getIndentation(); - isFirstAfterSection = false; - } - } - String path = getPath(baseKey, name); - String comment = getComment(path); - if (comment != null) { - sb.append((lineNum > 1 ? "\n" : "") + comment - .replaceAll("^#", Matcher.quoteReplacement(indent + "#")) - .replaceAll("\n#", Matcher.quoteReplacement("\n" + indent + "#"))); - } - if (value != null && !value.trim().isEmpty()) { - // Scalar with value - isFirstAfterSection = false; - } else if (indent.length() >= indentLevel) { - indentLevel = indent.length(); - sections.push(new Section(path, indentLevel)); - baseKey = path; - isFirstAfterSection = true; - } - } - lineNum++; - sb.append(line + "\n"); - } - return sb.toString().replaceAll("\r\n", "\n").replaceAll("\n\r", "\n").replaceAll("\n", "\r\n"); - } - - public void load(Reader reader) throws IOException { - readLines(new BufferedReader(reader)); - } - - public void loadFromString(String contents) { - try { - readLines(new BufferedReader(new StringReader(contents))); - } catch (IOException e) { - throw new IllegalStateException("Unable to read from string", e); - } - } - - - private static class Section { - private int indentation; - private final String path; - - private Section(String name, int indentation) { - this.indentation = indentation; - this.path = name; - } - - public int getIndentation() { - return indentation; - } - - public String getPath() { - return path; - } - - public void setIndentation(int indentLevel) { - indentation = indentLevel; - } - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java deleted file mode 100644 index 1510dcf8b..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/yml/YmlConfiguration.java +++ /dev/null @@ -1,50 +0,0 @@ -package dk.lockfuglsang.minecraft.yml; - -import com.google.common.collect.Streams; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * A YamlConfiguration that supports comments - *

- * Note: This includes a VERY SIMPLISTIC Yaml-parser, which sole purpose is to detect and store comments. - */ -@Deprecated(forRemoval = true) // Bukkit YamlConfiguration now preserves comments by default -public class YmlConfiguration extends YamlConfiguration { - - @Deprecated(forRemoval = true) // Use #getComments and #getInlineComments instead - public String getComment(String key) { - String comment = Streams.concat(super.getComments(key).stream(), - super.getInlineComments(key).stream()).collect(Collectors.joining(System.lineSeparator())); - if (comment.isEmpty()) { - return null; - } - return comment.replaceAll("^# ?", "").replaceAll("\n# ?", ""); - } - - @Deprecated(forRemoval = true) // Use #getComments and #getInlineComments instead - public Map getComments() { - Map comments = new LinkedHashMap<>(); - for (String key : getKeys(true)) { - String comment = getComment(key); - if (comment != null) { - comments.put(key, comment); - } - } - return comments; - } - - @Deprecated(forRemoval = true) // Use #setComments and #setInlineComments instead - public void addComment(String path, String comment) { - var comments = new ArrayList<>(super.getComments(path)); - comments.add(comment); - super.setComments(path, comments); - } - - @Deprecated(forRemoval = true) // Use #setComments and #setInlineComments instead - public void addComments(Map comments) { - comments.forEach(this::addComment); - } -} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java index d892a39ec..526f2e2fb 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java @@ -1,7 +1,5 @@ package dk.lockfuglsang.minecraft.util; -import dk.lockfuglsang.minecraft.nbt.NBTItemStackTagger; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Server; @@ -28,7 +26,6 @@ public class BukkitServerMock { * Stubbing data, allows for advanced stubbing behaviour for item-meta */ protected static Map> itemMetaMap = new HashMap<>(); - private static ItemFactory itemFactoryMock; public static Server setupServerMock() throws NoSuchFieldException, IllegalAccessException { Field server = Bukkit.class.getDeclaredField("server"); @@ -36,19 +33,17 @@ public static Server setupServerMock() throws NoSuchFieldException, IllegalAcces Server serverMock = createServerMock(); server.set(null, serverMock); server.setAccessible(false); - - NBTUtil.setNBTItemStackTagger(new TestNBTItemStackTagger()); return serverMock; } public static Server createServerMock() { Server serverMock = mock(Server.class); - itemFactoryMock = mock(ItemFactory.class); + ItemFactory itemFactoryMock = mock(ItemFactory.class); when(itemFactoryMock.isApplicable(any(ItemMeta.class), any(Material.class))) .thenReturn(true); - when(itemFactoryMock.equals(any(ItemMeta.class), any(ItemMeta.class))) + when(itemFactoryMock.equals(any(), any())) .thenAnswer((Answer) invocationOnMock -> { // Better equals for mocks? return Objects.equals("" + invocationOnMock.getArguments()[0], @@ -62,8 +57,30 @@ public static Server createServerMock() { .thenAnswer((Answer) invocationOnMock -> invocationOnMock.getArguments()[0] != null ? (ItemMeta) invocationOnMock.getArguments()[0] : null); - when(itemFactoryMock.updateMaterial(any(ItemMeta.class), any(Material.class))) - .thenAnswer(i -> i.getArguments()[1]); + + when(itemFactoryMock.createItemStack(any())) + .thenAnswer((Answer) invocationOnMock -> { + String specification = (String) invocationOnMock.getArguments()[0]; + var componentSplitIndex = specification.indexOf('['); + String typeSpecification; + String components; + if (componentSplitIndex > 0) { + typeSpecification = specification.substring(0, componentSplitIndex); + components = specification.substring(componentSplitIndex); + } else { + typeSpecification = specification; + components = ""; + } + var type = Material.matchMaterial(typeSpecification); + var itemStack = new ItemStack(type); + var mockMeta = mock(ItemMeta.class, withSettings().extraInterfaces(Damageable.class)); + when(((Damageable)mockMeta).getDamage()).thenReturn(0); + when(mockMeta.toString()).thenReturn(components); + when(mockMeta.getAsComponentString()).thenReturn(components.isEmpty() ? "[]" : components); + when(itemStack.getItemMeta()).thenReturn(mockMeta); + return itemStack; + }); + when(serverMock.getItemFactory()).thenReturn(itemFactoryMock); UnsafeValues unsafeMock = mock(UnsafeValues.class); @@ -103,33 +120,4 @@ public static ItemMeta createItemMetaStub() { when(meta.clone()).thenReturn(meta); // Don't clone it - we need to verify it return meta; } - - public static class TestNBTItemStackTagger implements NBTItemStackTagger { - @Override - public String getNBTTag(ItemStack itemStack) { - if (itemMetaMap.containsKey(itemStack.getItemMeta())) { - Map metaMap = itemMetaMap.get(itemStack.getItemMeta()); - if (metaMap.containsKey("nbt")) { - return metaMap.get("nbt"); - } - } - return ""; - } - - @Override - public ItemStack setNBTTag(ItemStack itemStack, String tag) { - ItemMeta itemMeta = itemStack.getItemMeta(); - if (itemMeta != null && itemMetaMap.containsKey(itemMeta)) { - Map metaMap = itemMetaMap.get(itemMeta); - metaMap.put("nbt", tag); - itemStack.setItemMeta(itemMeta); - } - return itemStack; - } - - @Override - public ItemStack addNBTTag(ItemStack itemStack, String tag) { - return setNBTTag(itemStack, tag); - } - } } diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java index f7936ddcb..dcba69b76 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackUtilTest.java @@ -1,46 +1,25 @@ package dk.lockfuglsang.minecraft.util; -import dk.lockfuglsang.minecraft.nbt.NBTItemStackTagger; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; -import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.Server; -import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.TreeMap; import static dk.lockfuglsang.minecraft.util.ItemStackMatcher.itemStack; import static dk.lockfuglsang.minecraft.util.ItemStackMatcher.itemStacks; import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; -/** - * Tests the utility methods of ItemStackUtil - */ public class ItemStackUtilTest extends BukkitServerMock { @BeforeClass public static void setUpClass() throws Exception { - Server server = setupServerMock(); + setupServerMock(); } @Before @@ -49,75 +28,75 @@ public void setUp() { itemMetaMap.clear(); } - @Test(expected = NullPointerException.class) - public void createItemsWithProbabiltyNull() throws Exception { - ItemStackUtil.createItemsWithProbabilty(null); + @Test + public void createBasicItemRequirement() { + ItemRequirement actual = ItemStackUtil.createItemRequirement("stone:1"); + ItemRequirement expected = new ItemRequirement(new ItemStack(Material.STONE), 1, ItemRequirement.Operator.NONE, 0.0); + assertThat(actual, is(expected)); } - @Test(expected = IllegalArgumentException.class) - public void createItemsWithProbabiltyInvalid() throws Exception { - ItemStackUtil.createItemsWithProbabilty(Arrays.asList("{p:0.9}10:1")); + @Test + public void createItemRequirementWithDifferentIncrements() { + var specifications = List.of("stone:1", "stone:12;+1", "stone:1;-10", "stone:100;*0.1", "stone:1;/12.1"); + var expected = List.of( + new ItemRequirement(new ItemStack(Material.STONE), 1, ItemRequirement.Operator.NONE, 0.0), + new ItemRequirement(new ItemStack(Material.STONE), 12, ItemRequirement.Operator.ADD, 1.0), + new ItemRequirement(new ItemStack(Material.STONE), 1, ItemRequirement.Operator.SUBTRACT, 10.0), + new ItemRequirement(new ItemStack(Material.STONE), 100, ItemRequirement.Operator.MULTIPLY, 0.1), + new ItemRequirement(new ItemStack(Material.STONE), 1, ItemRequirement.Operator.DIVIDE, 12.1) + ); + for (int i = 0; i < specifications.size(); i++) { + ItemRequirement actual = ItemStackUtil.createItemRequirement(specifications.get(i)); + assertThat(actual, is(expected.get(i))); + } } @Test - public void createItemsWithProbabilty1() throws Exception { - List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList("{p=0.9}LAVA_BUCKET:1")); - List expected = Arrays.asList( - new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1)) - ); - assertThat(actual, notNullValue()); + public void createComplexItemRequirement() { + ItemRequirement actual = ItemStackUtil.createItemRequirement("minecraft:white_banner[complex={item:[]}]:1923;/0.001"); + ItemRequirement expected = new ItemRequirement(new ItemStack(Material.WHITE_BANNER), 1923, ItemRequirement.Operator.DIVIDE, 0.001); assertThat(actual, is(expected)); + assertThat(actual.type().getItemMeta().toString(), is("[complex={item:[]}]")); } @Test - public void createItemsWithProbabiltyN() throws Exception { - List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList( - "{p=0.9}LAVA_BUCKET:1", - "{p=0.2}STONE:2:3", - "{p=0.3}NETHER_BRICK_FENCE:2" - )); - List expected = Arrays.asList( - new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1)), - new ItemStackUtil.ItemProbability(0.2, new ItemStack(Material.STONE, 3, (short) 2)), - new ItemStackUtil.ItemProbability(0.3, new ItemStack(Material.NETHER_BRICK_FENCE, 2)) - ); + public void createItemsWithProbability1() { + List actual = ItemStackUtil.createItemsWithProbability(List.of("{p=0.9}LAVA_BUCKET:1")); + List expected = List.of(new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1))); assertThat(actual, notNullValue()); assertThat(actual, is(expected)); } @Test - public void createItemsWithProbabiltyWithNBTTag() throws Exception { - useMetaData = true; - List actual = ItemStackUtil.createItemsWithProbabilty(Arrays.asList( - "{p=0.9}LAVA_BUCKET:1{Potion:Death}", - "{p=0.2}STONE:2:3 {MyLittle:\"Pony\"}", - "{p=0.3}NETHER_BRICK_FENCE:2\t {meta:{nested:{data:[{},{}]}}}" - )); - List expected = Arrays.asList( - new ItemStackUtil.ItemProbability(0.9, NBTUtil.setNBTTag( - new ItemStack(Material.LAVA_BUCKET, 1), - "{Potion:Death}")), - new ItemStackUtil.ItemProbability(0.2, NBTUtil.setNBTTag( - new ItemStack(Material.STONE, 3, (short) 2), - "{MyLittle:\"Pony\"}")), - new ItemStackUtil.ItemProbability(0.3, NBTUtil.setNBTTag( - new ItemStack(Material.NETHER_BRICK_FENCE, 2), - "{meta:{nested:{data:[{},{}]}}}")) - ); + public void createItemsWithProbabilityN() { + List actual = ItemStackUtil.createItemsWithProbability(List.of("{p=0.9}LAVA_BUCKET:1", "{p=0.2}STONE:3", "{p=0.3}NETHER_BRICK_FENCE:2")); + List expected = List.of(new ItemStackUtil.ItemProbability(0.9, new ItemStack(Material.LAVA_BUCKET, 1)), new ItemStackUtil.ItemProbability(0.2, new ItemStack(Material.STONE, 3)), new ItemStackUtil.ItemProbability(0.3, new ItemStack(Material.NETHER_BRICK_FENCE, 2))); assertThat(actual, notNullValue()); assertThat(actual, is(expected)); - assertThat(NBTUtil.getNBTTag(actual.get(2).getItem()), is("{meta:{nested:{data:[{},{}]}}}")); } - @Test(expected = NullPointerException.class) - public void createItemListNull() throws Exception { - ItemStackUtil.createItemList((List) null); + @Test + public void createItemsWithProbabilityWithComponents() { + useMetaData = true; + List actual = ItemStackUtil.createItemsWithProbability(List.of("{p=0.9}lava_bucket[some: value]:1", "{p=0.2}minecraft:stone[quoted: \"value\"]:3", "{p=0.3}NETHER_BRICK_FENCE[meta:{nested:{data:[{},{}]}}]:2")); + + assertThat(actual.get(0).item().getType(), is(Material.LAVA_BUCKET)); + assertThat(actual.get(0).item().getItemMeta().toString(), is("[some: value]")); + assertThat(actual.get(0).probability(), is(0.9)); + + assertThat(actual.get(1).item().getType(), is(Material.STONE)); + assertThat(actual.get(1).item().getItemMeta().toString(), is("[quoted: \"value\"]")); + assertThat(actual.get(1).probability(), is(0.2)); + + assertThat(actual.get(2).item().getType(), is(Material.NETHER_BRICK_FENCE)); + assertThat(actual.get(2).item().getItemMeta().toString(), is("[meta:{nested:{data:[{},{}]}}]")); + assertThat(actual.get(2).probability(), is(0.3)); } @Test - public void createItemListInvalid() throws Exception { + public void createItemListInvalid() { try { - ItemStackUtil.createItemList(Arrays.asList("DART")); + ItemStackUtil.createItemList(List.of("DART")); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), is("Unknown item: 'DART'")); @@ -125,122 +104,60 @@ public void createItemListInvalid() throws Exception { } @Test - public void createItemList() throws Exception { - List actual = ItemStackUtil.createItemList(Arrays.asList( - "LAVA_BUCKET:1", - "STONE:2:3", - "NETHER_BRICK_FENCE:2" - )); - List expected = Arrays.asList( - new ItemStack(Material.LAVA_BUCKET, 1), - new ItemStack(Material.STONE, 3, (short) 2), - new ItemStack(Material.NETHER_BRICK_FENCE, 2) - ); + public void createItemList() { + List actual = ItemStackUtil.createItemList(List.of("LAVA_BUCKET:1", "STONE:3", "NETHER_BRICK_FENCE:2")); + List expected = List.of(new ItemStack(Material.LAVA_BUCKET, 1), new ItemStack(Material.STONE, 3), new ItemStack(Material.NETHER_BRICK_FENCE, 2)); assertThat(actual, itemStacks(expected)); } @Test - public void createItemListStringAndListWithNBTTags() throws Exception { - useMetaData = true; - List actual = ItemStackUtil.createItemList(Arrays.asList("NETHER_BRICK_FENCE:2{meta2}", "JUNGLE_WOOD:256 {meta3}")); - List expected = Arrays.asList( - NBTUtil.setNBTTag(new ItemStack(Material.NETHER_BRICK_FENCE, 2), "{meta2}"), - NBTUtil.setNBTTag(new ItemStack(Material.JUNGLE_WOOD, 256), "{meta3}") // Jungle Wood Planks - ); - assertThat(actual, is(expected)); + public void createItemListStringAndListWithComponents() { + List actual = ItemStackUtil.createItemList(List.of("diamond_sword[damage:200]:2", "white_banner[minecraft:banner_patterns=[{color: \"green\", pattern: \"minecraft:creeper\"}]]:256")); + + assertThat(actual.get(0).getType(), is(Material.DIAMOND_SWORD)); + assertThat(actual.get(1).getType(), is(Material.WHITE_BANNER)); + + assertThat(actual.get(0).getItemMeta().toString(), is("[damage:200]")); + assertThat(actual.get(1).getItemMeta().toString(), is("[minecraft:banner_patterns=[{color: \"green\", pattern: \"minecraft:creeper\"}]]")); + + assertThat(actual.get(0).getAmount(), is(2)); assertThat(actual.get(1).getAmount(), is(256)); - assertThat(NBTUtil.getNBTTag(actual.get(0)), is("{meta2}")); } @Test - public void createItemArrayNull() throws Exception { + public void createItemArrayNull() { ItemStack[] actual = ItemStackUtil.createItemArray(null); assertThat(actual, is(new ItemStack[0])); } @Test - public void createItemArrayEmpty() throws Exception { - ItemStack[] actual = ItemStackUtil.createItemArray(Collections.emptyList()); + public void createItemArrayEmpty() { + ItemStack[] actual = ItemStackUtil.createItemArray(List.of()); assertThat(actual, is(new ItemStack[0])); } @Test - public void createItemArray() throws Exception { - List expected = Arrays.asList( - new ItemStack(Material.LAVA_BUCKET, 1), - new ItemStack(Material.STONE, 3, (short) 2), - new ItemStack(Material.NETHER_BRICK_FENCE, 2), - new ItemStack(Material.JUNGLE_WOOD, 256) // Jungle Wood Planks + public void createItemArray() { + List expected = List.of(new ItemStack(Material.LAVA_BUCKET, 1), new ItemStack(Material.STONE, 3), new ItemStack(Material.NETHER_BRICK_FENCE, 2), new ItemStack(Material.JUNGLE_WOOD, 256) // Jungle Wood Planks ); ItemStack[] actual = ItemStackUtil.createItemArray(expected); assertThat(actual, is(expected.toArray())); } @Test - @Ignore("Bukkit.getUnsafe() is not available in test-runner") - public void createItemStack_LegacyColor() throws Exception { - ItemStack actual = ItemStackUtil.createItemStack("STAINED_GLASS_PANE:14"); - assertThat(actual.getType(), is(Material.RED_STAINED_GLASS_PANE)); - assertThat(actual.getDurability(), is(0)); - } - - @Test - public void createItemStackName() throws Exception { + public void createItemStackName() { ItemStack actual = ItemStackUtil.createItemStack("DIRT"); ItemStack expected = new ItemStack(Material.DIRT, 1); assertThat(actual, itemStack(expected)); - actual = ItemStackUtil.createItemStack("STONE:2"); // Diorite - expected = new ItemStack(Material.STONE, 1, (short) 2); + actual = ItemStackUtil.createItemStack("DIORITE"); + expected = new ItemStack(Material.DIORITE, 1); assertThat(actual, itemStack(expected)); } @Test - public void createItemStackWithMeta() throws Exception { - useMetaData = true; - ItemStack actual = ItemStackUtil.createItemStack("STONE:2", "&lMy Title", "Hello &4World"); - ItemStack expected = new ItemStack(Material.STONE, 1, (short) 2); - ItemMeta itemMeta = expected.getItemMeta(); - itemMeta.setDisplayName("\u00a7lMy Title"); - itemMeta.setLore(Arrays.asList("Hello \u00a74World")); - expected.setItemMeta(itemMeta); - - assertThat(actual.getItemMeta(), notNullValue()); - verify(actual.getItemMeta()).setDisplayName("\u00a7lMy Title"); - assertThat(actual, is(expected)); - } - - @Test - public void createItemStackWithMetaNBTTag() throws Exception { - useMetaData = true; - ItemStack actual = ItemStackUtil.createItemStack("STONE {display:{Name:\"Hi mom\"}}", "&lMy Title", "Hello &4World"); - ItemStack expected = new ItemStack(Material.STONE, 1); - ItemMeta itemMeta = expected.getItemMeta(); - itemMeta.setDisplayName("\u00a7lMy Title"); - itemMeta.setLore(Arrays.asList("Hello \u00a74World")); - expected.setItemMeta(itemMeta); - expected = NBTUtil.setNBTTag(expected, "{display:{Name:\"Hi mom\"}}"); - - assertThat(actual.getItemMeta(), notNullValue()); - verify(actual.getItemMeta()).setDisplayName("\u00a7lMy Title"); - assertThat(actual, is(expected)); - // Also verify the string, just to be extra sure - assertThat(actual.toString(), is("ItemStack{STONE x 1, {displayName=\u00a7lMy Title, lore=[Hello \u00a74World], nbt={display:{Name:\"Hi mom\"}}}}")); - } - - @Test - public void testCloneNull() throws Exception { - List clone = ItemStackUtil.clone(null); - assertThat(clone, nullValue()); - } - - @Test - public void testClone() throws Exception { - List orig = new ArrayList<>(Arrays.asList( - new ItemStack(Material.LAVA, 1), - new ItemStack(Material.DIRT, 2), - new ItemStack(Material.STONE, 3) - )); + public void testClone() { + List orig = new ArrayList<>(List.of(new ItemStack(Material.LAVA, 1), new ItemStack(Material.DIRT, 2), new ItemStack(Material.STONE, 3))); List clone = ItemStackUtil.clone(orig); assertThat(clone, itemStacks(orig)); orig.get(0).setAmount(10); @@ -250,5 +167,4 @@ public void testClone() throws Exception { assertThat(clone.size(), is(3)); assertThat(clone.get(1).getAmount(), is(2)); } - -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java deleted file mode 100644 index a11a356fe..000000000 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlCommentParserTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package dk.lockfuglsang.minecraft.yml; - -import org.junit.Test; - -import java.io.File; -import java.io.FileReader; - -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.assertThat; - -public class YmlCommentParserTest { - - @Test - public void testLoad() throws Exception { - File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); - YmlCommentParser parser = new YmlCommentParser(); - parser.load(new FileReader(simpleYml)); - assertThat(parser.getCommentMap(), notNullValue()); - assertThat(parser.getComment(null), nullValue()); - assertThat(parser.getComment("root"), is("#\n" + - "# This is a simple Yml file\n" + - "#\n" + - "# with multiple comments\n")); - assertThat(parser.getComment("root.child node"), is("# child nodes\n")); - assertThat(parser.getComment("root.a"), nullValue()); - assertThat(parser.getComment("root.a.section"), nullValue()); - assertThat(parser.getComment("root.a.section.deeper"), is("# a comment\n")); - assertThat(parser.getComment("root.a.section.deeper.b"), is("# b comment\n")); - assertThat(parser.getComment("root.child node.some-double"), is("# a number\n")); - } - - @Test - public void testReplaceAll() { - String comment = "# comment\n# and comment \n# and...\n"; - assertThat(comment.replaceAll("^# ?", "").replaceAll("\n# ?", "\n"), is("comment\nand comment \n and...\n")); - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4c292afe1..07e3e91ba 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ 3.8.6 ${project.version} 1.0.8 - 1.20.4-R0.1-SNAPSHOT + 1.20.6-R0.1-SNAPSHOT 1.7 7.2.19 7.0.9 diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index bc608917c..5db004e54 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -8,6 +8,7 @@ import dk.lockfuglsang.minecraft.util.ItemStackUtil; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Set; import java.util.logging.Logger; @@ -22,7 +23,7 @@ public class Settings { public static boolean island_removeCreaturesByTeleport; public static int island_protectionRange; public static int island_radius; - public static ItemStack[] island_chestItems; + private static List island_chestItems; public static boolean island_addExtraItems; public static String[] island_extraPermissions; public static boolean island_allowIslandLock; @@ -119,9 +120,9 @@ public static boolean loadPluginConfig(FileConfiguration config) { changed = true; } general_spawnSize = config.getInt("options.general.spawnSize", 50); - island_chestItems = ItemStackUtil.createItemArray(ItemStackUtil.createItemList( + island_chestItems = ItemStackUtil.createItemList( config.getStringList("options.island.chestItems") - )); + ); island_schematicName = config.getString("options.island.schematicName"); if (island_schematicName == null || "yourschematicname".equals(island_schematicName) || "uSkyBlockDefault".equals(island_schematicName)) { @@ -162,4 +163,7 @@ public static boolean loadPluginConfig(FileConfiguration config) { return changed; } + public static List getIslandChestItems() { + return ItemStackUtil.clone(island_chestItems); + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java index d5d2d8fc6..398b45590 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java @@ -5,43 +5,32 @@ import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class BlockCollection { - Map> blockCount; + Map blockCount; public BlockCollection() { this.blockCount = new HashMap<>(); } public synchronized void add(Block block) { - Map countMap = blockCount.getOrDefault(block.getType(), new HashMap<>()); - int currentValue = countMap.getOrDefault(block.getData(), 0); - countMap.put(block.getData(), currentValue + 1); - blockCount.put(block.getType(), countMap); + int currentValue = blockCount.getOrDefault(block.getType(), 0); + blockCount.put(block.getType(), currentValue + 1); } /** * Returns null if all the items are in the BlockCollection, a String describing the missing items if it's not - * @param itemStacks - * @return */ - public synchronized String diff(Collection itemStacks) { + public synchronized String diff(Map itemStacks) { StringBuilder sb = new StringBuilder(); - for (ItemStack item : itemStacks) { - int diff = 0; - if (item.getDurability() != 0) { - diff = item.getAmount() - count(item.getType(), (byte) (item.getDurability() & 0xff)); - } else { - diff = item.getAmount() - count(item.getType()); - } + for (Map.Entry item : itemStacks.entrySet()) { + int diff = item.getValue() - count(item.getKey().getType()); if (diff > 0) { - sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, ItemStackUtil.getItemName(item))); + sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, ItemStackUtil.getItemName(item.getKey()))); } } if (sb.toString().trim().isEmpty()) { @@ -51,12 +40,6 @@ public synchronized String diff(Collection itemStacks) { } private int count(Material type) { - Map countMap = blockCount.getOrDefault(type, Collections.emptyMap()); - return countMap.values().stream().mapToInt(i -> i).sum(); - } - - public int count(Material type, byte data) { - Map countMap = blockCount.getOrDefault(type, Collections.emptyMap()); - return countMap.getOrDefault(data, 0); + return blockCount.getOrDefault(type, 0); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java index 028ad3b2a..23bbb2104 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java @@ -1,19 +1,19 @@ package us.talabrek.ultimateskyblock.challenge; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; +import dk.lockfuglsang.minecraft.util.FormatUtil; +import dk.lockfuglsang.minecraft.util.ItemRequirement; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.FormatUtil; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.logging.Level; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.Map; +import java.util.stream.Collectors; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; import static dk.lockfuglsang.minecraft.util.FormatUtil.*; @@ -22,7 +22,6 @@ * The data-object for a challenge */ public class Challenge { - public static final Pattern REQ_PATTERN = Pattern.compile("(?(?[0-9A-Z_]+)(:(?[0-9]+))?(?\\{.*\\})?):(?[0-9]+)(;(?[+\\-*\\^])(?[0-9]+))?"); public static final int MAX_DETAILS = 11; public static final int MAX_LINE = 30; @@ -30,9 +29,9 @@ public enum Type { PLAYER, ISLAND, ISLAND_LEVEL; static Type from(String s) { - if (s == null || s.trim().isEmpty() || s.trim().toLowerCase().equals("onplayer")) { + if (s == null || s.trim().isEmpty() || s.trim().equalsIgnoreCase("onplayer")) { return PLAYER; - } else if (s != null && s.equalsIgnoreCase("islandlevel")) { + } else if (s.equalsIgnoreCase("islandlevel")) { return ISLAND_LEVEL; } return ISLAND; @@ -43,10 +42,10 @@ static Type from(String s) { private final String description; private final String displayName; private final Type type; - private final List requiredItems; + private final List requiredItems; private final List requiredEntities; private final List requiredChallenges; - private double requiredLevel; + private final double requiredLevel; private final Rank rank; private final int resetInHours; private final ItemStack displayItem; @@ -59,10 +58,10 @@ static Type from(String s) { private final Reward repeatReward; private final int repeatLimit; - public Challenge(String name, String displayName, String description, Type type, List requiredItems, - List requiredEntities, List requiredChallenges, double requiredLevel, Rank rank, int resetInHours, - ItemStack displayItem, String tool, ItemStack lockedItem, int offset, boolean takeItems, - int radius, Reward reward, Reward repeatReward, int repeatLimit) { + public Challenge(String name, String displayName, String description, Type type, List requiredItems, + List requiredEntities, List requiredChallenges, double requiredLevel, Rank rank, + int resetInHours, ItemStack displayItem, String tool, ItemStack lockedItem, int offset, + boolean takeItems, int radius, Reward reward, Reward repeatReward, int repeatLimit) { this.name = name; this.displayName = displayName; this.type = type; @@ -112,29 +111,12 @@ public double getRequiredLevel() { return requiredLevel; } - public List getRequiredItems(int timesCompleted) { - List items = new ArrayList<>(); - for (String item : requiredItems) { - if (item == null || item.trim().isEmpty()) { - continue; // Just skip it - } - Matcher m = REQ_PATTERN.matcher(item); - if (m.matches()) { - int amount = Integer.parseInt(m.group("amount"), 10); - char op = m.group("op") != null ? m.group("op").charAt(0) : 0; - int inc = m.group("inc") != null ? Integer.parseInt(m.group("inc"), 10) : 0; - amount = ChallengeLogic.calcAmount(amount, op, inc, timesCompleted); - ItemStack mat = ItemStackUtil.createItemStack(m.group("itemstack")); - ItemMeta meta = mat.getItemMeta(); - mat.setItemMeta(meta); - mat = NBTUtil.addNBTTag(mat, m.group("meta")); - mat.setAmount(amount); - items.add(mat); - } else if (!item.matches("[0-9]+") && type != Type.ISLAND_LEVEL) { - uSkyBlock.getInstance().getLogger().log(Level.INFO, "Malformed challenge " + name + ", item: " + item + " is not a valid required item"); - } - } - return items; + @NotNull + public Map getRequiredItems(int timesCompleted) { + return this.requiredItems.stream().collect(Collectors.toUnmodifiableMap( + item -> item.type().clone(), + item -> item.amountForRepetitions(timesCompleted) + )); } public List getRequiredEntities() { @@ -157,8 +139,7 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr int timesCompleted = completion.getTimesCompletedInCooldown(); ItemStack currentChallengeItem = getDisplayItem(); ItemMeta meta = currentChallengeItem.getItemMeta(); - List lores = new ArrayList<>(); - lores.addAll(prefix(wordWrap(getDescription(), MAX_LINE), "\u00a77")); + List lores = new ArrayList<>(prefix(wordWrap(getDescription(), MAX_LINE), "\u00a77")); Reward reward = getReward(); if (completion.getTimesCompleted() > 0 && isRepeatable()) { currentChallengeItem.setAmount(completion.getTimesCompleted() < currentChallengeItem.getMaxStackSize() ? completion.getTimesCompleted() : currentChallengeItem.getMaxStackSize()); @@ -175,7 +156,7 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr final int hours = (int) (cooldown / ChallengeLogic.MS_HOUR); lores.add(tr("\u00a74Requirements will reset in {0} hours.", hours)); } else if (cooldown >= 0) { - final int minutes = Math.round(cooldown / ChallengeLogic.MS_MIN); + final int minutes = Math.round((float) cooldown / ChallengeLogic.MS_MIN); lores.add(tr("\u00a74Requirements will reset in {0} minutes.", minutes)); } } else { @@ -187,27 +168,29 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr final int hours = (int) (cooldown / ChallengeLogic.MS_HOUR); lores.add(tr("\u00a74You can complete this again in {0} hours.", hours)); } else if (cooldown >= 0) { - final int minutes = Math.round(cooldown / ChallengeLogic.MS_MIN); + final int minutes = Math.round((float) cooldown / ChallengeLogic.MS_MIN); lores.add(tr("\u00a74You can complete this again in {0} minutes.", minutes)); } } } reward = getRepeatReward(); } - List reqItems = getRequiredItems(timesCompleted); - if ((reqItems != null && !reqItems.isEmpty()) || (requiredEntities != null && !requiredEntities.isEmpty())) { + Map requiredItemsForChallenge = getRequiredItems(timesCompleted); + if (!requiredItemsForChallenge.isEmpty() || requiredEntities != null && !requiredEntities.isEmpty()) { lores.add(tr("\u00a7eThis challenge requires:")); } List details = new ArrayList<>(); - if (reqItems != null && !reqItems.isEmpty()) { - for (ItemStack item : reqItems) { + if (!requiredItemsForChallenge.isEmpty()) { + for (Map.Entry requiredItem : requiredItemsForChallenge.entrySet()) { if (wrappedDetails(details).size() >= MAX_DETAILS) { details.add(tr("\u00a77and more...")); break; } - details.add(item.getAmount() > 1 - ? tr("\u00a7f{0}x \u00a77{1}", item.getAmount(), ItemStackUtil.getItemName(item)) - : tr("\u00a77{0}", ItemStackUtil.getItemName(item))); + int requiredAmount = requiredItem.getValue(); + ItemStack requiredType = requiredItem.getKey(); + details.add(requiredAmount > 1 + ? tr("\u00a7f{0}x \u00a77{1}", requiredAmount, ItemStackUtil.getItemName(requiredType)) + : tr("\u00a77{0}", ItemStackUtil.getItemName(requiredType))); } } if (requiredEntities != null && !requiredEntities.isEmpty() && wrappedDetails(details).size() < MAX_DETAILS) { @@ -217,8 +200,8 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr break; } details.add(entityMatch.getCount() > 1 - ? tr("\u00a7f{0}x \u00a77{1}", entityMatch.getCount(), entityMatch.getDisplayName()) - : tr("\u00a77{0}", entityMatch.getDisplayName())); + ? tr("\u00a7f{0}x \u00a77{1}", entityMatch.getCount(), entityMatch.getDisplayName()) + : tr("\u00a77{0}", entityMatch.getDisplayName())); } } lores.addAll(wrappedDetails(details)); @@ -231,9 +214,7 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr } List lines = wordWrap("\u00a7a" + reward.getRewardText(), 20, MAX_LINE); lores.add(tr("\u00a76Item Reward: \u00a7a") + lines.get(0)); - for (String line : lines.subList(1, lines.size())) { - lores.add(line); - } + lores.addAll(lines.subList(1, lines.size())); if (withCurrency) { lores.add(tr("\u00a76Currency Reward: \u00a7a{0}", reward.getCurrencyReward())); } @@ -292,16 +273,16 @@ public List getMissingRequirements(PlayerInfo playerInfo) { @Override public String toString() { return "Challenge{" + - "name='" + name + '\'' + - ", type=" + type + - ", requiredItems='" + requiredItems + '\'' + - ", rank='" + rank + '\'' + - ", resetInHours=" + resetInHours + - ", displayItem=" + displayItem + - ", takeItems=" + takeItems + - ", reward=" + reward + - ", repeatReward=" + repeatReward + - ", repeatLimit=" + repeatLimit + - '}'; + "name='" + name + '\'' + + ", type=" + type + + ", requiredItems='" + requiredItems + '\'' + + ", rank='" + rank + '\'' + + ", resetInHours=" + resetInHours + + ", displayItem=" + displayItem + + ", takeItems=" + takeItems + + ", reward=" + reward + + ", repeatReward=" + repeatReward + + ", repeatLimit=" + repeatLimit + + '}'; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index 9c70dc77a..07d9a1b45 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -1,17 +1,13 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.util.ItemRequirement; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import us.talabrek.ultimateskyblock.util.MetaUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -32,16 +28,17 @@ public static void setLogger(Logger log) { public static ChallengeDefaults createDefaults(ConfigurationSection section) { return new ChallengeDefaults( - section.getInt("defaultResetInHours", 144), - section.getBoolean("requiresPreviousRank", true), - normalize(section.getString("repeatableColor", "&a")), - normalize(section.getString("finishedColor", "&2")), - normalize(section.getString("challengeColor", "&e")), - section.getInt("rankLeeway", 1), - section.getBoolean("enableEconomyPlugin", true), - section.getBoolean("broadcastCompletion", true), - section.getInt("radius", 10), section.getBoolean("showLockedChallengeName", true), - section.getInt("repeatLimit", 0)); + section.getInt("defaultResetInHours", 144), + section.getBoolean("requiresPreviousRank", true), + normalize(section.getString("repeatableColor", "&a")), + normalize(section.getString("finishedColor", "&2")), + normalize(section.getString("challengeColor", "&e")), + section.getInt("rankLeeway", 1), + section.getBoolean("enableEconomyPlugin", true), + section.getBoolean("broadcastCompletion", true), + section.getInt("radius", 10), + section.getBoolean("showLockedChallengeName", true), + section.getInt("repeatLimit", 0)); } public static Challenge createChallenge(Rank rank, ConfigurationSection section, ChallengeDefaults defaults) { @@ -51,13 +48,14 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, } String displayName = section.getString("name", name); Challenge.Type type = Challenge.Type.from(section.getString("type", "onPlayer")); - List requiredItems = section.isList("requiredItems") ? section.getStringList("requiredItems") : Arrays.asList(section.getString("requiredItems", "").split(" ")); + List requiredItems = section.getStringList("requiredItems").stream() + .map(ItemStackUtil::createItemRequirement).toList(); List requiredEntities = createEntities(section.getStringList("requiredEntities")); int resetInHours = section.getInt("resetInHours", rank.getResetInHours()); String description = section.getString("description"); ItemStack displayItem = createItemStack( - section.getString("displayItem", defaults.displayItem), - normalize(displayName), description); + section.getString("displayItem", defaults.displayItem), + normalize(displayName), description); ItemStack lockedItem = section.isString("lockedDisplayItem") ? createItemStack(section.getString("lockedDisplayItem", "BARRIER"), displayName, description) : null; boolean takeItems = section.getBoolean("takeItems", true); int radius = section.getInt("radius", 10); @@ -70,9 +68,9 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, int offset = section.getInt("offset", 0); int repeatLimit = section.getInt("repeatLimit", 0); return new Challenge(name, displayName, description, type, - requiredItems, requiredEntities, requiredChallenges, section.getDouble("requiredLevel", 0d), rank, - resetInHours, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, - radius, reward, repeatReward, repeatLimit); + requiredItems, requiredEntities, requiredChallenges, section.getDouble("requiredLevel", 0d), rank, + resetInHours, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, + radius, reward, repeatReward, repeatLimit); } private static List createEntities(List requiredEntities) { @@ -109,12 +107,12 @@ private static Reward createReward(ConfigurationSection section) { items.addAll(Arrays.asList(section.getString("items").split(" "))); } return new Reward( - section.getString("text", "\u00a74Unknown"), - ItemStackUtil.createItemsWithProbabilty(items), - section.getString("permission"), - section.getInt("currency", 0), - section.getInt("xp", 0), - section.getStringList("commands")); + section.getString("text", "\u00a74Unknown"), + ItemStackUtil.createItemsWithProbability(items), + section.getString("permission"), + section.getInt("currency", 0), + section.getInt("xp", 0), + section.getStringList("commands")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 69be5eae6..9c68c79f2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -1,6 +1,5 @@ package us.talabrek.ultimateskyblock.challenge; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; import dk.lockfuglsang.minecraft.util.FormatUtil; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Bukkit; @@ -24,19 +23,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.logging.Level; import java.util.regex.Matcher; @@ -188,21 +175,6 @@ public Challenge getChallenge(String challengeName) { return null; } - public static int calcAmount(int amount, char op, int inc, int timesCompleted) { - switch (op) { - case '+': - return amount + inc * timesCompleted; - case '-': - return amount - inc * timesCompleted; // Why? - case '*': - case '^': - return amount * (int) Math.pow(inc, timesCompleted); // Oh, my god! Just do the time m8! - case '/': - return amount / (int) Math.pow(inc, timesCompleted); // Yay! Free stuff!!! - } - return amount; - } - public boolean tryComplete(final Player player, final String challenge, final String type) { if (type.equalsIgnoreCase("onPlayer")) { return tryCompleteOnPlayer(player, challenge); @@ -216,7 +188,8 @@ public boolean tryComplete(final Player player, final String challenge, final St /** * Try to complete a {@link Challenge} for the given {@link Player} where a minimal island level is a requirement. - * @param player Player to complete the challenge for. + * + * @param player Player to complete the challenge for. * @param challenge Challenge to complete. * @return True if the challenge was completed succesfully, false otherwise. */ @@ -228,7 +201,7 @@ private boolean tryCompleteIslandLevel(Player player, Challenge challenge) { return false; } - private boolean islandContains(Player player, List itemStacks, int radius) { + private boolean islandContains(Player player, Map itemStacks, int radius) { final Location l = player.getLocation(); final int px = l.getBlockX(); final int py = l.getBlockY(); @@ -254,13 +227,14 @@ private boolean islandContains(Player player, List itemStacks, int ra /** * Try to complete a {@link Challenge} on the island of the given {@link Player} where items or entities are * required to be present on the island. - * @param player Player to complete the challenge for. + * + * @param player Player to complete the challenge for. * @param challengeName Challenge to complete. * @return True if the challenge was completed succesfully, false otherwise. */ private boolean tryCompleteOnIsland(Player player, String challengeName) { Challenge challenge = getChallenge(challengeName); - List requiredItems = challenge.getRequiredItems(0); + Map requiredItems = challenge.getRequiredItems(0); int radius = challenge.getRadius(); if (islandContains(player, requiredItems, radius) && hasEntitiesNear(player, challenge.getRequiredEntities(), radius)) { giveReward(player, challenge); @@ -302,14 +276,15 @@ private boolean hasEntitiesNear(Player player, List requiredEntitie StringBuilder sb = new StringBuilder(); for (Map.Entry entry : countMap.entrySet()) { sb.append("\u00a7e - "); - sb.append(" \u00a74" + entry.getValue() + " \u00a7ex"); - sb.append(" \u00a7b" + entry.getKey().getDisplayName() + "\n"); + sb.append(" \u00a74").append(entry.getValue()).append(" \u00a7ex"); + sb.append(" \u00a7b").append(entry.getKey().getDisplayName()).append("\n"); } player.sendMessage(tr("\u00a7eStill the following entities short:\n{0}", sb.toString()).split("\n")); } return countMap.isEmpty(); } + // TODO: This logic is duplicated in SignLogic.tryComplete. Refactor to a common method. private boolean tryCompleteOnPlayer(Player player, String challengeName) { Challenge challenge = getChallenge(challengeName); PlayerInfo playerInfo = plugin.getPlayerInfo(player); @@ -317,17 +292,23 @@ private boolean tryCompleteOnPlayer(Player player, String challengeName) { if (challenge != null && completion != null) { StringBuilder sb = new StringBuilder(); boolean hasAll = true; - List requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); - for (ItemStack required : requiredItems) { - String name = ItemStackUtil.getItemName(required); - if (!player.getInventory().containsAtLeast(required, required.getAmount())) { - sb.append(tr(" \u00a74{0} \u00a7b{1}", (required.getAmount() - getCountOf(player.getInventory(), required)), name)); + Map requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); + for (Map.Entry required : requiredItems.entrySet()) { + ItemStack requiredType = required.getKey(); + int requiredAmount = required.getValue(); + String name = ItemStackUtil.getItemName(requiredType); + if (!player.getInventory().containsAtLeast(requiredType, requiredAmount)) { + sb.append(tr(" \u00a74{0} \u00a7b{1}", (requiredAmount - getCountOf(player.getInventory(), requiredType)), name)); hasAll = false; } } if (hasAll) { if (challenge.isTakeItems()) { - player.getInventory().removeItem(requiredItems.toArray(new ItemStack[requiredItems.size()])); + ItemStack[] itemsToRemove = ItemStackUtil.asValidItemStacksWithAmount(requiredItems); + var leftovers = player.getInventory().removeItem(itemsToRemove); + if (!leftovers.isEmpty()) { + throw new IllegalStateException("Player " + player.getName() + " had items left over after completing challenge " + challengeName + ": " + leftovers); + } } giveReward(player, challenge); return true; @@ -339,13 +320,9 @@ private boolean tryCompleteOnPlayer(Player player, String challengeName) { } public int getCountOf(Inventory inventory, ItemStack required) { - int count = 0; - for (ItemStack invItem : inventory.all(required.getType()).values()) { - if (invItem.getDurability() == required.getDurability() && NBTUtil.getNBTTag(invItem).equals(NBTUtil.getNBTTag(required))) { - count += invItem.getAmount(); - } - } - return count; + return Arrays.stream(inventory.getContents()) + .filter(item -> item != null && item.isSimilar(required)) + .mapToInt(ItemStack::getAmount).sum(); } private boolean giveReward(Player player, Challenge challenge) { @@ -475,7 +452,7 @@ private List getRanksForPage(int page, List ranksOnPage) { int i = 1; for (Iterator it = ranksOnPage.iterator(); it.hasNext(); i++) { it.next(); - int rowsInRanks = calculateRows(allRanks.subList(0,i)); + int rowsInRanks = calculateRows(allRanks.subList(0, i)); if (rowsToSkip <= 0 || ((rowsToSkip - rowsInRanks) < 0)) { return ranksOnPage; } @@ -551,10 +528,8 @@ public int populateChallengeRank(Inventory menu, final Rank rank, int location, } if (locked != null) { currentChallengeItem.setType(locked.getType()); - currentChallengeItem.setDurability(locked.getDurability()); } else if (lockedItem != null) { currentChallengeItem.setType(lockedItem.getType()); - currentChallengeItem.setDurability(lockedItem.getDurability()); } } else { lores = currentChallengeItem.getItemMeta().getLore(); @@ -642,10 +617,9 @@ public boolean isIslandSharing() { @EventHandler public void onMemberJoinedEvent(MemberJoinedEvent e) { - if (!completionLogic.isIslandSharing() || !(e.getPlayerInfo() instanceof PlayerInfo)) { + if (!completionLogic.isIslandSharing() || !(e.getPlayerInfo() instanceof PlayerInfo playerInfo)) { return; } - PlayerInfo playerInfo = (PlayerInfo) e.getPlayerInfo(); Map completions = completionLogic.getIslandChallenges(e.getIslandInfo().getName()); List permissions = new ArrayList<>(); for (Map.Entry entry : completions.entrySet()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java index 62f7280db..7ee0bc1f5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java @@ -32,8 +32,8 @@ public Reward(String rewardText, List itemReward, public List getItemReward() { List copy = new ArrayList<>(); for (ItemStackUtil.ItemProbability e : itemReward) { - if (RND.nextDouble() < e.getProbability()) { - copy.add(e.getItem().clone()); + if (RND.nextDouble() < e.probability()) { + copy.add(e.item().clone()); } } return copy; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index fe8790c25..720460e9e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -19,7 +19,7 @@ import us.talabrek.ultimateskyblock.command.admin.ImportCommand; import us.talabrek.ultimateskyblock.command.admin.JobsCommand; import us.talabrek.ultimateskyblock.command.admin.LanguageCommand; -import us.talabrek.ultimateskyblock.command.admin.NBTCommand; +import us.talabrek.ultimateskyblock.command.admin.ItemInfoCommand; import us.talabrek.ultimateskyblock.command.admin.OrphanCommand; import us.talabrek.ultimateskyblock.command.admin.PerkCommand; import us.talabrek.ultimateskyblock.command.admin.ProtectAllCommand; @@ -85,7 +85,7 @@ protected void doExecute(CommandSender sender, PlayerInfo playerInfo) { add(new DocumentCommand(plugin, "doc", "usb.admin.doc")); add(new RegionCommand(plugin, animationHandler)); add(new SetMaintenanceCommand(plugin)); - add(new NBTCommand()); + add(new ItemInfoCommand()); add(new ProtectAllCommand(plugin)); add(new ChunkCommand(plugin)); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java index a4133cb9b..293a544cf 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java @@ -4,9 +4,9 @@ import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -31,7 +31,7 @@ public ConfigCommand(uSkyBlock plugin) { @Override public boolean execute(CommandSender commandSender, String alias, Map map, String... args) { if (args.length > 0) { - YmlConfiguration config = FileUtil.getYmlConfiguration(map.get("config") + ".yml"); + FileConfiguration config = FileUtil.getYmlConfiguration(map.get("config") + ".yml"); String searchTerms = String.join(" ", args); List results = config.getKeys(true).stream() .filter(f -> f.contains(searchTerms)) @@ -47,7 +47,7 @@ public boolean execute(CommandSender commandSender, String alias, Map"); } else if (config.isDouble(key)) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java new file mode 100644 index 000000000..71768a8d7 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java @@ -0,0 +1,42 @@ +package us.talabrek.ultimateskyblock.command.admin; + +import dk.lockfuglsang.minecraft.command.AbstractCommand; +import dk.lockfuglsang.minecraft.command.CompositeCommand; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +/** + * Command for querying items reg. NBT stuff + */ +public class ItemInfoCommand extends CompositeCommand { + public ItemInfoCommand() { + super("iteminfo", "usb.admin.iteminfo", marktr("advanced info about items")); + add(new AbstractCommand("info|i", marktr("shows the component format for the currently held item")) { + @Override + public boolean execute(CommandSender sender, String alias, Map data, String... args) { + if (sender instanceof Player player) { + ItemStack itemStack = player.getInventory().getItemInMainHand(); + if (!itemStack.getType().isItem()) { + player.sendMessage(tr("\u00a7cNo item in hand!")); + return true; + } + String[] msgs = new String[]{ + tr("\u00a7eInfo for \u00a79{0}", ItemStackUtil.asString(itemStack)), + tr("\u00a77 - name: \u00a79{0}", ItemStackUtil.getItemName(itemStack)) + }; + player.sendMessage(msgs); + return true; + } + sender.sendMessage(tr("\u00a7eCan only be executed as a player")); + return false; + } + }); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java deleted file mode 100644 index 82e46a32f..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/NBTCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -package us.talabrek.ultimateskyblock.command.admin; - -import dk.lockfuglsang.minecraft.command.AbstractCommand; -import dk.lockfuglsang.minecraft.command.CompositeCommand; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; - -import java.util.Map; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -/** - * Command for querying items reg. NBT stuff - */ -public class NBTCommand extends CompositeCommand { - public NBTCommand() { - super("nbt", "usb.admin.nbt", marktr("advanced info about NBT stuff")); - add(new AbstractCommand("info|i", marktr("shows the NBTTag for the currently held item")) { - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (sender instanceof Player) { - Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInMainHand(); - if (!itemStack.getType().isItem()) { - player.sendMessage(tr("\u00a7cNo item in hand!")); - return true; - } - String[] msgs = new String[]{ - tr("\u00a7eInfo for \u00a79{0}", ItemStackUtil.asString(itemStack)), - tr("\u00a77 - name: \u00a79{0}", ItemStackUtil.getItemName(itemStack)), - tr("\u00a77 - nbttag: \u00a79{0}", NBTUtil.getNBTTag(itemStack)) - }; - player.sendMessage(msgs); - return true; - } - sender.sendMessage(tr("\u00a7eCan only be executed as a player")); - return false; - } - }); - add(new AbstractCommand("set|s", null, "nbttag", marktr("sets the NBTTag on the currently held item")) { - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (sender instanceof Player && args.length > 0) { - Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInMainHand(); - if (!itemStack.getType() .isItem()) { - player.sendMessage(tr("\u00a7cNo item in hand!")); - return true; - } - String nbtTag = join(args); - itemStack = NBTUtil.setNBTTag(itemStack, nbtTag); - player.getInventory().setItemInMainHand(itemStack); - player.sendMessage(tr("\u00a7eSet \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); - return true; - } - sender.sendMessage(tr("\u00a7eCan only be executed as a player")); - return false; - } - }); - add(new AbstractCommand("add|a", null, "nbttag", marktr("adds the NBTTag on the currently held item")) { - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (sender instanceof Player && args.length > 0) { - Player player = (Player) sender; - ItemStack itemStack = player.getInventory().getItemInMainHand(); - if (!itemStack.getType().isItem()) { - player.sendMessage(tr("\u00a7cNo item in hand!")); - return true; - } - String nbtTag = join(args); - itemStack = NBTUtil.addNBTTag(itemStack, nbtTag); - player.getInventory().setItemInMainHand(itemStack); - player.sendMessage(tr("\u00a7eAdded \u00a79{0}\u00a7e to \u00a7c{1}", nbtTag, itemStack)); - return true; - } - sender.sendMessage(tr("\u00a7eCan only be executed as a player")); - return false; - } - }); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java index 2d8708507..a02664923 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java @@ -60,7 +60,7 @@ public NetherTerraFormEvents(uSkyBlock plugin) { ConfigurationSection config = plugin.getConfig().getConfigurationSection("nether.terraform"); if (config != null) { for (String key : config.getKeys(false)) { - Material mat = Material.getMaterial(key); + Material mat = Material.matchMaterial(key); if (mat != null) { terraFormMap.put(mat, MaterialUtil.createProbabilityList(config.getStringList(key))); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java index 71a05ed7a..9feb9fbc0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java @@ -49,24 +49,24 @@ public static void loadIslandSchematic(final File file, final Location origin, P } boolean noAir = false; BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(origin.getWorld()), -1); - editSession.setSideEffectApplier(SideEffectSet.none()); - ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(origin); - if (region != null) { - editSession.setMask(new RegionMask(getRegion(origin.getWorld(), region))); - } - try { + + try (EditSession editSession = WorldEdit.getInstance().newEditSessionBuilder() + .world(new BukkitWorld(origin.getWorld())).build()) { + editSession.setSideEffectApplier(SideEffectSet.none()); + ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(origin); + if (region != null) { + editSession.setMask(new RegionMask(getRegion(origin.getWorld(), region))); + } ClipboardFormat clipboardFormat = ClipboardFormats.findByFile(file); try (InputStream in = new FileInputStream(file)) { Clipboard clipboard = clipboardFormat.getReader(in).read(); Operation operation = new ClipboardHolder(clipboard) - .createPaste(editSession) - .to(to) - .ignoreAirBlocks(noAir) - .build(); + .createPaste(editSession) + .to(to) + .ignoreAirBlocks(noAir) + .build(); Operations.completeBlindly(operation); } - editSession.flushSession(); } catch (IOException e) { log.log(Level.INFO, "Unable to paste schematic " + file, e); } @@ -200,23 +200,23 @@ public static Set getBorderRegions(Region region) { // min < minChunk < maxChunk < max if (minModX != 0) { borders.add(new CuboidRegion(region.getWorld(), - BlockVector3.at(minX, minY, minZ), - BlockVector3.at(minChunkX - 1, maxY, maxZ))); + BlockVector3.at(minX, minY, minZ), + BlockVector3.at(minChunkX - 1, maxY, maxZ))); } if (maxModZ != 15 && maxModZ != -1) { borders.add(new CuboidRegion(region.getWorld(), - BlockVector3.at(minChunkX, minY, maxChunkZ + 1), - BlockVector3.at(maxChunkX, maxY, maxZ))); + BlockVector3.at(minChunkX, minY, maxChunkZ + 1), + BlockVector3.at(maxChunkX, maxY, maxZ))); } if (maxModX != 15 && maxModX != -1) { borders.add(new CuboidRegion(region.getWorld(), - BlockVector3.at(maxChunkX + 1, minY, minZ), - BlockVector3.at(maxX, maxY, maxZ))); + BlockVector3.at(maxChunkX + 1, minY, minZ), + BlockVector3.at(maxX, maxY, maxZ))); } if (minModZ != 0) { borders.add(new CuboidRegion(region.getWorld(), - BlockVector3.at(minChunkX, minY, minZ), - BlockVector3.at(maxChunkX, maxY, minChunkZ - 1))); + BlockVector3.at(minChunkX, minY, minZ), + BlockVector3.at(maxChunkX, maxY, minChunkZ - 1))); } return borders; } @@ -233,7 +233,7 @@ public static void clearIsland(@NotNull final World islandWorld, @NotNull final Runnable onCompletion = () -> { long diff = System.currentTimeMillis() - t; LogUtil.log(Level.INFO, String.format("Cleared island on %s in %d.%03d seconds", - islandWorld.getName(), (diff / 1000), (diff % 1000))); + islandWorld.getName(), (diff / 1000), (diff % 1000))); if (afterDeletion != null) { afterDeletion.run(); } @@ -264,7 +264,7 @@ public static Region getRegion(World skyWorld, ProtectedRegion region) { public static boolean isOuterPossible() { return Settings.island_distance >= Settings.island_protectionRange && - ((Settings.island_distance % 32) == 0 || (Settings.island_distance - Settings.island_protectionRange) > 32); + ((Settings.island_distance % 32) == 0 || (Settings.island_distance - Settings.island_protectionRange) > 32); } public static void loadRegion(Location location) { @@ -296,6 +296,6 @@ public static void refreshRegion(Location location) { } public static EditSession createEditSession(com.sk89q.worldedit.world.World bukkitWorld, int maxBlocks) { - return WorldEdit.getInstance().getEditSessionFactory().getEditSession(bukkitWorld, maxBlocks); + return WorldEdit.getInstance().newEditSessionBuilder().world(bukkitWorld).maxBlocks(maxBlocks).build(); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java index 9466aaeb7..8c28a5f98 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java @@ -40,14 +40,14 @@ public WorldEditClear(uSkyBlock plugin, World world, Set borderRegions, private List createRegions(Set borderRegions) { List list = new ArrayList<>(); for (Region region : borderRegions) { - if (region.getLength() > region.getWidth()) { + if (region.getLength() > region.getWidth()) { // Z-axis BlockVector3 min = region.getMinimumPoint(); BlockVector3 max = region.getMaximumPoint(); BlockVector3 pt = BlockVector3.at(max.getX(), max.getY(), max.getZ()); pt = pt.withZ(min.getBlockZ()); while (pt.getBlockZ() < max.getBlockZ()) { - int dz = Math.min(INCREMENT, Math.abs(max.getBlockZ()-pt.getBlockZ())); + int dz = Math.min(INCREMENT, Math.abs(max.getBlockZ() - pt.getBlockZ())); pt = pt.add(0, 0, dz); list.add(new CuboidRegion(min, pt)); min = min.withZ(pt.getZ()); @@ -59,7 +59,7 @@ private List createRegions(Set borderRegions) { BlockVector3 pt = BlockVector3.at(max.getX(), max.getY(), max.getZ()); pt = pt.withX(min.getBlockX()); while (pt.getBlockX() < max.getBlockX()) { - int dx = Math.min(INCREMENT, Math.abs(max.getBlockX()-pt.getBlockX())); + int dx = Math.min(INCREMENT, Math.abs(max.getBlockX() - pt.getBlockX())); pt = pt.add(dx, 0, 0); list.add(new CuboidRegion(min, pt)); min = min.withX(pt.getX()); @@ -73,16 +73,14 @@ private List createRegions(Set borderRegions) { protected boolean execute() { while (!regions.isEmpty()) { final Region region = regions.remove(0); - final EditSession editSession = WorldEditHandler.createEditSession( - new BukkitWorld(world), (int) region.getVolume()); - editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); - editSession.setSideEffectApplier(SideEffectSet.defaults()); - try { + try (EditSession editSession = WorldEditHandler.createEditSession( + new BukkitWorld(world), (int) region.getVolume())) { + editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); + editSession.setSideEffectApplier(SideEffectSet.defaults()); editSession.setBlocks(region, BlockTypes.AIR.getDefaultState()); } catch (MaxChangedBlocksException e) { log.log(Level.INFO, "Warning: we got MaxChangedBlocks from WE, please increase it!"); } - editSession.flushSession(); if (!tick()) { break; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverter.java new file mode 100644 index 000000000..18789afa5 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverter.java @@ -0,0 +1,341 @@ +package us.talabrek.ultimateskyblock.imports; + +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +public class ItemComponentConverter { + + private final Logger logger; + + public ItemComponentConverter(Logger logger) { + this.logger = logger; + } + + public void checkAndDoImport(File directory) { + var configFile = new File(directory, "config.yml"); + if (configFile.exists() && YamlConfiguration.loadConfiguration(configFile).getInt("version") <= 108) { + importFile(configFile); + } + var challengesFile = new File(directory, "challenges.yml"); + if (challengesFile.exists() && YamlConfiguration.loadConfiguration(challengesFile).getInt("version") <= 106) { + importFile(challengesFile); + } + } + + public void importFile(File file) { + Path configFile = file.toPath(); + try { + Files.copy(configFile, configFile.getParent().resolve(configFile.getFileName() + ".old")); + + FileConfiguration config = new YamlConfiguration(); + config.load(file); + + if (file.getName().equals("challenges.yml")) { + convertChallenges(config); + } else if (file.getName().equals("config.yml")) { + convertConfig(config); + } + + config.save(file); + } catch (Exception e) { + throw new RuntimeException("An error occurred while attempting to convert file " + file, e); + } + } + + private void convertConfig(FileConfiguration config) { + var oldVersion = config.getInt("version"); + if (oldVersion > 108) { + logger.warning("Expecting config.yml version 108, but found " + oldVersion + " instead. Skipping conversion."); + return; + } + + logger.info("Converting config.yml to new item component format for Minecraft 1.20.5 and later."); + + for (var path : config.getKeys(true)) { + if (path.endsWith("chestItems") + || (path.contains(".extraPermissions.") && config.isList(path)) + || path.endsWith("extraItems") + ) { + var oldSpecifications = config.getStringList(path); + var results = oldSpecifications.stream().map(spec -> convertItemReward(spec, path)).toList(); + var newSpecifications = results.stream().map(pair -> pair.item).toList(); + var newComments = results.stream().map(pair -> pair.comment).filter(Objects::nonNull).toList(); + if (!newSpecifications.isEmpty()) { + config.set(path, newSpecifications); + } + if (!newComments.isEmpty()) { + List comments = new ArrayList<>(config.getComments(path)); + comments.addAll(newComments); + config.setComments(path, comments); + } + } else if (path.endsWith("displayItem") || path.endsWith("tool")) { + var oldSpecification = config.getString(path); + var pair = convertDisplayItem(oldSpecification, path); + config.set(path, pair.item); + if (pair.comment != null) { + List comments = new ArrayList<>(config.getComments(path)); + comments.add(pair.comment); + config.setComments(path, comments); + } + } + } + + // fix old grass block in default config. We don't fix all of them, as GRASS has referred to both grass_block + // and short_grass in the past, and we cannot determine what the user meant. They should fix it manually. + List giantBonus = config.getStringList("options.island.extraPermissions.giantbonus"); + if (giantBonus.contains("grass:1")) { + var index = giantBonus.indexOf("grass:1"); + giantBonus.set(index, "grass_block:1"); + config.set("options.island.extraPermissions.giantbonus", giantBonus); + } + + config.set("version", 109); + } + + private void convertChallenges(FileConfiguration config) throws Exception { + var oldVersion = config.getInt("version"); + if (oldVersion > 106) { + logger.warning("Expecting challanges.yml version 106, but found " + oldVersion + " instead. Skipping conversion."); + return; + } + logger.info("Converting challenges.yml to new item component format for Minecraft 1.20.5 and later."); + + convertChallengeItems(config); + updateHeaderAndVersion(config); + } + + + private void convertChallengeItems(FileConfiguration config) { + for (var path : config.getKeys(true)) { + if (path.endsWith("displayItem") || path.endsWith("lockedDisplayItem")) { + var oldSpecification = config.getString(path); + var pair = convertDisplayItem(oldSpecification, path); + config.set(path, pair.item); + if (pair.comment != null) { + List comments = new ArrayList<>(config.getComments(path)); + comments.add(pair.comment); + config.setComments(path, comments); + } + } else if (path.endsWith(".items")) { + var oldSpecifications = config.getStringList(path); + var results = oldSpecifications.stream().map(spec -> convertItemReward(spec, path)).toList(); + var newSpecifications = results.stream().map(pair -> pair.item).toList(); + var newComments = results.stream().map(pair -> pair.comment).filter(Objects::nonNull).toList(); + config.set(path, newSpecifications); + if (!newComments.isEmpty()) { + List comments = new ArrayList<>(config.getComments(path)); + comments.addAll(newComments); + config.setComments(path, comments); + } + } else if (path.endsWith("requiredItems")) { + var oldSpecifications = config.getStringList(path); + var results = oldSpecifications.stream().map(spec -> convertItemRequirement(spec, path)).toList(); + var newSpecifications = results.stream().map(pair -> pair.item).toList(); + var newComments = results.stream().map(pair -> pair.comment).filter(Objects::nonNull).toList(); + config.set(path, newSpecifications); + if (!newComments.isEmpty()) { + List comments = new ArrayList<>(config.getComments(path)); + comments.addAll(newComments); + config.setComments(path, comments); + } + } + } + } + + private void updateHeaderAndVersion(FileConfiguration config) throws Exception { + config.set("version", 107); + // Add a comment to the version number with the latest changes. This replaces the old explanation, + // which is moved to the header where it is more convenient and stable. + config.setComments("version", Arrays.asList( + null, + "This file has been updated to version 107. Please check the changes made in this version.", + "Changes in this version:", + " - Items are now specified in the new component format.", + " - Refer to the config header for the new format.", + " - NBT tags are not automatically converted. They have been moved to the comments, please check them manually.", + " You can use the following converter to convert the old item specifications to the new format:", + " https://docs.papermc.io/misc/tools/item-command-converter", + "DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen!" + )); + + // Add the new header with explanations and usage instructions + var defaultConfig = new YamlConfiguration(); + try (var reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull( + getClass().getClassLoader().getResourceAsStream("challenges.yml")), StandardCharsets.UTF_8))) { + defaultConfig.load(reader); + } + config.options().setHeader(defaultConfig.options().getHeader()); + } + + private static final Pattern DISPLAY_PATTERN = Pattern.compile("(?[0-9A-Z_]+)(:(?[0-9]+))?\\s*(?\\{.*})?"); + private static final Pattern REWARD_PATTERN = Pattern.compile("(\\{p=(?0\\.[0-9]+)})?(?[0-9A-Z_]+)(:(?[0-9]+))?:(?[0-9]+)\\s*(?\\{.*})?"); + public static final Pattern REQUIREMENT_PATTERN = Pattern.compile("(?(?[0-9A-Z_]+)(:(?[0-9]+))?(?\\{.*})?):(?[0-9]+)(;(?[-+*^])(?[0-9]+))?"); + + private SpecificationCommentPair convertDisplayItem(String oldSpecification, String path) { + var matcher = DISPLAY_PATTERN.matcher(oldSpecification); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid display item specification at path " + path); + } + var itemType = fixMaterial(matcher.group("id")); + var type = Material.matchMaterial(itemType); + if (type != null) { + itemType = type.getKey().getKey(); + } else { + itemType = itemType.toLowerCase(Locale.ROOT); + logger.warning("Unknown material " + itemType + " in display item specification at " + path); + } + var sub = matcher.group("sub"); + if (sub != null) { + logger.warning("Old pre-1.13 item specification at " + path + " uses subtypes, which are no longer supported."); + } + var meta = matcher.group("meta"); + if (meta != null && meta.trim().isEmpty()) { + meta = null; + } + String comment = null; + if (meta != null) { + logger.warning("Some items contain NBT tags, which are not automatically converted. Please check the entry at " + path + " manually."); + comment = itemType + meta; + } + + var newSpecification = new StringBuilder(); + newSpecification.append(itemType); + if (meta != null) { + newSpecification.append("[]"); + } + + return new SpecificationCommentPair(newSpecification.toString(), comment); + } + + private SpecificationCommentPair convertItemReward(String oldSpecification, String path) { + var matcher = REWARD_PATTERN.matcher(oldSpecification); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid reward item specification at path " + path); + } + var probability = matcher.group("prob"); + + var itemType = fixMaterial(matcher.group("id")); + var type = Material.matchMaterial(itemType); + if (type != null) { + itemType = type.getKey().getKey(); + } else { + itemType = itemType.toLowerCase(Locale.ROOT); + logger.warning("Unknown material " + itemType + " in reward item specification at " + path); + } + var sub = matcher.group("sub"); + if (sub != null) { + logger.warning("Old pre-1.13 item specification at " + path + " uses subtypes, which are no longer supported."); + } + var amount = matcher.group("amount"); + var meta = matcher.group("meta"); + if (meta != null && meta.trim().isEmpty()) { + meta = null; + } + String comment = null; + String convertedMeta = convertDefaultItemMeta(meta); + + if (meta != null && convertedMeta == null) { + logger.warning("Some items contain NBT tags, which are not automatically converted. Please check the entry at " + path + " manually."); + comment = itemType + meta; + } + + var newSpecification = new StringBuilder(); + if (probability != null) { + newSpecification.append("{p=").append(probability).append("}"); + } + newSpecification.append(itemType); + if (convertedMeta != null) { + newSpecification.append(convertedMeta); + } else if (meta != null) { + newSpecification.append("[]"); + } + + newSpecification.append(":").append(amount); + + return new SpecificationCommentPair(newSpecification.toString(), comment); + } + + private SpecificationCommentPair convertItemRequirement(String oldSpecification, String path) { + var matcher = REQUIREMENT_PATTERN.matcher(oldSpecification); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid requirement item specification at path " + path + ": " + oldSpecification); + } + + var itemType = fixMaterial(matcher.group("type")); + var type = Material.matchMaterial(itemType); + if (type != null) { + itemType = type.getKey().getKey(); + } else { + itemType = itemType.toLowerCase(Locale.ROOT); + logger.warning("Unknown material " + itemType + " in reward item specification at " + path); + } + var sub = matcher.group("subtype"); + if (sub != null) { + logger.warning("Old pre-1.13 item specification at " + path + " uses subtypes, which are no longer supported."); + } + var amount = matcher.group("amount"); + var meta = matcher.group("meta"); + if (meta != null && meta.trim().isEmpty()) { + meta = null; + } + String comment = null; + if (meta != null) { + logger.warning("Some items contain NBT tags, which are not automatically converted. Please check the entry at " + path + " manually."); + comment = itemType + meta; + } + + var op = matcher.group("op"); + var inc = matcher.group("inc"); + + var newSpecification = new StringBuilder(); + newSpecification.append(itemType); + if (meta != null) { + newSpecification.append("[]"); + } + newSpecification.append(":").append(amount); + if (op != null) { + newSpecification.append(";").append(op).append(inc); + } + + return new SpecificationCommentPair(newSpecification.toString(), comment); + } + + private static final Map DEFAULT_ITEM_META_CONVERSION = Map.of( + "{Enchantments:[{id:\"minecraft:infinity\",lvl:1},{id:\"minecraft:unbreaking\",lvl:3}]}", "[enchantments={levels:{infinity:1,unbreaking:3}}]", + "{Enchantments:[{id:\"minecraft:infinity\",lvl:1},{id:\"minecraft:unbreaking\",lvl:3},{id:\"minecraft:power\",lvl:5}]}", "[enchantments={levels:{infinity:1,power:5,unbreaking:3}}]", + "{Enchantments:[{id:\"minecraft:sharpness\",lvl:5},{id:\"minecraft:unbreaking\",lvl:3},{id:\"minecraft:fire\",lvl:1}]}", "[enchantments={levels:{fire_aspect:1,sharpness:5,unbreaking:3}}]", + "{Enchantments:[{id:\"minecraft:feather_falling\",lvl:4},{id:\"minecraft:protection\",lvl:4},{id:\"minecraft:blast_protection\",lvl:4}]}", "[enchantments={levels:{blast_protection:4,feather_falling:4,protection:4}}]" + ); + + private String convertDefaultItemMeta(String oldMeta) { + if (oldMeta == null) { + return null; + } + return DEFAULT_ITEM_META_CONVERSION.get(oldMeta); + } + + private static final Map MATERIAL_UPDATES = Map.of( + "SIGN", "OAK_SIGN", + "SAPLING", "OAK_SAPLING" + ); + + private String fixMaterial(String material) { + return MATERIAL_UPDATES.getOrDefault(material, material); + } + + private record SpecificationCommentPair(@NotNull String item, @Nullable String comment) { + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java index cfb00d6e0..b8b744e86 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java @@ -13,21 +13,17 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; public class BlockLimitLogic { - public enum CanPlace { YES, UNCERTAIN, NO}; + public enum CanPlace {YES, UNCERTAIN, NO} - private static final Logger log = Logger.getLogger(BlockLimitLogic.class.getName()); - private uSkyBlock plugin; - private Map blockLimits = new HashMap<>(); + private final Map blockLimits = new HashMap<>(); // TODO: R4zorax - 13-07-2018: Persist this somehow - and use a guavacache - private Map> blockCounts = new HashMap<>(); + private final Map> blockCounts = new HashMap<>(); private final boolean limitsEnabled; public BlockLimitLogic(uSkyBlock plugin) { - this.plugin = plugin; FileConfiguration config = plugin.getConfig(); limitsEnabled = config.getBoolean("options.island.block-limits.enabled", false); if (limitsEnabled) { @@ -35,12 +31,12 @@ public BlockLimitLogic(uSkyBlock plugin) { Set keys = section.getKeys(false); keys.remove("enabled"); for (String key : keys) { - Material material = Material.getMaterial(key.toUpperCase()); + Material material = Material.matchMaterial(key.toUpperCase()); int limit = section.getInt(key, -1); if (material != null && limit >= 0) { blockLimits.put(material, limit); } else { - log.warning("Unknown material " + key + " supplied for block-limit, or value not an integer"); + plugin.getLogger().warning("Unknown material " + key + " supplied for block-limit, or value not an integer"); } } } @@ -50,7 +46,7 @@ public int getLimit(Material type) { return blockLimits.getOrDefault(type, Integer.MAX_VALUE); } - public Map getLimits() { + public Map getLimits() { return Collections.unmodifiableMap(blockLimits); } @@ -62,7 +58,7 @@ public void updateBlockCount(Location islandLocation, IslandScore score) { blockCounts.put(islandLocation, countMap); } - private Map asBlockCount(IslandScore score) { + private Map asBlockCount(IslandScore score) { Map countMap = new ConcurrentHashMap<>(); for (BlockScore blockScore : score.getTop()) { Material type = blockScore.getBlock().getType(); @@ -102,7 +98,7 @@ public void incBlockCount(Location islandLocation, Material type) { } Map islandCount = blockCounts.getOrDefault(islandLocation, new ConcurrentHashMap<>()); int blockCount = islandCount.getOrDefault(type, 0); - islandCount.put(type, blockCount+1); + islandCount.put(type, blockCount + 1); blockCounts.put(islandLocation, islandCount); } @@ -112,7 +108,7 @@ public void decBlockCount(Location islandLocation, Material type) { } Map islandCount = blockCounts.getOrDefault(islandLocation, new ConcurrentHashMap<>()); int blockCount = islandCount.getOrDefault(type, 0); - islandCount.put(type, blockCount-1); + islandCount.put(type, blockCount - 1); blockCounts.put(islandLocation, islandCount); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java index 1ff90c783..6bf2a727b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java @@ -9,6 +9,7 @@ import org.bukkit.block.Chest; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.Settings; @@ -129,7 +130,7 @@ public boolean setChest(@Nullable Location chestLocation, @NotNull Perk perk) { if (block.getType() == Material.CHEST) { final Chest chest = (Chest) block.getState(); final Inventory inventory = chest.getInventory(); - inventory.addItem(Settings.island_chestItems); + inventory.addItem(Settings.getIslandChestItems().toArray(new ItemStack[0])); if (Settings.island_addExtraItems) { inventory.addItem(ItemStackUtil.createItemArray(perk.getExtraItems())); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java index af27b0c5e..ef02af27a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java @@ -1,8 +1,9 @@ package us.talabrek.ultimateskyblock.island; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Location; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import us.talabrek.ultimateskyblock.Settings; @@ -24,7 +25,7 @@ public class IslandLocatorLogic { private static final Logger log = Logger.getLogger(IslandLocatorLogic.class.getName()); private final uSkyBlock plugin; private final File configFile; - private final YmlConfiguration config; + private final FileConfiguration config; private final Map reservations = new ConcurrentHashMap<>(); private Location lastIsland = null; private long reservationTimeout; @@ -32,7 +33,7 @@ public class IslandLocatorLogic { public IslandLocatorLogic(final uSkyBlock plugin) { this.plugin = plugin; this.configFile = new File(plugin.getDataFolder(), "lastIslandConfig.yml"); - this.config = new YmlConfiguration(); + this.config = new YamlConfiguration(); FileUtil.readConfig(config, configFile); // Backward compatibility if (!config.contains("options.general.lastIslandX") && plugin.getConfig().contains("options.general.lastIslandX")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java index a5448cac6..61e8ad924 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java @@ -1,17 +1,16 @@ package us.talabrek.ultimateskyblock.menu; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import us.talabrek.ultimateskyblock.util.GuiItemUtil; import java.text.MessageFormat; import java.text.ParseException; import java.util.Arrays; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.Objects; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -19,14 +18,13 @@ * Created by R4zorax on 03/10/2015. */ public class AbstractConfigMenu { - private static final Pattern UUID_PATTERN = Pattern.compile("^.*Id:\\\"(?[^\\\"]+)\\\".*"); - private YmlConfiguration menuConfig; + private final FileConfiguration menuConfig; - public AbstractConfigMenu(YmlConfiguration menuConfig) { + public AbstractConfigMenu(FileConfiguration menuConfig) { this.menuConfig = menuConfig; } - public YmlConfiguration getMenuConfig() { + public FileConfiguration getMenuConfig() { return menuConfig; } @@ -36,21 +34,8 @@ protected static void ensureCapacity(List menuList, int index) { } } - protected ItemStack createItem(Material icon, String title, List lore) { - return createItem(icon, (short) 0, title, lore); - } - - protected ItemStack createItem(Material icon, int subType, String title, List lore) { - ItemStack itemStack = new ItemStack(icon, 1, (short) (subType & 0xff)); - ItemMeta meta = itemStack.getItemMeta(); - meta.setDisplayName(title); - meta.setLore(lore); - itemStack.setItemMeta(meta); - return itemStack; - } - protected static int getIndex(int row, int col) { - return row*9 + col; + return row * 9 + col; } boolean isBlackListed(String file, String currentPath) { @@ -74,19 +59,16 @@ protected int getPage(String s) { return 1; } - protected ItemStack createItem(String item) { - if (item == null) { - return null; - } - Matcher m = UUID_PATTERN.matcher(item); - if (m.matches()) { - ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1); - Bukkit.getUnsafe().modifyItemStack(itemStack, item); - ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setDisplayName(tr(itemMeta.getDisplayName())); - itemStack.setItemMeta(itemMeta); - return itemStack; - } - return null; + protected ItemStack createItemFromComponentString(String components) { + return GuiItemUtil.createItemFromComponentString(components); + } + + protected ItemStack createItem(Material icon, String title, List lore) { + ItemStack itemStack = new ItemStack(icon, 1); + ItemMeta meta = Objects.requireNonNull(itemStack.getItemMeta()); + meta.setDisplayName(title); + meta.setLore(lore); + itemStack.setItemMeta(meta); + return itemStack; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java index c09fc5d20..ec44970dd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.menu; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; @@ -9,7 +9,7 @@ * Simple menu-less editor for boolean values. */ public class BooleanEditMenu extends AbstractConfigMenu implements EditMenu { - public BooleanEditMenu(YmlConfiguration menuConfig) { + public BooleanEditMenu(FileConfiguration menuConfig) { super(menuConfig); } @@ -21,7 +21,7 @@ public boolean onClick(InventoryClickEvent e) { @Override public Inventory createEditMenu(String configName, String path, int page) { - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); if (config.isBoolean(path)) { boolean value = config.getBoolean(path); config.set(path, !value); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java index 55922bfe2..1a34d53af 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java @@ -1,7 +1,8 @@ package us.talabrek.ultimateskyblock.menu; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -14,7 +15,7 @@ */ public class ConfigMenu { - private final YmlConfiguration menuConfig; + private final FileConfiguration menuConfig; private final uSkyBlock plugin; private final MenuItemFactory factory; private final List editMenus = new ArrayList<>(); @@ -22,7 +23,7 @@ public class ConfigMenu { public ConfigMenu(uSkyBlock plugin) { this.plugin = plugin; - menuConfig = new YmlConfiguration(); + menuConfig = new YamlConfiguration(); FileUtil.readConfig(menuConfig, getClass().getClassLoader().getResourceAsStream("configmenu.yml")); factory = new MenuItemFactory(); mainMenu = new MainConfigMenu(plugin, menuConfig, factory, editMenus); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java index 89215f265..3227860f3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java @@ -1,24 +1,22 @@ package us.talabrek.ultimateskyblock.menu; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; +import us.talabrek.ultimateskyblock.util.GuiItemUtil; + +import java.util.*; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; @@ -27,14 +25,14 @@ * Editor for integer nodes. */ public class IntegerEditMenu extends AbstractConfigMenu implements EditMenu { - private static final String DEFAULT_NUMBER_ICON = "STAINED_GLASS_PANE:11"; - private final YmlConfiguration menuConfig; + private static final Material DEFAULT_NUMBER_ICON = Material.BLUE_STAINED_GLASS_PANE; + private final FileConfiguration menuConfig; private final MenuItemFactory factory; private final EditMenu parent; private final Map increments = new LinkedHashMap<>(); - public IntegerEditMenu(YmlConfiguration menuConfig, MenuItemFactory factory, EditMenu parent) { + public IntegerEditMenu(FileConfiguration menuConfig, MenuItemFactory factory, EditMenu parent) { super(menuConfig); this.menuConfig = menuConfig; this.factory = factory; @@ -43,9 +41,10 @@ public IntegerEditMenu(YmlConfiguration menuConfig, MenuItemFactory factory, Edi if (incSection != null) { for (String inc : incSection.getKeys(false)) { int incValue = Integer.parseInt(inc, 10); - increments.put(inc, ItemStackUtil.createItemStack(incSection.getString(inc, "IRON_INGOT"), - incValue < 0 ? tr("\u00a7c{0,number,#}", incValue) : tr("\u00a7a+{0,number,#}", incValue), - null)); + String itemType = incSection.getString(inc, Material.IRON_INGOT.name()); + String displayName = incValue < 0 ? tr("\u00a7c{0,number,#}", incValue) : tr("\u00a7a+{0,number,#}", incValue); + ItemStack displayItem = GuiItemUtil.createGuiDisplayItem(itemType, displayName); + increments.put(inc, displayItem); } } } @@ -53,8 +52,8 @@ public IntegerEditMenu(YmlConfiguration menuConfig, MenuItemFactory factory, Edi @Override public boolean onClick(InventoryClickEvent event) { if (!(event.getInventory().getHolder() instanceof UltimateHolder) || - ((UltimateHolder) event.getInventory().getHolder()).getTitle() == null || - !stripFormatting(((UltimateHolder) event.getInventory().getHolder()).getTitle()).contains(stripFormatting(getTitle()))) { + ((UltimateHolder) event.getInventory().getHolder()).getTitle() == null || + !stripFormatting(((UltimateHolder) event.getInventory().getHolder()).getTitle()).contains(stripFormatting(getTitle()))) { return false; } if (event.getSlotType() != InventoryType.SlotType.CONTAINER) { @@ -72,7 +71,7 @@ public boolean onClick(InventoryClickEvent event) { ItemStack clickedItem = event.getCurrentItem(); if (slot >= getIndex(3, 0) && slot <= getIndex(3, 8)) { // increment buttons - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); int value = config.getInt(path, 0); int increment = getDisplayNameAsInt(clickedItem); if (event.getClick() == ClickType.LEFT) { @@ -83,7 +82,7 @@ public boolean onClick(InventoryClickEvent event) { config.set(path, value); config.set("dirty", true); } - if (slot != getIndex(5,0)) { + if (slot != getIndex(5, 0)) { player.openInventory(createEditMenu(configName, path, page)); } else { player.openInventory(parent.createEditMenu(configName, path, page)); @@ -94,8 +93,9 @@ public boolean onClick(InventoryClickEvent event) { private int getDisplayNameAsInt(ItemStack clickedItem) { int number = 0; try { - number = Integer.parseInt(stripFormatting(clickedItem.getItemMeta().getDisplayName()).replaceAll("[^0-9\\-]+", ""), 10); - } catch (NumberFormatException ex) {} + number = Integer.parseInt(stripFormatting(clickedItem.getItemMeta().getDisplayName()).replaceAll("[^0-9\\-]+", ""), 10); + } catch (NumberFormatException ex) { + } return number; } @@ -121,14 +121,14 @@ private int getDisplayNameAsInt(ItemStack clickedItem) { */ @Override public Inventory createEditMenu(String configName, String path, int page) { - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); if (!config.isInt(path)) { return null; } int value = config.getInt(path, 0); Inventory menu = Bukkit.createInventory(new UltimateHolder(null, getTitle(), MenuType.CONFIG), 6 * 9, getTitle()); menu.setMaxStackSize(MenuItemFactory.MAX_INT_VALUE); - ItemStack frame = createItem(Material.BLACK_STAINED_GLASS_PANE, 0, null, null); + ItemStack frame = createItem(Material.BLACK_STAINED_GLASS_PANE, null, null); for (int i = 0; i < 27; i++) { menu.setItem(i, frame); } @@ -136,19 +136,15 @@ public Inventory createEditMenu(String configName, String path, int page) { int col = 7; do { int tenValue = nvalue % 10; - String specificIcon = menuConfig.getString("integer-menu.number-items." + tenValue, null); - ItemStack numberItem = specificIcon != null ? ItemStackUtil.createItemStack(specificIcon) : ItemStackUtil.createItemStack(DEFAULT_NUMBER_ICON); - ItemStackUtil.Builder builder = ItemStackUtil.builder(numberItem); - if (specificIcon == null) { - builder.amount(tenValue); - } - builder.displayName(value < 0 ? tr("\u00a7c{0,number,#}", value) : tr("\u00a7a{0,number,#}", value)); - menu.setItem(getIndex(1, col), builder.build()); + String itemType = menuConfig.getString("integer-menu.number-items." + tenValue, DEFAULT_NUMBER_ICON.name()); + String displayName = value < 0 ? tr("\u00a7c{0,number,#}", value) : tr("\u00a7a{0,number,#}", value); + ItemStack displayItem = GuiItemUtil.createGuiDisplayItem(itemType, displayName); + menu.setItem(getIndex(1, col), displayItem); nvalue = (nvalue - tenValue) / 10; col--; } while (nvalue != 0 && col > 0); if (value < 0) { - menu.setItem(getIndex(1, col), createItem(Material.RED_CARPET, 0, factory.INT + value, null)); + menu.setItem(getIndex(1, col), createItem(Material.RED_CARPET, MenuItemFactory.INT + value, null)); } ItemStack valueItem = factory.createIntegerItem(value, path, config, false); List lore = valueItem.getItemMeta().getLore(); @@ -160,15 +156,15 @@ public Inventory createEditMenu(String configName, String path, int page) { } int incValue = getDisplayNameAsInt(inc); ItemStack icon = ItemStackUtil.builder(inc) - .lore(tr("&aLeft:&7 Increment with {0}", inc.getItemMeta().getDisplayName())) - .lore(tr("&cRight-Click:&7 Set to {0}", incValue)) - .lore(lore) - .build(); + .lore(tr("&aLeft:&7 Increment with {0}", inc.getItemMeta().getDisplayName())) + .lore(tr("&cRight-Click:&7 Set to {0}", incValue)) + .lore(lore) + .build(); menu.setItem(getIndex(3, col), icon); col++; } menu.setItem(getIndex(5, 0), createItem(Material.OAK_DOOR, "\u00a79" + tr("Return"), - Arrays.asList(configName, path, tr("\u00a77Page {0}", page)))); + Arrays.asList(configName, path, tr("\u00a77Page {0}", page)))); return menu; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java index 419397ef5..ce7c07569 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java @@ -1,10 +1,11 @@ package us.talabrek.ultimateskyblock.menu; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; @@ -37,7 +38,7 @@ public class MainConfigMenu extends AbstractConfigMenu implements EditMenu { private final MenuItemFactory factory; private final List editMenus; - public MainConfigMenu(uSkyBlock plugin, YmlConfiguration menuConfig, MenuItemFactory factory, List editMenus) { + public MainConfigMenu(uSkyBlock plugin, FileConfiguration menuConfig, MenuItemFactory factory, List editMenus) { super(menuConfig); this.plugin = plugin; this.factory = factory; @@ -135,7 +136,7 @@ private void saveConfig(final Player player, final String configName, final int @Override public void run() { try { - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); config.set("dirty", null); config.save(new File(plugin.getDataFolder(), configName)); plugin.sync(new Runnable() { @@ -155,7 +156,7 @@ public void run() { } private Inventory createFileMenu(String filename, int page) { - YmlConfiguration config = FileUtil.getYmlConfiguration(filename); + FileConfiguration config = FileUtil.getYmlConfiguration(filename); int row = 0; int col = 1; ArrayList menuList = new ArrayList<>(54); @@ -268,16 +269,16 @@ public Inventory createEditMenu(String configName, String path, int page) { return createFileMenu(configName, page); } - private int addSection(ArrayList menuList, ConfigurationSection sec, int row, int col, YmlConfiguration config, String filename) { + private int addSection(ArrayList menuList, ConfigurationSection sec, int row, int col, FileConfiguration config, String filename) { if (isBlackListed(filename, sec.getCurrentPath())) { return row; } ItemStack item = new ItemStack(Material.PAPER, 1); ItemMeta meta = item.getItemMeta(); meta.setDisplayName("\u00a77\u00a7o" + sec.getName()); - String comment = config.getComment(sec.getCurrentPath()); - if (comment != null) { - meta.setLore(wordWrap(comment.replaceAll("\n", " "), 20, 20)); + List comments = config.getComments(sec.getCurrentPath()); + if (!comments.isEmpty()) { + meta.setLore(wordWrap(String.join(" ", comments), 20, 20)); } item.setItemMeta(meta); int index = getIndex(row, col); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java index 2bd9ef489..a129c0096 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.menu; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -22,25 +22,25 @@ public class MenuItemFactory { public static final int MAX_INT_VALUE = 64; public static final String READONLY = "\u00a77"; - public ItemStack createStringItem(String value, String path, YmlConfiguration config, boolean readonly) { + public ItemStack createStringItem(String value, String path, FileConfiguration config, boolean readonly) { return createLeafItem(new ItemStack(readonly ? Material.FLINT_AND_STEEL : Material.NAME_TAG, 1), value, path, config); } - public ItemStack createLeafItem(ItemStack item, String value, String path, YmlConfiguration config) { + public ItemStack createLeafItem(ItemStack item, String value, String path, FileConfiguration config) { ItemMeta meta = item.getItemMeta(); meta.setDisplayName("\u00a77\u00a7o" + path.substring(path.lastIndexOf('.')+1)); List lore = new ArrayList<>(); lore.add(STRING + value); - String comment = config.getComment(path); - if (comment != null) { - lore.addAll(wordWrap(comment.replaceAll("\n", " "), 20, 20)); + List comments = config.getComments(path); + if (!comments.isEmpty()) { + lore.addAll(wordWrap(String.join(" ", comments), 20, 20)); } meta.setLore(lore); item.setItemMeta(meta); return item; } - public ItemStack createIntegerItem(int value, String path, YmlConfiguration config, boolean readonly) { + public ItemStack createIntegerItem(int value, String path, FileConfiguration config, boolean readonly) { ItemStack item = createIntegerIcon(value, readonly); return createLeafItem( item, @@ -51,10 +51,10 @@ public ItemStack createIntegerItem(int value, String path, YmlConfiguration conf public ItemStack createIntegerIcon(int value, boolean readonly) { return Math.abs(value) <= MAX_INT_VALUE ? (readonly ? new ItemStack(Material.DETECTOR_RAIL, value) : new ItemStack(Material.RAIL, value)) - : (readonly ? new ItemStack(Material.IRON_BARS, 1, (short)1) : new ItemStack(Material.ACTIVATOR_RAIL, 1)); + : (readonly ? new ItemStack(Material.IRON_BARS, 1) : new ItemStack(Material.ACTIVATOR_RAIL, 1)); } - public ItemStack createBooleanItem(boolean value, String path, YmlConfiguration config, boolean readonly) { + public ItemStack createBooleanItem(boolean value, String path, FileConfiguration config, boolean readonly) { ItemStack icon = new ItemStack(readonly ? (value ? Material.GREEN_WOOL : Material.RED_WOOL) : (value ? Material.LIME_WOOL : Material.PINK_WOOL), 1); return createLeafItem(icon, value ? TRUE + tr("true") : FALSE + tr("false"), path, config); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index ac1e3441f..c2f9a83bf 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -20,6 +20,7 @@ import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.GuiItemUtil; import us.talabrek.ultimateskyblock.util.PlayerUtil; import java.util.ArrayList; @@ -55,90 +56,90 @@ public class SkyBlockMenu { private ItemStack invite = new ItemStack(Material.CARROT_ON_A_STICK, 1); private ItemStack kick = new ItemStack(Material.LEATHER_BOOTS, 1); private List permissionMenuItems = Arrays.asList( - new PartyPermissionMenuItem(biome, "canChangeBiome", tr("Change Biome"), - tr("change the island''s biome.")), - new PartyPermissionMenuItem(lock, "canToggleLock", tr("Toggle Island Lock"), - tr("toggle the island''s lock.")), - new PartyPermissionMenuItem(warpset, "canChangeWarp", tr("Set Island Warp"), - tr("set the island''s warp."), - tr("set the island''s warp,\nwhich allows non-group\nmembers to teleport to\nthe island.")), - new PartyPermissionMenuItem(warptoggle, "canToggleWarp", tr("Toggle Island Warp"), - tr("toggle the island''s warp."), - tr("toggle the island''s warp,\nallowing them to turn it\non or off at anytime, but\nnot set the location.")), - new PartyPermissionMenuItem(invite, "canInviteOthers", tr("Invite Players"), - tr("invite others to the island."), - tr("invite\n" + - "other players to the island if\n" + - "there is enough room for more\n" + - "members")), - new PartyPermissionMenuItem(kick, "canKickOthers", tr("Kick Players"), - tr("kick others from the island."), - tr("kick\n" + - "other players from the island,\n" + - "but they are unable to kick\n" + - "the island leader.")) + new PartyPermissionMenuItem(biome, "canChangeBiome", tr("Change Biome"), + tr("change the island''s biome.")), + new PartyPermissionMenuItem(lock, "canToggleLock", tr("Toggle Island Lock"), + tr("toggle the island''s lock.")), + new PartyPermissionMenuItem(warpset, "canChangeWarp", tr("Set Island Warp"), + tr("set the island''s warp."), + tr("set the island''s warp,\nwhich allows non-group\nmembers to teleport to\nthe island.")), + new PartyPermissionMenuItem(warptoggle, "canToggleWarp", tr("Toggle Island Warp"), + tr("toggle the island''s warp."), + tr("toggle the island''s warp,\nallowing them to turn it\non or off at anytime, but\nnot set the location.")), + new PartyPermissionMenuItem(invite, "canInviteOthers", tr("Invite Players"), + tr("invite others to the island."), + tr("invite\n" + + "other players to the island if\n" + + "there is enough room for more\n" + + "members")), + new PartyPermissionMenuItem(kick, "canKickOthers", tr("Kick Players"), + tr("kick others from the island."), + tr("kick\n" + + "other players from the island,\n" + + "but they are unable to kick\n" + + "the island leader.")) ); private List biomeMenus = Arrays.asList( - new BiomeMenuItem(new ItemStack(Material.TROPICAL_FISH, 1), - "ocean", tr("Ocean"), - tr("The ocean biome is the basic\nstarting biome for all islands.\npassive mobs like animals will\nnot spawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.SPRUCE_SAPLING, 1), - "forest", tr("Forest"), - tr("The forest biome will allow\nyour island to spawn passive.\nmobs like animals (including\nwolves). Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.SAND, 1), - "desert", tr("Desert"), - tr("The desert biome makes it so\nthat there is no rain or snow\non your island. Passive mobs\nwon't spawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.JUNGLE_SAPLING, 1), - "jungle", tr("Jungle"), - tr("The jungle biome is bright\nand colorful. Passive mobs\n(including ocelots) will\nspawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.LILY_PAD, 1), - "swamp", tr("Swampland"), - tr("The swamp biome is dark\nand dull. Passive mobs\nwill spawn normally and\nslimes have a small chance\nto spawn at night depending\non the moon phase.") - ), - new BiomeMenuItem(new ItemStack(Material.SNOW, 1), - "taiga", tr("Taiga"), - tr("The taiga biome has snow\ninstead of rain. Passive\nmobs will spawn normally\n(including wolves) and\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.RED_MUSHROOM, 1), - "mushroom_fields", tr("Mushroom"), - tr("The mushroom biome is\nbright and colorful.\nMooshrooms are the only\nmobs that will spawn.\nNo other passive or\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.NETHER_BRICK, 1), - "nether_wastes", tr("Hell"), - tr("The hell biome looks\ndark and dead. Some\nmobs from the nether will\nspawn in this biome\n(excluding ghasts and\nblazes).") - ), - new BiomeMenuItem(new ItemStack(Material.ENDER_EYE, 1), - "the_end", tr("Sky"), - tr("The sky biome gives your\nisland a special dark sky.\nOnly endermen will spawn\nin this biome.") - ), - new BiomeMenuItem(new ItemStack(Material.TALL_GRASS, 1), - "plains", tr("Plains"), - tr("The plains biome has rain\ninstead of snow. Passive\nmobs will spawn normally\n(including horses) and\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.EMERALD_ORE, 1), - "windswept_hills", tr("Extreme Hills"), - tr("The extreme hills biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.ROSE_BUSH, 1), - "flower_forest", tr("Flower Forest"), - tr("The flower forest biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.PRISMARINE_SHARD, 1), - "deep_ocean", tr("Deep Ocean"), - tr("The deep-ocean biome is an advanced\n" + - "biome. Passive mobs like animals will\n" + - "not spawn. Hostile mobs \n"+ - "(including Guardians) will\n" + - "spawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), - "snowy_plains", tr("Ice Plains"), - tr("The ice-plains biome is an advanced biome.\nMobs will spawn naturally.\nincluding polar-bears") - ) + new BiomeMenuItem(new ItemStack(Material.TROPICAL_FISH, 1), + "ocean", tr("Ocean"), + tr("The ocean biome is the basic\nstarting biome for all islands.\npassive mobs like animals will\nnot spawn. Hostile mobs will\nspawn normally.") + ), + new BiomeMenuItem(new ItemStack(Material.SPRUCE_SAPLING, 1), + "forest", tr("Forest"), + tr("The forest biome will allow\nyour island to spawn passive.\nmobs like animals (including\nwolves). Hostile mobs will\nspawn normally.") + ), + new BiomeMenuItem(new ItemStack(Material.SAND, 1), + "desert", tr("Desert"), + tr("The desert biome makes it so\nthat there is no rain or snow\non your island. Passive mobs\nwon't spawn. Hostile mobs will\nspawn normally.") + ), + new BiomeMenuItem(new ItemStack(Material.JUNGLE_SAPLING, 1), + "jungle", tr("Jungle"), + tr("The jungle biome is bright\nand colorful. Passive mobs\n(including ocelots) will\nspawn. Hostile mobs will\nspawn normally.") + ), + new BiomeMenuItem(new ItemStack(Material.LILY_PAD, 1), + "swamp", tr("Swampland"), + tr("The swamp biome is dark\nand dull. Passive mobs\nwill spawn normally and\nslimes have a small chance\nto spawn at night depending\non the moon phase.") + ), + new BiomeMenuItem(new ItemStack(Material.SNOW, 1), + "taiga", tr("Taiga"), + tr("The taiga biome has snow\ninstead of rain. Passive\nmobs will spawn normally\n(including wolves) and\nhostile mobs will spawn.") + ), + new BiomeMenuItem(new ItemStack(Material.RED_MUSHROOM, 1), + "mushroom_fields", tr("Mushroom"), + tr("The mushroom biome is\nbright and colorful.\nMooshrooms are the only\nmobs that will spawn.\nNo other passive or\nhostile mobs will spawn.") + ), + new BiomeMenuItem(new ItemStack(Material.NETHER_BRICK, 1), + "nether_wastes", tr("Hell"), + tr("The hell biome looks\ndark and dead. Some\nmobs from the nether will\nspawn in this biome\n(excluding ghasts and\nblazes).") + ), + new BiomeMenuItem(new ItemStack(Material.ENDER_EYE, 1), + "the_end", tr("Sky"), + tr("The sky biome gives your\nisland a special dark sky.\nOnly endermen will spawn\nin this biome.") + ), + new BiomeMenuItem(new ItemStack(Material.TALL_GRASS, 1), + "plains", tr("Plains"), + tr("The plains biome has rain\ninstead of snow. Passive\nmobs will spawn normally\n(including horses) and\nhostile mobs will spawn.") + ), + new BiomeMenuItem(new ItemStack(Material.EMERALD_ORE, 1), + "windswept_hills", tr("Extreme Hills"), + tr("The extreme hills biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") + ), + new BiomeMenuItem(new ItemStack(Material.ROSE_BUSH, 1), + "flower_forest", tr("Flower Forest"), + tr("The flower forest biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") + ), + new BiomeMenuItem(new ItemStack(Material.PRISMARINE_SHARD, 1), + "deep_ocean", tr("Deep Ocean"), + tr("The deep-ocean biome is an advanced\n" + + "biome. Passive mobs like animals will\n" + + "not spawn. Hostile mobs \n" + + "(including Guardians) will\n" + + "spawn normally.") + ), + new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), + "snowy_plains", tr("Ice Plains"), + tr("The ice-plains biome is an advanced biome.\nMobs will spawn naturally.\nincluding polar-bears") + ) ); public SkyBlockMenu(uSkyBlock plugin, ChallengeLogic challengeLogic) { @@ -149,7 +150,7 @@ public SkyBlockMenu(uSkyBlock plugin, ChallengeLogic challengeLogic) { public Inventory displayPartyPlayerGUI(final Player player, final String pname) { List lores = new ArrayList<>(); String emptyTitle = tr("{0} <{1}>", "", tr("Permissions")); - String title = tr("{0} <{1}>", pname.substring(0, Math.min(32-emptyTitle.length(), pname.length())), tr("Permissions")); + String title = tr("{0} <{1}>", pname.substring(0, Math.min(32 - emptyTitle.length(), pname.length())), tr("Permissions")); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 9, title); final ItemStack pHead = new ItemStack(Material.PLAYER_HEAD, 1); final SkullMeta meta3 = (SkullMeta) pHead.getItemMeta(); @@ -200,6 +201,7 @@ private void addLore(List lores, String format, String multiLine) { lores.add(format + line); } } + private void addLore(List lores, String multiLine) { addLore(lores, "", multiLine); } @@ -323,7 +325,8 @@ private void updateBiomeRadius(Player player, Inventory menu) { String radius = PlayerUtil.getMetadata(player, "biome.radius", "all"); String radiusDisplay; switch (radius) { - case "chunk": radiusDisplay = tr("\u00a72chunk"); + case "chunk": + radiusDisplay = tr("\u00a72chunk"); break; case "all": radiusDisplay = tr("\u00a7call"); @@ -403,9 +406,8 @@ private void addExtraMenus(Player player, Inventory menu) { } } // Only SIMPLE icons supported... - ItemStack item = new ItemStack(Material.matchMaterial(icon), 1); + ItemStack item = GuiItemUtil.createGuiDisplayItem(icon, title); ItemMeta meta = item.getItemMeta(); - meta.setDisplayName(title); meta.setLore(lores); item.setItemMeta(meta); menu.setItem(index, item); @@ -462,7 +464,7 @@ private boolean isExtraMenuAction(Player player, ItemStack currentItem) { public Inventory displayChallengeGUI(final Player player, int page, String playerName) { int total = challengeLogic.getTotalPages(); String title = "\u00a79" + pre("{0} ({1}/{2})", tr("Challenge Menu"), page, total); - Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), CHALLENGE_PAGESIZE+COLS_PER_ROW, title); + Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), CHALLENGE_PAGESIZE + COLS_PER_ROW, title); final PlayerInfo pi = playerName == null ? plugin.getPlayerInfo(player) : plugin.getPlayerInfo(playerName); challengeLogic.populateChallengeRank(menu, pi, page, playerName != null && player.hasPermission("usb.mod.bypassrestriction")); int[] pages = new int[9]; @@ -470,28 +472,28 @@ public Inventory displayChallengeGUI(final Player player, int page, String playe pages[8] = total; int startOffset = 2; if (page > 5) { - startOffset = (int) ((Math.round(page/2d)) - 1); - if (startOffset > total-7) { - startOffset = total-7; + startOffset = (int) ((Math.round(page / 2d)) - 1); + if (startOffset > total - 7) { + startOffset = total - 7; } } for (int i = 0; i < 7; i++) { - pages[i+1] = startOffset+i; + pages[i + 1] = startOffset + i; } for (int i = 0; i < pages.length; i++) { int p = pages[i]; if (p >= 1 && p <= total) { ItemStack pageItem; if (p == page) { - pageItem = ItemStackUtil.createItemStack("WRITABLE_BOOK", tr("\u00a77Current page"), null); + pageItem = GuiItemUtil.createGuiDisplayItem(Material.WRITABLE_BOOK, tr("\u00a77Current page")); } else { - pageItem = ItemStackUtil.createItemStack("BOOK", tr("\u00a77Page {0}", p), null); + pageItem = GuiItemUtil.createGuiDisplayItem(Material.BOOK, tr("\u00a77Page {0}", p)); } if (i == 0) { pageItem = ItemStackUtil.builder(pageItem) - .displayName(tr("\u00a77First Page")) - .lore(playerName != null ? playerName : "") - .build(); + .displayName(tr("\u00a77First Page")) + .lore(playerName != null ? playerName : "") + .build(); } else if (i == 8) { pageItem = ItemStackUtil.builder(pageItem).displayName(tr("\u00a77Last Page")).build(); } @@ -512,7 +514,7 @@ public Inventory displayIslandGUI(final Player player) { private Inventory createInitMenu(Player player) { List schemeNames = plugin.getIslandGenerator().getSchemeNames(); - int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d)*9; + int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d) * 9; String title = "\u00a79" + tr("Island Create Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); List lores = new ArrayList<>(); @@ -558,7 +560,7 @@ private Inventory createInitMenu(Player player) { addLore(lores, "\u00a7f", tr("Teleport to the spawn area.")); meta.setLore(lores); menuItem.setItemMeta(meta); - menu.setItem(menuSize-2, menuItem); + menu.setItem(menuSize - 2, menuItem); lores.clear(); menuItem = new ItemStack(Material.PLAYER_HEAD, 1); @@ -567,7 +569,7 @@ private Inventory createInitMenu(Player player) { addLore(lores, "\u00a7f", tr("Want to join another player''s\nisland instead of starting\nyour own? If another player\ninvites you to their island\nyou can click here or use\n\u00a7e/island accept\u00a7f to join them.\n\u00a7e\u00a7lClick here to accept an invite!\n\u00a7e\u00a7l(You must be invited first)")); meta2.setLore(lores); menuItem.setItemMeta(meta2); - menu.setItem(menuSize-1, menuItem); + menu.setItem(menuSize - 1, menuItem); return menu; } @@ -585,7 +587,7 @@ private int getMaxSchemeIndex(List schemeNames) { } private Inventory createMainMenu(Player player) { - String title = "\u00a79" + tr("Island Menu"); + String title = "\u00a79" + tr("Island Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 18, title); List lores = new ArrayList<>(); ItemStack menuItem = new ItemStack(Material.OAK_DOOR, 1); @@ -777,7 +779,7 @@ public void onClick(InventoryClickEvent event) { ItemMeta meta = currentItem.getItemMeta(); SkullMeta skull = meta instanceof SkullMeta ? (SkullMeta) meta : null; if (!(event.getInventory().getHolder() instanceof UltimateHolder)) - return; + return; String inventoryName = stripFormatting(((UltimateHolder) event.getInventory().getHolder()).getTitle()); int slotIndex = event.getSlot(); int menuSize = event.getInventory().getSize(); @@ -838,9 +840,9 @@ private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta met event.setCancelled(true); if (slotIndex == 0) { p.performCommand("island create"); - } else if (slotIndex == menuSize-2) { + } else if (slotIndex == menuSize - 2) { p.performCommand("island spawn"); - } else if (slotIndex == menuSize-1) { + } else if (slotIndex == menuSize - 1) { p.performCommand("island accept"); } else if (meta != null && meta.getDisplayName() != null) { String schemeName = stripFormatting(meta.getDisplayName()); @@ -922,15 +924,15 @@ private void updateLeaveMenuItemTimer(final Player p, final Inventory inventory, } private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, long millisLeft) { - if (currentItem == null || currentItem.getItemMeta() == null ||currentItem.getItemMeta().getLore() == null) { + if (currentItem == null || currentItem.getItemMeta() == null || currentItem.getItemMeta().getLore() == null) { return; } ItemMeta meta = currentItem.getItemMeta(); List lore = meta.getLore(); if (millisLeft >= 0) { - lore.set(lore.size()-1, tr("\u00a7cClick within \u00a79{0}\u00a7c to leave!", TimeUtil.millisAsString(millisLeft))); + lore.set(lore.size() - 1, tr("\u00a7cClick within \u00a79{0}\u00a7c to leave!", TimeUtil.millisAsString(millisLeft))); } else { - lore.set(lore.size()-1, tr("\u00a7cClick to leave")); + lore.set(lore.size() - 1, tr("\u00a7cClick to leave")); } meta.setLore(lore); currentItem.setItemMeta(meta); @@ -939,7 +941,7 @@ private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, lon public Inventory createRestartGUI(Player player) { List schemeNames = plugin.getIslandGenerator().getSchemeNames(); - int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d)*9; + int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d) * 9; String title = "\u00a79" + tr("Island Restart Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); List lores = new ArrayList<>(); @@ -1013,16 +1015,15 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt } ItemStack item = event.getInventory().getItem(event.getInventory().getSize() - 9); String playerName = item != null && item.hasItemMeta() && item.getItemMeta().getLore() != null - && item.getItemMeta().getLore().size() > 0 - ? item.getItemMeta().getLore().get(0) - : null; + && item.getItemMeta().getLore().size() > 0 + ? item.getItemMeta().getLore().get(0) + : null; if (playerName != null && playerName.trim().isEmpty()) { playerName = null; } // Last row is pagination if (slotIndex >= CHALLENGE_PAGESIZE && slotIndex < CHALLENGE_PAGESIZE + COLS_PER_ROW - && currentItem != null && currentItem.getType() != Material.AIR) - { + && currentItem != null && currentItem.getType() != Material.AIR) { // Pagination p.openInventory(displayChallengeGUI(p, currentItem.getAmount(), playerName)); return; @@ -1039,7 +1040,7 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt } p.openInventory(displayChallengeGUI(p, page, playerName)); } else { - if (slotIndex < (CHALLENGE_PAGESIZE/2)) { // Upper half + if (slotIndex < (CHALLENGE_PAGESIZE / 2)) { // Upper half if (page > 1) { p.openInventory(displayChallengeGUI(p, page - 1, playerName)); } else { @@ -1055,7 +1056,7 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt private boolean isAirOrLocked(ItemStack currentItem) { return currentItem != null && currentItem.getType() == Material.AIR || - currentItem != null && currentItem.getItemMeta() != null && currentItem.getItemMeta().getDisplayName().equals(tr("\u00a74\u00a7lLocked Challenge")); + currentItem != null && currentItem.getItemMeta() != null && currentItem.getItemMeta().getDisplayName().equals(tr("\u00a74\u00a7lLocked Challenge")); } private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, Player p, int slotIndex) { @@ -1076,7 +1077,7 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, } if (currentItem.getType() == Material.RED_CARPET && ix > 0) { ix--; - } else if (currentItem.getType() == Material.GREEN_CARPET && ix < radii.size()-1) { + } else if (currentItem.getType() == Material.GREEN_CARPET && ix < radii.size() - 1) { ix++; } radius = radii.get(ix); @@ -1087,7 +1088,7 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, } for (BiomeMenuItem biomeMenu : biomeMenus) { ItemStack menuIcon = biomeMenu.getIcon(); - if (currentItem.getType() == menuIcon.getType() && currentItem.getDurability() == menuIcon.getDurability()) { + if (currentItem.getType() == menuIcon.getType()) { String radius = PlayerUtil.getMetadata(p, "biome.radius", "all"); p.performCommand("island biome " + biomeMenu.getId() + " " + radius); return; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java index 3772afe08..7435deaf2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java @@ -1,21 +1,22 @@ package us.talabrek.ultimateskyblock.menu; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import us.talabrek.ultimateskyblock.player.UltimateHolder; +import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; -import us.talabrek.ultimateskyblock.player.UltimateHolder; -import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; @@ -25,28 +26,28 @@ */ public class StringEditMenu extends AbstractConfigMenu implements EditMenu { private final EditMenu parent; - private ArrayList keyboard = new ArrayList<>(); - private ArrayList capslockOverlay = new ArrayList<>(); + private final List keyboard = new ArrayList<>(); + private final List capslockOverlay = new ArrayList<>(); - private ItemStack capsOn; - private ItemStack capsOff; + private final ItemStack capsOn; + private final ItemStack capsOff; private final int capsIndex; private final int backspaceIndex; private final int returnIndex; - public StringEditMenu(YmlConfiguration menuConfig, EditMenu parent) { + public StringEditMenu(FileConfiguration menuConfig, EditMenu parent) { super(menuConfig); this.parent = parent; List characterMap = menuConfig.getList("keyboard.en"); - ensureCapacity(keyboard, 9*6); - ensureCapacity(capslockOverlay, 9*6); + ensureCapacity(keyboard, 9 * 6); + ensureCapacity(capslockOverlay, 9 * 6); int row = 0; for (Object o : characterMap) { int col = 0; if (o instanceof List) { - for (String item : (List)o) { - ItemStack character = createItem(item); + for (String item : (List) o) { + ItemStack character = createItemFromComponentString(item); if (character != null) { keyboard.set(getIndex(row, col), character); } @@ -59,15 +60,15 @@ public StringEditMenu(YmlConfiguration menuConfig, EditMenu parent) { if (overlay != null) { for (String key : overlay.getKeys(false)) { int index = Integer.parseInt(key, 10); - ItemStack item = createItem(overlay.getString(key)); + ItemStack item = createItemFromComponentString(overlay.getString(key)); if (item != null) { capslockOverlay.set(index, item); } } } - capsOn = createItem(menuConfig.getString("keyboard.capslock.true")); - capsOff = createItem(menuConfig.getString("keyboard.capslock.false")); - keyboard.set(getIndex(0,0), createItem(Material.OAK_DOOR, "\u00a79" + tr("Return"), null)); + capsOn = createItemFromComponentString(menuConfig.getString("keyboard.capslock.true")); + capsOff = createItemFromComponentString(menuConfig.getString("keyboard.capslock.false")); + keyboard.set(getIndex(0, 0), createItem(Material.OAK_DOOR, "\u00a79" + tr("Return"), null)); capsIndex = getIndex(5, 0); keyboard.set(capsIndex, capsOff); backspaceIndex = getIndex(0, 5); @@ -77,7 +78,7 @@ public StringEditMenu(YmlConfiguration menuConfig, EditMenu parent) { @Override public boolean onClick(InventoryClickEvent e) { if (!(e.getInventory().getHolder() instanceof UltimateHolder) || - !stripFormatting(((UltimateHolder) e.getInventory().getHolder()).getTitle()).equals(stripFormatting(getTitle()))) { + !stripFormatting(((UltimateHolder) e.getInventory().getHolder()).getTitle()).equals(stripFormatting(getTitle()))) { return false; } Player player = (Player) e.getWhoClicked(); @@ -88,13 +89,13 @@ public boolean onClick(InventoryClickEvent e) { ItemStack currentItem = e.getCurrentItem(); boolean isCaps = e.getInventory().getItem(capsIndex).getItemMeta().getDisplayName().equals(tr("Caps On")); if (currentItem != null) { - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); String value = config.getString(path); if (e.getSlot() == capsIndex) { // Toggle caps ItemStack capsItem = isCaps ? capsOff.clone() : capsOn.clone(); ItemMeta meta = capsItem.getItemMeta(); - meta.setLore(Arrays.asList(value)); + meta.setLore(Collections.singletonList(value)); capsItem.setItemMeta(meta); e.getInventory().setItem(capsIndex, capsItem); isCaps = !isCaps; @@ -128,7 +129,7 @@ public Inventory createEditMenu(String configName, String path, int page) { } private Inventory createEditMenuInternal(String configName, String path, int page, boolean isCaps) { - YmlConfiguration config = FileUtil.getYmlConfiguration(configName); + FileConfiguration config = FileUtil.getYmlConfiguration(configName); if (!config.isString(path)) { return null; } @@ -146,20 +147,20 @@ private Inventory createEditMenuInternal(String configName, String path, int pag ItemStack capsItem = isCaps ? capsOn.clone() : capsOff.clone(); ItemMeta itemMeta = capsItem.getItemMeta(); - itemMeta.setLore(Arrays.asList(value)); + itemMeta.setLore(List.of(value)); capsItem.setItemMeta(itemMeta); menu.setItem(capsIndex, capsItem); return menu; } - private void setCharacters(Inventory menu, String value, ArrayList itemList) { + private void setCharacters(Inventory menu, String value, List itemList) { int index = 0; for (ItemStack item : itemList) { if (item != null) { ItemStack clone = item.clone(); ItemMeta itemMeta = clone.getItemMeta(); - itemMeta.setLore(Arrays.asList(value)); + itemMeta.setLore(Collections.singletonList(value)); clone.setItemMeta(itemMeta); menu.setItem(index, clone); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/Perk.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/Perk.java index 2e044d53a..ea75e27cb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/Perk.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/Perk.java @@ -1,16 +1,10 @@ package us.talabrek.ultimateskyblock.player; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Perk is an immutable object holding all the perks, @@ -23,7 +17,7 @@ public class Perk { private final double rewBonus; private final double hungerReduction; private final Set schematics; - private Map blockLimits; + private final Map blockLimits; private final int villagers; private final int golems; @@ -37,15 +31,15 @@ public class Perk { double hungerReduction, List schematics, Map blockLimits) { - this.maxPartySize = maxPartySize >= 0 ? maxPartySize : 0; - this.animals = animals >= 0 ? animals : 0; - this.monsters = monsters >= 0 ? monsters : 0; - this.villagers = villagers >= 0 ? villagers : 0; - this.golems = golems >= 0 ? golems : 0; - this.extraItems = extraItems != null ? extraItems : Collections.emptyList(); + this.maxPartySize = Math.max(maxPartySize, 0); + this.animals = Math.max(animals, 0); + this.monsters = Math.max(monsters, 0); + this.villagers = Math.max(villagers, 0); + this.golems = Math.max(golems, 0); + this.extraItems = extraItems != null ? extraItems : Collections.emptyList(); this.rewBonus = rewBonus >= 0 ? rewBonus : 0; this.hungerReduction = hungerReduction >= 0 && hungerReduction <= 1 ? hungerReduction : 0; - this.schematics = schematics != null ? new HashSet<>(schematics) : Collections.emptySet(); + this.schematics = schematics != null ? new HashSet<>(schematics) : Collections.emptySet(); this.blockLimits = blockLimits != null ? new HashMap<>(blockLimits) : Collections.emptyMap(); } @@ -70,10 +64,12 @@ public int getGolems() { } public List getExtraItems() { - return extraItems; + return ItemStackUtil.clone(extraItems); } - public Map getBlockLimits() { return blockLimits; } + public Map getBlockLimits() { + return blockLimits; + } public double getRewBonus() { return rewBonus; @@ -95,29 +91,28 @@ public Perk combine(Perk other) { schems.addAll(this.schematics); schems.addAll(other.getSchematics()); return new Perk( - items, - Math.max(maxPartySize, other.getMaxPartySize()), - Math.max(animals, other.getAnimals()), - Math.max(monsters, other.getMonsters()), - Math.max(villagers, other.getVillagers()), - Math.max(golems, other.getGolems()), - Math.max(rewBonus, other.getRewBonus()), - Math.max(hungerReduction, other.getHungerReduction()), - schems, null); + items, + Math.max(maxPartySize, other.getMaxPartySize()), + Math.max(animals, other.getAnimals()), + Math.max(monsters, other.getMonsters()), + Math.max(villagers, other.getVillagers()), + Math.max(golems, other.getGolems()), + Math.max(rewBonus, other.getRewBonus()), + Math.max(hungerReduction, other.getHungerReduction()), + schems, null); } @Override public String toString() { - return (maxPartySize > 0 ? "maxPartySize:" + maxPartySize + "\n" : "") + - (animals > 0 ? "animals:" + animals +"\n" : "") + - (monsters > 0 ? "monsters:" + monsters +"\n" : "") + - (villagers > 0 ? "villagers:" + villagers + "\n" : "") + - (golems > 0 ? "golems:" + golems + "\n" : "") + - (!extraItems.isEmpty() ? "extraItems:" + ItemStackUtil.asShortString(extraItems) +"\n" : "") + - (rewBonus > 0 ? "rewBonus:" + rewBonus +"\n" : "") + - (hungerReduction > 0 ? "hungerReduction:" + hungerReduction +"\n" : "") + - (!schematics.isEmpty() ? "schematics:" + schematics +"\n" : "") + - (!blockLimits.isEmpty() ? "blockLimits:" + blockLimits +"\n" : "") - ; + return (maxPartySize > 0 ? "maxPartySize:" + maxPartySize + "\n" : "") + + (animals > 0 ? "animals:" + animals + "\n" : "") + + (monsters > 0 ? "monsters:" + monsters + "\n" : "") + + (villagers > 0 ? "villagers:" + villagers + "\n" : "") + + (golems > 0 ? "golems:" + golems + "\n" : "") + + (!extraItems.isEmpty() ? "extraItems:" + ItemStackUtil.asShortString(extraItems) + "\n" : "") + + (rewBonus > 0 ? "rewBonus:" + rewBonus + "\n" : "") + + (hungerReduction > 0 ? "hungerReduction:" + hungerReduction + "\n" : "") + + (!schematics.isEmpty() ? "schematics:" + schematics + "\n" : "") + + (!blockLimits.isEmpty() ? "blockLimits:" + blockLimits + "\n" : ""); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 666eda583..300e0a303 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -1,7 +1,6 @@ package us.talabrek.ultimateskyblock.player; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.apache.commons.lang3.Validate; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -9,6 +8,7 @@ import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +41,7 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private static final long serialVersionUID = 1L; private static final int YML_VERSION = 1; private final uSkyBlock plugin; - private String playerName; + private final String playerName; private String displayName; private UUID uuid; @@ -49,8 +49,8 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private Location homeLocation; - private volatile FileConfiguration playerData; - private File playerConfigFile; + private final FileConfiguration playerData; + private final File playerConfigFile; private boolean islandGenerating = false; private boolean dirty = false; @@ -65,7 +65,7 @@ public PlayerInfo(String currentPlayerName, UUID playerUUID, uSkyBlock plugin) { if (!playerConfigFile.exists() && nameFile.exists() && !currentPlayerName.equals(PlayerDB.UNKNOWN_PLAYER_NAME)) { nameFile.renameTo(playerConfigFile); } - playerData = new YmlConfiguration(); + playerData = new YamlConfiguration(); if (playerConfigFile.exists()) { FileUtil.readConfig(playerData, playerConfigFile); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java index 0bfa04f64..c832c0fa8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.signs; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -10,7 +10,9 @@ import org.bukkit.block.Sign; import org.bukkit.block.data.type.WallSign; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; @@ -19,14 +21,14 @@ import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import us.talabrek.ultimateskyblock.util.LocationUtil; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.logging.Logger; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -38,7 +40,7 @@ public class SignLogic { private static final Logger log = Logger.getLogger(SignLogic.class.getName()); private static final int SIGN_LINE_WIDTH = 11; // Actually more like 15, but we break after. - private final YmlConfiguration config; + private final FileConfiguration config; private final File configFile; private final uSkyBlock plugin; private final ChallengeLogic challengeLogic; @@ -169,6 +171,7 @@ private void updateSignAsync(final Location chestLoc) { } } + // TODO: This method accesses a lot of unsynchronized data, and should be refactored to be sync. private void updateSignAsync(final Location chestLoc, String islandName, String signLoc) { String challengeName = config.getString("signs." + signLoc + ".challenge", null); if (challengeName == null) { @@ -178,12 +181,12 @@ private void updateSignAsync(final Location chestLoc, String islandName, String if (challenge == null || challenge.getType() != Challenge.Type.PLAYER) { return; } - final List requiredItems = new ArrayList<>(); + Map requiredItems = new LinkedHashMap<>(); boolean isChallengeAvailable = false; if (challengeLogic.isIslandSharing()) { final ChallengeCompletion completion = challengeLogic.getIslandCompletion(islandName, challengeName); if (completion != null) { - requiredItems.addAll(challenge.getRequiredItems(completion.getTimesCompletedInCooldown())); + requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); } } IslandInfo islandInfo = plugin.getIslandInfo(islandName); @@ -197,11 +200,12 @@ private void updateSignAsync(final Location chestLoc, String islandName, String String signLocString = config.getString("signs." + signLoc + ".location", null); final Location signLocation = LocationUtil.fromString(signLocString); final boolean challengeLocked = !isChallengeAvailable; + final Map requiredItemsFinal = requiredItems; // Back to sync - plugin.sync(() -> updateSignFromChestSync(chestLoc, signLocation, challenge, requiredItems, challengeLocked)); + plugin.sync(() -> updateSignFromChestSync(chestLoc, signLocation, challenge, requiredItemsFinal, challengeLocked)); } - private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challenge challenge, List requiredItems, boolean challengeLocked) { + private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challenge challenge, Map requiredItems, boolean challengeLocked) { Block chestBlock = chestLoc.getBlock(); Block signBlock = signLoc != null ? signLoc.getBlock() : null; if (signBlock != null && isChest(chestBlock) && signBlock.getState().getBlockData() instanceof WallSign) { @@ -210,10 +214,12 @@ private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challe int missing = -1; if (!requiredItems.isEmpty() && !challengeLocked) { missing = 0; - for (ItemStack required : requiredItems) { - if (!chest.getInventory().containsAtLeast(required, required.getAmount())) { + for (Map.Entry required : requiredItems.entrySet()) { + ItemStack requiredType = required.getKey(); + int requiredAmount = required.getValue(); + if (!chest.getInventory().containsAtLeast(requiredType, requiredAmount)) { // Max shouldn't be needed, provided containsAtLeast matches getCountOf... but it might not - missing += Math.max(0, required.getAmount() - plugin.getChallengeLogic().getCountOf(chest.getInventory(), required)); + missing += Math.max(0, requiredAmount - plugin.getChallengeLogic().getCountOf(chest.getInventory(), requiredType)); } } } @@ -296,9 +302,13 @@ private void tryCompleteAsync(final Player player, Location location) { } } + // This logic is duplicated in ChallengeLogic.tryCompleteOnPlayer. It has a lot of the same checks. If they + // pass, it moves the items to the player inventory and then calls the challengeLogic to complete the challenge. + // This is prone to bugs and exploits, and should be refactored. Ideally we get rid of the transfer and just + // refactor the challenge logic to accept multiple inventories as source. private void tryComplete(Player player, Location chestLoc, Challenge challenge) { BlockState state = chestLoc.getBlock().getState(); - if (!(state instanceof Chest)) { + if (!(state instanceof Chest chest)) { return; } PlayerInfo playerInfo = plugin.getPlayerInfo(player); @@ -306,35 +316,27 @@ private void tryComplete(Player player, Location chestLoc, Challenge challenge) return; } ChallengeCompletion completion = challengeLogic.getChallenge(playerInfo, challenge.getName()); - List requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); - Chest chest = (Chest) state; + Map requiredItems = challenge.getRequiredItems(completion.getTimesCompletedInCooldown()); int missing = 0; - for (ItemStack required : requiredItems) { + for (Map.Entry required : requiredItems.entrySet()) { + ItemStack requiredType = required.getKey(); + int requiredAmount = required.getValue(); int diff = 0; - if (!player.getInventory().containsAtLeast(required, required.getAmount())) { - diff = required.getAmount() - plugin.getChallengeLogic().getCountOf(player.getInventory(), required); + if (!player.getInventory().containsAtLeast(requiredType, requiredAmount)) { + diff = requiredAmount - plugin.getChallengeLogic().getCountOf(player.getInventory(), requiredType); } - if (diff > 0 && !chest.getInventory().containsAtLeast(required, diff)) { - diff -= plugin.getChallengeLogic().getCountOf(chest.getInventory(), required); + if (diff > 0 && !chest.getInventory().containsAtLeast(requiredType, diff)) { + diff -= plugin.getChallengeLogic().getCountOf(chest.getInventory(), requiredType); } else { diff = 0; } missing += diff; } if (missing == 0) { - ItemStack[] items = requiredItems.toArray(new ItemStack[0]); - ItemStack[] copy = ItemStackUtil.clone(requiredItems).toArray(new ItemStack[requiredItems.size()]); - HashMap missingItems = player.getInventory().removeItem(items); - missingItems = chest.getInventory().removeItem(missingItems.values().toArray(new ItemStack[0])); - if (!missingItems.isEmpty()) { - // This effectively means, we just donated some items to the player (exploit!!) - log.warning("Not all items removed from chest and player: " + missingItems.values()); - } - HashMap leftOvers = player.getInventory().addItem(copy); - if (leftOvers.isEmpty()) { + boolean successfulItemTransfer = attemptToMoveItemsToPlayerInventory(player.getInventory(), chest.getInventory(), requiredItems); + if (successfulItemTransfer) { plugin.getChallengeLogic().completeChallenge(player, challenge.getName()); } else { - chest.getInventory().addItem(leftOvers.values().toArray(new ItemStack[0])); player.sendMessage(tr("\u00a7cWARNING:\u00a7e Could not transfer all the required items to your inventory!")); } updateSignsOnContainer(chest.getLocation()); @@ -343,4 +345,25 @@ private void tryComplete(Player player, Location chestLoc, Challenge challenge) } } + // This is a counter-intuitive way transfer the required items from the chest to the player inventory. + // It's prone to bugs and exploits, and should be refactored. Ideally we get rid of the transfer and just + // refactor the challenge logic to accept multiple inventories as source. + private static boolean attemptToMoveItemsToPlayerInventory(Inventory player, Inventory chest, Map requiredItems) { + ItemStack[] itemsToRemove = ItemStackUtil.asValidItemStacksWithAmount(requiredItems); + ItemStack[] itemCopy = ItemStackUtil.asValidItemStacksWithAmount(requiredItems); + + HashMap missingItems = player.removeItem(itemsToRemove); + missingItems = chest.removeItem(missingItems.values().toArray(new ItemStack[0])); + if (!missingItems.isEmpty()) { + // This effectively means, we just donated some items to the player (exploit!!) + throw new IllegalStateException("Not all items removed from chest and player: " + missingItems.values()); + } + HashMap leftOvers = player.addItem(itemCopy); + if (leftOvers.isEmpty()) { + return true; + } else { + chest.addItem(leftOvers.values().toArray(new ItemStack[0])); + return false; + } + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index cfba262c0..7a40d9d0c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -8,12 +8,12 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import dk.lockfuglsang.minecraft.util.TimeUtil; import dk.lockfuglsang.minecraft.util.VersionUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Biome; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -65,6 +65,7 @@ import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; +import us.talabrek.ultimateskyblock.imports.ItemComponentConverter; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; import us.talabrek.ultimateskyblock.island.IslandGenerator; @@ -204,12 +205,21 @@ public FileConfiguration getConfig() { return FileUtil.getYmlConfiguration("config.yml"); } + private void convertConfigItemsTo1_20_6IfRequired() { + var converter = new ItemComponentConverter(getLogger()); + converter.checkAndDoImport(getDataFolder()); + } + @Override public void onEnable() { WorldManager.skyBlockWorld = null; // Force a re-import or what-ever... WorldManager.skyBlockNetherWorld = null; missingRequirements = null; instance = this; + + // Converter has to run before the plugin loads its config files. + convertConfigItemsTo1_20_6IfRequired(); + CommandManager.registerRequirements(this); FileUtil.setDataFolder(getDataFolder()); FileUtil.setAllwaysOverwrite("levelConfig.yml"); @@ -247,8 +257,8 @@ public void run() { updateChecker = new SkyUpdateChecker(this); // Runs every 4 hours - // noinspection deprecation - getServer().getScheduler().scheduleAsyncRepeatingTask(this, () -> getUpdateChecker().checkForUpdates(), 0L, 288000L); + long FOUR_HOURS_IN_TICKS = 4L * 60L * 60L * 20L; + getServer().getScheduler().runTaskTimerAsynchronously(this, () -> getUpdateChecker().checkForUpdates(), 0L, FOUR_HOURS_IN_TICKS); metricsManager = new MetricsManager(this); } @@ -400,13 +410,10 @@ public void deletePlayerIsland(final String player, final Runnable runner) { pi = playerLogic.getPlayerInfo(member); islandInfo.removeMember(pi); } - islandLogic.clearIsland(islandLocation, new Runnable() { - @Override - public void run() { - postDelete(finalPI); - postDelete(islandInfo); - if (runner != null) runner.run(); - } + islandLogic.clearIsland(islandLocation, () -> { + postDelete(finalPI); + postDelete(islandInfo); + if (runner != null) runner.run(); }); } @@ -769,7 +776,7 @@ private void reloadConfigs() { challengeLogic = new ChallengeLogic(FileUtil.getYmlConfiguration("challenges.yml"), this); menu = new SkyBlockMenu(this, challengeLogic); configMenu = new ConfigMenu(this); - YmlConfiguration levelConfig = FileUtil.getYmlConfiguration("levelConfig.yml"); + FileConfiguration levelConfig = FileUtil.getYmlConfiguration("levelConfig.yml"); // Disabled until AWE/FAWE supports 1.13 //levelLogic = AsyncWorldEditHandler.isAWE() ? new AweLevelLogic(this, levelConfig) : new ChunkSnapshotLevelLogic(this, levelConfig); levelLogic = new ChunkSnapshotLevelLogic(this, levelConfig); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java index dbe03258b..1970b8f53 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java @@ -1,114 +1,16 @@ package us.talabrek.ultimateskyblock.util; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.FileConfiguration; - import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Common file-utilities. */ public enum FileUtil {; - private static final Logger log = Logger.getLogger(FileUtil.class.getName()); - private static final Collection allwaysOverwrite = new ArrayList<>(); - private static final Collection neverOverwrite = new ArrayList<>(); - private static final Map configFiles = new ConcurrentHashMap<>(); - private static Locale locale = Locale.getDefault(); - private static File dataFolder; - - public static void setAllwaysOverwrite(String... configs) { - for (String s : configs) { - if (!allwaysOverwrite.contains(s)) { - allwaysOverwrite.add(s); - } - } - } - - public static void setNeverOverwrite(String... configs) { - for (String s : configs) { - if (!neverOverwrite.contains(s)) { - neverOverwrite.add(s); - } - } - } - - public static YmlConfiguration loadConfig(File file) { - YmlConfiguration config = new YmlConfiguration(); - readConfig(config, file); - return config; - } - - public static void readConfig(FileConfiguration config, File file) { - if (file == null) { - log.log(Level.INFO, "No " + file + " found, it will be created"); - return; - } - File configFile = file; - File localeFile = new File(configFile.getParentFile(), getLocaleName(file.getName())); - if (localeFile.exists() && localeFile.canRead()) { - configFile = localeFile; - } - if (!configFile.exists()) { - log.log(Level.INFO, "No " + configFile + " found, it will be created"); - return; - } - try (Reader rdr = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { - config.load(rdr); - } catch (InvalidConfigurationException e) { - log.log(Level.SEVERE, "Unable to read config file " + configFile, e); - if (configFile.exists()) { - try { - Files.copy(Paths.get(configFile.toURI()), Paths.get(configFile.getParent(), configFile.getName() + ".err"), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e1) { - // Ignore - we tried... - } - } - } catch (IOException e) { - log.log(Level.SEVERE, "Unable to read config file " + configFile, e); - } - } - - public static void readConfig(FileConfiguration config, InputStream inputStream) { - if (inputStream == null) { - return; - } - try (Reader rdr = new InputStreamReader(inputStream, "UTF-8")) { - config.load(rdr); - } catch (InvalidConfigurationException | IOException e) { - log.log(Level.SEVERE, "Unable to read configuration", e); - } - } - - public static FilenameFilter createYmlFilenameFilter() { - return new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name != null && name.endsWith(".yml"); - } - }; - } public static String getBasename(File file) { return getBasename(file.getName()); @@ -128,205 +30,10 @@ public static String getExtension(String fileName) { return ""; } - private static File getDataFolder() { - return dataFolder != null ? dataFolder : new File("."); - } - - /** - * System-encoding agnostic config-reader - * Reads and returns the configuration found in: - *

-     *   a) the datafolder
-     *
-     *     a.1) if a config named "config_en.yml" exists - that is read.
-     *
-     *     a.2) otherwise "config.yml" is read (created if need be).
-     *
-     *   b) if the version differs from the same resource on the classpath
-     *
-     *      b.1) all nodes in the jar-file-version is merged* into the local-file
-     *
-     *      b.2) unless the configName is in the allwaysOverwrite - then the jar-version wins
-     *
-     * *merged: using data-conversion of special nodes.
-     * 
- */ - public static YmlConfiguration getYmlConfiguration(String configName) { - // Caching, for your convenience! (and a bigger memory print!) - - if (!configFiles.containsKey(configName)) { - YmlConfiguration config = new YmlConfiguration(); - try { - // read from datafolder! - File configFile = getConfigFile(configName); - YmlConfiguration configJar = new YmlConfiguration(); - readConfig(config, configFile); - readConfig(configJar, getResource(configName)); - if (!configFile.exists() || config.getInt("version", 0) < configJar.getInt("version", 0)) { - if (configFile.exists()) { - if (neverOverwrite.contains(configName)) { - configFiles.put(configName, config); - return config; - } - File backupFolder = new File(getDataFolder(), "backup"); - backupFolder.mkdirs(); - String bakFile = String.format("%1$s-%2$tY%2$tm%2$td-%2$tH%2$tM.yml", getBasename(configName), new Date()); - log.log(Level.INFO, "Moving existing config " + configName + " to backup/" + bakFile); - Files.move(Paths.get(configFile.toURI()), - Paths.get(new File(backupFolder, bakFile).toURI()), - StandardCopyOption.REPLACE_EXISTING); - if (allwaysOverwrite.contains(configName)) { - FileUtil.copy(getResource(configName), configFile); - config = configJar; - } else { - config = mergeConfig(configJar, config); - config.save(configFile); - config.load(configFile); - } - } else { - config = mergeConfig(configJar, config); - config.save(configFile); - config.load(configFile); - } - } - } catch (Exception e) { - log.log(Level.SEVERE, "Unable to handle config-file " + configName, e); - } - configFiles.put(configName, config); - } - return configFiles.get(configName); - } - - private static InputStream getResource(String configName) { - String resourceName = getLocaleName(configName); - ClassLoader loader = FileUtil.class.getClassLoader(); - InputStream resourceAsStream = loader.getResourceAsStream(resourceName); - if (resourceAsStream != null) { - return resourceAsStream; - } - return loader.getResourceAsStream(configName); - } - - private static String getLocaleName(String fileName) { - String baseName = getBasename(fileName); - return baseName + "_" + locale + fileName.substring(baseName.length()); - } - - public static File getConfigFile(String configName) { - File file = new File(getDataFolder(), getLocaleName(configName)); - if (file.exists()) { - return file; - } - return new File(getDataFolder(), configName); - } - public static void copy(InputStream stream, File file) throws IOException { if (stream == null || file == null) { throw new IOException("Invalid resource for " + file); } Files.copy(stream, Paths.get(file.toURI()), StandardCopyOption.REPLACE_EXISTING); } - - /** - * Merges the important keys from src to destination. - * @param src The source (containing the new values). - * @param dest The destination (containing old-values). - */ - private static YmlConfiguration mergeConfig(YmlConfiguration src, YmlConfiguration dest) { - int existing = dest.getInt("version"); - int version = src.getInt("version", existing); - dest.setDefaults(src); - dest.options().copyDefaults(true); - dest.addComments(src.getComments()); - dest.set("version", version); - dest.options().copyHeader(false); - src.options().copyHeader(false); - removeExcludes(dest); - moveNodes(src, dest); - replaceDefaults(src, dest); - return dest; - } - - /** - * Removes nodes from dest.defaults, that are specifically excluded in the config - */ - private static void removeExcludes(YmlConfiguration dest) { - List keys = dest.getStringList("merge-ignore"); - for (String key : keys) { - dest.getDefaults().set(key, null); - } - } - - private static void replaceDefaults(YmlConfiguration src, YmlConfiguration dest) { - ConfigurationSection forceSection = src.getConfigurationSection("force-replace"); - if (forceSection != null) { - for (String key : forceSection.getKeys(true)) { - Object def = forceSection.get(key, null); - Object value = dest.get(key, def); - Object newDef = src.get(key, null); - if (def != null && def.equals(value)) { - dest.set(key, newDef); - } - } - } - dest.set("force-replace", null); - dest.getDefaults().set("force-replace", null); - } - - private static void moveNodes(YmlConfiguration src, YmlConfiguration dest) { - ConfigurationSection moveSection = src.getConfigurationSection("move-nodes"); - if (moveSection != null) { - List keys = new ArrayList<>(moveSection.getKeys(true)); - Collections.reverse(keys); // Depth first - for (String key : keys) { - if (moveSection.isString(key)) { - String srcPath = key; - String tgtPath = moveSection.getString(key, key); - Object value = dest.get(srcPath); - if (value != null) { - dest.set(tgtPath, value); - dest.set(srcPath, null); - } - } else if (moveSection.isConfigurationSection(key)) { - // Check to see if dest section should be nuked... - if (dest.isConfigurationSection(key) && dest.getConfigurationSection(key).getKeys(false).isEmpty()) { - dest.set(key, null); - } - } - } - } - dest.set("move-nodes", null); - dest.getDefaults().set("move-nodes", null); - } - - public static void setDataFolder(File dataFolder) { - FileUtil.dataFolder = dataFolder; - configFiles.clear(); - } - - public static void setLocale(Locale loc) { - locale = loc != null ? loc : locale; - } - - public static void reload() { - for (Map.Entry e : configFiles.entrySet()) { - File configFile = new File(getDataFolder(), e.getKey()); - readConfig(e.getValue(), configFile); - } - } - - public static Properties readProperties(String fileName) { - File configFile = getConfigFile(fileName); - if (configFile != null && configFile.exists() && configFile.canRead()) { - Properties prop = new Properties(); - try (InputStreamReader in = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { - prop.load(in); - return prop; - } catch (IOException e) { - log.log(Level.WARNING, "Error reading " + fileName, e); - } - } - return null; - } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java new file mode 100644 index 000000000..933e3aabb --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java @@ -0,0 +1,54 @@ +package us.talabrek.ultimateskyblock.util; + +import dk.lockfuglsang.minecraft.util.FormatUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Locale; + +public class GuiItemUtil { + private GuiItemUtil() { + // Uninstantiable static utility class + } + + // TODO: Replace calls to this specific method with a more general one + public static ItemStack createItemFromComponentString(String components) { + if (components == null) { + return null; + } + return Bukkit.getItemFactory().createItemStack(components); + } + + public static ItemStack createGuiDisplayItem(String material, String name) { + return createGuiDisplayItem(material, name, null); + } + + public static ItemStack createGuiDisplayItem(String material, String name, String description) { + Material type = Material.matchMaterial(material.toUpperCase(Locale.ROOT)); + if (type == null) { + type = Material.BARRIER; + } + return createGuiDisplayItem(type, name, description); + } + + public static ItemStack createGuiDisplayItem(Material material, String name) { + return createGuiDisplayItem(material, name, null); + } + + public static ItemStack createGuiDisplayItem(Material material, String name, String description) { + ItemStack itemStack = new ItemStack(material); + ItemMeta meta = itemStack.getItemMeta(); + if (meta != null) { + if (name != null) { + meta.setDisplayName(FormatUtil.normalize(name)); + } + if (description != null) { + meta.setLore(FormatUtil.wordWrap(FormatUtil.normalize(description), 30, 30)); + } + itemStack.setItemMeta(meta); + } + return itemStack; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java index 47cdd748f..f646fd2ba 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/MaterialUtil.java @@ -16,7 +16,7 @@ */ public enum MaterialUtil { ; - private static final Pattern MATERIAL_PROBABILITY = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?\\s*(?[A-Z_0-9]+)"); + private static final Pattern MATERIAL_PROBABILITY = Pattern.compile("(\\{p=(?0\\.[0-9]+)\\})?\\s*(?[A-Z_0-9a-z]+)"); private static final Collection SANDS = Arrays.asList(Material.SAND, Material.RED_SAND, Material.GRAVEL, Material.WHITE_CONCRETE_POWDER, Material.ORANGE_CONCRETE_POWDER, Material.MAGENTA_CONCRETE_POWDER, Material.LIGHT_BLUE_CONCRETE_POWDER, Material.YELLOW_CONCRETE_POWDER, Material.LIME_CONCRETE_POWDER, Material.PINK_CONCRETE_POWDER, Material.GRAY_CONCRETE_POWDER, Material.LIGHT_GRAY_CONCRETE_POWDER, Material.CYAN_CONCRETE_POWDER, Material.PURPLE_CONCRETE_POWDER, Material.BLUE_CONCRETE_POWDER, Material.BROWN_CONCRETE_POWDER, Material.GREEN_CONCRETE_POWDER, Material.RED_CONCRETE_POWDER, Material.BLACK_CONCRETE_POWDER); private static final Collection WOOD_TOOLS = Arrays.asList(Material.WOODEN_AXE, Material.WOODEN_HOE, Material.WOODEN_PICKAXE, Material.WOODEN_SHOVEL, Material.WOODEN_SWORD); private static final Collection STONE_TOOLS = Arrays.asList(Material.STONE_AXE, Material.STONE_HOE, Material.STONE_PICKAXE, Material.STONE_SHOVEL, Material.STONE_SWORD); @@ -68,7 +68,7 @@ public static List createProbabilityList(List matLi for (String line : matList) { Matcher m = MATERIAL_PROBABILITY.matcher(line); if (m.matches()) { - Material mat = Material.getMaterial(m.group("id")); + Material mat = Material.matchMaterial(m.group("id")); if (mat == null) { Bukkit.getLogger().log(Level.WARNING, "Unknown material: " + line); continue; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ServerUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ServerUtil.java index 951b1c72e..43699c0a0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ServerUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ServerUtil.java @@ -1,9 +1,10 @@ package us.talabrek.ultimateskyblock.util; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -18,7 +19,7 @@ public static boolean isBungeeEnabled() { boolean isBungeeMode = false; File spigotYml = new File(".", "spigot.yml"); if (spigotYml.exists()) { - YmlConfiguration spigotConfig = new YmlConfiguration(); + FileConfiguration spigotConfig = new YamlConfiguration(); FileUtil.readConfig(spigotConfig, spigotYml); isBungeeMode = spigotConfig.getBoolean("settings.bungeecord", false); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java index 439218242..f03cfe371 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java @@ -1,9 +1,10 @@ package us.talabrek.ultimateskyblock.uuid; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -31,12 +32,12 @@ public class FilePlayerDB implements PlayerDB { private static final Logger log = Logger.getLogger(FilePlayerDB.class.getName()); private final File uuid2NameFile; - private final YmlConfiguration uuid2NameConfig; + private final FileConfiguration uuid2NameConfig; private final uSkyBlock plugin; private boolean isShuttingDown = false; private volatile BukkitTask saveTask; - private long saveDelay; + private final long saveDelay; // These caches should NOT be guavaCaches, we need them alive most of the time private final Map name2uuidCache = new ConcurrentHashMap<>(); @@ -45,7 +46,7 @@ public class FilePlayerDB implements PlayerDB { public FilePlayerDB(uSkyBlock plugin) { this.plugin = plugin; uuid2NameFile = new File(plugin.getDataFolder(), "uuid2name.yml"); - uuid2NameConfig = new YmlConfiguration(); + uuid2NameConfig = new YamlConfiguration(); if (uuid2NameFile.exists()) { FileUtil.readConfig(uuid2NameConfig, uuid2NameFile); } @@ -192,7 +193,6 @@ public Player getPlayer(String name) { if (uuid != null) { return getPlayer(uuid); } - //noinspection deprecation Player player = Bukkit.getPlayer(name); if (player != null) { updatePlayer(player.getUniqueId(), player.getName(), player.getDisplayName()); diff --git a/uSkyBlock-Core/src/main/resources/challenges.yml b/uSkyBlock-Core/src/main/resources/challenges.yml index daf9b5607..e97fca755 100644 --- a/uSkyBlock-Core/src/main/resources/challenges.yml +++ b/uSkyBlock-Core/src/main/resources/challenges.yml @@ -1,3 +1,119 @@ +# ====================================================================================================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the +# most used settings while the double commented (##) are optional if you like to use those settings. +# +# Item type format +# Item types are defined as in the minecraft /give command, i.e. with their minecraft key and possible components in +# square brackets. For example, 'minecraft:diamond_sword[damage=42]'. Refer to the Minecraft wiki for more information: +# https://minecraft.wiki/w/Data_component_format. You can also use the command '/usb iteminfo' to get the information. +# +# This item type is supplemented with additional information depending on where it is used: +# +# display-item: +# An item to be displayed in a GUI. It only defines the item type as above, without any additional information. +# For example: 'cobblestone', 'minecraft:stone', 'diamond_sword[damage=42]'. +# +# item-requirement: :[;+] +# An item requirement for a challenge. The amount is the number of items required. The optional + is the number +# of items to add to the required amount for each repeat of the challenge. For example, 'cobblestone:64;+16' would +# require 64 cobblestone for the first completion and 80 cobblestone for the second completion. Other options are +# -, *, and / for subtraction, multiplication, and division, respectively. For example, 'cobblestone:64;*2' would +# require 64 cobblestone for the first completion, 128 cobblestone for the second completion, and 256 cobblestone for +# the third completion. +# +# item-reward: [{p=}]: +# An item reward for a challenge. The amount is the number of items to give. The optional {p=} is the +# probability of the item being given. For example, 'cobblestone:64' would give 64 cobblestone every time the challenge +# is completed, while '{p=0.1}cobblestone:64' would give 64 cobblestone 10% of the time. +# +# ====================================================================================================================== +# All challenges are defined in the ranks section. Each rank is a tier of challenges that players can complete. +# +# ranks: +# # [text] name of the challenge Rank. +# TierX: +# # [text] The name of the challenge rank that shows when you do /challenges (supports capitals and color codes). +# name: '&aCustom Challenges rank name' +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: 'cyan_terracotta' +# # [integer] The time in hours before required items reset to default (this overwrites the main reset time) +# resetInHours: 20 +# # These requirements controls when a challenge group will be available to a player. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, +# if you have 4 challenges with a rankLeeway of 1, a player would only need to complete 3 to advance to +# the next rank. A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [List[text]] Challenges that have to be completed before this group will available to a player. +# challenges: +# - a challenge name +# ====================================================================================================================== +# challenges: +# # [text] The name of the challenge. All challenge names should be lower-case. +# defaultchallenge: +# # [text] The name of the challenge that shows in /challenges (this supports capitals and color codes). +# name: '&a Default Challenge' +# # [text] The descriptions players see when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This defines whether the required blocks/items should be in the player's +# # inventory or on their island. When using onIsland, the player must within 10 blocks from the required blocks +# # on his island. When using islandLevel, the 'requiredItems' field should be the island level required. The +# # player must use /island level first to update their level. +# type: onPlayer +# ## type: islandLevel +# ## type: onIsland +# # [integer] Overrides the default radius of 10 blocks when using onIsland. +# ## radius: 20 +# # [List[item-requirement] The items required to complete the challenge. +# requiredItems: +# - stone:64;+16 +# - cobblestone:64;+16 +# # [true/false] If the challenge can be repeated or not. +# ## repeatable: true +# # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. +# # A value of 0 means unlimited repeats. +# ## repeatLimit: 5 +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: cobblestone +# # [integer] The time in hours before required items reset to default (overwrites the main and rank defaults). +# ## resetInHours: 4 +# # [true/false] Take required items on completing a challenge. +# ## takeItems: true +# # The rewards players get for completing the challenge +# reward: +# # [text] Description of the reward. +# text: 'Mossy cobblestone and an iron pickaxe with unbreaking 1' +# # [List[item-requirement]] A list of items given to the player for completing the challenge. +# items: +# - mossy_cobblestone:16 +# - iron_pickaxe[enchantments={levels:{unbreaking:1}}]:1 +# # [permission node] A permission granted for completion. Multiple permissions are space-separated. +# ## permission: 'test.permission' +# # [integer] How much currency to give for completion. (requires an economy plugin) +# ## currency: 0 +# # [integer] How much xp to give to the player for completion. +# ## xp: 0 +# # [List[Text]] Executes the given command upon completion. Prepend with "op" or "console" to run the commands +# as OP or from the Console. Examples: +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +# ## commands: +# ## - 'op: me are the GOD of things' +# ## - 'console: give {party} aweseomestuff 32' +# # reward section to reward the player for completing a repeated challenge (any time after the first). The +# # structure is identical to the 'reward' section. +# repeatReward: +# text: 'Mossy cobblestone' +# items: +# - mossy_cobblestone:16 +# +# ====================================================================================================================== + # [true/false] Enable the use of the challenges command. allowChallenges: true @@ -18,53 +134,59 @@ requirePreviousRank: true # A rankLeeway of 0 would require them all. rankLeeway: 12 -#[integer] The time in hours before required items reset to default. (only if not specified in the challenges below) +# [integer] The time in hours before required items reset to default. (only if not specified in the challenges below) defaultResetInHours: 20 -#[color code] The color to use for uncompleted challenges in the list. +# [integer] The default radius in blocks when using onIsland. Can be overridden in the challenges below. +radius: 10 + +# [integer] The maximum number of times a challenge can be completed by default. 0 means unlimited. Can be overridden in the challenge definition below. +repeatLimit: 0 + +# [color code] The color to use for uncompleted challenges in the list. challengeColor: '&e' -#[color code] The color to use for completed challenges in the list. (non-repeatable) +# [color code] The color to use for completed challenges in the list. (non-repeatable) finishedColor: '&2' -#[color code] The color to use for completed challenges in the list. (repeatable) +# [color code] The color to use for completed challenges in the list. (repeatable) repeatableColor: '&a' -#[true/false] If true, enables vault to handle currency rewards. +# [true/false] If true, enables vault to handle currency rewards. enableEconomyPlugin: true # [true/false] If false, challenges are not reset on island creation (or restart) resetChallengesOnCreate: true # Material to show for locked challenges (i.e. STAINED_GLASS_PANE:14 for a red glass-pane, or 160:14) -lockedDisplayItem: RED_STAINED_GLASS_PANE +lockedDisplayItem: red_stained_glass_pane # Material to show for onIsland challenges when locked ISLAND: - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + lockedDisplayItem: blue_stained_glass_pane # Material to show for islandLevel challenges when locked ISLAND_LEVEL: - lockedDisplayItem: BLACK_STAINED_GLASS_PANE + lockedDisplayItem: black_stained_glass_pane -# Whether or not to show the name of locked challenges +# Whether to show the name of locked challenges showLockedChallengeName: true # When creating your own challenges you will have # to uncomment the section below or the default challenges # will be re-added on every server restart. When altering # the default challenges this should be fine to leave. -#merge-ignore: +# merge-ignore: # - 'ranks' # -#=============================================== +# =============================================== # An explanation to setup your own challenges # can be found at the bottom of this file. -#=============================================== +# =============================================== ranks: Tier1: name: '&7Novice' - displayItem: CYAN_TERRACOTTA + displayItem: cyan_terracotta resetInHours: 20 challenges: cobblestonegenerator: @@ -72,24 +194,24 @@ ranks: description: Mine from a cobblestone generator. type: onPlayer requiredItems: - - COBBLESTONE:64;+2 - displayItem: COBBLESTONE - lockedDisplayItem: GRAY_STAINED_GLASS_PANE + - cobblestone:64;+2 + displayItem: cobblestone + lockedDisplayItem: gray_stained_glass_pane resetInHours: 12 reward: text: 3 leather, 20% chance to get a book items: - - LEATHER:3 - - '{p=0.2}BOOK:1' + - leather:3 + - '{p=0.2}book:1' currency: 10 xp: 10 commands: - - op:effect give {player} regeneration + - op:effect give {player} regeneration repeatReward: text: 1 leather, 10% chance to get a book items: - - LEATHER:1 - - '{p=0.1}BOOK:1' + - leather:1 + - '{p=0.1}book:1' currency: 5 xp: 5 applecollector: @@ -97,45 +219,45 @@ ranks: description: Collect apples from trees. type: onPlayer requiredItems: - - APPLE:2;+1 - displayItem: APPLE - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - apple:2;+1 + displayItem: apple + lockedDisplayItem: brown_stained_glass_pane resetInHours: 6 reward: text: 1 of each sapling, (4 dark oak) items: - - OAK_SAPLING:1 - - SPRUCE_SAPLING:1 - - BIRCH_SAPLING:1 - - JUNGLE_SAPLING:1 - - ACACIA_SAPLING:1 - - DARK_OAK_SAPLING:4 - - '{p=0.2}JUNGLE_SAPLING:3' + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.2}jungle_sapling:3' currency: 20 xp: 20 repeatReward: text: 1 of each sapling (4 dark oak) items: - - OAK_SAPLING:1 - - SPRUCE_SAPLING:1 - - BIRCH_SAPLING:1 - - JUNGLE_SAPLING:1 - - ACACIA_SAPLING:1 - - DARK_OAK_SAPLING:4 - - '{p=0.1}JUNGLE_SAPLING:3' + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.1}jungle_sapling:3' currency: 10 xp: 10 sugarplanter: name: '&9Sugar Planter' type: onIsland - displayItem: SUGAR_CANE - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane requiredItems: - - SUGAR_CANE:4 + - sugar_cane:4 reward: text: 4 dirt items: - - DIRT:4 + - dirt:4 currency: 20 xp: 20 sugarfarmer: @@ -143,22 +265,22 @@ ranks: description: Harvest sugarcane from a farm. type: onPlayer requiredItems: - - SUGAR_CANE:64;+16 + - sugar_cane:64;+16 offset: -1 - displayItem: SUGAR_CANE - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 dirt items: - - DIRT:8 - - '{p=0.1}BONE:1' + - dirt:8 + - '{p=0.1}bone:1' currency: 20 xp: 20 repeatReward: text: 4 dirt items: - - DIRT:4 - - '{p=0.05}DIRT:4' + - dirt:4 + - '{p=0.05}dirt:4' currency: 10 xp: 10 melonfarmer: @@ -166,19 +288,19 @@ ranks: description: Harvest slices of melon from a farm. type: onPlayer requiredItems: - - MELON_SLICE:128;+8 - displayItem: MELON - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - melon_slice:128;+8 + displayItem: melon + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 dirt items: - - DIRT:8 + - dirt:8 currency: 20 xp: 20 repeatReward: text: 4 dirt items: - - DIRT:4 + - dirt:4 currency: 10 xp: 10 cactusfarmer: @@ -186,22 +308,22 @@ ranks: description: Harvest cacti from a farm. type: onPlayer requiredItems: - - CACTUS:64;+16 - displayItem: CACTUS - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - cactus:64;+16 + displayItem: cactus + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 sand, 20% chance to get a bone items: - - SAND:8 - - '{p=0.2}BONE:1' - - '{p=0.1}WOODEN_HOE:1' + - sand:8 + - '{p=0.2}bone:1' + - '{p=0.1}wooden_hoe:1' currency: 20 xp: 20 repeatReward: text: 4 sand items: - - SAND:4 - - '{p=0.1}BONE:1' + - sand:4 + - '{p=0.1}bone:1' currency: 10 xp: 10 pumpkinfarmer: @@ -209,21 +331,21 @@ ranks: description: Harvest pumpkins from a farm. type: onPlayer requiredItems: - - PUMPKIN:64;+4 - displayItem: PUMPKIN - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - pumpkin:64;+4 + displayItem: pumpkin + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 dirt items: - - DIRT:8 - - '{p=0.3}JACK_O_LANTERN:1' + - dirt:8 + - '{p=0.3}jack_o_lantern:1' currency: 20 xp: 20 repeatReward: text: 4 dirt items: - - DIRT:4 - - '{p=0.05}JACK_O_LANTERN:1' + - dirt:4 + - '{p=0.05}jack_o_lantern:1' currency: 10 xp: 10 stonebrickmaker: @@ -231,25 +353,25 @@ ranks: description: Make 64 Stone Bricks. type: onPlayer requiredItems: - - STONE_BRICKS:64;+8 - - STONE_BRICK_SLAB:30;+6 - - CHISELED_STONE_BRICKS:30;+6 - - STONE_BRICK_STAIRS:16;+4 - displayItem: STONE_BRICKS - lockedDisplayItem: GRAY_STAINED_GLASS_PANE + - stone_bricks:64;+8 + - stone_brick_slab:30;+6 + - chiseled_stone_bricks:30;+6 + - stone_brick_stairs:16;+4 + displayItem: stone_bricks + lockedDisplayItem: gray_stained_glass_pane reward: text: 4 redstone ore, 4 iron ore, 1 chicken items: - - REDSTONE_ORE:4 - - IRON_ORE:4 - - CHICKEN_SPAWN_EGG:1 + - redstone_ore:4 + - iron_ore:4 + - chicken_spawn_egg:1 currency: 30 xp: 30 repeatReward: text: 1 redstone ore, 1 iron ore items: - - REDSTONE_ORE:1 - - IRON_ORE:1 + - redstone_ore:1 + - iron_ore:1 currency: 15 xp: 15 novicebuilder: @@ -257,31 +379,31 @@ ranks: description: Reach island level 20. type: islandLevel requiredLevel: 20 - displayItem: COAL_ORE + displayItem: coal_ore reward: text: 8 dirt, 8 sand, 5 emeralds items: - - DIRT:8 - - SAND:8 - - EMERALD:5 - - DIAMOND:1 + - dirt:8 + - sand:8 + - emerald:5 + - diamond:1 currency: 20 xp: 20 commands: - - op:effect give {party} regeneration + - op:effect give {party} regeneration adeptbuilder: name: '&aAdept Builder' description: Reach island level 50. type: islandLevel requiredLevel: 50 - displayItem: IRON_ORE + displayItem: iron_ore offset: -1 reward: text: 10 obsidian, 2 diamonds, 5 emeralds items: - - OBSIDIAN:10 - - EMERALD:5 - - DIAMOND:2 + - obsidian:10 + - emerald:5 + - diamond:2 currency: 100 xp: 100 expertbuilder: @@ -289,15 +411,15 @@ ranks: description: Reach island level 100. type: islandLevel requiredLevel: 100 - displayItem: GOLD_ORE + displayItem: gold_ore offset: -1 reward: text: 16 dirt, 16 sand, 3 diamonds, 5 emeralds items: - - DIRT:16 - - SAND:16 - - EMERALD:5 - - DIAMOND:3 + - dirt:16 + - sand:16 + - emerald:5 + - diamond:3 currency: 250 xp: 250 masterbuilder: @@ -305,15 +427,15 @@ ranks: description: Reach island level 250. type: islandLevel requiredLevel: 250 - displayItem: DIAMOND_ORE + displayItem: diamond_ore offset: -1 reward: text: 32 dirt, 32 sand, 4 diamonds, 5 emeralds items: - - DIRT:32 - - SAND:32 - - EMERALD:5 - - DIAMOND:4 + - dirt:32 + - sand:32 + - emerald:5 + - diamond:4 currency: 500 xp: 500 skylord: @@ -321,55 +443,55 @@ ranks: description: Reach island level 500. type: islandLevel requiredLevel: 500 - displayItem: EMERALD_ORE + displayItem: emerald_ore offset: -1 reward: text: 64 dirt, 64 sand, 5 diamond, 5 emeralds items: - - DIRT:64 - - SAND:64 - - DIAMOND:5 - - EMERALD:5 + - dirt:64 + - sand:64 + - diamond:5 + - emerald:5 currency: 1000 xp: 1000 Tier2: name: '&aAdept' - displayItem: LIME_TERRACOTTA + displayItem: lime_terracotta resetInHours: 20 requires: # means disabled in effect rankLeeway: 99 challenges: - - cobblestonegenerator - - novicebuilder + - cobblestonegenerator + - novicebuilder challenges: lumberjack: name: '&3Lumberjack' description: Collect all types of wood logs. type: onPlayer requiredItems: - - OAK_LOG:16;+2 - - SPRUCE_LOG:16;+2 - - BIRCH_LOG:16;+2 - - JUNGLE_LOG:16;+2 - - ACACIA_LOG:16;+2 - - DARK_OAK_LOG:16;+2 - displayItem: OAK_LOG - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - oak_log:16;+2 + - spruce_log:16;+2 + - birch_log:16;+2 + - jungle_log:16;+2 + - acacia_log:16;+2 + - dark_oak_log:16;+2 + displayItem: oak_log + lockedDisplayItem: cyan_stained_glass_pane reward: text: 4 redstone ore, 4 iron ore, 1 wolf items: - - REDSTONE_ORE:4 - - IRON_ORE:4 - - WOLF_SPAWN_EGG:1 + - redstone_ore:4 + - iron_ore:4 + - wolf_spawn_egg:1 currency: 30 xp: 30 repeatReward: text: 1 redstone ore, 1 iron ore items: - - REDSTONE_ORE:1 - - IRON_ORE:1 + - redstone_ore:1 + - iron_ore:1 currency: 15 xp: 15 shroompicker: @@ -377,23 +499,23 @@ ranks: description: Collect red and brown mushrooms. type: onPlayer requiredItems: - - BROWN_MUSHROOM:64;+4 - - RED_MUSHROOM:64;+4 - displayItem: RED_MUSHROOM - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - brown_mushroom:64;+4 + - red_mushroom:64;+4 + displayItem: red_mushroom + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 mycelium, 4 podzol items: - - MYCELIUM:8 - - PODZOL:4 + - mycelium:8 + - podzol:4 currency: 30 xp: 30 repeatReward: text: 4 mycelium items: - - MYCELIUM:4 - - '{p=0.02}MYCELIUM:4' - - '{p=0.02}PODZOL:2' + - mycelium:4 + - '{p=0.02}mycelium:4' + - '{p=0.02}podzol:2' currency: 15 xp: 15 potatofarmer: @@ -401,27 +523,27 @@ ranks: description: Harvest potato's from a farm. type: onPlayer requiredItems: - - POTATO:64;+16 - displayItem: POTATO - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - potato:64;+16 + displayItem: potato + lockedDisplayItem: brown_stained_glass_pane reward: text: 1 carrot, 4 dirt items: - - CARROT:1 - - DIRT:4 - - '{p=0.10}BEETROOT_SEEDS:1' - - '{p=0.05}RED_SAND:1' - - '{p=0.01}DIAMOND:1' + - carrot:1 + - dirt:4 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' currency: 50 xp: 50 repeatReward: text: 4 dirt and a baked potato items: - - DIRT:4 - - BAKED_POTATO:1 - - '{p=0.10}BEETROOT_SEEDS:1' - - '{p=0.05}RED_SAND:1' - - '{p=0.01}DIAMOND:1' + - dirt:4 + - baked_potato:1 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' currency: 25 xp: 25 carrotfarmer: @@ -429,25 +551,25 @@ ranks: description: Harvest carrot's from a farm. type: onPlayer requiredItems: - - CARROT:64;+16 - displayItem: CARROT - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - carrot:64;+16 + displayItem: carrot + lockedDisplayItem: brown_stained_glass_pane reward: text: a pig with saddle and a potato items: - - SADDLE:1 - - POTATO:1 - - PIG_SPAWN_EGG:1 - - '{p=0.05}RED_SAND:1' - - '{p=0.01}DIAMOND:1' + - saddle:1 + - potato:1 + - pig_spawn_egg:1 + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' currency: 50 xp: 50 repeatReward: text: 1 golden carrot items: - - GOLDEN_CARROT:1 - - '{p=0.05}SAND:1' - - '{p=0.01}DIAMOND:1' + - golden_carrot:1 + - '{p=0.05}sand:1' + - '{p=0.01}diamond:1' currency: 25 xp: 25 wheatfarmer: @@ -455,20 +577,20 @@ ranks: description: Harvest wheat from a farm. type: onPlayer requiredItems: - - WHEAT:64;+16 - displayItem: WHEAT - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - wheat:64;+16 + displayItem: wheat + lockedDisplayItem: brown_stained_glass_pane reward: text: 8 dirt items: - - DIRT:8 + - dirt:8 currency: 20 xp: 20 repeatReward: text: 4 dirt items: - - DIRT:4 - - '{p=0.2}BONE:1' + - dirt:4 + - '{p=0.2}bone:1' currency: 10 xp: 10 monsterfarm: @@ -476,32 +598,32 @@ ranks: description: Build a mob farm and collect mob loot. type: onPlayer requiredItems: - - ROTTEN_FLESH:64;+4 - - STRING:32;+2 - - ARROW:32;+2 - - BONE:32;+2 - - GUNPOWDER:16;+1 - - SPIDER_EYE:5 - displayItem: ROTTEN_FLESH - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - rotten_flesh:64;+4 + - string:32;+2 + - arrow:32;+2 + - bone:32;+2 + - gunpowder:16;+1 + - spider_eye:5 + displayItem: rotten_flesh + lockedDisplayItem: purple_stained_glass_pane reward: text: 4 redstone ore, 4 iron ore and 1 flint items: - - REDSTONE_ORE:4 - - IRON_ORE:4 - - FLINT:1 - - '{p=0.10}POTATO:1' - - '{p=0.10}CARROT:1' + - redstone_ore:4 + - iron_ore:4 + - flint:1 + - '{p=0.10}potato:1' + - '{p=0.10}carrot:1' currency: 30 xp: 30 repeatReward: text: 1 redstone ore, 1 iron ore, 1 flint items: - - REDSTONE_ORE:1 - - IRON_ORE:4 - - FLINT:1 - - '{p=0.05}POTATO:1' - - '{p=0.05}CARROT:1' + - redstone_ore:1 + - iron_ore:4 + - flint:1 + - '{p=0.05}potato:1' + - '{p=0.05}carrot:1' currency: 15 xp: 15 homeowner: @@ -509,24 +631,24 @@ ranks: description: Build a house with furnishings. type: onIsland requiredChallenges: - - stonebrickmaker + - stonebrickmaker requiredItems: - - RED_BED:1 - - CRAFTING_TABLE:1 - - GLASS:1 - - OAK_DOOR:1 - - FURNACE:1 - - BOOKSHELF:1 - - TORCH:1 - lockedDisplayItem: BLUE_STAINED_GLASS_PANE - displayItem: OAK_DOOR + - red_bed:1 + - crafting_table:1 + - glass:1 + - oak_door:1 + - furnace:1 + - bookshelf:1 + - torch:1 + lockedDisplayItem: blue_stained_glass_pane + displayItem: oak_door reward: text: 4 redstone ore, 5 inksac, 4 iron ore and some seeds items: - - REDSTONE_ORE:4 - - IRON_ORE:4 - - INK_SAC:5 - - BEETROOT_SEEDS:1 + - redstone_ore:4 + - iron_ore:4 + - ink_sac:5 + - beetroot_seeds:1 currency: 40 xp: 40 netherportal: @@ -534,75 +656,75 @@ ranks: description: Build a nether portal on your island. type: onIsland requiredChallenges: - - adeptbuilder - - homeowner + - adeptbuilder + - homeowner requiredItems: - - OBSIDIAN:10 - - NETHER_PORTAL:1 - displayItem: OBSIDIAN - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + - obsidian:10 + - nether_portal:1 + displayItem: obsidian + lockedDisplayItem: blue_stained_glass_pane reward: text: 1 iron pickaxe, 1 iron shovel items: - - IRON_SHOVEL:1 - - IRON_PICKAXE:1 + - iron_shovel:1 + - iron_pickaxe:1 currency: 40 xp: 40 nethermining: name: '&7Nether Mining' description: Mine from your Nether island. type: onPlayer - displayItem: NETHERRACK - lockedDisplayItem: GRAY_STAINED_GLASS_PANE + displayItem: netherrack + lockedDisplayItem: gray_stained_glass_pane offset: -1 requiredItems: - - NETHERRACK:64;+2 - - SOUL_SAND:16;+2 - - GRAVEL:16;+2 - - QUARTZ:32;+2 - - GLOWSTONE:16;+2 - - COARSE_DIRT:4;+2 + - netherrack:64;+2 + - soul_sand:16;+2 + - gravel:16;+2 + - quartz:32;+2 + - glowstone:16;+2 + - coarse_dirt:4;+2 reward: text: 1 ghast tear, 1 magic bow items: - - GHAST_TEAR:1 - - 'BOW:1 {Enchantments:[{id:"minecraft:infinity",lvl:1},{id:"minecraft:unbreaking",lvl:3}]}' + - ghast_tear:1 + - 'bow[enchantments={levels:{infinity:1,unbreaking:3}}]:1' currency: 40 xp: 40 repeatReward: text: a blaze-rod and a chance of ghast tear items: - - BLAZE_ROD:1 - - '{p=0.10}GHAST_TEAR:1' + - blaze_rod:1 + - '{p=0.10}ghast_tear:1' currency: 20 xp: 20 Tier3: name: '&eExpert' - displayItem: YELLOW_TERRACOTTA + displayItem: yellow_terracotta resetInHours: 20 requires: challenges: - - adeptbuilder + - adeptbuilder challenges: toolmaker: name: '&3Tool Maker' description: Make all stone tools type: onPlayer requiredChallenges: - - lumberjack + - lumberjack requiredItems: - - STONE_SHOVEL:1 - - STONE_PICKAXE:1 - - STONE_AXE:1 - - STONE_HOE:1 - displayItem: STONE_AXE - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - stone_shovel:1 + - stone_pickaxe:1 + - stone_axe:1 + - stone_hoe:1 + displayItem: stone_axe + lockedDisplayItem: cyan_stained_glass_pane reward: text: 4 redstone ore, 4 iron, 1 pig items: - - REDSTONE_ORE:4 - - IRON_ORE:4 - - PIG_SPAWN_EGG:1 + - redstone_ore:4 + - iron_ore:4 + - pig_spawn_egg:1 currency: 30 xp: 30 sawmill: @@ -611,31 +733,31 @@ ranks: type: onPlayer offset: -1 requiredChallenges: - - toolmaker + - toolmaker requiredItems: - - STRIPPED_OAK_LOG:8;+2 - - STRIPPED_SPRUCE_LOG:8;+2 - - STRIPPED_BIRCH_LOG:8;+2 - - STRIPPED_JUNGLE_LOG:8;+2 - - STRIPPED_ACACIA_LOG:8;+2 - - STRIPPED_DARK_OAK_LOG:8;+2 - displayItem: IRON_AXE - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - stripped_oak_log:8;+2 + - stripped_spruce_log:8;+2 + - stripped_birch_log:8;+2 + - stripped_jungle_log:8;+2 + - stripped_acacia_log:8;+2 + - stripped_dark_oak_log:8;+2 + displayItem: iron_axe + lockedDisplayItem: cyan_stained_glass_pane reward: text: 4 redstone ore, 4 iron, cocoa and a mule items: - - COCOA_BEANS:1 - - REDSTONE_ORE:4 - - IRON_ORE:4 - - MULE_SPAWN_EGG:1 + - cocoa_beans:1 + - redstone_ore:4 + - iron_ore:4 + - mule_spawn_egg:1 currency: 30 xp: 30 repeatReward: text: 1 redstone ore, 1 iron ore items: - - REDSTONE_ORE:1 - - IRON_ORE:1 - - '{p=0.05}GOLD_ORE:1' + - redstone_ore:1 + - iron_ore:1 + - '{p=0.05}gold_ore:1' currency: 15 xp: 15 torchmaker: @@ -643,62 +765,62 @@ ranks: description: Make 128 torches. type: onPlayer requiredChallenges: - - lumberjack + - lumberjack requiredItems: - - TORCH:128;+32 - displayItem: TORCH - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - torch:128;+32 + displayItem: torch + lockedDisplayItem: cyan_stained_glass_pane reward: text: 4 redstone ore, 4 iron ore items: - - REDSTONE_ORE:4 - - IRON_ORE:4 + - redstone_ore:4 + - iron_ore:4 currency: 30 xp: 30 repeatReward: text: 1 redstone ore, 1 iron ore items: - - REDSTONE_ORE:1 - - IRON_ORE:1 + - redstone_ore:1 + - iron_ore:1 currency: 15 xp: 15 expertfarmer: name: '&6Expert Farmer' description: Harvest many different farming resources. type: onPlayer - displayItem: IRON_HOE - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + displayItem: iron_hoe + lockedDisplayItem: brown_stained_glass_pane requiredChallenges: - - applecollector - - melonfarmer - - pumpkinfarmer - - wheatfarmer - - carrotfarmer - - potatofarmer - - cactusfarmer - - sugarfarmer - - shroompicker + - applecollector + - melonfarmer + - pumpkinfarmer + - wheatfarmer + - carrotfarmer + - potatofarmer + - cactusfarmer + - sugarfarmer + - shroompicker requiredItems: - - MELON_SLICE:256;+2 - - SUGAR_CANE:128;+2 - - WHEAT:128;+2 - - POTATO:128;+2 - - CARROT:128;+2 - - PUMPKIN:128;+2 - - CACTUS:128;+2 - - BEETROOT:128;+2 + - melon_slice:256;+2 + - sugar_cane:128;+2 + - wheat:128;+2 + - potato:128;+2 + - carrot:128;+2 + - pumpkin:128;+2 + - cactus:128;+2 + - beetroot:128;+2 reward: text: a bucket, cocoa and a cow items: - - BUCKET:1 - - COCOA_BEANS:1 - - COW_SPAWN_EGG:1 + - bucket:1 + - cocoa_beans:1 + - cow_spawn_egg:1 currency: 50 xp: 50 repeatReward: text: a cow items: - - COW_SPAWN_EGG:1 + - cow_spawn_egg:1 currency: 25 xp: 25 fisherman: @@ -706,75 +828,75 @@ ranks: description: Catch different types of fish. type: onPlayer requiredItems: - - COD:5;+1 - - SALMON:5;+1 - - PUFFERFISH:3;+1 - - TROPICAL_FISH:1;+0 - - INK_SAC:5;+2 - displayItem: COD - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - cod:5;+1 + - salmon:5;+1 + - pufferfish:3;+1 + - tropical_fish:1;+0 + - ink_sac:5;+2 + displayItem: cod + lockedDisplayItem: purple_stained_glass_pane reward: text: 10 lapis blocks, 20 prismarine, kelp, deep-ocean items: - - LAPIS_BLOCK:10 - - PRISMARINE:20 - - KELP:1 - - '{p=0.20}PRISMARINE_CRYSTALS:5' + - lapis_block:10 + - prismarine:20 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' permission: usb.biome.deep_ocean currency: 50 xp: 50 repeatReward: text: 2 lapis, 5 prismarine, kelp and a chance at prismarine crystals items: - - LAPIS_LAZULI:2 - - PRISMARINE:5 - - KELP:1 - - '{p=0.20}PRISMARINE_CRYSTALS:5' + - lapis_lazuli:2 + - prismarine:5 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' currency: 25 xp: 25 woolcollector: name: '&5Wool Collector' description: Collect every color of wool. type: onPlayer - displayItem: WHITE_WOOL - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + displayItem: white_wool + lockedDisplayItem: purple_stained_glass_pane requiredChallenges: - - monsterfarmer + - monsterfarmer requiredItems: - - WHITE_WOOL:2;+4 - - ORANGE_WOOL:2;+4 - - MAGENTA_WOOL:2;+4 - - LIGHT_BLUE_WOOL:2;+4 - - YELLOW_WOOL:2;+4 - - LIME_WOOL:2;+4 - - PINK_WOOL:2;+4 - - GRAY_WOOL:2;+4 - - LIGHT_GRAY_WOOL:2;+4 - - CYAN_WOOL:2;+4 - - PURPLE_WOOL:2;+4 - - BLUE_WOOL:2;+4 - - BROWN_WOOL:2;+4 - - GREEN_WOOL:2;+4 - - RED_WOOL:2;+4 - - BLACK_WOOL:2;+4 + - white_wool:2;+4 + - orange_wool:2;+4 + - magenta_wool:2;+4 + - light_blue_wool:2;+4 + - yellow_wool:2;+4 + - lime_wool:2;+4 + - pink_wool:2;+4 + - gray_wool:2;+4 + - light_gray_wool:2;+4 + - cyan_wool:2;+4 + - purple_wool:2;+4 + - blue_wool:2;+4 + - brown_wool:2;+4 + - green_wool:2;+4 + - red_wool:2;+4 + - black_wool:2;+4 reward: text: 2 diamonds, sheep, emerald, flowers items: - - DIAMOND:2 - - EMERALD:1 - - SHEEP_SPAWN_EGG:1 - - ROSE_BUSH:1 - - PEONY:1 + - diamond:2 + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 permission: usb.biome.flower_forest currency: 70 xp: 70 repeatReward: text: emerald, sheep, flowers items: - - EMERALD:1 - - SHEEP_SPAWN_EGG:1 - - ROSE_BUSH:1 - - PEONY:1 + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 currency: 35 xp: 35 maestro: @@ -782,57 +904,57 @@ ranks: description: Make a jukebox and collect all music discs. type: onPlayer requiredItems: - - MUSIC_DISC_13:1 - - MUSIC_DISC_CAT:1 - - MUSIC_DISC_BLOCKS:1 - - MUSIC_DISC_CHIRP:1 - - MUSIC_DISC_FAR:1 - - MUSIC_DISC_MALL:1 - - MUSIC_DISC_MELLOHI:1 - - MUSIC_DISC_STAL:1 - - MUSIC_DISC_STRAD:1 - - MUSIC_DISC_WARD:1 - - MUSIC_DISC_11:1 - - MUSIC_DISC_WAIT:1 - - JUKEBOX:1 - displayItem: JUKEBOX - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - music_disc_13:1 + - music_disc_cat:1 + - music_disc_blocks:1 + - music_disc_chirp:1 + - music_disc_far:1 + - music_disc_mall:1 + - music_disc_mellohi:1 + - music_disc_stal:1 + - music_disc_strad:1 + - music_disc_ward:1 + - music_disc_11:1 + - music_disc_wait:1 + - jukebox:1 + displayItem: jukebox + lockedDisplayItem: purple_stained_glass_pane reward: text: 3 diamonds, 1 gold block, 10 emeralds items: - - DIAMOND:3 - - EMERALD:10 - - GOLD_BLOCK:1 + - diamond:3 + - emerald:10 + - gold_block:1 currency: 70 xp: 70 repeatReward: text: 2 gold ore, 1 diamond items: - - GOLD_ORE:2 - - DIAMOND:1 - - '{p=0.2}DIAMOND:1' + - gold_ore:2 + - diamond:1 + - '{p=0.2}diamond:1' currency: 35 xp: 35 ironfarm: name: '&9Iron Farm' description: Build an iron-farm. type: onIsland - displayItem: IRON_BLOCK - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: iron_block + lockedDisplayItem: blue_stained_glass_pane radius: 50 requiredChallenges: - - monsterfarm - - applecollector + - monsterfarm + - applecollector requiredItems: - - OAK_DOOR:30 + - oak_door:30 requiredEntities: - - Villager:10 - - IRON_GOLEM:1 + - Villager:10 + - IRON_GOLEM:1 reward: text: 2 gold blocks, 1 diamond block items: - - GOLD_BLOCK:2 - - DIAMOND_BLOCK:1 + - gold_block:2 + - diamond_block:1 currency: 500 xp: 400 netherfortress: @@ -841,78 +963,78 @@ ranks: type: onIsland radius: 50 requiredItems: - - NETHER_BRICKS:512 - - NETHER_BRICK_SLAB:64 - - NETHER_BRICK_FENCE:64 - - NETHER_BRICK_STAIRS:64 - - SOUL_SAND:32 - displayItem: NETHER_BRICK_FENCE - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + - nether_bricks:512 + - nether_brick_slab:64 + - nether_brick_fence:64 + - nether_brick_stairs:64 + - soul_sand:32 + displayItem: nether_brick_fence + lockedDisplayItem: blue_stained_glass_pane reward: text: a wither-skull and a blaze rod and a chance of diamonds items: - - WITHER_SKELETON_SKULL:1 - - BLAZE_ROD:1 - - '{p=0.05}DIAMOND:3' - - '{p=0.10}DIAMOND:2' - - '{p=0.15}DIAMOND:1' + - wither_skeleton_skull:1 + - blaze_rod:1 + - '{p=0.05}diamond:3' + - '{p=0.10}diamond:2' + - '{p=0.15}diamond:1' currency: 40 xp: 40 - #=============================================== + # =============================================== Tier4: name: '&cMaster' - displayItem: ORANGE_TERRACOTTA + displayItem: orange_terracotta resetInHours: 20 requires: # disabled rankLeeway: 99 challenges: - - expertbuilder + - expertbuilder challenges: glassmaker: name: '&3Glassmaker' description: Collect every color of stained glass. type: onPlayer - displayItem: WHITE_STAINED_GLASS - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + displayItem: white_stained_glass + lockedDisplayItem: cyan_stained_glass_pane requiredItems: - - WHITE_STAINED_GLASS:8;+2 - - ORANGE_STAINED_GLASS:8;+2 - - MAGENTA_STAINED_GLASS:8;+2 - - LIGHT_BLUE_STAINED_GLASS:8;+2 - - YELLOW_STAINED_GLASS:8;+2 - - LIME_STAINED_GLASS:8;+2 - - PINK_STAINED_GLASS:8;+2 - - GRAY_STAINED_GLASS:8;+2 - - LIGHT_GRAY_STAINED_GLASS:8;+2 - - CYAN_STAINED_GLASS:8;+2 - - PURPLE_STAINED_GLASS:8;+2 - - BLUE_STAINED_GLASS:8;+2 - - BROWN_STAINED_GLASS:8;+2 - - GREEN_STAINED_GLASS:8;+2 - - RED_STAINED_GLASS:8;+2 - - BLACK_STAINED_GLASS:8;+2 + - white_stained_glass:8;+2 + - orange_stained_glass:8;+2 + - magenta_stained_glass:8;+2 + - light_blue_stained_glass:8;+2 + - yellow_stained_glass:8;+2 + - lime_stained_glass:8;+2 + - pink_stained_glass:8;+2 + - gray_stained_glass:8;+2 + - light_gray_stained_glass:8;+2 + - cyan_stained_glass:8;+2 + - purple_stained_glass:8;+2 + - blue_stained_glass:8;+2 + - brown_stained_glass:8;+2 + - green_stained_glass:8;+2 + - red_stained_glass:8;+2 + - black_stained_glass:8;+2 reward: text: 2 diamonds, 2 disks, 1 emeralds items: - - DIAMOND:2 - - MUSIC_DISC_WARD:1 - - MUSIC_DISC_11:1 - - EMERALD:1 - - SUNFLOWER:1 - - LILAC:1 + - diamond:2 + - music_disc_ward:1 + - music_disc_11:1 + - emerald:1 + - sunflower:1 + - lilac:1 permission: usb.biome.flower_forest currency: 70 xp: 70 repeatReward: text: 30% chance on 1 or 2 disks, 1 emeralds items: - - '{p=0.3}MUSIC_DISC_WARD:1' - - '{p=0.3}MUSIC_DISC_11:1' - - EMERALD:1 - - SUNFLOWER:1 - - LILAC:1 + - '{p=0.3}music_disc_ward:1' + - '{p=0.3}music_disc_11:1' + - emerald:1 + - sunflower:1 + - lilac:1 currency: 35 xp: 35 carpenter: @@ -920,34 +1042,34 @@ ranks: description: Collect all types of wood items. type: onPlayer requiredItems: - - JUNGLE_STAIRS:16;+8 - - SPRUCE_DOOR:1;+1 - - DARK_OAK_FENCE_GATE:2;+2 - - ACACIA_FENCE:30;+15 - - LADDER:30;+15 - - OAK_TRAPDOOR:4;+2 - - OAK_PRESSURE_PLATE:2;+1 + - jungle_stairs:16;+8 + - spruce_door:1;+1 + - dark_oak_fence_gate:2;+2 + - acacia_fence:30;+15 + - ladder:30;+15 + - oak_trapdoor:4;+2 + - oak_pressure_plate:2;+1 requiredChallenges: - - toolmaker - - lumberjack:2 - displayItem: CRAFTING_TABLE - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - toolmaker + - lumberjack:2 + displayItem: crafting_table + lockedDisplayItem: cyan_stained_glass_pane reward: text: a parrot and a jukebox with some redstone and iron items: - - PARROT_SPAWN_EGG:1 - - JUKEBOX:1 - - REDSTONE_ORE:4 - - IRON_ORE:4 + - parrot_spawn_egg:1 + - jukebox:1 + - redstone_ore:4 + - iron_ore:4 currency: 30 xp: 30 repeatReward: text: redstone, iron and a slim chance at a parrot items: - - REDSTONE_ORE:1 - - IRON_ORE:1 - - '{p=0.25}JUKEBOX:1' - - '{p=0.05}PARROT_SPAWN_EGG:1' + - redstone_ore:1 + - iron_ore:1 + - '{p=0.25}jukebox:1' + - '{p=0.05}parrot_spawn_egg:1' currency: 15 xp: 15 cookielover: @@ -955,29 +1077,29 @@ ranks: description: Make cookies and a bucket of milk. type: onPlayer requiredChallenges: - - expertfarmer + - expertfarmer requiredItems: - - COOKIE:128;+4 - - MILK_BUCKET:1 - displayItem: COOKIE - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - cookie:128;+4 + - milk_bucket:1 + displayItem: cookie + lockedDisplayItem: yellow_stained_glass_pane reward: text: 4 redstone ore, clay a bucket and a diamond items: - - REDSTONE_ORE:4 - - CLAY:5 - - DIAMOND:1 - - BUCKET:1 + - redstone_ore:4 + - clay:5 + - diamond:1 + - bucket:1 currency: 80 xp: 80 repeatReward: text: iron ore and some clay items: - - IRON_ORE:1 - - CLAY:5 - - BUCKET:1 - - '{p=0.4}CLAY:3' - - '{p=0.3}IRON_ORE:2' + - iron_ore:1 + - clay:5 + - bucket:1 + - '{p=0.4}clay:3' + - '{p=0.3}iron_ore:2' currency: 40 xp: 40 deepseafisherman: @@ -985,33 +1107,33 @@ ranks: description: Farm the deep sea type: onPlayer requiredItems: - - COD:10;+5 - - SALMON:10;+5 - - PUFFERFISH:5;+3 - - TROPICAL_FISH:3;+2 - - PRISMARINE_CRYSTALS:16;+8 - - PRISMARINE_SHARD:16;+8 - - DRIED_KELP_BLOCK:64;+32 - - NAUTILUS_SHELL:1 - displayItem: HEART_OF_THE_SEA - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - cod:10;+5 + - salmon:10;+5 + - pufferfish:5;+3 + - tropical_fish:3;+2 + - prismarine_crystals:16;+8 + - prismarine_shard:16;+8 + - dried_kelp_block:64;+32 + - nautilus_shell:1 + displayItem: heart_of_the_sea + lockedDisplayItem: purple_stained_glass_pane reward: text: heart-of-the-sea, nautilus shell and a turtle items: - - NAUTILUS_SHELL:1 - - HEART_OF_THE_SEA:1 - - TURTLE_SPAWN_EGG:1 - - '{p=0.1}NAUTILUS_SHELL:1' + - nautilus_shell:1 + - heart_of_the_sea:1 + - turtle_spawn_egg:1 + - '{p=0.1}nautilus_shell:1' permission: usb.biome.deep_ocean currency: 50 xp: 50 repeatReward: text: nautilus shell, turtle and a chance of a heart items: - - NAUTILUS_SHELL:1 - - TURTLE_SPAWN_EGG:1 - - '{p=0.05}HEART_OF_THE_SEA:1' - - '{p=0.1}NAUTILUS_SHELL:1' + - nautilus_shell:1 + - turtle_spawn_egg:1 + - '{p=0.05}heart_of_the_sea:1' + - '{p=0.1}nautilus_shell:1' currency: 25 xp: 25 horsingaround: @@ -1019,27 +1141,27 @@ ranks: description: Get hay bales for the horses. type: onPlayer requiredItems: - - HAY_BLOCK:32;+4 - - LEAD:8;+2 - - CARROT_ON_A_STICK:1 - - SHEARS:1 + - hay_block:32;+4 + - lead:8;+2 + - carrot_on_a_stick:1 + - shears:1 requirecChallenges: - - wheatfarmer - displayItem: HAY_BLOCK - lockedDisplayItem: BROWN_STAINED_GLASS_PANE + - wheatfarmer + displayItem: hay_block + lockedDisplayItem: brown_stained_glass_pane reward: text: 1 horse, 1 iron horse armor, 5% chance on diamond horse armor items: - - IRON_HORSE_ARMOR:1 - - HORSE_SPAWN_EGG:1 - - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}diamond_horse_armor:1' currency: 50 xp: 50 repeatReward: text: 1 redstone ore, 1 emerald items: - - REDSTONE:1 - - EMERALD:1 + - redstone:1 + - emerald:1 currency: 25 xp: 25 slimefarmer: @@ -1047,72 +1169,72 @@ ranks: description: Collect slimeballs from slimes. type: onPlayer requiredItems: - - SLIME_BALL:64;+4 - displayItem: SLIME_BALL - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - slime_ball:64;+4 + displayItem: slime_ball + lockedDisplayItem: purple_stained_glass_pane reward: text: 1 diamond, 1 emeralds, swampland items: - - DIAMOND:1 - - EMERALD:1 + - diamond:1 + - emerald:1 permission: usb.biome.swamp currency: 70 xp: 70 repeatReward: text: 1 redstone ore, 1 emeralds items: - - REDSTONE_ORE:1 - - EMERALD:1 + - redstone_ore:1 + - emerald:1 currency: 35 xp: 35 animalfarm: name: '&9Animal Farm' description: Create an animal farm. type: onIsland - displayItem: OAK_FENCE + displayItem: oak_fence radius: 40 requiredChallenges: - - woolcollector - - potatofarmer - - carrotfarmer + - woolcollector + - potatofarmer + - carrotfarmer requiredEntities: - - Cow:8 - - Pig:8 - - Chicken:16 - - Sheep:{"Color":"WHITE"} - - Sheep:{"Color":"ORANGE"} - - Sheep:{"Color":"MAGENTA"} - - Sheep:{"Color":"LIGHT_BLUE"} - - Sheep:{"Color":"YELLOW"} - - Sheep:{"Color":"LIME"} - - Sheep:{"Color":"PINK"} - - Sheep:{"Color":"GRAY"} - - Sheep:{"Color":"LIGHT_GRAY"} - - Sheep:{"Color":"CYAN"} - - Sheep:{"Color":"PURPLE"} - - Sheep:{"Color":"BLUE"} - - Sheep:{"Color":"BROWN"} - - Sheep:{"Color":"GREEN"} - - Sheep:{"Color":"RED"} - - Sheep:{"Color":"BLACK"} + - Cow:8 + - Pig:8 + - Chicken:16 + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} reward: text: 1 horse, 1 iron horse armor, 5% chance horse armor items: - - IRON_HORSE_ARMOR:1 - - HORSE_SPAWN_EGG:1 - - '{p=0.05}IRON_HORSE_ARMOR:1' - - '{p=0.05}GOLDEN_HORSE_ARMOR:1' - - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' currency: 50 xp: 50 repeatReward: text: 1 redstone ore, 1 emerald, 5% chance horse armor items: - - REDSTONE:1 - - EMERALD:1 - - '{p=0.05}IRON_HORSE_ARMOR:1' - - '{p=0.05}GOLDEN_HORSE_ARMOR:1' - - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + - redstone:1 + - emerald:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' currency: 25 xp: 25 witherhunter: @@ -1120,24 +1242,24 @@ ranks: description: Collect some Wither Skeleton skulls. type: onPlayer requiredChallenges: - - netherfortress + - netherfortress requiredItems: - - WITHER_SKELETON_SKULL:10;+1 - displayItem: WITHER_SKELETON_SKULL - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - wither_skeleton_skull:10;+1 + displayItem: wither_skeleton_skull + lockedDisplayItem: purple_stained_glass_pane offset: -1 reward: text: 5 diamonds, 5% chance of nether star items: - - DIAMOND:5 - - '{p=0.05}NETHER_STAR:1' + - diamond:5 + - '{p=0.05}nether_star:1' currency: 400 xp: 400 repeatReward: text: 2 gold ore, 5% chance of nether star items: - - GOLD_ORE:2 - - '{p=0.05}NETHER_STAR:1' + - gold_ore:2 + - '{p=0.05}nether_star:1' currency: 20 xp: 20 pearlcollector: @@ -1145,69 +1267,69 @@ ranks: description: Collect enderpearls from endermen. type: onPlayer requiredItems: - - ENDER_PEARL:10;+4 - displayItem: ENDER_PEARL - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - ender_pearl:10;+4 + displayItem: ender_pearl + lockedDisplayItem: purple_stained_glass_pane reward: text: 5 gold ore, 1 blaze rod, 1 emerald items: - - GOLD_ORE:5 - - BLAZE_ROD:1 - - EMERALD:1 + - gold_ore:5 + - blaze_rod:1 + - emerald:1 currency: 70 xp: 70 repeatReward: text: 1 gold ore, 1 blaze rod items: - - GOLD_ORE:1 - - BLAZE_ROD:1 + - gold_ore:1 + - blaze_rod:1 currency: 35 xp: 35 - #=============================================== + # =============================================== Tier5: name: '&4Sky Lord' - displayItem: RED_TERRACOTTA + displayItem: red_terracotta resetInHours: 48 requires: challenges: - - masterbuilder + - masterbuilder challenges: technician: name: '&3Technician' description: Collect some of every type of redstone equipment. type: onPlayer requiredItems: - - REDSTONE:64;+16 - - REDSTONE_TORCH:32;+4 - - REPEATER:5;+1 - - COMPARATOR:3;+1 - - PISTON:2;+1 - - STICKY_PISTON:2;+1 - - LEVER:1;+1 - - STONE_BUTTON:1;+1 - - STONE_PRESSURE_PLATE:1;+1 - - HOPPER:1;+1 - - DISPENSER:1;+1 - - DROPPER:1;+1 - - DAYLIGHT_DETECTOR:1;+1 - displayItem: REDSTONE - lockedDisplayItem: CYAN_STAINED_GLASS_PANE + - redstone:64;+16 + - redstone_torch:32;+4 + - repeater:5;+1 + - comparator:3;+1 + - piston:2;+1 + - sticky_piston:2;+1 + - lever:1;+1 + - stone_button:1;+1 + - stone_pressure_plate:1;+1 + - hopper:1;+1 + - dispenser:1;+1 + - dropper:1;+1 + - daylight_detector:1;+1 + displayItem: redstone + lockedDisplayItem: cyan_stained_glass_pane reward: text: some snow, ice and packed ice items: - - SNOW_BLOCK:4 - - ICE:8 - - PACKED_ICE:8 - - REDSTONE_BLOCK:64 + - snow_block:4 + - ice:8 + - packed_ice:8 + - redstone_block:64 currency: 70 xp: 70 repeatReward: text: a stack of redstone blocks and some ice items: - - REDSTONE_BLOCK:64 - - ICE:4 - - PACKED_ICE:1 + - redstone_block:64 + - ice:4 + - packed_ice:1 currency: 35 xp: 35 emeraldcollector: @@ -1215,25 +1337,25 @@ ranks: description: Collect emeralds. type: onPlayer requiredItems: - - EMERALD:60;+10 - displayItem: EMERALD - lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + - emerald:60;+10 + displayItem: emerald + lockedDisplayItem: purple_stained_glass_pane reward: text: a full set of diamond armor items: - - DIAMOND_HELMET:1 - - DIAMOND_CHESTPLATE:1 - - DIAMOND_LEGGINGS:1 - - DIAMOND_BOOTS:1 + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 currency: 70 xp: 70 repeatReward: text: full diamond armor items: - - DIAMOND_HELMET:1 - - DIAMOND_CHESTPLATE:1 - - DIAMOND_LEGGINGS:1 - - DIAMOND_BOOTS:1 + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 currency: 35 xp: 35 topchef: @@ -1241,40 +1363,40 @@ ranks: description: Collect every kind of edible food. type: onPlayer requiredItems: - - BAKED_POTATO:1 - - BREAD:1 - - CAKE:1 - - COOKED_CHICKEN:1 - - COOKED_COD:1 - - COOKED_SALMON:1 - - TROPICAL_FISH:1 - - COOKED_PORKCHOP:1 - - COOKIE:1 - - GOLDEN_APPLE:1 - - GOLDEN_CARROT:1 - - MUSHROOM_STEW:1 - - PUMPKIN_PIE:1 - - COOKED_BEEF:1 - - MELON:1 - - CARROT:1 + - baked_potato:1 + - bread:1 + - cake:1 + - cooked_chicken:1 + - cooked_cod:1 + - cooked_salmon:1 + - tropical_fish:1 + - cooked_porkchop:1 + - cookie:1 + - golden_apple:1 + - golden_carrot:1 + - mushroom_stew:1 + - pumpkin_pie:1 + - cooked_beef:1 + - melon:1 + - carrot:1 requiredChallenges: - - expertfarmer - - fisherman - - cookielover - displayItem: CARROT - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - expertfarmer + - fisherman + - cookielover + displayItem: carrot + lockedDisplayItem: yellow_stained_glass_pane reward: text: 2 diamond, 1 mooshroom items: - - DIAMOND:2 - - MOOSHROOM_SPAWN_EGG:1 + - diamond:2 + - mooshroom_spawn_egg:1 currency: 80 xp: 80 repeatReward: text: 1 diamond, 1 mooshroom items: - - DIAMOND:1 - - MOOSHROOM_SPAWN_EGG:1 + - diamond:1 + - mooshroom_spawn_egg:1 currency: 40 xp: 40 tajmahal: @@ -1282,21 +1404,21 @@ ranks: description: Build a temple of quartz type: onIsland radius: 30 - displayItem: QUARTZ_BLOCK - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: quartz_block + lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - - nethermining + - nethermining requiredItems: - - QUARTZ_BLOCK:512 - - CHISELED_QUARTZ_BLOCK:64 - - QUARTZ_PILLAR:128 - - QUARTZ_STAIRS:64 - - QUARTZ_SLAB:192 + - quartz_block:512 + - chiseled_quartz_block:64 + - quartz_pillar:128 + - quartz_stairs:64 + - quartz_slab:192 reward: text: 3 end-portal frames, red sand items: - - END_PORTAL_FRAME:3 - - RED_SAND:64 + - end_portal_frame:3 + - red_sand:64 currency: 1000 xp: 500 greatpyramid: @@ -1304,21 +1426,21 @@ ranks: description: Build a pyramid of sandstone type: onIsland radius: 30 - displayItem: SANDSTONE - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: sandstone + lockedDisplayItem: blue_stained_glass_pane requiredItems: - - SANDSTONE:512 - - CHISELED_SANDSTONE:64 - - SMOOTH_SANDSTONE:128 - - SANDSTONE_STAIRS:64 - - SANDSTONE_SLAB:192 - - RED_SANDSTONE:16 + - sandstone:512 + - chiseled_sandstone:64 + - smooth_sandstone:128 + - sandstone_stairs:64 + - sandstone_slab:192 + - red_sandstone:16 reward: text: 3 end-portal frames, 3 diamonds, bow items: - - END_PORTAL_FRAME:3 - - DIAMOND:3 - - BOW:1 {Enchantments:[{id:"minecraft:infinity",lvl:1},{id:"minecraft:unbreaking",lvl:3},{id:"minecraft:power",lvl:5}]} + - end_portal_frame:3 + - diamond:3 + - 'bow[enchantments={levels:{infinity:1,power:5,unbreaking:3}}]:1' currency: 1000 xp: 500 poseidonshalls: @@ -1326,36 +1448,36 @@ ranks: description: Build the halls of Poseidon type: onIsland radius: 50 - displayItem: PRISMARINE - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: prismarine + lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - - deepseafisherman + - deepseafisherman requiredItems: - - PRISMARINE:512 - - PRISMARINE_BRICKS:128 - - DARK_PRISMARINE:64 - - SEA_LANTERN:32 - - CONDUIT:1 - - FLOWER_POT:16 - - VINE:128 - - POPPY:10 - - BLUE_ORCHID:10 - - ALLIUM:10 - - AZURE_BLUET:10 - - RED_TULIP:10 - - ORANGE_TULIP:10 - - WHITE_TULIP:10 - - PINK_TULIP:10 - - OXEYE_DAISY:10 - - SUNFLOWER:10 - - LILAC:10 - - ROSE_BUSH:10 - - PEONY:10 + - prismarine:512 + - prismarine_bricks:128 + - dark_prismarine:64 + - sea_lantern:32 + - conduit:1 + - flower_pot:16 + - vine:128 + - poppy:10 + - blue_orchid:10 + - allium:10 + - azure_bluet:10 + - red_tulip:10 + - orange_tulip:10 + - white_tulip:10 + - pink_tulip:10 + - oxeye_daisy:10 + - sunflower:10 + - lilac:10 + - rose_bush:10 + - peony:10 reward: text: 3 end-portal frames, 5 diamonds items: - - END_PORTAL_FRAME:3 - - DIAMOND:5 + - end_portal_frame:3 + - diamond:5 currency: 1000 xp: 500 beaconator: @@ -1363,23 +1485,23 @@ ranks: description: Build a very expensive beacon. type: onIsland radius: 15 - displayItem: BEACON - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: beacon + lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - - netherfortress - - ironfarm - - maestro - - witherhunter + - netherfortress + - ironfarm + - maestro + - witherhunter requiredItems: - - BEACON:1 - - DIAMOND_BLOCK:1 - - EMERALD_BLOCK:8 - - GOLD_BLOCK:25 - - IRON_BLOCK:49 + - beacon:1 + - diamond_block:1 + - emerald_block:8 + - gold_block:25 + - iron_block:49 reward: items: - - END_PORTAL_FRAME:3 - - DIAMOND_SWORD:1 {Enchantments:[{id:"minecraft:sharpness",lvl:5},{id:"minecraft:unbreaking",lvl:3},{id:"minecraft:fire",lvl:1}]} + - end_portal_frame:3 + - 'diamond_sword[enchantments={levels:{fire_aspect:1,sharpness:5,unbreaking:3}}]:1' text: some end-portal-pieces and a magic diamond sword currency: 4000 xp: 1000 @@ -1388,380 +1510,281 @@ ranks: description: Build and activate an end-portal. type: onIsland radius: 15 - displayItem: END_PORTAL_FRAME - lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: end_portal_frame + lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - - beaconator - - tajmahal - - poseidonshalls - - greatpyramid + - beaconator + - tajmahal + - poseidonshalls + - greatpyramid requiredItems: - - END_PORTAL_FRAME:12 - - END_PORTAL:9 + - end_portal_frame:12 + - end_portal:9 reward: text: 5 diamonds and some nice boots items: - - DIAMOND:5 - - DIAMOND_BOOTS:1 {Enchantments:[{id:"minecraft:feather_falling",lvl:4},{id:"minecraft:protection",lvl:4},{id:"minecraft:blast_protection",lvl:4}]} + - diamond:5 + - 'diamond_boots[enchantments={levels:{blast_protection:4,feather_falling:4,protection:4}}]:1' currency: 4000 xp: 1000 - #=============================================== + # =============================================== Tier6: name: '&aWorld Foods' - displayItem: LIGHT_GRAY_TERRACOTTA + displayItem: light_gray_terracotta resetInHours: 20 requires: challenges: - - masterbuilder - - topchef + - masterbuilder + - topchef challenges: fishandchips: name: '&eFish & Chips' description: Create the famous English Fish & Chips. type: onPlayer requiredItems: - - COOKED_COD:32;+8 - - BAKED_POTATO:32;+8 - displayItem: COOKED_COD - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - cooked_cod:32;+8 + - baked_potato:32;+8 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane reward: text: 16 baked potatos, 1 disk, 4 emerald items: - - BAKED_POTATO:16 - - MUSIC_DISC_13:1 - - EMERALD:4 + - baked_potato:16 + - music_disc_13:1 + - emerald:4 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips &2Click the link for more info' repeatReward: text: 30% chance on 1 disk, 1 emerald items: - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_13:1' + - emerald:1 + - '{p=0.3}music_disc_13:1' currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips &2Click the link for more info' smorrebrod: name: '&eSmørrebrød' description: Create the famous Danish smørrebrød. type: onPlayer requiredItems: - - BREAD:16;+4 - - COOKED_SALMON:8;+4 - - TROPICAL_FISH:2;+1 - - COOKED_PORKCHOP:8;+4 - - COOKED_BEEF:8;+4 - displayItem: COOKED_COD - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - bread:16;+4 + - cooked_salmon:8;+4 + - tropical_fish:2;+1 + - cooked_porkchop:8;+4 + - cooked_beef:8;+4 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane reward: text: 1 rod, 2 name tags, 2 ocelots items: - - FISHING_ROD:1 - - NAME_TAG:2 - - OCELOT_SPAWN_EGG:2 + - fishing_rod:1 + - name_tag:2 + - ocelot_spawn_egg:2 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine &2Click the link for more info' repeatReward: text: 1 emerald items: - - EMERALD:1 + - emerald:1 currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine &2Click the link for more info' hutspot: name: '&eHutspot' description: Create the famous Dutch hutspot. type: onPlayer requiredItems: - - POTATO:64;+8 - - CARROT:64;+8 - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE - displayItem: GOLDEN_CARROT + - potato:64;+8 + - carrot:64;+8 + lockedDisplayItem: yellow_stained_glass_pane + displayItem: golden_carrot reward: text: 1 golden carrot, 1 disk, 4 emerald items: - - GOLDEN_CARROT:1 - - MUSIC_DISC_CAT:1 - - EMERALD:4 + - golden_carrot:1 + - music_disc_cat:1 + - emerald:4 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click the link for more info' repeatReward: text: 30% chance on 1 disk, 1 emerald items: - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_CAT:1' + - emerald:1 + - '{p=0.3}music_disc_cat:1' currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click the link for more info' apfelstrudel: name: '&eApfelstrudele' description: Create the famous German apfelstrudel. type: onPlayer requiredItems: - - APPLE:8;+5 - - WHEAT:16;+5 - - SUGAR:16;+5 - - MILK_BUCKET:1 - displayItem: GOLDEN_APPLE - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - apple:8;+5 + - wheat:16;+5 + - sugar:16;+5 + - milk_bucket:1 + displayItem: golden_apple + lockedDisplayItem: yellow_stained_glass_pane reward: text: 1 bucket, 1 disk, 4 emerald items: - - BUCKET:1 - - EMERALD:4 - - MUSIC_DISC_BLOCKS:1 + - bucket:1 + - emerald:4 + - music_disc_blocks:1 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click the link for more info' repeatReward: text: 1 bucket, 30% chance on 1 disk, 1 emerald items: - - BUCKET:1 - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_BLOCKS:1' + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_blocks:1' currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click the link for more info' brownies: name: '&eBrownies' description: Create the famous American brownies. type: onPlayer requiredItems: - - WHEAT:16;+5 - - SUGAR:16;+5 - - EGG:16;+5 - - INK_SAC:16;+5 - - MILK_BUCKET:1 - displayItem: DARK_OAK_SLAB - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - wheat:16;+5 + - sugar:16;+5 + - egg:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: dark_oak_slab + lockedDisplayItem: yellow_stained_glass_pane reward: text: 1 bucket, 1 disk, 4 emerald items: - - BUCKET:1 - - EMERALD:4 - - MUSIC_DISC_FAR:1 + - bucket:1 + - emerald:4 + - music_disc_far:1 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie &2Click the link for more info' repeatReward: text: 1 bucket, 30% chance on 1 disk, 1 emerald items: - - BUCKET:1 - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_FAR:1' + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_far:1' currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie &2Click the link for more info' pastafunghi: name: '&ePasta Funghi' description: Create the famous Italian Pasta Funghi. type: onPlayer requiredItems: - - WHEAT:32;+8 - - EGG:32;+8 - - BROWN_MUSHROOM:16;+4 - - RED_MUSHROOM:16;+4 - - MILK_BUCKET:1 - displayItem: RED_MUSHROOM_BLOCK - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - wheat:32;+8 + - egg:32;+8 + - brown_mushroom:16;+4 + - red_mushroom:16;+4 + - milk_bucket:1 + displayItem: red_mushroom_block + lockedDisplayItem: yellow_stained_glass_pane reward: text: 2 rabbits, 1 bucket items: - - BUCKET:1 - - RABBIT_SPAWN_EGG:2 + - bucket:1 + - rabbit_spawn_egg:2 currency: 60 xp: 60 commands: - - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the - link for more info + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info repeatReward: text: 30% chance on 1 disk, 1 emerald items: - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_13:1' + - emerald:1 + - '{p=0.3}music_disc_13:1' currency: 30 xp: 30 commands: - - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the - link for more info + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info chocolate: name: '&eBelgian chocolate' description: Create the famous belgian chocolate. type: onPlayer requiredItems: - - SUGAR:16;+5 - - INK_SAC:16;+5 - - MILK_BUCKET:1 - displayItem: PIG_SPAWN_EGG - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - sugar:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: pig_spawn_egg + lockedDisplayItem: yellow_stained_glass_pane reward: text: 1 bucket, 1 disk, 4 emeralds items: - - BUCKET:1 - - EMERALD:4 - - MUSIC_DISC_MALL:1 + - bucket:1 + - emerald:4 + - music_disc_mall:1 currency: 60 xp: 60 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate &2Click the link for more info' repeatReward: text: 1 bucket, 30% chance on 1 disk, 1 emerald items: - - BUCKET:1 - - EMERALD:1 - - '{p=0.3}MUSIC_DISC_MALL:1' + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_mall:1' currency: 30 xp: 30 commands: - - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate &2Click the link for more info' baker: name: '&ePâtisserie' description: Bake cakes, pumpkin pies, and cookies. type: onPlayer requiredItems: - - CAKE:5;+1 - - PUMPKIN_PIE:5;+1 - - COOKIE:128;+4 - displayItem: CAKE - lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + - cake:5;+1 + - pumpkin_pie:5;+1 + - cookie:128;+4 + displayItem: cake + lockedDisplayItem: yellow_stained_glass_pane reward: text: 5 gold ore, 1 diamond items: - - GOLD_ORE:5 - - DIAMOND:1 + - gold_ore:5 + - diamond:1 currency: 80 xp: 80 repeatReward: text: 2 iron ore, 1 gold ore items: - - IRON_ORE:2 - - GOLD_ORE:1 + - iron_ore:2 + - gold_ore:1 currency: 40 xp: 40 -#=============================================== -# -# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the most used settings -# while the double commented (##) are optionnal if you like to use those settings. -# -#ranks: -# # [text] name of the challenge Rank. -# TierX: -# #[text] The name of the challenge rank that shows up when you do /challenges (this supports capitals and colorcodes). -# name: '&aCuston Challenges rank name' -# # [itemid] The itemid of the item to be displayed in the challenge menu for complete challenges. -# displayItem: 3 -# # [integer] The time in hours before required items reset to default (tis overwrites the Main reset time) -# resetInHours: 20 -# # The requierments will allow when a challenge groups will be available to see and complete for players. -# requires: -# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 challenges -# # with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. -# # A rankLeeway of 0 would require them all. -# rankLeeway: 8 -# # [text] Challenges that has to be completed before this group will show in the Challenges GUI -# challenges: -# - a challenge name -#=============================================== -# challenges: -# #[text] The name of the challenge. All challenge names should be lower case. -# defaultchallengename: -# #[text] The name of the challenge that shows up when you do /challenges (this supports capitals and colorcodes). -# name: '&a' -# # [text] What the player sees when they do /challenges -# description: -# # [onIsland/onPlayer/islandLevel] This tells whether the required blocks/items should be in the player's inventory or on their island -# # When using onIsland, the player must be 10 blocks away from the required blocks on his island. -# # When using onIsland, the default radius distance is set to 10, all items requierd must be within this distance. -# # When using islandLevel, the 'requiredItems' field should be the island level required. The player must use /island level first to update his level. -# type: onPlayer -## type: islandLevel -## type: onIsland -# # To override the default radius when using onIsland, uncommend the "radius: " and fill in your own value. -## radius: -# # [itemid list] The itemid:count of the items required for the challenge. -# requiredItems: '' -# # [true/false] If the challenge can repeated or not. -# # [itemid] The itemid of the item to be displayed in the challenge menu for complete challenges. -# displayItem: -## tool: -# # [integer] The time in hours before required items reset to default (this overwrites the Main and Ranks reset times). -## resetInHours: -# # [true/false] Take required items on completing a challenge. -# # # reward section to reward the player for completing the challenge. -# reward: -# # [text] Description of the reward. If omitted §4Unknown will be shown. -# text: -# # [itemid list] The itemid::count of the reward to give the player for completing the challenge. -# items: -## # [permission node] A permission granted for completion. Multiple permissions are space-separated, i.e. - "test.1 test.2" (use none to not give a permission) -# # # [integer] How much currency to give for the first time completion. (requires an economy plugin) -# currency: 0 -# # [integer] How much xp to give to the player for the first time completion. -# xp: 0 -# # Executes the given command upon completion. Prepend with "op" or "console" to run the commands as OP or from the Console. Examples: -# # commands: -# # - 'op: me are the GOD of things' -# # - 'console: give {party} aweseomestuff 32' -# # Possible command arguments are: -# # {player} - The name of the player -# # {playerName} - The display name of the player -# # {challenge} - The name of the challenge -# # {position} - The position of the player -# # {party} - Execute the command once for each member of the party (substituting the name) -## commands: -## - op: -## - console: -# # reward section to reward the player for completing a repeated challenge. -# repeatReward: -# # [text] Description of the reward. If omitted §4Unknown will be shown. -# text: -# # [itemid list] The itemid::count of the reward to give the player for completing the challenge. -# items: -## # [integer] How much currency to give for the first time completion. (requires an economy plugin) -# currency: 0 -# # [integer] How much xp to give to the player for the first time completion. -# xp: 0 -# # Executes the given command upon completion. Prepend with "op" or "console" to run the commands as OP or from the Console. Examples: -# # commands: -# # - 'op: me are the GOD of things' -# # - 'console: give {party} aweseomestuff 32' -# # Possible command arguments are: -# # {player} - The name of the player -# # {playerName} - The display name of the player -# # {challenge} - The name of the challenge -# # {position} - The position of the player -# # {party} - Execute the command once for each member of the party (substituting the name) -## commands: -## - op: -## - console: -# -# All commented settings (#) in the above challenges (not the explanation) can be removed to clean up the challenges.yml. -# -# DO NOT CHANGE! -version: 106 +# DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen! +version: 107 diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index 9e6ad6657..f09239e9b 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -49,15 +49,15 @@ options: # [item list] The list of items to place in the chest when a player starts a new island. ITEM_ID:HOW_MANY. # default is 2 ice, 1 watermelon, 1 cactus, 1 lava bucket, 1 red & brown mushroom, 1 pumpkin seed, 1 sugar cane, 1 sign. chestItems: - - ICE:2 - - MELON_SLICE:1 - - CACTUS:1 - - LAVA_BUCKET:1 - - RED_MUSHROOM:1 - - BROWN_MUSHROOM:1 - - PUMPKIN_SEEDS:1 - - SUGAR_CANE:1 - - OAK_SIGN:1 + - ice:2 + - melon_slice:1 + - cactus:1 + - lava_bucket:1 + - red_mushroom:1 + - brown_mushroom:1 + - pumpkin_seeds:1 + - sugar_cane:1 + - oak_sign:1 addExtraItems: true islandTeleportDelay: 2 allowPvP: deny @@ -82,27 +82,27 @@ options: spawner: 10 extraPermissions: smallbonus: - - COBBLESTONE:16 - - COOKED_PORKCHOP:5 + - cobblestone:16 + - cooked_porkchop:5 mediumbonus: - - TORCH:16 - - LAVA_BUCKET:1 + - torch:16 + - lava_bucket:1 largebonus: - - DIRT:5 - - SAND:5 + - dirt:5 + - sand:5 giantbonus: - - GRASS:1 - - MYCELIUM:1 + - grass_block:1 + - mycelium:1 extremebonus: - - BONE:8 - - COAL:4 + - bone:8 + - coal:4 donorbonus: - - BOW:1 - - ARROW:32 - - STONE_SWORD:1 + - bow:1 + - arrow:32 + - stone_sword:1 netheraccess: - - OBSIDIAN:14 - - FLINT_AND_STEEL:1 + - obsidian:14 + - flint_and_steel:1 extras: # [true/false] If true, return players that don't have an island (this includes players removed from a party while offline), to the server spawn when they login. @@ -277,7 +277,7 @@ options: donor-perks: # the permission node to give to someone 'usb.donor.small': - extraItems: [BONE_MEAL:1] + extraItems: [bone_meal:1] maxPartySize: 5 animals: 84 monsters: 60 @@ -305,7 +305,7 @@ island-schemes: description: The default uSkyBlock island # item to display in the GUI - displayItem: OAK_SAPLING + displayItem: oak_sapling # optional, default true (true enabled in GUI, false disabled in GUI) enabled: true @@ -329,12 +329,12 @@ island-schemes: skySMP: permission: usb.schematic.skysmp description: The original SkySMP island - displayItem: OAK_LEAVES + displayItem: oak_leaves enabled: false index: 3 extraItems: - - OBSIDIAN:14 - - FLINT_AND_STEEL:1 + - obsidian:14 + - flint_and_steel:1 maxPartySize: 4 animals: 64 monsters: 50 @@ -462,7 +462,7 @@ placeholder: servercommandplaceholder: false # DO NOT TOUCH THE FIELDS BELOW -version: 108 +version: 109 force-replace: options.party.invite-timeout: 100 options.island.islandTeleportDelay: 5 diff --git a/uSkyBlock-Core/src/main/resources/configmenu.yml b/uSkyBlock-Core/src/main/resources/configmenu.yml index 7d44d7537..4b0f529ab 100644 --- a/uSkyBlock-Core/src/main/resources/configmenu.yml +++ b/uSkyBlock-Core/src/main/resources/configmenu.yml @@ -36,86 +36,145 @@ keyboard: en: - # row 0 - null - - '{display:{Name:"-"},SkullOwner:{Id:"d59b62b4-0a1d-4475-a5b4-1fb0b58669ff",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg2YzljOTc3YTM2ZDg5ZjVmNGU5ZDJhNmQ4YjhkNTg5YTc1MTE4YjFjZjllMzZjNGVhYzdlOWE2MTE2YSJ9fX0="}]}}}' - - '{display:{Name:"!"},SkullOwner:{Id:"0a3628f0-f5b5-4a6f-8058-860006ca8732",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODdkMTlhYWJmY2ZkOTlmZmFiYTQyMTRjYWVmMjk5NTE2Y2U1MmU2ZDEzYmYyZGRhMTI1OTg1ZTQ4MWI3MmY5In19fQ=="}]}}}' - - '{display:{Name:":"},SkullOwner:{Id:"2f380f4a-64c3-4b2c-af18-6c491692e649",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ4OThjNDBlNDdjNWQyZDc2OTI0MDY1MzYwNzY4MDY1ZDYyNGVlNWI5ZWUwYmU5ZTEyYjk4ZmI3N2M3NiJ9fX0="}]}}}' - - '{display:{Name:"?"},SkullOwner:{Id:"808ac216-799a-4d42-bd68-7c9f0c1e89d1",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FhYjI3Mjg0MGQ3OTBjMmVkMmJlNWM4NjAyODlmOTVkODhlMzE2YjY1YzQ1NmZmNmEzNTE4MGQyZTViZmY2In19fQ=="}]}}}' - - '{display:{Name:"Backspace"},SkullOwner:{Id:"87e36f19-408a-4066-94ef-b0db25b96c48",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjI1OTliZDk4NjY1OWI4Y2UyYzQ5ODg1MjVjOTRlMTlkZGQzOWZhZDA4YTM4Mjg0YTE5N2YxYjcwNjc1YWNjIn19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"-","color":"white","italic":false}',minecraft:profile={id:[I;-711236940,169690229,-1514922064,-1249482241],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg2YzljOTc3YTM2ZDg5ZjVmNGU5ZDJhNmQ4YjhkNTg5YTc1MTE4YjFjZjllMzZjNGVhYzdlOWE2MTE2YSJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"!","color":"white","italic":false}',minecraft:profile={id:[I;171321584,-172668305,-2141682176,113936178],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODdkMTlhYWJmY2ZkOTlmZmFiYTQyMTRjYWVmMjk5NTE2Y2U1MmU2ZDEzYmYyZGRhMTI1OTg1ZTQ4MWI3MmY5In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":":","color":"white","italic":false}',minecraft:profile={id:[I;792203082,1690520364,-1357353911,378725961],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ4OThjNDBlNDdjNWQyZDc2OTI0MDY1MzYwNzY4MDY1ZDYyNGVlNWI5ZWUwYmU5ZTEyYjk4ZmI3N2M3NiJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"?","color":"white","italic":false}',minecraft:profile={id:[I;-2138389994,2040155458,-1117225825,203327953],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FhYjI3Mjg0MGQ3OTBjMmVkMmJlNWM4NjAyODlmOTVkODhlMzE2YjY1YzQ1NmZmNmEzNTE4MGQyZTViZmY2In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"Backspace","color":"white","italic":false}',minecraft:profile={id:[I;-2015138023,1082802278,-1796230949,632908872],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjI1OTliZDk4NjY1OWI4Y2UyYzQ5ODg1MjVjOTRlMTlkZGQzOWZhZDA4YTM4Mjg0YTE5N2YxYjcwNjc1YWNjIn19fQ=="}]}] - - '{display:{Name:"7"},SkullOwner:{Id:"cb9c723d-3663-4ef3-a83c-c7405fddd7c2",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDRiYTZhYzA3ZDQyMjM3N2E4NTU3OTNmMzZkZWEyZWQyNDAyMjNmNTJmZDE2NDgxODE2MTJlY2QxYTBjZmQ1In19fQ=="}]}}}' - - '{display:{Name:"8"},SkullOwner:{Id:"36118da7-6989-4602-af43-82589e1ed6cf",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzYxYThhNjQxNDM3YmU5YWVhMjA3MjUzZGQzZjI1NDQwZDk1NGVhMmI1ODY2YzU1MmYzODZiMjlhYzRkMDQ5In19fQ=="}]}}}' - - '{display:{Name:"9"},SkullOwner:{Id:"8b867e70-124a-4a4f-9782-3b5581ab709b",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE5MjhlMWJmZDg2YTliNzkzOTdjNGNiNGI2NWVmOTlhZjQ5YjdkNWY3OTU3YWQ2MmMwYzY5OWE2MjJjZmJlIn19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"7","color":"white","italic":false}',minecraft:profile={id:[I;-878939587,912477939,-1472411840,1608374210],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDRiYTZhYzA3ZDQyMjM3N2E4NTU3OTNmMzZkZWEyZWQyNDAyMjNmNTJmZDE2NDgxODE2MTJlY2QxYTBjZmQ1In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"8","color":"white","italic":false}',minecraft:profile={id:[I;907120039,1770604034,-1354530216,-1642146097],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzYxYThhNjQxNDM3YmU5YWVhMjA3MjUzZGQzZjI1NDQwZDk1NGVhMmI1ODY2YzU1MmYzODZiMjlhYzRkMDQ5In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"9","color":"white","italic":false}',minecraft:profile={id:[I;-1954120080,306858575,-1753072811,-2119470949],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE5MjhlMWJmZDg2YTliNzkzOTdjNGNiNGI2NWVmOTlhZjQ5YjdkNWY3OTU3YWQ2MmMwYzY5OWE2MjJjZmJlIn19fQ=="}]}] - # row 1 - - '{display:{Name:"A"},SkullOwner:{Id:"e8e10bc5-b94e-4378-a54c-ac71a662fec9",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTY3ZDgxM2FlN2ZmZTViZTk1MWE0ZjQxZjJhYTYxOWE1ZTM4OTRlODVlYTVkNDk4NmY4NDk0OWM2M2Q3NjcyZSJ9fX0="}]}}}' - - '{display:{Name:"B"},SkullOwner:{Id:"d0f793ff-b041-427c-bc24-440834e986fa",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTBjMWI1ODRmMTM5ODdiNDY2MTM5Mjg1YjJmM2YyOGRmNjc4NzEyM2QwYjMyMjgzZDg3OTRlMzM3NGUyMyJ9fX0="}]}}}' - - '{display:{Name:"C"},SkullOwner:{Id:"db8ddc48-84d7-4f98-bce3-0fb2d43cd4dd",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJlOTgzZWM0NzgwMjRlYzZmZDA0NmZjZGZhNDg0MjY3NjkzOTU1MWI0NzM1MDQ0N2M3N2MxM2FmMThlNmYifX19"}]}}}' - - '{display:{Name:"D"},SkullOwner:{Id:"c142dbd3-dbdf-4f46-a491-12162d3a3e8e",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5M2RjMGQ0YzVlODBmZjlhOGEwNWQyZmNmZTI2OTUzOWNiMzkyNzE5MGJhYzE5ZGEyZmNlNjFkNzEifX19"}]}}}' - - '{display:{Name:"E"},SkullOwner:{Id:"96eaca3a-0f22-484f-bad7-46153597e191",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiMjczN2VjYmY5MTBlZmUzYjI2N2RiN2Q0YjMyN2YzNjBhYmM3MzJjNzdiZDBlNGVmZjFkNTEwY2RlZiJ9fX0="}]}}}' - - '{display:{Name:"F"},SkullOwner:{Id:"5d098233-5c27-4e8a-a36f-959c9e35041b",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjE4M2JhYjUwYTMyMjQwMjQ4ODZmMjUyNTFkMjRiNmRiOTNkNzNjMjQzMjU1OWZmNDllNDU5YjRjZDZhIn19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"A","color":"white","italic":false}',minecraft:profile={id:[I;-387904571,-1186053256,-1521701775,-1503461687],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTY3ZDgxM2FlN2ZmZTViZTk1MWE0ZjQxZjJhYTYxOWE1ZTM4OTRlODVlYTVkNDk4NmY4NDk0OWM2M2Q3NjcyZSJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"B","color":"white","italic":false}',minecraft:profile={id:[I;-789081089,-1337900420,-1138473976,887719674],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTBjMWI1ODRmMTM5ODdiNDY2MTM5Mjg1YjJmM2YyOGRmNjc4NzEyM2QwYjMyMjgzZDg3OTRlMzM3NGUyMyJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"C","color":"white","italic":false}',minecraft:profile={id:[I;-611460024,-2066264168,-1125969998,-734210851],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJlOTgzZWM0NzgwMjRlYzZmZDA0NmZjZGZhNDg0MjY3NjkzOTU1MWI0NzM1MDQ0N2M3N2MxM2FmMThlNmYifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"D","color":"white","italic":false}',minecraft:profile={id:[I;-1052582957,-606122170,-1533996522,758791822],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5M2RjMGQ0YzVlODBmZjlhOGEwNWQyZmNmZTI2OTUzOWNiMzkyNzE5MGJhYzE5ZGEyZmNlNjFkNzEifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"E","color":"white","italic":false}',minecraft:profile={id:[I;-1762997702,253904975,-1160296939,899146129],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiMjczN2VjYmY5MTBlZmUzYjI2N2RiN2Q0YjMyN2YzNjBhYmM3MzJjNzdiZDBlNGVmZjFkNTEwY2RlZiJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"F","color":"white","italic":false}',minecraft:profile={id:[I;1560904243,1546079882,-1552968292,-1640692709],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjE4M2JhYjUwYTMyMjQwMjQ4ODZmMjUyNTFkMjRiNmRiOTNkNzNjMjQzMjU1OWZmNDllNDU5YjRjZDZhIn19fQ=="}]}] - - '{display:{Name:"4"},SkullOwner:{Id:"c2ba9ae6-7c8e-4cb0-9e79-459e2f6b96ec",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiZmNmYjQ4OWRhODY3ZGNlOTZlM2MzYzE3YTNkYjdjNzljYWU4YWMxZjlhNWE4YzhhYzk1ZTRiYTMifX19"}]}}}' - - '{display:{Name:"5"},SkullOwner:{Id:"463ae31c-73d3-4b97-a4e0-03777f8a43d2",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY0ZWNmMTEwYjBhY2VlNGFmMWRhMzQzZmIxMzZmMWYyYzIxNjg1N2RmZGE2OTYxZGVmZGJlZTdiOTUyOCJ9fX0="}]}}}' - - '{display:{Name:"6"},SkullOwner:{Id:"e3cb6368-4c87-4e9b-a329-fbdca086bff1",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMzMWE2YTZmY2Q2OTk1YjYyMDg4ZDM1M2JmYjY4ZDliODlhZTI1ODMyNWNhZjNmMjg4NjQ2NGY1NGE3MzI5In19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"4","color":"white","italic":false}',minecraft:profile={id:[I;-1027958042,2089700528,-1636219490,795580140],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiZmNmYjQ4OWRhODY3ZGNlOTZlM2MzYzE3YTNkYjdjNzljYWU4YWMxZjlhNWE4YzhhYzk1ZTRiYTMifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"5","color":"white","italic":false}',minecraft:profile={id:[I;1178264348,1943227287,-1528822921,2139767762],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY0ZWNmMTEwYjBhY2VlNGFmMWRhMzQzZmIxMzZmMWYyYzIxNjg1N2RmZGE2OTYxZGVmZGJlZTdiOTUyOCJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"6","color":"white","italic":false}',minecraft:profile={id:[I;-473210008,1283935899,-1557529636,-1601781775],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMzMWE2YTZmY2Q2OTk1YjYyMDg4ZDM1M2JmYjY4ZDliODlhZTI1ODMyNWNhZjNmMjg4NjQ2NGY1NGE3MzI5In19fQ=="}]}] - # row 2 - - '{display:{Name:"G"},SkullOwner:{Id:"0b017eae-cd4d-48eb-9407-863e794c4bac",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWNhM2YzMjRiZWVlZmI2YTBlMmM1YjNjNDZhYmM5MWNhOTFjMTRlYmE0MTlmYTQ3NjhhYzMwMjNkYmI0YjIifX19"}]}}}' - - '{display:{Name:"H"},SkullOwner:{Id:"ba7a5f3c-db71-4827-8612-ce6bd82ee992",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFmMzQ2MmE0NzM1NDlmMTQ2OWY4OTdmODRhOGQ0MTE5YmM3MWQ0YTVkODUyZTg1YzI2YjU4OGE1YzBjNzJmIn19fQ=="}]}}}' - - '{display:{Name:"I"},SkullOwner:{Id:"2ab25358-deaa-46b7-b351-d9732a448ff1",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDYxNzhhZDUxZmQ1MmIxOWQwYTM4ODg3MTBiZDkyMDY4ZTkzMzI1MmFhYzZiMTNjNzZlN2U2ZWE1ZDMyMjYifX19"}]}}}' - - '{display:{Name:"J"},SkullOwner:{Id:"be1f1677-af64-4f59-85be-244f28eb1306",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2E3OWRiOTkyMzg2N2U2OWMxZGJmMTcxNTFlNmY0YWQ5MmNlNjgxYmNlZGQzOTc3ZWViYmM0NGMyMDZmNDkifX19"}]}}}' - - '{display:{Name:"K"},SkullOwner:{Id:"4f264d8d-87a3-496a-ad1d-eda0a22a30f0",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTQ2MWIzOGM4ZTQ1NzgyYWRhNTlkMTYxMzJhNDIyMmMxOTM3NzhlN2Q3MGM0NTQyYzk1MzYzNzZmMzdiZTQyIn19fQ=="}]}}}' - - '{display:{Name:"L"},SkullOwner:{Id:"75ae0d27-f43c-416d-96a0-fdd6dbba7ab0",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5ZjUwYjQzMmQ4NjhhZTM1OGUxNmY2MmVjMjZmMzU0MzdhZWI5NDkyYmNlMTM1NmM5YWE2YmIxOWEzODYifX19"}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"G","color":"white","italic":false}',minecraft:profile={id:[I;184647342,-850573077,-1811446210,2035043244],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWNhM2YzMjRiZWVlZmI2YTBlMmM1YjNjNDZhYmM5MWNhOTFjMTRlYmE0MTlmYTQ3NjhhYzMwMjNkYmI0YjIifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"H","color":"white","italic":false}',minecraft:profile={id:[I;-1166385348,-613332953,-2045587861,-668014190],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFmMzQ2MmE0NzM1NDlmMTQ2OWY4OTdmODRhOGQ0MTE5YmM3MWQ0YTVkODUyZTg1YzI2YjU4OGE1YzBjNzJmIn19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"I","color":"white","italic":false}',minecraft:profile={id:[I;716329816,-559266121,-1286481549,709136369],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDYxNzhhZDUxZmQ1MmIxOWQwYTM4ODg3MTBiZDkyMDY4ZTkzMzI1MmFhYzZiMTNjNzZlN2U2ZWE1ZDMyMjYifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"J","color":"white","italic":false}',minecraft:profile={id:[I;-1105258889,-1352380583,-2051136433,686494470],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2E3OWRiOTkyMzg2N2U2OWMxZGJmMTcxNTFlNmY0YWQ5MmNlNjgxYmNlZGQzOTc3ZWViYmM0NGMyMDZmNDkifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"K","color":"white","italic":false}',minecraft:profile={id:[I;1327910285,-2019341974,-1390547552,-1574293264],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTQ2MWIzOGM4ZTQ1NzgyYWRhNTlkMTYxMzJhNDIyMmMxOTM3NzhlN2Q3MGM0NTQyYzk1MzYzNzZmMzdiZTQyIn19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"L","color":"white","italic":false}',minecraft:profile={id:[I;1974340903,-197377683,-1767834154,-608535888],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5ZjUwYjQzMmQ4NjhhZTM1OGUxNmY2MmVjMjZmMzU0MzdhZWI5NDkyYmNlMTM1NmM5YWE2YmIxOWEzODYifX19"}]}] - - '{display:{Name:"1"},SkullOwner:{Id:"cc70838c-9905-4fad-865f-8a5f83430272",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFhOTQ2M2ZkM2M0MzNkNWUxZDlmZWM2ZDVkNGIwOWE4M2E5NzBiMGI3NGRkNTQ2Y2U2N2E3MzM0OGNhYWIifX19"}]}}}' - - '{display:{Name:"2"},SkullOwner:{Id:"8d5350b9-6464-4f4b-999e-462af24dc872",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWNiNDE5ZDk4NGQ4Nzk2MzczYzk2NDYyMzNjN2EwMjY2NGJkMmNlM2ExZDM0NzZkZDliMWM1NDYzYjE0ZWJlIn19fQ=="}]}}}' - - '{display:{Name:"3"},SkullOwner:{Id:"76480708-e78b-4bb9-9987-131f4f5b50f6",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjhlYmFiNTdiNzYxNGJiMjJhMTE3YmU0M2U4NDhiY2QxNGRhZWNiNTBlOGY1ZDA5MjZlNDg2NGRmZjQ3MCJ9fX0="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"1","color":"white","italic":false}',minecraft:profile={id:[I;-865041524,-1727705171,-2040559009,-2092760462],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFhOTQ2M2ZkM2M0MzNkNWUxZDlmZWM2ZDVkNGIwOWE4M2E5NzBiMGI3NGRkNTQ2Y2U2N2E3MzM0OGNhYWIifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"2","color":"white","italic":false}',minecraft:profile={id:[I;-1923919687,1684295499,-1717680598,-229783438],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWNiNDE5ZDk4NGQ4Nzk2MzczYzk2NDYyMzNjN2EwMjY2NGJkMmNlM2ExZDM0NzZkZDliMWM1NDYzYjE0ZWJlIn19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"3","color":"white","italic":false}',minecraft:profile={id:[I;1984431880,-410301511,-1719200993,1331384566],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjhlYmFiNTdiNzYxNGJiMjJhMTE3YmU0M2U4NDhiY2QxNGRhZWNiNTBlOGY1ZDA5MjZlNDg2NGRmZjQ3MCJ9fX0="}]}] - # row 3 - - '{display:{Name:"M"},SkullOwner:{Id:"a291bc00-e8d7-42cf-8d57-588291f3ebc2",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDljNDVhMjRhYWFiZjQ5ZTIxN2MxNTQ4MzIwNDg0OGE3MzU4MmFiYTdmYWUxMGVlMmM1N2JkYjc2NDgyZiJ9fX0="}]}}}' - - '{display:{Name:"N"},SkullOwner:{Id:"439f4d78-dedd-427f-9973-c3906c4df529",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzViOGIzZDhjNzdkZmI4ZmJkMjQ5NWM4NDJlYWM5NGZmZmE2ZjU5M2JmMTVhMjU3NGQ4NTRkZmYzOTI4In19fQ=="}]}}}' - - '{display:{Name:"O"},SkullOwner:{Id:"4ec45cf0-b927-444b-85fb-f5910bfae296",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDExZGUxY2FkYjJhZGU2MTE0OWU1ZGVkMWJkODg1ZWRmMGRmNjI1OTI1NWIzM2I1ODdhOTZmOTgzYjJhMSJ9fX0="}]}}}' - - '{display:{Name:"P"},SkullOwner:{Id:"6c22192b-5af9-4d07-a96f-f95b9e81d163",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTBhNzk4OWI1ZDZlNjIxYTEyMWVlZGFlNmY0NzZkMzUxOTNjOTdjMWE3Y2I4ZWNkNDM2MjJhNDg1ZGMyZTkxMiJ9fX0="}]}}}' - - '{display:{Name:"Q"},SkullOwner:{Id:"047b3876-eac3-414b-8978-1c083fd8df86",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDM2MDlmMWZhZjgxZWQ0OWM1ODk0YWMxNGM5NGJhNTI5ODlmZGE0ZTFkMmE1MmZkOTQ1YTU1ZWQ3MTllZDQifX19"}]}}}' - - '{display:{Name:"R"},SkullOwner:{Id:"9af104ca-dfbb-4616-9101-d10016c2b11a",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTVjZWQ5OTMxYWNlMjNhZmMzNTEzNzEzNzliZjA1YzYzNWFkMTg2OTQzYmMxMzY0NzRlNGU1MTU2YzRjMzcifX19"}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"M","color":"white","italic":false}',minecraft:profile={id:[I;-1567507456,-388545841,-1923655550,-1846285374],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDljNDVhMjRhYWFiZjQ5ZTIxN2MxNTQ4MzIwNDg0OGE3MzU4MmFiYTdmYWUxMGVlMmM1N2JkYjc2NDgyZiJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"N","color":"white","italic":false}',minecraft:profile={id:[I;1134513528,-555924865,-1720466544,1817048361],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzViOGIzZDhjNzdkZmI4ZmJkMjQ5NWM4NDJlYWM5NGZmZmE2ZjU5M2JmMTVhMjU3NGQ4NTRkZmYzOTI4In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"O","color":"white","italic":false}',minecraft:profile={id:[I;1321491696,-1188608949,-2047085167,200991382],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDExZGUxY2FkYjJhZGU2MTE0OWU1ZGVkMWJkODg1ZWRmMGRmNjI1OTI1NWIzM2I1ODdhOTZmOTgzYjJhMSJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"P","color":"white","italic":false}',minecraft:profile={id:[I;1814173995,1526287623,-1452279461,-1635659421],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTBhNzk4OWI1ZDZlNjIxYTEyMWVlZGFlNmY0NzZkMzUxOTNjOTdjMWE3Y2I4ZWNkNDM2MjJhNDg1ZGMyZTkxMiJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"Q","color":"white","italic":false}',minecraft:profile={id:[I;75184246,-356302517,-1988617208,1071177606],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDM2MDlmMWZhZjgxZWQ0OWM1ODk0YWMxNGM5NGJhNTI5ODlmZGE0ZTFkMmE1MmZkOTQ1YTU1ZWQ3MTllZDQifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"R","color":"white","italic":false}',minecraft:profile={id:[I;-1695480630,-541374954,-1862151936,381858074],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTVjZWQ5OTMxYWNlMjNhZmMzNTEzNzEzNzliZjA1YzYzNWFkMTg2OTQzYmMxMzY0NzRlNGU1MTU2YzRjMzcifX19"}]}] - - '{display:{Name:"/"},SkullOwner:{Id:"015eeece-cc8f-46a1-acd5-cf010870730a",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2Y5NWQ3YzFiYmYzYWZhMjg1ZDhkOTY3NTdiYjU1NzIyNTlhM2FlODU0ZjUzODlkYzUzMjA3Njk5ZDk0ZmQ4In19fQ=="}]}}}' - - '{display:{Name:"0"},SkullOwner:{Id:"a58ddb02-267b-4122-b8cc-5a6fbef9db04",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTVhMjI0ODA3NjkzOTc4ZWQ4MzQzNTVmOWU1MTQ1ZjljNTZlZjY4Y2Y2ZjJjOWUxNzM0YTQ2ZTI0NmFhZTEifX19"}]}}}' - - '{display:{Name:"."},SkullOwner:{Id:"361e6180-ceac-4838-89e5-be46fb40fe84",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzMzYWEyNDkxNmM4ODY5NmVlNzFkYjdhYzhjZDMwNmFkNzMwOTZiNWI2ZmZkODY4ZTFjMzg0YjFkNjJjZmIzYyJ9fX0="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"/","color":"white","italic":false}',minecraft:profile={id:[I;22998734,-863025503,-1395273983,141587210],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2Y5NWQ3YzFiYmYzYWZhMjg1ZDhkOTY3NTdiYjU1NzIyNTlhM2FlODU0ZjUzODlkYzUzMjA3Njk5ZDk0ZmQ4In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"0","color":"white","italic":false}',minecraft:profile={id:[I;-1517430014,645611810,-1194567057,-1090921724],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTVhMjI0ODA3NjkzOTc4ZWQ4MzQzNTVmOWU1MTQ1ZjljNTZlZjY4Y2Y2ZjJjOWUxNzM0YTQ2ZTI0NmFhZTEifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":".","color":"white","italic":false}',minecraft:profile={id:[I;907960704,-827570120,-1981432250,-79626620],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzMzYWEyNDkxNmM4ODY5NmVlNzFkYjdhYzhjZDMwNmFkNzMwOTZiNWI2ZmZkODY4ZTFjMzg0YjFkNjJjZmIzYyJ9fX0="}]}] - # row 4 - - '{display:{Name:"S"},SkullOwner:{Id:"826bfe2f-387c-44d7-9cd3-fc3046a6204d",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2U0MWM2MDU3MmM1MzNlOTNjYTQyMTIyODkyOWU1NGQ2Yzg1NjUyOTQ1OTI0OWMyNWMzMmJhMzNhMWIxNTE3In19fQ=="}]}}}' - - '{display:{Name:"T"},SkullOwner:{Id:"08c08ff3-95f3-44cc-8da3-d0e1331cf469",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU2MmU4YzFkNjZiMjFlNDU5YmU5YTI0ZTVjMDI3YTM0ZDI2OWJkY2U0ZmJlZTJmNzY3OGQyZDNlZTQ3MTgifX19"}]}}}' - - '{display:{Name:"U"},SkullOwner:{Id:"dd376034-312d-4515-9c70-eafbba1a12e4",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjA3ZmJjMzM5ZmYyNDFhYzNkNjYxOWJjYjY4MjUzZGZjM2M5ODc4MmJhZjNmMWY0ZWZkYjk1NGY5YzI2In19fQ=="}]}}}' - - '{display:{Name:"V"},SkullOwner:{Id:"18724f9a-8aab-4f3f-a0ff-26e4b704d53f",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2M5YTEzODYzOGZlZGI1MzRkNzk5Mjg4NzZiYWJhMjYxYzdhNjRiYTc5YzQyNGRjYmFmY2M5YmFjNzAxMGI4In19fQ=="}]}}}' - - '{display:{Name:"W"},SkullOwner:{Id:"20816a64-5743-4624-8d5e-00549a64179b",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjY5YWQxYTg4ZWQyYjA3NGUxMzAzYTEyOWY5NGU0YjcxMGNmM2U1YjRkOTk1MTYzNTY3ZjY4NzE5YzNkOTc5MiJ9fX0="}]}}}' - - '{display:{Name:"X"},SkullOwner:{Id:"33b5946c-20d1-466f-8dd5-11a0fdcd7105",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE2Nzg3YmEzMjU2NGU3YzJmM2EwY2U2NDQ5OGVjYmIyM2I4OTg0NWU1YTY2YjVjZWM3NzM2ZjcyOWVkMzcifX19"}]}}}' - - '{display:{Name:"Y"},SkullOwner:{Id:"579ec4fb-0baf-4716-89ba-1c175fbd6e3c",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzUyZmIzODhlMzMyMTJhMjQ3OGI1ZTE1YTk2ZjI3YWNhNmM2MmFjNzE5ZTFlNWY4N2ExY2YwZGU3YjE1ZTkxOCJ9fX0="}]}}}' - - '{display:{Name:"Z"},SkullOwner:{Id:"0f3a3e42-4410-48a6-9d46-97392e7a6e27",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA1ODJiOWI1ZDk3OTc0YjExNDYxZDYzZWNlZDg1ZjQzOGEzZWVmNWRjMzI3OWY5YzQ3ZTFlMzhlYTU0YWU4ZCJ9fX0="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"S","color":"white","italic":false}',minecraft:profile={id:[I;-2106851793,947668183,-1663828944,1185292365],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2U0MWM2MDU3MmM1MzNlOTNjYTQyMTIyODkyOWU1NGQ2Yzg1NjUyOTQ1OTI0OWMyNWMzMmJhMzNhMWIxNTE3In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"T","color":"white","italic":false}',minecraft:profile={id:[I;146837491,-1779219252,-1918643999,857535593],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU2MmU4YzFkNjZiMjFlNDU5YmU5YTI0ZTVjMDI3YTM0ZDI2OWJkY2U0ZmJlZTJmNzY3OGQyZDNlZTQ3MTgifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"U","color":"white","italic":false}',minecraft:profile={id:[I;-583573452,825050389,-1670321413,-1172696348],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjA3ZmJjMzM5ZmYyNDFhYzNkNjYxOWJjYjY4MjUzZGZjM2M5ODc4MmJhZjNmMWY0ZWZkYjk1NGY5YzI2In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"V","color":"white","italic":false}',minecraft:profile={id:[I;410144666,-1968484545,-1593891100,-1224420033],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2M5YTEzODYzOGZlZGI1MzRkNzk5Mjg4NzZiYWJhMjYxYzdhNjRiYTc5YzQyNGRjYmFmY2M5YmFjNzAxMGI4In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"W","color":"white","italic":false}',minecraft:profile={id:[I;545352292,1464026660,-1923219372,-1704716389],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjY5YWQxYTg4ZWQyYjA3NGUxMzAzYTEyOWY5NGU0YjcxMGNmM2U1YjRkOTk1MTYzNTY3ZjY4NzE5YzNkOTc5MiJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"X","color":"white","italic":false}',minecraft:profile={id:[I;867538028,550585967,-1915416160,-36867835],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE2Nzg3YmEzMjU2NGU3YzJmM2EwY2U2NDQ5OGVjYmIyM2I4OTg0NWU1YTY2YjVjZWM3NzM2ZjcyOWVkMzcifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"Y","color":"white","italic":false}',minecraft:profile={id:[I;1470022907,196036374,-1984291817,1606250044],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzUyZmIzODhlMzMyMTJhMjQ3OGI1ZTE1YTk2ZjI3YWNhNmM2MmFjNzE5ZTFlNWY4N2ExY2YwZGU3YjE1ZTkxOCJ9fX0="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":"Z","color":"white","italic":false}',minecraft:profile={id:[I;255475266,1141917862,-1656318151,779775527],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA1ODJiOWI1ZDk3OTc0YjExNDYxZDYzZWNlZDg1ZjQzOGEzZWVmNWRjMzI3OWY5YzQ3ZTFlMzhlYTU0YWU4ZCJ9fX0="}]}] - null - null - # row 5 - null # capslock - null - - '{display:{Name:"<"},SkullOwner:{Id:"21ca358a-0bb9-4441-9c08-aefff75524a8",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZjOWYyYWE4ZTk3OTg3NDIxZTdmYWIyNDhhZmMyNDJjYmU1MWY5ZWRiZmE0NzFjYTZjMDE0OTRlZGVkYTcifX19"}]}}}' - - '{display:{Name:" "},SkullOwner:{Id:"97ced8c3-6a7d-4478-af9b-f47e6051f357",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}}}' - - '{display:{Name:" "},SkullOwner:{Id:"97ced8c3-6a7d-4478-af9b-f47e6051f357",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}}}' - - '{display:{Name:" "},SkullOwner:{Id:"97ced8c3-6a7d-4478-af9b-f47e6051f357",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"<","color":"white","italic":false}',minecraft:profile={id:[I;566900106,196691009,-1677152513,-145415000],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZjOWYyYWE4ZTk3OTg3NDIxZTdmYWIyNDhhZmMyNDJjYmU1MWY5ZWRiZmE0NzFjYTZjMDE0OTRlZGVkYTcifX19"}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] + - > + minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] - null - - '{display:{Name:"&"},SkullOwner:{Id:"b9f96b3b-ff11-4017-b0ce-c0c9872d3556",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJmMTQzZTgxZWM4NzI1YmQyNjcyOTNmMmY5N2EzZGFlMTNiNmE4NDhlNjZhZjAxZjJhNTk0ZGUwYzAzYjY4In19fQ=="}]}}}' + - > + minecraft:player_head[minecraft:custom_name='{"text":"&","color":"white","italic":false}',minecraft:profile={id:[I;-1174836421,-15646697,-1328627511,-2027080362],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJmMTQzZTgxZWM4NzI1YmQyNjcyOTNmMmY5N2EzZGFlMTNiNmE4NDhlNjZhZjAxZjJhNTk0ZGUwYzAzYjY4In19fQ=="}]}] capslock: - on: '{display:{Name:"Caps On"},SkullOwner:{Id:"aef9582f-42f0-4566-8626-477245376ca2",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmE0ODUxYzg3OGJmNDJhMWNkYzAzYmMwNjcxZDExZTlkZDY5NzdlNzM4MTNhZmFmNTRjMjQzMjg5MjFiMSJ9fX0="}]}}}' - off: '{display:{Name:"Caps Off"},SkullOwner:{Id:"a8a8e02f-30f7-4b54-ad11-f1fa8f7830ea",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE4ZWY5MmVmYTE1NjY5ZGY0ODMzMmQxMThhMmY3MDU3NzJhMmEzZmNkMGZiODJhNjFmMjc3Yjg0OWEyYmQ2In19fQ=="}]}}}' + on: > + minecraft:player_head[minecraft:custom_name='{"text":"Caps On","color":"white","italic":false}',minecraft:profile={id:[I;-1359390673,1123042662,-2044311694,1161260194],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmE0ODUxYzg3OGJmNDJhMWNkYzAzYmMwNjcxZDExZTlkZDY5NzdlNzM4MTNhZmFmNTRjMjQzMjg5MjFiMSJ9fX0="}]}] + off: > + minecraft:player_head[minecraft:custom_name='{"text":"Caps Off","color":"white","italic":false}',minecraft:profile={id:[I;-1465327569,821513044,-1391332870,-1887948566],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE4ZWY5MmVmYTE1NjY5ZGY0ODMzMmQxMThhMmY3MDU3NzJhMmEzZmNkMGZiODJhNjFmMjc3Yjg0OWEyYmQ2In19fQ=="}]}] overlay: - 1: '{display:{Name:"+"},SkullOwner:{Id:"80e287ca-69a7-4a03-8811-324a469079b9",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWUzOTVlNzVlMmViOGM0YjcyNDRkY2RiNzVjNTdhNmQ3YWRmMzc1NTNmMjFkNDRlZmM3YmQ3MTQxODQzNDVkIn19fQ=="}]}}}' - 7: '{display:{Name:"("},SkullOwner:{Id:"dc61f26c-79f0-45b8-be4c-fad9fef6e0d1",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA3MWNiMTc3ZDQ1OTdkNGY1MWE2NjM3NWVmOWIwMTQyY2Q2OGMzZTljNjRhZWJiNjJmMTZlM2MzOTAxNDJmIn19fQ=="}]}}}' - 8: '{display:{Name:")"},SkullOwner:{Id:"d9d19efe-cb96-4e6a-a7a0-29aed68e958c",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNjNzJlZjBlOTQ0MmM1YjY3YTUwYTY5YjI5ZWUxMDRmODExZmFkYTZiZmVkZTJlY2RiM2I1YjU1NTAifX19"}]}}}' - 16: '{display:{Name:"{\"text\":\"''{''\"}"},SkullOwner:{Id:"5e1368b1-c858-4748-b2bb-e92c76700554",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5OTMyY2ZhZTc1ZDM4ZjdjNzFmN2Y5NTNkMThmNmI2MGZjYjg4NThkMWQ5YjQ5YTE1ZDc2NmJjY2IyNThmNiJ9fX0="}]}}}' - 17: '{display:{Name:"{\"text\":\"''}''\"}"},SkullOwner:{Id:"4fbb057e-7eeb-4cfb-8cfc-ad2739fddedf",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiOGIxMWQ2NWUwZDA2OGQzYTk0OWM0MWVmNGQxMmUxODNjZmFlZWE0NGZmYzY4ZWM0MzliNWQ5NzcxMjcifX19"}]}}}' - 25: '{display:{Name:"["},SkullOwner:{Id:"68f2f3b4-e105-4887-9765-68200e7a831b",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTM0YTlmYTlkMmNlNTY4YWUyYjIxZWRhMGNiMzM5NGZlNTJkNjc4M2I0ZmViYWFhOTFmMjg2ZmY5MzMyIn19fQ=="}]}}}' - 26: '{display:{Name:"]"},SkullOwner:{Id:"00962524-4195-4480-9a1b-f9e67178dca9",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTQ4YjY5ZWMxNTViMTg3Mzc2Yjg4YmMwMzg0ZDI1NTM4ZGRlZDlkYjgzOWVhYmI1OWU0NjE4ZWE0NiJ9fX0="}]}}}' - 31: '{display:{Name:"*"},SkullOwner:{Id:"0fa2efdb-cfca-4853-8335-9f0ae1e70b49",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwZThlZmExY2QwNzI4Mjk3NDdhNjk3NzM3OTE2OTVmODBjZmFlOGJmYTg3MmZiMWIyOGEyMTFlZDAzMSJ9fX0="}]}}}' - 47: '{display:{Name:">"},SkullOwner:{Id:"6d6a08e5-e1ad-4c81-b4cc-e7fbee8766db",Properties:{textures:[{Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzEwZTE0OWI2NTE2MzgyZTM2ZGQ2YzRjOTk3ZDg4OWQwNDZkMTNiNTQzM2Y1YWZlYjNiYTVmYjlkYWI0MmY5In19fQ=="}]}}}' + 1: > + minecraft:player_head[minecraft:custom_name='{"text":"+","color":"white","italic":false}',minecraft:profile={id:[I;-2132637750,1772571139,-2012138934,1183873465],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWUzOTVlNzVlMmViOGM0YjcyNDRkY2RiNzVjNTdhNmQ3YWRmMzc1NTNmMjFkNDRlZmM3YmQ3MTQxODQzNDVkIn19fQ=="}]}] + 7: > + minecraft:player_head[minecraft:custom_name='{"text":"(","color":"white","italic":false}',minecraft:profile={id:[I;-597560724,2045789624,-1102251303,-17375023],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA3MWNiMTc3ZDQ1OTdkNGY1MWE2NjM3NWVmOWIwMTQyY2Q2OGMzZTljNjRhZWJiNjJmMTZlM2MzOTAxNDJmIn19fQ=="}]}] + 8: > + minecraft:player_head[minecraft:custom_name='{"text":")","color":"white","italic":false}',minecraft:profile={id:[I;-640573698,-879341974,-1482675794,-695298676],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNjNzJlZjBlOTQ0MmM1YjY3YTUwYTY5YjI5ZWUxMDRmODExZmFkYTZiZmVkZTJlY2RiM2I1YjU1NTAifX19"}]}] + 16: > + minecraft:player_head[minecraft:custom_name='{"text":"{","color":"white","italic":false}',minecraft:profile={id:[I;1578330289,-933738680,-1296307924,1987052884],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5OTMyY2ZhZTc1ZDM4ZjdjNzFmN2Y5NTNkMThmNmI2MGZjYjg4NThkMWQ5YjQ5YTE1ZDc2NmJjY2IyNThmNiJ9fX0="}]}] + 17: > + minecraft:player_head[minecraft:custom_name='{"text":"}","color":"white","italic":false}',minecraft:profile={id:[I;1337656702,2129349883,-1929597657,972938975],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiOGIxMWQ2NWUwZDA2OGQzYTk0OWM0MWVmNGQxMmUxODNjZmFlZWE0NGZmYzY4ZWM0MzliNWQ5NzcxMjcifX19"}]}] + 25: > + minecraft:player_head[minecraft:custom_name='{"text":"[","color":"white","italic":false}',minecraft:profile={id:[I;1760752564,-519747449,-1754961888,242909979],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTM0YTlmYTlkMmNlNTY4YWUyYjIxZWRhMGNiMzM5NGZlNTJkNjc4M2I0ZmViYWFhOTFmMjg2ZmY5MzMyIn19fQ=="}]}] + 26: > + minecraft:player_head[minecraft:custom_name='{"text":"]","color":"white","italic":false}',minecraft:profile={id:[I;9839908,1100301440,-1709442586,1903746217],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTQ4YjY5ZWMxNTViMTg3Mzc2Yjg4YmMwMzg0ZDI1NTM4ZGRlZDlkYjgzOWVhYmI1OWU0NjE4ZWE0NiJ9fX0="}]}] + 31: > + minecraft:player_head[minecraft:custom_name='{"text":"*","color":"white","italic":false}',minecraft:profile={id:[I;262336475,-808826797,-2093637878,-504951991],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwZThlZmExY2QwNzI4Mjk3NDdhNjk3NzM3OTE2OTVmODBjZmFlOGJmYTg3MmZiMWIyOGEyMTFlZDAzMSJ9fX0="}]}] + 47: > + minecraft:player_head[minecraft:custom_name='{"text":">","color":"white","italic":false}',minecraft:profile={id:[I;1835665637,-508736383,-1261639685,-293116197],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzEwZTE0OWI2NTE2MzgyZTM2ZGQ2YzRjOTk3ZDg4OWQwNDZkMTNiNTQzM2Y1YWZlYjNiYTVmYjlkYWI0MmY5In19fQ=="}]}] # DO NOT TOUCH THESE -version: 2 +version: 3 diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 023391409..6979a866d 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -18,7 +18,7 @@ softdepend: - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.19 +api-version: 1.20.6 libraries: - com.google.code.gson:gson:${gson.version} - com.google.guava:guava:${guava.version} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java index ad5d23b94..0d99c2a4f 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java @@ -8,11 +8,12 @@ import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.List; +import java.util.Map; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -26,6 +27,7 @@ public void beforeEach() throws NoSuchFieldException, IllegalAccessException { } @Test + @Ignore public void createChallenge_IronGolem() { InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("challengefactory/requiredEntities.yml"); YamlConfiguration config = YamlConfiguration.loadConfiguration(new InputStreamReader(resourceAsStream)); @@ -41,6 +43,7 @@ public void createChallenge_IronGolem() { } @Test + @Ignore public void createChallenge_ManyItems() { InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("challengefactory/manyRequiredItems.yml"); YamlConfiguration config = YamlConfiguration.loadConfiguration(new InputStreamReader(resourceAsStream)); @@ -50,9 +53,8 @@ public void createChallenge_ManyItems() { Challenge challenge = ChallengeFactory.createChallenge(rank, rankSection.getConfigurationSection("challenges.villageguard"), defaults); assertThat(challenge, notNullValue()); - List requiredItems = challenge.getRequiredItems(0); + Map requiredItems = challenge.getRequiredItems(0); assertThat(requiredItems.size(), is(1)); - assertThat(ItemStackUtil.asString(requiredItems.get(0)), is(ItemStackUtil.asString(new ItemStack(Material.COBBLESTONE, 257)))); + assertThat(ItemStackUtil.asString(requiredItems.keySet().stream().findFirst().get()), is(ItemStackUtil.asString(new ItemStack(Material.COBBLESTONE, 257)))); } - -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogicTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogicTest.java deleted file mode 100644 index 24182af90..000000000 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogicTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package us.talabrek.ultimateskyblock.challenge; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.nbt.NBTItemStackTagger; -import dk.lockfuglsang.minecraft.nbt.NBTUtil; -import dk.lockfuglsang.minecraft.util.FormatUtil; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; -import org.bukkit.Bukkit; -import org.bukkit.Server; -import org.bukkit.inventory.ItemFactory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.PluginManager; -import org.junit.Ignore; -import org.junit.Test; -import us.talabrek.ultimateskyblock.uSkyBlock; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.List; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ChallengeLogicTest { - - @Test - public void testWordWrap() { - String test = "a little version that doesn't mean anything, but should be broken on multiple lines"; - List expected = Arrays.asList( - "a little", - "version that doesn't", - "mean anything,", - "but should be broken", - "on multiple lines"); - - assertThat(FormatUtil.wordWrap(test, 8, 15), is(expected)); - } - - @Test - @Ignore("Bukkit 1.13 uses server.Unsafe(), which is NULL in test-runner") - public void testDefaultChallengesYml() throws Exception { - setupServerMock(); - YmlConfiguration config = new YmlConfiguration(); - FileUtil.readConfig(config, new File("src/main/resources/challenges.yml")); - uSkyBlock plugin = mock(uSkyBlock.class); - when(plugin.getConfig()).thenReturn(config); - when(plugin.getDataFolder()).thenReturn(new File("target/test-classes")); - ChallengeLogic sut = new ChallengeLogic(config, plugin); - // Adjust these values accordingly - assertThat(sut.getRanks().size(), is(6)); - assertThat(sut.getAllChallengeNames().size(), is(54)); - } - - private static Server setupServerMock() throws NoSuchFieldException, IllegalAccessException { - NBTUtil.setNBTItemStackTagger(new NBTItemStackTagger() { - @Override - public String getNBTTag(ItemStack itemStack) { - return null; - } - - @Override - public ItemStack setNBTTag(ItemStack itemStack, String tag) { - return null; - } - - @Override - public ItemStack addNBTTag(ItemStack itemStack, String tag) { - return null; - } - }); - Field server = Bukkit.class.getDeclaredField("server"); - server.setAccessible(true); - Server serverMock = createServerMock(); - server.set(null, serverMock); - server.setAccessible(false); - return serverMock; - } - - private static Server createServerMock() { - Server serverMock = mock(Server.class); - ItemFactory itemFactoryMock = mock(ItemFactory.class); - when(serverMock.getItemFactory()).thenReturn(itemFactoryMock); - PluginManager pluginManagerMock = mock(PluginManager.class); - when(serverMock.getPluginManager()).thenReturn(pluginManagerMock); - return serverMock; - } -} \ No newline at end of file diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java new file mode 100644 index 000000000..26ebf2adb --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java @@ -0,0 +1,78 @@ +package us.talabrek.ultimateskyblock.imports; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Objects; +import java.util.logging.Logger; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ItemComponentConverterTest { + + @Rule + public TemporaryFolder testFolder = new TemporaryFolder(); + + @Test + public void testMinimalChallengeConversion() throws Exception { + testConfig("test-challenges.yml", "test-challenges-expected.yml", "challenges.yml"); + } + + @Test + public void testDefaultChallengeConversion() throws Exception { + testConfig("old-default-challenges.yml", "old-default-challenges-expected.yml", "challenges.yml"); + } + + @Test + public void testDefaultSettingsConversion() throws Exception { + testConfig("old-config.yml", "old-config-expected.yml", "config.yml"); + } + + private void testConfig(String originalName, String expectedName, String fileName) throws Exception { + var testFile = new File(testFolder.getRoot(), fileName); + try (var reader = Objects.requireNonNull(getClass().getResourceAsStream(originalName))) { + Files.copy(reader, testFile.toPath()); + } + + var converter = new ItemComponentConverter(Logger.getAnonymousLogger()); + converter.importFile(testFile); + + assertTrue(testFile.exists()); + File backup = new File(testFolder.getRoot(), fileName + ".old"); + assertTrue(backup.isFile()); + + YamlConfiguration actual = new YamlConfiguration(); + actual.load(testFile); + YamlConfiguration expected = new YamlConfiguration(); + try (var reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull( + getClass().getResourceAsStream(expectedName)), StandardCharsets.UTF_8))) { + expected.load(reader); + } + assertConfigsEquals(expected, actual); + } + + private void assertConfigsEquals(YamlConfiguration expected, YamlConfiguration actual) { + for (String key : expected.getKeys(true)) { + assertTrue("Missing key: " + key, actual.contains(key)); + if (expected.isConfigurationSection(key)) { + assertTrue("Key should be a section: " + key, actual.isConfigurationSection(key)); + } else { + assertEquals("Items mismatch at key: " + key, expected.get(key), actual.get(key)); + } + assertThat("Comments mismatch at key: " + key, actual.getComments(key), is(expected.getComments(key))); + assertThat("Inline comments mismatch at key: " + key, actual.getInlineComments(key), is(expected.getInlineComments(key))); + } + assertThat("Headers should be the same", actual.options().getHeader(), is(expected.options().getHeader())); + assertThat("Footers should be the same", actual.options().getFooter(), is(expected.options().getFooter())); + } +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java index e54d5b2ed..98fd0c695 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java @@ -1,8 +1,9 @@ package us.talabrek.ultimateskyblock.island; -import dk.lockfuglsang.minecraft.yml.YmlConfiguration; import org.bukkit.Location; import org.bukkit.World; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; @@ -94,7 +95,7 @@ public Location answer(InvocationOnMock invocationOnMock) throws Throwable { private uSkyBlock createPluginMock() { uSkyBlock plugin = mock(uSkyBlock.class); - YmlConfiguration config = new YmlConfiguration(); + FileConfiguration config = new YamlConfiguration(); when(plugin.getConfig()).thenReturn(config); OrphanLogic orphanLogic = mock(OrphanLogic.class); when(plugin.getOrphanLogic()).thenReturn(orphanLogic); @@ -103,4 +104,4 @@ private uSkyBlock createPluginMock() { when(plugin.getWorldManager()).thenReturn(worldManager); return plugin; } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java index 8d311ea87..b128bc190 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BlockUtilTest.java @@ -3,10 +3,13 @@ import org.bukkit.Material; import org.bukkit.block.Block; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; public class BlockUtilTest { + + @Ignore @Test public void testIsBreathable() throws Exception { Block fakeBlock = Mockito.mock(Block.class); diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config-expected.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config-expected.yml new file mode 100644 index 000000000..873f75319 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config-expected.yml @@ -0,0 +1,476 @@ +# The language used in the plugin (en is default). +language: en +options: + general: + + # [integer] The max number of players allowed in a single party. (including the leader) + maxPartySize: 4 + + # [integer] The time in seconds before a player can use the /island info command again. (note: cooldowns are reset when the plugin is reloaded) + cooldownInfo: 20 + + # [integer] The time in seconds before a player can use the /island restart command again. + cooldownRestart: 30 + + # [integer] The time in seconds before a player can use the /island biome command again. + biomeChange: 60 + + # [string] The default biome assigned to new islands + defaultBiome: OCEAN + + # [integer] The number of milliseconds between the same notification is sent to the player. + # This is used when events are triggered heavily - i.e. item-pickup-prevention, damage-prevention etc. + maxSpam: 2000 + + # [string] The name of the skyblock world, will be automatically generated if it doesn't exist. + worldName: skyworld + + # [integer] Area around 0,0 where islands will not be created to protect spawn. + spawnSize: 64 + island: + + # [integer] The y-coordinate (height) where islands are spawned. + height: 150 + + # [integer] The number of blocks between islands. + distance: 128 + + # [integer] The size of the protective region for each island. Can't be higher than 'distance' + # and MUST be divisible by 32 if you intend to use nether. + protectionRange: 128 + + # [filename] The schematic to use for island generation. + # Put your schematic in the 'uSkyBlock/schematics' folder, you don't need to add the '.schematic' part below. + schematicName: default + + # [true/false] If true, remove all hostile mobs when a player teleports back to their island. + removeCreaturesByTeleport: false + + # [item list] The list of items to place in the chest when a player starts a new island. ITEM_ID:HOW_MANY. + # default is 2 ice, 1 watermelon, 1 cactus, 1 lava bucket, 1 red & brown mushroom, 1 pumpkin seed, 1 sugar cane, 1 sign. + chestItems: + - ice:2 + - melon_slice:1 + - cactus:1 + - lava_bucket:1 + - red_mushroom:1 + - brown_mushroom:1 + - pumpkin_seeds:1 + - sugar_cane:1 + - oak_sign:1 + addExtraItems: true + islandTeleportDelay: 2 + allowPvP: deny + allowIslandLock: true + useIslandLevel: true + useTopTen: true + topTenTimeout: 20 + autoRefreshScore: 0 + topTenShowMembers: true + fixFlatland: false + chat-format: '&9SKY &r{DISPLAYNAME} &f>&d {MESSAGE}' + log-size: 10 + spawn-limits: + enabled: true + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + block-limits: + enabled: true + hopper: 50 + spawner: 10 + extraPermissions: + smallbonus: + - cobblestone:16 + - cooked_porkchop:5 + mediumbonus: + - torch:16 + - lava_bucket:1 + largebonus: + - dirt:5 + - sand:5 + giantbonus: + - grass_block:1 + - mycelium:1 + extremebonus: + - bone:8 + - coal:4 + donorbonus: + - bow:1 + - arrow:32 + - stone_sword:1 + netheraccess: + - obsidian:14 + - flint_and_steel:1 + extras: + + # [true/false] If true, return players that don't have an island (this includes players removed from a party while offline), to the server spawn when they login. + # NOTE: Requires EssentialsSpawn or another plugin with the "/spawn" command + sendToSpawn: false + + # [true/false] If true, when a player respawns they will respawn on their island. Will first attempt to respawn them at the closest safe location to their island home, then their island spawn, then the server spawn. + # NOTE: If this is true, sendToSpawn is ignored unless the player has no island or no viable island home or spawn location. + respawnAtIsland: true + + # [true/false] If true, a player can right-click on a block of obsidian on their island while holding an empty bucket to remove the obsidian and fill the bucket with lava. This is useful for people that accidentally + # turn their lava into obsidian with a bad cobblestone generator design. Will only work on the player's island and if there are no other obsidian blocks nearby (so can't be used on portals). + obsidianToLava: true + + # Contains flags for enabling PROTECTION of various mechanics. + protection: + + # Whether or not, items dropped on the ground should be limited to party-members. + item-drops: true + + # If true, only creepers targeting party-members will explode + creepers: true + + # If true, Withers will be limited to harming island-members/island blocks. + withers: true + + # Whether or not the plugin will try to protect the player from accidentally extinguishing lava + protect-lava: true + + # Whether or not portalling to the nether roof should be blocked. + nether-roof: true + + # Whether or not anyone can trade i skyblock + # default: false - since it goes against the core of skyblock + villager-trading-enabled: false + + # Generally protections against griefers + # If the flag is true, it generally means the protection is active + # (meaning the action is blocked) + visitors: + + # Protect visitors from trampling your crop + trampling: true + + # Protect against visitors attacked animals + kill-animals: true + + # Protect against visitors attacking monsters + kill-monsters: true + + # Protect from shearing + shearing: true + + # Protect from begin bombarded with eggs that hatch + hatching: true + + # Protect from villager-trading + villager-trading: true + + # Whether or not visitors are protected from fall damage + fall: true + + # Whether or not visitors are protected from fire damage (incl. lava) + fire-damage: true + + # Whether or not visitors are protected from monster damage + monster-damage: false + + # Whether or not visitors should be allowed to drop items + item-drops: true + + # Warns online members when a player visits the island. + warn-on-warp: true + + # Whether or not to actively block banned players from entering an island (by walking/flying). + block-banned-entry: true + + # Whether or not visitors can use portals (default: false) + use-portals: false + + # Wheter or not visitors can mount vehicles + vehicle-enter: false + + # Wheter or not visitors can break vehicles + vehicle-damage: false + + # Contains flags for controlling monster spawning on islands. + spawning: + # Controls if Phantoms are allowed to spawn naturally. Non-natural spawns, e.g. from a spawnegg, are not + # managed by us. + phantoms: + # [true/false] If natural Phantom spawns are allowed in the overworld. True enables Phantom spawning. + overworld: true + # [true/false] If natural Phantom spawns are allowed in the nether. True enables Phantom spawning. + nether: false + + party: + + # The number of ms before an invite timeouts (1000 ms per second) + invite-timeout: 30000 + + # The format used in /partytalk chat messages + chat-format: '&9PARTY &r{DISPLAYNAME} &f>&b {MESSAGE}' + + # Extra commands to execute when players join an island + join-commands: + - op:playsound block.enderchest.open block @p + + # Extra commands to execute when players leave an island + leave-commands: + - op:playsound block.enderchest.close block @p + + # This section provide some performance tweaking configs + advanced: + + # If true, display-name is looked up (might be performance intensive). + useDisplayNames: false + + # [number] The threshold for purging islands. + # any island with a level above this, is spared. + purgeLevel: 10 + + # [seconds] The number of seconds for confirming a command by + # re-executing it (/is leave, /is restart). + confirmTimeout: 10 + + # [number] The number of chunks to regenerate per server tick. Might be decreased or increased based on available + # server resources. Default value: 4. + chunkRegenSpeed: 4 + + # If false, the world spawn will be ignored. You should take care of placing the world spawn location + # with /mv setspawn and managing the spawn building. + manageSpawn: true + + # Controls advanced behaviour reg. the internal playerdb + playerdb: + + # valid values are: yml, memory, bukkit + storage: bukkit + + # Section about restarting your island (or accepting an invite). + restart: + + # Clears the player's inventory on island create/restart + clearInventory: true + + # Clears the player's armor on island create/restart + clearArmor: true + + # Clears the player's enderchest on island create/restart + clearEnderChest: true + + # Clears the permissions the player has been granted from rewards + clearPerms: true + + # Clears the users balance (set to 0) + clearCurrency: false + + # [ms] The number of ms to wait, before porting the player back + # on /is restart or /is create (default: 1000) + teleportDelay: 1000 + + # [true/false] Whether or not the player should be auto teleported to the island when it's ready + teleportWhenReady: true + + # list of commands to execute after island-creation + # i.e. + # - me Jumps with &ajoy + extra-commands: [] + +# In this section it's possible to assign additional perks to permission-nodes +donor-perks: + # the permission node to give to someone + 'usb.donor.small': + extraItems: [bone_meal:1] + maxPartySize: 5 + animals: 84 + monsters: 60 + villagers: 20 + golems: 6 + # 10% more XP + rewardBonus: 0.1 + # 10% less hunger + hungerReduction: 0.1 + +# Whether or not to show the UI for create/restart +island-schemes-enabled: true + +# List of selections for /is create and /is restart +# the nodes under island-schemes must match the schematic-names from the schematics folder. +island-schemes: + + # name of the schematic + default: + + # permission needed to use island + permission: usb.island.create + + # small discription of the island + description: The default uSkyBlock island + + # item to display in the GUI + displayItem: oak_sapling + + # optional, default true (true enabled in GUI, false disabled in GUI) + enabled: true + + # optional, must be listed in ascending order + index: 2 + + # optional extra's that can be given per island + extraItems: '' + maxPartySize: 4 + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + + # Get 100% of the normal score + scoreMultiply: 1.0 + + # But start with no offset + scoreOffset: 0 + skySMP: + permission: usb.schematic.skysmp + description: The original SkySMP island + displayItem: oak_leaves + enabled: false + index: 3 + extraItems: + - obsidian:14 + - flint_and_steel:1 + maxPartySize: 4 + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + scoreMultiply: 0.9 + scoreOffset: 40 + spawn: + description: The default spawn schematic + enabled: false +confirmation: + + # [true/false] Whether to require confirmation (i.e. repeating the command twice). + is leave: true + + # [true/false] Whether to require confirmation (i.e. repeating the command twice). + is restart: true +asyncworldedit: + + # Supports disabling the detection of AWE + enabled: true + + # Show progress to the user every 5 seconds + progressEveryMs: 5000 + + # Or 20pct (what-ever comes first) + progressEveryPct: 20 + watchDog: + + # The maximum time to wait for AWE paste to complete (2m, 3m20s, etc.) + timeout: 15s + + # The number of ms between each heartbeat + heartBeatMs: 2000 +worldguard: + entry-message: true + exit-message: true +nether: + enabled: true + height: 75 + lava_level: 7 + activate-at: + level: 100 + schematicName: uSkyBlockNether + terraform-enabled: true + + # The distance to search for valid terra-form location. + terraform-distance: 7 + + # In what range of pitch (vertical aim) will terraforming be enabled + # -90 is looking directly upwards + # 90 is looking directly down + terraform-min-pitch: -70.0 + terraform-max-pitch: 90.0 + + # The probability of forming blocks + terraform: + NETHERRACK: + - '{p=0.30}NETHERRACK' + - '{p=0.15}NETHERRACK' + - '{p=0.05}NETHER_QUARTZ_ORE' + - '{p=0.05}SOUL_SAND' + NETHER_QUARTZ_ORE: + - '{p=0.30}NETHER_QUARTZ_ORE' + - '{p=0.10}NETHER_QUARTZ_ORE' + SOUL_SAND: + - '{p=0.25}SOUL_SAND' + - '{p=0.07}SOUL_SAND' + - '{p=0.05}GRAVEL' + GRAVEL: + - '{p=0.15}GRAVEL' + - '{p=0.05}GRAVEL' + - '{p=0.05}SOUL_SAND' + GLOWSTONE: + - '{p=0.80}GLOWSTONE' + - '{p=0.15}GLOWSTONE' + + # Weights that is applied to the above terraform chances depending on the tool used + terraform-weight: + WOOD: 0 + STONE: 1.0 + IRON: 0.9 + GOLD: 1.5 + DIAMOND: 0.2 + NETHERITE: 1.2 + + # The chances of changing a pigzombie when spawned on a netherbrick + spawn-chances: + enabled: true + wither: 0.2 + skeleton: 0.1 + blaze: 0.2 +tool-menu: + enabled: true + tool: oak_sapling + commands: + CHEST: island + CRAFTING_TABLE: challenges + BEDROCK: island spawn + +plugin-updates: + # Should we check for updates and log a message if an update is available + check: true + # Possible options: RELEASE or STAGING + branch: RELEASE + +# Placeholders - enable these to get placeholder substitution +# usb_version +# usb_island_level, usb_island_level_int +# usb_island_rank, usb_island_partysize_max, usb_island_partysize +# usb_island_leader, usb_island_bans, usb_island_members, usb_island_trustees +# usb_island_biome, usb_island_schematic +# usb_island_location, usb_island_location_x, usb_island_location_y, usb_island_location_z +# usb_island_golems_max, usb_island_monsters_max, usb_island_animals_max, usb_island_villagers_max, +# usb_island_golems, usb_island_monsters, usb_island_animals, usb_island_villagers +placeholder: + + # Hooks into MVdWPlaceholderAPI + mvdwplaceholderapi: false + + # uSkyBlock native placeholders for chat messages and format + chatplaceholder: false + + # uSkyBlock native placeholders for server-commands + servercommandplaceholder: false + +# DO NOT TOUCH THE FIELDS BELOW +version: 109 +force-replace: + options.party.invite-timeout: 100 + options.island.islandTeleportDelay: 5 + options.island.useOldIslands: false + options.island.schematicName: yourschematichere +move-nodes: + options.restart.confirmation: confirmation.is restart + options.party.leave.confirmation: confirmation.is leave + options.island.hopperlimit: options.island.block-limits.hopper + options.island.spawnerlimit: options.island.block-limits.mob_spawner + options.island.block-limits.mob_spawner: options.island.block-limits.spawner diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config.yml new file mode 100644 index 000000000..ebf8f7db1 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-config.yml @@ -0,0 +1,476 @@ +# The language used in the plugin (en is default). +language: en +options: + general: + + # [integer] The max number of players allowed in a single party. (including the leader) + maxPartySize: 4 + + # [integer] The time in seconds before a player can use the /island info command again. (note: cooldowns are reset when the plugin is reloaded) + cooldownInfo: 20 + + # [integer] The time in seconds before a player can use the /island restart command again. + cooldownRestart: 30 + + # [integer] The time in seconds before a player can use the /island biome command again. + biomeChange: 60 + + # [string] The default biome assigned to new islands + defaultBiome: OCEAN + + # [integer] The number of milliseconds between the same notification is sent to the player. + # This is used when events are triggered heavily - i.e. item-pickup-prevention, damage-prevention etc. + maxSpam: 2000 + + # [string] The name of the skyblock world, will be automatically generated if it doesn't exist. + worldName: skyworld + + # [integer] Area around 0,0 where islands will not be created to protect spawn. + spawnSize: 64 + island: + + # [integer] The y-coordinate (height) where islands are spawned. + height: 150 + + # [integer] The number of blocks between islands. + distance: 128 + + # [integer] The size of the protective region for each island. Can't be higher than 'distance' + # and MUST be divisible by 32 if you intend to use nether. + protectionRange: 128 + + # [filename] The schematic to use for island generation. + # Put your schematic in the 'uSkyBlock/schematics' folder, you don't need to add the '.schematic' part below. + schematicName: default + + # [true/false] If true, remove all hostile mobs when a player teleports back to their island. + removeCreaturesByTeleport: false + + # [item list] The list of items to place in the chest when a player starts a new island. ITEM_ID:HOW_MANY. + # default is 2 ice, 1 watermelon, 1 cactus, 1 lava bucket, 1 red & brown mushroom, 1 pumpkin seed, 1 sugar cane, 1 sign. + chestItems: + - ICE:2 + - MELON_SLICE:1 + - CACTUS:1 + - LAVA_BUCKET:1 + - RED_MUSHROOM:1 + - BROWN_MUSHROOM:1 + - PUMPKIN_SEEDS:1 + - SUGAR_CANE:1 + - SIGN:1 + addExtraItems: true + islandTeleportDelay: 2 + allowPvP: deny + allowIslandLock: true + useIslandLevel: true + useTopTen: true + topTenTimeout: 20 + autoRefreshScore: 0 + topTenShowMembers: true + fixFlatland: false + chat-format: '&9SKY &r{DISPLAYNAME} &f>&d {MESSAGE}' + log-size: 10 + spawn-limits: + enabled: true + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + block-limits: + enabled: true + hopper: 50 + spawner: 10 + extraPermissions: + smallbonus: + - COBBLESTONE:16 + - COOKED_PORKCHOP:5 + mediumbonus: + - TORCH:16 + - LAVA_BUCKET:1 + largebonus: + - DIRT:5 + - SAND:5 + giantbonus: + - GRASS:1 + - MYCELIUM:1 + extremebonus: + - BONE:8 + - COAL:4 + donorbonus: + - BOW:1 + - ARROW:32 + - STONE_SWORD:1 + netheraccess: + - OBSIDIAN:14 + - FLINT_AND_STEEL:1 + extras: + + # [true/false] If true, return players that don't have an island (this includes players removed from a party while offline), to the server spawn when they login. + # NOTE: Requires EssentialsSpawn or another plugin with the "/spawn" command + sendToSpawn: false + + # [true/false] If true, when a player respawns they will respawn on their island. Will first attempt to respawn them at the closest safe location to their island home, then their island spawn, then the server spawn. + # NOTE: If this is true, sendToSpawn is ignored unless the player has no island or no viable island home or spawn location. + respawnAtIsland: true + + # [true/false] If true, a player can right-click on a block of obsidian on their island while holding an empty bucket to remove the obsidian and fill the bucket with lava. This is useful for people that accidentally + # turn their lava into obsidian with a bad cobblestone generator design. Will only work on the player's island and if there are no other obsidian blocks nearby (so can't be used on portals). + obsidianToLava: true + + # Contains flags for enabling PROTECTION of various mechanics. + protection: + + # Whether or not, items dropped on the ground should be limited to party-members. + item-drops: true + + # If true, only creepers targeting party-members will explode + creepers: true + + # If true, Withers will be limited to harming island-members/island blocks. + withers: true + + # Whether or not the plugin will try to protect the player from accidentally extinguishing lava + protect-lava: true + + # Whether or not portalling to the nether roof should be blocked. + nether-roof: true + + # Whether or not anyone can trade i skyblock + # default: false - since it goes against the core of skyblock + villager-trading-enabled: false + + # Generally protections against griefers + # If the flag is true, it generally means the protection is active + # (meaning the action is blocked) + visitors: + + # Protect visitors from trampling your crop + trampling: true + + # Protect against visitors attacked animals + kill-animals: true + + # Protect against visitors attacking monsters + kill-monsters: true + + # Protect from shearing + shearing: true + + # Protect from begin bombarded with eggs that hatch + hatching: true + + # Protect from villager-trading + villager-trading: true + + # Whether or not visitors are protected from fall damage + fall: true + + # Whether or not visitors are protected from fire damage (incl. lava) + fire-damage: true + + # Whether or not visitors are protected from monster damage + monster-damage: false + + # Whether or not visitors should be allowed to drop items + item-drops: true + + # Warns online members when a player visits the island. + warn-on-warp: true + + # Whether or not to actively block banned players from entering an island (by walking/flying). + block-banned-entry: true + + # Whether or not visitors can use portals (default: false) + use-portals: false + + # Wheter or not visitors can mount vehicles + vehicle-enter: false + + # Wheter or not visitors can break vehicles + vehicle-damage: false + + # Contains flags for controlling monster spawning on islands. + spawning: + # Controls if Phantoms are allowed to spawn naturally. Non-natural spawns, e.g. from a spawnegg, are not + # managed by us. + phantoms: + # [true/false] If natural Phantom spawns are allowed in the overworld. True enables Phantom spawning. + overworld: true + # [true/false] If natural Phantom spawns are allowed in the nether. True enables Phantom spawning. + nether: false + + party: + + # The number of ms before an invite timeouts (1000 ms per second) + invite-timeout: 30000 + + # The format used in /partytalk chat messages + chat-format: '&9PARTY &r{DISPLAYNAME} &f>&b {MESSAGE}' + + # Extra commands to execute when players join an island + join-commands: + - op:playsound block.enderchest.open block @p + + # Extra commands to execute when players leave an island + leave-commands: + - op:playsound block.enderchest.close block @p + + # This section provide some performance tweaking configs + advanced: + + # If true, display-name is looked up (might be performance intensive). + useDisplayNames: false + + # [number] The threshold for purging islands. + # any island with a level above this, is spared. + purgeLevel: 10 + + # [seconds] The number of seconds for confirming a command by + # re-executing it (/is leave, /is restart). + confirmTimeout: 10 + + # [number] The number of chunks to regenerate per server tick. Might be decreased or increased based on available + # server resources. Default value: 4. + chunkRegenSpeed: 4 + + # If false, the world spawn will be ignored. You should take care of placing the world spawn location + # with /mv setspawn and managing the spawn building. + manageSpawn: true + + # Controls advanced behaviour reg. the internal playerdb + playerdb: + + # valid values are: yml, memory, bukkit + storage: bukkit + + # Section about restarting your island (or accepting an invite). + restart: + + # Clears the player's inventory on island create/restart + clearInventory: true + + # Clears the player's armor on island create/restart + clearArmor: true + + # Clears the player's enderchest on island create/restart + clearEnderChest: true + + # Clears the permissions the player has been granted from rewards + clearPerms: true + + # Clears the users balance (set to 0) + clearCurrency: false + + # [ms] The number of ms to wait, before porting the player back + # on /is restart or /is create (default: 1000) + teleportDelay: 1000 + + # [true/false] Whether or not the player should be auto teleported to the island when it's ready + teleportWhenReady: true + + # list of commands to execute after island-creation + # i.e. + # - me Jumps with &ajoy + extra-commands: [] + +# In this section it's possible to assign additional perks to permission-nodes +donor-perks: + # the permission node to give to someone + 'usb.donor.small': + extraItems: [BONE_MEAL:1] + maxPartySize: 5 + animals: 84 + monsters: 60 + villagers: 20 + golems: 6 + # 10% more XP + rewardBonus: 0.1 + # 10% less hunger + hungerReduction: 0.1 + +# Whether or not to show the UI for create/restart +island-schemes-enabled: true + +# List of selections for /is create and /is restart +# the nodes under island-schemes must match the schematic-names from the schematics folder. +island-schemes: + + # name of the schematic + default: + + # permission needed to use island + permission: usb.island.create + + # small discription of the island + description: The default uSkyBlock island + + # item to display in the GUI + displayItem: SAPLING + + # optional, default true (true enabled in GUI, false disabled in GUI) + enabled: true + + # optional, must be listed in ascending order + index: 2 + + # optional extra's that can be given per island + extraItems: '' + maxPartySize: 4 + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + + # Get 100% of the normal score + scoreMultiply: 1.0 + + # But start with no offset + scoreOffset: 0 + skySMP: + permission: usb.schematic.skysmp + description: The original SkySMP island + displayItem: OAK_LEAVES + enabled: false + index: 3 + extraItems: + - OBSIDIAN:14 + - FLINT_AND_STEEL:1 + maxPartySize: 4 + animals: 64 + monsters: 50 + villagers: 16 + golems: 5 + scoreMultiply: 0.9 + scoreOffset: 40 + spawn: + description: The default spawn schematic + enabled: false +confirmation: + + # [true/false] Whether to require confirmation (i.e. repeating the command twice). + is leave: true + + # [true/false] Whether to require confirmation (i.e. repeating the command twice). + is restart: true +asyncworldedit: + + # Supports disabling the detection of AWE + enabled: true + + # Show progress to the user every 5 seconds + progressEveryMs: 5000 + + # Or 20pct (what-ever comes first) + progressEveryPct: 20 + watchDog: + + # The maximum time to wait for AWE paste to complete (2m, 3m20s, etc.) + timeout: 15s + + # The number of ms between each heartbeat + heartBeatMs: 2000 +worldguard: + entry-message: true + exit-message: true +nether: + enabled: true + height: 75 + lava_level: 7 + activate-at: + level: 100 + schematicName: uSkyBlockNether + terraform-enabled: true + + # The distance to search for valid terra-form location. + terraform-distance: 7 + + # In what range of pitch (vertical aim) will terraforming be enabled + # -90 is looking directly upwards + # 90 is looking directly down + terraform-min-pitch: -70.0 + terraform-max-pitch: 90.0 + + # The probability of forming blocks + terraform: + NETHERRACK: + - '{p=0.30}NETHERRACK' + - '{p=0.15}NETHERRACK' + - '{p=0.05}NETHER_QUARTZ_ORE' + - '{p=0.05}SOUL_SAND' + NETHER_QUARTZ_ORE: + - '{p=0.30}NETHER_QUARTZ_ORE' + - '{p=0.10}NETHER_QUARTZ_ORE' + SOUL_SAND: + - '{p=0.25}SOUL_SAND' + - '{p=0.07}SOUL_SAND' + - '{p=0.05}GRAVEL' + GRAVEL: + - '{p=0.15}GRAVEL' + - '{p=0.05}GRAVEL' + - '{p=0.05}SOUL_SAND' + GLOWSTONE: + - '{p=0.80}GLOWSTONE' + - '{p=0.15}GLOWSTONE' + + # Weights that is applied to the above terraform chances depending on the tool used + terraform-weight: + WOOD: 0 + STONE: 1.0 + IRON: 0.9 + GOLD: 1.5 + DIAMOND: 0.2 + NETHERITE: 1.2 + + # The chances of changing a pigzombie when spawned on a netherbrick + spawn-chances: + enabled: true + wither: 0.2 + skeleton: 0.1 + blaze: 0.2 +tool-menu: + enabled: true + tool: SAPLING + commands: + CHEST: island + CRAFTING_TABLE: challenges + BEDROCK: island spawn + +plugin-updates: + # Should we check for updates and log a message if an update is available + check: true + # Possible options: RELEASE or STAGING + branch: RELEASE + +# Placeholders - enable these to get placeholder substitution +# usb_version +# usb_island_level, usb_island_level_int +# usb_island_rank, usb_island_partysize_max, usb_island_partysize +# usb_island_leader, usb_island_bans, usb_island_members, usb_island_trustees +# usb_island_biome, usb_island_schematic +# usb_island_location, usb_island_location_x, usb_island_location_y, usb_island_location_z +# usb_island_golems_max, usb_island_monsters_max, usb_island_animals_max, usb_island_villagers_max, +# usb_island_golems, usb_island_monsters, usb_island_animals, usb_island_villagers +placeholder: + + # Hooks into MVdWPlaceholderAPI + mvdwplaceholderapi: false + + # uSkyBlock native placeholders for chat messages and format + chatplaceholder: false + + # uSkyBlock native placeholders for server-commands + servercommandplaceholder: false + +# DO NOT TOUCH THE FIELDS BELOW +version: 108 +force-replace: + options.party.invite-timeout: 100 + options.island.islandTeleportDelay: 5 + options.island.useOldIslands: false + options.island.schematicName: yourschematichere +move-nodes: + options.restart.confirmation: confirmation.is restart + options.party.leave.confirmation: confirmation.is leave + options.island.hopperlimit: options.island.block-limits.hopper + options.island.spawnerlimit: options.island.block-limits.mob_spawner + options.island.block-limits.mob_spawner: options.island.block-limits.spawner diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml new file mode 100644 index 000000000..47f39c495 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml @@ -0,0 +1,1791 @@ +# ====================================================================================================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the +# most used settings while the double commented (##) are optional if you like to use those settings. +# +# Item type format +# Item types are defined as in the minecraft /give command, i.e. with their minecraft key and possible components in +# square brackets. For example, 'minecraft:diamond_sword[damage=42]'. Refer to the Minecraft wiki for more information: +# https://minecraft.wiki/w/Data_component_format. You can also use the command '/usb iteminfo' to get the information. +# +# This item type is supplemented with additional information depending on where it is used: +# +# display-item: +# An item to be displayed in a GUI. It only defines the item type as above, without any additional information. +# For example: 'cobblestone', 'minecraft:stone', 'diamond_sword[damage=42]'. +# +# item-requirement: :[;+] +# An item requirement for a challenge. The amount is the number of items required. The optional + is the number +# of items to add to the required amount for each repeat of the challenge. For example, 'cobblestone:64;+16' would +# require 64 cobblestone for the first completion and 80 cobblestone for the second completion. Other options are +# -, *, and / for subtraction, multiplication, and division, respectively. For example, 'cobblestone:64;*2' would +# require 64 cobblestone for the first completion, 128 cobblestone for the second completion, and 256 cobblestone for +# the third completion. +# +# item-reward: [{p=}]: +# An item reward for a challenge. The amount is the number of items to give. The optional {p=} is the +# probability of the item being given. For example, 'cobblestone:64' would give 64 cobblestone every time the challenge +# is completed, while '{p=0.1}cobblestone:64' would give 64 cobblestone 10% of the time. +# +# ====================================================================================================================== +# All challenges are defined in the ranks section. Each rank is a tier of challenges that players can complete. +# +# ranks: +# # [text] name of the challenge Rank. +# TierX: +# # [text] The name of the challenge rank that shows when you do /challenges (supports capitals and color codes). +# name: '&aCustom Challenges rank name' +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: 'cyan_terracotta' +# # [integer] The time in hours before required items reset to default (this overwrites the main reset time) +# resetInHours: 20 +# # These requirements controls when a challenge group will be available to a player. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, +# if you have 4 challenges with a rankLeeway of 1, a player would only need to complete 3 to advance to +# the next rank. A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [List[text]] Challenges that have to be completed before this group will available to a player. +# challenges: +# - a challenge name +# ====================================================================================================================== +# challenges: +# # [text] The name of the challenge. All challenge names should be lower-case. +# defaultchallenge: +# # [text] The name of the challenge that shows in /challenges (this supports capitals and color codes). +# name: '&a Default Challenge' +# # [text] The descriptions players see when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This defines whether the required blocks/items should be in the player's +# # inventory or on their island. When using onIsland, the player must within 10 blocks from the required blocks +# # on his island. When using islandLevel, the 'requiredItems' field should be the island level required. The +# # player must use /island level first to update their level. +# type: onPlayer +# ## type: islandLevel +# ## type: onIsland +# # [integer] Overrides the default radius of 10 blocks when using onIsland. +# ## radius: 20 +# # [List[item-requirement] The items required to complete the challenge. +# requiredItems: +# - stone:64;+16 +# - cobblestone:64;+16 +# # [true/false] If the challenge can be repeated or not. +# ## repeatable: true +# # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. +# # A value of 0 means unlimited repeats. +# ## repeatLimit: 5 +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: cobblestone +# # [integer] The time in hours before required items reset to default (overwrites the main and rank defaults). +# ## resetInHours: 4 +# # [true/false] Take required items on completing a challenge. +# ## takeItems: true +# # The rewards players get for completing the challenge +# reward: +# # [text] Description of the reward. +# text: 'Mossy cobblestone and an iron pickaxe with unbreaking 1' +# # [List[item-requirement]] A list of items given to the player for completing the challenge. +# items: +# - mossy_cobblestone:16 +# - iron_pickaxe[enchantments={levels:{unbreaking:1}}]:1 +# # [permission node] A permission granted for completion. Multiple permissions are space-separated. +# ## permission: 'test.permission' +# # [integer] How much currency to give for completion. (requires an economy plugin) +# ## currency: 0 +# # [integer] How much xp to give to the player for completion. +# ## xp: 0 +# # [List[Text]] Executes the given command upon completion. Prepend with "op" or "console" to run the commands +# as OP or from the Console. Examples: +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +# ## commands: +# ## - 'op: me are the GOD of things' +# ## - 'console: give {party} aweseomestuff 32' +# # reward section to reward the player for completing a repeated challenge (any time after the first). The +# # structure is identical to the 'reward' section. +# repeatReward: +# text: 'Mossy cobblestone' +# items: +# - mossy_cobblestone:16 +# +# ====================================================================================================================== + +# [true/false] Enable the use of the challenges command. +allowChallenges: true + +# [island/player] Whether challenges are tracked per player, or per island +challengeSharing: island + +# [true/false] If true, first time challenge completions are broadcast to the whole server. +broadcastCompletion: true + +# [text] The color/formatting of the broadcast text when showing first time completions. +broadcastText: '&6' + +# [true/false] If true, challenges in higher level ranks require challenges in lower level ranks to be completed. +requirePreviousRank: true + +# [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 easy challenges +# with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. +# A rankLeeway of 0 would require them all. +rankLeeway: 12 + +# [integer] The time in hours before required items reset to default. (only if not specified in the challenges below) +defaultResetInHours: 20 + +# [color code] The color to use for uncompleted challenges in the list. +challengeColor: '&e' + +# [color code] The color to use for completed challenges in the list. (non-repeatable) +finishedColor: '&2' + +# [color code] The color to use for completed challenges in the list. (repeatable) +repeatableColor: '&a' + +# [true/false] If true, enables vault to handle currency rewards. +enableEconomyPlugin: true + +# [true/false] If false, challenges are not reset on island creation (or restart) +resetChallengesOnCreate: true + +# Material to show for locked challenges (i.e. STAINED_GLASS_PANE:14 for a red glass-pane, or 160:14) +lockedDisplayItem: red_stained_glass_pane + +# Material to show for onIsland challenges when locked +ISLAND: + lockedDisplayItem: blue_stained_glass_pane + +# Material to show for islandLevel challenges when locked +ISLAND_LEVEL: + lockedDisplayItem: black_stained_glass_pane + +# Whether to show the name of locked challenges +showLockedChallengeName: true + +# When creating your own challenges you will have +# to uncomment the section below or the default challenges +# will be re-added on every server restart. When altering +# the default challenges this should be fine to leave. +# merge-ignore: +# - 'ranks' +# +# =============================================== +# An explanation to setup your own challenges +# can be found at the bottom of this file. +# =============================================== +ranks: + Tier1: + name: '&7Novice' + displayItem: cyan_terracotta + resetInHours: 20 + challenges: + cobblestonegenerator: + name: '&7Cobble Stone Generator' + description: Mine from a cobblestone generator. + type: onPlayer + requiredItems: + - cobblestone:64;+2 + displayItem: cobblestone + lockedDisplayItem: gray_stained_glass_pane + resetInHours: 12 + reward: + text: 3 leather, 20% chance to get a book + items: + - leather:3 + - '{p=0.2}book:1' + currency: 10 + xp: 10 + commands: + - op:effect give {player} regeneration + repeatReward: + text: 1 leather, 10% chance to get a book + items: + - leather:1 + - '{p=0.1}book:1' + currency: 5 + xp: 5 + applecollector: + name: '&6Apple Collector' + description: Collect apples from trees. + type: onPlayer + requiredItems: + - apple:2;+1 + displayItem: apple + lockedDisplayItem: brown_stained_glass_pane + resetInHours: 6 + reward: + text: 1 of each sapling, (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.2}jungle_sapling:3' + currency: 20 + xp: 20 + repeatReward: + text: 1 of each sapling (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.1}jungle_sapling:3' + currency: 10 + xp: 10 + sugarplanter: + name: '&9Sugar Planter' + type: onIsland + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + requiredItems: + - sugar_cane:4 + reward: + text: 4 dirt + items: + - dirt:4 + currency: 20 + xp: 20 + sugarfarmer: + name: '&6Sugar Farmer' + description: Harvest sugarcane from a farm. + type: onPlayer + requiredItems: + - sugar_cane:64;+16 + offset: -1 + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.1}bone:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}dirt:4' + currency: 10 + xp: 10 + melonfarmer: + name: '&6Melon Farmer' + description: Harvest slices of melon from a farm. + type: onPlayer + requiredItems: + - melon_slice:128;+8 + displayItem: melon + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + currency: 10 + xp: 10 + cactusfarmer: + name: '&6Cactus Farmer' + description: Harvest cacti from a farm. + type: onPlayer + requiredItems: + - cactus:64;+16 + displayItem: cactus + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 sand, 20% chance to get a bone + items: + - sand:8 + - '{p=0.2}bone:1' + - '{p=0.1}wooden_hoe:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 sand + items: + - sand:4 + - '{p=0.1}bone:1' + currency: 10 + xp: 10 + pumpkinfarmer: + name: '&6Pumpkin Farmer' + description: Harvest pumpkins from a farm. + type: onPlayer + requiredItems: + - pumpkin:64;+4 + displayItem: pumpkin + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.3}jack_o_lantern:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}jack_o_lantern:1' + currency: 10 + xp: 10 + stonebrickmaker: + name: '&aStone Brick Maker' + description: Make 64 Stone Bricks. + type: onPlayer + requiredItems: + - stone_bricks:64;+8 + - stone_brick_slab:30;+6 + - chiseled_stone_bricks:30;+6 + - stone_brick_stairs:16;+4 + displayItem: stone_bricks + lockedDisplayItem: gray_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 chicken + items: + - redstone_ore:4 + - iron_ore:4 + - chicken_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + novicebuilder: + name: '&7Novice Builder' + description: Reach island level 20. + type: islandLevel + requiredLevel: 20 + displayItem: coal_ore + reward: + text: 8 dirt, 8 sand, 5 emeralds + items: + - dirt:8 + - sand:8 + - emerald:5 + - diamond:1 + currency: 20 + xp: 20 + commands: + - op:effect give {party} regeneration + adeptbuilder: + name: '&aAdept Builder' + description: Reach island level 50. + type: islandLevel + requiredLevel: 50 + displayItem: iron_ore + offset: -1 + reward: + text: 10 obsidian, 2 diamonds, 5 emeralds + items: + - obsidian:10 + - emerald:5 + - diamond:2 + currency: 100 + xp: 100 + expertbuilder: + name: '&eExpert Builder' + description: Reach island level 100. + type: islandLevel + requiredLevel: 100 + displayItem: gold_ore + offset: -1 + reward: + text: 16 dirt, 16 sand, 3 diamonds, 5 emeralds + items: + - dirt:16 + - sand:16 + - emerald:5 + - diamond:3 + currency: 250 + xp: 250 + masterbuilder: + name: '&cMaster Builder' + description: Reach island level 250. + type: islandLevel + requiredLevel: 250 + displayItem: diamond_ore + offset: -1 + reward: + text: 32 dirt, 32 sand, 4 diamonds, 5 emeralds + items: + - dirt:32 + - sand:32 + - emerald:5 + - diamond:4 + currency: 500 + xp: 500 + skylord: + name: '&4Sky Lord' + description: Reach island level 500. + type: islandLevel + requiredLevel: 500 + displayItem: emerald_ore + offset: -1 + reward: + text: 64 dirt, 64 sand, 5 diamond, 5 emeralds + items: + - dirt:64 + - sand:64 + - diamond:5 + - emerald:5 + currency: 1000 + xp: 1000 + Tier2: + name: '&aAdept' + displayItem: lime_terracotta + resetInHours: 20 + requires: + + # means disabled in effect + rankLeeway: 99 + challenges: + - cobblestonegenerator + - novicebuilder + challenges: + lumberjack: + name: '&3Lumberjack' + description: Collect all types of wood logs. + type: onPlayer + requiredItems: + - oak_log:16;+2 + - spruce_log:16;+2 + - birch_log:16;+2 + - jungle_log:16;+2 + - acacia_log:16;+2 + - dark_oak_log:16;+2 + displayItem: oak_log + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 wolf + items: + - redstone_ore:4 + - iron_ore:4 + - wolf_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + shroompicker: + name: '&6Shroom Picker' + description: Collect red and brown mushrooms. + type: onPlayer + requiredItems: + - brown_mushroom:64;+4 + - red_mushroom:64;+4 + displayItem: red_mushroom + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 mycelium, 4 podzol + items: + - mycelium:8 + - podzol:4 + currency: 30 + xp: 30 + repeatReward: + text: 4 mycelium + items: + - mycelium:4 + - '{p=0.02}mycelium:4' + - '{p=0.02}podzol:2' + currency: 15 + xp: 15 + potatofarmer: + name: '&6Potato Farmer' + description: Harvest potato's from a farm. + type: onPlayer + requiredItems: + - potato:64;+16 + displayItem: potato + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 carrot, 4 dirt + items: + - carrot:1 + - dirt:4 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 4 dirt and a baked potato + items: + - dirt:4 + - baked_potato:1 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + carrotfarmer: + name: '&6Carrot Farmer' + description: Harvest carrot's from a farm. + type: onPlayer + requiredItems: + - carrot:64;+16 + displayItem: carrot + lockedDisplayItem: brown_stained_glass_pane + reward: + text: a pig with saddle and a potato + items: + - saddle:1 + - potato:1 + - pig_spawn_egg:1 + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 golden carrot + items: + - golden_carrot:1 + - '{p=0.05}sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + wheatfarmer: + name: '&6Wheat Farmer' + description: Harvest wheat from a farm. + type: onPlayer + requiredItems: + - wheat:64;+16 + displayItem: wheat + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.2}bone:1' + currency: 10 + xp: 10 + monsterfarm: + name: '&5Monster Farm' + description: Build a mob farm and collect mob loot. + type: onPlayer + requiredItems: + - rotten_flesh:64;+4 + - string:32;+2 + - arrow:32;+2 + - bone:32;+2 + - gunpowder:16;+1 + - spider_eye:5 + displayItem: rotten_flesh + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore and 1 flint + items: + - redstone_ore:4 + - iron_ore:4 + - flint:1 + - '{p=0.10}potato:1' + - '{p=0.10}carrot:1' + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore, 1 flint + items: + - redstone_ore:1 + - iron_ore:4 + - flint:1 + - '{p=0.05}potato:1' + - '{p=0.05}carrot:1' + currency: 15 + xp: 15 + homeowner: + name: '&9Home Owner' + description: Build a house with furnishings. + type: onIsland + requiredChallenges: + - stonebrickmaker + requiredItems: + - red_bed:1 + - crafting_table:1 + - glass:1 + - oak_door:1 + - furnace:1 + - bookshelf:1 + - torch:1 + lockedDisplayItem: blue_stained_glass_pane + displayItem: oak_door + reward: + text: 4 redstone ore, 5 inksac, 4 iron ore and some seeds + items: + - redstone_ore:4 + - iron_ore:4 + - ink_sac:5 + - beetroot_seeds:1 + currency: 40 + xp: 40 + netherportal: + name: '&9Nether Portal' + description: Build a nether portal on your island. + type: onIsland + requiredChallenges: + - adeptbuilder + - homeowner + requiredItems: + - obsidian:10 + - nether_portal:1 + displayItem: obsidian + lockedDisplayItem: blue_stained_glass_pane + reward: + text: 1 iron pickaxe, 1 iron shovel + items: + - iron_shovel:1 + - iron_pickaxe:1 + currency: 40 + xp: 40 + nethermining: + name: '&7Nether Mining' + description: Mine from your Nether island. + type: onPlayer + displayItem: netherrack + lockedDisplayItem: gray_stained_glass_pane + offset: -1 + requiredItems: + - netherrack:64;+2 + - soul_sand:16;+2 + - gravel:16;+2 + - quartz:32;+2 + - glowstone:16;+2 + - coarse_dirt:4;+2 + reward: + text: 1 ghast tear, 1 magic bow + items: + - ghast_tear:1 + - 'bow[enchantments={levels:{infinity:1,unbreaking:3}}]:1' + currency: 40 + xp: 40 + repeatReward: + text: a blaze-rod and a chance of ghast tear + items: + - blaze_rod:1 + - '{p=0.10}ghast_tear:1' + currency: 20 + xp: 20 + Tier3: + name: '&eExpert' + displayItem: yellow_terracotta + resetInHours: 20 + requires: + challenges: + - adeptbuilder + challenges: + toolmaker: + name: '&3Tool Maker' + description: Make all stone tools + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - stone_shovel:1 + - stone_pickaxe:1 + - stone_axe:1 + - stone_hoe:1 + displayItem: stone_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, 1 pig + items: + - redstone_ore:4 + - iron_ore:4 + - pig_spawn_egg:1 + currency: 30 + xp: 30 + sawmill: + name: '&3Saw Mill' + description: Deliver a collection of processed wood + type: onPlayer + offset: -1 + requiredChallenges: + - toolmaker + requiredItems: + - stripped_oak_log:8;+2 + - stripped_spruce_log:8;+2 + - stripped_birch_log:8;+2 + - stripped_jungle_log:8;+2 + - stripped_acacia_log:8;+2 + - stripped_dark_oak_log:8;+2 + displayItem: iron_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, cocoa and a mule + items: + - cocoa_beans:1 + - redstone_ore:4 + - iron_ore:4 + - mule_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.05}gold_ore:1' + currency: 15 + xp: 15 + torchmaker: + name: '&3Torch Maker' + description: Make 128 torches. + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - torch:128;+32 + displayItem: torch + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore + items: + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + expertfarmer: + name: '&6Expert Farmer' + description: Harvest many different farming resources. + type: onPlayer + displayItem: iron_hoe + lockedDisplayItem: brown_stained_glass_pane + requiredChallenges: + - applecollector + - melonfarmer + - pumpkinfarmer + - wheatfarmer + - carrotfarmer + - potatofarmer + - cactusfarmer + - sugarfarmer + - shroompicker + requiredItems: + - melon_slice:256;+2 + - sugar_cane:128;+2 + - wheat:128;+2 + - potato:128;+2 + - carrot:128;+2 + - pumpkin:128;+2 + - cactus:128;+2 + - beetroot:128;+2 + reward: + text: a bucket, cocoa and a cow + items: + - bucket:1 + - cocoa_beans:1 + - cow_spawn_egg:1 + currency: 50 + xp: 50 + repeatReward: + text: a cow + items: + - cow_spawn_egg:1 + currency: 25 + xp: 25 + fisherman: + name: '&5Fisherman' + description: Catch different types of fish. + type: onPlayer + requiredItems: + - cod:5;+1 + - salmon:5;+1 + - pufferfish:3;+1 + - tropical_fish:1;+0 + - ink_sac:5;+2 + displayItem: cod + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 10 lapis blocks, 20 prismarine, kelp, deep-ocean + items: + - lapis_block:10 + - prismarine:20 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: 2 lapis, 5 prismarine, kelp and a chance at prismarine crystals + items: + - lapis_lazuli:2 + - prismarine:5 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + currency: 25 + xp: 25 + woolcollector: + name: '&5Wool Collector' + description: Collect every color of wool. + type: onPlayer + displayItem: white_wool + lockedDisplayItem: purple_stained_glass_pane + requiredChallenges: + - monsterfarmer + requiredItems: + - white_wool:2;+4 + - orange_wool:2;+4 + - magenta_wool:2;+4 + - light_blue_wool:2;+4 + - yellow_wool:2;+4 + - lime_wool:2;+4 + - pink_wool:2;+4 + - gray_wool:2;+4 + - light_gray_wool:2;+4 + - cyan_wool:2;+4 + - purple_wool:2;+4 + - blue_wool:2;+4 + - brown_wool:2;+4 + - green_wool:2;+4 + - red_wool:2;+4 + - black_wool:2;+4 + reward: + text: 2 diamonds, sheep, emerald, flowers + items: + - diamond:2 + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: emerald, sheep, flowers + items: + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + currency: 35 + xp: 35 + maestro: + name: '&5Maestro' + description: Make a jukebox and collect all music discs. + type: onPlayer + requiredItems: + - music_disc_13:1 + - music_disc_cat:1 + - music_disc_blocks:1 + - music_disc_chirp:1 + - music_disc_far:1 + - music_disc_mall:1 + - music_disc_mellohi:1 + - music_disc_stal:1 + - music_disc_strad:1 + - music_disc_ward:1 + - music_disc_11:1 + - music_disc_wait:1 + - jukebox:1 + displayItem: jukebox + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 3 diamonds, 1 gold block, 10 emeralds + items: + - diamond:3 + - emerald:10 + - gold_block:1 + currency: 70 + xp: 70 + repeatReward: + text: 2 gold ore, 1 diamond + items: + - gold_ore:2 + - diamond:1 + - '{p=0.2}diamond:1' + currency: 35 + xp: 35 + ironfarm: + name: '&9Iron Farm' + description: Build an iron-farm. + type: onIsland + displayItem: iron_block + lockedDisplayItem: blue_stained_glass_pane + radius: 50 + requiredChallenges: + - monsterfarm + - applecollector + requiredItems: + - oak_door:30 + requiredEntities: + - Villager:10 + - IRON_GOLEM:1 + reward: + text: 2 gold blocks, 1 diamond block + items: + - gold_block:2 + - diamond_block:1 + currency: 500 + xp: 400 + netherfortress: + name: '&9Nether Fortress' + description: Build a netherfortress. + type: onIsland + radius: 50 + requiredItems: + - nether_bricks:512 + - nether_brick_slab:64 + - nether_brick_fence:64 + - nether_brick_stairs:64 + - soul_sand:32 + displayItem: nether_brick_fence + lockedDisplayItem: blue_stained_glass_pane + reward: + text: a wither-skull and a blaze rod and a chance of diamonds + items: + - wither_skeleton_skull:1 + - blaze_rod:1 + - '{p=0.05}diamond:3' + - '{p=0.10}diamond:2' + - '{p=0.15}diamond:1' + currency: 40 + xp: 40 + # =============================================== + Tier4: + name: '&cMaster' + displayItem: orange_terracotta + resetInHours: 20 + requires: + + # disabled + rankLeeway: 99 + challenges: + - expertbuilder + challenges: + glassmaker: + name: '&3Glassmaker' + description: Collect every color of stained glass. + type: onPlayer + displayItem: white_stained_glass + lockedDisplayItem: cyan_stained_glass_pane + requiredItems: + - white_stained_glass:8;+2 + - orange_stained_glass:8;+2 + - magenta_stained_glass:8;+2 + - light_blue_stained_glass:8;+2 + - yellow_stained_glass:8;+2 + - lime_stained_glass:8;+2 + - pink_stained_glass:8;+2 + - gray_stained_glass:8;+2 + - light_gray_stained_glass:8;+2 + - cyan_stained_glass:8;+2 + - purple_stained_glass:8;+2 + - blue_stained_glass:8;+2 + - brown_stained_glass:8;+2 + - green_stained_glass:8;+2 + - red_stained_glass:8;+2 + - black_stained_glass:8;+2 + reward: + text: 2 diamonds, 2 disks, 1 emeralds + items: + - diamond:2 + - music_disc_ward:1 + - music_disc_11:1 + - emerald:1 + - sunflower:1 + - lilac:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: 30% chance on 1 or 2 disks, 1 emeralds + items: + - '{p=0.3}music_disc_ward:1' + - '{p=0.3}music_disc_11:1' + - emerald:1 + - sunflower:1 + - lilac:1 + currency: 35 + xp: 35 + carpenter: + name: '&3Carpenter' + description: Collect all types of wood items. + type: onPlayer + requiredItems: + - jungle_stairs:16;+8 + - spruce_door:1;+1 + - dark_oak_fence_gate:2;+2 + - acacia_fence:30;+15 + - ladder:30;+15 + - oak_trapdoor:4;+2 + - oak_pressure_plate:2;+1 + requiredChallenges: + - toolmaker + - lumberjack:2 + displayItem: crafting_table + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: a parrot and a jukebox with some redstone and iron + items: + - parrot_spawn_egg:1 + - jukebox:1 + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: redstone, iron and a slim chance at a parrot + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.25}jukebox:1' + - '{p=0.05}parrot_spawn_egg:1' + currency: 15 + xp: 15 + cookielover: + name: '&eCookie Lover' + description: Make cookies and a bucket of milk. + type: onPlayer + requiredChallenges: + - expertfarmer + requiredItems: + - cookie:128;+4 + - milk_bucket:1 + displayItem: cookie + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 4 redstone ore, clay a bucket and a diamond + items: + - redstone_ore:4 + - clay:5 + - diamond:1 + - bucket:1 + currency: 80 + xp: 80 + repeatReward: + text: iron ore and some clay + items: + - iron_ore:1 + - clay:5 + - bucket:1 + - '{p=0.4}clay:3' + - '{p=0.3}iron_ore:2' + currency: 40 + xp: 40 + deepseafisherman: + name: '&5Deep Sea Fishing' + description: Farm the deep sea + type: onPlayer + requiredItems: + - cod:10;+5 + - salmon:10;+5 + - pufferfish:5;+3 + - tropical_fish:3;+2 + - prismarine_crystals:16;+8 + - prismarine_shard:16;+8 + - dried_kelp_block:64;+32 + - nautilus_shell:1 + displayItem: heart_of_the_sea + lockedDisplayItem: purple_stained_glass_pane + reward: + text: heart-of-the-sea, nautilus shell and a turtle + items: + - nautilus_shell:1 + - heart_of_the_sea:1 + - turtle_spawn_egg:1 + - '{p=0.1}nautilus_shell:1' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: nautilus shell, turtle and a chance of a heart + items: + - nautilus_shell:1 + - turtle_spawn_egg:1 + - '{p=0.05}heart_of_the_sea:1' + - '{p=0.1}nautilus_shell:1' + currency: 25 + xp: 25 + horsingaround: + name: '&6Horsing Around' + description: Get hay bales for the horses. + type: onPlayer + requiredItems: + - hay_block:32;+4 + - lead:8;+2 + - carrot_on_a_stick:1 + - shears:1 + requirecChallenges: + - wheatfarmer + displayItem: hay_block + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 horse, 1 iron horse armor, 5% chance on diamond horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald + items: + - redstone:1 + - emerald:1 + currency: 25 + xp: 25 + slimefarmer: + name: '&5Slime Farmer' + description: Collect slimeballs from slimes. + type: onPlayer + requiredItems: + - slime_ball:64;+4 + displayItem: slime_ball + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 1 diamond, 1 emeralds, swampland + items: + - diamond:1 + - emerald:1 + permission: usb.biome.swamp + currency: 70 + xp: 70 + repeatReward: + text: 1 redstone ore, 1 emeralds + items: + - redstone_ore:1 + - emerald:1 + currency: 35 + xp: 35 + animalfarm: + name: '&9Animal Farm' + description: Create an animal farm. + type: onIsland + displayItem: oak_fence + radius: 40 + requiredChallenges: + - woolcollector + - potatofarmer + - carrotfarmer + requiredEntities: + - Cow:8 + - Pig:8 + - Chicken:16 + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} + reward: + text: 1 horse, 1 iron horse armor, 5% chance horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald, 5% chance horse armor + items: + - redstone:1 + - emerald:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 25 + xp: 25 + witherhunter: + name: '&5Wither Hunter' + description: Collect some Wither Skeleton skulls. + type: onPlayer + requiredChallenges: + - netherfortress + requiredItems: + - wither_skeleton_skull:10;+1 + displayItem: wither_skeleton_skull + lockedDisplayItem: purple_stained_glass_pane + offset: -1 + reward: + text: 5 diamonds, 5% chance of nether star + items: + - diamond:5 + - '{p=0.05}nether_star:1' + currency: 400 + xp: 400 + repeatReward: + text: 2 gold ore, 5% chance of nether star + items: + - gold_ore:2 + - '{p=0.05}nether_star:1' + currency: 20 + xp: 20 + pearlcollector: + name: '&5Pearl Collector' + description: Collect enderpearls from endermen. + type: onPlayer + requiredItems: + - ender_pearl:10;+4 + displayItem: ender_pearl + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 5 gold ore, 1 blaze rod, 1 emerald + items: + - gold_ore:5 + - blaze_rod:1 + - emerald:1 + currency: 70 + xp: 70 + repeatReward: + text: 1 gold ore, 1 blaze rod + items: + - gold_ore:1 + - blaze_rod:1 + currency: 35 + xp: 35 + + # =============================================== + Tier5: + name: '&4Sky Lord' + displayItem: red_terracotta + resetInHours: 48 + requires: + challenges: + - masterbuilder + challenges: + technician: + name: '&3Technician' + description: Collect some of every type of redstone equipment. + type: onPlayer + requiredItems: + - redstone:64;+16 + - redstone_torch:32;+4 + - repeater:5;+1 + - comparator:3;+1 + - piston:2;+1 + - sticky_piston:2;+1 + - lever:1;+1 + - stone_button:1;+1 + - stone_pressure_plate:1;+1 + - hopper:1;+1 + - dispenser:1;+1 + - dropper:1;+1 + - daylight_detector:1;+1 + displayItem: redstone + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: some snow, ice and packed ice + items: + - snow_block:4 + - ice:8 + - packed_ice:8 + - redstone_block:64 + currency: 70 + xp: 70 + repeatReward: + text: a stack of redstone blocks and some ice + items: + - redstone_block:64 + - ice:4 + - packed_ice:1 + currency: 35 + xp: 35 + emeraldcollector: + name: '&5Emerald Collector' + description: Collect emeralds. + type: onPlayer + requiredItems: + - emerald:60;+10 + displayItem: emerald + lockedDisplayItem: purple_stained_glass_pane + reward: + text: a full set of diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 70 + xp: 70 + repeatReward: + text: full diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 35 + xp: 35 + topchef: + name: '&eTop Chef' + description: Collect every kind of edible food. + type: onPlayer + requiredItems: + - baked_potato:1 + - bread:1 + - cake:1 + - cooked_chicken:1 + - cooked_cod:1 + - cooked_salmon:1 + - tropical_fish:1 + - cooked_porkchop:1 + - cookie:1 + - golden_apple:1 + - golden_carrot:1 + - mushroom_stew:1 + - pumpkin_pie:1 + - cooked_beef:1 + - melon:1 + - carrot:1 + requiredChallenges: + - expertfarmer + - fisherman + - cookielover + displayItem: carrot + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 diamond, 1 mooshroom + items: + - diamond:2 + - mooshroom_spawn_egg:1 + currency: 80 + xp: 80 + repeatReward: + text: 1 diamond, 1 mooshroom + items: + - diamond:1 + - mooshroom_spawn_egg:1 + currency: 40 + xp: 40 + tajmahal: + name: '&9Taj Mahal' + description: Build a temple of quartz + type: onIsland + radius: 30 + displayItem: quartz_block + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - nethermining + requiredItems: + - quartz_block:512 + - chiseled_quartz_block:64 + - quartz_pillar:128 + - quartz_stairs:64 + - quartz_slab:192 + reward: + text: 3 end-portal frames, red sand + items: + - end_portal_frame:3 + - red_sand:64 + currency: 1000 + xp: 500 + greatpyramid: + name: '&9Great Pyramid' + description: Build a pyramid of sandstone + type: onIsland + radius: 30 + displayItem: sandstone + lockedDisplayItem: blue_stained_glass_pane + requiredItems: + - sandstone:512 + - chiseled_sandstone:64 + - smooth_sandstone:128 + - sandstone_stairs:64 + - sandstone_slab:192 + - red_sandstone:16 + reward: + text: 3 end-portal frames, 3 diamonds, bow + items: + - end_portal_frame:3 + - diamond:3 + - 'bow[enchantments={levels:{infinity:1,power:5,unbreaking:3}}]:1' + currency: 1000 + xp: 500 + poseidonshalls: + name: '&9Poseidon''s Halls' + description: Build the halls of Poseidon + type: onIsland + radius: 50 + displayItem: prismarine + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - deepseafisherman + requiredItems: + - prismarine:512 + - prismarine_bricks:128 + - dark_prismarine:64 + - sea_lantern:32 + - conduit:1 + - flower_pot:16 + - vine:128 + - poppy:10 + - blue_orchid:10 + - allium:10 + - azure_bluet:10 + - red_tulip:10 + - orange_tulip:10 + - white_tulip:10 + - pink_tulip:10 + - oxeye_daisy:10 + - sunflower:10 + - lilac:10 + - rose_bush:10 + - peony:10 + reward: + text: 3 end-portal frames, 5 diamonds + items: + - end_portal_frame:3 + - diamond:5 + currency: 1000 + xp: 500 + beaconator: + name: '&9Beaconator' + description: Build a very expensive beacon. + type: onIsland + radius: 15 + displayItem: beacon + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - netherfortress + - ironfarm + - maestro + - witherhunter + requiredItems: + - beacon:1 + - diamond_block:1 + - emerald_block:8 + - gold_block:25 + - iron_block:49 + reward: + items: + - end_portal_frame:3 + - 'diamond_sword[enchantments={levels:{fire_aspect:1,sharpness:5,unbreaking:3}}]:1' + text: some end-portal-pieces and a magic diamond sword + currency: 4000 + xp: 1000 + endportal: + name: '&9End Portal' + description: Build and activate an end-portal. + type: onIsland + radius: 15 + displayItem: end_portal_frame + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - beaconator + - tajmahal + - poseidonshalls + - greatpyramid + requiredItems: + - end_portal_frame:12 + - end_portal:9 + reward: + text: 5 diamonds and some nice boots + items: + - diamond:5 + - 'diamond_boots[enchantments={levels:{blast_protection:4,feather_falling:4,protection:4}}]:1' + currency: 4000 + xp: 1000 + + # =============================================== + Tier6: + name: '&aWorld Foods' + displayItem: light_gray_terracotta + resetInHours: 20 + requires: + challenges: + - masterbuilder + - topchef + challenges: + fishandchips: + name: '&eFish & Chips' + description: Create the famous English Fish & Chips. + type: onPlayer + requiredItems: + - cooked_cod:32;+8 + - baked_potato:32;+8 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 16 baked potatos, 1 disk, 4 emerald + items: + - baked_potato:16 + - music_disc_13:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + smorrebrod: + name: '&eSmørrebrød' + description: Create the famous Danish smørrebrød. + type: onPlayer + requiredItems: + - bread:16;+4 + - cooked_salmon:8;+4 + - tropical_fish:2;+1 + - cooked_porkchop:8;+4 + - cooked_beef:8;+4 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 rod, 2 name tags, 2 ocelots + items: + - fishing_rod:1 + - name_tag:2 + - ocelot_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + repeatReward: + text: 1 emerald + items: + - emerald:1 + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + hutspot: + name: '&eHutspot' + description: Create the famous Dutch hutspot. + type: onPlayer + requiredItems: + - potato:64;+8 + - carrot:64;+8 + lockedDisplayItem: yellow_stained_glass_pane + displayItem: golden_carrot + reward: + text: 1 golden carrot, 1 disk, 4 emerald + items: + - golden_carrot:1 + - music_disc_cat:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_cat:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + apfelstrudel: + name: '&eApfelstrudele' + description: Create the famous German apfelstrudel. + type: onPlayer + requiredItems: + - apple:8;+5 + - wheat:16;+5 + - sugar:16;+5 + - milk_bucket:1 + displayItem: golden_apple + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_blocks:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_blocks:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + brownies: + name: '&eBrownies' + description: Create the famous American brownies. + type: onPlayer + requiredItems: + - wheat:16;+5 + - sugar:16;+5 + - egg:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: dark_oak_slab + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_far:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_far:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + pastafunghi: + name: '&ePasta Funghi' + description: Create the famous Italian Pasta Funghi. + type: onPlayer + requiredItems: + - wheat:32;+8 + - egg:32;+8 + - brown_mushroom:16;+4 + - red_mushroom:16;+4 + - milk_bucket:1 + displayItem: red_mushroom_block + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 rabbits, 1 bucket + items: + - bucket:1 + - rabbit_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + chocolate: + name: '&eBelgian chocolate' + description: Create the famous belgian chocolate. + type: onPlayer + requiredItems: + - sugar:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: pig_spawn_egg + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emeralds + items: + - bucket:1 + - emerald:4 + - music_disc_mall:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_mall:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + baker: + name: '&ePâtisserie' + description: Bake cakes, pumpkin pies, and cookies. + type: onPlayer + requiredItems: + - cake:5;+1 + - pumpkin_pie:5;+1 + - cookie:128;+4 + displayItem: cake + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 5 gold ore, 1 diamond + items: + - gold_ore:5 + - diamond:1 + currency: 80 + xp: 80 + repeatReward: + text: 2 iron ore, 1 gold ore + items: + - iron_ore:2 + - gold_ore:1 + currency: 40 + xp: 40 + +# This file has been updated to version 107. Please check the changes made in this version. +# Changes in this version: +# - Items are now specified in the new component format. +# - Refer to the config header for the new format. +# - NBT tags are not automatically converted. They have been moved to the comments, please check them manually. +# You can use the following converter to convert the old item specifications to the new format: +# https://docs.papermc.io/misc/tools/item-command-converter +# DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen! +version: 107 diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges.yml new file mode 100644 index 000000000..2f6d9f62e --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges.yml @@ -0,0 +1,1767 @@ +# [true/false] Enable the use of the challenges command. +allowChallenges: true + +# [island/player] Whether challenges are tracked per player, or per island +challengeSharing: island + +# [true/false] If true, first time challenge completions are broadcast to the whole server. +broadcastCompletion: true + +# [text] The color/formatting of the broadcast text when showing first time completions. +broadcastText: '&6' + +# [true/false] If true, challenges in higher level ranks require challenges in lower level ranks to be completed. +requirePreviousRank: true + +# [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 easy challenges +# with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. +# A rankLeeway of 0 would require them all. +rankLeeway: 12 + +#[integer] The time in hours before required items reset to default. (only if not specified in the challenges below) +defaultResetInHours: 20 + +#[color code] The color to use for uncompleted challenges in the list. +challengeColor: '&e' + +#[color code] The color to use for completed challenges in the list. (non-repeatable) +finishedColor: '&2' + +#[color code] The color to use for completed challenges in the list. (repeatable) +repeatableColor: '&a' + +#[true/false] If true, enables vault to handle currency rewards. +enableEconomyPlugin: true + +# [true/false] If false, challenges are not reset on island creation (or restart) +resetChallengesOnCreate: true + +# Material to show for locked challenges (i.e. STAINED_GLASS_PANE:14 for a red glass-pane, or 160:14) +lockedDisplayItem: RED_STAINED_GLASS_PANE + +# Material to show for onIsland challenges when locked +ISLAND: + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + +# Material to show for islandLevel challenges when locked +ISLAND_LEVEL: + lockedDisplayItem: BLACK_STAINED_GLASS_PANE + +# Whether to show the name of locked challenges +showLockedChallengeName: true + +# When creating your own challenges you will have +# to uncomment the section below or the default challenges +# will be re-added on every server restart. When altering +# the default challenges this should be fine to leave. +#merge-ignore: +# - 'ranks' +# +#=============================================== +# An explanation to setup your own challenges +# can be found at the bottom of this file. +#=============================================== +ranks: + Tier1: + name: '&7Novice' + displayItem: CYAN_TERRACOTTA + resetInHours: 20 + challenges: + cobblestonegenerator: + name: '&7Cobble Stone Generator' + description: Mine from a cobblestone generator. + type: onPlayer + requiredItems: + - COBBLESTONE:64;+2 + displayItem: COBBLESTONE + lockedDisplayItem: GRAY_STAINED_GLASS_PANE + resetInHours: 12 + reward: + text: 3 leather, 20% chance to get a book + items: + - LEATHER:3 + - '{p=0.2}BOOK:1' + currency: 10 + xp: 10 + commands: + - op:effect give {player} regeneration + repeatReward: + text: 1 leather, 10% chance to get a book + items: + - LEATHER:1 + - '{p=0.1}BOOK:1' + currency: 5 + xp: 5 + applecollector: + name: '&6Apple Collector' + description: Collect apples from trees. + type: onPlayer + requiredItems: + - APPLE:2;+1 + displayItem: APPLE + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + resetInHours: 6 + reward: + text: 1 of each sapling, (4 dark oak) + items: + - OAK_SAPLING:1 + - SPRUCE_SAPLING:1 + - BIRCH_SAPLING:1 + - JUNGLE_SAPLING:1 + - ACACIA_SAPLING:1 + - DARK_OAK_SAPLING:4 + - '{p=0.2}JUNGLE_SAPLING:3' + currency: 20 + xp: 20 + repeatReward: + text: 1 of each sapling (4 dark oak) + items: + - OAK_SAPLING:1 + - SPRUCE_SAPLING:1 + - BIRCH_SAPLING:1 + - JUNGLE_SAPLING:1 + - ACACIA_SAPLING:1 + - DARK_OAK_SAPLING:4 + - '{p=0.1}JUNGLE_SAPLING:3' + currency: 10 + xp: 10 + sugarplanter: + name: '&9Sugar Planter' + type: onIsland + displayItem: SUGAR_CANE + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + requiredItems: + - SUGAR_CANE:4 + reward: + text: 4 dirt + items: + - DIRT:4 + currency: 20 + xp: 20 + sugarfarmer: + name: '&6Sugar Farmer' + description: Harvest sugarcane from a farm. + type: onPlayer + requiredItems: + - SUGAR_CANE:64;+16 + offset: -1 + displayItem: SUGAR_CANE + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 dirt + items: + - DIRT:8 + - '{p=0.1}BONE:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - DIRT:4 + - '{p=0.05}DIRT:4' + currency: 10 + xp: 10 + melonfarmer: + name: '&6Melon Farmer' + description: Harvest slices of melon from a farm. + type: onPlayer + requiredItems: + - MELON_SLICE:128;+8 + displayItem: MELON + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 dirt + items: + - DIRT:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - DIRT:4 + currency: 10 + xp: 10 + cactusfarmer: + name: '&6Cactus Farmer' + description: Harvest cacti from a farm. + type: onPlayer + requiredItems: + - CACTUS:64;+16 + displayItem: CACTUS + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 sand, 20% chance to get a bone + items: + - SAND:8 + - '{p=0.2}BONE:1' + - '{p=0.1}WOODEN_HOE:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 sand + items: + - SAND:4 + - '{p=0.1}BONE:1' + currency: 10 + xp: 10 + pumpkinfarmer: + name: '&6Pumpkin Farmer' + description: Harvest pumpkins from a farm. + type: onPlayer + requiredItems: + - PUMPKIN:64;+4 + displayItem: PUMPKIN + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 dirt + items: + - DIRT:8 + - '{p=0.3}JACK_O_LANTERN:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - DIRT:4 + - '{p=0.05}JACK_O_LANTERN:1' + currency: 10 + xp: 10 + stonebrickmaker: + name: '&aStone Brick Maker' + description: Make 64 Stone Bricks. + type: onPlayer + requiredItems: + - STONE_BRICKS:64;+8 + - STONE_BRICK_SLAB:30;+6 + - CHISELED_STONE_BRICKS:30;+6 + - STONE_BRICK_STAIRS:16;+4 + displayItem: STONE_BRICKS + lockedDisplayItem: GRAY_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron ore, 1 chicken + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + - CHICKEN_SPAWN_EGG:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - REDSTONE_ORE:1 + - IRON_ORE:1 + currency: 15 + xp: 15 + novicebuilder: + name: '&7Novice Builder' + description: Reach island level 20. + type: islandLevel + requiredLevel: 20 + displayItem: COAL_ORE + reward: + text: 8 dirt, 8 sand, 5 emeralds + items: + - DIRT:8 + - SAND:8 + - EMERALD:5 + - DIAMOND:1 + currency: 20 + xp: 20 + commands: + - op:effect give {party} regeneration + adeptbuilder: + name: '&aAdept Builder' + description: Reach island level 50. + type: islandLevel + requiredLevel: 50 + displayItem: IRON_ORE + offset: -1 + reward: + text: 10 obsidian, 2 diamonds, 5 emeralds + items: + - OBSIDIAN:10 + - EMERALD:5 + - DIAMOND:2 + currency: 100 + xp: 100 + expertbuilder: + name: '&eExpert Builder' + description: Reach island level 100. + type: islandLevel + requiredLevel: 100 + displayItem: GOLD_ORE + offset: -1 + reward: + text: 16 dirt, 16 sand, 3 diamonds, 5 emeralds + items: + - DIRT:16 + - SAND:16 + - EMERALD:5 + - DIAMOND:3 + currency: 250 + xp: 250 + masterbuilder: + name: '&cMaster Builder' + description: Reach island level 250. + type: islandLevel + requiredLevel: 250 + displayItem: DIAMOND_ORE + offset: -1 + reward: + text: 32 dirt, 32 sand, 4 diamonds, 5 emeralds + items: + - DIRT:32 + - SAND:32 + - EMERALD:5 + - DIAMOND:4 + currency: 500 + xp: 500 + skylord: + name: '&4Sky Lord' + description: Reach island level 500. + type: islandLevel + requiredLevel: 500 + displayItem: EMERALD_ORE + offset: -1 + reward: + text: 64 dirt, 64 sand, 5 diamond, 5 emeralds + items: + - DIRT:64 + - SAND:64 + - DIAMOND:5 + - EMERALD:5 + currency: 1000 + xp: 1000 + Tier2: + name: '&aAdept' + displayItem: LIME_TERRACOTTA + resetInHours: 20 + requires: + + # means disabled in effect + rankLeeway: 99 + challenges: + - cobblestonegenerator + - novicebuilder + challenges: + lumberjack: + name: '&3Lumberjack' + description: Collect all types of wood logs. + type: onPlayer + requiredItems: + - OAK_LOG:16;+2 + - SPRUCE_LOG:16;+2 + - BIRCH_LOG:16;+2 + - JUNGLE_LOG:16;+2 + - ACACIA_LOG:16;+2 + - DARK_OAK_LOG:16;+2 + displayItem: OAK_LOG + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron ore, 1 wolf + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + - WOLF_SPAWN_EGG:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - REDSTONE_ORE:1 + - IRON_ORE:1 + currency: 15 + xp: 15 + shroompicker: + name: '&6Shroom Picker' + description: Collect red and brown mushrooms. + type: onPlayer + requiredItems: + - BROWN_MUSHROOM:64;+4 + - RED_MUSHROOM:64;+4 + displayItem: RED_MUSHROOM + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 mycelium, 4 podzol + items: + - MYCELIUM:8 + - PODZOL:4 + currency: 30 + xp: 30 + repeatReward: + text: 4 mycelium + items: + - MYCELIUM:4 + - '{p=0.02}MYCELIUM:4' + - '{p=0.02}PODZOL:2' + currency: 15 + xp: 15 + potatofarmer: + name: '&6Potato Farmer' + description: Harvest potato's from a farm. + type: onPlayer + requiredItems: + - POTATO:64;+16 + displayItem: POTATO + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 1 carrot, 4 dirt + items: + - CARROT:1 + - DIRT:4 + - '{p=0.10}BEETROOT_SEEDS:1' + - '{p=0.05}RED_SAND:1' + - '{p=0.01}DIAMOND:1' + currency: 50 + xp: 50 + repeatReward: + text: 4 dirt and a baked potato + items: + - DIRT:4 + - BAKED_POTATO:1 + - '{p=0.10}BEETROOT_SEEDS:1' + - '{p=0.05}RED_SAND:1' + - '{p=0.01}DIAMOND:1' + currency: 25 + xp: 25 + carrotfarmer: + name: '&6Carrot Farmer' + description: Harvest carrot's from a farm. + type: onPlayer + requiredItems: + - CARROT:64;+16 + displayItem: CARROT + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: a pig with saddle and a potato + items: + - SADDLE:1 + - POTATO:1 + - PIG_SPAWN_EGG:1 + - '{p=0.05}RED_SAND:1' + - '{p=0.01}DIAMOND:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 golden carrot + items: + - GOLDEN_CARROT:1 + - '{p=0.05}SAND:1' + - '{p=0.01}DIAMOND:1' + currency: 25 + xp: 25 + wheatfarmer: + name: '&6Wheat Farmer' + description: Harvest wheat from a farm. + type: onPlayer + requiredItems: + - WHEAT:64;+16 + displayItem: WHEAT + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 8 dirt + items: + - DIRT:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - DIRT:4 + - '{p=0.2}BONE:1' + currency: 10 + xp: 10 + monsterfarm: + name: '&5Monster Farm' + description: Build a mob farm and collect mob loot. + type: onPlayer + requiredItems: + - ROTTEN_FLESH:64;+4 + - STRING:32;+2 + - ARROW:32;+2 + - BONE:32;+2 + - GUNPOWDER:16;+1 + - SPIDER_EYE:5 + displayItem: ROTTEN_FLESH + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron ore and 1 flint + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + - FLINT:1 + - '{p=0.10}POTATO:1' + - '{p=0.10}CARROT:1' + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore, 1 flint + items: + - REDSTONE_ORE:1 + - IRON_ORE:4 + - FLINT:1 + - '{p=0.05}POTATO:1' + - '{p=0.05}CARROT:1' + currency: 15 + xp: 15 + homeowner: + name: '&9Home Owner' + description: Build a house with furnishings. + type: onIsland + requiredChallenges: + - stonebrickmaker + requiredItems: + - RED_BED:1 + - CRAFTING_TABLE:1 + - GLASS:1 + - OAK_DOOR:1 + - FURNACE:1 + - BOOKSHELF:1 + - TORCH:1 + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + displayItem: OAK_DOOR + reward: + text: 4 redstone ore, 5 inksac, 4 iron ore and some seeds + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + - INK_SAC:5 + - BEETROOT_SEEDS:1 + currency: 40 + xp: 40 + netherportal: + name: '&9Nether Portal' + description: Build a nether portal on your island. + type: onIsland + requiredChallenges: + - adeptbuilder + - homeowner + requiredItems: + - OBSIDIAN:10 + - NETHER_PORTAL:1 + displayItem: OBSIDIAN + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + reward: + text: 1 iron pickaxe, 1 iron shovel + items: + - IRON_SHOVEL:1 + - IRON_PICKAXE:1 + currency: 40 + xp: 40 + nethermining: + name: '&7Nether Mining' + description: Mine from your Nether island. + type: onPlayer + displayItem: NETHERRACK + lockedDisplayItem: GRAY_STAINED_GLASS_PANE + offset: -1 + requiredItems: + - NETHERRACK:64;+2 + - SOUL_SAND:16;+2 + - GRAVEL:16;+2 + - QUARTZ:32;+2 + - GLOWSTONE:16;+2 + - COARSE_DIRT:4;+2 + reward: + text: 1 ghast tear, 1 magic bow + items: + - GHAST_TEAR:1 + - 'BOW:1 {Enchantments:[{id:"minecraft:infinity",lvl:1},{id:"minecraft:unbreaking",lvl:3}]}' + currency: 40 + xp: 40 + repeatReward: + text: a blaze-rod and a chance of ghast tear + items: + - BLAZE_ROD:1 + - '{p=0.10}GHAST_TEAR:1' + currency: 20 + xp: 20 + Tier3: + name: '&eExpert' + displayItem: YELLOW_TERRACOTTA + resetInHours: 20 + requires: + challenges: + - adeptbuilder + challenges: + toolmaker: + name: '&3Tool Maker' + description: Make all stone tools + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - STONE_SHOVEL:1 + - STONE_PICKAXE:1 + - STONE_AXE:1 + - STONE_HOE:1 + displayItem: STONE_AXE + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron, 1 pig + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + - PIG_SPAWN_EGG:1 + currency: 30 + xp: 30 + sawmill: + name: '&3Saw Mill' + description: Deliver a collection of processed wood + type: onPlayer + offset: -1 + requiredChallenges: + - toolmaker + requiredItems: + - STRIPPED_OAK_LOG:8;+2 + - STRIPPED_SPRUCE_LOG:8;+2 + - STRIPPED_BIRCH_LOG:8;+2 + - STRIPPED_JUNGLE_LOG:8;+2 + - STRIPPED_ACACIA_LOG:8;+2 + - STRIPPED_DARK_OAK_LOG:8;+2 + displayItem: IRON_AXE + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron, cocoa and a mule + items: + - COCOA_BEANS:1 + - REDSTONE_ORE:4 + - IRON_ORE:4 + - MULE_SPAWN_EGG:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - REDSTONE_ORE:1 + - IRON_ORE:1 + - '{p=0.05}GOLD_ORE:1' + currency: 15 + xp: 15 + torchmaker: + name: '&3Torch Maker' + description: Make 128 torches. + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - TORCH:128;+32 + displayItem: TORCH + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, 4 iron ore + items: + - REDSTONE_ORE:4 + - IRON_ORE:4 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - REDSTONE_ORE:1 + - IRON_ORE:1 + currency: 15 + xp: 15 + expertfarmer: + name: '&6Expert Farmer' + description: Harvest many different farming resources. + type: onPlayer + displayItem: IRON_HOE + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + requiredChallenges: + - applecollector + - melonfarmer + - pumpkinfarmer + - wheatfarmer + - carrotfarmer + - potatofarmer + - cactusfarmer + - sugarfarmer + - shroompicker + requiredItems: + - MELON_SLICE:256;+2 + - SUGAR_CANE:128;+2 + - WHEAT:128;+2 + - POTATO:128;+2 + - CARROT:128;+2 + - PUMPKIN:128;+2 + - CACTUS:128;+2 + - BEETROOT:128;+2 + reward: + text: a bucket, cocoa and a cow + items: + - BUCKET:1 + - COCOA_BEANS:1 + - COW_SPAWN_EGG:1 + currency: 50 + xp: 50 + repeatReward: + text: a cow + items: + - COW_SPAWN_EGG:1 + currency: 25 + xp: 25 + fisherman: + name: '&5Fisherman' + description: Catch different types of fish. + type: onPlayer + requiredItems: + - COD:5;+1 + - SALMON:5;+1 + - PUFFERFISH:3;+1 + - TROPICAL_FISH:1;+0 + - INK_SAC:5;+2 + displayItem: COD + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: 10 lapis blocks, 20 prismarine, kelp, deep-ocean + items: + - LAPIS_BLOCK:10 + - PRISMARINE:20 + - KELP:1 + - '{p=0.20}PRISMARINE_CRYSTALS:5' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: 2 lapis, 5 prismarine, kelp and a chance at prismarine crystals + items: + - LAPIS_LAZULI:2 + - PRISMARINE:5 + - KELP:1 + - '{p=0.20}PRISMARINE_CRYSTALS:5' + currency: 25 + xp: 25 + woolcollector: + name: '&5Wool Collector' + description: Collect every color of wool. + type: onPlayer + displayItem: WHITE_WOOL + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + requiredChallenges: + - monsterfarmer + requiredItems: + - WHITE_WOOL:2;+4 + - ORANGE_WOOL:2;+4 + - MAGENTA_WOOL:2;+4 + - LIGHT_BLUE_WOOL:2;+4 + - YELLOW_WOOL:2;+4 + - LIME_WOOL:2;+4 + - PINK_WOOL:2;+4 + - GRAY_WOOL:2;+4 + - LIGHT_GRAY_WOOL:2;+4 + - CYAN_WOOL:2;+4 + - PURPLE_WOOL:2;+4 + - BLUE_WOOL:2;+4 + - BROWN_WOOL:2;+4 + - GREEN_WOOL:2;+4 + - RED_WOOL:2;+4 + - BLACK_WOOL:2;+4 + reward: + text: 2 diamonds, sheep, emerald, flowers + items: + - DIAMOND:2 + - EMERALD:1 + - SHEEP_SPAWN_EGG:1 + - ROSE_BUSH:1 + - PEONY:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: emerald, sheep, flowers + items: + - EMERALD:1 + - SHEEP_SPAWN_EGG:1 + - ROSE_BUSH:1 + - PEONY:1 + currency: 35 + xp: 35 + maestro: + name: '&5Maestro' + description: Make a jukebox and collect all music discs. + type: onPlayer + requiredItems: + - MUSIC_DISC_13:1 + - MUSIC_DISC_CAT:1 + - MUSIC_DISC_BLOCKS:1 + - MUSIC_DISC_CHIRP:1 + - MUSIC_DISC_FAR:1 + - MUSIC_DISC_MALL:1 + - MUSIC_DISC_MELLOHI:1 + - MUSIC_DISC_STAL:1 + - MUSIC_DISC_STRAD:1 + - MUSIC_DISC_WARD:1 + - MUSIC_DISC_11:1 + - MUSIC_DISC_WAIT:1 + - JUKEBOX:1 + displayItem: JUKEBOX + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: 3 diamonds, 1 gold block, 10 emeralds + items: + - DIAMOND:3 + - EMERALD:10 + - GOLD_BLOCK:1 + currency: 70 + xp: 70 + repeatReward: + text: 2 gold ore, 1 diamond + items: + - GOLD_ORE:2 + - DIAMOND:1 + - '{p=0.2}DIAMOND:1' + currency: 35 + xp: 35 + ironfarm: + name: '&9Iron Farm' + description: Build an iron-farm. + type: onIsland + displayItem: IRON_BLOCK + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + radius: 50 + requiredChallenges: + - monsterfarm + - applecollector + requiredItems: + - OAK_DOOR:30 + requiredEntities: + - Villager:10 + - IRON_GOLEM:1 + reward: + text: 2 gold blocks, 1 diamond block + items: + - GOLD_BLOCK:2 + - DIAMOND_BLOCK:1 + currency: 500 + xp: 400 + netherfortress: + name: '&9Nether Fortress' + description: Build a netherfortress. + type: onIsland + radius: 50 + requiredItems: + - NETHER_BRICKS:512 + - NETHER_BRICK_SLAB:64 + - NETHER_BRICK_FENCE:64 + - NETHER_BRICK_STAIRS:64 + - SOUL_SAND:32 + displayItem: NETHER_BRICK_FENCE + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + reward: + text: a wither-skull and a blaze rod and a chance of diamonds + items: + - WITHER_SKELETON_SKULL:1 + - BLAZE_ROD:1 + - '{p=0.05}DIAMOND:3' + - '{p=0.10}DIAMOND:2' + - '{p=0.15}DIAMOND:1' + currency: 40 + xp: 40 + #=============================================== + Tier4: + name: '&cMaster' + displayItem: ORANGE_TERRACOTTA + resetInHours: 20 + requires: + + # disabled + rankLeeway: 99 + challenges: + - expertbuilder + challenges: + glassmaker: + name: '&3Glassmaker' + description: Collect every color of stained glass. + type: onPlayer + displayItem: WHITE_STAINED_GLASS + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + requiredItems: + - WHITE_STAINED_GLASS:8;+2 + - ORANGE_STAINED_GLASS:8;+2 + - MAGENTA_STAINED_GLASS:8;+2 + - LIGHT_BLUE_STAINED_GLASS:8;+2 + - YELLOW_STAINED_GLASS:8;+2 + - LIME_STAINED_GLASS:8;+2 + - PINK_STAINED_GLASS:8;+2 + - GRAY_STAINED_GLASS:8;+2 + - LIGHT_GRAY_STAINED_GLASS:8;+2 + - CYAN_STAINED_GLASS:8;+2 + - PURPLE_STAINED_GLASS:8;+2 + - BLUE_STAINED_GLASS:8;+2 + - BROWN_STAINED_GLASS:8;+2 + - GREEN_STAINED_GLASS:8;+2 + - RED_STAINED_GLASS:8;+2 + - BLACK_STAINED_GLASS:8;+2 + reward: + text: 2 diamonds, 2 disks, 1 emeralds + items: + - DIAMOND:2 + - MUSIC_DISC_WARD:1 + - MUSIC_DISC_11:1 + - EMERALD:1 + - SUNFLOWER:1 + - LILAC:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: 30% chance on 1 or 2 disks, 1 emeralds + items: + - '{p=0.3}MUSIC_DISC_WARD:1' + - '{p=0.3}MUSIC_DISC_11:1' + - EMERALD:1 + - SUNFLOWER:1 + - LILAC:1 + currency: 35 + xp: 35 + carpenter: + name: '&3Carpenter' + description: Collect all types of wood items. + type: onPlayer + requiredItems: + - JUNGLE_STAIRS:16;+8 + - SPRUCE_DOOR:1;+1 + - DARK_OAK_FENCE_GATE:2;+2 + - ACACIA_FENCE:30;+15 + - LADDER:30;+15 + - OAK_TRAPDOOR:4;+2 + - OAK_PRESSURE_PLATE:2;+1 + requiredChallenges: + - toolmaker + - lumberjack:2 + displayItem: CRAFTING_TABLE + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: a parrot and a jukebox with some redstone and iron + items: + - PARROT_SPAWN_EGG:1 + - JUKEBOX:1 + - REDSTONE_ORE:4 + - IRON_ORE:4 + currency: 30 + xp: 30 + repeatReward: + text: redstone, iron and a slim chance at a parrot + items: + - REDSTONE_ORE:1 + - IRON_ORE:1 + - '{p=0.25}JUKEBOX:1' + - '{p=0.05}PARROT_SPAWN_EGG:1' + currency: 15 + xp: 15 + cookielover: + name: '&eCookie Lover' + description: Make cookies and a bucket of milk. + type: onPlayer + requiredChallenges: + - expertfarmer + requiredItems: + - COOKIE:128;+4 + - MILK_BUCKET:1 + displayItem: COOKIE + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 4 redstone ore, clay a bucket and a diamond + items: + - REDSTONE_ORE:4 + - CLAY:5 + - DIAMOND:1 + - BUCKET:1 + currency: 80 + xp: 80 + repeatReward: + text: iron ore and some clay + items: + - IRON_ORE:1 + - CLAY:5 + - BUCKET:1 + - '{p=0.4}CLAY:3' + - '{p=0.3}IRON_ORE:2' + currency: 40 + xp: 40 + deepseafisherman: + name: '&5Deep Sea Fishing' + description: Farm the deep sea + type: onPlayer + requiredItems: + - COD:10;+5 + - SALMON:10;+5 + - PUFFERFISH:5;+3 + - TROPICAL_FISH:3;+2 + - PRISMARINE_CRYSTALS:16;+8 + - PRISMARINE_SHARD:16;+8 + - DRIED_KELP_BLOCK:64;+32 + - NAUTILUS_SHELL:1 + displayItem: HEART_OF_THE_SEA + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: heart-of-the-sea, nautilus shell and a turtle + items: + - NAUTILUS_SHELL:1 + - HEART_OF_THE_SEA:1 + - TURTLE_SPAWN_EGG:1 + - '{p=0.1}NAUTILUS_SHELL:1' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: nautilus shell, turtle and a chance of a heart + items: + - NAUTILUS_SHELL:1 + - TURTLE_SPAWN_EGG:1 + - '{p=0.05}HEART_OF_THE_SEA:1' + - '{p=0.1}NAUTILUS_SHELL:1' + currency: 25 + xp: 25 + horsingaround: + name: '&6Horsing Around' + description: Get hay bales for the horses. + type: onPlayer + requiredItems: + - HAY_BLOCK:32;+4 + - LEAD:8;+2 + - CARROT_ON_A_STICK:1 + - SHEARS:1 + requirecChallenges: + - wheatfarmer + displayItem: HAY_BLOCK + lockedDisplayItem: BROWN_STAINED_GLASS_PANE + reward: + text: 1 horse, 1 iron horse armor, 5% chance on diamond horse armor + items: + - IRON_HORSE_ARMOR:1 + - HORSE_SPAWN_EGG:1 + - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald + items: + - REDSTONE:1 + - EMERALD:1 + currency: 25 + xp: 25 + slimefarmer: + name: '&5Slime Farmer' + description: Collect slimeballs from slimes. + type: onPlayer + requiredItems: + - SLIME_BALL:64;+4 + displayItem: SLIME_BALL + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: 1 diamond, 1 emeralds, swampland + items: + - DIAMOND:1 + - EMERALD:1 + permission: usb.biome.swamp + currency: 70 + xp: 70 + repeatReward: + text: 1 redstone ore, 1 emeralds + items: + - REDSTONE_ORE:1 + - EMERALD:1 + currency: 35 + xp: 35 + animalfarm: + name: '&9Animal Farm' + description: Create an animal farm. + type: onIsland + displayItem: OAK_FENCE + radius: 40 + requiredChallenges: + - woolcollector + - potatofarmer + - carrotfarmer + requiredEntities: + - Cow:8 + - Pig:8 + - Chicken:16 + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} + reward: + text: 1 horse, 1 iron horse armor, 5% chance horse armor + items: + - IRON_HORSE_ARMOR:1 + - HORSE_SPAWN_EGG:1 + - '{p=0.05}IRON_HORSE_ARMOR:1' + - '{p=0.05}GOLDEN_HORSE_ARMOR:1' + - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald, 5% chance horse armor + items: + - REDSTONE:1 + - EMERALD:1 + - '{p=0.05}IRON_HORSE_ARMOR:1' + - '{p=0.05}GOLDEN_HORSE_ARMOR:1' + - '{p=0.05}DIAMOND_HORSE_ARMOR:1' + currency: 25 + xp: 25 + witherhunter: + name: '&5Wither Hunter' + description: Collect some Wither Skeleton skulls. + type: onPlayer + requiredChallenges: + - netherfortress + requiredItems: + - WITHER_SKELETON_SKULL:10;+1 + displayItem: WITHER_SKELETON_SKULL + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + offset: -1 + reward: + text: 5 diamonds, 5% chance of nether star + items: + - DIAMOND:5 + - '{p=0.05}NETHER_STAR:1' + currency: 400 + xp: 400 + repeatReward: + text: 2 gold ore, 5% chance of nether star + items: + - GOLD_ORE:2 + - '{p=0.05}NETHER_STAR:1' + currency: 20 + xp: 20 + pearlcollector: + name: '&5Pearl Collector' + description: Collect enderpearls from endermen. + type: onPlayer + requiredItems: + - ENDER_PEARL:10;+4 + displayItem: ENDER_PEARL + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: 5 gold ore, 1 blaze rod, 1 emerald + items: + - GOLD_ORE:5 + - BLAZE_ROD:1 + - EMERALD:1 + currency: 70 + xp: 70 + repeatReward: + text: 1 gold ore, 1 blaze rod + items: + - GOLD_ORE:1 + - BLAZE_ROD:1 + currency: 35 + xp: 35 + + #=============================================== + Tier5: + name: '&4Sky Lord' + displayItem: RED_TERRACOTTA + resetInHours: 48 + requires: + challenges: + - masterbuilder + challenges: + technician: + name: '&3Technician' + description: Collect some of every type of redstone equipment. + type: onPlayer + requiredItems: + - REDSTONE:64;+16 + - REDSTONE_TORCH:32;+4 + - REPEATER:5;+1 + - COMPARATOR:3;+1 + - PISTON:2;+1 + - STICKY_PISTON:2;+1 + - LEVER:1;+1 + - STONE_BUTTON:1;+1 + - STONE_PRESSURE_PLATE:1;+1 + - HOPPER:1;+1 + - DISPENSER:1;+1 + - DROPPER:1;+1 + - DAYLIGHT_DETECTOR:1;+1 + displayItem: REDSTONE + lockedDisplayItem: CYAN_STAINED_GLASS_PANE + reward: + text: some snow, ice and packed ice + items: + - SNOW_BLOCK:4 + - ICE:8 + - PACKED_ICE:8 + - REDSTONE_BLOCK:64 + currency: 70 + xp: 70 + repeatReward: + text: a stack of redstone blocks and some ice + items: + - REDSTONE_BLOCK:64 + - ICE:4 + - PACKED_ICE:1 + currency: 35 + xp: 35 + emeraldcollector: + name: '&5Emerald Collector' + description: Collect emeralds. + type: onPlayer + requiredItems: + - EMERALD:60;+10 + displayItem: EMERALD + lockedDisplayItem: PURPLE_STAINED_GLASS_PANE + reward: + text: a full set of diamond armor + items: + - DIAMOND_HELMET:1 + - DIAMOND_CHESTPLATE:1 + - DIAMOND_LEGGINGS:1 + - DIAMOND_BOOTS:1 + currency: 70 + xp: 70 + repeatReward: + text: full diamond armor + items: + - DIAMOND_HELMET:1 + - DIAMOND_CHESTPLATE:1 + - DIAMOND_LEGGINGS:1 + - DIAMOND_BOOTS:1 + currency: 35 + xp: 35 + topchef: + name: '&eTop Chef' + description: Collect every kind of edible food. + type: onPlayer + requiredItems: + - BAKED_POTATO:1 + - BREAD:1 + - CAKE:1 + - COOKED_CHICKEN:1 + - COOKED_COD:1 + - COOKED_SALMON:1 + - TROPICAL_FISH:1 + - COOKED_PORKCHOP:1 + - COOKIE:1 + - GOLDEN_APPLE:1 + - GOLDEN_CARROT:1 + - MUSHROOM_STEW:1 + - PUMPKIN_PIE:1 + - COOKED_BEEF:1 + - MELON:1 + - CARROT:1 + requiredChallenges: + - expertfarmer + - fisherman + - cookielover + displayItem: CARROT + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 2 diamond, 1 mooshroom + items: + - DIAMOND:2 + - MOOSHROOM_SPAWN_EGG:1 + currency: 80 + xp: 80 + repeatReward: + text: 1 diamond, 1 mooshroom + items: + - DIAMOND:1 + - MOOSHROOM_SPAWN_EGG:1 + currency: 40 + xp: 40 + tajmahal: + name: '&9Taj Mahal' + description: Build a temple of quartz + type: onIsland + radius: 30 + displayItem: QUARTZ_BLOCK + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + requiredChallenges: + - nethermining + requiredItems: + - QUARTZ_BLOCK:512 + - CHISELED_QUARTZ_BLOCK:64 + - QUARTZ_PILLAR:128 + - QUARTZ_STAIRS:64 + - QUARTZ_SLAB:192 + reward: + text: 3 end-portal frames, red sand + items: + - END_PORTAL_FRAME:3 + - RED_SAND:64 + currency: 1000 + xp: 500 + greatpyramid: + name: '&9Great Pyramid' + description: Build a pyramid of sandstone + type: onIsland + radius: 30 + displayItem: SANDSTONE + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + requiredItems: + - SANDSTONE:512 + - CHISELED_SANDSTONE:64 + - SMOOTH_SANDSTONE:128 + - SANDSTONE_STAIRS:64 + - SANDSTONE_SLAB:192 + - RED_SANDSTONE:16 + reward: + text: 3 end-portal frames, 3 diamonds, bow + items: + - END_PORTAL_FRAME:3 + - DIAMOND:3 + - BOW:1 {Enchantments:[{id:"minecraft:infinity",lvl:1},{id:"minecraft:unbreaking",lvl:3},{id:"minecraft:power",lvl:5}]} + currency: 1000 + xp: 500 + poseidonshalls: + name: '&9Poseidon''s Halls' + description: Build the halls of Poseidon + type: onIsland + radius: 50 + displayItem: PRISMARINE + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + requiredChallenges: + - deepseafisherman + requiredItems: + - PRISMARINE:512 + - PRISMARINE_BRICKS:128 + - DARK_PRISMARINE:64 + - SEA_LANTERN:32 + - CONDUIT:1 + - FLOWER_POT:16 + - VINE:128 + - POPPY:10 + - BLUE_ORCHID:10 + - ALLIUM:10 + - AZURE_BLUET:10 + - RED_TULIP:10 + - ORANGE_TULIP:10 + - WHITE_TULIP:10 + - PINK_TULIP:10 + - OXEYE_DAISY:10 + - SUNFLOWER:10 + - LILAC:10 + - ROSE_BUSH:10 + - PEONY:10 + reward: + text: 3 end-portal frames, 5 diamonds + items: + - END_PORTAL_FRAME:3 + - DIAMOND:5 + currency: 1000 + xp: 500 + beaconator: + name: '&9Beaconator' + description: Build a very expensive beacon. + type: onIsland + radius: 15 + displayItem: BEACON + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + requiredChallenges: + - netherfortress + - ironfarm + - maestro + - witherhunter + requiredItems: + - BEACON:1 + - DIAMOND_BLOCK:1 + - EMERALD_BLOCK:8 + - GOLD_BLOCK:25 + - IRON_BLOCK:49 + reward: + items: + - END_PORTAL_FRAME:3 + - DIAMOND_SWORD:1 {Enchantments:[{id:"minecraft:sharpness",lvl:5},{id:"minecraft:unbreaking",lvl:3},{id:"minecraft:fire",lvl:1}]} + text: some end-portal-pieces and a magic diamond sword + currency: 4000 + xp: 1000 + endportal: + name: '&9End Portal' + description: Build and activate an end-portal. + type: onIsland + radius: 15 + displayItem: END_PORTAL_FRAME + lockedDisplayItem: BLUE_STAINED_GLASS_PANE + requiredChallenges: + - beaconator + - tajmahal + - poseidonshalls + - greatpyramid + requiredItems: + - END_PORTAL_FRAME:12 + - END_PORTAL:9 + reward: + text: 5 diamonds and some nice boots + items: + - DIAMOND:5 + - DIAMOND_BOOTS:1 {Enchantments:[{id:"minecraft:feather_falling",lvl:4},{id:"minecraft:protection",lvl:4},{id:"minecraft:blast_protection",lvl:4}]} + currency: 4000 + xp: 1000 + + #=============================================== + Tier6: + name: '&aWorld Foods' + displayItem: LIGHT_GRAY_TERRACOTTA + resetInHours: 20 + requires: + challenges: + - masterbuilder + - topchef + challenges: + fishandchips: + name: '&eFish & Chips' + description: Create the famous English Fish & Chips. + type: onPlayer + requiredItems: + - COOKED_COD:32;+8 + - BAKED_POTATO:32;+8 + displayItem: COOKED_COD + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 16 baked potatos, 1 disk, 4 emerald + items: + - BAKED_POTATO:16 + - MUSIC_DISC_13:1 + - EMERALD:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_13:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + smorrebrod: + name: '&eSmørrebrød' + description: Create the famous Danish smørrebrød. + type: onPlayer + requiredItems: + - BREAD:16;+4 + - COOKED_SALMON:8;+4 + - TROPICAL_FISH:2;+1 + - COOKED_PORKCHOP:8;+4 + - COOKED_BEEF:8;+4 + displayItem: COOKED_COD + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 1 rod, 2 name tags, 2 ocelots + items: + - FISHING_ROD:1 + - NAME_TAG:2 + - OCELOT_SPAWN_EGG:2 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + repeatReward: + text: 1 emerald + items: + - EMERALD:1 + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + hutspot: + name: '&eHutspot' + description: Create the famous Dutch hutspot. + type: onPlayer + requiredItems: + - POTATO:64;+8 + - CARROT:64;+8 + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + displayItem: GOLDEN_CARROT + reward: + text: 1 golden carrot, 1 disk, 4 emerald + items: + - GOLDEN_CARROT:1 + - MUSIC_DISC_CAT:1 + - EMERALD:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_CAT:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + apfelstrudel: + name: '&eApfelstrudele' + description: Create the famous German apfelstrudel. + type: onPlayer + requiredItems: + - APPLE:8;+5 + - WHEAT:16;+5 + - SUGAR:16;+5 + - MILK_BUCKET:1 + displayItem: GOLDEN_APPLE + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - BUCKET:1 + - EMERALD:4 + - MUSIC_DISC_BLOCKS:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - BUCKET:1 + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_BLOCKS:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + brownies: + name: '&eBrownies' + description: Create the famous American brownies. + type: onPlayer + requiredItems: + - WHEAT:16;+5 + - SUGAR:16;+5 + - EGG:16;+5 + - INK_SAC:16;+5 + - MILK_BUCKET:1 + displayItem: DARK_OAK_SLAB + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - BUCKET:1 + - EMERALD:4 + - MUSIC_DISC_FAR:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - BUCKET:1 + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_FAR:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + pastafunghi: + name: '&ePasta Funghi' + description: Create the famous Italian Pasta Funghi. + type: onPlayer + requiredItems: + - WHEAT:32;+8 + - EGG:32;+8 + - BROWN_MUSHROOM:16;+4 + - RED_MUSHROOM:16;+4 + - MILK_BUCKET:1 + displayItem: RED_MUSHROOM_BLOCK + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 2 rabbits, 1 bucket + items: + - BUCKET:1 + - RABBIT_SPAWN_EGG:2 + currency: 60 + xp: 60 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_13:1' + currency: 30 + xp: 30 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + chocolate: + name: '&eBelgian chocolate' + description: Create the famous belgian chocolate. + type: onPlayer + requiredItems: + - SUGAR:16;+5 + - INK_SAC:16;+5 + - MILK_BUCKET:1 + displayItem: PIG_SPAWN_EGG + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 1 bucket, 1 disk, 4 emeralds + items: + - BUCKET:1 + - EMERALD:4 + - MUSIC_DISC_MALL:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - BUCKET:1 + - EMERALD:1 + - '{p=0.3}MUSIC_DISC_MALL:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + baker: + name: '&ePâtisserie' + description: Bake cakes, pumpkin pies, and cookies. + type: onPlayer + requiredItems: + - CAKE:5;+1 + - PUMPKIN_PIE:5;+1 + - COOKIE:128;+4 + displayItem: CAKE + lockedDisplayItem: YELLOW_STAINED_GLASS_PANE + reward: + text: 5 gold ore, 1 diamond + items: + - GOLD_ORE:5 + - DIAMOND:1 + currency: 80 + xp: 80 + repeatReward: + text: 2 iron ore, 1 gold ore + items: + - IRON_ORE:2 + - GOLD_ORE:1 + currency: 40 + xp: 40 + +#=============================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the most used settings +# while the double commented (##) are optionnal if you like to use those settings. +# +#ranks: +# # [text] name of the challenge Rank. +# TierX: +# #[text] The name of the challenge rank that shows up when you do /challenges (this supports capitals and colorcodes). +# name: '&aCuston Challenges rank name' +# # [itemid] The itemid of the item to be displayed in the challenge menu for complete challenges. +# displayItem: 3 +# # [integer] The time in hours before required items reset to default (tis overwrites the Main reset time) +# resetInHours: 20 +# # The requierments will allow when a challenge groups will be available to see and complete for players. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 challenges +# # with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. +# # A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [text] Challenges that has to be completed before this group will show in the Challenges GUI +# challenges: +# - a challenge name +#=============================================== +# challenges: +# #[text] The name of the challenge. All challenge names should be lower case. +# defaultchallengename: +# #[text] The name of the challenge that shows up when you do /challenges (this supports capitals and colorcodes). +# name: '&a' +# # [text] What the player sees when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This tells whether the required blocks/items should be in the player's inventory or on their island +# # When using onIsland, the player must be 10 blocks away from the required blocks on his island. +# # When using onIsland, the default radius distance is set to 10, all items requierd must be within this distance. +# # When using islandLevel, the 'requiredItems' field should be the island level required. The player must use /island level first to update his level. +# type: onPlayer +## type: islandLevel +## type: onIsland +# # To override the default radius when using onIsland, uncommend the "radius: " and fill in your own value. +## radius: +# # [itemid list] The itemid:count of the items required for the challenge. +# requiredItems: '' +# # [true/false] If the challenge can repeated or not. +# # [itemid] The itemid of the item to be displayed in the challenge menu for complete challenges. +# displayItem: +## tool: +# # [integer] The time in hours before required items reset to default (this overwrites the Main and Ranks reset times). +## resetInHours: +# # [true/false] Take required items on completing a challenge. +# # # reward section to reward the player for completing the challenge. +# reward: +# # [text] Description of the reward. If omitted §4Unknown will be shown. +# text: +# # [itemid list] The itemid::count of the reward to give the player for completing the challenge. +# items: +## # [permission node] A permission granted for completion. Multiple permissions are space-separated, i.e. - "test.1 test.2" (use none to not give a permission) +# # # [integer] How much currency to give for the first time completion. (requires an economy plugin) +# currency: 0 +# # [integer] How much xp to give to the player for the first time completion. +# xp: 0 +# # Executes the given command upon completion. Prepend with "op" or "console" to run the commands as OP or from the Console. Examples: +# # commands: +# # - 'op: me are the GOD of things' +# # - 'console: give {party} aweseomestuff 32' +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +## commands: +## - op: +## - console: +# # reward section to reward the player for completing a repeated challenge. +# repeatReward: +# # [text] Description of the reward. If omitted §4Unknown will be shown. +# text: +# # [itemid list] The itemid::count of the reward to give the player for completing the challenge. +# items: +## # [integer] How much currency to give for the first time completion. (requires an economy plugin) +# currency: 0 +# # [integer] How much xp to give to the player for the first time completion. +# xp: 0 +# # Executes the given command upon completion. Prepend with "op" or "console" to run the commands as OP or from the Console. Examples: +# # commands: +# # - 'op: me are the GOD of things' +# # - 'console: give {party} aweseomestuff 32' +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +## commands: +## - op: +## - console: +# +# All commented settings (#) in the above challenges (not the explanation) can be removed to clean up the test-challenges.yml. +# +# DO NOT CHANGE! +version: 106 diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml new file mode 100644 index 000000000..af7696f81 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml @@ -0,0 +1,181 @@ +# ====================================================================================================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the +# most used settings while the double commented (##) are optional if you like to use those settings. +# +# Item type format +# Item types are defined as in the minecraft /give command, i.e. with their minecraft key and possible components in +# square brackets. For example, 'minecraft:diamond_sword[damage=42]'. Refer to the Minecraft wiki for more information: +# https://minecraft.wiki/w/Data_component_format. You can also use the command '/usb iteminfo' to get the information. +# +# This item type is supplemented with additional information depending on where it is used: +# +# display-item: +# An item to be displayed in a GUI. It only defines the item type as above, without any additional information. +# For example: 'cobblestone', 'minecraft:stone', 'diamond_sword[damage=42]'. +# +# item-requirement: :[;+] +# An item requirement for a challenge. The amount is the number of items required. The optional + is the number +# of items to add to the required amount for each repeat of the challenge. For example, 'cobblestone:64;+16' would +# require 64 cobblestone for the first completion and 80 cobblestone for the second completion. Other options are +# -, *, and / for subtraction, multiplication, and division, respectively. For example, 'cobblestone:64;*2' would +# require 64 cobblestone for the first completion, 128 cobblestone for the second completion, and 256 cobblestone for +# the third completion. +# +# item-reward: [{p=}]: +# An item reward for a challenge. The amount is the number of items to give. The optional {p=} is the +# probability of the item being given. For example, 'cobblestone:64' would give 64 cobblestone every time the challenge +# is completed, while '{p=0.1}cobblestone:64' would give 64 cobblestone 10% of the time. +# +# ====================================================================================================================== +# All challenges are defined in the ranks section. Each rank is a tier of challenges that players can complete. +# +# ranks: +# # [text] name of the challenge Rank. +# TierX: +# # [text] The name of the challenge rank that shows when you do /challenges (supports capitals and color codes). +# name: '&aCustom Challenges rank name' +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: 'cyan_terracotta' +# # [integer] The time in hours before required items reset to default (this overwrites the main reset time) +# resetInHours: 20 +# # These requirements controls when a challenge group will be available to a player. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, +# if you have 4 challenges with a rankLeeway of 1, a player would only need to complete 3 to advance to +# the next rank. A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [List[text]] Challenges that have to be completed before this group will available to a player. +# challenges: +# - a challenge name +# ====================================================================================================================== +# challenges: +# # [text] The name of the challenge. All challenge names should be lower-case. +# defaultchallenge: +# # [text] The name of the challenge that shows in /challenges (this supports capitals and color codes). +# name: '&a Default Challenge' +# # [text] The descriptions players see when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This defines whether the required blocks/items should be in the player's +# # inventory or on their island. When using onIsland, the player must within 10 blocks from the required blocks +# # on his island. When using islandLevel, the 'requiredItems' field should be the island level required. The +# # player must use /island level first to update their level. +# type: onPlayer +# ## type: islandLevel +# ## type: onIsland +# # [integer] Overrides the default radius of 10 blocks when using onIsland. +# ## radius: 20 +# # [List[item-requirement] The items required to complete the challenge. +# requiredItems: +# - stone:64;+16 +# - cobblestone:64;+16 +# # [true/false] If the challenge can be repeated or not. +# ## repeatable: true +# # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. +# # A value of 0 means unlimited repeats. +# ## repeatLimit: 5 +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: cobblestone +# # [integer] The time in hours before required items reset to default (overwrites the main and rank defaults). +# ## resetInHours: 4 +# # [true/false] Take required items on completing a challenge. +# ## takeItems: true +# # The rewards players get for completing the challenge +# reward: +# # [text] Description of the reward. +# text: 'Mossy cobblestone and an iron pickaxe with unbreaking 1' +# # [List[item-requirement]] A list of items given to the player for completing the challenge. +# items: +# - mossy_cobblestone:16 +# - iron_pickaxe[enchantments={levels:{unbreaking:1}}]:1 +# # [permission node] A permission granted for completion. Multiple permissions are space-separated. +# ## permission: 'test.permission' +# # [integer] How much currency to give for completion. (requires an economy plugin) +# ## currency: 0 +# # [integer] How much xp to give to the player for completion. +# ## xp: 0 +# # [List[Text]] Executes the given command upon completion. Prepend with "op" or "console" to run the commands +# as OP or from the Console. Examples: +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +# ## commands: +# ## - 'op: me are the GOD of things' +# ## - 'console: give {party} aweseomestuff 32' +# # reward section to reward the player for completing a repeated challenge (any time after the first). The +# # structure is identical to the 'reward' section. +# repeatReward: +# text: 'Mossy cobblestone' +# items: +# - mossy_cobblestone:16 +# +# ====================================================================================================================== + +# Unrelated items - should be preserved +allowChallenges: true + +challengeColor: '&e' + +# Unrelated item that should be converted +ISLAND: + # Comment should be preserved + lockedDisplayItem: blue_stained_glass_pane # Ideally inline comments are also preserved + +# Challenge items - items should be converted + +path: + to: + name: '&7Novice' + # Simple display item + displayItem: cyan_terracotta + resetInHours: 20 + challenges: + testchallenge: + name: '&7Only for testing' + description: Not a real challenge. + type: onPlayer + # Mix of required items + # enchanted_book{StoredEnchantments:[{id:34,lvl:3}]} + requiredItems: + - cobblestone:64;+2 + - iron_ingot:100 + - enchanted_book[]:1 + - white_wool:32;-1 + - diamond:1;*1 + - invalid_item:10 + displayItem: cobblestone + # Complex display item with meta + # enchanted_book{StoredEnchantments:[{id:34,lvl:3}]} + lockedDisplayItem: enchanted_book[] + resetInHours: 12 + reward: + text: Reward to test the converter + # enchanted_book{StoredEnchantments:[{id:34,lvl:3}]} + items: + - leather:3 + - '{p=0.2}book:1' + - '{p=0.99}enchanted_book[]:3' + currency: 10 + xp: 10 + commands: + - op:test command + repeatReward: + text: This should work the same + items: + - leather:1 + - '{p=0.1}book:1' + currency: 5 + xp: 5 + +# This file has been updated to version 107. Please check the changes made in this version. +# Changes in this version: +# - Items are now specified in the new component format. +# - Refer to the config header for the new format. +# - NBT tags are not automatically converted. They have been moved to the comments, please check them manually. +# You can use the following converter to convert the old item specifications to the new format: +# https://docs.papermc.io/misc/tools/item-command-converter +# DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen! +version: 107 diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges.yml new file mode 100644 index 000000000..b59a71ed8 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges.yml @@ -0,0 +1,58 @@ +# Header Comments +# Make sure these are preserved + +# Unrelated items - should be preserved +allowChallenges: true + +challengeColor: '&e' + +# Unrelated item that should be converted +ISLAND: + # Comment should be preserved + lockedDisplayItem: BLUE_STAINED_GLASS_PANE # Ideally inline comments are also preserved + +# Challenge items - items should be converted + +path: + to: + name: '&7Novice' + # Simple display item + displayItem: CYAN_TERRACOTTA + resetInHours: 20 + challenges: + testchallenge: + name: '&7Only for testing' + description: Not a real challenge. + type: onPlayer + # Mix of required items + requiredItems: + - COBBLESTONE:64;+2 + - IRON_INGOT:100 + - ENCHANTED_BOOK{StoredEnchantments:[{id:34,lvl:3}]}:1 + - WHITE_WOOL:32;-1 + - DIAMOND:1;*1 + - INVALID_ITEM:10 + displayItem: COBBLESTONE + # Complex display item with meta + lockedDisplayItem: 'ENCHANTED_BOOK {StoredEnchantments:[{id:34,lvl:3}]}' + resetInHours: 12 + reward: + text: Reward to test the converter + items: + - LEATHER:3 + - '{p=0.2}BOOK:1' + - '{p=0.99}ENCHANTED_BOOK:3 {StoredEnchantments:[{id:34,lvl:3}]}' + currency: 10 + xp: 10 + commands: + - op:test command + repeatReward: + text: This should work the same + items: + - LEATHER:1 + - '{p=0.1}BOOK:1' + currency: 5 + xp: 5 + +# Here used to be the old config description. It should be removed and added as header. +version: 106 From c015b028db66611e4bd8ab2d80d16ea457e88fe3 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 28 Jul 2024 22:46:39 +0200 Subject: [PATCH 129/190] Remove YmlConfigurationTest#saveToFile because it keeps breaking on line separators --- .../minecraft/yml/YmlConfigurationTest.java | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java index a1649a6f2..8b70a8bea 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java @@ -4,33 +4,12 @@ import org.hamcrest.Matchers; import org.junit.Test; -import java.io.BufferedReader; import java.io.File; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.stream.Collectors; -import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; -/** - * Created by R4zorax on 15/07/2016. - */ public class YmlConfigurationTest { - @Test - public void saveToString() throws Exception { - File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); - YamlConfiguration config = new YamlConfiguration(); - config.load(simpleYml); - - config.set("root.child node.abe", "lincoln\nwas a wonderful\npresident"); - String expected = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("yml/simple_expected.yml"), StandardCharsets.UTF_8)) - .lines().collect(Collectors.joining(System.lineSeparator())); - config.save(new File(simpleYml.getParent(), "new_actual.yml")); - assertThat(config.saveToString(), is(expected)); - } - @Test public void testGetStringList_List() throws Exception { File simpleYml = new File(getClass().getClassLoader().getResource("yml/simple.yml").toURI()); From 8644963317a7a83c1806821738f509cd2a41815c Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 9 Dec 2024 21:16:20 +0100 Subject: [PATCH 130/190] Split block requirements from item requirements (#59) * Remove AWE integration AsynchWorldEdit has been abandoned for over 2 years and does not work with current server versions. We should focus on supporting FAWE going ahead. * Decouple block from item requirements in challenges This resolves an issue in newer Spigot versions where non-item blocks in challenge requirements prevent the plugin from loading. Fixes #58 * Add converter to new challenges format * Update item conversion tests to new config header * Add timestamp to challenge file backup to avoid overwriting old backups * Update the challenges version number after conversion --- .github/deploy-release.sh | 4 - .github/deploy-staging.sh | 4 - .../minecraft/util/BlockRequirement.java | 9 + .../minecraft/util/ItemStackUtil.java | 44 +- pom.xml | 6 - uSkyBlock-AWE370/README.md | 5 - uSkyBlock-AWE370/pom.xml | 68 - .../handler/asyncworldedit/AWE370Adaptor.java | 200 -- .../block/BlockCollection.java | 13 +- .../ultimateskyblock/challenge/Challenge.java | 25 +- .../challenge/ChallengeFactory.java | 7 +- .../challenge/ChallengeLogic.java | 7 +- .../handler/AsyncWorldEditHandler.java | 14 - .../imports/BlockRequirementConverter.java | 97 + .../talabrek/ultimateskyblock/uSkyBlock.java | 8 +- .../ultimateskyblock/util/FileUtil.java | 10 +- .../src/main/resources/challenges.yml | 26 +- uSkyBlock-Core/src/main/resources/plugin.yml | 1 - .../imports/ItemComponentConverterTest.java | 34 + .../imports/expected-block-challenges.yml | 1794 +++++++++++++++++ .../imports/old-block-challenges.yml | 1790 ++++++++++++++++ .../old-default-challenges-expected.yml | 6 +- .../imports/test-challenges-expected.yml | 6 +- uSkyBlock-Plugin/pom.xml | 4 - uSkyBlock-Plugin/src/assembly/plugin.xml | 1 - 25 files changed, 3832 insertions(+), 351 deletions(-) create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/BlockRequirement.java delete mode 100644 uSkyBlock-AWE370/README.md delete mode 100644 uSkyBlock-AWE370/pom.xml delete mode 100644 uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/BlockRequirementConverter.java create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/expected-block-challenges.yml create mode 100644 uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-block-challenges.yml diff --git a/.github/deploy-release.sh b/.github/deploy-release.sh index cc8cdbfe2..90e5023c8 100644 --- a/.github/deploy-release.sh +++ b/.github/deploy-release.sh @@ -20,10 +20,6 @@ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh index adc899db5..37b67e296 100644 --- a/.github/deploy-staging.sh +++ b/.github/deploy-staging.sh @@ -20,10 +20,6 @@ rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ -$HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-AWE370/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ - rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/BlockRequirement.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/BlockRequirement.java new file mode 100644 index 000000000..0d243a8dd --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/BlockRequirement.java @@ -0,0 +1,9 @@ +package dk.lockfuglsang.minecraft.util; + +import org.bukkit.block.data.BlockData; + +// This class should ideally be located in package us.talabrek.ultimateskyblock.challenge. However, it is not possible +// to move there as it is required by ItemStackUtil in this module. This is a limitation of the current design. +// The parsing logic should eventually be moved to the uSkyBlock-Core module. +public record BlockRequirement(BlockData type, int amount) { +} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java index 96a4fce25..03b5a554b 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java @@ -2,6 +2,7 @@ import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.block.data.BlockData; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -30,6 +31,27 @@ public enum ItemStackUtil { private static final Pattern ITEM_REQUIREMENT_PATTERN = Pattern.compile( "(?(minecraft:)?[0-9A-Za-z_]+(\\[.*])?):(?\\d+)(;(?[-+*^/])(?\\d+(.\\d+)?))?" ); + private static final Pattern BLOCK_REQUIREMENT_PATTERN = Pattern.compile( + "(?(minecraft:)?[0-9A-Za-z_]+(\\[.*])?):(?\\d+)" + ); + + @NotNull + public static BlockRequirement createBlockRequirement(@NotNull String specification) { + Matcher matcher = BLOCK_REQUIREMENT_PATTERN.matcher(specification); + if (matcher.matches()) { + BlockData itemStack = getBlockType(matcher); + int amount = Integer.parseInt(matcher.group("amount")); + return new BlockRequirement(itemStack, amount); + } else { + throw new IllegalArgumentException("Invalid item requirement: '" + specification + "'"); + } + } + + @NotNull + private static BlockData getBlockType(@NotNull Matcher matcher) { + String type = matcher.group("type"); + return Bukkit.createBlockData(type.toLowerCase(Locale.ROOT)); + } @NotNull public static ItemRequirement createItemRequirement(@NotNull String specification) { @@ -69,22 +91,7 @@ public static List createItemsWithProbability(@NotNull List typesWithAmount) { diff --git a/pom.xml b/pom.xml index 07e3e91ba..88a1a6dec 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,6 @@ uSkyBlock-Core uSkyBlock-Plugin uSkyBlock-FAWE - uSkyBlock-AWE370 @@ -209,11 +208,6 @@ uSkyBlock-FAWE ${project.version} - - ovh.uskyblock - uSkyBlock-AWE370 - ${project.version} - ovh.uskyblock po-utils diff --git a/uSkyBlock-AWE370/README.md b/uSkyBlock-AWE370/README.md deleted file mode 100644 index acc7ad06e..000000000 --- a/uSkyBlock-AWE370/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# uSkyBlock-AsyncWorldEdit 3.7.0 - -This module holds the AWE 3.7.0 dependent integration (AsyncWorldEdit-API 2.2.0). - -It is a separate module, so we are able to compile (and test) it in a controlled manner (side by side the AWE211 integration). diff --git a/uSkyBlock-AWE370/pom.xml b/uSkyBlock-AWE370/pom.xml deleted file mode 100644 index 94be33f46..000000000 --- a/uSkyBlock-AWE370/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.1.0-SNAPSHOT - - 4.0.0 - uSkyBlock-AWE370 - - - - org.primesoft.asyncworldedit - AsyncWorldEdit-API - [2.2.0-rc-01, 2.2.0) - jar - - - com.sk89q.worldedit - * - - - - - ovh.uskyblock - uSkyBlock-Core - - - org.spigotmc - spigot-api - ${spigotapi.version} - true - provided - - - - com.sk89q.worldedit - worldedit-bukkit - ${worldedit.version} - provided - - - org.bukkit - bukkit - - - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - diff --git a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java b/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java deleted file mode 100644 index ff675a560..000000000 --- a/uSkyBlock-AWE370/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/AWE370Adaptor.java +++ /dev/null @@ -1,200 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.asyncworldedit; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.function.operation.Operations; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.session.ClipboardHolder; -import com.sk89q.worldedit.world.World; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitTask; -import org.primesoft.asyncworldedit.api.IAsyncWorldEdit; -import org.primesoft.asyncworldedit.api.blockPlacer.IBlockPlacerPlayer; -import org.primesoft.asyncworldedit.api.playerManager.IPlayerEntry; -import org.primesoft.asyncworldedit.api.playerManager.IPlayerManager; -import org.primesoft.asyncworldedit.api.utils.IFuncParamEx; -import org.primesoft.asyncworldedit.api.worldedit.IAsyncEditSessionFactory; -import org.primesoft.asyncworldedit.api.worldedit.ICancelabeEditSession; -import org.primesoft.asyncworldedit.api.worldedit.IThreadSafeEditSession; -import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; -import us.talabrek.ultimateskyblock.player.PlayerPerk; -import us.talabrek.ultimateskyblock.uSkyBlock; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Adaptor depending on AWE 3.7.x classes - */ -public class AWE370Adaptor implements AWEAdaptor { - private static final Logger log = Logger.getLogger(AWE370Adaptor.class.getName()); - static long progressEveryMs = 3000; // 2 seconds - static double progressEveryPct = 20; - private static final Set pendingJobs = Collections.synchronizedSet(new LinkedHashSet<>()); - private uSkyBlock plugin; - - private static void updateProgress(IPlayerEntry playerEntry, int queuedBlocks, int maxQueuedBlocks) { - if (maxQueuedBlocks <= 1) { - return; // Not the "real" number of blocks... just ignore... - } - if (playerEntry != null && playerEntry.isUnknown() && playerEntry.getAweMode()) { - synchronized (pendingJobs) { - if (queuedBlocks == maxQueuedBlocks) { - // Either a fresh job, or a new merge - markJobs(maxQueuedBlocks, 0); - } - int blocksPlaced = maxQueuedBlocks - queuedBlocks; - boolean isFirst = true; - for (Iterator it = pendingJobs.iterator(); it.hasNext(); ) { - PlayerJob job = it.next(); - int left = job.progress(blocksPlaced); - if (left > 0 && isFirst && pendingJobs.size() > 1) { - it.remove(); - markJobs(blocksPlaced + left, queuedBlocks - left); - } - isFirst = false; - } - } - } - } - - private BukkitTask timerTask; - - private static void markJobs(int maxQueuedBlocks, int startOffset) { - synchronized (pendingJobs) { - int rest = maxQueuedBlocks; - for (PlayerJob job : pendingJobs) { - int missing = job.mark(rest, startOffset); - rest -= missing; - startOffset += missing; - } - } - } - - private static IAsyncWorldEdit getAWE() { - return (IAsyncWorldEdit) Bukkit.getPluginManager().getPlugin("AsyncWorldEdit"); - } - - @Override - public void onEnable(uSkyBlock plugin) { - this.plugin = plugin; - progressEveryMs = plugin.getConfig().getInt("asyncworldedit.progressEveryMs", 3000); - progressEveryPct = plugin.getConfig().getDouble("asyncworldedit.progressEveryPct", 20); - } - - @Override - public void registerCompletion(Player player) { - PlayerJob newJob = new PlayerJob(player, progressEveryMs, progressEveryPct, plugin); - pendingJobs.remove(newJob); - pendingJobs.add(newJob); - } - - @Override - public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { - final IAsyncWorldEdit awe = getAWE(); - BukkitWorld bukkitWorld = new BukkitWorld(origin.getWorld()); - int maxBlocks = ((bukkitWorld.getMaxY() - bukkitWorld.getMinY()) * Settings.island_protectionRange * Settings.island_protectionRange); - IPlayerManager pm = awe.getPlayerManager(); - final IPlayerEntry playerEntry = pm.getUnknownPlayer(); - IThreadSafeEditSession tsSession = (IThreadSafeEditSession) createEditSession(bukkitWorld, maxBlocks); - IFuncParamEx action = new PasteAction(origin, file); - - String jobName = "loadIslandSchematic"; - if (playerPerk != null) { - Player player = Bukkit.getPlayer(playerPerk.getPlayerInfo().getUniqueId()); - registerCompletion(player); - jobName = jobName.concat(":" + playerPerk.getPlayerInfo().getPlayerName()); - } - - awe.getBlockPlacer().performAsAsyncJob(tsSession, playerEntry, jobName, action); - if (timerTask != null) { - timerTask.cancel(); - } - timerTask = plugin.async(new Runnable() { - int maxSize = -1; - @Override - public void run() { - IBlockPlacerPlayer playerEvents = awe.getBlockPlacer().getPlayerEvents(playerEntry); - if (playerEvents != null) { - int size = playerEvents.getQueue().size(); - if (maxSize == -1 || size > maxSize) { - maxSize = size; - } - updateProgress(playerEntry, size, maxSize); - } else { - updateProgress(playerEntry, 0, maxSize); - timerTask.cancel(); - } - } - }, 500, 500); - } - - public EditSession createEditSession(World bukkitWorld, int maxBlocks) { - WorldEdit worldEdit = WorldEdit.getInstance(); - IAsyncEditSessionFactory sessionFactory = (IAsyncEditSessionFactory) worldEdit.getEditSessionFactory(); - return (EditSession) sessionFactory.getThreadSafeEditSession(bukkitWorld, maxBlocks, null, getAWE().getPlayerManager().getUnknownPlayer()); - } - - @Override - public void regenerate(Region region, Runnable onCompletion) { - AsyncWorldEditHandler.NULL_ADAPTOR.regenerate(region, onCompletion); - } - - @Override - public void onDisable(uSkyBlock plugin) { - } - - private static class PasteAction implements IFuncParamEx { - private final Location origin; - private final File file; - - public PasteAction(Location origin, File file) { - this.origin = origin; - this.file = file; - } - - public Integer execute(ICancelabeEditSession editSession) { - ClipboardFormat format = ClipboardFormats.findByFile(file); - if (format == null) { - log.log(Level.SEVERE, "Unable to find schematic format for file {}", file); - return null; - } - - try (InputStream inStream = new FileInputStream(file)) { - Clipboard clipboard = format.getReader(inStream).read(); - ClipboardHolder holder = new ClipboardHolder(clipboard); - editSession.enableQueue(); - - BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final Operation operation = holder - .createPaste(editSession) - .to(to) - .ignoreAirBlocks(true) - .build(); - Operations.completeBlindly(operation); - editSession.flushSession(); - } catch (IOException ex) { - log.log(Level.WARNING, "Error while pasting schematic", ex); - } - return 32768; - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java index 398b45590..e3dfce4ef 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/block/BlockCollection.java @@ -1,11 +1,12 @@ package us.talabrek.ultimateskyblock.block; +import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.inventory.ItemStack; import java.util.HashMap; +import java.util.List; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -17,7 +18,7 @@ public BlockCollection() { this.blockCount = new HashMap<>(); } - public synchronized void add(Block block) { + public void add(Block block) { int currentValue = blockCount.getOrDefault(block.getType(), 0); blockCount.put(block.getType(), currentValue + 1); } @@ -25,12 +26,12 @@ public synchronized void add(Block block) { /** * Returns null if all the items are in the BlockCollection, a String describing the missing items if it's not */ - public synchronized String diff(Map itemStacks) { + public String diff(List requirements) { StringBuilder sb = new StringBuilder(); - for (Map.Entry item : itemStacks.entrySet()) { - int diff = item.getValue() - count(item.getKey().getType()); + for (BlockRequirement requirement : requirements) { + int diff = requirement.amount() - count(requirement.type().getMaterial()); if (diff > 0) { - sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, ItemStackUtil.getItemName(item.getKey()))); + sb.append(tr(" \u00a7f{0}x \u00a77{1}", diff, ItemStackUtil.getBlockName(requirement.type()))); } } if (sb.toString().trim().isEmpty()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java index 23bbb2104..b047b6b13 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.FormatUtil; import dk.lockfuglsang.minecraft.util.ItemRequirement; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -43,6 +44,7 @@ static Type from(String s) { private final String displayName; private final Type type; private final List requiredItems; + private final List requiredBlocks; private final List requiredEntities; private final List requiredChallenges; private final double requiredLevel; @@ -59,13 +61,15 @@ static Type from(String s) { private final int repeatLimit; public Challenge(String name, String displayName, String description, Type type, List requiredItems, - List requiredEntities, List requiredChallenges, double requiredLevel, Rank rank, + @NotNull List requiredBlocks, List requiredEntities, + List requiredChallenges, double requiredLevel, Rank rank, int resetInHours, ItemStack displayItem, String tool, ItemStack lockedItem, int offset, boolean takeItems, int radius, Reward reward, Reward repeatReward, int repeatLimit) { this.name = name; this.displayName = displayName; this.type = type; this.requiredItems = requiredItems; + this.requiredBlocks = requiredBlocks; this.requiredEntities = requiredEntities; this.requiredChallenges = requiredChallenges; this.requiredLevel = requiredLevel; @@ -119,6 +123,11 @@ public Map getRequiredItems(int timesCompleted) { )); } + @NotNull + public List getRequiredBlocks() { + return requiredBlocks; + } + public List getRequiredEntities() { return requiredEntities; } @@ -176,7 +185,8 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr reward = getRepeatReward(); } Map requiredItemsForChallenge = getRequiredItems(timesCompleted); - if (!requiredItemsForChallenge.isEmpty() || requiredEntities != null && !requiredEntities.isEmpty()) { + if (!requiredItemsForChallenge.isEmpty() || !requiredBlocks.isEmpty() + || (requiredEntities != null && !requiredEntities.isEmpty())) { lores.add(tr("\u00a7eThis challenge requires:")); } List details = new ArrayList<>(); @@ -193,6 +203,17 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr : tr("\u00a77{0}", ItemStackUtil.getItemName(requiredType))); } } + if (!requiredBlocks.isEmpty() && wrappedDetails(details).size() < MAX_DETAILS) { + for (BlockRequirement blockRequirement : requiredBlocks) { + if (wrappedDetails(details).size() >= MAX_DETAILS) { + details.add(tr("\u00a77and more...")); + break; + } + details.add(blockRequirement.amount() > 1 + ? tr("\u00a7f{0}x \u00a77{1}", blockRequirement.amount(), ItemStackUtil.getBlockName(blockRequirement.type())) + : tr("\u00a77{0}", ItemStackUtil.getBlockName(blockRequirement.type()))); + } + } if (requiredEntities != null && !requiredEntities.isEmpty() && wrappedDetails(details).size() < MAX_DETAILS) { for (EntityMatch entityMatch : requiredEntities) { if (wrappedDetails(details).size() >= MAX_DETAILS) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index 07d9a1b45..0df3c5bb3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.ItemRequirement; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.configuration.ConfigurationSection; @@ -50,6 +51,8 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, Challenge.Type type = Challenge.Type.from(section.getString("type", "onPlayer")); List requiredItems = section.getStringList("requiredItems").stream() .map(ItemStackUtil::createItemRequirement).toList(); + List requiredBlocks = section.getStringList("requiredBlocks").stream() + .map(ItemStackUtil::createBlockRequirement).toList(); List requiredEntities = createEntities(section.getStringList("requiredEntities")); int resetInHours = section.getInt("resetInHours", rank.getResetInHours()); String description = section.getString("description"); @@ -68,8 +71,8 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, int offset = section.getInt("offset", 0); int repeatLimit = section.getInt("repeatLimit", 0); return new Challenge(name, displayName, description, type, - requiredItems, requiredEntities, requiredChallenges, section.getDouble("requiredLevel", 0d), rank, - resetInHours, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, + requiredItems, requiredBlocks, requiredEntities, requiredChallenges, section.getDouble("requiredLevel", 0d), + rank, resetInHours, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, radius, reward, repeatReward, repeatLimit); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 9c68c79f2..b83a8ddde 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.FormatUtil; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Bukkit; @@ -201,7 +202,7 @@ private boolean tryCompleteIslandLevel(Player player, Challenge challenge) { return false; } - private boolean islandContains(Player player, Map itemStacks, int radius) { + private boolean islandContains(Player player, List itemStacks, int radius) { final Location l = player.getLocation(); final int px = l.getBlockX(); final int py = l.getBlockY(); @@ -234,9 +235,9 @@ private boolean islandContains(Player player, Map itemStacks */ private boolean tryCompleteOnIsland(Player player, String challengeName) { Challenge challenge = getChallenge(challengeName); - Map requiredItems = challenge.getRequiredItems(0); + List requiredBlocks = challenge.getRequiredBlocks(); int radius = challenge.getRadius(); - if (islandContains(player, requiredItems, radius) && hasEntitiesNear(player, challenge.getRequiredEntities(), radius)) { + if (islandContains(player, requiredBlocks, radius) && hasEntitiesNear(player, challenge.getRequiredEntities(), radius)) { giveReward(player, challenge); return true; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 4e6919993..f2783b531 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -56,7 +56,6 @@ public static AWEAdaptor getAWEAdaptor() { } //Plugin fawe = getFAWE(); Plugin fawe = null; // Disabled b/c 1.18.1 releases - Plugin awe = getAWE(); String className; if (fawe != null) { VersionUtil.Version version = VersionUtil.getVersion(fawe.getDescription().getVersion()); @@ -68,15 +67,6 @@ public static AWEAdaptor getAWEAdaptor() { log(Level.WARNING, "Unable to locate FAWE adaptor for version " + version + ": " + ex); adaptor = NULL_ADAPTOR; } - } else if (awe != null) { - VersionUtil.Version version = VersionUtil.getVersion(awe.getDescription().getVersion()); - className = "us.talabrek.ultimateskyblock.handler.asyncworldedit.AWE370Adaptor"; - try { - adaptor = (AWEAdaptor) Class.forName(className).getDeclaredConstructor().newInstance(); - log(Level.INFO, "Hooked into AWE version " + version); - } catch (Exception ex) { - log(Level.WARNING, "Unable to locale AWE adaptor for version " + version, ex); - } } else { adaptor = NULL_ADAPTOR; } @@ -92,10 +82,6 @@ public static Plugin getFAWE() { return Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit"); } - public static Plugin getAWE() { - return Bukkit.getPluginManager().getPlugin("AsyncWorldEdit"); - } - public static final AWEAdaptor NULL_ADAPTOR = new AWEAdaptor() { @Override public void onEnable(uSkyBlock plugin) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/BlockRequirementConverter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/BlockRequirementConverter.java new file mode 100644 index 000000000..470788168 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/BlockRequirementConverter.java @@ -0,0 +1,97 @@ +package us.talabrek.ultimateskyblock.imports; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Objects; +import java.util.logging.Logger; + +import static us.talabrek.ultimateskyblock.util.FileUtil.generateTimestamp; + +public class BlockRequirementConverter { + + private static final int NEW_CHALLENGES_VERSION = 108; + private final Logger logger; + + public BlockRequirementConverter(Logger logger) { + this.logger = logger; + } + + public void checkAndDoImport(File directory) { + var challengesFile = new File(directory, "challenges.yml"); + if (challengesFile.exists() && YamlConfiguration.loadConfiguration(challengesFile).getInt("version") < NEW_CHALLENGES_VERSION) { + importFile(challengesFile); + } + } + + public void importFile(File file) { + Path configFile = file.toPath(); + try { + Files.copy(configFile, configFile.getParent().resolve(configFile.getFileName() + "_" + generateTimestamp() + ".old")); + + FileConfiguration config = new YamlConfiguration(); + config.load(file); + + if (file.getName().equals("challenges.yml")) { + convertChallenges(config); + } + + config.save(file); + } catch (Exception e) { + throw new RuntimeException("An error occurred while attempting to convert file " + file, e); + } + } + + private void convertChallenges(FileConfiguration config) throws Exception { + var oldVersion = config.getInt("version"); + if (oldVersion >= NEW_CHALLENGES_VERSION) { + logger.warning("Expecting challanges.yml version " + (NEW_CHALLENGES_VERSION - 1) + ", but found " + oldVersion + " instead. Skipping conversion."); + return; + } + logger.info("Converting challenges.yml to new block requirement format."); + + convertBlockRequirements(config); + } + + private void convertBlockRequirements(FileConfiguration config) { + var ranks = config.getConfigurationSection("ranks"); + if (ranks != null) { + for (var rank : ranks.getKeys(false)) { + var challenges = ranks.getConfigurationSection(rank + ".challenges"); + if (challenges != null) { + for (var challenge : challenges.getKeys(false)) { + var challengeSection = challenges.getConfigurationSection(challenge); + if (challengeSection != null + && challengeSection.getString("type", "").equals("onIsland") + && challengeSection.isSet("requiredItems") + ) { + var requiredItems = challengeSection.getStringList("requiredItems"); + var requiredBlocks = new ArrayList<>(requiredItems); + challengeSection.set("requiredBlocks", requiredBlocks); + challengeSection.set("requiredItems", null); + } + } + } + } + } + + // Add the new header with explanations and usage instructions + var defaultConfig = new YamlConfiguration(); + try (var reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull( + getClass().getClassLoader().getResourceAsStream("challenges.yml")), StandardCharsets.UTF_8))) { + defaultConfig.load(reader); + } catch (Exception e) { + logger.warning("Failed to load default challenges.yml file - unable to update the config header."); + } + config.options().setHeader(defaultConfig.options().getHeader()); + + config.set("version", NEW_CHALLENGES_VERSION); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 7a40d9d0c..8855ad0fa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -13,7 +13,6 @@ import org.bukkit.block.Biome; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -65,6 +64,7 @@ import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; +import us.talabrek.ultimateskyblock.imports.BlockRequirementConverter; import us.talabrek.ultimateskyblock.imports.ItemComponentConverter; import us.talabrek.ultimateskyblock.imports.USBImporterExecutor; import us.talabrek.ultimateskyblock.island.BlockLimitLogic; @@ -210,6 +210,11 @@ private void convertConfigItemsTo1_20_6IfRequired() { converter.checkAndDoImport(getDataFolder()); } + private void convertConfigToBlockRequirements() { + var converter = new BlockRequirementConverter(getLogger()); + converter.checkAndDoImport(getDataFolder()); + } + @Override public void onEnable() { WorldManager.skyBlockWorld = null; // Force a re-import or what-ever... @@ -219,6 +224,7 @@ public void onEnable() { // Converter has to run before the plugin loads its config files. convertConfigItemsTo1_20_6IfRequired(); + convertConfigToBlockRequirements(); CommandManager.registerRequirements(this); FileUtil.setDataFolder(getDataFolder()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java index 1970b8f53..54389fb6c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/FileUtil.java @@ -6,6 +6,8 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; /** * Common file-utilities. @@ -25,7 +27,7 @@ public static String getBasename(String file) { public static String getExtension(String fileName) { if (fileName != null && !fileName.isEmpty()) { - return fileName.substring(getBasename(fileName).length()+1); + return fileName.substring(getBasename(fileName).length() + 1); } return ""; } @@ -36,4 +38,10 @@ public static void copy(InputStream stream, File file) throws IOException { } Files.copy(stream, Paths.get(file.toURI()), StandardCopyOption.REPLACE_EXISTING); } + + public static String generateTimestamp() { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"); + LocalDateTime now = LocalDateTime.now(); + return now.format(formatter); + } } diff --git a/uSkyBlock-Core/src/main/resources/challenges.yml b/uSkyBlock-Core/src/main/resources/challenges.yml index e97fca755..3c0d13931 100644 --- a/uSkyBlock-Core/src/main/resources/challenges.yml +++ b/uSkyBlock-Core/src/main/resources/challenges.yml @@ -65,10 +65,14 @@ # ## type: onIsland # # [integer] Overrides the default radius of 10 blocks when using onIsland. # ## radius: 20 -# # [List[item-requirement] The items required to complete the challenge. +# # List[item-requirement] The items required to complete the challenge. # requiredItems: # - stone:64;+16 # - cobblestone:64;+16 +# # List[block-requirement] The blocks required to complete the challenge. +# requiredBlocks: +# - stone:64 +# - cobblestone:64 # # [true/false] If the challenge can be repeated or not. # ## repeatable: true # # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. @@ -252,7 +256,7 @@ ranks: type: onIsland displayItem: sugar_cane lockedDisplayItem: brown_stained_glass_pane - requiredItems: + requiredBlocks: - sugar_cane:4 reward: text: 4 dirt @@ -632,7 +636,7 @@ ranks: type: onIsland requiredChallenges: - stonebrickmaker - requiredItems: + requiredBlocks: - red_bed:1 - crafting_table:1 - glass:1 @@ -658,7 +662,7 @@ ranks: requiredChallenges: - adeptbuilder - homeowner - requiredItems: + requiredBlocks: - obsidian:10 - nether_portal:1 displayItem: obsidian @@ -945,7 +949,7 @@ ranks: requiredChallenges: - monsterfarm - applecollector - requiredItems: + requiredBlocks: - oak_door:30 requiredEntities: - Villager:10 @@ -962,7 +966,7 @@ ranks: description: Build a netherfortress. type: onIsland radius: 50 - requiredItems: + requiredBlocks: - nether_bricks:512 - nether_brick_slab:64 - nether_brick_fence:64 @@ -1408,7 +1412,7 @@ ranks: lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - nethermining - requiredItems: + requiredBlocks: - quartz_block:512 - chiseled_quartz_block:64 - quartz_pillar:128 @@ -1428,7 +1432,7 @@ ranks: radius: 30 displayItem: sandstone lockedDisplayItem: blue_stained_glass_pane - requiredItems: + requiredBlocks: - sandstone:512 - chiseled_sandstone:64 - smooth_sandstone:128 @@ -1452,7 +1456,7 @@ ranks: lockedDisplayItem: blue_stained_glass_pane requiredChallenges: - deepseafisherman - requiredItems: + requiredBlocks: - prismarine:512 - prismarine_bricks:128 - dark_prismarine:64 @@ -1492,7 +1496,7 @@ ranks: - ironfarm - maestro - witherhunter - requiredItems: + requiredBlocks: - beacon:1 - diamond_block:1 - emerald_block:8 @@ -1517,7 +1521,7 @@ ranks: - tajmahal - poseidonshalls - greatpyramid - requiredItems: + requiredBlocks: - end_portal_frame:12 - end_portal:9 reward: diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 6979a866d..5191e092e 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -15,7 +15,6 @@ softdepend: - Vault # WE/AWE - FastAsyncWorldEdit - - AsyncWorldEdit # placeholders - MVdWPlaceholderAPI api-version: 1.20.6 diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java index 26ebf2adb..12f63010a 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/imports/ItemComponentConverterTest.java @@ -38,6 +38,40 @@ public void testDefaultSettingsConversion() throws Exception { testConfig("old-config.yml", "old-config-expected.yml", "config.yml"); } + @Test + public void testDefaultChallengeConversionBlockRequirements() throws Exception { + testBlockConverterConfig("old-block-challenges.yml", "expected-block-challenges.yml", "challenges.yml"); + } + + private void testBlockConverterConfig(String originalName, String expectedName, String fileName) throws Exception { + var testFile = new File(testFolder.getRoot(), fileName); + try (var reader = Objects.requireNonNull(getClass().getResourceAsStream(originalName))) { + Files.copy(reader, testFile.toPath()); + } + + var converter = new BlockRequirementConverter(Logger.getAnonymousLogger()); + converter.importFile(testFile); + + assertTrue(testFile.exists()); + long backupFiles; + try (var stream = Files.find(testFolder.getRoot().toPath(), 1, + (path, attr) -> + path.getFileName().toString().startsWith(fileName) && path.getFileName().toString().endsWith(".old") + )) { + backupFiles = stream.count(); + } + assertEquals(1, backupFiles); + + YamlConfiguration actual = new YamlConfiguration(); + actual.load(testFile); + YamlConfiguration expected = new YamlConfiguration(); + try (var reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull( + getClass().getResourceAsStream(expectedName)), StandardCharsets.UTF_8))) { + expected.load(reader); + } + assertConfigsEquals(expected, actual); + } + private void testConfig(String originalName, String expectedName, String fileName) throws Exception { var testFile = new File(testFolder.getRoot(), fileName); try (var reader = Objects.requireNonNull(getClass().getResourceAsStream(originalName))) { diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/expected-block-challenges.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/expected-block-challenges.yml new file mode 100644 index 000000000..8e04580c2 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/expected-block-challenges.yml @@ -0,0 +1,1794 @@ +# ====================================================================================================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the +# most used settings while the double commented (##) are optional if you like to use those settings. +# +# Item type format +# Item types are defined as in the minecraft /give command, i.e. with their minecraft key and possible components in +# square brackets. For example, 'minecraft:diamond_sword[damage=42]'. Refer to the Minecraft wiki for more information: +# https://minecraft.wiki/w/Data_component_format. You can also use the command '/usb iteminfo' to get the information. +# +# This item type is supplemented with additional information depending on where it is used: +# +# display-item: +# An item to be displayed in a GUI. It only defines the item type as above, without any additional information. +# For example: 'cobblestone', 'minecraft:stone', 'diamond_sword[damage=42]'. +# +# item-requirement: :[;+] +# An item requirement for a challenge. The amount is the number of items required. The optional + is the number +# of items to add to the required amount for each repeat of the challenge. For example, 'cobblestone:64;+16' would +# require 64 cobblestone for the first completion and 80 cobblestone for the second completion. Other options are +# -, *, and / for subtraction, multiplication, and division, respectively. For example, 'cobblestone:64;*2' would +# require 64 cobblestone for the first completion, 128 cobblestone for the second completion, and 256 cobblestone for +# the third completion. +# +# item-reward: [{p=}]: +# An item reward for a challenge. The amount is the number of items to give. The optional {p=} is the +# probability of the item being given. For example, 'cobblestone:64' would give 64 cobblestone every time the challenge +# is completed, while '{p=0.1}cobblestone:64' would give 64 cobblestone 10% of the time. +# +# ====================================================================================================================== +# All challenges are defined in the ranks section. Each rank is a tier of challenges that players can complete. +# +# ranks: +# # [text] name of the challenge Rank. +# TierX: +# # [text] The name of the challenge rank that shows when you do /challenges (supports capitals and color codes). +# name: '&aCustom Challenges rank name' +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: 'cyan_terracotta' +# # [integer] The time in hours before required items reset to default (this overwrites the main reset time) +# resetInHours: 20 +# # These requirements controls when a challenge group will be available to a player. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, +# if you have 4 challenges with a rankLeeway of 1, a player would only need to complete 3 to advance to +# the next rank. A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [List[text]] Challenges that have to be completed before this group will available to a player. +# challenges: +# - a challenge name +# ====================================================================================================================== +# challenges: +# # [text] The name of the challenge. All challenge names should be lower-case. +# defaultchallenge: +# # [text] The name of the challenge that shows in /challenges (this supports capitals and color codes). +# name: '&a Default Challenge' +# # [text] The descriptions players see when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This defines whether the required blocks/items should be in the player's +# # inventory or on their island. When using onIsland, the player must within 10 blocks from the required blocks +# # on his island. When using islandLevel, the 'requiredItems' field should be the island level required. The +# # player must use /island level first to update their level. +# type: onPlayer +# ## type: islandLevel +# ## type: onIsland +# # [integer] Overrides the default radius of 10 blocks when using onIsland. +# ## radius: 20 +# # List[item-requirement] The items required to complete the challenge. +# requiredItems: +# - stone:64;+16 +# - cobblestone:64;+16 +# # List[block-requirement] The blocks required to complete the challenge. +# requiredBlocks: +# - stone:64 +# - cobblestone:64 +# # [true/false] If the challenge can be repeated or not. +# ## repeatable: true +# # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. +# # A value of 0 means unlimited repeats. +# ## repeatLimit: 5 +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: cobblestone +# # [integer] The time in hours before required items reset to default (overwrites the main and rank defaults). +# ## resetInHours: 4 +# # [true/false] Take required items on completing a challenge. +# ## takeItems: true +# # The rewards players get for completing the challenge +# reward: +# # [text] Description of the reward. +# text: 'Mossy cobblestone and an iron pickaxe with unbreaking 1' +# # [List[item-requirement]] A list of items given to the player for completing the challenge. +# items: +# - mossy_cobblestone:16 +# - iron_pickaxe[enchantments={levels:{unbreaking:1}}]:1 +# # [permission node] A permission granted for completion. Multiple permissions are space-separated. +# ## permission: 'test.permission' +# # [integer] How much currency to give for completion. (requires an economy plugin) +# ## currency: 0 +# # [integer] How much xp to give to the player for completion. +# ## xp: 0 +# # [List[Text]] Executes the given command upon completion. Prepend with "op" or "console" to run the commands +# as OP or from the Console. Examples: +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +# ## commands: +# ## - 'op: me are the GOD of things' +# ## - 'console: give {party} aweseomestuff 32' +# # reward section to reward the player for completing a repeated challenge (any time after the first). The +# # structure is identical to the 'reward' section. +# repeatReward: +# text: 'Mossy cobblestone' +# items: +# - mossy_cobblestone:16 +# +# ====================================================================================================================== + +# [true/false] Enable the use of the challenges command. +allowChallenges: true + +# [island/player] Whether challenges are tracked per player, or per island +challengeSharing: island + +# [true/false] If true, first time challenge completions are broadcast to the whole server. +broadcastCompletion: true + +# [text] The color/formatting of the broadcast text when showing first time completions. +broadcastText: '&6' + +# [true/false] If true, challenges in higher level ranks require challenges in lower level ranks to be completed. +requirePreviousRank: true + +# [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 easy challenges +# with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. +# A rankLeeway of 0 would require them all. +rankLeeway: 12 + +# [integer] The time in hours before required items reset to default. (only if not specified in the challenges below) +defaultResetInHours: 20 + +# [integer] The default radius in blocks when using onIsland. Can be overridden in the challenges below. +radius: 10 + +# [integer] The maximum number of times a challenge can be completed by default. 0 means unlimited. Can be overridden in the challenge definition below. +repeatLimit: 0 + +# [color code] The color to use for uncompleted challenges in the list. +challengeColor: '&e' + +# [color code] The color to use for completed challenges in the list. (non-repeatable) +finishedColor: '&2' + +# [color code] The color to use for completed challenges in the list. (repeatable) +repeatableColor: '&a' + +# [true/false] If true, enables vault to handle currency rewards. +enableEconomyPlugin: true + +# [true/false] If false, challenges are not reset on island creation (or restart) +resetChallengesOnCreate: true + +# Material to show for locked challenges (i.e. STAINED_GLASS_PANE:14 for a red glass-pane, or 160:14) +lockedDisplayItem: red_stained_glass_pane + +# Material to show for onIsland challenges when locked +ISLAND: + lockedDisplayItem: blue_stained_glass_pane + +# Material to show for islandLevel challenges when locked +ISLAND_LEVEL: + lockedDisplayItem: black_stained_glass_pane + +# Whether to show the name of locked challenges +showLockedChallengeName: true + +# When creating your own challenges you will have +# to uncomment the section below or the default challenges +# will be re-added on every server restart. When altering +# the default challenges this should be fine to leave. +# merge-ignore: +# - 'ranks' +# +# =============================================== +# An explanation to setup your own challenges +# can be found at the bottom of this file. +# =============================================== +ranks: + Tier1: + name: '&7Novice' + displayItem: cyan_terracotta + resetInHours: 20 + challenges: + cobblestonegenerator: + name: '&7Cobble Stone Generator' + description: Mine from a cobblestone generator. + type: onPlayer + requiredItems: + - cobblestone:64;+2 + displayItem: cobblestone + lockedDisplayItem: gray_stained_glass_pane + resetInHours: 12 + reward: + text: 3 leather, 20% chance to get a book + items: + - leather:3 + - '{p=0.2}book:1' + currency: 10 + xp: 10 + commands: + - op:effect give {player} regeneration + repeatReward: + text: 1 leather, 10% chance to get a book + items: + - leather:1 + - '{p=0.1}book:1' + currency: 5 + xp: 5 + applecollector: + name: '&6Apple Collector' + description: Collect apples from trees. + type: onPlayer + requiredItems: + - apple:2;+1 + displayItem: apple + lockedDisplayItem: brown_stained_glass_pane + resetInHours: 6 + reward: + text: 1 of each sapling, (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.2}jungle_sapling:3' + currency: 20 + xp: 20 + repeatReward: + text: 1 of each sapling (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.1}jungle_sapling:3' + currency: 10 + xp: 10 + sugarplanter: + name: '&9Sugar Planter' + type: onIsland + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + requiredBlocks: + - sugar_cane:4 + reward: + text: 4 dirt + items: + - dirt:4 + currency: 20 + xp: 20 + sugarfarmer: + name: '&6Sugar Farmer' + description: Harvest sugarcane from a farm. + type: onPlayer + requiredItems: + - sugar_cane:64;+16 + offset: -1 + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.1}bone:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}dirt:4' + currency: 10 + xp: 10 + melonfarmer: + name: '&6Melon Farmer' + description: Harvest slices of melon from a farm. + type: onPlayer + requiredItems: + - melon_slice:128;+8 + displayItem: melon + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + currency: 10 + xp: 10 + cactusfarmer: + name: '&6Cactus Farmer' + description: Harvest cacti from a farm. + type: onPlayer + requiredItems: + - cactus:64;+16 + displayItem: cactus + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 sand, 20% chance to get a bone + items: + - sand:8 + - '{p=0.2}bone:1' + - '{p=0.1}wooden_hoe:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 sand + items: + - sand:4 + - '{p=0.1}bone:1' + currency: 10 + xp: 10 + pumpkinfarmer: + name: '&6Pumpkin Farmer' + description: Harvest pumpkins from a farm. + type: onPlayer + requiredItems: + - pumpkin:64;+4 + displayItem: pumpkin + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.3}jack_o_lantern:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}jack_o_lantern:1' + currency: 10 + xp: 10 + stonebrickmaker: + name: '&aStone Brick Maker' + description: Make 64 Stone Bricks. + type: onPlayer + requiredItems: + - stone_bricks:64;+8 + - stone_brick_slab:30;+6 + - chiseled_stone_bricks:30;+6 + - stone_brick_stairs:16;+4 + displayItem: stone_bricks + lockedDisplayItem: gray_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 chicken + items: + - redstone_ore:4 + - iron_ore:4 + - chicken_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + novicebuilder: + name: '&7Novice Builder' + description: Reach island level 20. + type: islandLevel + requiredLevel: 20 + displayItem: coal_ore + reward: + text: 8 dirt, 8 sand, 5 emeralds + items: + - dirt:8 + - sand:8 + - emerald:5 + - diamond:1 + currency: 20 + xp: 20 + commands: + - op:effect give {party} regeneration + adeptbuilder: + name: '&aAdept Builder' + description: Reach island level 50. + type: islandLevel + requiredLevel: 50 + displayItem: iron_ore + offset: -1 + reward: + text: 10 obsidian, 2 diamonds, 5 emeralds + items: + - obsidian:10 + - emerald:5 + - diamond:2 + currency: 100 + xp: 100 + expertbuilder: + name: '&eExpert Builder' + description: Reach island level 100. + type: islandLevel + requiredLevel: 100 + displayItem: gold_ore + offset: -1 + reward: + text: 16 dirt, 16 sand, 3 diamonds, 5 emeralds + items: + - dirt:16 + - sand:16 + - emerald:5 + - diamond:3 + currency: 250 + xp: 250 + masterbuilder: + name: '&cMaster Builder' + description: Reach island level 250. + type: islandLevel + requiredLevel: 250 + displayItem: diamond_ore + offset: -1 + reward: + text: 32 dirt, 32 sand, 4 diamonds, 5 emeralds + items: + - dirt:32 + - sand:32 + - emerald:5 + - diamond:4 + currency: 500 + xp: 500 + skylord: + name: '&4Sky Lord' + description: Reach island level 500. + type: islandLevel + requiredLevel: 500 + displayItem: emerald_ore + offset: -1 + reward: + text: 64 dirt, 64 sand, 5 diamond, 5 emeralds + items: + - dirt:64 + - sand:64 + - diamond:5 + - emerald:5 + currency: 1000 + xp: 1000 + Tier2: + name: '&aAdept' + displayItem: lime_terracotta + resetInHours: 20 + requires: + + # means disabled in effect + rankLeeway: 99 + challenges: + - cobblestonegenerator + - novicebuilder + challenges: + lumberjack: + name: '&3Lumberjack' + description: Collect all types of wood logs. + type: onPlayer + requiredItems: + - oak_log:16;+2 + - spruce_log:16;+2 + - birch_log:16;+2 + - jungle_log:16;+2 + - acacia_log:16;+2 + - dark_oak_log:16;+2 + displayItem: oak_log + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 wolf + items: + - redstone_ore:4 + - iron_ore:4 + - wolf_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + shroompicker: + name: '&6Shroom Picker' + description: Collect red and brown mushrooms. + type: onPlayer + requiredItems: + - brown_mushroom:64;+4 + - red_mushroom:64;+4 + displayItem: red_mushroom + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 mycelium, 4 podzol + items: + - mycelium:8 + - podzol:4 + currency: 30 + xp: 30 + repeatReward: + text: 4 mycelium + items: + - mycelium:4 + - '{p=0.02}mycelium:4' + - '{p=0.02}podzol:2' + currency: 15 + xp: 15 + potatofarmer: + name: '&6Potato Farmer' + description: Harvest potato's from a farm. + type: onPlayer + requiredItems: + - potato:64;+16 + displayItem: potato + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 carrot, 4 dirt + items: + - carrot:1 + - dirt:4 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 4 dirt and a baked potato + items: + - dirt:4 + - baked_potato:1 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + carrotfarmer: + name: '&6Carrot Farmer' + description: Harvest carrot's from a farm. + type: onPlayer + requiredItems: + - carrot:64;+16 + displayItem: carrot + lockedDisplayItem: brown_stained_glass_pane + reward: + text: a pig with saddle and a potato + items: + - saddle:1 + - potato:1 + - pig_spawn_egg:1 + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 golden carrot + items: + - golden_carrot:1 + - '{p=0.05}sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + wheatfarmer: + name: '&6Wheat Farmer' + description: Harvest wheat from a farm. + type: onPlayer + requiredItems: + - wheat:64;+16 + displayItem: wheat + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.2}bone:1' + currency: 10 + xp: 10 + monsterfarm: + name: '&5Monster Farm' + description: Build a mob farm and collect mob loot. + type: onPlayer + requiredItems: + - rotten_flesh:64;+4 + - string:32;+2 + - arrow:32;+2 + - bone:32;+2 + - gunpowder:16;+1 + - spider_eye:5 + displayItem: rotten_flesh + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore and 1 flint + items: + - redstone_ore:4 + - iron_ore:4 + - flint:1 + - '{p=0.10}potato:1' + - '{p=0.10}carrot:1' + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore, 1 flint + items: + - redstone_ore:1 + - iron_ore:4 + - flint:1 + - '{p=0.05}potato:1' + - '{p=0.05}carrot:1' + currency: 15 + xp: 15 + homeowner: + name: '&9Home Owner' + description: Build a house with furnishings. + type: onIsland + requiredChallenges: + - stonebrickmaker + requiredBlocks: + - red_bed:1 + - crafting_table:1 + - glass:1 + - oak_door:1 + - furnace:1 + - bookshelf:1 + - torch:1 + lockedDisplayItem: blue_stained_glass_pane + displayItem: oak_door + reward: + text: 4 redstone ore, 5 inksac, 4 iron ore and some seeds + items: + - redstone_ore:4 + - iron_ore:4 + - ink_sac:5 + - beetroot_seeds:1 + currency: 40 + xp: 40 + netherportal: + name: '&9Nether Portal' + description: Build a nether portal on your island. + type: onIsland + requiredChallenges: + - adeptbuilder + - homeowner + requiredBlocks: + - obsidian:10 + - nether_portal:1 + displayItem: obsidian + lockedDisplayItem: blue_stained_glass_pane + reward: + text: 1 iron pickaxe, 1 iron shovel + items: + - iron_shovel:1 + - iron_pickaxe:1 + currency: 40 + xp: 40 + nethermining: + name: '&7Nether Mining' + description: Mine from your Nether island. + type: onPlayer + displayItem: netherrack + lockedDisplayItem: gray_stained_glass_pane + offset: -1 + requiredItems: + - netherrack:64;+2 + - soul_sand:16;+2 + - gravel:16;+2 + - quartz:32;+2 + - glowstone:16;+2 + - coarse_dirt:4;+2 + reward: + text: 1 ghast tear, 1 magic bow + items: + - ghast_tear:1 + - 'bow[enchantments={levels:{infinity:1,unbreaking:3}}]:1' + currency: 40 + xp: 40 + repeatReward: + text: a blaze-rod and a chance of ghast tear + items: + - blaze_rod:1 + - '{p=0.10}ghast_tear:1' + currency: 20 + xp: 20 + Tier3: + name: '&eExpert' + displayItem: yellow_terracotta + resetInHours: 20 + requires: + challenges: + - adeptbuilder + challenges: + toolmaker: + name: '&3Tool Maker' + description: Make all stone tools + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - stone_shovel:1 + - stone_pickaxe:1 + - stone_axe:1 + - stone_hoe:1 + displayItem: stone_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, 1 pig + items: + - redstone_ore:4 + - iron_ore:4 + - pig_spawn_egg:1 + currency: 30 + xp: 30 + sawmill: + name: '&3Saw Mill' + description: Deliver a collection of processed wood + type: onPlayer + offset: -1 + requiredChallenges: + - toolmaker + requiredItems: + - stripped_oak_log:8;+2 + - stripped_spruce_log:8;+2 + - stripped_birch_log:8;+2 + - stripped_jungle_log:8;+2 + - stripped_acacia_log:8;+2 + - stripped_dark_oak_log:8;+2 + displayItem: iron_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, cocoa and a mule + items: + - cocoa_beans:1 + - redstone_ore:4 + - iron_ore:4 + - mule_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.05}gold_ore:1' + currency: 15 + xp: 15 + torchmaker: + name: '&3Torch Maker' + description: Make 128 torches. + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - torch:128;+32 + displayItem: torch + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore + items: + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + expertfarmer: + name: '&6Expert Farmer' + description: Harvest many different farming resources. + type: onPlayer + displayItem: iron_hoe + lockedDisplayItem: brown_stained_glass_pane + requiredChallenges: + - applecollector + - melonfarmer + - pumpkinfarmer + - wheatfarmer + - carrotfarmer + - potatofarmer + - cactusfarmer + - sugarfarmer + - shroompicker + requiredItems: + - melon_slice:256;+2 + - sugar_cane:128;+2 + - wheat:128;+2 + - potato:128;+2 + - carrot:128;+2 + - pumpkin:128;+2 + - cactus:128;+2 + - beetroot:128;+2 + reward: + text: a bucket, cocoa and a cow + items: + - bucket:1 + - cocoa_beans:1 + - cow_spawn_egg:1 + currency: 50 + xp: 50 + repeatReward: + text: a cow + items: + - cow_spawn_egg:1 + currency: 25 + xp: 25 + fisherman: + name: '&5Fisherman' + description: Catch different types of fish. + type: onPlayer + requiredItems: + - cod:5;+1 + - salmon:5;+1 + - pufferfish:3;+1 + - tropical_fish:1;+0 + - ink_sac:5;+2 + displayItem: cod + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 10 lapis blocks, 20 prismarine, kelp, deep-ocean + items: + - lapis_block:10 + - prismarine:20 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: 2 lapis, 5 prismarine, kelp and a chance at prismarine crystals + items: + - lapis_lazuli:2 + - prismarine:5 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + currency: 25 + xp: 25 + woolcollector: + name: '&5Wool Collector' + description: Collect every color of wool. + type: onPlayer + displayItem: white_wool + lockedDisplayItem: purple_stained_glass_pane + requiredChallenges: + - monsterfarmer + requiredItems: + - white_wool:2;+4 + - orange_wool:2;+4 + - magenta_wool:2;+4 + - light_blue_wool:2;+4 + - yellow_wool:2;+4 + - lime_wool:2;+4 + - pink_wool:2;+4 + - gray_wool:2;+4 + - light_gray_wool:2;+4 + - cyan_wool:2;+4 + - purple_wool:2;+4 + - blue_wool:2;+4 + - brown_wool:2;+4 + - green_wool:2;+4 + - red_wool:2;+4 + - black_wool:2;+4 + reward: + text: 2 diamonds, sheep, emerald, flowers + items: + - diamond:2 + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: emerald, sheep, flowers + items: + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + currency: 35 + xp: 35 + maestro: + name: '&5Maestro' + description: Make a jukebox and collect all music discs. + type: onPlayer + requiredItems: + - music_disc_13:1 + - music_disc_cat:1 + - music_disc_blocks:1 + - music_disc_chirp:1 + - music_disc_far:1 + - music_disc_mall:1 + - music_disc_mellohi:1 + - music_disc_stal:1 + - music_disc_strad:1 + - music_disc_ward:1 + - music_disc_11:1 + - music_disc_wait:1 + - jukebox:1 + displayItem: jukebox + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 3 diamonds, 1 gold block, 10 emeralds + items: + - diamond:3 + - emerald:10 + - gold_block:1 + currency: 70 + xp: 70 + repeatReward: + text: 2 gold ore, 1 diamond + items: + - gold_ore:2 + - diamond:1 + - '{p=0.2}diamond:1' + currency: 35 + xp: 35 + ironfarm: + name: '&9Iron Farm' + description: Build an iron-farm. + type: onIsland + displayItem: iron_block + lockedDisplayItem: blue_stained_glass_pane + radius: 50 + requiredChallenges: + - monsterfarm + - applecollector + requiredBlocks: + - oak_door:30 + requiredEntities: + - Villager:10 + - IRON_GOLEM:1 + reward: + text: 2 gold blocks, 1 diamond block + items: + - gold_block:2 + - diamond_block:1 + currency: 500 + xp: 400 + netherfortress: + name: '&9Nether Fortress' + description: Build a netherfortress. + type: onIsland + radius: 50 + requiredBlocks: + - nether_bricks:512 + - nether_brick_slab:64 + - nether_brick_fence:64 + - nether_brick_stairs:64 + - soul_sand:32 + displayItem: nether_brick_fence + lockedDisplayItem: blue_stained_glass_pane + reward: + text: a wither-skull and a blaze rod and a chance of diamonds + items: + - wither_skeleton_skull:1 + - blaze_rod:1 + - '{p=0.05}diamond:3' + - '{p=0.10}diamond:2' + - '{p=0.15}diamond:1' + currency: 40 + xp: 40 + # =============================================== + Tier4: + name: '&cMaster' + displayItem: orange_terracotta + resetInHours: 20 + requires: + + # disabled + rankLeeway: 99 + challenges: + - expertbuilder + challenges: + glassmaker: + name: '&3Glassmaker' + description: Collect every color of stained glass. + type: onPlayer + displayItem: white_stained_glass + lockedDisplayItem: cyan_stained_glass_pane + requiredItems: + - white_stained_glass:8;+2 + - orange_stained_glass:8;+2 + - magenta_stained_glass:8;+2 + - light_blue_stained_glass:8;+2 + - yellow_stained_glass:8;+2 + - lime_stained_glass:8;+2 + - pink_stained_glass:8;+2 + - gray_stained_glass:8;+2 + - light_gray_stained_glass:8;+2 + - cyan_stained_glass:8;+2 + - purple_stained_glass:8;+2 + - blue_stained_glass:8;+2 + - brown_stained_glass:8;+2 + - green_stained_glass:8;+2 + - red_stained_glass:8;+2 + - black_stained_glass:8;+2 + reward: + text: 2 diamonds, 2 disks, 1 emeralds + items: + - diamond:2 + - music_disc_ward:1 + - music_disc_11:1 + - emerald:1 + - sunflower:1 + - lilac:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: 30% chance on 1 or 2 disks, 1 emeralds + items: + - '{p=0.3}music_disc_ward:1' + - '{p=0.3}music_disc_11:1' + - emerald:1 + - sunflower:1 + - lilac:1 + currency: 35 + xp: 35 + carpenter: + name: '&3Carpenter' + description: Collect all types of wood items. + type: onPlayer + requiredItems: + - jungle_stairs:16;+8 + - spruce_door:1;+1 + - dark_oak_fence_gate:2;+2 + - acacia_fence:30;+15 + - ladder:30;+15 + - oak_trapdoor:4;+2 + - oak_pressure_plate:2;+1 + requiredChallenges: + - toolmaker + - lumberjack:2 + displayItem: crafting_table + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: a parrot and a jukebox with some redstone and iron + items: + - parrot_spawn_egg:1 + - jukebox:1 + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: redstone, iron and a slim chance at a parrot + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.25}jukebox:1' + - '{p=0.05}parrot_spawn_egg:1' + currency: 15 + xp: 15 + cookielover: + name: '&eCookie Lover' + description: Make cookies and a bucket of milk. + type: onPlayer + requiredChallenges: + - expertfarmer + requiredItems: + - cookie:128;+4 + - milk_bucket:1 + displayItem: cookie + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 4 redstone ore, clay a bucket and a diamond + items: + - redstone_ore:4 + - clay:5 + - diamond:1 + - bucket:1 + currency: 80 + xp: 80 + repeatReward: + text: iron ore and some clay + items: + - iron_ore:1 + - clay:5 + - bucket:1 + - '{p=0.4}clay:3' + - '{p=0.3}iron_ore:2' + currency: 40 + xp: 40 + deepseafisherman: + name: '&5Deep Sea Fishing' + description: Farm the deep sea + type: onPlayer + requiredItems: + - cod:10;+5 + - salmon:10;+5 + - pufferfish:5;+3 + - tropical_fish:3;+2 + - prismarine_crystals:16;+8 + - prismarine_shard:16;+8 + - dried_kelp_block:64;+32 + - nautilus_shell:1 + displayItem: heart_of_the_sea + lockedDisplayItem: purple_stained_glass_pane + reward: + text: heart-of-the-sea, nautilus shell and a turtle + items: + - nautilus_shell:1 + - heart_of_the_sea:1 + - turtle_spawn_egg:1 + - '{p=0.1}nautilus_shell:1' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: nautilus shell, turtle and a chance of a heart + items: + - nautilus_shell:1 + - turtle_spawn_egg:1 + - '{p=0.05}heart_of_the_sea:1' + - '{p=0.1}nautilus_shell:1' + currency: 25 + xp: 25 + horsingaround: + name: '&6Horsing Around' + description: Get hay bales for the horses. + type: onPlayer + requiredItems: + - hay_block:32;+4 + - lead:8;+2 + - carrot_on_a_stick:1 + - shears:1 + requirecChallenges: + - wheatfarmer + displayItem: hay_block + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 horse, 1 iron horse armor, 5% chance on diamond horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald + items: + - redstone:1 + - emerald:1 + currency: 25 + xp: 25 + slimefarmer: + name: '&5Slime Farmer' + description: Collect slimeballs from slimes. + type: onPlayer + requiredItems: + - slime_ball:64;+4 + displayItem: slime_ball + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 1 diamond, 1 emeralds, swampland + items: + - diamond:1 + - emerald:1 + permission: usb.biome.swamp + currency: 70 + xp: 70 + repeatReward: + text: 1 redstone ore, 1 emeralds + items: + - redstone_ore:1 + - emerald:1 + currency: 35 + xp: 35 + animalfarm: + name: '&9Animal Farm' + description: Create an animal farm. + type: onIsland + displayItem: oak_fence + radius: 40 + requiredChallenges: + - woolcollector + - potatofarmer + - carrotfarmer + requiredEntities: + - Cow:8 + - Pig:8 + - Chicken:16 + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} + reward: + text: 1 horse, 1 iron horse armor, 5% chance horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald, 5% chance horse armor + items: + - redstone:1 + - emerald:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 25 + xp: 25 + witherhunter: + name: '&5Wither Hunter' + description: Collect some Wither Skeleton skulls. + type: onPlayer + requiredChallenges: + - netherfortress + requiredItems: + - wither_skeleton_skull:10;+1 + displayItem: wither_skeleton_skull + lockedDisplayItem: purple_stained_glass_pane + offset: -1 + reward: + text: 5 diamonds, 5% chance of nether star + items: + - diamond:5 + - '{p=0.05}nether_star:1' + currency: 400 + xp: 400 + repeatReward: + text: 2 gold ore, 5% chance of nether star + items: + - gold_ore:2 + - '{p=0.05}nether_star:1' + currency: 20 + xp: 20 + pearlcollector: + name: '&5Pearl Collector' + description: Collect enderpearls from endermen. + type: onPlayer + requiredItems: + - ender_pearl:10;+4 + displayItem: ender_pearl + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 5 gold ore, 1 blaze rod, 1 emerald + items: + - gold_ore:5 + - blaze_rod:1 + - emerald:1 + currency: 70 + xp: 70 + repeatReward: + text: 1 gold ore, 1 blaze rod + items: + - gold_ore:1 + - blaze_rod:1 + currency: 35 + xp: 35 + + # =============================================== + Tier5: + name: '&4Sky Lord' + displayItem: red_terracotta + resetInHours: 48 + requires: + challenges: + - masterbuilder + challenges: + technician: + name: '&3Technician' + description: Collect some of every type of redstone equipment. + type: onPlayer + requiredItems: + - redstone:64;+16 + - redstone_torch:32;+4 + - repeater:5;+1 + - comparator:3;+1 + - piston:2;+1 + - sticky_piston:2;+1 + - lever:1;+1 + - stone_button:1;+1 + - stone_pressure_plate:1;+1 + - hopper:1;+1 + - dispenser:1;+1 + - dropper:1;+1 + - daylight_detector:1;+1 + displayItem: redstone + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: some snow, ice and packed ice + items: + - snow_block:4 + - ice:8 + - packed_ice:8 + - redstone_block:64 + currency: 70 + xp: 70 + repeatReward: + text: a stack of redstone blocks and some ice + items: + - redstone_block:64 + - ice:4 + - packed_ice:1 + currency: 35 + xp: 35 + emeraldcollector: + name: '&5Emerald Collector' + description: Collect emeralds. + type: onPlayer + requiredItems: + - emerald:60;+10 + displayItem: emerald + lockedDisplayItem: purple_stained_glass_pane + reward: + text: a full set of diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 70 + xp: 70 + repeatReward: + text: full diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 35 + xp: 35 + topchef: + name: '&eTop Chef' + description: Collect every kind of edible food. + type: onPlayer + requiredItems: + - baked_potato:1 + - bread:1 + - cake:1 + - cooked_chicken:1 + - cooked_cod:1 + - cooked_salmon:1 + - tropical_fish:1 + - cooked_porkchop:1 + - cookie:1 + - golden_apple:1 + - golden_carrot:1 + - mushroom_stew:1 + - pumpkin_pie:1 + - cooked_beef:1 + - melon:1 + - carrot:1 + requiredChallenges: + - expertfarmer + - fisherman + - cookielover + displayItem: carrot + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 diamond, 1 mooshroom + items: + - diamond:2 + - mooshroom_spawn_egg:1 + currency: 80 + xp: 80 + repeatReward: + text: 1 diamond, 1 mooshroom + items: + - diamond:1 + - mooshroom_spawn_egg:1 + currency: 40 + xp: 40 + tajmahal: + name: '&9Taj Mahal' + description: Build a temple of quartz + type: onIsland + radius: 30 + displayItem: quartz_block + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - nethermining + requiredBlocks: + - quartz_block:512 + - chiseled_quartz_block:64 + - quartz_pillar:128 + - quartz_stairs:64 + - quartz_slab:192 + reward: + text: 3 end-portal frames, red sand + items: + - end_portal_frame:3 + - red_sand:64 + currency: 1000 + xp: 500 + greatpyramid: + name: '&9Great Pyramid' + description: Build a pyramid of sandstone + type: onIsland + radius: 30 + displayItem: sandstone + lockedDisplayItem: blue_stained_glass_pane + requiredBlocks: + - sandstone:512 + - chiseled_sandstone:64 + - smooth_sandstone:128 + - sandstone_stairs:64 + - sandstone_slab:192 + - red_sandstone:16 + reward: + text: 3 end-portal frames, 3 diamonds, bow + items: + - end_portal_frame:3 + - diamond:3 + - 'bow[enchantments={levels:{infinity:1,power:5,unbreaking:3}}]:1' + currency: 1000 + xp: 500 + poseidonshalls: + name: '&9Poseidon''s Halls' + description: Build the halls of Poseidon + type: onIsland + radius: 50 + displayItem: prismarine + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - deepseafisherman + requiredBlocks: + - prismarine:512 + - prismarine_bricks:128 + - dark_prismarine:64 + - sea_lantern:32 + - conduit:1 + - flower_pot:16 + - vine:128 + - poppy:10 + - blue_orchid:10 + - allium:10 + - azure_bluet:10 + - red_tulip:10 + - orange_tulip:10 + - white_tulip:10 + - pink_tulip:10 + - oxeye_daisy:10 + - sunflower:10 + - lilac:10 + - rose_bush:10 + - peony:10 + reward: + text: 3 end-portal frames, 5 diamonds + items: + - end_portal_frame:3 + - diamond:5 + currency: 1000 + xp: 500 + beaconator: + name: '&9Beaconator' + description: Build a very expensive beacon. + type: onIsland + radius: 15 + displayItem: beacon + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - netherfortress + - ironfarm + - maestro + - witherhunter + requiredBlocks: + - beacon:1 + - diamond_block:1 + - emerald_block:8 + - gold_block:25 + - iron_block:49 + reward: + items: + - end_portal_frame:3 + - 'diamond_sword[enchantments={levels:{fire_aspect:1,sharpness:5,unbreaking:3}}]:1' + text: some end-portal-pieces and a magic diamond sword + currency: 4000 + xp: 1000 + endportal: + name: '&9End Portal' + description: Build and activate an end-portal. + type: onIsland + radius: 15 + displayItem: end_portal_frame + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - beaconator + - tajmahal + - poseidonshalls + - greatpyramid + requiredBlocks: + - end_portal_frame:12 + - end_portal:9 + reward: + text: 5 diamonds and some nice boots + items: + - diamond:5 + - 'diamond_boots[enchantments={levels:{blast_protection:4,feather_falling:4,protection:4}}]:1' + currency: 4000 + xp: 1000 + + # =============================================== + Tier6: + name: '&aWorld Foods' + displayItem: light_gray_terracotta + resetInHours: 20 + requires: + challenges: + - masterbuilder + - topchef + challenges: + fishandchips: + name: '&eFish & Chips' + description: Create the famous English Fish & Chips. + type: onPlayer + requiredItems: + - cooked_cod:32;+8 + - baked_potato:32;+8 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 16 baked potatos, 1 disk, 4 emerald + items: + - baked_potato:16 + - music_disc_13:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + smorrebrod: + name: '&eSmørrebrød' + description: Create the famous Danish smørrebrød. + type: onPlayer + requiredItems: + - bread:16;+4 + - cooked_salmon:8;+4 + - tropical_fish:2;+1 + - cooked_porkchop:8;+4 + - cooked_beef:8;+4 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 rod, 2 name tags, 2 ocelots + items: + - fishing_rod:1 + - name_tag:2 + - ocelot_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + repeatReward: + text: 1 emerald + items: + - emerald:1 + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + hutspot: + name: '&eHutspot' + description: Create the famous Dutch hutspot. + type: onPlayer + requiredItems: + - potato:64;+8 + - carrot:64;+8 + lockedDisplayItem: yellow_stained_glass_pane + displayItem: golden_carrot + reward: + text: 1 golden carrot, 1 disk, 4 emerald + items: + - golden_carrot:1 + - music_disc_cat:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_cat:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + apfelstrudel: + name: '&eApfelstrudele' + description: Create the famous German apfelstrudel. + type: onPlayer + requiredItems: + - apple:8;+5 + - wheat:16;+5 + - sugar:16;+5 + - milk_bucket:1 + displayItem: golden_apple + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_blocks:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_blocks:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + brownies: + name: '&eBrownies' + description: Create the famous American brownies. + type: onPlayer + requiredItems: + - wheat:16;+5 + - sugar:16;+5 + - egg:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: dark_oak_slab + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_far:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_far:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + pastafunghi: + name: '&ePasta Funghi' + description: Create the famous Italian Pasta Funghi. + type: onPlayer + requiredItems: + - wheat:32;+8 + - egg:32;+8 + - brown_mushroom:16;+4 + - red_mushroom:16;+4 + - milk_bucket:1 + displayItem: red_mushroom_block + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 rabbits, 1 bucket + items: + - bucket:1 + - rabbit_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + chocolate: + name: '&eBelgian chocolate' + description: Create the famous belgian chocolate. + type: onPlayer + requiredItems: + - sugar:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: pig_spawn_egg + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emeralds + items: + - bucket:1 + - emerald:4 + - music_disc_mall:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_mall:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + baker: + name: '&ePâtisserie' + description: Bake cakes, pumpkin pies, and cookies. + type: onPlayer + requiredItems: + - cake:5;+1 + - pumpkin_pie:5;+1 + - cookie:128;+4 + displayItem: cake + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 5 gold ore, 1 diamond + items: + - gold_ore:5 + - diamond:1 + currency: 80 + xp: 80 + repeatReward: + text: 2 iron ore, 1 gold ore + items: + - iron_ore:2 + - gold_ore:1 + currency: 40 + xp: 40 + +# DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen! +version: 108 diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-block-challenges.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-block-challenges.yml new file mode 100644 index 000000000..e97fca755 --- /dev/null +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-block-challenges.yml @@ -0,0 +1,1790 @@ +# ====================================================================================================================== +# +# Here follows the format and explanation for the challenge group and challenges setup. The single commented (#) are the +# most used settings while the double commented (##) are optional if you like to use those settings. +# +# Item type format +# Item types are defined as in the minecraft /give command, i.e. with their minecraft key and possible components in +# square brackets. For example, 'minecraft:diamond_sword[damage=42]'. Refer to the Minecraft wiki for more information: +# https://minecraft.wiki/w/Data_component_format. You can also use the command '/usb iteminfo' to get the information. +# +# This item type is supplemented with additional information depending on where it is used: +# +# display-item: +# An item to be displayed in a GUI. It only defines the item type as above, without any additional information. +# For example: 'cobblestone', 'minecraft:stone', 'diamond_sword[damage=42]'. +# +# item-requirement: :[;+] +# An item requirement for a challenge. The amount is the number of items required. The optional + is the number +# of items to add to the required amount for each repeat of the challenge. For example, 'cobblestone:64;+16' would +# require 64 cobblestone for the first completion and 80 cobblestone for the second completion. Other options are +# -, *, and / for subtraction, multiplication, and division, respectively. For example, 'cobblestone:64;*2' would +# require 64 cobblestone for the first completion, 128 cobblestone for the second completion, and 256 cobblestone for +# the third completion. +# +# item-reward: [{p=}]: +# An item reward for a challenge. The amount is the number of items to give. The optional {p=} is the +# probability of the item being given. For example, 'cobblestone:64' would give 64 cobblestone every time the challenge +# is completed, while '{p=0.1}cobblestone:64' would give 64 cobblestone 10% of the time. +# +# ====================================================================================================================== +# All challenges are defined in the ranks section. Each rank is a tier of challenges that players can complete. +# +# ranks: +# # [text] name of the challenge Rank. +# TierX: +# # [text] The name of the challenge rank that shows when you do /challenges (supports capitals and color codes). +# name: '&aCustom Challenges rank name' +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: 'cyan_terracotta' +# # [integer] The time in hours before required items reset to default (this overwrites the main reset time) +# resetInHours: 20 +# # These requirements controls when a challenge group will be available to a player. +# requires: +# # [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, +# if you have 4 challenges with a rankLeeway of 1, a player would only need to complete 3 to advance to +# the next rank. A rankLeeway of 0 would require them all. +# rankLeeway: 8 +# # [List[text]] Challenges that have to be completed before this group will available to a player. +# challenges: +# - a challenge name +# ====================================================================================================================== +# challenges: +# # [text] The name of the challenge. All challenge names should be lower-case. +# defaultchallenge: +# # [text] The name of the challenge that shows in /challenges (this supports capitals and color codes). +# name: '&a Default Challenge' +# # [text] The descriptions players see when they do /challenges +# description: +# # [onIsland/onPlayer/islandLevel] This defines whether the required blocks/items should be in the player's +# # inventory or on their island. When using onIsland, the player must within 10 blocks from the required blocks +# # on his island. When using islandLevel, the 'requiredItems' field should be the island level required. The +# # player must use /island level first to update their level. +# type: onPlayer +# ## type: islandLevel +# ## type: onIsland +# # [integer] Overrides the default radius of 10 blocks when using onIsland. +# ## radius: 20 +# # [List[item-requirement] The items required to complete the challenge. +# requiredItems: +# - stone:64;+16 +# - cobblestone:64;+16 +# # [true/false] If the challenge can be repeated or not. +# ## repeatable: true +# # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. +# # A value of 0 means unlimited repeats. +# ## repeatLimit: 5 +# # [display-item] The item to be displayed in the challenge menu for completed challenges. +# displayItem: cobblestone +# # [integer] The time in hours before required items reset to default (overwrites the main and rank defaults). +# ## resetInHours: 4 +# # [true/false] Take required items on completing a challenge. +# ## takeItems: true +# # The rewards players get for completing the challenge +# reward: +# # [text] Description of the reward. +# text: 'Mossy cobblestone and an iron pickaxe with unbreaking 1' +# # [List[item-requirement]] A list of items given to the player for completing the challenge. +# items: +# - mossy_cobblestone:16 +# - iron_pickaxe[enchantments={levels:{unbreaking:1}}]:1 +# # [permission node] A permission granted for completion. Multiple permissions are space-separated. +# ## permission: 'test.permission' +# # [integer] How much currency to give for completion. (requires an economy plugin) +# ## currency: 0 +# # [integer] How much xp to give to the player for completion. +# ## xp: 0 +# # [List[Text]] Executes the given command upon completion. Prepend with "op" or "console" to run the commands +# as OP or from the Console. Examples: +# # Possible command arguments are: +# # {player} - The name of the player +# # {playerName} - The display name of the player +# # {challenge} - The name of the challenge +# # {position} - The position of the player +# # {party} - Execute the command once for each member of the party (substituting the name) +# ## commands: +# ## - 'op: me are the GOD of things' +# ## - 'console: give {party} aweseomestuff 32' +# # reward section to reward the player for completing a repeated challenge (any time after the first). The +# # structure is identical to the 'reward' section. +# repeatReward: +# text: 'Mossy cobblestone' +# items: +# - mossy_cobblestone:16 +# +# ====================================================================================================================== + +# [true/false] Enable the use of the challenges command. +allowChallenges: true + +# [island/player] Whether challenges are tracked per player, or per island +challengeSharing: island + +# [true/false] If true, first time challenge completions are broadcast to the whole server. +broadcastCompletion: true + +# [text] The color/formatting of the broadcast text when showing first time completions. +broadcastText: '&6' + +# [true/false] If true, challenges in higher level ranks require challenges in lower level ranks to be completed. +requirePreviousRank: true + +# [integer] The number of tasks per rank that can be left uncompleted to advance to the next rank. For example, if you have 4 easy challenges +# with a rankLeeway of 1, a player would only need to complete 3 to advance to the next rank. +# A rankLeeway of 0 would require them all. +rankLeeway: 12 + +# [integer] The time in hours before required items reset to default. (only if not specified in the challenges below) +defaultResetInHours: 20 + +# [integer] The default radius in blocks when using onIsland. Can be overridden in the challenges below. +radius: 10 + +# [integer] The maximum number of times a challenge can be completed by default. 0 means unlimited. Can be overridden in the challenge definition below. +repeatLimit: 0 + +# [color code] The color to use for uncompleted challenges in the list. +challengeColor: '&e' + +# [color code] The color to use for completed challenges in the list. (non-repeatable) +finishedColor: '&2' + +# [color code] The color to use for completed challenges in the list. (repeatable) +repeatableColor: '&a' + +# [true/false] If true, enables vault to handle currency rewards. +enableEconomyPlugin: true + +# [true/false] If false, challenges are not reset on island creation (or restart) +resetChallengesOnCreate: true + +# Material to show for locked challenges (i.e. STAINED_GLASS_PANE:14 for a red glass-pane, or 160:14) +lockedDisplayItem: red_stained_glass_pane + +# Material to show for onIsland challenges when locked +ISLAND: + lockedDisplayItem: blue_stained_glass_pane + +# Material to show for islandLevel challenges when locked +ISLAND_LEVEL: + lockedDisplayItem: black_stained_glass_pane + +# Whether to show the name of locked challenges +showLockedChallengeName: true + +# When creating your own challenges you will have +# to uncomment the section below or the default challenges +# will be re-added on every server restart. When altering +# the default challenges this should be fine to leave. +# merge-ignore: +# - 'ranks' +# +# =============================================== +# An explanation to setup your own challenges +# can be found at the bottom of this file. +# =============================================== +ranks: + Tier1: + name: '&7Novice' + displayItem: cyan_terracotta + resetInHours: 20 + challenges: + cobblestonegenerator: + name: '&7Cobble Stone Generator' + description: Mine from a cobblestone generator. + type: onPlayer + requiredItems: + - cobblestone:64;+2 + displayItem: cobblestone + lockedDisplayItem: gray_stained_glass_pane + resetInHours: 12 + reward: + text: 3 leather, 20% chance to get a book + items: + - leather:3 + - '{p=0.2}book:1' + currency: 10 + xp: 10 + commands: + - op:effect give {player} regeneration + repeatReward: + text: 1 leather, 10% chance to get a book + items: + - leather:1 + - '{p=0.1}book:1' + currency: 5 + xp: 5 + applecollector: + name: '&6Apple Collector' + description: Collect apples from trees. + type: onPlayer + requiredItems: + - apple:2;+1 + displayItem: apple + lockedDisplayItem: brown_stained_glass_pane + resetInHours: 6 + reward: + text: 1 of each sapling, (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.2}jungle_sapling:3' + currency: 20 + xp: 20 + repeatReward: + text: 1 of each sapling (4 dark oak) + items: + - oak_sapling:1 + - spruce_sapling:1 + - birch_sapling:1 + - jungle_sapling:1 + - acacia_sapling:1 + - dark_oak_sapling:4 + - '{p=0.1}jungle_sapling:3' + currency: 10 + xp: 10 + sugarplanter: + name: '&9Sugar Planter' + type: onIsland + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + requiredItems: + - sugar_cane:4 + reward: + text: 4 dirt + items: + - dirt:4 + currency: 20 + xp: 20 + sugarfarmer: + name: '&6Sugar Farmer' + description: Harvest sugarcane from a farm. + type: onPlayer + requiredItems: + - sugar_cane:64;+16 + offset: -1 + displayItem: sugar_cane + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.1}bone:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}dirt:4' + currency: 10 + xp: 10 + melonfarmer: + name: '&6Melon Farmer' + description: Harvest slices of melon from a farm. + type: onPlayer + requiredItems: + - melon_slice:128;+8 + displayItem: melon + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + currency: 10 + xp: 10 + cactusfarmer: + name: '&6Cactus Farmer' + description: Harvest cacti from a farm. + type: onPlayer + requiredItems: + - cactus:64;+16 + displayItem: cactus + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 sand, 20% chance to get a bone + items: + - sand:8 + - '{p=0.2}bone:1' + - '{p=0.1}wooden_hoe:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 sand + items: + - sand:4 + - '{p=0.1}bone:1' + currency: 10 + xp: 10 + pumpkinfarmer: + name: '&6Pumpkin Farmer' + description: Harvest pumpkins from a farm. + type: onPlayer + requiredItems: + - pumpkin:64;+4 + displayItem: pumpkin + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + - '{p=0.3}jack_o_lantern:1' + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.05}jack_o_lantern:1' + currency: 10 + xp: 10 + stonebrickmaker: + name: '&aStone Brick Maker' + description: Make 64 Stone Bricks. + type: onPlayer + requiredItems: + - stone_bricks:64;+8 + - stone_brick_slab:30;+6 + - chiseled_stone_bricks:30;+6 + - stone_brick_stairs:16;+4 + displayItem: stone_bricks + lockedDisplayItem: gray_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 chicken + items: + - redstone_ore:4 + - iron_ore:4 + - chicken_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + novicebuilder: + name: '&7Novice Builder' + description: Reach island level 20. + type: islandLevel + requiredLevel: 20 + displayItem: coal_ore + reward: + text: 8 dirt, 8 sand, 5 emeralds + items: + - dirt:8 + - sand:8 + - emerald:5 + - diamond:1 + currency: 20 + xp: 20 + commands: + - op:effect give {party} regeneration + adeptbuilder: + name: '&aAdept Builder' + description: Reach island level 50. + type: islandLevel + requiredLevel: 50 + displayItem: iron_ore + offset: -1 + reward: + text: 10 obsidian, 2 diamonds, 5 emeralds + items: + - obsidian:10 + - emerald:5 + - diamond:2 + currency: 100 + xp: 100 + expertbuilder: + name: '&eExpert Builder' + description: Reach island level 100. + type: islandLevel + requiredLevel: 100 + displayItem: gold_ore + offset: -1 + reward: + text: 16 dirt, 16 sand, 3 diamonds, 5 emeralds + items: + - dirt:16 + - sand:16 + - emerald:5 + - diamond:3 + currency: 250 + xp: 250 + masterbuilder: + name: '&cMaster Builder' + description: Reach island level 250. + type: islandLevel + requiredLevel: 250 + displayItem: diamond_ore + offset: -1 + reward: + text: 32 dirt, 32 sand, 4 diamonds, 5 emeralds + items: + - dirt:32 + - sand:32 + - emerald:5 + - diamond:4 + currency: 500 + xp: 500 + skylord: + name: '&4Sky Lord' + description: Reach island level 500. + type: islandLevel + requiredLevel: 500 + displayItem: emerald_ore + offset: -1 + reward: + text: 64 dirt, 64 sand, 5 diamond, 5 emeralds + items: + - dirt:64 + - sand:64 + - diamond:5 + - emerald:5 + currency: 1000 + xp: 1000 + Tier2: + name: '&aAdept' + displayItem: lime_terracotta + resetInHours: 20 + requires: + + # means disabled in effect + rankLeeway: 99 + challenges: + - cobblestonegenerator + - novicebuilder + challenges: + lumberjack: + name: '&3Lumberjack' + description: Collect all types of wood logs. + type: onPlayer + requiredItems: + - oak_log:16;+2 + - spruce_log:16;+2 + - birch_log:16;+2 + - jungle_log:16;+2 + - acacia_log:16;+2 + - dark_oak_log:16;+2 + displayItem: oak_log + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore, 1 wolf + items: + - redstone_ore:4 + - iron_ore:4 + - wolf_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + shroompicker: + name: '&6Shroom Picker' + description: Collect red and brown mushrooms. + type: onPlayer + requiredItems: + - brown_mushroom:64;+4 + - red_mushroom:64;+4 + displayItem: red_mushroom + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 mycelium, 4 podzol + items: + - mycelium:8 + - podzol:4 + currency: 30 + xp: 30 + repeatReward: + text: 4 mycelium + items: + - mycelium:4 + - '{p=0.02}mycelium:4' + - '{p=0.02}podzol:2' + currency: 15 + xp: 15 + potatofarmer: + name: '&6Potato Farmer' + description: Harvest potato's from a farm. + type: onPlayer + requiredItems: + - potato:64;+16 + displayItem: potato + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 carrot, 4 dirt + items: + - carrot:1 + - dirt:4 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 4 dirt and a baked potato + items: + - dirt:4 + - baked_potato:1 + - '{p=0.10}beetroot_seeds:1' + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + carrotfarmer: + name: '&6Carrot Farmer' + description: Harvest carrot's from a farm. + type: onPlayer + requiredItems: + - carrot:64;+16 + displayItem: carrot + lockedDisplayItem: brown_stained_glass_pane + reward: + text: a pig with saddle and a potato + items: + - saddle:1 + - potato:1 + - pig_spawn_egg:1 + - '{p=0.05}red_sand:1' + - '{p=0.01}diamond:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 golden carrot + items: + - golden_carrot:1 + - '{p=0.05}sand:1' + - '{p=0.01}diamond:1' + currency: 25 + xp: 25 + wheatfarmer: + name: '&6Wheat Farmer' + description: Harvest wheat from a farm. + type: onPlayer + requiredItems: + - wheat:64;+16 + displayItem: wheat + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 8 dirt + items: + - dirt:8 + currency: 20 + xp: 20 + repeatReward: + text: 4 dirt + items: + - dirt:4 + - '{p=0.2}bone:1' + currency: 10 + xp: 10 + monsterfarm: + name: '&5Monster Farm' + description: Build a mob farm and collect mob loot. + type: onPlayer + requiredItems: + - rotten_flesh:64;+4 + - string:32;+2 + - arrow:32;+2 + - bone:32;+2 + - gunpowder:16;+1 + - spider_eye:5 + displayItem: rotten_flesh + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore and 1 flint + items: + - redstone_ore:4 + - iron_ore:4 + - flint:1 + - '{p=0.10}potato:1' + - '{p=0.10}carrot:1' + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore, 1 flint + items: + - redstone_ore:1 + - iron_ore:4 + - flint:1 + - '{p=0.05}potato:1' + - '{p=0.05}carrot:1' + currency: 15 + xp: 15 + homeowner: + name: '&9Home Owner' + description: Build a house with furnishings. + type: onIsland + requiredChallenges: + - stonebrickmaker + requiredItems: + - red_bed:1 + - crafting_table:1 + - glass:1 + - oak_door:1 + - furnace:1 + - bookshelf:1 + - torch:1 + lockedDisplayItem: blue_stained_glass_pane + displayItem: oak_door + reward: + text: 4 redstone ore, 5 inksac, 4 iron ore and some seeds + items: + - redstone_ore:4 + - iron_ore:4 + - ink_sac:5 + - beetroot_seeds:1 + currency: 40 + xp: 40 + netherportal: + name: '&9Nether Portal' + description: Build a nether portal on your island. + type: onIsland + requiredChallenges: + - adeptbuilder + - homeowner + requiredItems: + - obsidian:10 + - nether_portal:1 + displayItem: obsidian + lockedDisplayItem: blue_stained_glass_pane + reward: + text: 1 iron pickaxe, 1 iron shovel + items: + - iron_shovel:1 + - iron_pickaxe:1 + currency: 40 + xp: 40 + nethermining: + name: '&7Nether Mining' + description: Mine from your Nether island. + type: onPlayer + displayItem: netherrack + lockedDisplayItem: gray_stained_glass_pane + offset: -1 + requiredItems: + - netherrack:64;+2 + - soul_sand:16;+2 + - gravel:16;+2 + - quartz:32;+2 + - glowstone:16;+2 + - coarse_dirt:4;+2 + reward: + text: 1 ghast tear, 1 magic bow + items: + - ghast_tear:1 + - 'bow[enchantments={levels:{infinity:1,unbreaking:3}}]:1' + currency: 40 + xp: 40 + repeatReward: + text: a blaze-rod and a chance of ghast tear + items: + - blaze_rod:1 + - '{p=0.10}ghast_tear:1' + currency: 20 + xp: 20 + Tier3: + name: '&eExpert' + displayItem: yellow_terracotta + resetInHours: 20 + requires: + challenges: + - adeptbuilder + challenges: + toolmaker: + name: '&3Tool Maker' + description: Make all stone tools + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - stone_shovel:1 + - stone_pickaxe:1 + - stone_axe:1 + - stone_hoe:1 + displayItem: stone_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, 1 pig + items: + - redstone_ore:4 + - iron_ore:4 + - pig_spawn_egg:1 + currency: 30 + xp: 30 + sawmill: + name: '&3Saw Mill' + description: Deliver a collection of processed wood + type: onPlayer + offset: -1 + requiredChallenges: + - toolmaker + requiredItems: + - stripped_oak_log:8;+2 + - stripped_spruce_log:8;+2 + - stripped_birch_log:8;+2 + - stripped_jungle_log:8;+2 + - stripped_acacia_log:8;+2 + - stripped_dark_oak_log:8;+2 + displayItem: iron_axe + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron, cocoa and a mule + items: + - cocoa_beans:1 + - redstone_ore:4 + - iron_ore:4 + - mule_spawn_egg:1 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.05}gold_ore:1' + currency: 15 + xp: 15 + torchmaker: + name: '&3Torch Maker' + description: Make 128 torches. + type: onPlayer + requiredChallenges: + - lumberjack + requiredItems: + - torch:128;+32 + displayItem: torch + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: 4 redstone ore, 4 iron ore + items: + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: 1 redstone ore, 1 iron ore + items: + - redstone_ore:1 + - iron_ore:1 + currency: 15 + xp: 15 + expertfarmer: + name: '&6Expert Farmer' + description: Harvest many different farming resources. + type: onPlayer + displayItem: iron_hoe + lockedDisplayItem: brown_stained_glass_pane + requiredChallenges: + - applecollector + - melonfarmer + - pumpkinfarmer + - wheatfarmer + - carrotfarmer + - potatofarmer + - cactusfarmer + - sugarfarmer + - shroompicker + requiredItems: + - melon_slice:256;+2 + - sugar_cane:128;+2 + - wheat:128;+2 + - potato:128;+2 + - carrot:128;+2 + - pumpkin:128;+2 + - cactus:128;+2 + - beetroot:128;+2 + reward: + text: a bucket, cocoa and a cow + items: + - bucket:1 + - cocoa_beans:1 + - cow_spawn_egg:1 + currency: 50 + xp: 50 + repeatReward: + text: a cow + items: + - cow_spawn_egg:1 + currency: 25 + xp: 25 + fisherman: + name: '&5Fisherman' + description: Catch different types of fish. + type: onPlayer + requiredItems: + - cod:5;+1 + - salmon:5;+1 + - pufferfish:3;+1 + - tropical_fish:1;+0 + - ink_sac:5;+2 + displayItem: cod + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 10 lapis blocks, 20 prismarine, kelp, deep-ocean + items: + - lapis_block:10 + - prismarine:20 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: 2 lapis, 5 prismarine, kelp and a chance at prismarine crystals + items: + - lapis_lazuli:2 + - prismarine:5 + - kelp:1 + - '{p=0.20}prismarine_crystals:5' + currency: 25 + xp: 25 + woolcollector: + name: '&5Wool Collector' + description: Collect every color of wool. + type: onPlayer + displayItem: white_wool + lockedDisplayItem: purple_stained_glass_pane + requiredChallenges: + - monsterfarmer + requiredItems: + - white_wool:2;+4 + - orange_wool:2;+4 + - magenta_wool:2;+4 + - light_blue_wool:2;+4 + - yellow_wool:2;+4 + - lime_wool:2;+4 + - pink_wool:2;+4 + - gray_wool:2;+4 + - light_gray_wool:2;+4 + - cyan_wool:2;+4 + - purple_wool:2;+4 + - blue_wool:2;+4 + - brown_wool:2;+4 + - green_wool:2;+4 + - red_wool:2;+4 + - black_wool:2;+4 + reward: + text: 2 diamonds, sheep, emerald, flowers + items: + - diamond:2 + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: emerald, sheep, flowers + items: + - emerald:1 + - sheep_spawn_egg:1 + - rose_bush:1 + - peony:1 + currency: 35 + xp: 35 + maestro: + name: '&5Maestro' + description: Make a jukebox and collect all music discs. + type: onPlayer + requiredItems: + - music_disc_13:1 + - music_disc_cat:1 + - music_disc_blocks:1 + - music_disc_chirp:1 + - music_disc_far:1 + - music_disc_mall:1 + - music_disc_mellohi:1 + - music_disc_stal:1 + - music_disc_strad:1 + - music_disc_ward:1 + - music_disc_11:1 + - music_disc_wait:1 + - jukebox:1 + displayItem: jukebox + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 3 diamonds, 1 gold block, 10 emeralds + items: + - diamond:3 + - emerald:10 + - gold_block:1 + currency: 70 + xp: 70 + repeatReward: + text: 2 gold ore, 1 diamond + items: + - gold_ore:2 + - diamond:1 + - '{p=0.2}diamond:1' + currency: 35 + xp: 35 + ironfarm: + name: '&9Iron Farm' + description: Build an iron-farm. + type: onIsland + displayItem: iron_block + lockedDisplayItem: blue_stained_glass_pane + radius: 50 + requiredChallenges: + - monsterfarm + - applecollector + requiredItems: + - oak_door:30 + requiredEntities: + - Villager:10 + - IRON_GOLEM:1 + reward: + text: 2 gold blocks, 1 diamond block + items: + - gold_block:2 + - diamond_block:1 + currency: 500 + xp: 400 + netherfortress: + name: '&9Nether Fortress' + description: Build a netherfortress. + type: onIsland + radius: 50 + requiredItems: + - nether_bricks:512 + - nether_brick_slab:64 + - nether_brick_fence:64 + - nether_brick_stairs:64 + - soul_sand:32 + displayItem: nether_brick_fence + lockedDisplayItem: blue_stained_glass_pane + reward: + text: a wither-skull and a blaze rod and a chance of diamonds + items: + - wither_skeleton_skull:1 + - blaze_rod:1 + - '{p=0.05}diamond:3' + - '{p=0.10}diamond:2' + - '{p=0.15}diamond:1' + currency: 40 + xp: 40 + # =============================================== + Tier4: + name: '&cMaster' + displayItem: orange_terracotta + resetInHours: 20 + requires: + + # disabled + rankLeeway: 99 + challenges: + - expertbuilder + challenges: + glassmaker: + name: '&3Glassmaker' + description: Collect every color of stained glass. + type: onPlayer + displayItem: white_stained_glass + lockedDisplayItem: cyan_stained_glass_pane + requiredItems: + - white_stained_glass:8;+2 + - orange_stained_glass:8;+2 + - magenta_stained_glass:8;+2 + - light_blue_stained_glass:8;+2 + - yellow_stained_glass:8;+2 + - lime_stained_glass:8;+2 + - pink_stained_glass:8;+2 + - gray_stained_glass:8;+2 + - light_gray_stained_glass:8;+2 + - cyan_stained_glass:8;+2 + - purple_stained_glass:8;+2 + - blue_stained_glass:8;+2 + - brown_stained_glass:8;+2 + - green_stained_glass:8;+2 + - red_stained_glass:8;+2 + - black_stained_glass:8;+2 + reward: + text: 2 diamonds, 2 disks, 1 emeralds + items: + - diamond:2 + - music_disc_ward:1 + - music_disc_11:1 + - emerald:1 + - sunflower:1 + - lilac:1 + permission: usb.biome.flower_forest + currency: 70 + xp: 70 + repeatReward: + text: 30% chance on 1 or 2 disks, 1 emeralds + items: + - '{p=0.3}music_disc_ward:1' + - '{p=0.3}music_disc_11:1' + - emerald:1 + - sunflower:1 + - lilac:1 + currency: 35 + xp: 35 + carpenter: + name: '&3Carpenter' + description: Collect all types of wood items. + type: onPlayer + requiredItems: + - jungle_stairs:16;+8 + - spruce_door:1;+1 + - dark_oak_fence_gate:2;+2 + - acacia_fence:30;+15 + - ladder:30;+15 + - oak_trapdoor:4;+2 + - oak_pressure_plate:2;+1 + requiredChallenges: + - toolmaker + - lumberjack:2 + displayItem: crafting_table + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: a parrot and a jukebox with some redstone and iron + items: + - parrot_spawn_egg:1 + - jukebox:1 + - redstone_ore:4 + - iron_ore:4 + currency: 30 + xp: 30 + repeatReward: + text: redstone, iron and a slim chance at a parrot + items: + - redstone_ore:1 + - iron_ore:1 + - '{p=0.25}jukebox:1' + - '{p=0.05}parrot_spawn_egg:1' + currency: 15 + xp: 15 + cookielover: + name: '&eCookie Lover' + description: Make cookies and a bucket of milk. + type: onPlayer + requiredChallenges: + - expertfarmer + requiredItems: + - cookie:128;+4 + - milk_bucket:1 + displayItem: cookie + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 4 redstone ore, clay a bucket and a diamond + items: + - redstone_ore:4 + - clay:5 + - diamond:1 + - bucket:1 + currency: 80 + xp: 80 + repeatReward: + text: iron ore and some clay + items: + - iron_ore:1 + - clay:5 + - bucket:1 + - '{p=0.4}clay:3' + - '{p=0.3}iron_ore:2' + currency: 40 + xp: 40 + deepseafisherman: + name: '&5Deep Sea Fishing' + description: Farm the deep sea + type: onPlayer + requiredItems: + - cod:10;+5 + - salmon:10;+5 + - pufferfish:5;+3 + - tropical_fish:3;+2 + - prismarine_crystals:16;+8 + - prismarine_shard:16;+8 + - dried_kelp_block:64;+32 + - nautilus_shell:1 + displayItem: heart_of_the_sea + lockedDisplayItem: purple_stained_glass_pane + reward: + text: heart-of-the-sea, nautilus shell and a turtle + items: + - nautilus_shell:1 + - heart_of_the_sea:1 + - turtle_spawn_egg:1 + - '{p=0.1}nautilus_shell:1' + permission: usb.biome.deep_ocean + currency: 50 + xp: 50 + repeatReward: + text: nautilus shell, turtle and a chance of a heart + items: + - nautilus_shell:1 + - turtle_spawn_egg:1 + - '{p=0.05}heart_of_the_sea:1' + - '{p=0.1}nautilus_shell:1' + currency: 25 + xp: 25 + horsingaround: + name: '&6Horsing Around' + description: Get hay bales for the horses. + type: onPlayer + requiredItems: + - hay_block:32;+4 + - lead:8;+2 + - carrot_on_a_stick:1 + - shears:1 + requirecChallenges: + - wheatfarmer + displayItem: hay_block + lockedDisplayItem: brown_stained_glass_pane + reward: + text: 1 horse, 1 iron horse armor, 5% chance on diamond horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald + items: + - redstone:1 + - emerald:1 + currency: 25 + xp: 25 + slimefarmer: + name: '&5Slime Farmer' + description: Collect slimeballs from slimes. + type: onPlayer + requiredItems: + - slime_ball:64;+4 + displayItem: slime_ball + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 1 diamond, 1 emeralds, swampland + items: + - diamond:1 + - emerald:1 + permission: usb.biome.swamp + currency: 70 + xp: 70 + repeatReward: + text: 1 redstone ore, 1 emeralds + items: + - redstone_ore:1 + - emerald:1 + currency: 35 + xp: 35 + animalfarm: + name: '&9Animal Farm' + description: Create an animal farm. + type: onIsland + displayItem: oak_fence + radius: 40 + requiredChallenges: + - woolcollector + - potatofarmer + - carrotfarmer + requiredEntities: + - Cow:8 + - Pig:8 + - Chicken:16 + - Sheep:{"Color":"WHITE"} + - Sheep:{"Color":"ORANGE"} + - Sheep:{"Color":"MAGENTA"} + - Sheep:{"Color":"LIGHT_BLUE"} + - Sheep:{"Color":"YELLOW"} + - Sheep:{"Color":"LIME"} + - Sheep:{"Color":"PINK"} + - Sheep:{"Color":"GRAY"} + - Sheep:{"Color":"LIGHT_GRAY"} + - Sheep:{"Color":"CYAN"} + - Sheep:{"Color":"PURPLE"} + - Sheep:{"Color":"BLUE"} + - Sheep:{"Color":"BROWN"} + - Sheep:{"Color":"GREEN"} + - Sheep:{"Color":"RED"} + - Sheep:{"Color":"BLACK"} + reward: + text: 1 horse, 1 iron horse armor, 5% chance horse armor + items: + - iron_horse_armor:1 + - horse_spawn_egg:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 50 + xp: 50 + repeatReward: + text: 1 redstone ore, 1 emerald, 5% chance horse armor + items: + - redstone:1 + - emerald:1 + - '{p=0.05}iron_horse_armor:1' + - '{p=0.05}golden_horse_armor:1' + - '{p=0.05}diamond_horse_armor:1' + currency: 25 + xp: 25 + witherhunter: + name: '&5Wither Hunter' + description: Collect some Wither Skeleton skulls. + type: onPlayer + requiredChallenges: + - netherfortress + requiredItems: + - wither_skeleton_skull:10;+1 + displayItem: wither_skeleton_skull + lockedDisplayItem: purple_stained_glass_pane + offset: -1 + reward: + text: 5 diamonds, 5% chance of nether star + items: + - diamond:5 + - '{p=0.05}nether_star:1' + currency: 400 + xp: 400 + repeatReward: + text: 2 gold ore, 5% chance of nether star + items: + - gold_ore:2 + - '{p=0.05}nether_star:1' + currency: 20 + xp: 20 + pearlcollector: + name: '&5Pearl Collector' + description: Collect enderpearls from endermen. + type: onPlayer + requiredItems: + - ender_pearl:10;+4 + displayItem: ender_pearl + lockedDisplayItem: purple_stained_glass_pane + reward: + text: 5 gold ore, 1 blaze rod, 1 emerald + items: + - gold_ore:5 + - blaze_rod:1 + - emerald:1 + currency: 70 + xp: 70 + repeatReward: + text: 1 gold ore, 1 blaze rod + items: + - gold_ore:1 + - blaze_rod:1 + currency: 35 + xp: 35 + + # =============================================== + Tier5: + name: '&4Sky Lord' + displayItem: red_terracotta + resetInHours: 48 + requires: + challenges: + - masterbuilder + challenges: + technician: + name: '&3Technician' + description: Collect some of every type of redstone equipment. + type: onPlayer + requiredItems: + - redstone:64;+16 + - redstone_torch:32;+4 + - repeater:5;+1 + - comparator:3;+1 + - piston:2;+1 + - sticky_piston:2;+1 + - lever:1;+1 + - stone_button:1;+1 + - stone_pressure_plate:1;+1 + - hopper:1;+1 + - dispenser:1;+1 + - dropper:1;+1 + - daylight_detector:1;+1 + displayItem: redstone + lockedDisplayItem: cyan_stained_glass_pane + reward: + text: some snow, ice and packed ice + items: + - snow_block:4 + - ice:8 + - packed_ice:8 + - redstone_block:64 + currency: 70 + xp: 70 + repeatReward: + text: a stack of redstone blocks and some ice + items: + - redstone_block:64 + - ice:4 + - packed_ice:1 + currency: 35 + xp: 35 + emeraldcollector: + name: '&5Emerald Collector' + description: Collect emeralds. + type: onPlayer + requiredItems: + - emerald:60;+10 + displayItem: emerald + lockedDisplayItem: purple_stained_glass_pane + reward: + text: a full set of diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 70 + xp: 70 + repeatReward: + text: full diamond armor + items: + - diamond_helmet:1 + - diamond_chestplate:1 + - diamond_leggings:1 + - diamond_boots:1 + currency: 35 + xp: 35 + topchef: + name: '&eTop Chef' + description: Collect every kind of edible food. + type: onPlayer + requiredItems: + - baked_potato:1 + - bread:1 + - cake:1 + - cooked_chicken:1 + - cooked_cod:1 + - cooked_salmon:1 + - tropical_fish:1 + - cooked_porkchop:1 + - cookie:1 + - golden_apple:1 + - golden_carrot:1 + - mushroom_stew:1 + - pumpkin_pie:1 + - cooked_beef:1 + - melon:1 + - carrot:1 + requiredChallenges: + - expertfarmer + - fisherman + - cookielover + displayItem: carrot + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 diamond, 1 mooshroom + items: + - diamond:2 + - mooshroom_spawn_egg:1 + currency: 80 + xp: 80 + repeatReward: + text: 1 diamond, 1 mooshroom + items: + - diamond:1 + - mooshroom_spawn_egg:1 + currency: 40 + xp: 40 + tajmahal: + name: '&9Taj Mahal' + description: Build a temple of quartz + type: onIsland + radius: 30 + displayItem: quartz_block + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - nethermining + requiredItems: + - quartz_block:512 + - chiseled_quartz_block:64 + - quartz_pillar:128 + - quartz_stairs:64 + - quartz_slab:192 + reward: + text: 3 end-portal frames, red sand + items: + - end_portal_frame:3 + - red_sand:64 + currency: 1000 + xp: 500 + greatpyramid: + name: '&9Great Pyramid' + description: Build a pyramid of sandstone + type: onIsland + radius: 30 + displayItem: sandstone + lockedDisplayItem: blue_stained_glass_pane + requiredItems: + - sandstone:512 + - chiseled_sandstone:64 + - smooth_sandstone:128 + - sandstone_stairs:64 + - sandstone_slab:192 + - red_sandstone:16 + reward: + text: 3 end-portal frames, 3 diamonds, bow + items: + - end_portal_frame:3 + - diamond:3 + - 'bow[enchantments={levels:{infinity:1,power:5,unbreaking:3}}]:1' + currency: 1000 + xp: 500 + poseidonshalls: + name: '&9Poseidon''s Halls' + description: Build the halls of Poseidon + type: onIsland + radius: 50 + displayItem: prismarine + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - deepseafisherman + requiredItems: + - prismarine:512 + - prismarine_bricks:128 + - dark_prismarine:64 + - sea_lantern:32 + - conduit:1 + - flower_pot:16 + - vine:128 + - poppy:10 + - blue_orchid:10 + - allium:10 + - azure_bluet:10 + - red_tulip:10 + - orange_tulip:10 + - white_tulip:10 + - pink_tulip:10 + - oxeye_daisy:10 + - sunflower:10 + - lilac:10 + - rose_bush:10 + - peony:10 + reward: + text: 3 end-portal frames, 5 diamonds + items: + - end_portal_frame:3 + - diamond:5 + currency: 1000 + xp: 500 + beaconator: + name: '&9Beaconator' + description: Build a very expensive beacon. + type: onIsland + radius: 15 + displayItem: beacon + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - netherfortress + - ironfarm + - maestro + - witherhunter + requiredItems: + - beacon:1 + - diamond_block:1 + - emerald_block:8 + - gold_block:25 + - iron_block:49 + reward: + items: + - end_portal_frame:3 + - 'diamond_sword[enchantments={levels:{fire_aspect:1,sharpness:5,unbreaking:3}}]:1' + text: some end-portal-pieces and a magic diamond sword + currency: 4000 + xp: 1000 + endportal: + name: '&9End Portal' + description: Build and activate an end-portal. + type: onIsland + radius: 15 + displayItem: end_portal_frame + lockedDisplayItem: blue_stained_glass_pane + requiredChallenges: + - beaconator + - tajmahal + - poseidonshalls + - greatpyramid + requiredItems: + - end_portal_frame:12 + - end_portal:9 + reward: + text: 5 diamonds and some nice boots + items: + - diamond:5 + - 'diamond_boots[enchantments={levels:{blast_protection:4,feather_falling:4,protection:4}}]:1' + currency: 4000 + xp: 1000 + + # =============================================== + Tier6: + name: '&aWorld Foods' + displayItem: light_gray_terracotta + resetInHours: 20 + requires: + challenges: + - masterbuilder + - topchef + challenges: + fishandchips: + name: '&eFish & Chips' + description: Create the famous English Fish & Chips. + type: onPlayer + requiredItems: + - cooked_cod:32;+8 + - baked_potato:32;+8 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 16 baked potatos, 1 disk, 4 emerald + items: + - baked_potato:16 + - music_disc_13:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Fish_and_chips + &2Click the link for more info' + smorrebrod: + name: '&eSmørrebrød' + description: Create the famous Danish smørrebrød. + type: onPlayer + requiredItems: + - bread:16;+4 + - cooked_salmon:8;+4 + - tropical_fish:2;+1 + - cooked_porkchop:8;+4 + - cooked_beef:8;+4 + displayItem: cooked_cod + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 rod, 2 name tags, 2 ocelots + items: + - fishing_rod:1 + - name_tag:2 + - ocelot_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + repeatReward: + text: 1 emerald + items: + - emerald:1 + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Danish_cuisine + &2Click the link for more info' + hutspot: + name: '&eHutspot' + description: Create the famous Dutch hutspot. + type: onPlayer + requiredItems: + - potato:64;+8 + - carrot:64;+8 + lockedDisplayItem: yellow_stained_glass_pane + displayItem: golden_carrot + reward: + text: 1 golden carrot, 1 disk, 4 emerald + items: + - golden_carrot:1 + - music_disc_cat:1 + - emerald:4 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_cat:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Hutspot &2Click + the link for more info' + apfelstrudel: + name: '&eApfelstrudele' + description: Create the famous German apfelstrudel. + type: onPlayer + requiredItems: + - apple:8;+5 + - wheat:16;+5 + - sugar:16;+5 + - milk_bucket:1 + displayItem: golden_apple + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_blocks:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_blocks:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Apple_strudel &2Click + the link for more info' + brownies: + name: '&eBrownies' + description: Create the famous American brownies. + type: onPlayer + requiredItems: + - wheat:16;+5 + - sugar:16;+5 + - egg:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: dark_oak_slab + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emerald + items: + - bucket:1 + - emerald:4 + - music_disc_far:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_far:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Chocolate_brownie + &2Click the link for more info' + pastafunghi: + name: '&ePasta Funghi' + description: Create the famous Italian Pasta Funghi. + type: onPlayer + requiredItems: + - wheat:32;+8 + - egg:32;+8 + - brown_mushroom:16;+4 + - red_mushroom:16;+4 + - milk_bucket:1 + displayItem: red_mushroom_block + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 2 rabbits, 1 bucket + items: + - bucket:1 + - rabbit_spawn_egg:2 + currency: 60 + xp: 60 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + repeatReward: + text: 30% chance on 1 disk, 1 emerald + items: + - emerald:1 + - '{p=0.3}music_disc_13:1' + currency: 30 + xp: 30 + commands: + - console:msg {player} &9https://en.wikipedia.org/wiki/Pasta &2Click the + link for more info + chocolate: + name: '&eBelgian chocolate' + description: Create the famous belgian chocolate. + type: onPlayer + requiredItems: + - sugar:16;+5 + - ink_sac:16;+5 + - milk_bucket:1 + displayItem: pig_spawn_egg + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 1 bucket, 1 disk, 4 emeralds + items: + - bucket:1 + - emerald:4 + - music_disc_mall:1 + currency: 60 + xp: 60 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + repeatReward: + text: 1 bucket, 30% chance on 1 disk, 1 emerald + items: + - bucket:1 + - emerald:1 + - '{p=0.3}music_disc_mall:1' + currency: 30 + xp: 30 + commands: + - 'console: msg {player} &9https://en.wikipedia.org/wiki/Belgian_chocolate + &2Click the link for more info' + baker: + name: '&ePâtisserie' + description: Bake cakes, pumpkin pies, and cookies. + type: onPlayer + requiredItems: + - cake:5;+1 + - pumpkin_pie:5;+1 + - cookie:128;+4 + displayItem: cake + lockedDisplayItem: yellow_stained_glass_pane + reward: + text: 5 gold ore, 1 diamond + items: + - gold_ore:5 + - diamond:1 + currency: 80 + xp: 80 + repeatReward: + text: 2 iron ore, 1 gold ore + items: + - iron_ore:2 + - gold_ore:1 + currency: 40 + xp: 40 + +# DO NOT CHANGE THE VERSION! You will break the conversion and unexpected things will happen! +version: 107 diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml index 47f39c495..535ca2f3c 100644 --- a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/old-default-challenges-expected.yml @@ -65,10 +65,14 @@ # ## type: onIsland # # [integer] Overrides the default radius of 10 blocks when using onIsland. # ## radius: 20 -# # [List[item-requirement] The items required to complete the challenge. +# # List[item-requirement] The items required to complete the challenge. # requiredItems: # - stone:64;+16 # - cobblestone:64;+16 +# # List[block-requirement] The blocks required to complete the challenge. +# requiredBlocks: +# - stone:64 +# - cobblestone:64 # # [true/false] If the challenge can be repeated or not. # ## repeatable: true # # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. diff --git a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml index af7696f81..968e4a745 100644 --- a/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml +++ b/uSkyBlock-Core/src/test/resources/us/talabrek/ultimateskyblock/imports/test-challenges-expected.yml @@ -65,10 +65,14 @@ # ## type: onIsland # # [integer] Overrides the default radius of 10 blocks when using onIsland. # ## radius: 20 -# # [List[item-requirement] The items required to complete the challenge. +# # List[item-requirement] The items required to complete the challenge. # requiredItems: # - stone:64;+16 # - cobblestone:64;+16 +# # List[block-requirement] The blocks required to complete the challenge. +# requiredBlocks: +# - stone:64 +# - cobblestone:64 # # [true/false] If the challenge can be repeated or not. # ## repeatable: true # # [integer] The maximum number of times the challenge can be completed. Overrides the default repeatLimit. diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index bd1861267..e2cb7ed0e 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -70,9 +70,5 @@ ovh.uskyblock uSkyBlock-FAWE - - ovh.uskyblock - uSkyBlock-AWE370 - diff --git a/uSkyBlock-Plugin/src/assembly/plugin.xml b/uSkyBlock-Plugin/src/assembly/plugin.xml index f930bae34..c152c895a 100644 --- a/uSkyBlock-Plugin/src/assembly/plugin.xml +++ b/uSkyBlock-Plugin/src/assembly/plugin.xml @@ -13,7 +13,6 @@ ovh.uskyblock:uSkyBlock-APIv2 ovh.uskyblock:uSkyBlock-Core ovh.uskyblock:uSkyBlock-FAWE - ovh.uskyblock:uSkyBlock-AWE370 true From fcb93a8daff36d2677d9bbdd71bf44f72e9f2b25 Mon Sep 17 00:00:00 2001 From: minoneer Date: Sun, 22 Dec 2024 14:43:22 +0100 Subject: [PATCH 131/190] Fix blocks being converted into items when computing the island level (#63) This is no longer supported in Minecraft 1.21 for materials that cannot be items such as lava or potted plants. Fixes #62 --- .../api/model/BlockScore.java | 21 ++++++++++++++++++- .../command/island/InfoCommand.java | 9 ++++---- .../island/BlockLimitLogic.java | 2 +- .../island/level/BlockLevelConfig.java | 2 +- .../island/level/BlockMatch.java | 5 ----- .../island/level/BlockScoreComparator.java | 2 +- .../island/level/BlockScoreImpl.java | 13 ++++++------ .../island/level/IslandScore.java | 5 ++--- 8 files changed, 35 insertions(+), 24 deletions(-) diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/model/BlockScore.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/model/BlockScore.java index 4d5456f4d..6214a3408 100644 --- a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/model/BlockScore.java +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/model/BlockScore.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.api.model; import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; /** @@ -14,8 +16,25 @@ public interface BlockScore { * * @return The type of block. * @since v2.1.2 + * @deprecated Converting a BlockData to an ItemStack is not supported in Minecraft. Use #getBlockData() instead. */ - ItemStack getBlock(); + @Deprecated(since = "v3.1.0") + default ItemStack getBlock() { + Material material = getBlockData().getMaterial(); + if (material.isItem()) { + return new ItemStack(material); + } else { + throw new UnsupportedOperationException("BlockData is not an item. Use getBlockData() instead."); + } + } + + /** + * The type of block. + * + * @return The type of block. + * @since v3.1.0 + */ + BlockData getBlockData(); /** * The number of blocks of this type found on the island. diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java index 1616169a9..2010f2933 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java @@ -5,6 +5,7 @@ import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.model.BlockScore; +import us.talabrek.ultimateskyblock.api.model.IslandScore; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PatienceTester; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -65,7 +66,7 @@ public boolean getIslandInfo(final Player player, final String islandPlayer, fin return false; } final PlayerInfo playerInfo = islandPlayer.equals(player.getName()) ? plugin.getPlayerInfo(player) : plugin.getPlayerInfo(islandPlayer); - final Callback showInfo = new Callback() { + final Callback showInfo = new Callback<>() { @Override public void run() { if (player.isOnline()) { @@ -82,8 +83,8 @@ public void run() { player.sendMessage(tr("Score Count Block")); for (BlockScore score : getState().getTop((currentPage - 1) * 10, 10)) { player.sendMessage(score.getState().getColor() + tr("{0,number,00.00} {1,number,#} {2}", - score.getScore(), score.getCount(), - ItemStackUtil.getItemName(score.getBlock()))); + score.getScore(), score.getCount(), + ItemStackUtil.getBlockName(score.getBlockData()))); } player.sendMessage(tr("\u00a7aIsland level is {0,number,###.##}", getState().getScore())); } @@ -101,6 +102,4 @@ public void run() { }, 1L); return true; } - - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java index b8b744e86..f5935c8b2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java @@ -61,7 +61,7 @@ public void updateBlockCount(Location islandLocation, IslandScore score) { private Map asBlockCount(IslandScore score) { Map countMap = new ConcurrentHashMap<>(); for (BlockScore blockScore : score.getTop()) { - Material type = blockScore.getBlock().getType(); + Material type = blockScore.getBlockData().getMaterial(); if (blockLimits.containsKey(type)) { int initalValue = countMap.getOrDefault(type, 0); initalValue += blockScore.getCount(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java index 82e998577..99d262ab6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockLevelConfig.java @@ -60,7 +60,7 @@ public BlockScore calculateScore(int count, double pointsPerLevel) { adjustedCount = dReturns(adjustedCount, diminishingReturns); } double blockScore = adjustedCount * scorePerBlock; - return new BlockScoreImpl(baseBlock.asItemStack(), count, blockScore/pointsPerLevel, state); + return new BlockScoreImpl(baseBlock.getType().createBlockData(), count, blockScore/pointsPerLevel, state); } private double dReturns(final double val, final double scale) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java index 8fb14ddc6..0afff1bae 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockMatch.java @@ -1,7 +1,6 @@ package us.talabrek.ultimateskyblock.island.level; import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; /** * Holds the identification of a unit to be matched against a block @@ -17,10 +16,6 @@ public Material getType() { return type; } - public ItemStack asItemStack() { - return new ItemStack(type, 1); - } - public boolean matches(Material material) { return this.type == material; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java index 3e759acae..99ca9dd97 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreComparator.java @@ -16,7 +16,7 @@ public int compare(BlockScore o1, BlockScore o2) { cmp = o2.getCount() - o1.getCount(); } if (cmp == 0) { - cmp = ItemStackUtil.getItemName(o2.getBlock()).compareTo(ItemStackUtil.getItemName(o1.getBlock())); + cmp = ItemStackUtil.getBlockName(o2.getBlockData()).compareTo(ItemStackUtil.getBlockName(o1.getBlockData())); } return cmp; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java index 1d8def7ab..fa594bb2c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/BlockScoreImpl.java @@ -1,26 +1,26 @@ package us.talabrek.ultimateskyblock.island.level; import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import org.bukkit.inventory.ItemStack; +import org.bukkit.block.data.BlockData; public class BlockScoreImpl implements us.talabrek.ultimateskyblock.api.model.BlockScore { - private final ItemStack block; + private final BlockData block; private final int count; private final double score; private final State state; private final String name; - public BlockScoreImpl(ItemStack block, int count, double score, State state) { + public BlockScoreImpl(BlockData block, int count, double score, State state) { this(block, count, score, state, null); } - public BlockScoreImpl(ItemStack block, int count, double score, State state, String name) { + public BlockScoreImpl(BlockData block, int count, double score, State state, String name) { this.block = block; this.count = count; this.score = score; this.state = state; - this.name = name != null ? name : ItemStackUtil.getItemName(getBlock()); + this.name = name != null ? name : ItemStackUtil.getBlockName(getBlockData()); } @Override @@ -34,9 +34,8 @@ public String toString() { '}'; } - @Override - public ItemStack getBlock() { + public BlockData getBlockData() { return block; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java index 149ab4bd3..1afa19624 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/IslandScore.java @@ -3,7 +3,6 @@ import us.talabrek.ultimateskyblock.api.model.BlockScore; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,7 +41,7 @@ private BlockScoreImpl add(BlockScore score, BlockScore existing) { if (score.getState().ordinal() > existing.getState().ordinal()) { state = existing.getState(); } - return new BlockScoreImpl(existing.getBlock(), + return new BlockScoreImpl(existing.getBlockData(), score.getCount() + existing.getCount(), score.getScore() + existing.getScore(), state, score.getName()); } @@ -70,7 +69,7 @@ public List getTop(int offset, int num) { throw new IllegalArgumentException("Offset must be a non-negative integer."); } if (!isSorted) { - Collections.sort(top, new BlockScoreComparator()); + top.sort(new BlockScoreComparator()); isSorted = true; } return top.subList(offset, Math.min(offset+num, top.size())); From 3fadc5e7d3aaee90b98447b8f7fb458f7c8eddd8 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 22 Dec 2024 14:58:58 +0100 Subject: [PATCH 132/190] First try on fixing deployment --- .github/deploy-release.sh | 52 ++++++++++++++++++------------------- .github/deploy-staging.sh | 52 ++++++++++++++++++------------------- .github/workflows/build.yml | 6 ++--- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/.github/deploy-release.sh b/.github/deploy-release.sh index 90e5023c8..4fbbaae91 100644 --- a/.github/deploy-release.sh +++ b/.github/deploy-release.sh @@ -4,58 +4,58 @@ echo -e "Running release script...\n" echo -e "Publishing javadocs and artifacts...\n" cd $HOME -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/po-utils/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ echo -e "Publishing javadocs...\n" -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/po-utils/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/release/po-utils/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/release/po-utils/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-API/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/release/uSkyBlock-API/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-APIv2/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/release/uSkyBlock-APIv2/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/release/uSkyBlock-Core/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/release/uSkyBlock-Core/ echo -e "Publishing final plugin release...\n" -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ -travis@travis.internetpolice.eu:WWW-USB/downloads/release/uSkyBlock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/downloads/release/uSkyBlock/ -rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/classes/version.json \ -travis@travis.internetpolice.eu:WWW-USB/versions/release.json +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/versions/release.json diff --git a/.github/deploy-staging.sh b/.github/deploy-staging.sh index 37b67e296..87ccfd640 100644 --- a/.github/deploy-staging.sh +++ b/.github/deploy-staging.sh @@ -4,58 +4,58 @@ echo -e "Running staging script...\n" echo -e "Publishing javadocs and artifacts...\n" cd $HOME -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/po-utils/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-FAWE/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/mvn-repo/ \ -travis@travis.internetpolice.eu:WWW-USB/maven/uskyblock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/maven/uskyblock/ echo -e "Publishing javadocs...\n" -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/po-utils/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/master/po-utils/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/master/po-utils/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-API/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-API/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/master/uSkyBlock-API/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-APIv2/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-APIv2/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/master/uSkyBlock-APIv2/ -rsync -r --delete --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --delete --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Core/target/site/apidocs/ \ -travis@travis.internetpolice.eu:WWW-USB/javadocs/master/uSkyBlock-Core/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/javadocs/master/uSkyBlock-Core/ echo -e "Publishing final plugin release...\n" -rsync -r --quiet -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/uSkyBlock-*.jar \ -travis@travis.internetpolice.eu:WWW-USB/downloads/master/uSkyBlock/ +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/downloads/master/uSkyBlock/ -rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 2222 -o StrictHostKeyChecking=no" \ +rsync -r --quiet --no-R --no-implied-dirs -e "ssh -p 7685 -o StrictHostKeyChecking=no" \ $HOME/work/uSkyBlock/uSkyBlock/uSkyBlock-Plugin/target/classes/version.json \ -travis@travis.internetpolice.eu:WWW-USB/versions/staging.json +u36810p330294@uskyblock.ovh:domains/uskyblock.ovh/public_html/versions/staging.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ecf294d9..2e7080ef7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: jobs: build_and_test: if: github.repository_owner == 'uskyblock' - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout repository uses: actions/checkout@v3 @@ -23,9 +23,9 @@ jobs: cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - - name: JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Install gettext run: sudo apt-get install -y gettext From 559c296381e891fc689cd1be168f2dab901c7dfa Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 22 Dec 2024 15:11:45 +0100 Subject: [PATCH 133/190] Stay on JDK17 for now --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e7080ef7..8eab538e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: JDK 17 uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '17' distribution: 'temurin' - name: Install gettext run: sudo apt-get install -y gettext From 0718e51dbae6cb4f908e56233c8a307b1b8a1250 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 22 Dec 2024 17:43:59 +0100 Subject: [PATCH 134/190] Remove old release scripts --- changelog.md | 25 ------------------------- changelog.sh | 16 ---------------- prerelease.sh | 10 ---------- release.sh | 14 -------------- 4 files changed, 65 deletions(-) delete mode 100644 changelog.md delete mode 100644 changelog.sh delete mode 100644 prerelease.sh delete mode 100644 release.sh diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 105d0400a..000000000 --- a/changelog.md +++ /dev/null @@ -1,25 +0,0 @@ -## Change Log for v2.7.6..v2.7.6-201809101626 - - -## Translations -``` -Gettext Statistics -Locale | code | % | Trans | Untr | Fuzzy | Translator --------------------- | ---------- | ---- | -------- | -------- | -------- | ---------------- -Chinese (China) | zh_CN | 31% | 230 | 524 | 0 | Miku_Snow -Czech | cs | 80% | 604 | 150 | 0 | martyHR -Danish | da | 94% | 706 | 48 | 0 | R4zorax -Dutch | nl | 91% | 683 | 71 | 0 | clrxbl -English (UK) | en_GB | 92% | 696 | 58 | 0 | dutchy1001 -French | fr | 82% | 616 | 138 | 0 | Wura -German | de | 87% | 656 | 98 | 0 | I9hdkill I9hdkill@spigotmc.org -Italian | it | 97% | 732 | 22 | 0 | Leomixer17 -Korean | ko | 90% | 676 | 78 | 0 | swan201 -Portuguese (Brazil) | pt_BR | 62% | 466 | 288 | 0 | _Rodrigo -Russian | ru | 62% | 465 | 289 | 0 | Error203 -Spanish | es | 62% | 469 | 285 | 0 | Delu -Swedish | sv | 87% | 653 | 101 | 0 | maol3 -Vietnamese (Vietnam) | vi_VN | 76% | 574 | 180 | 0 | -xx (LOL) | xx_LOL | 90% | 680 | 74 | 0 | Woolwind -xx (PIRATE) | xx_PIRATE | 90% | 680 | 74 | 0 | R4zorax -``` diff --git a/changelog.sh b/changelog.sh deleted file mode 100644 index 3ffa76390..000000000 --- a/changelog.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -newversion=$1 -lastversion=$2 -if [[ -z $lastversion ]];then - tag=$( git describe --tags --abbrev=0 ) - lastversion="${tag%-*}" -fi -if [[ -z $newversion ]];then - newversion="HEAD" -fi -echo -e "## Change Log for ${lastversion}..${newversion}\n" -git log --oneline ${lastversion}..HEAD | grep "#" | awk '{printf(" * %s\n",$0)}' -echo -e "\n## Translations" -echo '```' -cat uSkyBlock-Core/target/classes/gettext-report.txt -echo '```' \ No newline at end of file diff --git a/prerelease.sh b/prerelease.sh deleted file mode 100644 index 67b11897f..000000000 --- a/prerelease.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -tag=$( git describe --tags --abbrev=0 ) -lastversion="${tag%-*}" -tstamp=$( date +%Y%m%d%H%M ) -newversion="$lastversion-$tstamp" -./changelog.sh $newversion $lastversion > changelog.md -git commit -a -m "Changelog for $tag" -git push -git tag $newversion -git push --tags diff --git a/release.sh b/release.sh deleted file mode 100644 index 741225d4c..000000000 --- a/release.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -if [[ -z $1 ]]; then - echo "Usage: $0 " - exit -1 -fi -newversion=$1 -tag=$( git describe --tags --abbrev=0 ) -tstamp=$( date +%Y%m%d%H%M ) -lastversion="${tag%-*}" -./changelog.sh $newversion $lastversion > changelog.md -git commit -a -m "Changelog for $tag" -git push -git tag $newversion -git push --tags From a74ba78cb8457ef3c7efe75f8992f1aa21c15ac0 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 22 Dec 2024 17:46:42 +0100 Subject: [PATCH 135/190] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 21 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..40ccc1285 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,21 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +_Please paste the output from `/usb version` below_ +``` +paste it here please (replace this text) +``` + +_What steps will reproduce the problem?_ +1. +2. +3. + +_If you have any log-files, please paste them to [pastebin.com](http://pastebin.com)_ +* server-log: link-to-pastebin diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..11fc491ef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 16f3b859254b08d76d57dfa0468b31ad093a74f2 Mon Sep 17 00:00:00 2001 From: Muspah Date: Sun, 22 Dec 2024 17:47:08 +0100 Subject: [PATCH 136/190] Remove old issue_template --- ISSUE_TEMPLATE.md | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 11f97984d..000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,14 +0,0 @@ -_Please paste the output from `/usb version` below_ -``` -paste it here please (replace this text) -``` - -_What steps will reproduce the problem?_ -1. -2. -3. - -_If you have any log-files, please paste them to [pastebin.com](http://pastebin.com)_ -* server-log: link-to-pastebin - -(Not following the template will result in closing the issue.) From c8174707199a57b2157f55c433b243791c39e268 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 23 Dec 2024 10:29:51 +0100 Subject: [PATCH 137/190] Update build to Java 21 (#64) Includes: - Updated maven plugins - Upgrade Mockito tests - Updated build script --- .github/workflows/build.yml | 4 +-- bukkit-utils/pom.xml | 15 --------- .../command/BaseCommandExecutorTest.java | 23 +++++--------- .../command/CompositeCommandTest.java | 22 ++++++------- .../minecraft/util/BukkitServerMock.java | 2 +- po-utils/pom.xml | 5 +-- pom.xml | 31 +++++++++++++------ uSkyBlock-API/pom.xml | 14 ++++----- uSkyBlock-APIv2/pom.xml | 5 +-- uSkyBlock-Core/pom.xml | 10 ++---- .../challenge/ChallengeFormatTest.java | 3 +- .../ultimateskyblock/chat/ChatEventsTest.java | 2 +- .../event/InternalEventsTest.java | 22 ++++++------- .../event/MenuEventsTest.java | 4 +-- .../island/IslandLocatorLogicTest.java | 21 ++++--------- uSkyBlock-Plugin/pom.xml | 1 - 16 files changed, 75 insertions(+), 109 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8eab538e8..55e1a9cae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,10 +22,10 @@ jobs: run: | cd uSkyBlock-Core/src/main/po && perl en2pirate.pl && cd - cd uSkyBlock-Core/src/main/po && perl en2kitteh.pl && cd - - - name: JDK 17 + - name: JDK 21 uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Install gettext run: sudo apt-get install -y gettext diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml index 7d3bf8e0f..7e3d4ba34 100644 --- a/bukkit-utils/pom.xml +++ b/bukkit-utils/pom.xml @@ -54,16 +54,10 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 - - 16 - UTF-8 - org.apache.maven.plugins maven-jar-plugin - 3.2.0 @@ -75,7 +69,6 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.0 public false @@ -93,7 +86,6 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 attach-sources @@ -125,13 +117,6 @@ ${vaultapi.version} true - - - - - - - org.hamcrest hamcrest-core diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java index 44d9f5700..e502fe5a9 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java @@ -4,7 +4,6 @@ import org.junit.BeforeClass; import org.junit.Test; import org.mockito.ArgumentMatchers; -import org.mockito.Matchers; import org.mockito.Mockito; import org.mockito.stubbing.Answer; @@ -13,7 +12,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.when; @@ -27,11 +26,9 @@ public static void setUp() { mycmd.add(new AbstractCommand("hello|h", "myplugin.perm.hello", "say hello to the player") { @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { - sender.sendMessage(new String[]{ - "Hello! and welcome " + sender.getName(), - "I was called with : " + alias, - "I had " + args.length + " arguments: " + Arrays.asList(args) - }); + sender.sendMessage("Hello! and welcome " + sender.getName(), + "I was called with : " + alias, + "I had " + args.length + " arguments: " + Arrays.asList(args)); return true; } }); @@ -62,26 +59,22 @@ private void addPerm(CommandSender sender, String s) { when(sender.hasPermission(ArgumentMatchers.isA(String.class))).thenReturn(true); } - private void addOp(CommandSender sender) { - when(sender.isOp()).thenReturn(true); - } - private CommandSender createCommandSender() { CommandSender mock = Mockito.mock(CommandSender.class); Answer answer = invocationOnMock -> { for (Object o : invocationOnMock.getArguments()) { if (o != null && o.getClass().isArray()) { for (Object o2 : (Object[]) o) { - messages.append("" + o2 + "\n"); + messages.append(o2).append("\n"); } } else { - messages.append("" + o + "\n"); + messages.append(o).append("\n"); } } return null; }; doAnswer(answer).when(mock).sendMessage(anyString()); - doAnswer(answer).when(mock).sendMessage(Matchers.any()); + doAnswer(answer).when(mock).sendMessage(ArgumentMatchers.any(String[].class)); return mock; } -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java index c764f08dd..6fb59e129 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java @@ -14,13 +14,13 @@ import java.util.UUID; import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; public class CompositeCommandTest { - private static UUID ownerUUID = UUID.randomUUID(); - private static UUID adminUUID = UUID.randomUUID(); - private static UUID modUUID = UUID.randomUUID(); + private static final UUID ownerUUID = UUID.randomUUID(); + private static final UUID adminUUID = UUID.randomUUID(); + private static final UUID modUUID = UUID.randomUUID(); private static BaseCommandExecutor executor; @BeforeClass @@ -89,7 +89,7 @@ public void PermOnAdmin() { executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); verify(player).sendMessage("executed admin"); - assertThat(messages, Matchers.contains(new String[]{"executed admin", "§eYou do not have access (§4perm.sub§e)"})); + assertThat(messages, Matchers.contains("executed admin", "§eYou do not have access (§4perm.sub§e)")); } @Test @@ -103,7 +103,7 @@ public void AllPerms() { executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); verify(player).sendMessage("executed admin"); - assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + assertThat(messages, Matchers.contains("executed admin", "from sub")); } @Test @@ -116,7 +116,7 @@ public void NoPerm_PermissionOverride() { // Act executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); - assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + assertThat(messages, Matchers.contains("executed admin", "from sub")); } @Test @@ -129,7 +129,7 @@ public void NoPerm_PermissionSubOverride() { // Act executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); - assertThat(messages, Matchers.contains(new String[]{"§eYou do not have access (§4plugin§e)"})); + assertThat(messages, Matchers.contains("§eYou do not have access (§4plugin§e)")); } @Test @@ -145,7 +145,7 @@ public void BasePerm_PermissionCompositeOverride() { // Act executor.onCommand(player, null, "alias", new String[]{"admin", "sub"}); - assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub"})); + assertThat(messages, Matchers.contains("executed admin", "from sub")); } @Test @@ -162,7 +162,7 @@ public void BasePerm_PermissionAbstractCommandOverride() { // Act executor.onCommand(player, null, "alias", new String[]{"admin", "sub2"}); - assertThat(messages, Matchers.contains(new String[]{"executed admin", "from sub2"})); + assertThat(messages, Matchers.contains("executed admin", "from sub2")); } private List recordMessages(Player player) { @@ -175,4 +175,4 @@ private List recordMessages(Player player) { return messages; } -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java index 526f2e2fb..94bc3f04e 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java @@ -17,7 +17,7 @@ import java.util.Objects; import java.util.TreeMap; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; public class BukkitServerMock { diff --git a/po-utils/pom.xml b/po-utils/pom.xml index ebe67b21d..023e26809 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -46,11 +46,8 @@ + org.apache.maven.plugins maven-compiler-plugin - - 17 - utf-8 - org.apache.maven.plugins diff --git a/pom.xml b/pom.xml index 88a1a6dec..34035a80e 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 2.2 4.13.2 5.9.0 - 3.12.4 + 5.14.2 @@ -69,40 +69,51 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.13.0 - 17 + 21 + UTF-8 org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.11.2 org.apache.maven.plugins maven-shade-plugin - 3.4.1 + 3.6.0 org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 + + + org.apache.maven.plugins + maven-clean-plugin + 3.4.0 org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.5.2 org.apache.maven.plugins maven-failsafe-plugin - 3.0.0-M5 + 3.5.2 + + + org.apache.maven.plugins + maven-assembly-plugin + 3.7.1 @@ -110,7 +121,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0 + 3.5.0 enforce-maven diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 339148212..211bbe7fe 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -4,6 +4,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + uSkyBlock + ovh.uskyblock + 3.1.0-SNAPSHOT + com.github.rlf uSkyBlock-API 3.1.0-SNAPSHOT @@ -31,7 +36,7 @@ org.spigotmc spigot-api - 1.20.4-R0.1-SNAPSHOT + ${spigotapi.version} provided true @@ -47,20 +52,14 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 - - 17 - org.apache.maven.plugins maven-jar-plugin - 3.2.0 org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 public false @@ -84,7 +83,6 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 attach-sources diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index 10bd75876..f54a135e7 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -28,11 +28,8 @@ + org.apache.maven.plugins maven-compiler-plugin - - 17 - utf-8 - org.apache.maven.plugins diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 33503cbbb..c5f77cbc1 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -16,10 +16,6 @@ org.apache.maven.plugins maven-compiler-plugin - - 17 - utf-8 - com.google.code.maven-replacer-plugin @@ -52,7 +48,7 @@ org.codehaus.mojo buildnumber-maven-plugin - 1.4 + 3.2.1 generate-resources @@ -120,8 +116,8 @@ + org.apache.maven.plugins maven-clean-plugin - 3.1.0 @@ -140,7 +136,7 @@ org.apache.maven.plugins maven-antrun-plugin - 1.8 + 3.1.0 prepare-package diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java index 03cc1f8aa..44f965284 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java @@ -11,7 +11,6 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.when; public class ChallengeFormatTest { @@ -80,4 +79,4 @@ public void getMissingRequirement_AllFullyCompleted() { String missingRequirement = ChallengeFormat.getMissingRequirement(playerInfo, Arrays.asList("cobblestonegenerator", "pumpkinfarmer:2"), challengeLogic); assertThat(missingRequirement, is(nullValue())); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java index 4ea6c1aec..96f61342a 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java @@ -33,7 +33,7 @@ public void setUp() { when(fakeScheduler.runTask(any(Plugin.class), any(Runnable.class))).thenReturn(mock(BukkitTask.class)); when(fakeServer.getScheduler()).thenReturn(fakeScheduler); - fakeLogic = spy(mock(ChatLogic.class)); + fakeLogic = mock(ChatLogic.class); doNothing().when(fakeLogic).sendMessage(any(), any(), any()); listener = new ChatEvents(fakeLogic, fakePlugin); diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/InternalEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/InternalEventsTest.java index bb18bd6db..e5513cd7a 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/InternalEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/InternalEventsTest.java @@ -32,7 +32,7 @@ public class InternalEventsTest { @Before public void setUp() { - fakePlugin = spy(mock(uSkyBlock.class)); + fakePlugin = mock(uSkyBlock.class); internalEvents = new InternalEvents(fakePlugin); YamlConfiguration config = new YamlConfiguration(); @@ -40,7 +40,7 @@ public void setUp() { config.set("options.party.leave-commands", Arrays.asList("dont", "stop", "me", "now")); doReturn(config).when(fakePlugin).getConfig(); - fakeBlockLimitLogic = spy(mock(BlockLimitLogic.class)); + fakeBlockLimitLogic = mock(BlockLimitLogic.class); doNothing().when(fakeBlockLimitLogic).updateBlockCount(any(), any()); doReturn(fakeBlockLimitLogic).when(fakePlugin).getBlockLimitLogic(); @@ -73,7 +73,7 @@ public void testOnCreate() { @Test public void testOnMemberJoin() { IslandInfo fakeIslandInfo = mock(IslandInfo.class); - PlayerInfo fakePlayerInfo = spy(mock(PlayerInfo.class)); + PlayerInfo fakePlayerInfo = mock(PlayerInfo.class); doReturn(true).when(fakePlayerInfo).execCommands(any()); List commandList = fakePlugin.getConfig().getStringList("options.party.join-commands"); @@ -86,7 +86,7 @@ public void testOnMemberJoin() { @Test public void testOnMemberLeft() { IslandInfo fakeIslandInfo = mock(IslandInfo.class); - PlayerInfo fakePlayerInfo = spy(mock(PlayerInfo.class)); + PlayerInfo fakePlayerInfo = mock(PlayerInfo.class); doReturn(true).when(fakePlayerInfo).execCommands(any()); List commandList = fakePlugin.getConfig().getStringList("options.party.leave-commands"); @@ -103,7 +103,7 @@ public void testOnScoreChanged() { Location islandLocation = new Location(null, -10.00, 25.00, 10.00); uSkyBlockScoreChangedEvent event = new uSkyBlockScoreChangedEvent(fakePlayer, fakePlugin, - fakeIslandScore, islandLocation); + fakeIslandScore, islandLocation); internalEvents.onScoreChanged(event); verify(fakeBlockLimitLogic).updateBlockCount(islandLocation, fakeIslandScore); } @@ -113,12 +113,12 @@ public void testOnInfoEvent() { Player fakePlayer = getFakePlayer(); Location islandLocation = new Location(null, -10.00, 25.00, 10.00); Callback callback = - new Callback() { - @Override - public void run() { - // Do nothing - } - }; + new Callback<>() { + @Override + public void run() { + // Do nothing + } + }; IslandInfoEvent event = new IslandInfoEvent(fakePlayer, islandLocation, callback); internalEvents.onInfoEvent(event); diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java index efa4a4db6..8b8c04053 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java @@ -29,8 +29,8 @@ public class MenuEventsTest { @Before public void setUp() { uSkyBlock fakePlugin = mock(uSkyBlock.class); - fakeConfigMenu = spy(mock(ConfigMenu.class)); - fakeMenu = spy(mock(SkyBlockMenu.class)); + fakeConfigMenu = mock(ConfigMenu.class); + fakeMenu = mock(SkyBlockMenu.class); doNothing().when(fakeConfigMenu).onClick(any(InventoryClickEvent.class)); doNothing().when(fakeMenu).onClick(any(InventoryClickEvent.class)); diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java index 98fd0c695..88b86918c 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java @@ -6,7 +6,6 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -25,7 +24,7 @@ import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -64,13 +63,10 @@ public void testNextIslandLocationReservationConcurrency() throws Exception { final List locations = new ArrayList<>(); ThreadGroup threadGroup = new ThreadGroup("My"); for (int i = 0; i < 10; i++) { - Thread t = new Thread(threadGroup, new Runnable() { - @Override - public void run() { - Player player = createPlayerMock(); - Location location = locator.getNextIslandLocation(player); - locations.add(location); - } + Thread t = new Thread(threadGroup, () -> { + Player player = createPlayerMock(); + Location location = locator.getNextIslandLocation(player); + locations.add(location); }); t.start(); } @@ -84,12 +80,7 @@ public void run() { private Player createPlayerMock() { Player player = mock(Player.class); - when(player.getLocation()).then(new Answer() { - @Override - public Location answer(InvocationOnMock invocationOnMock) throws Throwable { - return new Location(null, 100, 100, 100); - } - }); + when(player.getLocation()).then((Answer) invocationOnMock -> new Location(null, 100, 100, 100)); return player; } diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index e2cb7ed0e..9d23c4627 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -16,7 +16,6 @@ maven-assembly-plugin - 3.1.1 distro-assembly From bd879b9ac018751c575eec315852f0d7be45f7b5 Mon Sep 17 00:00:00 2001 From: minoneer Date: Sat, 28 Dec 2024 19:09:51 +0100 Subject: [PATCH 138/190] Fix wither spawning with disabled spawn-limits (#66) * Fix wither spawning with disabled spawn-limits Resolves #60 Decouples wither-origin tracking and spawn limit listeners. The issue was that withers were tagged with their origin island in the creature spawn listeners for of SpawnEvents, which is not registered if spawn limits are disabled. I solved this by moving the wither tagging logic into a separate listener that is always active. Untagged Withers are despawned by the GriefEvents listener. I also migrated the tagging to PDC to make the tagging consistent without relying on name tagging that is prone to errors. * Cleanup SpawnEvents --- .../ultimateskyblock/event/GriefEvents.java | 44 ++++++++--------- .../ultimateskyblock/event/SpawnEvents.java | 48 +++++-------------- .../event/WitherTagListener.java | 34 +++++++++++++ .../talabrek/ultimateskyblock/uSkyBlock.java | 12 +---- 4 files changed, 67 insertions(+), 71 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java index 01620c482..9aba849bb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java @@ -3,6 +3,7 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Animals; import org.bukkit.entity.Creature; @@ -25,14 +26,15 @@ import org.bukkit.event.player.PlayerEggThrowEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerShearEntityEvent; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.projectiles.ProjectileSource; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.text.MessageFormat; -import java.text.ParseException; - /** * Handling of mob-related events. */ @@ -171,39 +173,34 @@ public void onWitherSkullExplosion(EntityDamageByEntityEvent e) { } } - private void handleWitherRampage(Cancellable e, Wither shooter, Location targetLocation) { - String islandName = getOwningIsland(shooter); + private void handleWitherRampage(Cancellable event, Wither shooter, Location targetLocation) { + String withersIsland = getOwningIsland(shooter); String targetIsland = WorldGuardHandler.getIslandNameAt(targetLocation); - if (targetIsland == null || !targetIsland.equals(islandName)) { - e.setCancelled(true); - checkWitherLeash(shooter, islandName); + if (targetIsland == null || !targetIsland.equals(withersIsland)) { + event.setCancelled(true); + checkWitherLeash(shooter, withersIsland); } } - private void checkWitherLeash(Wither shooter, String islandName) { + private void checkWitherLeash(@NotNull Wither shooter, @Nullable String withersIsland) { String currentIsland = WorldGuardHandler.getIslandNameAt(shooter.getLocation()); - if (currentIsland == null || !currentIsland.equals(islandName)) { + if (currentIsland == null || !currentIsland.equals(withersIsland)) { shooter.remove(); - IslandInfo islandInfo = plugin.getIslandInfo(islandName); + IslandInfo islandInfo = plugin.getIslandInfo(withersIsland); if (islandInfo != null) { islandInfo.sendMessageToOnlineMembers(I18nUtil.tr("\u00a7cWither Despawned!\u00a7e It wandered too far from your island.")); } } } - private String getOwningIsland(Wither wither) { - if (wither.hasMetadata("fromIsland")) { - return wither.getMetadata("fromIsland").get(0).asString(); + private @Nullable String getOwningIsland(@NotNull Wither wither) { + PersistentDataContainer container = wither.getPersistentDataContainer(); + NamespacedKey key = new NamespacedKey(plugin, WitherTagListener.ENTITY_ORIGIN_METADATA); + if (container.has(key, PersistentDataType.STRING)) { + return container.get(key, PersistentDataType.STRING); + } else { + return null; } - try { - Object[] parse = new MessageFormat(I18nUtil.marktr("{0}''s Wither")).parse(wither.getCustomName()); - if (parse != null && parse.length == 1 && parse[0] instanceof String) { - return (String) parse[0]; - } - } catch (ParseException e) { - // Ignore - } - return null; } @EventHandler @@ -215,5 +212,4 @@ public void onEgg(PlayerEggThrowEvent e) { e.setHatching(false); } } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index ea2e8087f..e9e0befba 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -1,16 +1,13 @@ package us.talabrek.ultimateskyblock.event; -import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.entity.EntityType; -import org.bukkit.entity.Ghast; import org.bukkit.entity.Phantom; import org.bukkit.entity.Player; import org.bukkit.entity.WaterMob; -import org.bukkit.entity.Wither; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; @@ -19,17 +16,13 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.material.MonsterEggs; -import org.bukkit.material.SpawnEgg; -import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.inventory.meta.SpawnEggMeta; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; +import java.util.Collection; import java.util.Set; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -38,15 +31,7 @@ * Responsible for controlling spawns on uSkyBlock islands. */ public class SpawnEvents implements Listener { - private static final Set RIGHT_CLICKS = new HashSet<>(Arrays.asList(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK)); - private static final Set PLAYER_INITIATED = new HashSet<>(Arrays.asList( - CreatureSpawnEvent.SpawnReason.BREEDING, - CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM, CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN, - CreatureSpawnEvent.SpawnReason.BUILD_WITHER - )); - private static final Set ADMIN_INITIATED = new HashSet<>(Arrays.asList( - CreatureSpawnEvent.SpawnReason.SPAWNER_EGG - )); + private static final Set RIGHT_CLICKS = Set.of(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK); private final uSkyBlock plugin; @@ -69,14 +54,14 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { return; } ItemStack item = event.getItem(); - if (RIGHT_CLICKS.contains(event.getAction()) && item != null && isSpawnEgg(item)) { + if (RIGHT_CLICKS.contains(event.getAction()) && item != null && item.getItemMeta() instanceof SpawnEggMeta spawnEggMeta) { if (!plugin.playerIsOnIsland(player)) { event.setCancelled(true); plugin.notifyPlayer(player, tr("\u00a7eYou can only use spawn-eggs on your own island.")); return; } - SpawnEgg spawnEgg = (SpawnEgg) item.getData(); - checkLimits(event, spawnEgg.getSpawnedType(), player.getLocation()); + + checkLimits(event, spawnEggMeta.getSpawnedType(), player.getLocation()); if (event.isCancelled()) { plugin.notifyPlayer(player, tr("\u00a7cYou have reached your spawn-limit for your island.")); event.setUseItemInHand(Event.Result.DENY); @@ -85,16 +70,12 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { } } - private boolean isSpawnEgg(ItemStack item) { - return item.getType().name().endsWith("_SPAWN_EGG") && item.getData() instanceof MonsterEggs; - } - @EventHandler(ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent event) { if (event == null || !plugin.getWorldManager().isSkyAssociatedWorld(event.getLocation().getWorld())) { return; // Bail out, we don't care } - if (!event.isCancelled() && ADMIN_INITIATED.contains(event.getSpawnReason())) { + if (event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SPAWNER_EGG)) { return; // Allow it, the above method would have blocked it if it should be blocked. } checkLimits(event, event.getEntity().getType(), event.getLocation()); @@ -105,22 +86,15 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { event.setCancelled(true); } } - if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.BUILD_WITHER && event.getEntity() instanceof Wither) { - IslandInfo islandInfo = plugin.getIslandInfo(event.getLocation()); - if (islandInfo != null && islandInfo.getLeader() != null) { - event.getEntity().setCustomName(I18nUtil.tr("{0}''s Wither", islandInfo.getLeader())); - event.getEntity().setMetadata("fromIsland", new FixedMetadataValue(plugin, islandInfo.getName())); - } - } } private boolean isPrismarineRoof(Location loc) { - List prismarineBlocks = Arrays.asList(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); + Collection prismarineBlocks = Set.of(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); return prismarineBlocks.contains(LocationUtil.findRoofBlock(loc).getType()); } private boolean isDeepOceanBiome(Location loc) { - List deepOceans = Arrays.asList(Biome.DEEP_OCEAN, Biome.DEEP_COLD_OCEAN, Biome.DEEP_FROZEN_OCEAN, Biome.DEEP_LUKEWARM_OCEAN); + Collection deepOceans = Set.of(Biome.DEEP_OCEAN, Biome.DEEP_COLD_OCEAN, Biome.DEEP_FROZEN_OCEAN, Biome.DEEP_LUKEWARM_OCEAN); return deepOceans.contains(loc.getWorld().getBiome(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); } @@ -133,12 +107,12 @@ private void checkLimits(Cancellable event, EntityType entityType, Location loca event.setCancelled(true); // Only allow spawning on active islands... return; } - if (entityType.getEntityClass().isAssignableFrom(Ghast.class) && location.getWorld().getEnvironment() != World.Environment.NETHER) { + if (entityType.equals(EntityType.GHAST) && location.getWorld().getEnvironment() != World.Environment.NETHER) { // Disallow ghasts for now... event.setCancelled(true); return; } - us.talabrek.ultimateskyblock.api.IslandInfo islandInfo = plugin.getIslandInfo(islandName); + IslandInfo islandInfo = plugin.getIslandInfo(islandName); if (islandInfo == null) { // Disallow spawns on inactive islands event.setCancelled(true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java new file mode 100644 index 000000000..d03d4c715 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java @@ -0,0 +1,34 @@ +package us.talabrek.ultimateskyblock.event; + +import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Wither; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.persistence.PersistentDataType; +import us.talabrek.ultimateskyblock.api.IslandInfo; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public class WitherTagListener implements Listener { + + static final String ENTITY_ORIGIN_METADATA = "from-island"; + private final uSkyBlock plugin; + + public WitherTagListener(uSkyBlock plugin) { + this.plugin = plugin; + } + + @EventHandler(ignoreCancelled = true) + public void onCreatureSpawn(CreatureSpawnEvent event) { + if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.BUILD_WITHER + && event.getEntity() instanceof Wither wither) { + IslandInfo islandInfo = plugin.getIslandInfo(event.getLocation()); + if (islandInfo != null && islandInfo.getLeader() != null) { + wither.setCustomName(I18nUtil.tr("{0}''s Wither", islandInfo.getLeader())); + NamespacedKey key = new NamespacedKey(plugin, ENTITY_ORIGIN_METADATA); + wither.getPersistentDataContainer().set(key, PersistentDataType.STRING, islandInfo.getName()); + } + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 8855ad0fa..740d82a69 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -48,16 +48,7 @@ import us.talabrek.ultimateskyblock.command.admin.DebugCommand; import us.talabrek.ultimateskyblock.command.admin.SetMaintenanceCommand; import us.talabrek.ultimateskyblock.command.island.BiomeCommand; -import us.talabrek.ultimateskyblock.event.ExploitEvents; -import us.talabrek.ultimateskyblock.event.GriefEvents; -import us.talabrek.ultimateskyblock.event.InternalEvents; -import us.talabrek.ultimateskyblock.event.ItemDropEvents; -import us.talabrek.ultimateskyblock.event.MenuEvents; -import us.talabrek.ultimateskyblock.event.NetherTerraFormEvents; -import us.talabrek.ultimateskyblock.event.PlayerEvents; -import us.talabrek.ultimateskyblock.event.SpawnEvents; -import us.talabrek.ultimateskyblock.event.ToolMenuEvents; -import us.talabrek.ultimateskyblock.event.WorldGuardEvents; +import us.talabrek.ultimateskyblock.event.*; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; @@ -334,6 +325,7 @@ public void registerEvents() { manager.registerEvents(new PlayerEvents(this), this); manager.registerEvents(new MenuEvents(this), this); manager.registerEvents(new ExploitEvents(this), this); + manager.registerEvents(new WitherTagListener(this), this); if (getConfig().getBoolean("options.protection.enabled", true)) { manager.registerEvents(new GriefEvents(this), this); if (getConfig().getBoolean("options.protection.item-drops", true)) { From bcf06ab80d524b3170aa9aed906c2d96d957756f Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 30 Dec 2024 11:44:19 +0100 Subject: [PATCH 139/190] Make listener names consistent and tag withers on proper priority --- .../us/talabrek/ultimateskyblock/event/GriefEvents.java | 2 +- .../event/{WitherTagListener.java => WitherTagEvents.java} | 7 ++++--- .../main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) rename uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/{WitherTagListener.java => WitherTagEvents.java} (85%) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java index 9aba849bb..281ca685a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java @@ -195,7 +195,7 @@ private void checkWitherLeash(@NotNull Wither shooter, @Nullable String withersI private @Nullable String getOwningIsland(@NotNull Wither wither) { PersistentDataContainer container = wither.getPersistentDataContainer(); - NamespacedKey key = new NamespacedKey(plugin, WitherTagListener.ENTITY_ORIGIN_METADATA); + NamespacedKey key = new NamespacedKey(plugin, WitherTagEvents.ENTITY_ORIGIN_METADATA); if (container.has(key, PersistentDataType.STRING)) { return container.get(key, PersistentDataType.STRING); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java similarity index 85% rename from uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java rename to uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java index d03d4c715..87251dd02 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagListener.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java @@ -4,22 +4,23 @@ import org.bukkit.NamespacedKey; import org.bukkit.entity.Wither; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.persistence.PersistentDataType; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -public class WitherTagListener implements Listener { +public class WitherTagEvents implements Listener { static final String ENTITY_ORIGIN_METADATA = "from-island"; private final uSkyBlock plugin; - public WitherTagListener(uSkyBlock plugin) { + public WitherTagEvents(uSkyBlock plugin) { this.plugin = plugin; } - @EventHandler(ignoreCancelled = true) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent event) { if (event.getSpawnReason() == CreatureSpawnEvent.SpawnReason.BUILD_WITHER && event.getEntity() instanceof Wither wither) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 740d82a69..8b661c51e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -325,7 +325,7 @@ public void registerEvents() { manager.registerEvents(new PlayerEvents(this), this); manager.registerEvents(new MenuEvents(this), this); manager.registerEvents(new ExploitEvents(this), this); - manager.registerEvents(new WitherTagListener(this), this); + manager.registerEvents(new WitherTagEvents(this), this); if (getConfig().getBoolean("options.protection.enabled", true)) { manager.registerEvents(new GriefEvents(this), this); if (getConfig().getBoolean("options.protection.item-drops", true)) { From 919488db88b29ada10d37d9882f684fb3d7ed089 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 30 Dec 2024 11:55:37 +0100 Subject: [PATCH 140/190] Remove attempt to call non-existent name2uuid importer This was a left-over from the removal of the name2uuid importer in f5b676c Resolves #67 --- .../src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 8b661c51e..97a47f7f6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -242,10 +242,6 @@ public void run() { WorldGuardHandler.setupGlobal(getWorldManager().getNetherWorld()); } registerEventsAndCommands(); - if (!getConfig().getBoolean("importer.name2uuid.imported", false)) { - Bukkit.getConsoleSender().sendMessage(tr("Converting data to UUID, this make take a while!")); - getImporter().importUSB(Bukkit.getConsoleSender(), "name2uuid"); - } getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 log(Level.INFO, getVersionInfo(false)); From 3d7c8209cb2e464077bf5650e93c6283fd9e244b Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 30 Dec 2024 23:50:47 +0100 Subject: [PATCH 141/190] Replace deprecated API calls and similar errors --- .../minecraft/animation/BlockAnimation.java | 29 +-- .../animation/ParticleAnimation.java | 47 ---- .../minecraft/animation/PlayerHandler.java | 61 ----- .../minecraft/command/AbstractCommand.java | 20 -- .../minecraft/command/DocumentCommand.java | 3 +- .../minecraft/command/LanguageCommand.java | 2 +- .../lockfuglsang/minecraft/file/FileUtil.java | 29 +-- .../command/PluginYamlCommandVisitorTest.java | 4 +- .../minecraft/file/FileUtilTest.java | 4 +- .../minecraft/nbt/NBTUtilTest.java | 7 +- .../minecraft/util/BukkitServerMock.java | 7 +- .../minecraft/util/FormatUtilTest.java | 4 +- .../minecraft/util/ItemStackMatcher.java | 11 +- .../minecraft/util/LocationUtilTest.java | 5 +- .../minecraft/yml/YmlConfigurationTest.java | 2 +- .../lockfuglsang/minecraft/po/I18nUtil.java | 8 +- .../minecraft/po/I18nUtilTest.java | 5 +- .../minecraft/po/POParserTest.java | 5 +- .../ultimateskyblock/api/IslandInfo.java | 2 + .../challenge/ChallengeFactory.java | 5 +- .../challenge/EntityMatch.java | 9 +- .../chat/IslandChatCommand.java | 2 +- .../command/admin/AdminIslandCommand.java | 1 - .../command/admin/LanguageCommand.java | 2 +- .../command/admin/RegionCommand.java | 2 +- .../command/island/InviteCommand.java | 1 - .../command/island/KickCommand.java | 1 - .../command/island/LeaveCommand.java | 1 - .../event/NetherTerraFormEvents.java | 43 ++-- .../ultimateskyblock/event/SpawnEvents.java | 7 +- .../handler/AsyncWorldEditHandler.java | 19 +- .../handler/WorldEditHandler.java | 8 +- .../handler/WorldGuardHandler.java | 10 +- .../placeholder/PlaceholderHandler.java | 18 +- .../task/WorldEditClearFlatlandTask.java | 51 ++--- .../fixuuidleader/UUIDLeaderImporter.java | 4 +- .../ultimateskyblock/island/IslandInfo.java | 31 ++- .../ultimateskyblock/island/IslandLogic.java | 43 ++-- .../island/TopTenComparator.java | 2 +- .../island/task/RecalculateTopTen.java | 4 +- .../ultimateskyblock/menu/SkyBlockMenu.java | 211 +++++++++--------- .../ultimateskyblock/player/PlayerInfo.java | 6 + .../ultimateskyblock/player/PlayerLogic.java | 39 ++-- .../ultimateskyblock/signs/SignEvents.java | 24 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 74 +++--- .../ultimateskyblock/util/EntityUtil.java | 29 --- .../ultimateskyblock/uuid/BukkitPlayerDB.java | 2 - .../TopTenComparatorTest.java | 6 +- .../challenge/ChallengeFactoryTest.java | 2 +- .../challenge/ChallengeFormatTest.java | 2 +- .../command/IslandChatCommandTest.java | 5 +- .../event/GriefEventsTest.java | 4 +- .../handler/WorldEditHandlerTest.java | 7 +- .../placeholder/TextPlaceholderTest.java | 4 +- .../island/IslandLocatorLogicTest.java | 2 +- .../island/OrphanComparatorTest.java | 8 +- .../ultimateskyblock/uSkyBlockTest.java | 4 +- .../ultimateskyblock/util/EntityUtilTest.java | 75 ------- .../ultimateskyblock/util/FileUtilTest.java | 4 +- .../util/LocationUtilTest.java | 4 +- .../util/MaterialUtilTest.java | 4 +- 61 files changed, 377 insertions(+), 658 deletions(-) delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java index 1d478ff5b..1f27df819 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/BlockAnimation.java @@ -1,7 +1,7 @@ package dk.lockfuglsang.minecraft.animation; import org.bukkit.Location; -import org.bukkit.Material; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import java.util.List; @@ -12,15 +12,13 @@ public class BlockAnimation implements Animation { private final Player player; private final List points; - private final Material material; - private final byte data; + private final BlockData blockData; private volatile boolean shown; - public BlockAnimation(Player player, List points, Material material, byte data) { + public BlockAnimation(Player player, List points, BlockData blockData) { this.player = player; this.points = points; - this.material = material; - this.data = data; + this.blockData = blockData; shown = false; } @@ -33,9 +31,7 @@ public boolean show() { return false; } for (Location loc : points) { - if (!PlayerHandler.sendBlockChange(player, loc, material, data)) { - return false; - } + player.sendBlockChange(loc, blockData); } shown = true; return true; @@ -43,19 +39,12 @@ public boolean show() { @Override public boolean hide() { - try { - if (shown) { - for (Location loc : points) { - if (!PlayerHandler.sendBlockChange(player, loc, loc.getBlock().getType(), loc.getBlock().getData())) { - return false; - } - } - return true; - } - return false; - } finally { + if (shown) { shown = false; + player.sendBlockChanges(points.stream().map(loc -> loc.getBlock().getState()).toList()); + return true; } + return false; } @Override diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java deleted file mode 100644 index c9d10e407..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/ParticleAnimation.java +++ /dev/null @@ -1,47 +0,0 @@ -package dk.lockfuglsang.minecraft.animation; - -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.entity.Player; - -import java.util.List; - -/** - * An animation using particles (requires refreshes). - */ -public class ParticleAnimation implements Animation { - private final Player player; - private final Particle particle; - private final List points; - private final int animCount; - - public ParticleAnimation(Player player, List points, Particle particle, int animCount) { - this.player = player; - this.particle = particle; - this.points = points; - this.animCount = animCount; - } - - @Override - public boolean show() { - if (!player.isOnline()) { - return false; - } - for (Location loc : points) { - if (!PlayerHandler.spawnParticle(player, particle, loc, animCount)) { - return false; - } - } - return true; - } - - @Override - public boolean hide() { - return true; - } - - @Override - public Player getPlayer() { - return player; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java deleted file mode 100644 index 8c9d968d6..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/animation/PlayerHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -package dk.lockfuglsang.minecraft.animation; - -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Particle; -import org.bukkit.entity.Player; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.logging.Logger; - -/** - * Common handler across servers for sending particles and other packages to a player. - */ -public enum PlayerHandler {; - private static final Logger log = Logger.getLogger(PlayerHandler.class.getName()); - - public static boolean spawnParticle(Player player, Particle particle, Location loc, int count) { - try { - Method playMethod = getMethod(player, "spawnParticle", new Class[]{Particle.class, Location.class, Integer.TYPE}); - if (playMethod != null) { - playMethod.invoke(player, particle, loc, count); - return true; - } - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - log.finest("Unable to spawnParticle for player " + player + ": " + e); - } - return false; - } - - public static boolean sendBlockChange(Player player, Location location, Material material, byte data) { - try { - Method method = getMethod(player, "sendBlockChange", new Class[]{Location.class, Material.class, Byte.TYPE}); - if (method != null) { - method.invoke(player, location, material, data); - return true; - } - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - log.finest("Unable to sendBlockChange to player " + player + ": " + e); - } - return false; - } - - public static boolean playEffect(Player player, Location loc, Effect effect, int data) { - try { - Method playMethod = getMethod(player, "playEffect", new Class[]{Location.class, Effect.class, Integer.TYPE}); - if (playMethod != null) { - playMethod.invoke(player, loc, effect, data); - return true; - } - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - log.finest("Unable to playEffect for player " + player + ": " + e); - } - return false; - } - - private static Method getMethod(Object player, String methodName, Class[] paramClasses) throws NoSuchMethodException { - return player.getClass().getMethod(methodName, paramClasses); - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java index 930da6f0d..a86d973ea 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/AbstractCommand.java @@ -107,26 +107,6 @@ public Map getFeaturePermissions() { return Collections.unmodifiableMap(featurePerms); } - /** - * Convenience method until we can fully rely on everybody running JRE 8. - * @param args A list of arguments - * @param delim Delimiter to join them - * @return A string containing the arguments concatenated. - */ - public static String join(String[] args, String delim) { - String res = ""; - if (args != null && args.length > 0) { - for (String arg : args) { - res += (res.isEmpty() ? "" : delim) + arg; - } - } - return res; - } - - public static String join(String[] args) { - return join(args, " "); - } - public boolean hasPermissionOverride(CommandSender sender) { if (sender instanceof Player) { return permissionOverride.contains(((Player) sender).getUniqueId()) || (parent != null && parent.hasPermissionOverride(sender)); diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java index 28be5cb92..f1b95699e 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/DocumentCommand.java @@ -10,6 +10,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -61,7 +62,7 @@ private boolean writeToFile(CommandSender sender, DocumentWriter visitor, String } File docFile = new File(plugin.getDataFolder(), filename); try (FileOutputStream fos = new FileOutputStream(docFile); - PrintStream ps = new PrintStream(fos, true, "UTF-8")) + PrintStream ps = new PrintStream(fos, true, StandardCharsets.UTF_8)) { visitor.writeTo(ps); sender.sendMessage(tr("Wrote documentation to {0}", docFile)); diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java index 35cbdf108..ea3d1a645 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java @@ -47,7 +47,7 @@ public boolean execute(CommandSender sender, String alias, Map d if (line.startsWith("---")) { header = false; } else if (!header && line.contains("|")) { - String parts[] = line.split("\\|"); + String[] parts = line.split("\\|"); if (parts.length == 7) { sb.append(tr("\u00a7f{0} \u00a77{1} \u00a79 by {2} \u00a77{3}\n", parts[1].trim(), parts[0].trim(), parts[6].trim(), parts[2].trim())); } diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java index 3edcfa212..25591fc5c 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/file/FileUtil.java @@ -6,6 +6,7 @@ import org.bukkit.configuration.file.YamlConfiguration; import java.io.*; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @@ -14,29 +15,31 @@ import java.util.logging.Level; import java.util.logging.Logger; +import static java.util.Objects.requireNonNull; + /** * Common file-utilities. */ public enum FileUtil { ; private static final Logger log = Logger.getLogger(FileUtil.class.getName()); - private static final Collection allwaysOverwrite = new ArrayList<>(); + private static final Collection alwaysOverwrite = new ArrayList<>(); private static final Collection neverOverwrite = new ArrayList<>(); private static final Map configFiles = new ConcurrentHashMap<>(); private static Locale locale = Locale.getDefault(); private static File dataFolder; - public static void setAllwaysOverwrite(String... configs) { + public static void setAlwaysOverwrite(String... configs) { for (String s : configs) { - if (!allwaysOverwrite.contains(s)) { - allwaysOverwrite.add(s); + if (!alwaysOverwrite.contains(s)) { + alwaysOverwrite.add(s); } } } public static void readConfig(FileConfiguration config, File file) { if (file == null) { - log.log(Level.INFO, "No " + file + " found, it will be created"); + log.log(Level.INFO, "No config file found, it will be created"); return; } File configFile = file; @@ -48,7 +51,7 @@ public static void readConfig(FileConfiguration config, File file) { log.log(Level.INFO, "No " + configFile + " found, it will be created"); return; } - try (Reader rdr = new InputStreamReader(new FileInputStream(configFile), "UTF-8")) { + try (Reader rdr = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { config.load(rdr); } catch (InvalidConfigurationException e) { log.log(Level.SEVERE, "Unable to read config file " + configFile, e); @@ -68,7 +71,7 @@ public static void readConfig(FileConfiguration config, InputStream inputStream) if (inputStream == null) { return; } - try (Reader rdr = new InputStreamReader(inputStream, "UTF-8")) { + try (Reader rdr = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { config.load(rdr); } catch (InvalidConfigurationException | IOException e) { log.log(Level.SEVERE, "Unable to read configuration", e); @@ -76,7 +79,7 @@ public static void readConfig(FileConfiguration config, InputStream inputStream) } public static String getBasename(String file) { - String[] lastPart = file.split("(/|\\\\)"); + String[] lastPart = file.split("([/\\\\])"); file = lastPart[lastPart.length - 1]; if (file != null && file.lastIndexOf('.') != -1) { return file.substring(0, file.lastIndexOf('.')); @@ -138,7 +141,7 @@ public static FileConfiguration getYmlConfiguration(String configName) { Files.move(Paths.get(configFile.toURI()), Paths.get(new File(backupFolder, bakFile).toURI()), StandardCopyOption.REPLACE_EXISTING); - if (allwaysOverwrite.contains(configName)) { + if (alwaysOverwrite.contains(configName)) { FileUtil.copy(getResource(configName), configFile); config = configJar; } else { @@ -202,8 +205,6 @@ private static FileConfiguration mergeConfig(FileConfiguration src, FileConfigur dest.setDefaults(src); dest.options().copyDefaults(true); dest.set("version", version); - dest.options().copyHeader(false); - src.options().copyHeader(false); removeExcludes(dest); moveNodes(src, dest); replaceDefaults(src, dest); @@ -216,7 +217,7 @@ private static FileConfiguration mergeConfig(FileConfiguration src, FileConfigur private static void removeExcludes(FileConfiguration dest) { List keys = dest.getStringList("merge-ignore"); for (String key : keys) { - dest.getDefaults().set(key, null); + requireNonNull(dest.getDefaults()).set(key, null); } } @@ -233,7 +234,7 @@ private static void replaceDefaults(FileConfiguration src, FileConfiguration des } } dest.set("force-replace", null); - dest.getDefaults().set("force-replace", null); + requireNonNull(dest.getDefaults()).set("force-replace", null); } private static void moveNodes(FileConfiguration src, FileConfiguration dest) { @@ -259,7 +260,7 @@ private static void moveNodes(FileConfiguration src, FileConfiguration dest) { } } dest.set("move-nodes", null); - dest.getDefaults().set("move-nodes", null); + requireNonNull(dest.getDefaults()).set("move-nodes", null); } public static void setDataFolder(File dataFolder) { diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java index 32dcfcb5c..2da17d608 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/PluginYamlCommandVisitorTest.java @@ -8,7 +8,7 @@ import java.nio.file.Paths; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class PluginYamlCommandVisitorTest { @Test @@ -52,4 +52,4 @@ public void writeToSimpleFeatureMap() throws Exception { visitor.writeTo(out); assertThat(baos.toString(), is(expected)); } -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java index d0697dffd..a65c357f4 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/file/FileUtilTest.java @@ -3,7 +3,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; /** * JUnit tests for FileUtil @@ -20,4 +20,4 @@ public void testBaseName() { assertThat(FileUtil.getBasename("dir/something/filename.txt"), is("filename")); assertThat(FileUtil.getBasename("dir\\something\\filename.txt"), is("filename")); } -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java index 7a4a034cc..911df5c52 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/nbt/NBTUtilTest.java @@ -1,6 +1,7 @@ package dk.lockfuglsang.minecraft.nbt; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import org.hamcrest.CoreMatchers; import org.junit.Test; @@ -10,7 +11,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * Tests the NBTUtil @@ -25,10 +26,10 @@ public void testJSONMap() { String jsonString = "{\"Potion\":\"minecraft:empty\",\"CustomPotionEffects\":[{\"Id\":1},{\"Id\":2}]}"; Gson gson = new Gson(); - Map map = (Map) gson.fromJson(new StringReader(jsonString), Map.class); + Map map = gson.fromJson(new StringReader(jsonString), new TypeToken>(){}.getType()); assertThat(map.get("Potion"), CoreMatchers.is("minecraft:empty")); assertThat(map.get("CustomPotionEffects"), instanceOf(List.class)); - assertThat(((List)map.get("CustomPotionEffects")).get(0), instanceOf(Map.class)); + assertThat(((List)map.get("CustomPotionEffects")).getFirst(), instanceOf(Map.class)); } @Test diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java index 94bc3f04e..97e639fac 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/BukkitServerMock.java @@ -17,7 +17,6 @@ import java.util.Objects; import java.util.TreeMap; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; public class BukkitServerMock { @@ -36,6 +35,7 @@ public static Server setupServerMock() throws NoSuchFieldException, IllegalAcces return serverMock; } + @SuppressWarnings("deprecation") public static Server createServerMock() { Server serverMock = mock(Server.class); ItemFactory itemFactoryMock = mock(ItemFactory.class); @@ -84,11 +84,12 @@ public static Server createServerMock() { when(serverMock.getItemFactory()).thenReturn(itemFactoryMock); UnsafeValues unsafeMock = mock(UnsafeValues.class); - when(unsafeMock.fromLegacy(any(Material.class))).thenAnswer(a -> (Material) a.getArguments()[0]); + when(unsafeMock.fromLegacy(any(Material.class))).thenAnswer(a -> a.getArguments()[0]); when(serverMock.getUnsafe()).thenReturn(unsafeMock); return serverMock; } + @SuppressWarnings("unchecked") public static ItemMeta createItemMetaStub() { if (!useMetaData) { return null; @@ -103,7 +104,7 @@ public static ItemMeta createItemMetaStub() { if (displayName.isEmpty()) { metaData.remove("displayName"); } else { - metaData.put("displayName", "" + displayName); + metaData.put("displayName", displayName); } return null; }).when(meta).setDisplayName(any(String.class)); diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java index ea3a79d7f..b2d505593 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/FormatUtilTest.java @@ -6,7 +6,7 @@ import static dk.lockfuglsang.minecraft.util.FormatUtil.*; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class FormatUtilTest { @@ -64,4 +64,4 @@ public void testEscape() throws Exception { String text = "\u00a7eHello World\r\n\u00a7aThis is a \u00a7kmagic\r\n\u00a7lhej"; assertThat(escape(text), is("&eHello World\r\n&aThis is a &kmagic\r\n&lhej")); } -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java index 36a9e953f..972705eac 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/ItemStackMatcher.java @@ -44,15 +44,10 @@ public static Matcher> itemStacks(Collection> itemStacks(ItemStack... items) { - List> matchers = new ArrayList(); - ItemStack[] arr$ = items; - int len$ = items.length; - - for(int i$ = 0; i$ < len$; ++i$) { - ItemStack item = arr$[i$]; + List> matchers = new ArrayList<>(); + for (ItemStack item : items) { matchers.add(itemStack(item)); } - - return contains((List)matchers); + return contains(matchers); } } diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java index cf2d39184..397528f89 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/util/LocationUtilTest.java @@ -7,7 +7,7 @@ import org.junit.Test; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -60,5 +60,4 @@ public void fromString_asKey() { String key = "world/1_12,-34_12,2_00"; assertThat(LocationUtil.asString(LocationUtil.fromString(key)), is(LocationUtil.asString(loc))); } - -} \ No newline at end of file +} diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java index 8b70a8bea..4db603ec3 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/yml/YmlConfigurationTest.java @@ -7,7 +7,7 @@ import java.io.File; import java.util.List; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class YmlConfigurationTest { @Test diff --git a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java index e701b9951..cdc138a3a 100644 --- a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java +++ b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java @@ -131,13 +131,13 @@ public static void clearCache() { @Contract("null -> null") public static Locale getLocale(@Nullable String lang) { if (lang != null) { - String[] parts = lang.split("[_\\-]"); + String[] parts = lang.split("[-_]"); if (parts.length >= 3) { - return new Locale(parts[0], parts[1], parts[2]); + return Locale.of(parts[0], parts[1], parts[2]); } else if (parts.length == 2) { - return new Locale(parts[0], parts[1]); + return Locale.of(parts[0], parts[1]); } else { - return new Locale(parts[0]); + return Locale.of(parts[0]); } } return null; diff --git a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java index 8bb4316c9..d5416f68d 100644 --- a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java +++ b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java @@ -7,8 +7,9 @@ import java.net.URL; import java.util.Locale; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNull; public class I18nUtilTest { @Before @@ -101,7 +102,7 @@ public void testPre_withNonFormattedString() { assertThat(I18nUtil.pre(TEST_STRING), is(TEST_STRING)); } - + @Test public void testPre_withFormattedString() { String TEST_STRING = "\u00a7bThis is a test for {0} regarding {1}."; diff --git a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/POParserTest.java b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/POParserTest.java index f3edda683..0f7c522f9 100644 --- a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/POParserTest.java +++ b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/POParserTest.java @@ -7,7 +7,7 @@ import java.util.Properties; import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class POParserTest { @@ -74,5 +74,4 @@ private void verifyProps(String name) throws IOException { assertThat(properties.getProperty(key), is(value)); } } - -} \ No newline at end of file +} diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java index 37cf90b94..facb2c4e1 100644 --- a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java @@ -100,6 +100,7 @@ public interface IslandInfo { * @return True if the player has been banned from this island. * @deprecated Use {@link IslandInfo#isBanned(OfflinePlayer)} */ + @Deprecated(since = "2.7.10") boolean isBanned(Player player); /** @@ -164,6 +165,7 @@ public interface IslandInfo { * @return List of players trusted on this island. * @deprecated Use #getTrusteeUUIDs instead */ + @Deprecated(since = "2.7") List getTrustees(); /** diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index 0df3c5bb3..ecace5327 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -3,6 +3,7 @@ import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.ItemRequirement; import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.Registry; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; @@ -85,8 +86,8 @@ private static List createEntities(List requiredEntities) { String meta = m.group("meta"); String countStr = m.group("count"); int count = countStr != null ? Integer.parseInt(countStr, 10) : 1; - EntityType entityType = EntityType.fromName(type); - Map map = meta != null ? MetaUtil.createMap(meta.substring(1)) : new HashMap(); // skip the leading ':' + EntityType entityType = Registry.ENTITY_TYPE.match(type); + Map map = meta != null ? MetaUtil.createMap(meta.substring(1)) : new HashMap<>(); // skip the leading ':' if (entityType != null) { entities.add(new EntityMatch(entityType, map, count)); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java index 2f1660977..d86c19651 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/EntityMatch.java @@ -70,7 +70,7 @@ public boolean matches(@Nullable Entity entity) { private boolean matchFieldGetter(Entity entity, String key, Object value) { try { - Method method = entity.getClass().getMethod("get" + key, null); + Method method = entity.getClass().getMethod("get" + key); Object entityValue = method.invoke(entity); return matchValues(entityValue, value); } catch (InvocationTargetException | IllegalAccessException e) { @@ -84,7 +84,7 @@ private boolean matchFieldGetter(Entity entity, String key, Object value) { private boolean matchField(Entity entity, String key, Object value) { try { Field field = entity.getClass().getDeclaredField(key); - boolean wasAccessible = field.isAccessible(); + boolean wasAccessible = field.canAccess(this); if (!wasAccessible) { field.setAccessible(true); } @@ -102,9 +102,9 @@ private boolean matchField(Entity entity, String key, Object value) { private boolean matchValues(Object entityValue, Object value) { if (value instanceof Number && entityValue instanceof Enum) { - return ((Number) value).intValue() == ((Enum) entityValue).ordinal(); + return ((Number) value).intValue() == ((Enum) entityValue).ordinal(); } else if (value instanceof String && entityValue instanceof Enum) { - return ((String) value).equalsIgnoreCase(((Enum) entityValue).name()); + return ((String) value).equalsIgnoreCase(((Enum) entityValue).name()); } return ("" + entityValue).equalsIgnoreCase("" + value); } @@ -158,6 +158,7 @@ public String getDisplayName() { * @return Corresponding DyeColor, defaults to WHITE on invalid or NULL input. * @deprecated To be used for legacy challenge configs only, use {@link EntityMatch#getColor(String)}. */ + @Deprecated(since = "2.11") private @NotNull DyeColor getColor(@Nullable Number input) { if (input == null) { return DyeColor.WHITE; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandChatCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandChatCommand.java index 26398b42b..5d7adf308 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandChatCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandChatCommand.java @@ -53,7 +53,7 @@ public boolean execute(CommandSender commandSender, String alias, Map data, String... args) { IslandInfo islandInfo = null; if (args.length == 2) { - //noinspection deprecation islandInfo = plugin.getIslandInfo(Bukkit.getPlayer(args[1])); } else if (args.length == 1 && sender instanceof Player) { String islandName = WorldGuardHandler.getIslandNameAt(((Player) sender).getLocation()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java index cde30eae4..5c303e9b8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java @@ -53,7 +53,7 @@ public boolean execute(CommandSender sender, String alias, Map d if (line.startsWith("---")) { header = false; } else if (!header && line.contains("|")) { - String parts[] = line.split("\\|"); + String[] parts = line.split("\\|"); if (parts.length == 7) { sb.append(tr("\u00a7f{0} \u00a77{1} \u00a79 by {2} \u00a77{3}\n", parts[1].trim(), parts[0].trim(), parts[6].trim(), parts[2].trim())); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java index e58664abc..2108fb3be 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java @@ -255,6 +255,6 @@ public void setMaterial(Material material) { } public synchronized void addAnimation(Player player, List points) { - animationHandler.addAnimation(new BlockAnimation(player, points, material, (byte) 0)); + animationHandler.addAnimation(new BlockAnimation(player, points, material.createBlockData())); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java index cf5188ce2..a611269bd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java @@ -40,7 +40,6 @@ protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandIn } } if (args.length == 1) { - //noinspection deprecation Player otherPlayer = Bukkit.getPlayer(args[0]); if (!island.hasPerm(player, "canInviteOthers")) { player.sendMessage(I18nUtil.tr("\u00a74You do not have permission to invite others to this island!")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java index 8f11f146f..980c54ac2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java @@ -11,7 +11,6 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; -@SuppressWarnings("deprecation") public class KickCommand extends RequireIslandCommand { public KickCommand(uSkyBlock plugin) { super(plugin, "kick|remove", "usb.party.kick", "player", marktr("remove a member from your island.")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java index 24de8e602..e2944ed0b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java @@ -11,7 +11,6 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -@SuppressWarnings("deprecation") public class LeaveCommand extends RequireIslandCommand { public LeaveCommand(uSkyBlock plugin) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java index a02664923..6c4bebe70 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java @@ -38,7 +38,7 @@ */ public class NetherTerraFormEvents implements Listener { private final uSkyBlock plugin; - private final Map> terraFormMap = new HashMap<>(); + private final Map> terraFormMap = new HashMap<>(); private final Map toolWeights = new HashMap<>(); private static final Random RND = new Random(System.currentTimeMillis()); private final double maxScan; @@ -104,8 +104,7 @@ public void onBlockBreak(BlockBreakEvent event) { if (!terraFormMap.containsKey(block.getType())) { return; // Not a block we terra-form on. } - // TODO: 10/07/2016 - R4zorax: Handle dual-wielding (would break 1.8 compatibility) - ItemStack tool = event.getPlayer().getItemInHand(); + ItemStack tool = event.getPlayer().getInventory().getItemInMainHand(); if (event.getBlock().getDrops(tool).isEmpty()) { return; // Only terra-form when stuff is mined correctly } @@ -132,7 +131,7 @@ private Double getToolWeight(ItemStack tool) { } private void spawnBlock(Material type, Location location, Vector v, ProtectedCuboidRegion islandRegion) { - Location spawnLoc = null; + Location spawnLoc; if (MaterialUtil.isFallingMaterial(type)) { spawnLoc = findSolidSpawnLocation(location, v, islandRegion); } else { @@ -146,18 +145,18 @@ private void spawnBlock(Material type, Location location, Vector v, ProtectedCub private Location findAirSpawnLocation(Location location, Vector v, ProtectedCuboidRegion islandRegion) { // Searches in a cone for an air block Location lookAt = new Location(location.getWorld(), - Math.round(location.getX() + v.getX()), - Math.round(location.getY() + v.getY()), - Math.round(location.getZ() + v.getZ())); + Math.round(location.getX() + v.getX()), + Math.round(location.getY() + v.getY()), + Math.round(location.getZ() + v.getZ())); while (v.length() < maxScan) { for (Location loc : getLocationsInPlane(lookAt, v)) { if (loc.getBlock().getType() == Material.AIR && isAdjacentToSolid(loc) - && isInIslandRegion(islandRegion, loc)) { + && isInIslandRegion(islandRegion, loc)) { return loc; } } double n = v.length(); - v.normalize().multiply(n+1); + v.normalize().multiply(n + 1); } return null; } @@ -180,22 +179,22 @@ private Location findSolidSpawnLocation(Location location, Vector v, ProtectedCu while (v.length() < maxScan) { for (Location loc : getLocationsInPlane(location, v)) { if (loc.getBlock().getType() == Material.AIR - && loc.getBlock().getRelative(BlockFace.DOWN).getType().isSolid() - && isInIslandRegion(islandRegion, loc)) { + && loc.getBlock().getRelative(BlockFace.DOWN).getType().isSolid() + && isInIslandRegion(islandRegion, loc)) { return loc; } } double n = v.length(); - v.normalize().multiply(n+1); + v.normalize().multiply(n + 1); } return null; } private List getLocationsInPlane(Location location, Vector v) { Location lookAt = new Location(location.getWorld(), - Math.round(location.getX() + v.getX()), - Math.round(location.getY() + v.getY()), - Math.round(location.getZ() + v.getZ())); + Math.round(location.getX() + v.getX()), + Math.round(location.getY() + v.getY()), + Math.round(location.getZ() + v.getZ())); List locs = new ArrayList<>(); boolean xFixed = Math.abs(v.getX()) > Math.abs(v.getZ()); for (int r = 1; r <= v.length(); r++) { @@ -210,14 +209,14 @@ private List getLocationsInPlane(Location location, Vector v) { } } Collections.shuffle(locs); - locs = locs.subList(0, locs.size()/2); // Only try half + locs = locs.subList(0, locs.size() / 2); // Only try half return locs; } public List getYield(Material material, double toolWeight) { List copy = new ArrayList<>(); for (MaterialUtil.MaterialProbability e : terraFormMap.get(material)) { - if (RND.nextDouble() < e.getProbability()*toolWeight) { + if (RND.nextDouble() < e.getProbability() * toolWeight) { copy.add(e.getMaterial()); } } @@ -230,8 +229,7 @@ public void onGhastExplode(EntityExplodeEvent event) { return; // Bail out, not our problem } // TODO: 23/09/2015 - R4zorax: Perhaps enable this when island has a certain level? - if (event.getEntity() instanceof Fireball) { - Fireball fireball = (Fireball) event.getEntity(); + if (event.getEntity() instanceof Fireball fireball) { fireball.setIsIncendiary(false); fireball.setFireTicks(0); event.setCancelled(true); @@ -239,8 +237,7 @@ public void onGhastExplode(EntityExplodeEvent event) { } /** - * Comes AFTER the SpawnEvents{@link #onCreatureSpawn(CreatureSpawnEvent)} - so cancelled will have effect - * @param e + * Comes AFTER the {@link SpawnEvents#onCreatureSpawn(CreatureSpawnEvent)} - so cancelled will have effect */ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent e) { @@ -264,9 +261,9 @@ public void onCreatureSpawn(CreatureSpawnEvent e) { WitherSkeleton mob = (WitherSkeleton) e.getLocation().getWorld().spawnEntity( e.getLocation(), EntityType.WITHER_SKELETON); mob.getEquipment().setItemInMainHand(new ItemStack(Material.STONE_SWORD, 1)); - } else if (p <= chanceWither+chanceBlaze) { + } else if (p <= chanceWither + chanceBlaze) { e.getLocation().getWorld().spawnEntity(e.getLocation(), EntityType.BLAZE); - } else if (p <= chanceWither+chanceBlaze+chanceSkeleton) { + } else if (p <= chanceWither + chanceBlaze + chanceSkeleton) { e.getLocation().getWorld().spawnEntity(e.getLocation(), EntityType.SKELETON); } else { e.setCancelled(false); // Spawn PigZombie diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index e9e0befba..5091ad552 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -46,8 +46,8 @@ public SpawnEvents(uSkyBlock plugin) { @EventHandler public void onSpawnEggEvent(PlayerInteractEvent event) { - Player player = event != null ? event.getPlayer() : null; - if (player == null || event.isCancelled() || !plugin.getWorldManager().isSkyWorld(player.getWorld())) { + Player player = event.getPlayer(); + if (event.useItemInHand() == Event.Result.DENY || !plugin.getWorldManager().isSkyWorld(player.getWorld())) { return; // Bail out, we don't care } if (player.hasPermission("usb.mod.bypassprotection") || player.isOp()) { @@ -61,8 +61,9 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { return; } + //noinspection deprecation checkLimits(event, spawnEggMeta.getSpawnedType(), player.getLocation()); - if (event.isCancelled()) { + if (event.useItemInHand() == Event.Result.DENY) { plugin.notifyPlayer(player, tr("\u00a7cYou have reached your spawn-limit for your island.")); event.setUseItemInHand(Event.Result.DENY); event.setUseInteractedBlock(Event.Result.DENY); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index f2783b531..02ff035dd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -110,18 +110,13 @@ public EditSession createEditSession(World world, int maxBlocks) { @Override public void regenerate(final Region region, final Runnable onCompletion) { - uSkyBlock.getInstance().sync(new Runnable() { - @Override - public void run() { - try { - final EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), (int) region.getVolume()); - editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); - editSession.setSideEffectApplier(SideEffectSet.defaults()); - editSession.getWorld().regenerate(region, editSession); - editSession.flushSession(); - } finally { - onCompletion.run(); - } + uSkyBlock.getInstance().sync(() -> { + try (EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), (int) region.getVolume())) { + editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); + editSession.setSideEffectApplier(SideEffectSet.defaults()); + editSession.getWorld().regenerate(region, editSession); + } finally { + onCompletion.run(); } }); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java index 9feb9fbc0..4b9ed7541 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java @@ -170,11 +170,11 @@ public static Set getChunks(Region region) { * M(x) = X mod 16, i.e. Mc = C mod 16. * * Borders: - * O = A + 16 - Ma | A > 0 - * = A - Ma | A <= 0 + * {@code O = A + 16 - Ma | A > 0} + * {@code = A - Ma | A <= 0} * - * Q = C - Mc - 1 | C > 0 && Mc != 15 - * = C + Mc - 16 | C < 0 && Mc != -1 + * {@code Q = C - Mc - 1 | C > 0 && Mc != 15} + * {@code = C + Mc - 16 | C < 0 && Mc != -1} * */ public static Set getBorderRegions(Region region) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index 48dcbd27d..c6fa5e3cd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; @@ -75,7 +74,7 @@ public static boolean protectIsland(uSkyBlock plugin, CommandSender sender, Isla try { RegionManager regionManager = getRegionManager(plugin.getWorldManager().getWorld()); String regionName = islandConfig.getName() + "island"; - if (islandConfig != null && noOrOldRegion(regionManager, regionName, islandConfig)) { + if (noOrOldRegion(regionManager, regionName, islandConfig)) { updateRegion(islandConfig); islandConfig.setRegionVersion(getVersion()); return true; @@ -121,6 +120,7 @@ private static ProtectedCuboidRegion setRegionFlags(IslandInfo islandConfig) { return setRegionFlags(islandConfig, regionName); } + @SuppressWarnings("deprecation") // WorldGuard flags are deprecated to warn developers without replacement option private static ProtectedCuboidRegion setRegionFlags(IslandInfo islandConfig, String regionName) { Location islandLocation = islandConfig.getIslandLocation(); BlockVector3 minPoint = getProtectionVectorRight(islandLocation); @@ -308,11 +308,7 @@ public static Set getIntersectingRegions(Location islandLocatio RegionManager regionManager = getRegionManager(islandLocation.getWorld()); ApplicableRegionSet applicableRegions = regionManager.getApplicableRegions(getIslandRegion(islandLocation)); Set regions = getRegions(applicableRegions); - for (Iterator iterator = regions.iterator(); iterator.hasNext(); ) { - if (iterator.next() instanceof GlobalProtectedRegion) { - iterator.remove(); - } - } + regions.removeIf(protectedRegion -> protectedRegion instanceof GlobalProtectedRegion); log.exiting(CN, "getIntersectingRegions"); return regions; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java index 377ca08ed..21ded1e60 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java @@ -10,9 +10,9 @@ public class PlaceholderHandler { private static final String[] ADAPTORS = { - ChatPlaceholder.class.getName(), - ServerCommandPlaceholder.class.getName(), - "us.talabrek.ultimateskyblock.handler.placeholder.MVdWPlaceholderAPI", + ChatPlaceholder.class.getName(), + ServerCommandPlaceholder.class.getName(), + "us.talabrek.ultimateskyblock.handler.placeholder.MVdWPlaceholderAPI", }; private static PlaceholderAPI.PlaceholderReplacer replacer; @@ -24,10 +24,9 @@ public static void register(uSkyBlock plugin) { String baseName = FileUtil.getExtension(className); if (plugin.getConfig().getBoolean("placeholder." + baseName.toLowerCase(), false)) { try { - Class aClass = Class.forName(className); - Object o = aClass.newInstance(); - if (o instanceof PlaceholderAPI) { - PlaceholderAPI api = (PlaceholderAPI) o; + Class clazz = Class.forName(className); + Object o = clazz.getDeclaredConstructor().newInstance(); + if (o instanceof PlaceholderAPI api) { if (api.registerPlaceholder(plugin, placeholderReplacer)) { plugin.getLogger().info("uSkyBlock hooked into " + baseName); apis.add(api); @@ -35,8 +34,7 @@ public static void register(uSkyBlock plugin) { plugin.getLogger().info("uSkyBlock failed to hook into " + baseName); } } - } catch (Throwable e) { - // Ignore + } catch (Exception e) { plugin.getLogger().info("uSkyBlock failed to hook into " + baseName); } } @@ -45,7 +43,7 @@ public static void register(uSkyBlock plugin) { public static void unregister(uSkyBlock plugin) { PlaceholderAPI.PlaceholderReplacer placeholderReplacer = getReplacer(plugin); - for (Iterator it = apis.iterator(); it.hasNext();) { + for (Iterator it = apis.iterator(); it.hasNext(); ) { it.next().unregisterPlaceholder(plugin, placeholderReplacer); it.remove(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java index d371250eb..6871d0566 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java @@ -21,6 +21,7 @@ import java.util.Set; import java.util.logging.Level; +import static java.util.Objects.requireNonNull; import static us.talabrek.ultimateskyblock.util.LogUtil.log; /** @@ -28,7 +29,7 @@ * Not as fast as WorldEditRegenTask, but more versatile. */ public class WorldEditClearFlatlandTask extends IncrementalRunnable { - private static final BlockState AIR = BlockTypes.AIR.getDefaultState(); + private static final BlockState AIR = requireNonNull(BlockTypes.AIR).getDefaultState(); private final Set borderRegions; private final Set innerChunks; @@ -51,7 +52,7 @@ public WorldEditClearFlatlandTask(final uSkyBlock plugin, final CommandSender co bukkitWorld = new BukkitWorld(plugin.getWorldManager().getWorld()); minY = Math.min(region.getMinimumPoint().getBlockY(), region.getMaximumPoint().getBlockY()); maxY = Math.max(region.getMinimumPoint().getBlockY(), region.getMaximumPoint().getBlockY()); - maxBlocks = 2*Math.max(region.getLength(), region.getWidth())*16*(maxY-minY); + maxBlocks = 2 * Math.max(region.getLength(), region.getWidth()) * 16 * (maxY - minY); } @Override @@ -59,32 +60,32 @@ public boolean execute() { Iterator inner = innerChunks.iterator(); Iterator border = borderRegions.iterator(); while (!isComplete()) { - EditSession editSession = AsyncWorldEditHandler.createEditSession(bukkitWorld, maxBlocks); - editSession.setSideEffectApplier(SideEffectSet.defaults()); - editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); - if (inner.hasNext()) { - BlockVector2 chunk = inner.next(); - inner.remove(); - try { - int x = chunk.getX() << 4; - int z = chunk.getZ() << 4; - editSession.setBlocks(new CuboidRegion(bukkitWorld, - BlockVector3.at(x, minY, z), - BlockVector3.at(x + 15, maxY, z + 15)), + try (EditSession editSession = AsyncWorldEditHandler.createEditSession(bukkitWorld, maxBlocks)) { + editSession.setSideEffectApplier(SideEffectSet.defaults()); + editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); + if (inner.hasNext()) { + BlockVector2 chunk = inner.next(); + inner.remove(); + try { + int x = chunk.getX() << 4; + int z = chunk.getZ() << 4; + editSession.setBlocks(new CuboidRegion(bukkitWorld, + BlockVector3.at(x, minY, z), + BlockVector3.at(x + 15, maxY, z + 15)), AIR); - } catch (MaxChangedBlocksException e) { - plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); - } - } else if (border.hasNext()) { - Region borderRegion = border.next(); - border.remove(); - try { - editSession.setBlocks(borderRegion, AIR); - } catch (MaxChangedBlocksException e) { - plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); + } catch (MaxChangedBlocksException e) { + plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); + } + } else if (border.hasNext()) { + Region borderRegion = border.next(); + border.remove(); + try { + editSession.setBlocks(borderRegion, AIR); + } catch (MaxChangedBlocksException e) { + plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); + } } } - editSession.flushSession(); if (!tick()) { break; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java index 68e6831de..d36f515de 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java @@ -10,7 +10,7 @@ import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -46,7 +46,7 @@ public Boolean importFile(File file) { boolean changed = false; String leaderName = null; try (FileWriter fw = new FileWriter(ymlPath.toFile()); BufferedWriter out = new BufferedWriter(fw)) { - for (String line : Files.readAllLines(file.toPath(), Charset.forName("UTF-8"))) { + for (String line : Files.readAllLines(file.toPath(), StandardCharsets.UTF_8)) { if (line.contains("leader:")) { leaderName = line.substring(line.indexOf("leader:") + 7).trim(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 8d7140a82..32c56cf10 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -205,7 +205,7 @@ public void updatePermissionPerks(@NotNull final Player member, @NotNull Perk pe if (isLeader(member)) { String oldLeaderName = getLeader(); config.set("party.leader", member.getName()); - updateRegion |= !oldLeaderName.equals(member.getName()); + updateRegion = !oldLeaderName.equals(member.getName()); } ConfigurationSection section = config.getConfigurationSection("party.members." + member.getUniqueId()); boolean dirty = false; @@ -385,7 +385,7 @@ public boolean hasPerm(String playerName, String perm) { return hasPerm(plugin.getPlayerDB().getUUIDFromName(playerName), perm); } - private boolean hasPerm(UUID uuid, String perm) { + public boolean hasPerm(UUID uuid, String perm) { return uuid.equals(getLeaderUniqueId()) || config.getBoolean("party.members." + UUIDUtil.asString(uuid) + "." + perm); } @@ -415,17 +415,26 @@ public void setWarpLocation(@Nullable Location loc) { save(); } + // TODO: deprecate and replace all string-based methods + // TODO: unify all methods to take/return a custom Profile type that is guaranteed to contain a UUID and a name public boolean togglePerm(@NotNull final String playername, @NotNull final String perm) { Validate.notNull(playername, "Playername cannot be null"); Validate.notEmpty(playername, "Playername cannot be empty"); + + UUID uuid = plugin.getPlayerDB().getUUIDFromName(playername); + return togglePerm(uuid, perm); + } + + public boolean togglePerm(@NotNull final UUID playerId, @NotNull final String perm) { + Validate.notNull(playerId, "Playername cannot be null"); Validate.notNull(perm, "Perm cannot be null"); Validate.notEmpty(perm, "Perm cannot be empty"); - String uuidString = UUIDUtil.asString(plugin.getPlayerDB().getUUIDFromName(playername)); + String uuidString = UUIDUtil.asString(playerId); ConfigurationSection memberSection = config.getConfigurationSection("party.members." + uuidString); try { if (memberSection == null) { - log.info("Perms for " + playername + " failed to toggle because player is not a part of that island!"); + log.info("Perms for " + playerId + " failed to toggle because player is not a part of that island!"); return false; } if (memberSection.getBoolean(perm, false)) { @@ -436,7 +445,7 @@ public boolean togglePerm(@NotNull final String playername, @NotNull final Strin save(); return true; } catch (NullPointerException e) { - log.info("Perms for " + playername + " failed to toggle because player is not a part of that island!"); + log.info("Perms for " + playerId + " failed to toggle because player is not a part of that island!"); return false; } } @@ -507,7 +516,7 @@ public void log(@NotNull String message, @Nullable Object[] args) { sb.append(";").append(arg); } } - log.add(0, sb.toString()); + log.addFirst(sb.toString()); int logSize = plugin.getConfig().getInt("options.island.log-size", 10); if (log.size() > logSize) { log = log.subList(0, logSize); @@ -524,18 +533,22 @@ public int getPartySize() { public boolean isLeader(@NotNull OfflinePlayer target) { Validate.notNull(target, "Target cannot be null"); - return target.getUniqueId().equals(getLeaderUniqueId()); + return isLeader(target.getUniqueId()); } @Override - public boolean isLeader(Player player) { - return player.getUniqueId().equals(getLeaderUniqueId()); + public boolean isLeader(@NotNull Player player) { + return isLeader(player.getUniqueId()); } public boolean isLeader(String playerName) { return getLeaderUniqueId().equals(plugin.getPlayerDB().getUUIDFromName(playerName)); } + public boolean isLeader(@NotNull UUID playerId) { + return getLeaderUniqueId().equals(playerId); + } + public boolean hasWarp() { return config.getBoolean("general.warpActive"); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java index 096047dd3..be230b852 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java @@ -4,7 +4,6 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; import com.google.gson.GsonBuilder; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -17,6 +16,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.IslandLevel; import us.talabrek.ultimateskyblock.api.IslandRank; @@ -76,27 +76,19 @@ public IslandLogic(uSkyBlock plugin, File directoryIslands, OrphanLogic orphanLo cache = CacheBuilder .from(plugin.getConfig().getString("options.advanced.islandCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) - .removalListener(new RemovalListener() { - @Override - public void onRemoval(RemovalNotification removal) { - log.fine("Removing island-info " + removal.getKey() + " from cache"); - removal.getValue().saveToFile(); - } + .removalListener((RemovalListener) removal -> { + log.fine("Removing island-info " + removal.getKey() + " from cache"); + removal.getValue().saveToFile(); }) - .build(new CacheLoader() { + .build(new CacheLoader<>() { @Override - public IslandInfo load(String islandName) throws Exception { + public @NotNull IslandInfo load(@NotNull String islandName) { log.fine("Loading island-info " + islandName + " to cache!"); return new IslandInfo(islandName, plugin); } }); long every = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.advanced.island.saveEvery", 30)); - saveTask = plugin.async(new Runnable() { - @Override - public void run() { - saveDirtyToFiles(); - } - }, every, every); + saveTask = plugin.async(this::saveDirtyToFiles, every, every); } private void saveDirtyToFiles() { @@ -118,7 +110,7 @@ public synchronized IslandInfo getIslandInfo(String islandName) { throw new IllegalStateException("Unable to load island", e); } } - + public IslandInfo getIslandInfo(PlayerInfo playerInfo) { if (playerInfo != null && playerInfo.getHasIsland()) { return getIslandInfo(playerInfo.locationForParty()); @@ -217,7 +209,7 @@ public void displayTopTen(final CommandSender sender, int page) { page = 1; } sender.sendMessage(tr("\u00a7eWALL OF FAME (page {0} of {1}):", page, maxpage)); - if (ranks == null || ranks.isEmpty()) { + if (ranks.isEmpty()) { if (Settings.island_useTopTen) { sender.sendMessage(tr("\u00a74Top ten list is empty! Only islands above level {0} is considered.", topTenCutoff)); } else { @@ -239,8 +231,7 @@ public void displayTopTen(final CommandSender sender, int page) { } String message = String.format(tr("\u00a7a#%2d \u00a77(%5.2f): \u00a7e%s \u00a77%s"), place, level.getScore(), level.getLeaderName(), members); - if (sender instanceof Player) { - Player target = (Player) sender; + if (sender instanceof Player target) { String warpString = getJsonWarpString( message, tr("Click to warp to the island!"), @@ -360,7 +351,7 @@ public synchronized IslandInfo createIslandInfo(String location, String player) public synchronized void deleteIslandConfig(final String location) { try { IslandInfo islandInfo = cache.get(location); - updateRank(islandInfo, new IslandScore(0, Collections.EMPTY_LIST)); + updateRank(islandInfo, new IslandScore(0, Collections.emptyList())); if (islandInfo.exists()) { islandInfo.delete(); } @@ -389,13 +380,11 @@ public boolean hasIsland(Location loc) { } public IslandRank getRank(String islandName) { - if (ranks != null) { - ArrayList rankList = new ArrayList<>(ranks); - for (int i = 0; i < rankList.size(); i++) { - IslandLevel level = rankList.get(i); - if (level.getIslandName().equalsIgnoreCase(islandName)) { - return new IslandRank(level, i+1); - } + ArrayList rankList = new ArrayList<>(ranks); + for (int i = 0; i < rankList.size(); i++) { + IslandLevel level = rankList.get(i); + if (level.getIslandName().equalsIgnoreCase(islandName)) { + return new IslandRank(level, i+1); } } return null; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/TopTenComparator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/TopTenComparator.java index 51ec9d549..609e35de8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/TopTenComparator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/TopTenComparator.java @@ -24,7 +24,7 @@ public int compare(String o1, String o2) { private int getValue(String key) { Double d = dataMap.get(key); if (d != null) { - return (int)(Math.round(d.doubleValue()*10)); + return (int)(Math.round(d * 10)); } return 0; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java index 08eb208ea..3d69a2925 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java @@ -24,7 +24,7 @@ public RecalculateTopTen(uSkyBlock plugin, Set locations) { public void run() { if (!locations.isEmpty()) { String islandName = locations.remove(0); - plugin.calculateScoreAsync(null, islandName, new Callback() { + plugin.calculateScoreAsync(null, islandName, new Callback<>() { @Override public void run() { // We use the deprecated on purpose (the other would fail). @@ -32,7 +32,7 @@ public void run() { } }); } else { - plugin.fireAsyncEvent(new uSkyBlockEvent(null, plugin.getAPI(), uSkyBlockEvent.Cause.RANK_UPDATED)); + plugin.fireAsyncEvent(new uSkyBlockEvent(null, uSkyBlock.getAPI(), uSkyBlockEvent.Cause.RANK_UPDATED)); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index c2f9a83bf..19ba6c7f5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.menu; +import com.google.common.base.Preconditions; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; @@ -11,6 +12,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.profile.PlayerProfile; import org.bukkit.scheduler.BukkitTask; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.command.island.BiomeCommand; @@ -27,6 +29,7 @@ import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.UUID; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,6 +37,7 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; +import static java.util.Objects.requireNonNull; import static us.talabrek.ultimateskyblock.challenge.ChallengeLogic.CHALLENGE_PAGESIZE; import static us.talabrek.ultimateskyblock.challenge.ChallengeLogic.COLS_PER_ROW; import static us.talabrek.ultimateskyblock.util.LogUtil.log; @@ -46,16 +50,16 @@ public class SkyBlockMenu { private final Pattern PERM_VALUE_PATTERN = Pattern.compile("(\\[(?(?[!])?[^\\]]+)\\])?(?.*)"); private final Pattern CHALLENGE_PAGE_HEADER = Pattern.compile(tr("Challenge Menu") + ".*\\((?

[0-9]+)/(?[0-9]+)\\)"); - private uSkyBlock plugin; + private final uSkyBlock plugin; private final ChallengeLogic challengeLogic; - private ItemStack sign = new ItemStack(Material.OAK_SIGN, 1); - private ItemStack biome = new ItemStack(Material.JUNGLE_SAPLING, 1); - private ItemStack lock = new ItemStack(Material.IRON_BARS, 1); - private ItemStack warpset = new ItemStack(Material.END_PORTAL_FRAME, 1); - private ItemStack warptoggle = new ItemStack(Material.LEVER, 1); - private ItemStack invite = new ItemStack(Material.CARROT_ON_A_STICK, 1); - private ItemStack kick = new ItemStack(Material.LEATHER_BOOTS, 1); - private List permissionMenuItems = Arrays.asList( + private final ItemStack sign = new ItemStack(Material.OAK_SIGN, 1); + private final ItemStack biome = new ItemStack(Material.JUNGLE_SAPLING, 1); + private final ItemStack lock = new ItemStack(Material.IRON_BARS, 1); + private final ItemStack warpset = new ItemStack(Material.END_PORTAL_FRAME, 1); + private final ItemStack warptoggle = new ItemStack(Material.LEVER, 1); + private final ItemStack invite = new ItemStack(Material.CARROT_ON_A_STICK, 1); + private final ItemStack kick = new ItemStack(Material.LEATHER_BOOTS, 1); + private final List permissionMenuItems = Arrays.asList( new PartyPermissionMenuItem(biome, "canChangeBiome", tr("Change Biome"), tr("change the island''s biome.")), new PartyPermissionMenuItem(lock, "canToggleLock", tr("Toggle Island Lock"), @@ -68,18 +72,20 @@ public class SkyBlockMenu { tr("toggle the island''s warp,\nallowing them to turn it\non or off at anytime, but\nnot set the location.")), new PartyPermissionMenuItem(invite, "canInviteOthers", tr("Invite Players"), tr("invite others to the island."), - tr("invite\n" + - "other players to the island if\n" + - "there is enough room for more\n" + - "members")), + tr(""" + invite + other players to the island if + there is enough room for more + members""")), new PartyPermissionMenuItem(kick, "canKickOthers", tr("Kick Players"), tr("kick others from the island."), - tr("kick\n" + - "other players from the island,\n" + - "but they are unable to kick\n" + - "the island leader.")) + tr(""" + kick + other players from the island, + but they are unable to kick + the island leader.""")) ); - private List biomeMenus = Arrays.asList( + private final List biomeMenus = Arrays.asList( new BiomeMenuItem(new ItemStack(Material.TROPICAL_FISH, 1), "ocean", tr("Ocean"), tr("The ocean biome is the basic\nstarting biome for all islands.\npassive mobs like animals will\nnot spawn. Hostile mobs will\nspawn normally.") @@ -130,11 +136,12 @@ public class SkyBlockMenu { ), new BiomeMenuItem(new ItemStack(Material.PRISMARINE_SHARD, 1), "deep_ocean", tr("Deep Ocean"), - tr("The deep-ocean biome is an advanced\n" + - "biome. Passive mobs like animals will\n" + - "not spawn. Hostile mobs \n" + - "(including Guardians) will\n" + - "spawn normally.") + tr(""" + The deep-ocean biome is an advanced + biome. Passive mobs like animals will + not spawn. Hostile mobs\s + (including Guardians) will + spawn normally.""") ), new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), "snowy_plains", tr("Ice Plains"), @@ -147,33 +154,36 @@ public SkyBlockMenu(uSkyBlock plugin, ChallengeLogic challengeLogic) { this.challengeLogic = challengeLogic; } - public Inventory displayPartyPlayerGUI(final Player player, final String pname) { + public Inventory displayPartyPlayerGUI(final Player inventoryViewer, final PlayerProfile partyMember) { + Preconditions.checkNotNull(partyMember.getName(), "Player name must not be null"); + Preconditions.checkNotNull(partyMember.getUniqueId(), "Player UUID must not be null"); List lores = new ArrayList<>(); String emptyTitle = tr("{0} <{1}>", "", tr("Permissions")); - String title = tr("{0} <{1}>", pname.substring(0, Math.min(32 - emptyTitle.length(), pname.length())), tr("Permissions")); - Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 9, title); + String name = partyMember.getName(); + String title = tr("{0} <{1}>", name.substring(0, Math.min(32 - emptyTitle.length(), name.length())), tr("Permissions")); + Inventory menu = Bukkit.createInventory(new UltimateHolder(inventoryViewer, title, MenuType.DEFAULT), 9, title); final ItemStack pHead = new ItemStack(Material.PLAYER_HEAD, 1); - final SkullMeta meta3 = (SkullMeta) pHead.getItemMeta(); - ItemMeta meta2 = sign.getItemMeta(); + final SkullMeta meta3 = requireNonNull((SkullMeta) requireNonNull(pHead.getItemMeta())); + ItemMeta meta2 = requireNonNull(requireNonNull(sign.getItemMeta())); meta2.setDisplayName(tr("\u00a79Player Permissions")); addLore(lores, tr("\u00a7eClick here to return to\n\u00a7eyour island group''s info.")); meta2.setLore(lores); sign.setItemMeta(meta2); menu.addItem(sign); lores.clear(); - meta3.setOwner(pname); - meta3.setDisplayName(tr("\u00a7e{0}''\u00a79s Permissions", pname)); + meta3.setOwnerProfile(partyMember); + meta3.setDisplayName(tr("\u00a7e{0}''\u00a79s Permissions", name)); addLore(lores, tr("\u00a7eHover over an icon to view\n\u00a7ea permission. Change the\n\u00a7epermission by clicking it.")); meta3.setLore(lores); pHead.setItemMeta(meta3); menu.addItem(pHead); lores.clear(); - IslandInfo islandInfo = plugin.getIslandInfo(player); - boolean isLeader = islandInfo.isLeader(player); + IslandInfo islandInfo = plugin.getIslandInfo(inventoryViewer); + boolean isLeader = islandInfo.isLeader(inventoryViewer); for (PartyPermissionMenuItem menuItem : permissionMenuItems) { ItemStack itemStack = menuItem.getIcon(); - meta2 = itemStack.getItemMeta(); - if (islandInfo.hasPerm(pname, menuItem.getPerm())) { + meta2 = requireNonNull(requireNonNull(itemStack.getItemMeta())); + if (islandInfo.hasPerm(partyMember.getUniqueId(), menuItem.getPerm())) { meta2.setDisplayName("\u00a7a" + menuItem.getTitle()); lores.add(tr("\u00a7fThis player \u00a7acan")); addLore(lores, "\u00a7f", menuItem.getDescription()); @@ -211,8 +221,8 @@ public Inventory displayPartyGUI(final Player player) { String title = "\u00a79" + tr("Island Group Members"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 18, title); IslandInfo islandInfo = plugin.getIslandInfo(player); - final Set memberList = islandInfo.getMembers(); - final ItemMeta meta2 = sign.getItemMeta(); + final Set memberList = islandInfo.getMemberUUIDs(); + final ItemMeta meta2 = requireNonNull(requireNonNull(sign.getItemMeta())); meta2.setDisplayName("\u00a7a" + tr("Island Group Members")); lores.add(tr("Group Members: \u00a72{0}\u00a77/\u00a7e{1}", islandInfo.getPartySize(), islandInfo.getMaxPartySize())); if (islandInfo.getPartySize() < islandInfo.getMaxPartySize()) { @@ -225,19 +235,19 @@ public Inventory displayPartyGUI(final Player player) { sign.setItemMeta(meta2); menu.addItem(sign.clone()); lores.clear(); - for (String temp : memberList) { + for (UUID memberId : memberList) { ItemStack headItem = new ItemStack(Material.PLAYER_HEAD, 1); - SkullMeta meta3 = (SkullMeta) headItem.getItemMeta(); - meta3.setDisplayName(tr("\u00a7e{0}''s\u00a79 Permissions", temp)); - meta3.setOwner(temp); - boolean isLeader = islandInfo.isLeader(temp); + SkullMeta meta3 = requireNonNull((SkullMeta) requireNonNull(headItem.getItemMeta())); + meta3.setDisplayName(tr("\u00a7e{0}''s\u00a79 Permissions", memberId)); + meta3.setOwnerProfile(Bukkit.createPlayerProfile(memberId)); + boolean isLeader = islandInfo.isLeader(memberId); if (isLeader) { addLore(lores, "\u00a7a\u00a7l", tr("Leader")); } else { addLore(lores, "\u00a7e\u00a7l", tr("Member")); } for (PartyPermissionMenuItem perm : permissionMenuItems) { - if (isLeader || islandInfo.hasPerm(temp, perm.getPerm())) { + if (isLeader || islandInfo.hasPerm(memberId, perm.getPerm())) { lores.add("\u00a7a" + tr("Can {0}", "\u00a7f" + perm.getShortDescription())); } else { lores.add("\u00a7c" + tr("Cannot {0}", "\u00a7f" + perm.getShortDescription())); @@ -258,19 +268,17 @@ public Inventory displayLogGUI(final Player player) { List lores = new ArrayList<>(); String title = "\u00a79" + tr("Island Log"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 9, title); - ItemMeta meta4 = sign.getItemMeta(); + ItemMeta meta4 = requireNonNull(requireNonNull(sign.getItemMeta())); meta4.setDisplayName("\u00a79\u00a7l" + tr("Island Log")); addLore(lores, tr("\u00a7eClick here to return to\n\u00a7ethe main island screen.")); meta4.setLore(lores); sign.setItemMeta(meta4); - menu.addItem(new ItemStack[]{sign}); + menu.addItem(sign); lores.clear(); ItemStack menuItem = new ItemStack(Material.WRITABLE_BOOK, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7e\u00a7lIsland Log")); - for (String log : plugin.getIslandInfo(player).getLog()) { - lores.add(log); - } + lores.addAll(plugin.getIslandInfo(player).getLog()); meta4.setLore(lores); menuItem.setItemMeta(meta4); menu.setItem(8, menuItem); @@ -282,12 +290,12 @@ public Inventory displayBiomeGUI(final Player player) { List lores = new ArrayList<>(); String title = "\u00a79" + tr("Island Biome"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 27, title); - ItemMeta meta4 = sign.getItemMeta(); + ItemMeta meta4 = requireNonNull(requireNonNull(sign.getItemMeta())); meta4.setDisplayName("\u00a7h" + tr("Island Biome")); addLore(lores, tr("\u00a7eClick here to return to\n\u00a7ethe main island screen.")); meta4.setLore(lores); sign.setItemMeta(meta4); - menu.addItem(new ItemStack[]{sign}); + menu.addItem(sign); lores.clear(); String currentBiome = plugin.getIslandInfo(player).getBiome(); for (BiomeMenuItem biomeMenu : biomeMenus) { @@ -295,7 +303,7 @@ public Inventory displayBiomeGUI(final Player player) { continue; // Skip it } ItemStack menuItem = biomeMenu.getIcon(); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); if (player.hasPermission("usb.biome." + biomeMenu.getId())) { meta4.setDisplayName("\u00a7a" + tr("Biome: {0}", biomeMenu.getTitle())); addLore(lores, "\u00a7f", biomeMenu.getDescription()); @@ -323,21 +331,15 @@ public Inventory displayBiomeGUI(final Player player) { private void updateBiomeRadius(Player player, Inventory menu) { String radius = PlayerUtil.getMetadata(player, "biome.radius", "all"); - String radiusDisplay; - switch (radius) { - case "chunk": - radiusDisplay = tr("\u00a72chunk"); - break; - case "all": - radiusDisplay = tr("\u00a7call"); - break; - default: - radiusDisplay = tr("\u00a7e{0}", radius); - } + String radiusDisplay = switch (radius) { + case "chunk" -> tr("\u00a72chunk"); + case "all" -> tr("\u00a7call"); + default -> tr("\u00a7e{0}", radius); + }; List lores = new ArrayList<>(); ItemStack menuItem = new ItemStack(Material.RED_CARPET); - ItemMeta itemMeta = menuItem.getItemMeta(); + ItemMeta itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); itemMeta.setDisplayName(tr("\u00a7c-")); lores.add(tr("Decrease radius of biome-change")); lores.add(tr(tr("Current radius: {0}", radiusDisplay))); @@ -357,7 +359,7 @@ private void updateBiomeRadius(Player player, Inventory menu) { } else { menuItem.setAmount(1); } - itemMeta = menuItem.getItemMeta(); + itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); itemMeta.setDisplayName(tr("Current radius: {0}", radiusDisplay)); itemMeta.setLore(lores); menuItem.setItemMeta(itemMeta); @@ -365,7 +367,7 @@ private void updateBiomeRadius(Player player, Inventory menu) { lores.clear(); menuItem = new ItemStack(Material.GREEN_CARPET); - itemMeta = menuItem.getItemMeta(); + itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); itemMeta.setDisplayName(tr("\u00a72+")); lores.add(tr("Increase radius of biome-change")); lores.add(tr(tr("Current radius: {0}", radiusDisplay))); @@ -407,7 +409,7 @@ private void addExtraMenus(Player player, Inventory menu) { } // Only SIMPLE icons supported... ItemStack item = GuiItemUtil.createGuiDisplayItem(icon, title); - ItemMeta meta = item.getItemMeta(); + ItemMeta meta = requireNonNull(requireNonNull(item.getItemMeta())); meta.setLore(lores); item.setItemMeta(meta); menu.setItem(index, item); @@ -423,7 +425,7 @@ private boolean isExtraMenuAction(Player player, ItemStack currentItem) { return false; } Material itemType = currentItem.getType(); - String itemTitle = currentItem.getItemMeta().getDisplayName(); + String itemTitle = requireNonNull(currentItem.getItemMeta()).getDisplayName(); for (String sIndex : extras.getKeys(false)) { ConfigurationSection menuSection = extras.getConfigurationSection(sIndex); if (menuSection == null) { @@ -519,7 +521,7 @@ private Inventory createInitMenu(Player player) { Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); List lores = new ArrayList<>(); ItemStack menuItem = new ItemStack(Material.OAK_SAPLING, 1); - ItemMeta meta = menuItem.getItemMeta(); + ItemMeta meta = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta.setDisplayName(tr("\u00a7a\u00a7lStart an Island")); addLore(lores, "\u00a7f", tr("Start your skyblock journey\nby starting your own island.\nComplete challenges to earn\nitems and skybucks to help\nexpand your skyblock. You can\ninvite others to join in\nbuilding your island empire!\n\u00a7e\u00a7lClick here to start!")); meta.setLore(lores); @@ -537,7 +539,7 @@ private Inventory createInitMenu(Player player) { } index = Math.max(plugin.getConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index), 1); menuItem = islandPerk.getDisplayItem(); - meta = menuItem.getItemMeta(); + meta = requireNonNull(requireNonNull(menuItem.getItemMeta())); lores = meta.getLore(); if (lores == null) { lores = new ArrayList<>(); @@ -555,7 +557,7 @@ private Inventory createInitMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.SHORT_GRASS, 1); - meta = menuItem.getItemMeta(); + meta = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta.setDisplayName(tr("\u00a7a\u00a7lReturn to Spawn")); addLore(lores, "\u00a7f", tr("Teleport to the spawn area.")); meta.setLore(lores); @@ -564,7 +566,7 @@ private Inventory createInitMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.PLAYER_HEAD, 1); - final SkullMeta meta2 = (SkullMeta) menuItem.getItemMeta(); + final SkullMeta meta2 = requireNonNull((SkullMeta) requireNonNull(menuItem.getItemMeta())); meta2.setDisplayName(tr("\u00a7a\u00a7lJoin an Island")); addLore(lores, "\u00a7f", tr("Want to join another player''s\nisland instead of starting\nyour own? If another player\ninvites you to their island\nyou can click here or use\n\u00a7e/island accept\u00a7f to join them.\n\u00a7e\u00a7lClick here to accept an invite!\n\u00a7e\u00a7l(You must be invited first)")); meta2.setLore(lores); @@ -591,7 +593,7 @@ private Inventory createMainMenu(Player player) { Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 18, title); List lores = new ArrayList<>(); ItemStack menuItem = new ItemStack(Material.OAK_DOOR, 1); - ItemMeta meta4 = menuItem.getItemMeta(); + ItemMeta meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lReturn Home")); addLore(lores, "\u00a7f", tr("Return to your island''s home\npoint. You can change your home\npoint to any location on your\nisland using \u00a7b/island sethome\n\u00a7e\u00a7lClick here to return home.")); meta4.setLore(lores); @@ -602,7 +604,7 @@ private Inventory createMainMenu(Player player) { IslandInfo islandInfo = plugin.getIslandInfo(player); menuItem = new ItemStack(Material.DIAMOND_ORE, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lChallenges")); addLore(lores, "\u00a7f", tr("View a list of \u00a79challenges that\nyou can complete on your island\nto earn skybucks, items, perks,\nand titles.")); if (plugin.getChallengeLogic().isEnabled()) { @@ -616,7 +618,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.EXPERIENCE_BOTTLE, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Level")); addLore(lores, tr("\u00a7eCurrent Level: \u00a7a{0,number,##.#}", islandInfo.getLevel())); addLore(lores, plugin.getLimitLogic().getSummary(islandInfo)); @@ -627,7 +629,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.PLAYER_HEAD, 1); - final SkullMeta meta2 = (SkullMeta) menuItem.getItemMeta(); + final SkullMeta meta2 = requireNonNull((SkullMeta) requireNonNull(menuItem.getItemMeta())); meta2.setDisplayName("\u00a7a\u00a7l" + tr("Island Group")); lores.add(tr("\u00a7eMembers: \u00a72{0}/{1}", islandInfo.getPartySize(), islandInfo.getMaxPartySize())); addLore(lores, "\u00a7f", tr("View the members of your island\ngroup and their permissions. If\nyou are the island leader, you\ncan change the member permissions.\n\u00a7e\u00a7lClick here to view or change.")); @@ -637,7 +639,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.JUNGLE_SAPLING, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName("\u00a7a\u00a7l" + tr("Change Island Biome")); lores.add(tr("\u00a7eCurrent Biome: \u00a7b{0}", islandInfo.getBiome())); addLore(lores, "\u00a7f", tr("The island biome affects things\nlike grass color and spawning\nof both animals and monsters.")); @@ -652,7 +654,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.IRON_BARS, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Lock")); if (plugin.getIslandInfo(player).isLocked()) { addLore(lores, tr("\u00a7eLock Status: \u00a7aActive\n\u00a7fYour island is currently \u00a7clocked.\n\u00a7fPlayers outside of your group\n\u00a7fare unable to enter your island.")); @@ -676,7 +678,7 @@ private Inventory createMainMenu(Player player) { if (plugin.getIslandInfo(player).hasWarp()) { menuItem = new ItemStack(Material.END_PORTAL_FRAME, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Warp")); addLore(lores, tr("\u00a7eWarp Status: \u00a7aActive\n\u00a7fOther players may warp to your\n\u00a7fisland at anytime to the point\n\u00a7fyou set using \u00a7d/island setwarp.")); if (islandInfo.hasPerm(player, "canToggleWarp") && player.hasPermission("usb.island.togglewarp")) { @@ -686,7 +688,7 @@ private Inventory createMainMenu(Player player) { } } else { menuItem = new ItemStack(Material.END_STONE, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Warp")); addLore(lores, tr("\u00a7eWarp Status: \u00a78Inactive\n\u00a7fOther players can't warp to your\n\u00a7fisland. Set a warp point using\n\u00a7d/island setwarp \u00a7fbefore activating.")); if (islandInfo.hasPerm(player, "canToggleWarp") && player.hasPermission("usb.island.togglewarp")) { @@ -701,7 +703,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.SHORT_GRASS, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lReturn to Spawn")); addLore(lores, "\u00a7f", tr("Teleport to the spawn area.")); meta4.setLore(lores); @@ -710,7 +712,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.WRITABLE_BOOK, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Log")); addLore(lores, "\u00a7f", tr("View a log of events from\nyour island such as member,\nbiome, and warp changes.\n\u00a7e\u00a7lClick to view the log.")); meta4.setLore(lores); @@ -719,7 +721,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.RED_BED, 1); // red bed - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lChange Home Location")); addLore(lores, "\u00a7f", tr("When you teleport to your\nisland you will be taken to\nthis location.\n\u00a7e\u00a7lClick here to change.")); meta4.setLore(lores); @@ -728,7 +730,7 @@ private Inventory createMainMenu(Player player) { lores.clear(); menuItem = new ItemStack(Material.HOPPER, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lChange Warp Location")); addLore(lores, "\u00a7f", tr("When your warp is activated,\nother players will be taken to\nthis point when they teleport\nto your island.")); if (islandInfo.hasPerm(player, "canChangeWarp") && player.hasPermission("usb.island.setwarp")) { @@ -743,7 +745,7 @@ private Inventory createMainMenu(Player player) { if (islandInfo.isLeader(player)) { if (plugin.getConfig().getBoolean("island-schemes-enabled", true)) { menuItem = new ItemStack(Material.PODZOL, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7c\u00a7lRestart Island")); addLore(lores, "\u00a7f", tr("Restarts your island.\n\u00a74WARNING! \u00a7cwill remove your items and island!")); meta4.setLore(lores); @@ -753,7 +755,7 @@ private Inventory createMainMenu(Player player) { } } else { menuItem = new ItemStack(Material.IRON_DOOR, 1); - meta4 = menuItem.getItemMeta(); + meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7c\u00a7lLeave Island")); addLore(lores, "\u00a7f", tr("Leaves your island.\n\u00a74WARNING! \u00a7cwill remove all your items!")); addLore(lores, tr("\u00a7cClick to leave")); @@ -776,7 +778,7 @@ public void onClick(InventoryClickEvent event) { return; // Bail out, nothing we can do anyway } Player p = (Player) event.getWhoClicked(); - ItemMeta meta = currentItem.getItemMeta(); + ItemMeta meta = requireNonNull(currentItem.getItemMeta()); SkullMeta skull = meta instanceof SkullMeta ? (SkullMeta) meta : null; if (!(event.getInventory().getHolder() instanceof UltimateHolder)) return; @@ -808,7 +810,7 @@ private void onClickRestartMenu(final InventoryClickEvent event, final Player p, event.setCancelled(true); if (slotIndex == 0) { p.openInventory(createMainMenu(p)); - } else if (currentItem != null && meta != null && meta.getDisplayName() != null) { + } else if (currentItem != null && meta != null && meta.hasDisplayName()) { String schemeName = stripFormatting(meta.getDisplayName()); IslandPerk islandPerk = plugin.getPerkLogic().getIslandPerk(schemeName); if (plugin.getPerkLogic().getSchemes(p).contains(schemeName) && p.hasPermission(islandPerk.getPermission())) { @@ -844,7 +846,7 @@ private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta met p.performCommand("island spawn"); } else if (slotIndex == menuSize - 1) { p.performCommand("island accept"); - } else if (meta != null && meta.getDisplayName() != null) { + } else if (meta != null && meta.hasDisplayName()) { String schemeName = stripFormatting(meta.getDisplayName()); if (plugin.getPerkLogic().getSchemes(p).contains(schemeName)) { p.performCommand("island create " + schemeName); @@ -927,7 +929,7 @@ private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, lon if (currentItem == null || currentItem.getItemMeta() == null || currentItem.getItemMeta().getLore() == null) { return; } - ItemMeta meta = currentItem.getItemMeta(); + ItemMeta meta = requireNonNull(currentItem.getItemMeta()); List lore = meta.getLore(); if (millisLeft >= 0) { lore.set(lore.size() - 1, tr("\u00a7cClick within \u00a79{0}\u00a7c to leave!", TimeUtil.millisAsString(millisLeft))); @@ -946,7 +948,7 @@ public Inventory createRestartGUI(Player player) { Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); List lores = new ArrayList<>(); ItemStack menuItem = new ItemStack(Material.OAK_SIGN, 1); - ItemMeta meta = menuItem.getItemMeta(); + ItemMeta meta = requireNonNull(menuItem.getItemMeta()); meta.setDisplayName(tr("\u00a7a\u00a7lReturn to the main menu")); meta.setLore(lores); menuItem.setItemMeta(meta); @@ -973,7 +975,7 @@ private void updateRestartMenu(Inventory menu, Player player, List schem } index = plugin.getConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index); menuItem = islandPerk.getDisplayItem(); - meta = menuItem.getItemMeta(); + meta = requireNonNull(menuItem.getItemMeta()); lores = meta.getLore(); if (lores == null) { lores = new ArrayList<>(); @@ -992,7 +994,6 @@ private void updateRestartMenu(Inventory menu, Player player, List schem menuItem.setItemMeta(meta); menu.setItem(index++, menuItem); } - player.updateInventory(); } private void onClickLogMenu(InventoryClickEvent event, Player p, int slotIndex) { @@ -1014,9 +1015,9 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt max = Integer.parseInt(m.group("max")); } ItemStack item = event.getInventory().getItem(event.getInventory().getSize() - 9); - String playerName = item != null && item.hasItemMeta() && item.getItemMeta().getLore() != null - && item.getItemMeta().getLore().size() > 0 - ? item.getItemMeta().getLore().get(0) + String playerName = item != null && item.hasItemMeta() && requireNonNull(item.getItemMeta()).getLore() != null + && !item.getItemMeta().getLore().isEmpty() + ? item.getItemMeta().getLore().getFirst() : null; if (playerName != null && playerName.trim().isEmpty()) { playerName = null; @@ -1034,7 +1035,7 @@ private void onClickChallengeMenu(InventoryClickEvent event, ItemStack currentIt } if ((slotIndex % 9) > 0) { // 0,9... are the rank-headers... if (currentItem.getItemMeta() != null) { - String challenge = currentItem.getItemMeta().getDisplayName(); + String challenge = requireNonNull(currentItem.getItemMeta()).getDisplayName(); String challengeName = stripFormatting(challenge); p.performCommand("c c " + challengeName); } @@ -1106,25 +1107,27 @@ private void onClickPermissionMenu(InventoryClickEvent event, ItemStack currentI p.openInventory(displayPartyGUI(p)); } String[] playerPerm = inventoryName.split(" "); - String pname = playerPerm[0]; + String name = playerPerm[0]; + UUID uuid = plugin.getPlayerDB().getUUIDFromName(name); + PlayerProfile profile = Bukkit.createPlayerProfile(uuid, name); ItemStack skullItem = event.getInventory().getItem(1); if (skullItem != null && skullItem.getType().equals(Material.PLAYER_HEAD)) { - ItemMeta meta = skullItem.getItemMeta(); + ItemMeta meta = requireNonNull(skullItem.getItemMeta()); if (meta instanceof SkullMeta) { - pname = ((SkullMeta) meta).getOwner(); + profile = ((SkullMeta) meta).getOwnerProfile(); } } for (PartyPermissionMenuItem item : permissionMenuItems) { if (currentItem.getType() == item.getIcon().getType()) { - islandInfo.togglePerm(pname, item.getPerm()); - p.openInventory(displayPartyPlayerGUI(p, pname)); + islandInfo.togglePerm(profile.getUniqueId(), item.getPerm()); + p.openInventory(displayPartyPlayerGUI(p, profile)); return; } } if (currentItem.getType() == Material.OAK_SIGN) { p.openInventory(displayPartyGUI(p)); } else { - p.openInventory(displayPartyPlayerGUI(p, pname)); + p.openInventory(displayPartyPlayerGUI(p, profile)); } } @@ -1135,8 +1138,8 @@ private void onClickPartyMenu(InventoryClickEvent event, ItemStack currentItem, } if (meta == null || currentItem.getType() == Material.OAK_SIGN) { p.performCommand("island"); - } else if (skull != null && plugin.getIslandInfo(p).isLeader(p)) { - p.openInventory(displayPartyPlayerGUI(p, skull.getOwner())); + } else if (skull != null && skull.hasOwner() && plugin.getIslandInfo(p).isLeader(p)) { + p.openInventory(displayPartyPlayerGUI(p, skull.getOwnerProfile())); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 300e0a303..e9e7eee9e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; @@ -38,6 +39,7 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.api.PlayerInfo { private static final String CN = PlayerInfo.class.getName(); private static final Logger log = Logger.getLogger(CN); + @Serial private static final long serialVersionUID = 1L; private static final int YML_VERSION = 1; private final uSkyBlock plugin; @@ -116,6 +118,10 @@ public String getPlayerName() { return this.playerName; } + public UUID getPlayerId() { + return this.uuid; + } + public void setIslandLocation(final Location l) { this.islandLocation = l != null ? l.clone() : null; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java index 9a6f9a5c5..fe8d304af 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java @@ -4,7 +4,6 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; @@ -38,31 +37,23 @@ public PlayerLogic(uSkyBlock plugin) { playerDB = plugin.getPlayerDB(); playerCache = CacheBuilder .from(plugin.getConfig().getString("options.advanced.playerCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) - .removalListener(new RemovalListener() { - @Override - public void onRemoval(RemovalNotification removal) { - log.fine("Removing player-info for " + removal.getKey() + " from cache"); - PlayerInfo playerInfo = removal.getValue(); - if (playerInfo.isDirty()) { - playerInfo.saveToFile(); - } + .removalListener((RemovalListener) removal -> { + log.fine("Removing player-info for " + removal.getKey() + " from cache"); + PlayerInfo playerInfo = removal.getValue(); + if (playerInfo.isDirty()) { + playerInfo.saveToFile(); } }) - .build(new CacheLoader() { + .build(new CacheLoader<>() { @Override - public PlayerInfo load(UUID s) throws Exception { + public @NotNull PlayerInfo load(@NotNull UUID s) { log.fine("Loading player-info from " + s + " into cache!"); return loadPlayerData(s); } } ); long every = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.advanced.player.saveEvery", 2*60)); - saveTask = plugin.async(new Runnable() { - @Override - public void run() { - saveDirtyToFiles(); - } - }, every, every); + saveTask = plugin.async(this::saveDirtyToFiles, every, every); notificationManager = new NotificationManager(plugin); } @@ -113,17 +104,13 @@ public void run() { String islandName = WorldGuardHandler.getIslandNameAt(onlinePlayer.getLocation()); IslandInfo islandInfo = plugin.getIslandInfo(islandName); if (islandInfo != null && islandInfo.isBanned(onlinePlayer)) { - onlinePlayer.sendMessage(new String[]{ - tr("\u00a7eYou have been §cBANNED§e from {0}§e''s island.", islandInfo.getLeader()), - tr("\u00a7eSending you to spawn.") - }); + onlinePlayer.sendMessage(tr("\u00a7eYou have been §cBANNED§e from {0}§e''s island.", islandInfo.getLeader()), + tr("\u00a7eSending you to spawn.")); plugin.getTeleportLogic().spawnTeleport(onlinePlayer, true); } else if (islandInfo != null && islandInfo.isLocked()) { if (!onlinePlayer.hasPermission("usb.mod.bypassprotection")) { - onlinePlayer.sendMessage(new String[]{ - tr("\u00a7eThe island has been §cLOCKED§e.", islandInfo.getLeader()), - tr("\u00a7eSending you to spawn.") - }); + onlinePlayer.sendMessage(tr("\u00a7eThe island has been §cLOCKED§e.", islandInfo.getLeader()), + tr("\u00a7eSending you to spawn.")); plugin.getTeleportLogic().spawnTeleport(onlinePlayer, true); } } @@ -165,7 +152,7 @@ public void run() { } public void removeActivePlayer(PlayerInfo pi) { - playerCache.invalidate(pi.getPlayerName()); + playerCache.invalidate(pi.getPlayerId()); } public void shutdown() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java index b1d4664c2..ecb6e70c1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java @@ -10,6 +10,7 @@ import org.bukkit.block.Sign; import org.bukkit.block.data.type.WallSign; import org.bukkit.entity.Player; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -36,7 +37,7 @@ public SignEvents(uSkyBlock plugin, SignLogic logic) { @EventHandler(priority = EventPriority.HIGH) public void onPlayerHitSign(PlayerInteractEvent e) { - if (e.isCancelled() + if (e.useInteractedBlock() == Event.Result.DENY || (e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.LEFT_CLICK_BLOCK) || e.getClickedBlock() == null || !(e.getClickedBlock().getState().getBlockData() instanceof WallSign) @@ -59,14 +60,12 @@ public void onSignChanged(SignChangeEvent e) { || !e.getLines()[0].equalsIgnoreCase("[usb]") || e.getLines()[1].trim().isEmpty() || !e.getPlayer().hasPermission("usb.island.signs.place") - || !(e.getBlock().getState() instanceof Sign) + || !(e.getBlock().getState() instanceof Sign sign) ) { return; } - Sign sign = (Sign) e.getBlock().getState(); - if (sign.getBlock().getState().getBlockData() instanceof WallSign) { - WallSign data = (WallSign) sign.getBlock().getState().getBlockData(); + if (sign.getBlock().getState().getBlockData() instanceof WallSign data) { BlockFace attached = data.getFacing().getOppositeFace(); Block wallBlock = sign.getBlock().getRelative(attached); if (isChest(wallBlock)) { @@ -130,21 +129,20 @@ public void onSignOrChestBreak(BlockBreakEvent e) { } @EventHandler(priority = EventPriority.HIGHEST) - public void onBlockHit(PlayerInteractEvent e) { - Player player = e.getPlayer(); - if (e.getClickedBlock() == null - || e.getAction() != Action.RIGHT_CLICK_BLOCK - || e.getPlayer().getGameMode() != GameMode.SURVIVAL - || !(e.getClickedBlock().getState() instanceof Sign) + public void onBlockHit(PlayerInteractEvent event) { + Player player = event.getPlayer(); + if (event.getClickedBlock() == null + || event.getAction() != Action.RIGHT_CLICK_BLOCK + || event.getPlayer().getGameMode() != GameMode.SURVIVAL + || !(event.getClickedBlock().getState() instanceof Sign sign) || !player.hasPermission("usb.island.signs.use") || !plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld())) { return; } - Sign sign = (Sign) e.getClickedBlock().getState(); String firstLine = FormatUtil.stripFormatting(sign.getLine(0)).trim(); if (firstLine.startsWith("/")) { - e.setCancelled(true); + event.setCancelled(true); player.performCommand(firstLine.substring(1)); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 97a47f7f6..c9edf4545 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -104,6 +104,7 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +import static java.util.Objects.requireNonNull; import static us.talabrek.ultimateskyblock.util.LogUtil.log; public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManager.RequirementChecker { @@ -192,7 +193,7 @@ public void onDisable() { } @Override - public FileConfiguration getConfig() { + public @NotNull FileConfiguration getConfig() { return FileUtil.getYmlConfiguration("config.yml"); } @@ -219,7 +220,7 @@ public void onEnable() { CommandManager.registerRequirements(this); FileUtil.setDataFolder(getDataFolder()); - FileUtil.setAllwaysOverwrite("levelConfig.yml"); + FileUtil.setAlwaysOverwrite("levelConfig.yml"); I18nUtil.setDataFolder(getDataFolder()); reloadConfigs(); @@ -279,7 +280,7 @@ public synchronized boolean isRequirementsMet(CommandSender sender, Command comm } } if (pluginManager.isPluginEnabled(pluginReq[0])) { - PluginDescriptionFile desc = pluginManager.getPlugin(pluginReq[0]).getDescription(); + PluginDescriptionFile desc = requireNonNull(pluginManager.getPlugin(pluginReq[0])).getDescription(); if (VersionUtil.getVersion(desc.getVersion()).isLT(pluginReq[1])) { missingRequirements += tr("\u00a7buSkyBlock\u00a7e depends on \u00a79{0}\u00a7e >= \u00a7av{1}\u00a7e but only \u00a7cv{2}\u00a7e was found!\n", pluginReq[0], pluginReq[1], desc.getVersion()); } @@ -522,9 +523,7 @@ private boolean playerIsTrusted(Player player) { String islandName = WorldGuardHandler.getIslandNameAt(player.getLocation()); if (islandName != null) { us.talabrek.ultimateskyblock.api.IslandInfo islandInfo = islandLogic.getIslandInfo(islandName); - if (islandInfo != null && islandInfo.getTrustees().contains(player.getName())) { - return true; - } + return islandInfo != null && islandInfo.isTrusted(player); } return false; } @@ -567,10 +566,7 @@ public boolean hasIsland(final Player player) { } public boolean islandAtLocation(final Location loc) { - return ((WorldGuardHandler.getIntersectingRegions(loc).size() > 0) - || islandLogic.hasIsland(loc) - ); - + return ((!WorldGuardHandler.getIntersectingRegions(loc).isEmpty()) || islandLogic.hasIsland(loc)); } public boolean islandInSpawn(final Location loc) { @@ -623,9 +619,7 @@ public void createIsland(final Player player, String cSchem) { player.sendMessage(tr("\u00a7eYou do not have access to that island-schematic!")); return; } - if (pi != null) { - pi.setIslandGenerating(true); - } + pi.setIslandGenerating(true); try { Location next = getIslandLocatorLogic().getNextIslandLocation(player); if (getWorldManager().isSkyWorld(player.getWorld())) { @@ -865,19 +859,9 @@ public void execCommand(Player player, String command, boolean onlyInSky) { private void doExecCommand(final Player player, final String command, int delay) { if (delay == 0) { - sync(new Runnable() { - @Override - public void run() { - doExecCommand(player, command); - } - }); + sync(() -> doExecCommand(player, command)); } else if (delay > 0) { - sync(new Runnable() { - @Override - public void run() { - doExecCommand(player, command); - } - }, delay); + sync(() -> doExecCommand(player, command), delay); } else { log(Level.INFO, "WARN: Misconfigured command found, with negative delay! " + command); } @@ -939,7 +923,7 @@ public List getTopTen() { @Override public List getRanks(int offset, int length) { - return islandLogic != null ? islandLogic.getRanks(offset, length) : Collections.emptyList(); + return islandLogic != null ? islandLogic.getRanks(offset, length) : Collections.emptyList(); } @Override @@ -985,17 +969,17 @@ public void fireAsyncEvent(final Event event) { public String getVersionInfo(boolean checkEnabled) { PluginDescriptionFile description = getDescription(); - String msg = pre("\u00a77Name: \u00a7b{0}\n", description.getName()); - msg += pre("\u00a77Version: \u00a7b{0}\n", description.getVersion()); - msg += pre("\u00a77Description: \u00a7b{0}\n", description.getDescription()); - msg += pre("\u00a77Language: \u00a7b{0} ({1})\n", getConfig().get("language", "en"), I18nUtil.getI18n().getLocale()); - msg += pre("\u00a79 State: d={0}, r={1}, i={2}, p={3}, n={4}, awe={5}\n", Settings.island_distance, Settings.island_radius, - islandLogic.getSize(), playerLogic.getSize(), - Settings.nether_enabled, AsyncWorldEditHandler.isAWE()); - msg += pre("\u00a77Server: \u00a7e{0} {1}\n", getServer().getName(), getServer().getVersion()); - msg += pre("\u00a79 State: online={0}, bungee={1}\n", ServerUtil.isOnlineMode(), - ServerUtil.isBungeeEnabled()); - msg += pre("\u00a77------------------------------\n"); + StringBuilder msg = new StringBuilder(pre("\u00a77Name: \u00a7b{0}\n", description.getName())); + msg.append(pre("\u00a77Version: \u00a7b{0}\n", description.getVersion())); + msg.append(pre("\u00a77Description: \u00a7b{0}\n", description.getDescription())); + msg.append(pre("\u00a77Language: \u00a7b{0} ({1})\n", getConfig().get("language", "en"), I18nUtil.getI18n().getLocale())); + msg.append(pre("\u00a79 State: d={0}, r={1}, i={2}, p={3}, n={4}, awe={5}\n", Settings.island_distance, Settings.island_radius, + islandLogic.getSize(), playerLogic.getSize(), + Settings.nether_enabled, AsyncWorldEditHandler.isAWE())); + msg.append(pre("\u00a77Server: \u00a7e{0} {1}\n", getServer().getName(), getServer().getVersion())); + msg.append(pre("\u00a79 State: online={0}, bungee={1}\n", ServerUtil.isOnlineMode(), + ServerUtil.isBungeeEnabled())); + msg.append(pre("\u00a77------------------------------\n")); for (String[] dep : depends) { Plugin dependency = getServer().getPluginManager().getPlugin(dep[0]); if (dependency != null) { @@ -1011,18 +995,18 @@ public String getVersionInfo(boolean checkEnabled) { status = pre("\u00a74DISABLED"); } } - msg += pre("\u00a77\u00a7d{0} \u00a7f{1} \u00a77({2}\u00a77)\n", dependency.getName(), - dependency.getDescription().getVersion(), status); + msg.append(pre("\u00a77\u00a7d{0} \u00a7f{1} \u00a77({2}\u00a77)\n", dependency.getName(), + dependency.getDescription().getVersion(), status)); } } - msg += pre("\u00a77------------------------------\n"); + msg.append(pre("\u00a77------------------------------\n")); if (getConfig().getBoolean("plugin-updates.check", true) && getUpdateChecker().isUpdateAvailable()) { - msg += pre("\u00a7bA new update of uSkyBlock is available: \u00a7f{0}\n", getUpdateChecker().getLatestVersion()); - msg += pre("\u00a7fVisit {0} to download.\n", "https://www.uskyblock.ovh/get"); + msg.append(pre("\u00a7bA new update of uSkyBlock is available: \u00a7f{0}\n", getUpdateChecker().getLatestVersion())); + msg.append(pre("\u00a7fVisit {0} to download.\n", "https://www.uskyblock.ovh/get")); } - return msg; + return msg.toString(); } public PlayerDB getPlayerDB() { @@ -1038,7 +1022,7 @@ private IslandScore adjustScore(IslandScore score, IslandInfo islandInfo) { public void calculateScoreAsync(final Player player, String islandName, final Callback callback) { final IslandInfo islandInfo = getIslandInfo(islandName); - getLevelLogic().calculateScoreAsync(islandInfo.getIslandLocation(), new Callback() { + getLevelLogic().calculateScoreAsync(islandInfo.getIslandLocation(), new Callback<>() { @Override public void run() { IslandScore score = adjustScore(getState(), islandInfo); @@ -1114,7 +1098,7 @@ public void setMaintenanceMode(boolean maintenanceMode) { } @Override - public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String label, String[] args) { + public boolean onCommand(@NotNull CommandSender sender, org.bukkit.command.@NotNull Command command, @NotNull String label, String[] args) { if (!isRequirementsMet(sender, null, args)) { sender.sendMessage(tr("\u00a7cCommand is currently disabled!")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/EntityUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/EntityUtil.java index 112ddf914..6f52ee980 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/EntityUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/EntityUtil.java @@ -1,41 +1,12 @@ package us.talabrek.ultimateskyblock.util; import dk.lockfuglsang.minecraft.util.FormatUtil; -import org.bukkit.entity.Animals; -import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import org.bukkit.entity.Monster; -import org.bukkit.entity.NPC; - -import java.util.ArrayList; -import java.util.List; /** * Handles various entity operations. */ public enum EntityUtil {; - public static List getAnimals(List creatures) { - return getEntity(creatures, Animals.class); - } - - public static List getMonsters(List creatures) { - return getEntity(creatures, Monster.class); - } - - public static List getNPCs(List creatures) { - return getEntity(creatures, NPC.class); - } - - public static List getEntity(List creatures, Class typeClass) { - List list = new ArrayList<>(); - for (Entity e : creatures) { - if (typeClass.isInstance(e)) { - //noinspection unchecked - list.add((T) e); - } - } - return list; - } public static String getEntityDisplayName(EntityType entityType) { return FormatUtil.camelcase(entityType.name()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/BukkitPlayerDB.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/BukkitPlayerDB.java index fcc8af908..15ee6b954 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/BukkitPlayerDB.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/BukkitPlayerDB.java @@ -45,7 +45,6 @@ public String getDisplayName(UUID uuid) { @Override public String getDisplayName(String playerName) { - //noinspection deprecation Player player = Bukkit.getPlayer(playerName); return player != null ? player.getDisplayName() : null; } @@ -74,7 +73,6 @@ public Player getPlayer(UUID uuid) { @Override public Player getPlayer(String name) { - //noinspection deprecation return Bukkit.getPlayer(name); } diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/TopTenComparatorTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/TopTenComparatorTest.java index 99f396cf2..d912ee1ea 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/TopTenComparatorTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/TopTenComparatorTest.java @@ -9,12 +9,12 @@ import java.util.TreeMap; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TopTenComparatorTest { @Test - public void testCompare() throws Exception { + public void testCompare() { Map testMap = new HashMap<>(); testMap.put("test A", 10.2); testMap.put("test B", 10.3); @@ -29,4 +29,4 @@ public void testCompare() throws Exception { assertThat(sorted.toString(), is(expected)); assertThat(new LinkedHashMap<>(sorted).toString(), is(expected)); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java index 0d99c2a4f..d59d20f58 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactoryTest.java @@ -17,7 +17,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ChallengeFactoryTest { diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java index 44f965284..1996eee2e 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java @@ -10,7 +10,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.when; public class ChallengeFormatTest { diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/command/IslandChatCommandTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/command/IslandChatCommandTest.java index 3662278ad..40147733f 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/command/IslandChatCommandTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/command/IslandChatCommandTest.java @@ -3,10 +3,9 @@ import org.junit.Test; import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; /** * Created by R4zorax on 04/07/2016. @@ -22,4 +21,4 @@ public void getFormat() throws Exception { assertThat(msg, is("\u00a7b\u00a7cR4zorax: \u00a7aHello world $123")); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java index 5ae692731..fac131725 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java @@ -8,7 +8,7 @@ import java.text.ParseException; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class GriefEventsTest { @@ -22,4 +22,4 @@ public void testWitherNaming() throws ParseException { assertThat(parse.length, is(1)); assertThat((String)parse[0], is("R4zorax")); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java index 4e0fae719..7ca17c512 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java @@ -9,10 +9,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class WorldEditHandlerTest { @@ -207,7 +208,7 @@ public void testGetBorderRegionsUnalignedPos() throws Exception { public void testGetBorderRegionsAligned4Quadrants() throws Exception { Region region = new CuboidRegion(BlockVector3.at(-64,0,-64), BlockVector3.at(63, 15, 63)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expectedBorder = new HashSet<>(Arrays.asList()); + Set expectedBorder = new HashSet<>(); Set expectedInner = new HashSet<>(); for (int x = -4; x <= 3; x++) { for (int z = -4; z <= 3; z++) { @@ -270,4 +271,4 @@ public void testGetBorderRegionsUnaligned4Quadrants() throws Exception { assertThat(WorldEditHandler.getInnerChunks(region), is(expectedInner)); assertThat(WorldEditHandler.getOuterChunks(region), is(expectedOuter)); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java index 2ea9859dc..ab8ea2150 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java @@ -10,7 +10,7 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; /** * Created by R4zorax on 26/04/2016. @@ -37,4 +37,4 @@ public String replace(OfflinePlayer offlinePlayer, Player player, String placeho } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java index 88b86918c..ba72060c9 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java @@ -23,7 +23,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.notNullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/OrphanComparatorTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/OrphanComparatorTest.java index c32cb23db..c1f3fa9a9 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/OrphanComparatorTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/OrphanComparatorTest.java @@ -2,15 +2,13 @@ import org.junit.Test; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Set; import java.util.TreeSet; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; /** * Tests the OrphanComparator @@ -24,7 +22,7 @@ public void testSort() throws Exception { List list = Arrays.asList(o1,o2,o3); List expected = Arrays.asList(o3,o2,o1); - Collections.sort(list, new OrphanComparator()); + list.sort(new OrphanComparator()); assertThat(list, is(expected)); } @@ -38,4 +36,4 @@ public void testSet() throws Exception { assertThat(set.size(), is(3)); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/uSkyBlockTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/uSkyBlockTest.java index 7784626e8..d5af730c8 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/uSkyBlockTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/uSkyBlockTest.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; public class uSkyBlockTest { @@ -12,4 +12,4 @@ public void testStripFormatting() throws Exception { assertThat(stripFormatting(text), is("Hello Babe You wanna dance with somebody")); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/EntityUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/EntityUtilTest.java index aef130bd5..3f0591ba1 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/EntityUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/EntityUtilTest.java @@ -1,86 +1,11 @@ package us.talabrek.ultimateskyblock.util; -import org.bukkit.entity.Animals; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Cow; -import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import org.bukkit.entity.Evoker; -import org.bukkit.entity.Guardian; -import org.bukkit.entity.Monster; -import org.bukkit.entity.NPC; -import org.bukkit.entity.Pig; -import org.bukkit.entity.PigZombie; -import org.bukkit.entity.Pillager; -import org.bukkit.entity.Sheep; -import org.bukkit.entity.Skeleton; -import org.bukkit.entity.Turtle; -import org.bukkit.entity.Villager; -import org.bukkit.entity.WanderingTrader; import org.junit.Test; -import java.util.ArrayList; -import java.util.List; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; public class EntityUtilTest { - @Test - public void testGetEntity() { - List testList = new ArrayList<>(); - - ArmorStand fakeArmorStand = mock(ArmorStand.class); - Cow fakeCow = mock(Cow.class); - Evoker fakeEvoker = mock(Evoker.class); - Guardian fakeGuardian = mock(Guardian.class); - Pig fakePig = mock(Pig.class); - PigZombie fakePigZombie = mock(PigZombie.class); - Pillager fakePillager = mock(Pillager.class); - Sheep fakeSheep = mock(Sheep.class); - Skeleton fakeSkeleton = mock(Skeleton.class); - Turtle fakeTurtle = mock(Turtle.class); - Villager fakeVillager = mock(Villager.class); - WanderingTrader fakeWanderingTrader = mock(WanderingTrader.class); - - testList.add(fakeArmorStand); - testList.add(fakeCow); - testList.add(fakeEvoker); - testList.add(fakeGuardian); - testList.add(fakePig); - testList.add(fakePigZombie); - testList.add(fakePillager); - testList.add(fakeSheep); - testList.add(fakeSkeleton); - testList.add(fakeTurtle); - testList.add(fakeVillager); - testList.add(fakeWanderingTrader); - - List sheepList = EntityUtil.getEntity(testList, Sheep.class); - assertEquals(1, sheepList.size()); - assertEquals(fakeSheep, sheepList.get(0)); - - List animalsList = EntityUtil.getAnimals(testList); - assertEquals(4, animalsList.size()); - assertTrue(animalsList.contains(fakeCow)); - assertTrue(animalsList.contains(fakePig)); - assertTrue(animalsList.contains(fakeSheep)); - assertTrue(animalsList.contains(fakeTurtle)); - - List monsterList = EntityUtil.getMonsters(testList); - assertEquals(5, monsterList.size()); - assertTrue(monsterList.contains(fakeEvoker)); - assertTrue(monsterList.contains(fakeGuardian)); - assertTrue(monsterList.contains(fakePigZombie)); - assertTrue(monsterList.contains(fakePillager)); - assertTrue(monsterList.contains(fakeSkeleton)); - - List npcList = EntityUtil.getNPCs(testList); - assertEquals(2, npcList.size()); - assertTrue(npcList.contains(fakeVillager)); - assertTrue(npcList.contains(fakeWanderingTrader)); - } @Test public void testGetEntityDisplayName() { diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/FileUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/FileUtilTest.java index 8c8bdba8a..d06e32629 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/FileUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/FileUtilTest.java @@ -3,7 +3,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; /** * JUnit tests for FileUtil @@ -14,4 +14,4 @@ public void testGetExtension() { assertThat(FileUtil.getExtension("basename.ext"), is("ext")); assertThat(FileUtil.getExtension("my file.with.dot.yml"), is("yml")); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/LocationUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/LocationUtilTest.java index d28be49ec..689e7e2d2 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/LocationUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/LocationUtilTest.java @@ -5,7 +5,7 @@ import us.talabrek.ultimateskyblock.Settings; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class LocationUtilTest { @@ -36,4 +36,4 @@ public void testAlignToDistance1024x1024() throws Exception { loc.setZ(-512.01); assertThat(LocationUtil.alignToDistance(loc, 1024), is(new Location(null, -1024, Settings.island_height, -1024))); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MaterialUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MaterialUtilTest.java index e3bb4fc20..e76112c49 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MaterialUtilTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/MaterialUtilTest.java @@ -6,7 +6,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class MaterialUtilTest { @Test @@ -60,4 +60,4 @@ public void testGetToolType() { assertThat(MaterialUtil.getToolType(Material.DIAMOND_PICKAXE), is("DIAMOND")); assertThat(MaterialUtil.getToolType(Material.DIAMOND_SHOVEL), is("DIAMOND")); } -} \ No newline at end of file +} From 11f78a2cddca8bc0ca271da721b6172e95d5c970 Mon Sep 17 00:00:00 2001 From: minoneer Date: Fri, 3 Jan 2025 11:35:53 +0100 Subject: [PATCH 142/190] Update world generators to new generation model (#72) * Update world generators to new generation model Makes some biome-related things typesafe as a side effect. Resolves #68 * Copy biome list for tab completion purposes * Fix logging of biome to island config when using the biome GUI --- .../ultimateskyblock/api/IslandInfo.java | 23 +++- .../talabrek/ultimateskyblock/Settings.java | 40 ++++--- .../command/admin/AdminIslandCommand.java | 35 +++--- .../command/completion/BiomeTabCompleter.java | 3 +- .../command/island/BiomeCommand.java | 64 +++++----- .../placeholder/PlaceholderReplacerImpl.java | 2 +- .../ultimateskyblock/island/IslandInfo.java | 25 ++-- .../ultimateskyblock/menu/BiomeMenuItem.java | 11 +- .../ultimateskyblock/menu/SkyBlockMenu.java | 43 ++++--- .../talabrek/ultimateskyblock/uSkyBlock.java | 30 ++--- .../world/ChunkRegenerator.java | 74 +++--------- .../world/SingleBiomeProvider.java | 26 +++++ .../world/SkyBlockChunkGenerator.java | 29 ++--- .../world/SkyBlockNetherChunkGenerator.java | 110 +++++++++--------- uSkyBlock-Core/src/main/resources/config.yml | 7 +- 15 files changed, 266 insertions(+), 256 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SingleBiomeProvider.java diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java index facb2c4e1..70649b32b 100644 --- a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java @@ -3,11 +3,13 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.block.Biome; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -75,9 +77,28 @@ public interface IslandInfo { /** * The name of the biome. + * + * @deprecated Unsafe String value, use {@link #getIslandBiome()} or {@link #getBiomeName()} instead. + * @return The name of the biome. + */ + @Deprecated(since="3.1.0") + default String getBiome() { + return getIslandBiome().name().toUpperCase(Locale.ROOT); + } + + /** + * The biome of the island. + * + * @return The iceland's biome. + */ + Biome getIslandBiome(); + + /** + * The name of the biome. + * * @return The name of the biome. */ - String getBiome(); + String getBiomeName(); /** * The current party-size of the island. diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index 5db004e54..13858905a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -1,16 +1,18 @@ package us.talabrek.ultimateskyblock; import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.Registry; +import org.bukkit.block.Biome; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.command.island.BiomeCommand; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; public class Settings { @@ -32,7 +34,8 @@ public class Settings { public static int general_cooldownInfo; public static int general_cooldownRestart; public static int general_biomeChange; - public static String general_defaultBiome; + public static Biome general_defaultBiome; + public static Biome general_defaultNetherBiome; public static boolean extras_sendToSpawn; public static boolean extras_respawnAtIsland; public static boolean extras_obsidianToLava; @@ -87,14 +90,9 @@ public static boolean loadPluginConfig(FileConfiguration config) { } catch (Exception e) { general_biomeChange = 3600; } - try { - general_defaultBiome = config.getString("options.general.defaultBiome"); - if (!BiomeCommand.biomeExists(general_defaultBiome)) { - general_defaultBiome = "OCEAN"; - } - } catch (Exception e) { - general_defaultBiome = "OCEAN"; - } + general_defaultBiome = loadBiome(config, "options.general.defaultBiome", Biome.OCEAN); + general_defaultNetherBiome = loadBiome(config, "options.general.defaultNetherBiome", Biome.NETHER_WASTES); + try { general_cooldownRestart = config.getInt("options.general.cooldownRestart"); if (general_cooldownRestart < 0) { @@ -120,9 +118,7 @@ public static boolean loadPluginConfig(FileConfiguration config) { changed = true; } general_spawnSize = config.getInt("options.general.spawnSize", 50); - island_chestItems = ItemStackUtil.createItemList( - config.getStringList("options.island.chestItems") - ); + island_chestItems = ItemStackUtil.createItemList(config.getStringList("options.island.chestItems")); island_schematicName = config.getString("options.island.schematicName"); if (island_schematicName == null || "yourschematicname".equals(island_schematicName) || "uSkyBlockDefault".equals(island_schematicName)) { @@ -159,10 +155,24 @@ public static boolean loadPluginConfig(FileConfiguration config) { changed = true; } nether_lava_level = config.getInt("nether.lava_level", config.getInt("nether.lava-level", 32)); - nether_height = config.getInt("nether.height", island_height/2); + nether_height = config.getInt("nether.height", island_height / 2); return changed; } + private static Biome loadBiome(FileConfiguration config, String path, Biome defaultBiome) { + try { + String biomeKey = config.getString(path, defaultBiome.getKey().getKey()); + Biome parsedBiome = Registry.BIOME.match(biomeKey); + if (parsedBiome == null) { + log.log(Level.WARNING, "Invalid Biome in '{0}': {1}", new Object[]{path, biomeKey}); + parsedBiome = defaultBiome; + } + return parsedBiome; + } catch (Exception e) { + return defaultBiome; + } + } + public static List getIslandChestItems() { return ItemStackUtil.clone(island_chestItems); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java index d6be6428c..d9b4b6dcc 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java @@ -108,7 +108,11 @@ public boolean execute(CommandSender sender, String alias, Map d sender.sendMessage(tr("\u00a74That player has no island.")); return false; } - setBiome(sender, playerInfo, plugin.getIslandInfo(playerInfo), args[1]); + Biome biome = plugin.getBiome(args[0]); + if (biome == null) { + return false; + } + setBiome(sender, playerInfo, plugin.getIslandInfo(playerInfo), biome); return true; } else if (args.length == 1 && sender instanceof Player) { Biome biome = plugin.getBiome(args[0]); @@ -121,7 +125,7 @@ public boolean execute(CommandSender sender, String alias, Map d sender.sendMessage(tr("\u00a74No valid island at your location")); return false; } - setBiome(sender, islandInfo, biome.name()); + setBiome(sender, islandInfo, biome); return true; } return false; @@ -132,8 +136,7 @@ public boolean execute(CommandSender sender, String alias, Map d public boolean execute(CommandSender sender, String alias, Map data, String... args) { String cmd = "/usb island purge"; IslandInfo islandInfo = null; - if (args.length == 0 && sender instanceof Player) { - Player player = (Player) sender; + if (args.length == 0 && sender instanceof Player player) { String islandName = WorldGuardHandler.getIslandNameAt(player.getLocation()); islandInfo = plugin.getIslandInfo(islandName); } else if (args.length == 1) { @@ -186,29 +189,21 @@ private void removePlayerFromIsland(CommandSender sender, PlayerInfo playerInfo, playerInfo.save(); } - private void setBiome(CommandSender sender, IslandInfo islandInfo, String biome) { - if (uSkyBlock.getInstance().setBiome(islandInfo.getIslandLocation(), biome)) { - islandInfo.setBiome(biome); - sender.sendMessage(tr("\u00a7eChanged biome of {0}s island to {1}.", islandInfo.getLeader(), biome)); - } else { - islandInfo.setBiome("OCEAN"); - sender.sendMessage(tr("\u00a7eChanged biome of {0}s island to OCEAN.", islandInfo.getLeader())); - } + private void setBiome(CommandSender sender, IslandInfo islandInfo, Biome biome) { + uSkyBlock.getInstance().setBiome(islandInfo.getIslandLocation(), biome); + islandInfo.setBiome(biome); + sender.sendMessage(tr("\u00a7eChanged biome of {0}s island to {1}.", islandInfo.getLeader(), biome)); sender.sendMessage(tr("\u00a7aYou may need to go to spawn, or relog, to see the changes.")); } - private void setBiome(CommandSender sender, PlayerInfo playerInfo, IslandInfo islandInfo, String biome) { + private void setBiome(CommandSender sender, PlayerInfo playerInfo, IslandInfo islandInfo, Biome biome) { if (playerInfo == null || !playerInfo.getHasIsland()) { sender.sendMessage(tr("\u00a74That player has no island.")); return; } - if (uSkyBlock.getInstance().setBiome(playerInfo.getIslandLocation(), biome)) { - islandInfo.setBiome(biome); - sender.sendMessage(tr("\u00a7e{0} has had their biome changed to {1}.", playerInfo.getPlayerName(), biome)); - } else { - islandInfo.setBiome("OCEAN"); - sender.sendMessage(tr("\u00a7e{0} has had their biome changed to OCEAN.", playerInfo.getPlayerName())); - } + uSkyBlock.getInstance().setBiome(playerInfo.getIslandLocation(), biome); + islandInfo.setBiome(biome); + sender.sendMessage(tr("\u00a7e{0} has had their biome changed to {1}.", playerInfo.getPlayerName(), biome)); sender.sendMessage(tr("\u00a7aYou may need to go to spawn, or relog, to see the changes.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java index f2c05fcf0..3c7690ec4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java @@ -11,10 +11,9 @@ * TabCompleter for Biomes. */ public class BiomeTabCompleter extends AbstractTabCompleter { - private static final List BIOMES = new ArrayList<>(BiomeCommand.BIOMES.keySet()); @Override protected List getTabList(CommandSender commandSender, String term) { - return filter(BIOMES, term); + return filter(new ArrayList<>(BiomeCommand.AVAILABLE_BIOMES), term); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index 04eb9dfff..c6f66620d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -4,6 +4,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Registry; import org.bukkit.block.Biome; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.Settings; @@ -14,29 +15,22 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.HashMap; +import java.util.List; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class BiomeCommand extends RequireIslandCommand { - public static final Map BIOMES = new HashMap<>() { - { - for (Biome biome : Biome.values()) { - if (!biome.name().equalsIgnoreCase("custom")) { - put(biome.name().toLowerCase(), biome); - } - } - } - }; + public static final List AVAILABLE_BIOMES = + Registry.BIOME.stream().map(biome -> biome.getKey().getKey()).sorted().toList(); private final SkyBlockMenu menu; public BiomeCommand(uSkyBlock plugin, SkyBlockMenu menu) { super(plugin, "biome|b", null, "biome ?radius", marktr("change the biome of the island")); this.menu = menu; addFeaturePermission("usb.exempt.cooldown.biome", tr("exempt player from biome-cooldown")); - for (String biome : BIOMES.keySet()) { + for (String biome : AVAILABLE_BIOMES) { addFeaturePermission("usb.biome." + biome, tr("Let the player change their islands biome to {0}", biome.toUpperCase())); } } @@ -51,7 +45,7 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi } } if (args.length >= 1) { - final String biome = args[0].toLowerCase(); + final String biomeKey = args[0].toLowerCase(); if (!island.hasPerm(player, "canChangeBiome")) { player.sendMessage(tr("\u00a74You do not have permission to change the biome of this island!")); return true; @@ -62,8 +56,9 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi player.sendMessage(tr("\u00a7eYou must be on your island to change the biome!")); return true; } - if (!biomeExists(biome)) { - player.sendMessage(tr("\u00a7cYou have misspelled the biome name. Must be one of {0}", BIOMES.keySet())); + Biome biome = Registry.BIOME.match(biomeKey); + if (biome == null) { + player.sendMessage(tr("\u00a7cYou have misspelled the biome name. Must be one of {0}", AVAILABLE_BIOMES)); return true; } int cooldown = plugin.getCooldownHandler().getCooldown(player, "biome"); @@ -71,7 +66,7 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi player.sendMessage(tr("\u00a7eYou can change your biome again in {0,number,#} minutes.", cooldown / 60)); return true; } - if (!player.hasPermission("usb.biome." + biome.toLowerCase())) { + if (!player.hasPermission("usb.biome." + biomeKey.toLowerCase())) { player.sendMessage(tr("\u00a7cYou do not have permission to change your biome to that type.")); return true; } @@ -82,6 +77,8 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi minP.subtract(buffer, 0, buffer); maxP.add(buffer, 0, buffer); } + boolean changeEntireIslandBiome; + if (args.length == 2 && args[1].matches("[0-9]+")) { int radius = Integer.parseInt(args[1], 10); minP = BlockVector3.at(Math.max(location.getBlockX() - radius, minP.getBlockX()), @@ -90,39 +87,34 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi maxP = BlockVector3.at(Math.min(location.getBlockX() + radius, maxP.getBlockX()), Math.min(location.getBlockY() + radius, maxP.getBlockY()), Math.min(location.getBlockZ() + radius, maxP.getBlockZ())); - player.sendMessage(tr("\u00a77The pixies are busy changing the biome near you to \u00a79{0}\u00a77, be patient.", biome)); + changeEntireIslandBiome = false; + player.sendMessage(tr("\u00a77The pixies are busy changing the biome near you to \u00a79{0}\u00a77, be patient.", biomeKey)); } else if (args.length == 2 && args[1].equalsIgnoreCase("chunk")) { Chunk chunk = location.clone().getChunk(); - minP = BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4); + minP = BlockVector3.at(chunk.getX() << 4, location.getWorld().getMinHeight(), chunk.getZ() << 4); maxP = BlockVector3.at((chunk.getX() << 4) + 15, location.getWorld().getMaxHeight(), (chunk.getZ() << 4) + 15); - player.sendMessage(tr("\u00a77The pixies are busy changing the biome in your current chunk to \u00a79{0}\u00a77, be patient.", biome)); + changeEntireIslandBiome = false; + player.sendMessage(tr("\u00a77The pixies are busy changing the biome in your current chunk to \u00a79{0}\u00a77, be patient.", biomeKey)); } else if (args.length < 2 || args[1].equalsIgnoreCase("all")) { - player.sendMessage(tr("\u00a77The pixies are busy changing the biome of your island to \u00a79{0}\u00a77, be patient.", biome)); - } - Biome biomeEnum = BIOMES.get(biome); - if (biomeEnum == null) { - player.sendMessage(tr("\u00a7eInvalid biome {0} supplied!", biome)); + changeEntireIslandBiome = true; + player.sendMessage(tr("\u00a77The pixies are busy changing the biome of your island to \u00a79{0}\u00a77, be patient.", biomeKey)); + } else { + player.sendMessage(tr("\u00a7cInvalid arguments. Use /is biome [radius|chunk|all]")); return true; } - new SetBiomeTask(plugin, player.getWorld(), minP, maxP, biomeEnum, () -> { - if (args.length == 1) { + new SetBiomeTask(plugin, player.getWorld(), minP, maxP, biome, () -> { + String biomeName = biome.getKey().getKey(); + if (changeEntireIslandBiome) { island.setBiome(biome); - player.sendMessage(tr("\u00a7aYou have changed your island''s biome to {0}", biome.toUpperCase())); - island.sendMessageToIslandGroup(true, marktr("{0} changed the island biome to {1}"), player.getName(), biome.toUpperCase()); + player.sendMessage(tr("\u00a7aYou have changed your island''s biome to {0}", biomeName)); + island.sendMessageToIslandGroup(true, marktr("{0} changed the island biome to {1}"), player.getName(), biomeName); plugin.getCooldownHandler().resetCooldown(player, "biome", Settings.general_biomeChange); } else { - player.sendMessage(tr("\u00a7aYou have changed {0} blocks around you to the {1} biome", args[1], biome.toUpperCase())); - island.sendMessageToIslandGroup(true, marktr("{0} created an area with {1} biome"), player.getName(), biome.toUpperCase()); + player.sendMessage(tr("\u00a7aYou have changed {0} blocks around you to the {1} biome", args[1], biomeName)); + island.sendMessageToIslandGroup(true, marktr("{0} created an area with {1} biome"), player.getName(), biomeName); } }).runTask(plugin); } return true; } - - public static boolean biomeExists(String biomeName) { - if (biomeName == null) { - return false; - } - return BIOMES.containsKey(biomeName.toLowerCase()); - } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java index 4670cf514..1e3692ab4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java @@ -109,7 +109,7 @@ private String lookup(IslandInfo islandInfo, String placeholder) { case "usb_island_animals": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.ANIMAL); case "usb_island_villagers": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.VILLAGER); case "usb_island_partysize": return "" + islandInfo.getPartySize(); - case "usb_island_biome": return islandInfo.getBiome(); + case "usb_island_biome": return islandInfo.getBiomeName(); case "usb_island_bans": return ""+islandInfo.getBans(); case "usb_island_members": return ""+islandInfo.getMembers(); case "usb_island_trustees": return ""+islandInfo.getTrustees(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 32c56cf10..485dc10ba 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -6,6 +6,8 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.Registry; +import org.bukkit.block.Biome; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -390,15 +392,24 @@ public boolean hasPerm(UUID uuid, String perm) { } @Override - public String getBiome() { - return config.getString("general.biome", Settings.general_defaultBiome).toUpperCase(); + public Biome getIslandBiome() { + String biomeKey = config.getString("general.biome", Settings.general_defaultBiome.getKey().getKey()); + Biome biome = Registry.BIOME.match(biomeKey); + if (biome != null) { + return biome; + } else { + return Settings.general_defaultNetherBiome; + } } - public void setBiome(@NotNull String biome) { - Validate.notNull(biome, "Biome cannot be null"); - Validate.notEmpty(biome, "Biome cannot be empty"); + @Override + public String getBiomeName() { + return getIslandBiome().getKey().getKey(); + } - config.set("general.biome", biome.toUpperCase()); + public void setBiome(@NotNull Biome biome) { + Validate.notNull(biome, "Biome cannot be null"); + config.set("general.biome", biome.getKey().getKey()); save(); } @@ -981,7 +992,7 @@ public String toString() { String str = "\u00a7bIsland Info:\n"; str += ChatColor.GRAY + " - level: " + ChatColor.DARK_AQUA + String.format("%5.2f", getLevel()) + "\n"; str += ChatColor.GRAY + " - location: " + ChatColor.DARK_AQUA + name + "\n"; - str += ChatColor.GRAY + " - biome: " + ChatColor.DARK_AQUA + getBiome() + "\n"; + str += ChatColor.GRAY + " - biome: " + ChatColor.DARK_AQUA + getBiomeName() + "\n"; str += ChatColor.GRAY + " - schematic: " + ChatColor.DARK_AQUA + getSchematicName() + "\n"; str += ChatColor.GRAY + " - warp: " + ChatColor.DARK_AQUA + hasWarp() + "\n"; if (hasWarp()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java index 513a3c5ca..cf8a07b3d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java @@ -1,16 +1,17 @@ package us.talabrek.ultimateskyblock.menu; +import org.bukkit.block.Biome; import org.bukkit.inventory.ItemStack; public class BiomeMenuItem { private final ItemStack icon; - private final String name; + private final Biome biome; private final String title; private final String description; - public BiomeMenuItem(ItemStack icon, String name, String title, String description) { + public BiomeMenuItem(ItemStack icon, Biome biome, String title, String description) { this.icon = icon; - this.name = name; + this.biome = biome; this.title = title; this.description = description; } @@ -19,8 +20,8 @@ public ItemStack getIcon() { return icon.clone(); } - public String getId() { - return name; + public Biome getBiome() { + return biome; } public String getTitle() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 19ba6c7f5..d0ab18b09 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -5,6 +5,7 @@ import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.block.Biome; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; @@ -15,7 +16,6 @@ import org.bukkit.profile.PlayerProfile; import org.bukkit.scheduler.BukkitTask; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; -import us.talabrek.ultimateskyblock.command.island.BiomeCommand; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.IslandPerk; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -87,55 +87,55 @@ public class SkyBlockMenu { ); private final List biomeMenus = Arrays.asList( new BiomeMenuItem(new ItemStack(Material.TROPICAL_FISH, 1), - "ocean", tr("Ocean"), + Biome.OCEAN, tr("Ocean"), tr("The ocean biome is the basic\nstarting biome for all islands.\npassive mobs like animals will\nnot spawn. Hostile mobs will\nspawn normally.") ), new BiomeMenuItem(new ItemStack(Material.SPRUCE_SAPLING, 1), - "forest", tr("Forest"), + Biome.FOREST, tr("Forest"), tr("The forest biome will allow\nyour island to spawn passive.\nmobs like animals (including\nwolves). Hostile mobs will\nspawn normally.") ), new BiomeMenuItem(new ItemStack(Material.SAND, 1), - "desert", tr("Desert"), + Biome.DESERT, tr("Desert"), tr("The desert biome makes it so\nthat there is no rain or snow\non your island. Passive mobs\nwon't spawn. Hostile mobs will\nspawn normally.") ), new BiomeMenuItem(new ItemStack(Material.JUNGLE_SAPLING, 1), - "jungle", tr("Jungle"), + Biome.JUNGLE, tr("Jungle"), tr("The jungle biome is bright\nand colorful. Passive mobs\n(including ocelots) will\nspawn. Hostile mobs will\nspawn normally.") ), new BiomeMenuItem(new ItemStack(Material.LILY_PAD, 1), - "swamp", tr("Swampland"), + Biome.SWAMP, tr("Swampland"), tr("The swamp biome is dark\nand dull. Passive mobs\nwill spawn normally and\nslimes have a small chance\nto spawn at night depending\non the moon phase.") ), new BiomeMenuItem(new ItemStack(Material.SNOW, 1), - "taiga", tr("Taiga"), + Biome.TAIGA, tr("Taiga"), tr("The taiga biome has snow\ninstead of rain. Passive\nmobs will spawn normally\n(including wolves) and\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.RED_MUSHROOM, 1), - "mushroom_fields", tr("Mushroom"), + Biome.MUSHROOM_FIELDS, tr("Mushroom"), tr("The mushroom biome is\nbright and colorful.\nMooshrooms are the only\nmobs that will spawn.\nNo other passive or\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.NETHER_BRICK, 1), - "nether_wastes", tr("Hell"), + Biome.NETHER_WASTES, tr("Hell"), tr("The hell biome looks\ndark and dead. Some\nmobs from the nether will\nspawn in this biome\n(excluding ghasts and\nblazes).") ), new BiomeMenuItem(new ItemStack(Material.ENDER_EYE, 1), - "the_end", tr("Sky"), + Biome.THE_END, tr("Sky"), tr("The sky biome gives your\nisland a special dark sky.\nOnly endermen will spawn\nin this biome.") ), new BiomeMenuItem(new ItemStack(Material.TALL_GRASS, 1), - "plains", tr("Plains"), + Biome.PLAINS, tr("Plains"), tr("The plains biome has rain\ninstead of snow. Passive\nmobs will spawn normally\n(including horses) and\nhostile mobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.EMERALD_ORE, 1), - "windswept_hills", tr("Extreme Hills"), + Biome.WINDSWEPT_HILLS, tr("Extreme Hills"), tr("The extreme hills biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.ROSE_BUSH, 1), - "flower_forest", tr("Flower Forest"), + Biome.FLOWER_FOREST, tr("Flower Forest"), tr("The flower forest biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") ), new BiomeMenuItem(new ItemStack(Material.PRISMARINE_SHARD, 1), - "deep_ocean", tr("Deep Ocean"), + Biome.DEEP_OCEAN, tr("Deep Ocean"), tr(""" The deep-ocean biome is an advanced biome. Passive mobs like animals will @@ -144,7 +144,7 @@ public class SkyBlockMenu { spawn normally.""") ), new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), - "snowy_plains", tr("Ice Plains"), + Biome.SNOWY_PLAINS, tr("Ice Plains"), tr("The ice-plains biome is an advanced biome.\nMobs will spawn naturally.\nincluding polar-bears") ) ); @@ -297,17 +297,14 @@ public Inventory displayBiomeGUI(final Player player) { sign.setItemMeta(meta4); menu.addItem(sign); lores.clear(); - String currentBiome = plugin.getIslandInfo(player).getBiome(); + Biome currentBiome = plugin.getIslandInfo(player).getIslandBiome(); for (BiomeMenuItem biomeMenu : biomeMenus) { - if (!BiomeCommand.biomeExists(biomeMenu.getId())) { - continue; // Skip it - } ItemStack menuItem = biomeMenu.getIcon(); meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); - if (player.hasPermission("usb.biome." + biomeMenu.getId())) { + if (player.hasPermission("usb.biome." + biomeMenu.getBiome().getKey().getKey())) { meta4.setDisplayName("\u00a7a" + tr("Biome: {0}", biomeMenu.getTitle())); addLore(lores, "\u00a7f", biomeMenu.getDescription()); - if (biomeMenu.getId().equalsIgnoreCase(currentBiome)) { + if (biomeMenu.getBiome().equals(currentBiome)) { addLore(lores, tr("\u00a72\u00a7lThis is your current biome.")); } else { addLore(lores, tr("\u00a7e\u00a7lClick to change to this biome.")); @@ -641,7 +638,7 @@ private Inventory createMainMenu(Player player) { menuItem = new ItemStack(Material.JUNGLE_SAPLING, 1); meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName("\u00a7a\u00a7l" + tr("Change Island Biome")); - lores.add(tr("\u00a7eCurrent Biome: \u00a7b{0}", islandInfo.getBiome())); + lores.add(tr("\u00a7eCurrent Biome: \u00a7b{0}", islandInfo.getBiomeName())); addLore(lores, "\u00a7f", tr("The island biome affects things\nlike grass color and spawning\nof both animals and monsters.")); if (islandInfo.hasPerm(player, "canChangeBiome")) { addLore(lores, tr("\u00a7e\u00a7lClick here to change biomes.")); @@ -1091,7 +1088,7 @@ private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, ItemStack menuIcon = biomeMenu.getIcon(); if (currentItem.getType() == menuIcon.getType()) { String radius = PlayerUtil.getMetadata(p, "biome.radius", "all"); - p.performCommand("island biome " + biomeMenu.getId() + " " + radius); + p.performCommand("island biome " + biomeMenu.getBiome().getKey().getKey() + " " + radius); return; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index c9edf4545..76bc4b750 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -10,6 +10,7 @@ import dk.lockfuglsang.minecraft.util.VersionUtil; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Registry; import org.bukkit.block.Biome; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; @@ -47,8 +48,17 @@ import us.talabrek.ultimateskyblock.command.IslandCommand; import us.talabrek.ultimateskyblock.command.admin.DebugCommand; import us.talabrek.ultimateskyblock.command.admin.SetMaintenanceCommand; -import us.talabrek.ultimateskyblock.command.island.BiomeCommand; -import us.talabrek.ultimateskyblock.event.*; +import us.talabrek.ultimateskyblock.event.ExploitEvents; +import us.talabrek.ultimateskyblock.event.GriefEvents; +import us.talabrek.ultimateskyblock.event.InternalEvents; +import us.talabrek.ultimateskyblock.event.ItemDropEvents; +import us.talabrek.ultimateskyblock.event.MenuEvents; +import us.talabrek.ultimateskyblock.event.NetherTerraFormEvents; +import us.talabrek.ultimateskyblock.event.PlayerEvents; +import us.talabrek.ultimateskyblock.event.SpawnEvents; +import us.talabrek.ultimateskyblock.event.ToolMenuEvents; +import us.talabrek.ultimateskyblock.event.WitherTagEvents; +import us.talabrek.ultimateskyblock.event.WorldGuardEvents; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; @@ -593,19 +603,13 @@ public PlayerInfo getPlayerInfo(String playerName) { return playerLogic.getPlayerInfo(playerName); } - public boolean setBiome(final Location loc, final String bName) { - Biome biome = getBiome(bName); - if (biome == null) return false; - setBiome(loc, biome); - return true; - } - - public Biome getBiome(String bName) { - if (bName == null) return null; - return BiomeCommand.BIOMES.get(bName.toLowerCase()); + // TODO: move these to Biome/World related classes + public @Nullable Biome getBiome(String biomeName) { + if (biomeName == null) return null; + return Registry.BIOME.match(biomeName); } - private void setBiome(Location loc, Biome biome) { + public void setBiome(Location loc, Biome biome) { new SetBiomeTask(this, loc, biome, null).runTask(this); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java index 15140ab1b..291aa2def 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/ChunkRegenerator.java @@ -1,27 +1,24 @@ package us.talabrek.ultimateskyblock.world; import org.apache.commons.lang3.Validate; +import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.World; -import org.bukkit.block.Biome; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.ChunkGenerator; -import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.generator.ChunkGenerator.ChunkData; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Arrays; import java.util.List; import java.util.Random; -import static org.bukkit.World.Environment; - /** * Class responsible for regenerating chunks. */ @@ -52,7 +49,7 @@ public void regenerateChunks(@NotNull List chunkList, @Nullable Runnable task = scheduler.runTaskTimer(plugin, () -> { for (int i = 0; i <= CHUNKS_PER_TICK; i++) { if (!chunkList.isEmpty()) { - Chunk chunk = chunkList.remove(0); + Chunk chunk = chunkList.removeFirst(); regenerateChunk(chunk); } else { if (onCompletion != null) { @@ -74,15 +71,25 @@ public void regenerateChunk(@NotNull Chunk chunk) { spawnTeleportPlayers(chunk); - Random random = new Random(); - BiomeGrid biomeGrid = new DefaultBiomeGrid(world.getEnvironment()); - ChunkData chunkData = chunkGen.generateChunkData(world, random, chunk.getX(), chunk.getZ(), biomeGrid); + Random random = new Random(world.getSeed() + (long) chunk.getX() * (long) chunk.getZ()); + + World world = chunk.getWorld(); + + ChunkData chunkData = Bukkit.createChunkData(world); + chunkGen.generateNoise(world, random, chunk.getX(), chunk.getZ(), chunkData); + chunkGen.generateSurface(world, random, chunk.getX(), chunk.getZ(), chunkData); + chunkGen.generateBedrock(world, random, chunk.getX(), chunk.getZ(), chunkData); + chunkGen.generateCaves(world, random, chunk.getX(), chunk.getZ(), chunkData); + + BiomeProvider biomeProvider = chunkGen.getDefaultBiomeProvider(world); for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++) { + for (int y = world.getMinHeight(); y < world.getMaxHeight(); y++) { + if (biomeProvider != null) { + chunk.getBlock(x, y, z).setBiome(biomeProvider.getBiome(world, x, y, z)); + } chunk.getBlock(x, y, z).setBlockData(chunkData.getBlockData(x, y, z)); - chunk.getBlock(x, y, z).setBiome(biomeGrid.getBiome(x, y, z)); } } } @@ -111,49 +118,4 @@ private void spawnTeleportPlayers(@NotNull Chunk chunk) { } } } - - /** - * Default BiomeGrid used by uSkyBlock when regenerating chunks. - */ - static class DefaultBiomeGrid implements BiomeGrid { - private Biome defaultBiome; - - DefaultBiomeGrid(Environment env) { - switch (env) { - case THE_END: - defaultBiome = Biome.THE_END; - break; - case NETHER: - defaultBiome = Biome.NETHER_WASTES; - break; - default: - defaultBiome = Biome.valueOf(Settings.general_defaultBiome); - break; - } - } - - @NotNull - @Deprecated - @Override - public Biome getBiome(int x, int z) { - return defaultBiome; - } - - @NotNull - @Override - public Biome getBiome(int x, int y, int z) { - return defaultBiome; - } - - @Deprecated - @Override - public void setBiome(int x, int z, @NotNull Biome bio) { - defaultBiome = bio; - } - - @Override - public void setBiome(int x, int y, int z, @NotNull Biome bio) { - defaultBiome = bio; - } - } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SingleBiomeProvider.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SingleBiomeProvider.java new file mode 100644 index 000000000..819a28403 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SingleBiomeProvider.java @@ -0,0 +1,26 @@ +package us.talabrek.ultimateskyblock.world; + +import org.bukkit.block.Biome; +import org.bukkit.generator.BiomeProvider; +import org.bukkit.generator.WorldInfo; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class SingleBiomeProvider extends BiomeProvider { + private final Biome biome; + + public SingleBiomeProvider(Biome biome) { + this.biome = biome; + } + + @Override + public @NotNull Biome getBiome(@NotNull WorldInfo worldInfo, int x, int y, int z) { + return biome; + } + + @Override + public @NotNull List getBiomes(@NotNull WorldInfo worldInfo) { + return List.of(biome); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java index b0c60005e..f0ede4c3c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockChunkGenerator.java @@ -2,38 +2,33 @@ import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.block.Biome; +import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; +import org.bukkit.generator.WorldInfo; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; -import java.util.ArrayList; import java.util.List; import java.util.Random; +/** + * A chunk generator that generates an empty world with a single biome. + */ public class SkyBlockChunkGenerator extends ChunkGenerator { - private static final List emptyBlockPopulatorList = new ArrayList<>(); - @Override - public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid biome) { - ChunkData chunkData = createChunkData(world); - for (int x = 0; x <= 15; x++) { - for (int z = 0; z <= 15; z++) { - for (int y = 0; y < world.getMaxHeight(); y++) { - biome.setBiome(x, y, z, Biome.valueOf(Settings.general_defaultBiome)); - } - } - } - return chunkData; + @NotNull + public List getDefaultPopulators(@NotNull World world) { + return List.of(); } @Override - public List getDefaultPopulators(World world) { - return emptyBlockPopulatorList; + public BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) { + return new SingleBiomeProvider(Settings.general_defaultBiome); } @Override - public Location getFixedSpawnLocation(World world, Random random) { + public Location getFixedSpawnLocation(@NotNull World world, @NotNull Random random) { return new Location(world, 0.5d, Settings.island_height, 0.5d); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java index 24cc648c8..c6b826ded 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/SkyBlockNetherChunkGenerator.java @@ -3,97 +3,91 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.block.Biome; +import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; +import org.bukkit.generator.WorldInfo; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; -import java.util.ArrayList; import java.util.List; import java.util.Random; public class SkyBlockNetherChunkGenerator extends ChunkGenerator { - private static final List emptyBlockPopulatorList = new ArrayList(); + + // The nether height limits intentionally differ from World.getMinHeight() and World.getMaxHeight() to reflect + // vanilla nether limits. + private static final int MIN_HEIGHT = 0; + private static final int MAX_HEIGHT = 128; @Override - public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid biome) { - ChunkData chunkData = createChunkData(world); - for (int x = 0; x <= 15; x++) { - for (int z = 0; z <= 15; z++) { - for (int y = 0; y < world.getMaxHeight(); y++) { - biome.setBiome(x, y, z, Biome.NETHER_WASTES); - } - } - } - int y = 0; - // Solid floor + public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int chunkX, int chunkZ, @NotNull ChunkData chunkData) { + // Generate lava sea + chunkData.setRegion(0, MIN_HEIGHT, 0, 16, Settings.nether_lava_level + 1, 16, Material.LAVA); + + // Generate netherrack ceiling + + // First layer with holes + int y = MAX_HEIGHT - 8; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - chunkData.setBlock(x, y, z, Material.BEDROCK); + if (random.nextDouble() >= 0.20) { // 20% air + chunkData.setBlock(x, y, z, Material.NETHERRACK); + } } } - // Bedrock with holes in it - for (y = 1; y <= 5; y++) { - double yThreshold = 0.10 * y; + + // Solid block above + chunkData.setRegion(0, MAX_HEIGHT - 7, 0, 16, MAX_HEIGHT, 16, Material.NETHERRACK); + } + + @Override + public void generateBedrock(@NotNull WorldInfo worldInfo, @NotNull Random random, int chunkX, int chunkZ, @NotNull ChunkData chunkData) { + // Solid bedrock floor + chunkData.setRegion(0, MIN_HEIGHT, 0, 16, MIN_HEIGHT + 1, 16, Material.BEDROCK); + + // Bedrock floor with holes in it + for (int yOffset = 1; yOffset < 6; yOffset++) { + double yThreshold = 0.10 * yOffset; // 90% - 50% bedrock + int y = MIN_HEIGHT + yOffset; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - if (random.nextDouble() >= yThreshold) { // 10%-50% air + if (random.nextDouble() >= yThreshold) { chunkData.setBlock(x, y, z, Material.BEDROCK); - } else { - chunkData.setBlock(x, y, z, Material.LAVA); } } } } - for (y = 6; y <= Settings.nether_lava_level; y++) { - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - chunkData.setBlock(x, y, z, Material.LAVA); - } - } - } - y = 120; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - if (random.nextDouble() >= 0.20) { // 20% air - chunkData.setBlock(x, y, z, Material.NETHERRACK); - } - } - } - y = 121; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - chunkData.setBlock(x, y, z, Material.NETHERRACK); - } - } - for (y = 122; y <= 126; y++) { - double yThreashold = 0.20 * (127 - y); + + // Bedrock ceiling with holes in it + for (int yOffset = 1; yOffset < 6; yOffset++) { + double yThreshold = 0.20 * (yOffset); // 20% - 100% bedrock + int y = MAX_HEIGHT - yOffset - 1; for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { - if (random.nextDouble() >= yThreashold) { // 20%-100% bedrock + if (random.nextDouble() >= yThreshold) { chunkData.setBlock(x, y, z, Material.BEDROCK); - } else { - chunkData.setBlock(x, y, z, Material.NETHERRACK); } } } } - y = 127; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - chunkData.setBlock(x, y, z, Material.BEDROCK); - } - } - return chunkData; + + // Solid bedrock ceiling + chunkData.setRegion(0, MAX_HEIGHT - 1, 0, 16, MAX_HEIGHT, 16, Material.BEDROCK); + } + + @Override + public @NotNull List getDefaultPopulators(@NotNull World world) { + return List.of(); } @Override - public List getDefaultPopulators(World world) { - return emptyBlockPopulatorList; + public BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) { + return new SingleBiomeProvider(Settings.general_defaultNetherBiome); } @Override - public Location getFixedSpawnLocation(World world, Random random) { - return new Location(world, 0, Settings.nether_height, 0); + public Location getFixedSpawnLocation(@NotNull World world, @NotNull Random random) { + return new Location(world, 0, Settings.nether_height, 0); } } diff --git a/uSkyBlock-Core/src/main/resources/config.yml b/uSkyBlock-Core/src/main/resources/config.yml index f09239e9b..8f3ee1020 100644 --- a/uSkyBlock-Core/src/main/resources/config.yml +++ b/uSkyBlock-Core/src/main/resources/config.yml @@ -16,7 +16,10 @@ options: biomeChange: 60 # [string] The default biome assigned to new islands - defaultBiome: OCEAN + defaultBiome: ocean + + # [string] The default biome assigned to new islands + defaultNetherBiome: nether_wastes # [integer] The number of milliseconds between the same notification is sent to the player. # This is used when events are triggered heavily - i.e. item-pickup-prevention, damage-prevention etc. @@ -462,7 +465,7 @@ placeholder: servercommandplaceholder: false # DO NOT TOUCH THE FIELDS BELOW -version: 109 +version: 110 force-replace: options.party.invite-timeout: 100 options.island.islandTeleportDelay: 5 From 5bed2ba83830f65a7282159033f1ff5949102adf Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Tue, 28 Jan 2025 21:36:41 +0100 Subject: [PATCH 143/190] Fix item enchant not being actually applied to the menu items in the challenge menu (#73) Completed challenges are usually shown with an enchant glowing effect when they are completed at least once. This may be useful for the player, but the "enchanted" status of the item is also used in the ChallengeLogic to determine if a challenge with `offset: -1` is displayed or not, in place of the completed one. New MC version, with the new data component system, does not allow an enchant level of 0 (even with unsafe enchant level), an is silently ignored. This commit changes the enchant level to 1, and adds a flag to the item meta to hide the enchant information from the tooltip. --- .../talabrek/ultimateskyblock/challenge/ChallengeLogic.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index b83a8ddde..589514de5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -15,6 +15,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import us.talabrek.ultimateskyblock.api.event.MemberJoinedEvent; @@ -410,7 +411,8 @@ public ItemStack getItemStack(PlayerInfo playerInfo, String challengeName) { lores.add(tr("\u00a74\u00a7lYou can't repeat this challenge.")); } if (completion.getTimesCompleted() > 0) { - meta.addEnchant(Enchantment.LOYALTY, 0, true); + meta.addEnchant(Enchantment.LOYALTY, 1, true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); } meta.setLore(lores); currentChallengeItem.setItemMeta(meta); From 4fbd7ad6cf6d90dd36a1006eadcea3d04038996f Mon Sep 17 00:00:00 2001 From: minoneer Date: Wed, 5 Feb 2025 12:41:00 +0100 Subject: [PATCH 144/190] Biome Overhaul (#75) * Implement a modern GUI framework * Biome update - Biomes are now configurable by the administrator - The biome GUI automatically adjusts to the biomes available to the player - The biome command and its tab completion use the configured biomes - The biome menu use the new GUI framework * Add nullability annotations and checks * Slight improvements to biome GUI rendering * Add newer biome types to support spawning of all passive mobs. Resolves #39 --- .../ultimateskyblock/biome/BiomeConfig.java | 97 +++++++++ .../ultimateskyblock/biome/BiomeEntry.java | 22 ++ .../ultimateskyblock/biome/BiomeGui.java | 182 +++++++++++++++++ .../ultimateskyblock/biome/Biomes.java | 21 ++ .../command/AdminCommand.java | 6 +- .../command/IslandCommand.java | 11 +- .../command/completion/BiomeTabCompleter.java | 10 +- .../command/island/BiomeCommand.java | 20 +- .../ultimateskyblock/event/MenuEvents.java | 22 +- .../ultimateskyblock/gui/GuiListener.java | 33 +++ .../ultimateskyblock/gui/GuiManager.java | 68 +++++++ .../ultimateskyblock/gui/InventoryButton.java | 38 ++++ .../ultimateskyblock/gui/InventoryGui.java | 82 ++++++++ .../gui/InventoryHandler.java | 16 ++ .../ultimateskyblock/menu/SkyBlockMenu.java | 191 ------------------ .../talabrek/ultimateskyblock/uSkyBlock.java | 75 ++++--- uSkyBlock-Core/src/main/resources/biomes.yml | 173 ++++++++++++++++ 17 files changed, 809 insertions(+), 258 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeEntry.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeGui.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryButton.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryGui.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryHandler.java create mode 100644 uSkyBlock-Core/src/main/resources/biomes.yml diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java new file mode 100644 index 000000000..020448b05 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java @@ -0,0 +1,97 @@ +package us.talabrek.ultimateskyblock.biome; + +import dk.lockfuglsang.minecraft.file.FileUtil; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.Material; +import org.bukkit.Registry; +import org.bukkit.block.Biome; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +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.logging.Logger; + +import static java.util.Objects.requireNonNull; + +public class BiomeConfig { + + private final Logger logger; + private final List configuredBiomeEntries; + private final List configuredBiomeKeys; + + public BiomeConfig(Logger logger) { + this.logger = logger; + this.configuredBiomeEntries = loadBiomes(); + this.configuredBiomeKeys = configuredBiomeEntries.stream() + .map(entry -> entry.biome().getKey().getKey()) + .toList(); + } + + private @NotNull List loadBiomes() { + FileConfiguration biomeConfig = FileUtil.getYmlConfiguration("biomes.yml"); + ConfigurationSection biomeSection = biomeConfig.getConfigurationSection("biomes"); + if (biomeSection == null) { + throw new IllegalStateException("You biomes.yml is corrupted, missing 'biomes' section."); + } + List result = new ArrayList<>(); + for (String biomeKey : biomeSection.getKeys(false)) { + ConfigurationSection section = requireNonNull(biomeSection.getConfigurationSection(biomeKey)); + BiomeEntry biomeEntry = readBiomeEntry(biomeKey, section); + if (biomeEntry != null) { + result.add(biomeEntry); + } + } + return result; + } + + public @NotNull List getConfiguredBiomeEntries() { + return configuredBiomeEntries; + } + + public @NotNull List getAvailableBiomes(@NotNull Player player) { + return configuredBiomeEntries.stream() + .filter(entry -> player.hasPermission("usb.biome." + entry.biome().getKey().getKey())) + .toList(); + } + + public @NotNull List getConfiguredBiomeKeys() { + return configuredBiomeKeys; + } + + private @Nullable BiomeEntry readBiomeEntry(@NotNull String biomeKey, @NotNull ConfigurationSection section) { + String itemSpecification = section.getString("displayItem"); + String name = section.getString("name"); + String description = section.getString("description"); + + Biome biome = Registry.BIOME.match(biomeKey); + if (biome == null) { + logger.warning("Unknown biome key: " + biomeKey); + return null; + } + + ItemStack displayItem; + try { + displayItem = ItemStackUtil.createItemStack(itemSpecification); + } catch (IllegalArgumentException e) { + logger.warning("Invalid item specification for biome " + biomeKey + ": " + itemSpecification); + displayItem = new ItemStack(Material.GRASS_BLOCK); + } + + if (name == null) { + logger.warning("Missing name for biome " + biomeKey); + name = biomeKey; + } + + if (description == null) { + logger.warning("Missing description for biome " + biomeKey); + description = ""; + } + + return new BiomeEntry(displayItem, biome, name, description); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeEntry.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeEntry.java new file mode 100644 index 000000000..9f7587a08 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeEntry.java @@ -0,0 +1,22 @@ +package us.talabrek.ultimateskyblock.biome; + +import org.bukkit.block.Biome; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +public record BiomeEntry( + @NotNull ItemStack displayItem, + @NotNull Biome biome, + @NotNull String name, + @NotNull String description +) { + + public BiomeEntry { + displayItem = displayItem.clone(); + } + + @Override + public @NotNull ItemStack displayItem() { + return displayItem.clone(); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeGui.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeGui.java new file mode 100644 index 000000000..0bcac18aa --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeGui.java @@ -0,0 +1,182 @@ +package us.talabrek.ultimateskyblock.biome; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Biome; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.gui.InventoryButton; +import us.talabrek.ultimateskyblock.gui.InventoryGui; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +import static java.util.Objects.requireNonNull; + +public class BiomeGui extends InventoryGui { + + private static final int MAX_INVENTORY_SIZE = 54; + private static final int MIN_INVENTORY_SIZE = 18; + private static final int ROW_SIZE = 9; + private static final List RADIUS_OPTIONS = + List.of("10", "chunk", "20", "30", "40", "50", "60", "70", "80", "90", "100", "all"); + + private final List biomes; + private final Biome currentBiome; + private final int inventorySize; + private String radius = "all"; + + public BiomeGui(@NotNull List biomes, @NotNull Biome currentBiome) { + super(createInventory(computeInventorySize(biomes.size()))); + this.biomes = requireNonNull(biomes); + this.currentBiome = requireNonNull(currentBiome);; + this.inventorySize = computeInventorySize(biomes.size()); + } + + private static int computeInventorySize(int biomesSize) { + int inventorySize = ((int) Math.ceil((double) biomesSize / (double) ROW_SIZE)) * ROW_SIZE; + inventorySize += ROW_SIZE; // Add one row for radius controls + inventorySize = Math.min(inventorySize, MAX_INVENTORY_SIZE); + inventorySize = Math.max(inventorySize, MIN_INVENTORY_SIZE); + return inventorySize; + } + + private static Inventory createInventory(int size) { + return Bukkit.createInventory(null, size, "\u00a79" + tr("Island Biome")); + } + + @Override + public void decorate(@NotNull Player player) { + decorateBiomes(); + decorateRadiusControls(); + decorateBackButton(); + super.decorate(player); + } + + private void decorateBiomes() { + int displayedBiomes = Math.min(biomes.size(), inventorySize - ROW_SIZE); + for (int i = 0; i < displayedBiomes; i++) { + BiomeEntry biomeEntry = biomes.get(i); + this.addButton(i, createBiomeButton(biomeEntry, currentBiome)); + } + } + + private InventoryButton createBiomeButton(BiomeEntry biomeEntry, Biome currentBiome) { + ItemStack displayItem = biomeEntry.displayItem().clone(); + ItemMeta itemMeta = Objects.requireNonNull(displayItem.getItemMeta()); + itemMeta.setDisplayName("\u00a7a" + tr("Biome: {0}", biomeEntry.name())); + List lore = new ArrayList<>( + Arrays.stream(biomeEntry.description().split("\\R")) + .filter(line -> !line.isBlank()) + .map(line -> "\u00a7f" + line) + .toList() + ); + if (biomeEntry.biome().equals(currentBiome)) { + lore.add(tr("\u00a72\u00a7lThis is your current biome.")); + itemMeta.addEnchant(Enchantment.LOYALTY, 1, true); + } else { + lore.add(tr("\u00a7e\u00a7lClick to change to this biome.")); + } + itemMeta.setLore(lore); + displayItem.setItemMeta(itemMeta); + + return new InventoryButton() + .creator((player) -> displayItem) + .consumer((player, event) -> { + player.performCommand("island biome " + biomeEntry.biome().getKey().getKey() + " " + radius); + player.closeInventory(); + }); + } + + private void decorateRadiusControls() { + this.addButton(inventorySize - 6, creteMinusButton()); + this.addButton(inventorySize - 5, createRadiusDisplay()); + this.addButton(inventorySize - 4, createPlusButton()); + } + + private InventoryButton creteMinusButton() { + return new InventoryButton() + .creator((player) -> { + ItemStack displayItem = new ItemStack(Material.RED_CARPET); + ItemMeta itemMeta = requireNonNull(requireNonNull(displayItem.getItemMeta())); + itemMeta.setDisplayName(tr("\u00a7c-")); + List lore = List.of( + tr("Decrease radius of biome change"), + tr("Current radius: {0}", formatRadius(radius)) + ); + itemMeta.setLore(lore); + displayItem.setItemMeta(itemMeta); + return displayItem; + }) + .consumer((player, event) -> { + int ix = RADIUS_OPTIONS.indexOf(radius); + if (ix > 0) { + radius = RADIUS_OPTIONS.get(ix - 1); + } + decorate(player); + }); + } + + private InventoryButton createPlusButton() { + return new InventoryButton() + .creator((player) -> { + ItemStack displayItem = new ItemStack(Material.GREEN_CARPET); + ItemMeta itemMeta = requireNonNull(requireNonNull(displayItem.getItemMeta())); + itemMeta.setDisplayName(tr("\u00a72+")); + List lore = List.of( + tr("Increase radius of biome change"), + tr("Current radius: {0}", formatRadius(radius)) + ); + itemMeta.setLore(lore); + displayItem.setItemMeta(itemMeta); + return displayItem; + }) + .consumer((player, event) -> { + int ix = RADIUS_OPTIONS.indexOf(radius); + if (ix < RADIUS_OPTIONS.size() - 1) { + radius = RADIUS_OPTIONS.get(ix + 1); + } + decorate(player); + }); + } + + private InventoryButton createRadiusDisplay() { + return new InventoryButton() + .creator((player) -> { + ItemStack displayItem = new ItemStack(Material.GRASS_BLOCK); + ItemMeta itemMeta = requireNonNull(requireNonNull(displayItem.getItemMeta())); + itemMeta.setDisplayName(tr("Current radius: {0}", formatRadius(radius))); + displayItem.setItemMeta(itemMeta); + return displayItem; + }); + } + + private static String formatRadius(String radius) { + return switch (radius) { + case "chunk" -> tr("\u00a72chunk"); + case "all" -> tr("\u00a7call"); + default -> tr("\u00a7e{0}", radius); + }; + } + + private void decorateBackButton() { + InventoryButton backButton = new InventoryButton() + .creator((player) -> { + ItemStack displayItem = new ItemStack(Material.OAK_SIGN); + ItemMeta itemMeta = requireNonNull(displayItem.getItemMeta()); + itemMeta.setDisplayName(tr("\u00a7cBack to Main Menu")); + itemMeta.setLore(List.of(tr("\u00a7eClick here to return to the main island screen."))); + displayItem.setItemMeta(itemMeta); + return displayItem; + }) + .consumer((player, event) -> player.performCommand("island")); + this.addButton(inventorySize - 9, backButton); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java new file mode 100644 index 000000000..9b5c522d2 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java @@ -0,0 +1,21 @@ +package us.talabrek.ultimateskyblock.biome; + +import org.bukkit.entity.Player; +import us.talabrek.ultimateskyblock.gui.GuiManager; +import us.talabrek.ultimateskyblock.island.IslandInfo; + +public class Biomes { + + private final GuiManager guiManager; + private final BiomeConfig biomeConfig; + + public Biomes(GuiManager guiManager, BiomeConfig biomeConfig) { + this.guiManager = guiManager; + this.biomeConfig = biomeConfig; + } + + public void openBiomeGui(Player player, IslandInfo islandInfo) { + BiomeGui biomeGui = new BiomeGui(biomeConfig.getAvailableBiomes(player), islandInfo.getIslandBiome()); + guiManager.openGui(biomeGui, player); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index 720460e9e..1702faa04 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -5,6 +5,7 @@ import dk.lockfuglsang.minecraft.command.DocumentCommand; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import us.talabrek.ultimateskyblock.biome.BiomeConfig; import us.talabrek.ultimateskyblock.command.admin.AbstractPlayerInfoCommand; import us.talabrek.ultimateskyblock.command.admin.AdminChallengeCommand; import us.talabrek.ultimateskyblock.command.admin.AdminIslandCommand; @@ -44,12 +45,13 @@ * The new admin command, alias /usb */ public class AdminCommand extends BaseCommandExecutor { - public AdminCommand(final uSkyBlock plugin, ConfirmHandler confirmHandler, AnimationHandler animationHandler) { + public AdminCommand(final uSkyBlock plugin, ConfirmHandler confirmHandler, AnimationHandler animationHandler, + BiomeConfig biomeConfig) { super("usb", null, marktr("Ultimate SkyBlock Admin")); OnlinePlayerTabCompleter playerCompleter = new OnlinePlayerTabCompleter(); TabCompleter challengeCompleter = new ChallengeTabCompleter(); TabCompleter allPlayerCompleter = new AllPlayerTabCompleter(playerCompleter); - TabCompleter biomeCompleter = new BiomeTabCompleter(); + TabCompleter biomeCompleter = new BiomeTabCompleter(biomeConfig); addTab("oplayer", playerCompleter); addTab("player", allPlayerCompleter); addTab("island", allPlayerCompleter); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java index 0159e6bca..a2030bf55 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java @@ -5,6 +5,8 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.biome.BiomeConfig; +import us.talabrek.ultimateskyblock.biome.Biomes; import us.talabrek.ultimateskyblock.command.completion.AllPlayerTabCompleter; import us.talabrek.ultimateskyblock.command.completion.BiomeTabCompleter; import us.talabrek.ultimateskyblock.command.completion.MemberTabCompleter; @@ -49,7 +51,7 @@ public class IslandCommand extends BaseCommandExecutor { private final uSkyBlock plugin; private final SkyBlockMenu menu; - public IslandCommand(uSkyBlock plugin, SkyBlockMenu menu) { + public IslandCommand(uSkyBlock plugin, SkyBlockMenu menu, Biomes biomes, BiomeConfig biomeConfig) { super("island|is", "usb.island.create", marktr("general island command")); this.plugin = plugin; this.menu = menu; @@ -66,7 +68,7 @@ public IslandCommand(uSkyBlock plugin, SkyBlockMenu menu) { addTab("island", playerTabCompleter); addTab("player", playerTabCompleter); addTab("oplayer", onlinePlayerTabCompleter); - addTab("biome", new BiomeTabCompleter()); + addTab("biome", new BiomeTabCompleter(biomeConfig)); addTab("member", new MemberTabCompleter(plugin)); addTab("schematic", new SchematicTabCompleter(plugin)); addTab("perm", new PermissionTabCompleter(plugin)); @@ -85,7 +87,7 @@ public IslandCommand(uSkyBlock plugin, SkyBlockMenu menu) { if (Settings.island_useTopTen) { add(new TopCommand(plugin)); } - add(new BiomeCommand(plugin, menu)); + add(new BiomeCommand(plugin, biomes, biomeConfig)); add(new LevelCommand(plugin)); add(new InfoCommand(plugin)); add(new InviteCommand(plugin, inviteHandler)); @@ -106,8 +108,7 @@ public boolean onCommand(CommandSender sender, Command command, String alias, St if (!plugin.isRequirementsMet(sender, this, args)) { return true; } - if (sender instanceof Player) { - Player player = (Player) sender; + if (sender instanceof Player player) { if (args.length == 0) { player.openInventory(menu.displayIslandGUI(player)); return true; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java index 3c7690ec4..d8098116a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java @@ -2,7 +2,7 @@ import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; -import us.talabrek.ultimateskyblock.command.island.BiomeCommand; +import us.talabrek.ultimateskyblock.biome.BiomeConfig; import java.util.ArrayList; import java.util.List; @@ -12,8 +12,14 @@ */ public class BiomeTabCompleter extends AbstractTabCompleter { + private final BiomeConfig biomeConfig; + + public BiomeTabCompleter(BiomeConfig biomeConfig) { + this.biomeConfig = biomeConfig; + } + @Override protected List getTabList(CommandSender commandSender, String term) { - return filter(new ArrayList<>(BiomeCommand.AVAILABLE_BIOMES), term); + return filter(new ArrayList<>(biomeConfig.getConfiguredBiomeKeys()), term); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index c6f66620d..127ab664e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -8,29 +8,29 @@ import org.bukkit.block.Biome; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.biome.BiomeConfig; +import us.talabrek.ultimateskyblock.biome.Biomes; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.island.task.SetBiomeTask; -import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.List; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class BiomeCommand extends RequireIslandCommand { - public static final List AVAILABLE_BIOMES = - Registry.BIOME.stream().map(biome -> biome.getKey().getKey()).sorted().toList(); - private final SkyBlockMenu menu; + private final Biomes biomes; + private final BiomeConfig biomeConfig; - public BiomeCommand(uSkyBlock plugin, SkyBlockMenu menu) { + public BiomeCommand(uSkyBlock plugin, Biomes biomes, BiomeConfig biomeConfig) { super(plugin, "biome|b", null, "biome ?radius", marktr("change the biome of the island")); - this.menu = menu; + this.biomes = biomes; + this.biomeConfig = biomeConfig; addFeaturePermission("usb.exempt.cooldown.biome", tr("exempt player from biome-cooldown")); - for (String biome : AVAILABLE_BIOMES) { + for (String biome : biomeConfig.getConfiguredBiomeKeys()) { addFeaturePermission("usb.biome." + biome, tr("Let the player change their islands biome to {0}", biome.toUpperCase())); } } @@ -41,7 +41,7 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi if (!island.hasPerm(player, "canChangeBiome")) { player.sendMessage(tr("\u00a7cYou do not have permission to change the biome of your current island.")); } else { - player.openInventory(menu.displayBiomeGUI(player)); // Weird, that we show the UI + biomes.openBiomeGui(player, island); } } if (args.length >= 1) { @@ -58,7 +58,7 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi } Biome biome = Registry.BIOME.match(biomeKey); if (biome == null) { - player.sendMessage(tr("\u00a7cYou have misspelled the biome name. Must be one of {0}", AVAILABLE_BIOMES)); + player.sendMessage(tr("\u00a7cYou have misspelled the biome name. Must be one of {0}", biomeConfig.getConfiguredBiomeKeys())); return true; } int cooldown = plugin.getCooldownHandler().getCooldown(player, "biome"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java index d3c42c781..106dea0a6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java @@ -7,12 +7,6 @@ import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.uSkyBlock; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; - -/** - * Menu events. - */ public class MenuEvents implements Listener { private final uSkyBlock plugin; @@ -22,16 +16,12 @@ public MenuEvents(uSkyBlock plugin) { @EventHandler(priority = EventPriority.MONITOR) public void guiClick(final InventoryClickEvent event) { - if (!(event.getInventory().getHolder() instanceof UltimateHolder)) { - // Not our menu. - return; - } - - UltimateHolder holder = (UltimateHolder) event.getInventory().getHolder(); - if (holder.getMenuType() == UltimateHolder.MenuType.CONFIG) { - plugin.getConfigMenu().onClick(event); - } else { - plugin.getMenu().onClick(event); + if (event.getInventory().getHolder() instanceof UltimateHolder holder) { + if (holder.getMenuType() == UltimateHolder.MenuType.CONFIG) { + plugin.getConfigMenu().onClick(event); + } else { + plugin.getMenu().onClick(event); + } } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java new file mode 100644 index 000000000..02e1f02ee --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java @@ -0,0 +1,33 @@ +package us.talabrek.ultimateskyblock.gui; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.jetbrains.annotations.NotNull; + +import static java.util.Objects.requireNonNull; + +public class GuiListener implements Listener { + private final GuiManager guiManager; + + public GuiListener(@NotNull GuiManager guiManager) { + this.guiManager = requireNonNull(guiManager); + } + + @EventHandler + public void onClick(@NotNull InventoryClickEvent event) { + this.guiManager.handleClick(event); + } + + @EventHandler + public void onOpen(@NotNull InventoryOpenEvent event) { + this.guiManager.handleOpen(event); + } + + @EventHandler + public void onClose(@NotNull InventoryCloseEvent event) { + this.guiManager.handleClose(event); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java new file mode 100644 index 000000000..331a25bd8 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java @@ -0,0 +1,68 @@ +package us.talabrek.ultimateskyblock.gui; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.inventory.Inventory; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.Objects.requireNonNull; + +/* + * New GUI system as of Feb 2025. + * This system is designed to be more flexible, easier to use and extend, and to separate concerns. + * All old GUIs from us.talabrek.ultimateskyblock.menu should be converted to this system. + */ +public class GuiManager { + + private final Map activeInventories = new HashMap<>(); + + public void openGui(@NotNull InventoryGui gui, @NotNull Player player) { + requireNonNull(gui); + requireNonNull(player); + this.registerHandledInventory(gui.getInventory(), gui); + player.openInventory(gui.getInventory()); + } + + public void registerHandledInventory(@NotNull Inventory inventory, @NotNull InventoryHandler handler) { + requireNonNull(inventory); + requireNonNull(handler); + this.activeInventories.put(inventory, handler); + } + + public void unregisterInventory(@NotNull Inventory inventory) { + requireNonNull(inventory); + this.activeInventories.remove(inventory); + } + + public void handleClick(@NotNull InventoryClickEvent event) { + requireNonNull(event); + InventoryHandler handler = this.activeInventories.get(event.getInventory()); + if (handler != null) { + event.setCancelled(true); + handler.onClick(event); + } + } + + public void handleOpen(@NotNull InventoryOpenEvent event) { + requireNonNull(event); + InventoryHandler handler = this.activeInventories.get(event.getInventory()); + if (handler != null) { + handler.onOpen(event); + } + } + + public void handleClose(@NotNull InventoryCloseEvent event) { + requireNonNull(event); + Inventory inventory = event.getInventory(); + InventoryHandler handler = this.activeInventories.get(inventory); + if (handler != null) { + handler.onClose(event); + this.unregisterInventory(inventory); + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryButton.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryButton.java new file mode 100644 index 000000000..ed9443f15 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryButton.java @@ -0,0 +1,38 @@ +package us.talabrek.ultimateskyblock.gui; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.function.BiConsumer; +import java.util.function.Function; + +import static java.util.Objects.requireNonNull; + +public class InventoryButton { + + private Function iconCreator; + private BiConsumer eventConsumer = (player, event) -> { + }; + + public @NotNull InventoryButton creator(@NotNull Function iconCreator) { + this.iconCreator = iconCreator; + return this; + } + + public @NotNull InventoryButton consumer(@NotNull BiConsumer eventConsumer) { + this.eventConsumer = eventConsumer; + return this; + } + + public @NotNull BiConsumer getEventConsumer() { + requireNonNull(this.eventConsumer, "EventConsumer is not set"); + return this.eventConsumer; + } + + public @NotNull Function getIconCreator() { + requireNonNull(this.iconCreator, "IconCreator is not set"); + return this.iconCreator; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryGui.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryGui.java new file mode 100644 index 000000000..025817802 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryGui.java @@ -0,0 +1,82 @@ +package us.talabrek.ultimateskyblock.gui; + +import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static java.util.Objects.requireNonNull; + +public abstract class InventoryGui implements InventoryHandler { + + private static final Set REGULAR_CLICK_TYPES = Set.of( + ClickType.LEFT, + ClickType.RIGHT, + ClickType.SHIFT_LEFT, + ClickType.SHIFT_RIGHT, + ClickType.DOUBLE_CLICK, + ClickType.CREATIVE + ); + private final Inventory inventory; + private final Map buttonMap = new HashMap<>(); + + public InventoryGui(@NotNull Inventory inventory) { + this.inventory = requireNonNull(inventory); + } + + public @NotNull Inventory getInventory() { + return this.inventory; + } + + public void addButton(int slot, @NotNull InventoryButton button) { + requireNonNull(button); + this.buttonMap.put(slot, button); + } + + public void decorate(@NotNull Player player) { + requireNonNull(player); + this.buttonMap.forEach((slot, button) -> { + ItemStack icon = button.getIconCreator().apply(player); + icon = ItemStackUtil.asDisplayItem(icon); + this.inventory.setItem(slot, icon); + }); + } + + @Override + public void onClick(@NotNull InventoryClickEvent event) { + requireNonNull(event); + if (!Objects.equals(event.getClickedInventory(), this.inventory)) { + // Ignore clicks in other (lower) inventory our outside the inventory. + return; + } + if (!REGULAR_CLICK_TYPES.contains(event.getClick())) { + // Ignore non-regular click types. + return; + } + int slot = event.getSlot(); + InventoryButton button = this.buttonMap.get(slot); + if (button != null) { + button.getEventConsumer().accept((Player) event.getWhoClicked(), event); + } + } + + @Override + public void onOpen(@NotNull InventoryOpenEvent event) { + requireNonNull(event); + this.decorate((Player) event.getPlayer()); + } + + @Override + public void onClose(@NotNull InventoryCloseEvent event) { + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryHandler.java new file mode 100644 index 000000000..4ae2842c0 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/InventoryHandler.java @@ -0,0 +1,16 @@ +package us.talabrek.ultimateskyblock.gui; + +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.jetbrains.annotations.NotNull; + +public interface InventoryHandler { + + void onClick(@NotNull InventoryClickEvent event); + + void onOpen(@NotNull InventoryOpenEvent event); + + void onClose(@NotNull InventoryCloseEvent event); + +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index d0ab18b09..10edbae6e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -5,7 +5,6 @@ import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.Biome; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; @@ -23,7 +22,6 @@ import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.GuiItemUtil; -import us.talabrek.ultimateskyblock.util.PlayerUtil; import java.util.ArrayList; import java.util.Arrays; @@ -85,69 +83,6 @@ public class SkyBlockMenu { but they are unable to kick the island leader.""")) ); - private final List biomeMenus = Arrays.asList( - new BiomeMenuItem(new ItemStack(Material.TROPICAL_FISH, 1), - Biome.OCEAN, tr("Ocean"), - tr("The ocean biome is the basic\nstarting biome for all islands.\npassive mobs like animals will\nnot spawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.SPRUCE_SAPLING, 1), - Biome.FOREST, tr("Forest"), - tr("The forest biome will allow\nyour island to spawn passive.\nmobs like animals (including\nwolves). Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.SAND, 1), - Biome.DESERT, tr("Desert"), - tr("The desert biome makes it so\nthat there is no rain or snow\non your island. Passive mobs\nwon't spawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.JUNGLE_SAPLING, 1), - Biome.JUNGLE, tr("Jungle"), - tr("The jungle biome is bright\nand colorful. Passive mobs\n(including ocelots) will\nspawn. Hostile mobs will\nspawn normally.") - ), - new BiomeMenuItem(new ItemStack(Material.LILY_PAD, 1), - Biome.SWAMP, tr("Swampland"), - tr("The swamp biome is dark\nand dull. Passive mobs\nwill spawn normally and\nslimes have a small chance\nto spawn at night depending\non the moon phase.") - ), - new BiomeMenuItem(new ItemStack(Material.SNOW, 1), - Biome.TAIGA, tr("Taiga"), - tr("The taiga biome has snow\ninstead of rain. Passive\nmobs will spawn normally\n(including wolves) and\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.RED_MUSHROOM, 1), - Biome.MUSHROOM_FIELDS, tr("Mushroom"), - tr("The mushroom biome is\nbright and colorful.\nMooshrooms are the only\nmobs that will spawn.\nNo other passive or\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.NETHER_BRICK, 1), - Biome.NETHER_WASTES, tr("Hell"), - tr("The hell biome looks\ndark and dead. Some\nmobs from the nether will\nspawn in this biome\n(excluding ghasts and\nblazes).") - ), - new BiomeMenuItem(new ItemStack(Material.ENDER_EYE, 1), - Biome.THE_END, tr("Sky"), - tr("The sky biome gives your\nisland a special dark sky.\nOnly endermen will spawn\nin this biome.") - ), - new BiomeMenuItem(new ItemStack(Material.TALL_GRASS, 1), - Biome.PLAINS, tr("Plains"), - tr("The plains biome has rain\ninstead of snow. Passive\nmobs will spawn normally\n(including horses) and\nhostile mobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.EMERALD_ORE, 1), - Biome.WINDSWEPT_HILLS, tr("Extreme Hills"), - tr("The extreme hills biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.ROSE_BUSH, 1), - Biome.FLOWER_FOREST, tr("Flower Forest"), - tr("The flower forest biome.\nPassive mobs will spawn \nnormally and hostile\nmobs will spawn.") - ), - new BiomeMenuItem(new ItemStack(Material.PRISMARINE_SHARD, 1), - Biome.DEEP_OCEAN, tr("Deep Ocean"), - tr(""" - The deep-ocean biome is an advanced - biome. Passive mobs like animals will - not spawn. Hostile mobs\s - (including Guardians) will - spawn normally.""") - ), - new BiomeMenuItem(new ItemStack(Material.PACKED_ICE, 1), - Biome.SNOWY_PLAINS, tr("Ice Plains"), - tr("The ice-plains biome is an advanced biome.\nMobs will spawn naturally.\nincluding polar-bears") - ) - ); public SkyBlockMenu(uSkyBlock plugin, ChallengeLogic challengeLogic) { this.plugin = plugin; @@ -286,93 +221,6 @@ public Inventory displayLogGUI(final Player player) { return menu; } - public Inventory displayBiomeGUI(final Player player) { - List lores = new ArrayList<>(); - String title = "\u00a79" + tr("Island Biome"); - Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), 27, title); - ItemMeta meta4 = requireNonNull(requireNonNull(sign.getItemMeta())); - meta4.setDisplayName("\u00a7h" + tr("Island Biome")); - addLore(lores, tr("\u00a7eClick here to return to\n\u00a7ethe main island screen.")); - meta4.setLore(lores); - sign.setItemMeta(meta4); - menu.addItem(sign); - lores.clear(); - Biome currentBiome = plugin.getIslandInfo(player).getIslandBiome(); - for (BiomeMenuItem biomeMenu : biomeMenus) { - ItemStack menuItem = biomeMenu.getIcon(); - meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); - if (player.hasPermission("usb.biome." + biomeMenu.getBiome().getKey().getKey())) { - meta4.setDisplayName("\u00a7a" + tr("Biome: {0}", biomeMenu.getTitle())); - addLore(lores, "\u00a7f", biomeMenu.getDescription()); - if (biomeMenu.getBiome().equals(currentBiome)) { - addLore(lores, tr("\u00a72\u00a7lThis is your current biome.")); - } else { - addLore(lores, tr("\u00a7e\u00a7lClick to change to this biome.")); - } - } else { - meta4.setDisplayName("\u00a78" + tr("Biome: {0}", biomeMenu.getTitle())); - lores.add("\u00a7c" + tr("You cannot use this biome.")); - addLore(lores, "\u00a77", biomeMenu.getDescription()); - } - meta4.setLore(lores); - menuItem.setItemMeta(meta4); - menu.addItem(menuItem); - lores.clear(); - } - - updateBiomeRadius(player, menu); - - - return menu; - } - - private void updateBiomeRadius(Player player, Inventory menu) { - String radius = PlayerUtil.getMetadata(player, "biome.radius", "all"); - String radiusDisplay = switch (radius) { - case "chunk" -> tr("\u00a72chunk"); - case "all" -> tr("\u00a7call"); - default -> tr("\u00a7e{0}", radius); - }; - - List lores = new ArrayList<>(); - ItemStack menuItem = new ItemStack(Material.RED_CARPET); - ItemMeta itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); - itemMeta.setDisplayName(tr("\u00a7c-")); - lores.add(tr("Decrease radius of biome-change")); - lores.add(tr(tr("Current radius: {0}", radiusDisplay))); - itemMeta.setLore(lores); - menuItem.setItemMeta(itemMeta); - menu.setItem(21, menuItem); - - lores.clear(); - menuItem = new ItemStack(Material.GRASS_BLOCK); - if (radius.matches("[0-9]+")) { - int radiusInt = Integer.parseInt(radius, 10); - if (radiusInt <= menuItem.getType().getMaxStackSize()) { - menuItem.setAmount(radiusInt); - } else { - menuItem.setAmount(1); - } - } else { - menuItem.setAmount(1); - } - itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); - itemMeta.setDisplayName(tr("Current radius: {0}", radiusDisplay)); - itemMeta.setLore(lores); - menuItem.setItemMeta(itemMeta); - menu.setItem(22, menuItem); - - lores.clear(); - menuItem = new ItemStack(Material.GREEN_CARPET); - itemMeta = requireNonNull(requireNonNull(menuItem.getItemMeta())); - itemMeta.setDisplayName(tr("\u00a72+")); - lores.add(tr("Increase radius of biome-change")); - lores.add(tr(tr("Current radius: {0}", radiusDisplay))); - itemMeta.setLore(lores); - menuItem.setItemMeta(itemMeta); - menu.setItem(23, menuItem); - } - private void addExtraMenus(Player player, Inventory menu) { ConfigurationSection extras = plugin.getConfig().getConfigurationSection("options.extra-menus"); if (extras == null) { @@ -786,8 +634,6 @@ public void onClick(InventoryClickEvent event) { onClickPartyMenu(event, currentItem, p, meta, skull, slotIndex); } else if (inventoryName.contains(stripFormatting(tr("Permissions")))) { onClickPermissionMenu(event, currentItem, p, inventoryName, slotIndex); - } else if (inventoryName.equalsIgnoreCase(stripFormatting(tr("Island Biome")))) { - onClickBiomeMenu(event, currentItem, p, slotIndex); } else if (inventoryName.contains(stripFormatting(tr("Challenge Menu")))) { onClickChallengeMenu(event, currentItem, p, inventoryName); } else if (inventoryName.equalsIgnoreCase(stripFormatting(tr("Island Log")))) { @@ -1057,43 +903,6 @@ private boolean isAirOrLocked(ItemStack currentItem) { currentItem != null && currentItem.getItemMeta() != null && currentItem.getItemMeta().getDisplayName().equals(tr("\u00a74\u00a7lLocked Challenge")); } - private void onClickBiomeMenu(InventoryClickEvent event, ItemStack currentItem, Player p, int slotIndex) { - event.setCancelled(true); - if (slotIndex < 0 || slotIndex > 35) { - return; - } - if (slotIndex == 0 && currentItem.getType() == Material.OAK_SIGN) { - p.performCommand("island"); - return; - } - if (slotIndex >= 21 && slotIndex <= 23) { - List radii = Arrays.asList("10", "chunk", "20", "30", "40", "50", "60", "70", "80", "90", "100", "all"); - String radius = PlayerUtil.getMetadata(p, "biome.radius", "all"); - int ix = radii.indexOf(radius); - if (ix == -1) { - ix = 1; - } - if (currentItem.getType() == Material.RED_CARPET && ix > 0) { - ix--; - } else if (currentItem.getType() == Material.GREEN_CARPET && ix < radii.size() - 1) { - ix++; - } - radius = radii.get(ix); - PlayerUtil.setMetadata(p, "biome.radius", radius); - updateBiomeRadius(p, event.getInventory()); - event.setCancelled(true); - return; - } - for (BiomeMenuItem biomeMenu : biomeMenus) { - ItemStack menuIcon = biomeMenu.getIcon(); - if (currentItem.getType() == menuIcon.getType()) { - String radius = PlayerUtil.getMetadata(p, "biome.radius", "all"); - p.performCommand("island biome " + biomeMenu.getBiome().getKey().getKey() + " " + radius); - return; - } - } - } - private void onClickPermissionMenu(InventoryClickEvent event, ItemStack currentItem, Player p, String inventoryName, int slotIndex) { event.setCancelled(true); if (slotIndex < 0 || slotIndex > 35) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 76bc4b750..fabe9b474 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -38,6 +38,8 @@ import us.talabrek.ultimateskyblock.api.event.uSkyBlockScoreChangedEvent; import us.talabrek.ultimateskyblock.api.impl.UltimateSkyblockApi; import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; +import us.talabrek.ultimateskyblock.biome.BiomeConfig; +import us.talabrek.ultimateskyblock.biome.Biomes; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.chat.ChatEvents; import us.talabrek.ultimateskyblock.chat.ChatLogic; @@ -59,6 +61,8 @@ import us.talabrek.ultimateskyblock.event.ToolMenuEvents; import us.talabrek.ultimateskyblock.event.WitherTagEvents; import us.talabrek.ultimateskyblock.event.WorldGuardEvents; +import us.talabrek.ultimateskyblock.gui.GuiListener; +import us.talabrek.ultimateskyblock.gui.GuiManager; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; @@ -120,13 +124,13 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManager.RequirementChecker { private static final String CN = uSkyBlock.class.getName(); private static final String[][] depends = new String[][]{ - new String[]{"Vault", "1.7.1", "optional"}, - new String[]{"WorldEdit", "7.2.12", "optionalIf", "FastAsyncWorldEdit"}, - new String[]{"WorldGuard", "7.0.8"}, - new String[]{"FastAsyncWorldEdit", "2.4.3", "optional"}, - new String[]{"Multiverse-Core", "4.3.1", "optional"}, - new String[]{"Multiverse-Portals", "4.2.1", "optional"}, - new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, + new String[]{"Vault", "1.7.1", "optional"}, + new String[]{"WorldEdit", "7.2.12", "optionalIf", "FastAsyncWorldEdit"}, + new String[]{"WorldGuard", "7.0.8"}, + new String[]{"FastAsyncWorldEdit", "2.4.3", "optional"}, + new String[]{"Multiverse-Core", "4.3.1", "optional"}, + new String[]{"Multiverse-Portals", "4.2.1", "optional"}, + new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, }; private static String missingRequirements = null; private static final Random RND = new Random(System.currentTimeMillis()); @@ -141,6 +145,9 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private PerkLogic perkLogic; private TeleportLogic teleportLogic; private LimitLogic limitLogic; + private GuiManager guiManager; + private Biomes biomes; + private BiomeConfig biomeConfig; /* MANAGERS */ private HookManager hookManager; @@ -252,7 +259,7 @@ public void run() { if (getWorldManager().getNetherWorld() != null) { WorldGuardHandler.setupGlobal(getWorldManager().getNetherWorld()); } - registerEventsAndCommands(); + registerEventsAndCommands(uSkyBlock.this.guiManager, uSkyBlock.this.biomes, uSkyBlock.this.biomeConfig); getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 log(Level.INFO, getVersionInfo(false)); @@ -269,8 +276,8 @@ public void run() { public synchronized boolean isRequirementsMet(CommandSender sender, Command command, String... args) { if (maintenanceMode && !( - (command instanceof AdminCommand && args != null && args.length > 0 && args[0].equals("maintenance")) || - command instanceof SetMaintenanceCommand)) { + (command instanceof AdminCommand && args != null && args.length > 0 && args[0].equals("maintenance")) || + command instanceof SetMaintenanceCommand)) { sender.sendMessage(tr("\u00a7cMAINTENANCE:\u00a7e uSkyBlock is currently in maintenance mode")); return false; } @@ -326,11 +333,12 @@ public static uSkyBlock getInstance() { return uSkyBlock.instance; } - public void registerEvents() { + public void registerEvents(GuiManager guiManager) { final PluginManager manager = getServer().getPluginManager(); manager.registerEvents(new InternalEvents(this), this); manager.registerEvents(new PlayerEvents(this), this); manager.registerEvents(new MenuEvents(this), this); + manager.registerEvents(new GuiListener(guiManager), this); manager.registerEvents(new ExploitEvents(this), this); manager.registerEvents(new WitherTagEvents(this), this); if (getConfig().getBoolean("options.protection.enabled", true)) { @@ -490,7 +498,7 @@ public synchronized boolean devSetPlayerIsland(final Player sender, final Locati if (pi.getHasIsland()) { Location oldLoc = pi.getIslandLocation(); if (oldLoc != null - && !(newLoc.getBlockX() == oldLoc.getBlockX() && newLoc.getBlockZ() == oldLoc.getBlockZ())) { + && !(newLoc.getBlockX() == oldLoc.getBlockX() && newLoc.getBlockZ() == oldLoc.getBlockZ())) { deleteOldIsland = true; } } @@ -521,12 +529,12 @@ public synchronized boolean devSetPlayerIsland(final Player sender, final Locati public boolean playerIsOnIsland(final Player player) { return playerIsOnOwnIsland(player) - || playerIsTrusted(player); + || playerIsTrusted(player); } public boolean playerIsOnOwnIsland(Player player) { return locationIsOnIsland(player, player.getLocation()) - || locationIsOnNetherIsland(player, player.getLocation()); + || locationIsOnNetherIsland(player, player.getLocation()); } private boolean playerIsTrusted(Player player) { @@ -725,7 +733,7 @@ public IslandLocatorLogic getIslandLocatorLogic() { @Override public void reloadConfig() { reloadConfigs(); - registerEventsAndCommands(); + registerEventsAndCommands(this.guiManager, this.biomes, this.biomeConfig); } private void reloadConfigs() { @@ -783,13 +791,16 @@ private void reloadConfigs() { autoRecalculateTask.cancel(); } chatLogic = new ChatLogic(this); + this.guiManager = new GuiManager(); + this.biomeConfig = new BiomeConfig(getLogger()); + this.biomes = new Biomes(this.guiManager, this.biomeConfig); } - public void registerEventsAndCommands() { + public void registerEventsAndCommands(GuiManager guiManager, Biomes biomes, BiomeConfig biomeConfig) { if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { return; } - registerEvents(); + registerEvents(guiManager); int refreshEveryMinute = getConfig().getInt("options.island.autoRefreshScore", 0); if (refreshEveryMinute > 0) { int refreshTicks = refreshEveryMinute * 1200; // Ticks per minute @@ -800,9 +811,9 @@ public void registerEventsAndCommands() { confirmHandler = new ConfirmHandler(this, getConfig().getInt("options.advanced.confirmTimeout", 10)); cooldownHandler = new CooldownHandler(this); animationHandler = new AnimationHandler(this); - getCommand("island").setExecutor(new IslandCommand(this, menu)); + getCommand("island").setExecutor(new IslandCommand(this, menu, biomes, biomeConfig)); getCommand("challenges").setExecutor(new ChallengeCommand(this)); - getCommand("usb").setExecutor(new AdminCommand(this, confirmHandler, animationHandler)); + getCommand("usb").setExecutor(new AdminCommand(this, confirmHandler, animationHandler, biomeConfig)); getCommand("islandtalk").setExecutor(new IslandTalkCommand(this, chatLogic)); getCommand("partytalk").setExecutor(new PartyTalkCommand(this, chatLogic)); } @@ -832,10 +843,10 @@ public void execCommand(Player player, String command, boolean onlyInSky) { return; } command = command - .replaceAll("\\{player\\}", Matcher.quoteReplacement(player.getName())) - .replaceAll("\\{playerName\\}", Matcher.quoteReplacement(player.getDisplayName())) - .replaceAll("\\{playername\\}", Matcher.quoteReplacement(player.getDisplayName())) - .replaceAll("\\{position\\}", Matcher.quoteReplacement(LocationUtil.asString(player.getLocation()))); // Figure out what this should be + .replaceAll("\\{player\\}", Matcher.quoteReplacement(player.getName())) + .replaceAll("\\{playerName\\}", Matcher.quoteReplacement(player.getDisplayName())) + .replaceAll("\\{playername\\}", Matcher.quoteReplacement(player.getDisplayName())) + .replaceAll("\\{position\\}", Matcher.quoteReplacement(LocationUtil.asString(player.getLocation()))); // Figure out what this should be Matcher m = Pattern.compile("^\\{p=(?0?\\.[0-9]+)\\}(.*)$").matcher(command); if (m.matches()) { double p = Double.parseDouble(m.group("prob")); @@ -946,8 +957,8 @@ public double getIslandLevel(Player player) { public IslandRank getIslandRank(Player player) { PlayerInfo playerInfo = getPlayerInfo(player); return islandLogic != null && playerInfo != null && playerInfo.getHasIsland() ? - islandLogic.getRank(playerInfo.locationForParty()) - : null; + islandLogic.getRank(playerInfo.locationForParty()) + : null; } @Override @@ -967,7 +978,7 @@ public void fireChangeEvent(CommandSender sender, uSkyBlockEvent.Cause cause) { public void fireAsyncEvent(final Event event) { getServer().getScheduler().runTaskAsynchronously(this, - () -> getServer().getPluginManager().callEvent(event) + () -> getServer().getPluginManager().callEvent(event) ); } @@ -1115,13 +1126,13 @@ public BukkitTask async(Runnable runnable) { public BukkitTask async(Runnable runnable, long delayMs) { return Bukkit.getScheduler().runTaskLaterAsynchronously(this, runnable, - TimeUtil.millisAsTicks(delayMs)); + TimeUtil.millisAsTicks(delayMs)); } public BukkitTask async(Runnable runnable, long delay, long every) { return Bukkit.getScheduler().runTaskTimerAsynchronously(this, runnable, - TimeUtil.millisAsTicks(delay), - TimeUtil.millisAsTicks(every)); + TimeUtil.millisAsTicks(delay), + TimeUtil.millisAsTicks(every)); } public BukkitTask sync(Runnable runnable) { @@ -1130,13 +1141,13 @@ public BukkitTask sync(Runnable runnable) { public BukkitTask sync(Runnable runnable, long delayMs) { return Bukkit.getScheduler().runTaskLater(this, runnable, - TimeUtil.millisAsTicks(delayMs)); + TimeUtil.millisAsTicks(delayMs)); } public BukkitTask sync(Runnable runnable, long delay, long every) { return Bukkit.getScheduler().runTaskTimer(this, runnable, - TimeUtil.millisAsTicks(delay), - TimeUtil.millisAsTicks(every)); + TimeUtil.millisAsTicks(delay), + TimeUtil.millisAsTicks(every)); } public void execCommands(Player player, List cmdList) { diff --git a/uSkyBlock-Core/src/main/resources/biomes.yml b/uSkyBlock-Core/src/main/resources/biomes.yml new file mode 100644 index 000000000..bf00215b4 --- /dev/null +++ b/uSkyBlock-Core/src/main/resources/biomes.yml @@ -0,0 +1,173 @@ +biomes: + ocean: + displayItem: tropical_fish + name: Ocean + description: | + The ocean biome is the basic + starting biome for all islands. + Passive mobs like animals will + not spawn. Hostile mobs will + spawn normally. + + forest: + displayItem: spruce_sapling + name: Forest + description: | + The forest biome will allow + your island to spawn passive + mobs like animals (including + wolves). Hostile mobs will + spawn normally. + + desert: + displayItem: sand + name: Desert + description: | + The desert biome makes it so + that there is no rain or snow + on your island. Passive mobs + won't spawn. Hostile mobs will + spawn normally. + + jungle: + displayItem: jungle_sapling + name: Jungle + description: | + The jungle biome is bright + and colorful. Passive mobs + (including ocelots) will + spawn. Hostile mobs will + spawn normally. + + swamp: + displayItem: lily_pad + name: Swamp + description: | + The swamp biome is dark + and dull. Passive mobs + will spawn normally and + slimes have a small chance + to spawn at night depending + on the moon phase. + + taiga: + displayItem: snow + name: Taiga + description: | + The taiga biome has snow + instead of rain. Passive + mobs will spawn normally + (including wolves) and + hostile mobs will spawn. + + mushroom_fields: + displayItem: red_mushroom + name: Mushroom Fields + description: | + The mushroom biome is + bright and colorful. + Mooshrooms are the only + mobs that will spawn. + No other passive or + hostile mobs will spawn. + + nether_wastes: + displayItem: nether_brick + name: Nether Wastes + description: | + The nether wastes look + dark and dead. Some + mobs from the nether will + spawn in this biome + (excluding ghasts and + blazes). + + the_end: + displayItem: ender_eye + name: The End + description: | + The end biome gives your + island a special dark sky. + Only endermen will spawn + in this biome. + + plains: + displayItem: tall_grass + name: Plains + description: | + The plains biome has rain + instead of snow. Passive + mobs will spawn normally + (including horses) and + hostile mobs will spawn. + + windswept_hills: + displayItem: emerald_ore + name: Extreme Hills + description: | + The extreme hills biome. + Passive mobs will spawn + normally and hostile + mobs will spawn. + + flower_forest: + displayItem: rose_bush + name: Flower Forest + description: | + The flower forest biome. + Passive mobs will spawn + normally and hostile + mobs will spawn. + + savanna_plateau: + displayItem: acacia_sapling + name: Savanna Plateau + description: | + The savanna plateau biome. Passive + mobs will spawn normally, including + llamas, horses, and donkeys. + Hostile mobs will spawn. + + lush_caves: + displayItem: glow_berries + name: Lush Caves + description: | + The lush caves biome. Passive + mobs will spawn normally, including + axolotls and tropical fish. Hostile + mobs will spawn. + + lukewarm_ocean: + displayItem: tropical_fish + name: Lukewarm Ocean + description: | + The lukewarm ocean biome is an advanced + biome. Spawn includes cod, squid, dolphin, + puffer fish, and tropical fish. + + snowy_slopes: + displayItem: goat_horn + name: Snowy Slopes + description: | + The snowy slopes biome. Passive mobs include + rabbits and goats. Hostile mobs will spawn. + + deep_ocean: + displayItem: prismarine_shard + name: Deep Ocean + description: | + The deep ocean biome is an advanced + biome. Passive mobs like animals will + not spawn. Hostile mobs (including + Guardians) will spawn normally. + + snowy_plains: + displayItem: snow_block + name: Snowy Plains + description: | + The snowy plains biome is an advanced + biome. No passive mobs will spawn except + rabbits and polar bears. Strays can spawn + at night. + +version: 1 From 4d7afecca23c7c7946b43c000aaf66b4fe4f9dba Mon Sep 17 00:00:00 2001 From: minoneer Date: Fri, 7 Feb 2025 21:06:09 +0100 Subject: [PATCH 145/190] Fix #78 UnsupportedOperationException when using a spawner egg --- .../ultimateskyblock/event/SpawnEvents.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index 5091ad552..25d5f252b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -2,8 +2,11 @@ import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.World; import org.bukkit.block.Biome; +import org.bukkit.entity.EntitySnapshot; import org.bukkit.entity.EntityType; import org.bukkit.entity.Phantom; import org.bukkit.entity.Player; @@ -17,12 +20,15 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SpawnEggMeta; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; import java.util.Collection; +import java.util.Objects; import java.util.Set; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -54,15 +60,14 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { return; } ItemStack item = event.getItem(); - if (RIGHT_CLICKS.contains(event.getAction()) && item != null && item.getItemMeta() instanceof SpawnEggMeta spawnEggMeta) { + if (RIGHT_CLICKS.contains(event.getAction()) && item != null && item.getItemMeta() instanceof SpawnEggMeta) { if (!plugin.playerIsOnIsland(player)) { event.setCancelled(true); plugin.notifyPlayer(player, tr("\u00a7eYou can only use spawn-eggs on your own island.")); return; } - //noinspection deprecation - checkLimits(event, spawnEggMeta.getSpawnedType(), player.getLocation()); + checkLimits(event, getSpawnEggType(item), player.getLocation()); if (event.useItemInHand() == Event.Result.DENY) { plugin.notifyPlayer(player, tr("\u00a7cYou have reached your spawn-limit for your island.")); event.setUseItemInHand(Event.Result.DENY); @@ -71,6 +76,22 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { } } + private static @Nullable EntityType getSpawnEggType(@NotNull ItemStack itemStack) { + if (itemStack.getItemMeta() instanceof SpawnEggMeta spawnEggMeta) { + EntitySnapshot spawnedEntity = spawnEggMeta.getSpawnedEntity(); + if (spawnedEntity != null) { + return spawnedEntity.getEntityType(); + } else { + String key = itemStack.getType().getKey().toString(); + String entityKey = key.replace("_spawn_egg", ""); + NamespacedKey namespacedKey = Objects.requireNonNull(NamespacedKey.fromString(entityKey)); + return Registry.ENTITY_TYPE.get(namespacedKey); + } + } else { + return null; + } + } + @EventHandler(ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent event) { if (event == null || !plugin.getWorldManager().isSkyAssociatedWorld(event.getLocation().getWorld())) { From 41d3038c9d8574a386eebe79d94ba8ee146f16a8 Mon Sep 17 00:00:00 2001 From: minoneer Date: Sun, 9 Feb 2025 22:43:55 +0100 Subject: [PATCH 146/190] Release version 3.1.0 --- bukkit-utils/pom.xml | 4 ++-- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 4 ++-- uSkyBlock-APIv2/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 6 +++--- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml index 7e3d4ba34..885144b28 100644 --- a/bukkit-utils/pom.xml +++ b/bukkit-utils/pom.xml @@ -7,7 +7,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 bukkit-utils @@ -102,7 +102,7 @@ ovh.uskyblock po-utils - 3.1.0-SNAPSHOT + 3.1.0 org.spigotmc diff --git a/po-utils/pom.xml b/po-utils/pom.xml index 023e26809..f122e9501 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 4.0.0 jar diff --git a/pom.xml b/pom.xml index 34035a80e..a866aab0a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ovh.uskyblock uSkyBlock pom - 3.1.0-SNAPSHOT + 3.1.0 Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 211bbe7fe..7ecd679fe 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -7,11 +7,11 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 com.github.rlf uSkyBlock-API - 3.1.0-SNAPSHOT + 3.1.0 UTF-8 diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index f54a135e7..e1d7a18e9 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 4.0.0 jar diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index c5f77cbc1..09ea84fac 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 4.0.0 jar @@ -339,12 +339,12 @@ ovh.uskyblock bukkit-utils - 3.1.0-SNAPSHOT + 3.1.0 ovh.uskyblock bukkit-utils - 3.1.0-SNAPSHOT + 3.1.0 test-jar test diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index aab556bb4..a6e6a67ba 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 9d23c4627..386d4d0f8 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0-SNAPSHOT + 3.1.0 4.0.0 jar From 0fe8776f7f8a0b507328469ae5fa6bc4f87da63b Mon Sep 17 00:00:00 2001 From: minoneer Date: Sun, 9 Feb 2025 22:46:10 +0100 Subject: [PATCH 147/190] Dev version 3.2.0-SNAPSHOT --- bukkit-utils/pom.xml | 4 ++-- po-utils/pom.xml | 2 +- pom.xml | 2 +- uSkyBlock-API/pom.xml | 4 ++-- uSkyBlock-APIv2/pom.xml | 2 +- uSkyBlock-Core/pom.xml | 6 +++--- uSkyBlock-FAWE/pom.xml | 2 +- uSkyBlock-Plugin/pom.xml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml index 885144b28..d6c78ae12 100644 --- a/bukkit-utils/pom.xml +++ b/bukkit-utils/pom.xml @@ -7,7 +7,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT bukkit-utils @@ -102,7 +102,7 @@ ovh.uskyblock po-utils - 3.1.0 + 3.2.0-SNAPSHOT org.spigotmc diff --git a/po-utils/pom.xml b/po-utils/pom.xml index f122e9501..1701740b3 100644 --- a/po-utils/pom.xml +++ b/po-utils/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 jar diff --git a/pom.xml b/pom.xml index a866aab0a..db6931dd4 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ovh.uskyblock uSkyBlock pom - 3.1.0 + 3.2.0-SNAPSHOT Ultimate SkyBlock diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml index 7ecd679fe..25cd4787c 100644 --- a/uSkyBlock-API/pom.xml +++ b/uSkyBlock-API/pom.xml @@ -7,11 +7,11 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT com.github.rlf uSkyBlock-API - 3.1.0 + 3.2.0-SNAPSHOT UTF-8 diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml index e1d7a18e9..471465ef1 100644 --- a/uSkyBlock-APIv2/pom.xml +++ b/uSkyBlock-APIv2/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 jar diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index 09ea84fac..a4256820f 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 jar @@ -339,12 +339,12 @@ ovh.uskyblock bukkit-utils - 3.1.0 + 3.2.0-SNAPSHOT ovh.uskyblock bukkit-utils - 3.1.0 + 3.2.0-SNAPSHOT test-jar test diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml index a6e6a67ba..23315ca13 100644 --- a/uSkyBlock-FAWE/pom.xml +++ b/uSkyBlock-FAWE/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 uSkyBlock-FAWE diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml index 386d4d0f8..a342cfdbd 100644 --- a/uSkyBlock-Plugin/pom.xml +++ b/uSkyBlock-Plugin/pom.xml @@ -5,7 +5,7 @@ uSkyBlock ovh.uskyblock - 3.1.0 + 3.2.0-SNAPSHOT 4.0.0 jar From 8ad2dc248aee66baed7095507a14e601cff04cf8 Mon Sep 17 00:00:00 2001 From: minoneer Date: Sun, 9 Feb 2025 22:52:53 +0100 Subject: [PATCH 148/190] Dependency injection (#79) The goal of this PR is to improve the maintainability of the plugin by moving towards dependency-injection-based initialization. Current issue: The plugin currently uses a combination of static references, a massive single-instance service locator (the main uSkyBlock class), and passing dependencies down to child objects. This means initialization order is implicit, and changing anything in the order may break stuff due to undocumented implicit dependencies an overloaded main plugin class implicit cyclic dependencies between services changing a class usually requires changes to several others, including the main plugin class Things are hard to test, as everything depends on everything else This PR breaks these dependencies through dependency injection using Guice. Most services, commands, and listeners are initialized through DI Some services were refactored to depend on the actual type instead of the uSkyBlock class. This is an ongoing effort and will require continued effort in the future Moved most of the initialization code out of the main plugin class Initial testing looks good, but since this is a larger change, it may cause some initial instability or hidden issues. Closes #14 Resolves #76 * Add guice for dependency injection * Use DI for biome related classes * Initialize most services via dependency injection - Make most dependencies obvious by moving injections to the constructor - Break some cyclic dependencies - Reduce reliance on the main plugin class * Restructure Command and Listener lifecycle management * Initialize sub commands via dependency injection * Cleanup more bootstrapping * Additional bootstrap cleanup * Move Island level refresh task out of main plugin class * More lifecycle cleanup * Move version info to its own module * Fix static legacy initialization * Move directory initializations to their proper classes * Add Settings to early legacy initialization * Remove redundant imports from MainConfigMenu --- .../completion/AbstractTabCompleter.java | 1 + .../lockfuglsang/minecraft/util/TimeUtil.java | 9 + pom.xml | 1 + uSkyBlock-Core/pom.xml | 5 + .../ultimateskyblock/MetricsManager.java | 6 + .../ultimateskyblock/PluginConfig.java | 19 + .../ultimateskyblock/SkyUpdateChecker.java | 29 +- .../api/event/EventLogic.java | 24 +- .../async/IncrementalRunnable.java | 49 +-- .../ultimateskyblock/biome/BiomeConfig.java | 4 + .../ultimateskyblock/biome/Biomes.java | 2 + .../ultimateskyblock/bootstrap/Commands.java | 46 ++ .../ultimateskyblock/bootstrap/Listeners.java | 129 ++++++ .../bootstrap/PluginDataDir.java | 17 + .../ultimateskyblock/bootstrap/Services.java | 83 ++++ .../bootstrap/SkyblockApp.java | 49 +++ .../bootstrap/SkyblockModule.java | 67 +++ .../challenge/ChallengeLogic.java | 45 +- .../ultimateskyblock/chat/ChatEvents.java | 7 +- .../ultimateskyblock/chat/ChatLogic.java | 27 +- .../chat/IslandTalkCommand.java | 7 +- .../chat/PartyTalkCommand.java | 7 +- .../command/AdminCommand.java | 118 ++++-- .../command/ChallengeCommand.java | 45 +- .../command/InviteHandler.java | 36 +- .../command/IslandCommand.java | 111 +++-- .../command/admin/AdminChallengeCommand.java | 5 +- .../command/admin/AdminIslandCommand.java | 5 +- .../command/admin/ChunkCommand.java | 7 +- .../command/admin/ConfigCommand.java | 5 +- .../command/admin/CooldownCommand.java | 6 +- .../command/admin/DebugCommand.java | 19 +- .../command/admin/FlatlandFixCommand.java | 5 +- .../command/admin/FlushCommand.java | 5 +- .../command/admin/GenTopTenCommand.java | 5 +- .../command/admin/GotoIslandCommand.java | 5 +- .../command/admin/ImportCommand.java | 2 + .../command/admin/ItemInfoCommand.java | 3 + .../command/admin/JobsCommand.java | 5 +- .../command/admin/LanguageCommand.java | 5 +- .../command/admin/OrphanCommand.java | 6 +- .../command/admin/PerkCommand.java | 6 +- .../command/admin/PlayerInfoCommand.java | 20 + .../command/admin/ProtectAllCommand.java | 10 +- .../command/admin/PurgeCommand.java | 10 +- .../command/admin/RegionCommand.java | 5 +- .../admin/RegisterIslandToPlayerCommand.java | 7 +- .../command/admin/ReloadCommand.java | 3 + .../command/admin/SetMaintenanceCommand.java | 5 +- .../command/admin/VersionCommand.java | 15 +- .../command/admin/WGCommand.java | 5 +- .../command/admin/task/ProtectAllTask.java | 9 +- .../challenge/ChallengeCompleteCommand.java | 18 +- .../challenge/ChallengeInfoCommand.java | 29 +- .../completion/AllPlayerTabCompleter.java | 2 + .../AvailableChallengeTabCompleter.java | 25 +- .../command/completion/BiomeTabCompleter.java | 5 +- .../completion/MemberTabCompleter.java | 27 +- .../completion/PermissionTabCompleter.java | 5 +- .../command/completion/RankTabCompleter.java | 13 +- .../completion/SchematicTabCompleter.java | 2 + .../command/island/AcceptRejectCommand.java | 5 +- .../command/island/AutoCommand.java | 5 +- .../command/island/BanCommand.java | 6 +- .../command/island/BiomeCommand.java | 5 +- .../command/island/CreateCommand.java | 5 +- .../command/island/HomeCommand.java | 6 +- .../command/island/InfoCommand.java | 6 +- .../command/island/InviteCommand.java | 8 +- .../command/island/KickCommand.java | 6 +- .../command/island/LeaveCommand.java | 5 +- .../command/island/LevelCommand.java | 6 +- .../command/island/LockUnlockCommand.java | 6 +- .../command/island/LogCommand.java | 2 + .../command/island/MakeLeaderCommand.java | 6 +- .../command/island/MobLimitCommand.java | 5 +- .../command/island/PartyCommand.java | 5 +- .../command/island/PermCommand.java | 6 +- .../command/island/RestartCommand.java | 6 +- .../command/island/SetHomeCommand.java | 3 + .../command/island/SetWarpCommand.java | 6 +- .../command/island/SpawnCommand.java | 5 +- .../command/island/ToggleWarp.java | 3 + .../command/island/TopCommand.java | 5 +- .../command/island/TrustCommand.java | 6 +- .../command/island/WarpCommand.java | 5 +- .../ultimateskyblock/event/ExploitEvents.java | 7 +- .../ultimateskyblock/event/GriefEvents.java | 6 +- .../event/InternalEvents.java | 8 +- .../event/ItemDropEvents.java | 7 +- .../ultimateskyblock/event/MenuEvents.java | 20 +- .../event/NetherTerraFormEvents.java | 7 +- .../ultimateskyblock/event/PlayerEvents.java | 7 +- .../ultimateskyblock/event/SpawnEvents.java | 6 +- .../event/ToolMenuEvents.java | 10 +- .../event/WitherTagEvents.java | 7 +- .../event/WorldGuardEvents.java | 7 +- .../ultimateskyblock/gui/GuiListener.java | 4 + .../ultimateskyblock/gui/GuiManager.java | 2 + .../handler/ConfirmHandler.java | 57 +-- .../handler/CooldownHandler.java | 46 +- .../handler/task/WorldEditClear.java | 2 +- .../task/WorldEditClearFlatlandTask.java | 30 +- .../ultimateskyblock/hook/HookManager.java | 55 ++- .../imports/USBImporterExecutor.java | 6 +- .../fixuuidleader/UUIDLeaderImporter.java | 12 +- .../imports/update/USBUpdateImporter.java | 6 +- .../island/BlockLimitLogic.java | 21 +- .../island/IslandGenerator.java | 61 ++- .../ultimateskyblock/island/IslandInfo.java | 10 +- .../island/IslandLocatorLogic.java | 74 ++-- .../ultimateskyblock/island/IslandLogic.java | 208 +++++---- .../ultimateskyblock/island/LimitLogic.java | 70 +-- .../ultimateskyblock/island/OrphanLogic.java | 44 +- .../island/level/AutoIslandLevelRefresh.java | 43 ++ .../island/level/AweLevelLogic.java | 6 +- .../island/level/ChunkSnapshotLevelLogic.java | 44 +- .../island/level/CommonLevelLogic.java | 32 +- .../island/task/ChunkSnapShotTask.java | 10 +- .../island/task/SetBiomeTask.java | 4 +- .../ultimateskyblock/menu/ConfigMenu.java | 32 +- .../ultimateskyblock/menu/MainConfigMenu.java | 1 - .../ultimateskyblock/menu/SkyBlockMenu.java | 104 +++-- .../player/NotificationManager.java | 15 +- .../ultimateskyblock/player/PerkLogic.java | 132 +++--- .../ultimateskyblock/player/PlayerInfo.java | 17 +- .../ultimateskyblock/player/PlayerLogic.java | 161 ++++--- .../player/PlayerNotifier.java | 52 +-- .../player/TeleportLogic.java | 65 ++- .../ultimateskyblock/signs/SignEvents.java | 7 +- .../ultimateskyblock/signs/SignLogic.java | 57 ++- .../talabrek/ultimateskyblock/uSkyBlock.java | 401 +++++------------- .../ultimateskyblock/util/PlayerUtil.java | 45 -- .../ultimateskyblock/util/PluginInfo.java | 93 ++++ .../ultimateskyblock/util/Scheduler.java | 45 ++ .../ultimateskyblock/uuid/FilePlayerDB.java | 62 ++- .../ultimateskyblock/uuid/MemoryPlayerDB.java | 69 ++- .../ultimateskyblock/world/WorldManager.java | 141 +++--- uSkyBlock-Core/src/main/resources/plugin.yml | 1 + .../event/MenuEventsTest.java | 7 +- .../island/IslandLocatorLogicTest.java | 10 +- 141 files changed, 2509 insertions(+), 1331 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/PluginConfig.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Commands.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Listeners.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/PluginDataDir.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PlayerInfoCommand.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PlayerUtil.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PluginInfo.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/Scheduler.java diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java index d9227d208..dd0a87e2b 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/AbstractTabCompleter.java @@ -3,6 +3,7 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collections; diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java index 639cb453f..d60c8c64c 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java @@ -1,5 +1,6 @@ package dk.lockfuglsang.minecraft.util; +import java.time.Duration; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -89,4 +90,12 @@ public static long millisAsTicks(long ms) { public static long ticksAsMillis(int ticks) { return ticks * 50; } + + public static long durationAsTicks(Duration duration) { + return duration.toMillis() / 50; + } + + public static Duration ticksAsDuration(long ticks) { + return Duration.ofMillis(ticks * 50); + } } diff --git a/pom.xml b/pom.xml index db6931dd4..d44536ff8 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 1.7 7.2.19 7.0.9 + 7.0.0 UTF-8 ${project.artifactId} diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml index a4256820f..f34e779ee 100644 --- a/uSkyBlock-Core/pom.xml +++ b/uSkyBlock-Core/pom.xml @@ -459,6 +459,11 @@ gson provided + + com.google.inject + guice + ${guice.version} + be.maximvdw MVdWPlaceholderAPI diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java index 8d3ec64c4..47dd75ea0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/MetricsManager.java @@ -1,10 +1,13 @@ package us.talabrek.ultimateskyblock; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bstats.bukkit.Metrics; import org.bstats.charts.SimplePie; import java.util.logging.Level; +@Singleton public class MetricsManager { // Pushing to two accounts at the moment to track both legacy and current installations. private static final int BSTATS_MUSPAH_ID = 7525; @@ -12,9 +15,12 @@ public class MetricsManager { private final uSkyBlock plugin; + @Inject public MetricsManager(uSkyBlock plugin) { this.plugin = plugin; + } + public void setup() { try { setupMetrics(BSTATS_MUSPAH_ID); setupMetrics(BSTATS_RLF_ID); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/PluginConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/PluginConfig.java new file mode 100644 index 000000000..65e322301 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/PluginConfig.java @@ -0,0 +1,19 @@ +package us.talabrek.ultimateskyblock; + +import com.google.inject.Inject; +import dk.lockfuglsang.minecraft.file.FileUtil; +import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; + +public class PluginConfig { + + @Inject + public PluginConfig() { + Settings.loadPluginConfig(getYamlConfig()); + } + + @NotNull + public FileConfiguration getYamlConfig() { + return FileUtil.getYmlConfiguration("config.yml"); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java index c85ff6718..9e2e8d350 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java @@ -2,6 +2,7 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.google.inject.Inject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; @@ -16,15 +17,28 @@ import java.net.URI; import java.util.concurrent.CompletableFuture; +import java.util.logging.Level; +import java.util.logging.Logger; public class SkyUpdateChecker implements UpdateChecker { + + private final Logger logger; + private final PluginConfig config; + private final uSkyBlock plugin; + private String latestVersion; private final Gson gson = new Gson(); - private final uSkyBlock plugin; - public SkyUpdateChecker(uSkyBlock plugin) { + @Inject + public SkyUpdateChecker( + @NotNull uSkyBlock plugin, + @NotNull PluginConfig config, + @NotNull Logger logger + ) { this.plugin = plugin; + this.config = config; + this.logger = logger; } /** @@ -34,19 +48,19 @@ public SkyUpdateChecker(uSkyBlock plugin) { public void checkForUpdates() { URI uri = URL_RELEASE; - if (plugin.getConfig().getString("plugin-updates.branch", "RELEASE").equalsIgnoreCase("STAGING")) { + if (config.getYamlConfig().getString("plugin-updates.branch", "RELEASE").equalsIgnoreCase("STAGING")) { uri = URL_STAGING; } fetchLatestVersion(uri).thenAccept(version -> { latestVersion = version; if (latestVersion == null) { - plugin.getLogger().info("Failed to check for new uSkyBlock versions."); + logger.info("Failed to check for new uSkyBlock versions."); } if (isUpdateAvailable()) { - plugin.getLogger().info("There is a new version of uSkyBlock available: " + getLatestVersion()); - plugin.getLogger().info("Visit https://www.uskyblock.ovh/get to download."); + logger.info("There is a new version of uSkyBlock available: " + getLatestVersion()); + logger.info("Visit https://www.uskyblock.ovh/get to download."); } }); } @@ -97,8 +111,7 @@ public CompletableFuture fetchLatestVersion(URI uri) { } } } catch (Exception ex) { - plugin.getLogger().warning("Exception while trying to fetch latest plugin version."); - ex.printStackTrace(); + logger.log(Level.SEVERE, "Exception while trying to fetch latest plugin version.", ex); } return null; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/event/EventLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/event/EventLogic.java index 503bc38a7..293de7100 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/event/EventLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/api/event/EventLogic.java @@ -1,27 +1,31 @@ package us.talabrek.ultimateskyblock.api.event; +import com.google.inject.Inject; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; public class EventLogic { - private final uSkyBlock plugin; + private final Scheduler scheduler; - public EventLogic(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public EventLogic(@NotNull Scheduler scheduler) { + this.scheduler = scheduler; } /** * Fires a new async {@link IslandLeaderChangedEvent}. * - * @param islandInfo {@link IslandInfo} for the island in the scope of this event. + * @param islandInfo {@link IslandInfo} for the island in the scope of this event. * @param originalLeaderInfo {@link PlayerInfo} for the original island leader. - * @param newLeaderInfo {@link PlayerInfo} for the new island leader. + * @param newLeaderInfo {@link PlayerInfo} for the new island leader. */ public void fireIslandLeaderChangedEvent(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo, us.talabrek.ultimateskyblock.api.PlayerInfo originalLeaderInfo, us.talabrek.ultimateskyblock.api.PlayerInfo newLeaderInfo) { - plugin.async(() -> plugin.getServer().getPluginManager().callEvent(new IslandLeaderChangedEvent(islandInfo, originalLeaderInfo, newLeaderInfo))); + scheduler.async(() -> Bukkit.getPluginManager().callEvent(new IslandLeaderChangedEvent(islandInfo, originalLeaderInfo, newLeaderInfo))); } /** @@ -31,17 +35,17 @@ public void fireIslandLeaderChangedEvent(us.talabrek.ultimateskyblock.api.Island * @param playerInfo {@link PlayerInfo} for the joined member. */ public void fireMemberJoinedEvent(us.talabrek.ultimateskyblock.island.IslandInfo islandInfo, us.talabrek.ultimateskyblock.player.PlayerInfo playerInfo) { - plugin.async(() -> plugin.getServer().getPluginManager().callEvent(new MemberJoinedEvent(islandInfo, playerInfo))); + scheduler.async(() -> Bukkit.getPluginManager().callEvent(new MemberJoinedEvent(islandInfo, playerInfo))); } /** * Fires a new async {@link MemberLeftEvent}. * * @param islandInfo {@link IslandInfo} for the island that the member left. - * @param member {@link PlayerInfo} for the left member. + * @param member {@link PlayerInfo} for the left member. */ public void fireMemberLeftEvent(IslandInfo islandInfo, PlayerInfo member) { - plugin.async(() -> plugin.getServer().getPluginManager().callEvent(new MemberLeftEvent(islandInfo, member))); + scheduler.async(() -> Bukkit.getPluginManager().callEvent(new MemberLeftEvent(islandInfo, member))); } public void shutdown() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java index bda4eab2d..9f200ea35 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java @@ -1,8 +1,9 @@ package us.talabrek.ultimateskyblock.async; -import org.bukkit.scheduler.BukkitRunnable; -import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.TimeUtil; +import org.bukkit.scheduler.BukkitRunnable; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.util.Scheduler; /** * Convenience template class for executing heavy tasks on the main thread. @@ -23,7 +24,7 @@ * */ public abstract class IncrementalRunnable extends BukkitRunnable { - private final uSkyBlock plugin; + private final Scheduler scheduler; private Runnable onCompletion; /** * The maximum number of consecutive ms to execute a task. @@ -67,24 +68,24 @@ public abstract class IncrementalRunnable extends BukkitRunnable { */ private volatile int ticks = 0; - public IncrementalRunnable(uSkyBlock plugin) { - this(plugin, null, - plugin.getConfig().getInt("async.maxMs", 15), - plugin.getConfig().getInt("async.maxConsecutiveTicks", 20), - plugin.getConfig().getInt("async.yieldDelay", 2) + public IncrementalRunnable(Scheduler scheduler, PluginConfig config) { + this(scheduler, null, + config.getYamlConfig().getInt("async.maxMs", 15), + config.getYamlConfig().getInt("async.maxConsecutiveTicks", 20), + config.getYamlConfig().getInt("async.yieldDelay", 2) ); } - public IncrementalRunnable(uSkyBlock plugin, Runnable onCompletion) { - this(plugin, onCompletion, - plugin.getConfig().getInt("async.maxMs", 15), - plugin.getConfig().getInt("async.maxConsecutiveTicks", 20), - plugin.getConfig().getInt("async.yieldDelay", 2) + public IncrementalRunnable(Scheduler scheduler, PluginConfig config, Runnable onCompletion) { + this(scheduler, onCompletion, + config.getYamlConfig().getInt("async.maxMs", 15), + config.getYamlConfig().getInt("async.maxConsecutiveTicks", 20), + config.getYamlConfig().getInt("async.yieldDelay", 2) ); } - public IncrementalRunnable(uSkyBlock plugin, Runnable onCompletion, int maxMs, int maxConsecutive, int yieldDelay) { - this.plugin = plugin; + public IncrementalRunnable(Scheduler scheduler, Runnable onCompletion, int maxMs, int maxConsecutive, int yieldDelay) { + this.scheduler = scheduler; this.onCompletion = onCompletion; this.maxMs = maxMs; this.maxConsecutive = maxConsecutive; @@ -97,6 +98,7 @@ protected boolean hasTime() { /** * Used by sub-classes to see how much time they have left. + * * @return The number of ms the current #execute() has been running. */ protected long millisActive() { @@ -108,14 +110,10 @@ protected double millisLeft() { } public boolean stillTime() { - double millisPerTick = getTimeUsed()/(iterations != 0 ? iterations : 1); + double millisPerTick = getTimeUsed() / (iterations != 0 ? iterations : 1); return millisPerTick < millisLeft(); } - public uSkyBlock getPlugin() { - return plugin; - } - protected boolean tick() { iterations++; return stillTime(); @@ -123,12 +121,14 @@ protected boolean tick() { /** * Executes a potentially heavy task + * * @return true if done, false otherwise. */ protected abstract boolean execute(); /** * Returns the number of ms the task has been active. + * * @return the number of ms the task has been active. */ public long getTimeElapsed() { @@ -143,10 +143,11 @@ public long getTimeElapsed() { /** * Returns the number of ms the task has been actively executing. + * * @return the number of ms the task has been actively executing. */ public double getTimeUsed() { - return tUsed + (tRunning != 0 ? t()-tRunning : 0); + return tUsed + (tRunning != 0 ? t() - tRunning : 0); } public void cancel() { @@ -163,10 +164,10 @@ public final void run() { try { consecutiveRuns++; if (!execute() && !isCancelled) { - plugin.sync(this, TimeUtil.ticksAsMillis(consecutiveRuns < maxConsecutive ? 0 : yieldDelay)); + scheduler.sync(this, TimeUtil.ticksAsDuration(consecutiveRuns < maxConsecutive ? 0 : yieldDelay)); } else { if (onCompletion != null && !isCancelled) { - plugin.sync(onCompletion); + scheduler.sync(onCompletion); } complete(); } @@ -181,7 +182,7 @@ public final void run() { } private static double t() { - return System.nanoTime()/1000000d; + return System.nanoTime() / 1000000d; } protected void setOnCompletion(Runnable onCompletion) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java index 020448b05..dfeba39ec 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.biome; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.file.FileUtil; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Material; @@ -18,12 +20,14 @@ import static java.util.Objects.requireNonNull; +@Singleton public class BiomeConfig { private final Logger logger; private final List configuredBiomeEntries; private final List configuredBiomeKeys; + @Inject public BiomeConfig(Logger logger) { this.logger = logger; this.configuredBiomeEntries = loadBiomes(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java index 9b5c522d2..c54bfdfe2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/Biomes.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.biome; +import com.google.inject.Inject; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.gui.GuiManager; import us.talabrek.ultimateskyblock.island.IslandInfo; @@ -9,6 +10,7 @@ public class Biomes { private final GuiManager guiManager; private final BiomeConfig biomeConfig; + @Inject public Biomes(GuiManager guiManager, BiomeConfig biomeConfig) { this.guiManager = guiManager; this.biomeConfig = biomeConfig; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Commands.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Commands.java new file mode 100644 index 000000000..d969bebe7 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Commands.java @@ -0,0 +1,46 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.chat.IslandTalkCommand; +import us.talabrek.ultimateskyblock.chat.PartyTalkCommand; +import us.talabrek.ultimateskyblock.command.AdminCommand; +import us.talabrek.ultimateskyblock.command.ChallengeCommand; +import us.talabrek.ultimateskyblock.command.IslandCommand; + +import static java.util.Objects.requireNonNull; + +@Singleton +public class Commands { + + private final IslandCommand islandCommand; + private final ChallengeCommand challengeCommand; + private final AdminCommand adminCommand; + private final IslandTalkCommand islandTalkCommand; + private final PartyTalkCommand partyTalkCommand; + + @Inject + public Commands( + @NotNull IslandCommand islandCommand, + @NotNull ChallengeCommand challengeCommand, + @NotNull AdminCommand adminCommand, + @NotNull IslandTalkCommand islandTalkCommand, + @NotNull PartyTalkCommand partyTalkCommand + ) { + this.islandCommand = islandCommand; + this.challengeCommand = challengeCommand; + this.adminCommand = adminCommand; + this.islandTalkCommand = islandTalkCommand; + this.partyTalkCommand = partyTalkCommand; + } + + public void registerCommands(JavaPlugin plugin) { + requireNonNull(plugin.getCommand("island")).setExecutor(islandCommand); + requireNonNull(plugin.getCommand("challenges")).setExecutor(challengeCommand); + requireNonNull(plugin.getCommand("usb")).setExecutor(adminCommand); + requireNonNull(plugin.getCommand("islandtalk")).setExecutor(islandTalkCommand); + requireNonNull(plugin.getCommand("partytalk")).setExecutor(partyTalkCommand); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Listeners.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Listeners.java new file mode 100644 index 000000000..dbd89dd89 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Listeners.java @@ -0,0 +1,129 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.event.HandlerList; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginManager; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.chat.ChatEvents; +import us.talabrek.ultimateskyblock.event.ExploitEvents; +import us.talabrek.ultimateskyblock.event.GriefEvents; +import us.talabrek.ultimateskyblock.event.InternalEvents; +import us.talabrek.ultimateskyblock.event.ItemDropEvents; +import us.talabrek.ultimateskyblock.event.MenuEvents; +import us.talabrek.ultimateskyblock.event.NetherTerraFormEvents; +import us.talabrek.ultimateskyblock.event.PlayerEvents; +import us.talabrek.ultimateskyblock.event.SpawnEvents; +import us.talabrek.ultimateskyblock.event.ToolMenuEvents; +import us.talabrek.ultimateskyblock.event.WitherTagEvents; +import us.talabrek.ultimateskyblock.event.WorldGuardEvents; +import us.talabrek.ultimateskyblock.gui.GuiListener; +import us.talabrek.ultimateskyblock.signs.SignEvents; +import us.talabrek.ultimateskyblock.command.InviteHandler; +import us.talabrek.ultimateskyblock.uuid.PlayerDB; + +@Singleton +public class Listeners { + + private final PluginConfig config; + + private final GuiListener guiListener; + private final InternalEvents internalEvents; + private final PlayerEvents playerEvents; + private final MenuEvents menuEvents; + private final ExploitEvents exploitEvents; + private final WitherTagEvents witherTagEvents; + private final GriefEvents griefEvents; + private final ItemDropEvents itemDropEvents; + private final SpawnEvents spawnEvents; + private final WorldGuardEvents worldGuardEvents; + private final NetherTerraFormEvents netherTerraFormEvents; + private final ToolMenuEvents toolMenuEvents; + private final SignEvents signEvents; + private final ChatEvents chatEvents; + private final InviteHandler inviteHandler; + private final PlayerDB playerDB; + + @Inject + public Listeners( + @NotNull PluginConfig config, + @NotNull GuiListener guiListener, + @NotNull InternalEvents internalEvents, + @NotNull PlayerEvents playerEvents, + @NotNull MenuEvents menuEvents, + @NotNull ExploitEvents exploitEvents, + @NotNull WitherTagEvents witherTagEvents, + @NotNull GriefEvents griefEvents, + @NotNull ItemDropEvents itemDropEvents, + @NotNull SpawnEvents spawnEvents, + @NotNull WorldGuardEvents worldGuardEvents, + @NotNull NetherTerraFormEvents netherTerraFormEvents, + @NotNull ToolMenuEvents toolMenuEvents, + @NotNull SignEvents signEvents, + @NotNull ChatEvents chatEvents, + @NotNull InviteHandler inviteHandler, + @NotNull PlayerDB playerDB + ) { + this.config = config; + this.guiListener = guiListener; + this.internalEvents = internalEvents; + this.playerEvents = playerEvents; + this.menuEvents = menuEvents; + this.exploitEvents = exploitEvents; + this.witherTagEvents = witherTagEvents; + this.griefEvents = griefEvents; + this.itemDropEvents = itemDropEvents; + this.spawnEvents = spawnEvents; + this.worldGuardEvents = worldGuardEvents; + this.netherTerraFormEvents = netherTerraFormEvents; + this.toolMenuEvents = toolMenuEvents; + this.signEvents = signEvents; + this.chatEvents = chatEvents; + this.inviteHandler = inviteHandler; + this.playerDB = playerDB; + } + + public void registerListeners(Plugin plugin) { + PluginManager manager = plugin.getServer().getPluginManager(); + + manager.registerEvents(internalEvents, plugin); + manager.registerEvents(playerEvents, plugin); + manager.registerEvents(menuEvents, plugin); + manager.registerEvents(guiListener, plugin); + manager.registerEvents(exploitEvents, plugin); + manager.registerEvents(witherTagEvents, plugin); + manager.registerEvents(chatEvents, plugin); + manager.registerEvents(inviteHandler, plugin); + manager.registerEvents(playerDB, plugin); + + // TODO minoneer 06.02.2025: Move this logic. Either into the appropriate listener, or into submodules if we don't want all features active (e.g., the nether) + if (config.getYamlConfig().getBoolean("options.protection.enabled", true)) { + manager.registerEvents(griefEvents, plugin); + if (config.getYamlConfig().getBoolean("options.protection.item-drops", true)) { + manager.registerEvents(itemDropEvents, plugin); + } + } + if (config.getYamlConfig().getBoolean("options.island.spawn-limits.enabled", true)) { + manager.registerEvents(spawnEvents, plugin); + } + if (config.getYamlConfig().getBoolean("options.protection.visitors.block-banned-entry", true)) { + manager.registerEvents(worldGuardEvents, plugin); + } + if (Settings.nether_enabled) { + manager.registerEvents(netherTerraFormEvents, plugin); + } + if (config.getYamlConfig().getBoolean("tool-menu.enabled", true)) { + manager.registerEvents(toolMenuEvents, plugin); + } + if (config.getYamlConfig().getBoolean("signs.enabled", true)) { + manager.registerEvents(signEvents, plugin); + } + } + + public void unregisterListeners(Plugin plugin) { + HandlerList.unregisterAll(plugin); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/PluginDataDir.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/PluginDataDir.java new file mode 100644 index 000000000..1f8d5ba85 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/PluginDataDir.java @@ -0,0 +1,17 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.BindingAnnotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@BindingAnnotation +@Target({FIELD, PARAMETER, METHOD}) +@Retention(RUNTIME) +public @interface PluginDataDir { +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java new file mode 100644 index 000000000..abd45d4cf --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java @@ -0,0 +1,83 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.animation.AnimationHandler; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.MetricsManager; +import us.talabrek.ultimateskyblock.api.event.EventLogic; +import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; +import us.talabrek.ultimateskyblock.command.admin.DebugCommand; +import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; +import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; +import us.talabrek.ultimateskyblock.hook.HookManager; +import us.talabrek.ultimateskyblock.island.IslandLogic; +import us.talabrek.ultimateskyblock.island.level.AutoIslandLevelRefresh; +import us.talabrek.ultimateskyblock.player.PlayerLogic; +import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.uuid.PlayerDB; + +@Singleton +public class Services { + + private final AnimationHandler animationHandler; + private final ChallengeLogic challengeLogic; + private final EventLogic eventLogic; + private final PlayerLogic playerLogic; + private final IslandLogic islandLogic; + private final PlayerDB playerDB; + private final MetricsManager metricsManager; + private final HookManager hookManager; + private final AutoIslandLevelRefresh autoIslandLevelRefresh; + + @Inject + public Services( + @NotNull AnimationHandler animationHandler, + @NotNull ChallengeLogic challengeLogic, + @NotNull EventLogic eventLogic, + @NotNull PlayerLogic playerLogic, + @NotNull IslandLogic islandLogic, + @NotNull PlayerDB playerDB, + @NotNull MetricsManager metricsManager, + @NotNull HookManager hookManager, + @NotNull AutoIslandLevelRefresh autoIslandLevelRefresh + ) { + this.animationHandler = animationHandler; + this.challengeLogic = challengeLogic; + this.eventLogic = eventLogic; + this.playerLogic = playerLogic; + this.islandLogic = islandLogic; + this.playerDB = playerDB; + this.metricsManager = metricsManager; + this.hookManager = hookManager; + this.autoIslandLevelRefresh = autoIslandLevelRefresh; + } + + public void startup() { + metricsManager.setup(); + autoIslandLevelRefresh.startup(); + } + + public void delayedEnable(uSkyBlock plugin) { + hookManager.setupHooks(); + + // TODO: make these non-static objects + AsyncWorldEditHandler.onEnable(plugin); + WorldGuardHandler.setupGlobal(plugin.getWorldManager().getWorld()); + if (plugin.getWorldManager().getNetherWorld() != null) { + WorldGuardHandler.setupGlobal(plugin.getWorldManager().getNetherWorld()); + } + } + + public void shutdown(uSkyBlock plugin) { + autoIslandLevelRefresh.shutdown(); + animationHandler.stop(); + challengeLogic.shutdown(); + eventLogic.shutdown(); + playerLogic.shutdown(); + islandLogic.shutdown(); + playerDB.shutdown(); + AsyncWorldEditHandler.onDisable(plugin); + DebugCommand.disableLogging(null); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java new file mode 100644 index 000000000..2ec71e06a --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java @@ -0,0 +1,49 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; +import us.talabrek.ultimateskyblock.uSkyBlock; + +@Singleton +public class SkyblockApp { + + private final Services services; + private final Commands commands; + private final Listeners listeners; + + @Inject + public SkyblockApp(@NotNull Services services, @NotNull Commands commands, @NotNull Listeners listeners) { + this.services = services; + this.commands = commands; + this.listeners = listeners; + } + + + public void startup(uSkyBlock plugin) { + services.startup(); + } + + public void delayedEnable(uSkyBlock plugin) { + services.delayedEnable(plugin); + + // do these really have to be delayed? + commands.registerCommands(plugin); + listeners.registerListeners(plugin); + + // TODO: make this object oriented + PlaceholderHandler.register(plugin); + } + + public void shutdown(uSkyBlock plugin) { + PlaceholderHandler.unregister(plugin); + Bukkit.getScheduler().cancelTasks(plugin); + listeners.unregisterListeners(plugin); + services.shutdown(plugin); + + I18nUtil.clearCache(); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java new file mode 100644 index 000000000..13225d5b2 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java @@ -0,0 +1,67 @@ +package us.talabrek.ultimateskyblock.bootstrap; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.animation.AnimationHandler; +import dk.lockfuglsang.minecraft.command.DocumentCommand; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.SkyUpdateChecker; +import us.talabrek.ultimateskyblock.api.plugin.UpdateChecker; +import us.talabrek.ultimateskyblock.island.level.ChunkSnapshotLevelLogic; +import us.talabrek.ultimateskyblock.island.level.LevelLogic; +import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.uuid.BukkitPlayerDB; +import us.talabrek.ultimateskyblock.uuid.FilePlayerDB; +import us.talabrek.ultimateskyblock.uuid.MemoryPlayerDB; +import us.talabrek.ultimateskyblock.uuid.PlayerDB; + +import java.nio.file.Path; +import java.util.logging.Logger; + +public class SkyblockModule extends AbstractModule { + + private final uSkyBlock plugin; + + public SkyblockModule(uSkyBlock plugin) { + this.plugin = plugin; + } + + @Override + protected void configure() { + // TODO: this should not be injected, but it is here fore legacy reasons. Move all functionality out of the plugin class and into the appropriate classes. + bind(uSkyBlock.class).toInstance(plugin); + bind(Plugin.class).toInstance(plugin); + bind(Path.class).annotatedWith(PluginDataDir.class).toInstance(plugin.getDataFolder().toPath()); + bind(LevelLogic.class).to(ChunkSnapshotLevelLogic.class); + bind(UpdateChecker.class).to(SkyUpdateChecker.class); + } + + @Provides + @Singleton + public static + @NotNull PlayerDB providePlayerDB(PluginConfig config, uSkyBlock plugin, Scheduler scheduler, Logger logger) { + String playerDbStorage = config.getYamlConfig().getString("options.advanced.playerdb.storage", "yml"); + if (playerDbStorage.equalsIgnoreCase("yml")) { + return new FilePlayerDB(plugin, scheduler, logger); + } else if (playerDbStorage.equalsIgnoreCase("memory")) { + return new MemoryPlayerDB(config); + } else { + return new BukkitPlayerDB(); + } + } + + @Provides + @Singleton + public static @NotNull AnimationHandler provideAnimationHandler(Plugin plugin) { + return new AnimationHandler(plugin); + } + + @Provides + public static @NotNull DocumentCommand provideDocumentCommand(uSkyBlock plugin) { + return new DocumentCommand(plugin, "doc", "usb.admin.doc"); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 589514de5..d60edc28f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -1,5 +1,8 @@ package us.talabrek.ultimateskyblock.challenge; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.file.FileUtil; import dk.lockfuglsang.minecraft.util.BlockRequirement; import dk.lockfuglsang.minecraft.util.FormatUtil; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -18,15 +21,31 @@ import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.MemberJoinedEvent; import us.talabrek.ultimateskyblock.block.BlockCollection; +import us.talabrek.ultimateskyblock.hook.HookManager; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.Perk; +import us.talabrek.ultimateskyblock.player.PerkLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -35,6 +54,7 @@ /** * The home of challenge business logic. */ +@Singleton public class ChallengeLogic implements Listener { public static final long MS_MIN = 60 * 1000; public static final long MS_HOUR = 60 * MS_MIN; @@ -43,8 +63,12 @@ public class ChallengeLogic implements Listener { public static final int ROWS_OF_RANKS = 5; public static final int CHALLENGE_PAGESIZE = ROWS_OF_RANKS * COLS_PER_ROW; + private final Logger logger; private final FileConfiguration config; private final uSkyBlock plugin; + private final PerkLogic perkLogic; + private final HookManager hookManager; + private final Map ranks; public final ChallengeDefaults defaults; @@ -52,8 +76,17 @@ public class ChallengeLogic implements Listener { private final ItemStack lockedItem; private final Map lockedItemMap = new EnumMap<>(Challenge.Type.class); - public ChallengeLogic(FileConfiguration config, uSkyBlock plugin) { - this.config = config; + @Inject + public ChallengeLogic( + @NotNull Logger logger, + @NotNull uSkyBlock plugin, + @NotNull PerkLogic perkLogic, + @NotNull HookManager hookManager + ) { + this.logger = logger; + this.perkLogic = perkLogic; + this.hookManager = hookManager; + this.config = FileUtil.getYmlConfiguration("challenges.yml"); this.plugin = plugin; this.defaults = ChallengeFactory.createDefaults(config.getRoot()); ranks = ChallengeFactory.createRankMap(config.getConfigurationSection("ranks"), defaults); @@ -348,12 +381,12 @@ private boolean giveReward(Player player, Challenge challenge) { player.sendMessage(tr("\u00a7eExp reward: \u00a7f{0,number,#.#}", reward.getXpReward())); if (defaults.enableEconomyPlugin) { float rewBonus = 1; - Perk perk = plugin.getPerkLogic().getPerk(player); + Perk perk = perkLogic.getPerk(player); rewBonus += perk.getRewBonus(); float currencyReward = reward.getCurrencyReward() * rewBonus; double percentage = (rewBonus - 1.0) * 100.0; - plugin.getHookManager().getEconomyHook().ifPresent((hook) -> { + hookManager.getEconomyHook().ifPresent((hook) -> { hook.depositPlayer(player, currencyReward); player.sendMessage(tr("\u00a7eCurrency reward: \u00a7f{0,number,###.##} {1} \u00a7a ({2,number,##.##})%", @@ -549,7 +582,7 @@ public int populateChallengeRank(Inventory menu, final Rank rank, int location, } menu.setItem(location, currentChallengeItem); } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Invalid challenge " + challenge, e); + logger.log(Level.SEVERE, "Invalid challenge " + challenge, e); } } return location; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatEvents.java index ea5d129fd..a659cbde1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatEvents.java @@ -1,10 +1,13 @@ package us.talabrek.ultimateskyblock.chat; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.Server; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.IslandChatEvent; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -12,11 +15,13 @@ * @see us.talabrek.ultimateskyblock.api.event.IslandChatEvent * @see IslandChatCommand */ +@Singleton public class ChatEvents implements Listener { private final ChatLogic logic; private final uSkyBlock plugin; - public ChatEvents(ChatLogic logic, uSkyBlock plugin) { + @Inject + public ChatEvents(@NotNull ChatLogic logic, @NotNull uSkyBlock plugin) { this.logic = logic; this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java index 1d7f2b39b..10f48b0b5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java @@ -1,14 +1,18 @@ package us.talabrek.ultimateskyblock.chat; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.FormatUtil; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.FormatUtil; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.Arrays; import java.util.Collections; @@ -19,11 +23,12 @@ import java.util.UUID; import java.util.regex.Matcher; -import static us.talabrek.ultimateskyblock.api.event.IslandChatEvent.*; +import static us.talabrek.ultimateskyblock.api.event.IslandChatEvent.Type; /** * The primary logic of uSkyBlocks chat-handling */ +@Singleton public class ChatLogic { private static final List ALONE_MESSAGES = Arrays.asList( I18nUtil.tr("But you are ALLLLLLL ALOOOOONE!"), @@ -32,20 +37,24 @@ public class ChatLogic { I18nUtil.tr("But you are Talking to your self!") ); private final uSkyBlock plugin; + private final WorldManager worldManager; private final Map formats = new EnumMap<>(Type.class); private final Map toggled = new HashMap<>(); - public ChatLogic(uSkyBlock plugin) { + @Inject + public ChatLogic(@NotNull uSkyBlock plugin, @NotNull PluginConfig config, @NotNull WorldManager worldManager) { this.plugin = plugin; + this.worldManager = worldManager; formats.put(Type.PARTY, - plugin.getConfig().getString("options.party.chat-format", "&9PARTY &r{DISPLAYNAME} &f>&d {MESSAGE}")); + config.getYamlConfig().getString("options.party.chat-format", "&9PARTY &r{DISPLAYNAME} &f>&d {MESSAGE}")); formats.put(Type.ISLAND, - plugin.getConfig().getString("options.island.chat-format", "&9SKY &r{DISPLAYNAME} &f>&b {MESSAGE}")); + config.getYamlConfig().getString("options.island.chat-format", "&9SKY &r{DISPLAYNAME} &f>&b {MESSAGE}")); } /** * Gets a {@link List} containing {@link Player}'s with all the recipients that should receive the given message * {@link Type} from the sending {@link Player}. Returns an empty list when there are no recipients. + * * @param sender Player sending the message. * @param chatType Message type that the player is sending. * @return List of all recipients, or an empty list if there are none. @@ -55,8 +64,8 @@ public ChatLogic(uSkyBlock plugin) { IslandInfo islandInfo = plugin.getIslandInfo(sender); return islandInfo != null ? islandInfo.getOnlineMembers() : Collections.singletonList(sender); } else if (chatType == Type.ISLAND) { - if (plugin.getWorldManager().isSkyWorld(sender.getWorld())) { - return WorldGuardHandler.getPlayersInRegion(plugin.getWorldManager().getWorld(), + if (worldManager.isSkyWorld(sender.getWorld())) { + return WorldGuardHandler.getPlayersInRegion(worldManager.getWorld(), WorldGuardHandler.getIslandRegionAt(sender.getLocation())); } return Collections.emptyList(); @@ -67,6 +76,7 @@ public ChatLogic(uSkyBlock plugin) { /** * Sends the given message to all online partymembers or island visitors on the given {@link Player}'s island, * depending on the given {@link Type}. + * * @param sender Player sending the message. * @param type Message type to send. * @param message Message to send. @@ -90,6 +100,7 @@ public void sendMessage(Player sender, Type type, String message) { /** * Gets the message format for the given {@link Type}. + * * @param type Island chat type to lookup. * @return Message format. */ @@ -99,6 +110,7 @@ public void sendMessage(Player sender, Type type, String message) { /** * Toggle the {@link Type} on or off for the given {@link Player}, returns true if it is toggled on. + * * @param player Player to toggle the chat type for. * @param type Chat type to toggle. * @return True if it is toggled on, false otherwise. @@ -116,6 +128,7 @@ public synchronized boolean toggle(Player player, Type type) { /** * Gets the current {@link Type} toggle for the given {@link Player}, or null if none exists. + * * @param player Player to lookup. * @return The current Type toggle, or null if none exists. */ diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandTalkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandTalkCommand.java index a9b75f1b0..b64f7b42c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandTalkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/IslandTalkCommand.java @@ -1,5 +1,8 @@ package us.talabrek.ultimateskyblock.chat; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -7,9 +10,11 @@ /** * Island Talk */ +@Singleton public class IslandTalkCommand extends IslandChatCommand { - public IslandTalkCommand(uSkyBlock plugin, ChatLogic chatLogic) { + @Inject + public IslandTalkCommand(@NotNull uSkyBlock plugin, @NotNull ChatLogic chatLogic) { super(plugin, chatLogic, "islandtalk|istalk|it", "usb.island.talk", tr("talk to players on your island")); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/PartyTalkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/PartyTalkCommand.java index dd0e3e753..a0db3c52e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/PartyTalkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/PartyTalkCommand.java @@ -1,14 +1,19 @@ package us.talabrek.ultimateskyblock.chat; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; /** * Talk to your party */ +@Singleton public class PartyTalkCommand extends IslandChatCommand { - public PartyTalkCommand(uSkyBlock plugin, ChatLogic chatLogic) { + @Inject + public PartyTalkCommand(@NotNull uSkyBlock plugin, @NotNull ChatLogic chatLogic) { super(plugin, chatLogic, "partytalk|ptalk|ptk", "usb.party.talk", I18nUtil.tr("talk to your island party")); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index 1702faa04..b9f1b4084 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -1,12 +1,11 @@ package us.talabrek.ultimateskyblock.command; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.animation.AnimationHandler; import dk.lockfuglsang.minecraft.command.BaseCommandExecutor; import dk.lockfuglsang.minecraft.command.DocumentCommand; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import us.talabrek.ultimateskyblock.biome.BiomeConfig; -import us.talabrek.ultimateskyblock.command.admin.AbstractPlayerInfoCommand; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.admin.AdminChallengeCommand; import us.talabrek.ultimateskyblock.command.admin.AdminIslandCommand; import us.talabrek.ultimateskyblock.command.admin.ChunkCommand; @@ -18,11 +17,12 @@ import us.talabrek.ultimateskyblock.command.admin.GenTopTenCommand; import us.talabrek.ultimateskyblock.command.admin.GotoIslandCommand; import us.talabrek.ultimateskyblock.command.admin.ImportCommand; +import us.talabrek.ultimateskyblock.command.admin.ItemInfoCommand; import us.talabrek.ultimateskyblock.command.admin.JobsCommand; import us.talabrek.ultimateskyblock.command.admin.LanguageCommand; -import us.talabrek.ultimateskyblock.command.admin.ItemInfoCommand; import us.talabrek.ultimateskyblock.command.admin.OrphanCommand; import us.talabrek.ultimateskyblock.command.admin.PerkCommand; +import us.talabrek.ultimateskyblock.command.admin.PlayerInfoCommand; import us.talabrek.ultimateskyblock.command.admin.ProtectAllCommand; import us.talabrek.ultimateskyblock.command.admin.PurgeCommand; import us.talabrek.ultimateskyblock.command.admin.RegionCommand; @@ -36,7 +36,6 @@ import us.talabrek.ultimateskyblock.command.completion.OnlinePlayerTabCompleter; import us.talabrek.ultimateskyblock.command.completion.RankTabCompleter; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; -import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -44,51 +43,82 @@ /** * The new admin command, alias /usb */ +@Singleton public class AdminCommand extends BaseCommandExecutor { - public AdminCommand(final uSkyBlock plugin, ConfirmHandler confirmHandler, AnimationHandler animationHandler, - BiomeConfig biomeConfig) { + + @Inject + public AdminCommand( + @NotNull uSkyBlock plugin, + @NotNull ConfirmHandler confirmHandler, + @NotNull AnimationHandler animationHandler, + + @NotNull OnlinePlayerTabCompleter playerCompleter, + @NotNull ChallengeTabCompleter challengeCompleter, + @NotNull AllPlayerTabCompleter allPlayerCompleter, + @NotNull BiomeTabCompleter biomeCompleter, + @NotNull RankTabCompleter rankTabCompleter, + + @NotNull ReloadCommand reloadCommand, + @NotNull ImportCommand importCommand, + @NotNull GenTopTenCommand genTopTenCommand, + @NotNull AdminChallengeCommand adminChallengeCommand, + @NotNull OrphanCommand orphanCommand, + @NotNull AdminIslandCommand adminIslandCommand, + @NotNull PurgeCommand purgeCommand, + @NotNull GotoIslandCommand gotoIslandCommand, + @NotNull PlayerInfoCommand playerInfoCommand, + @NotNull FlatlandFixCommand flatlandFixCommand, + @NotNull DebugCommand debugCommand, + @NotNull WGCommand wgCommand, + @NotNull VersionCommand versionCommand, + @NotNull CooldownCommand cooldownCommand, + @NotNull PerkCommand perkCommand, + @NotNull LanguageCommand languageCommand, + @NotNull FlushCommand flushCommand, + @NotNull JobsCommand jobsCommand, + @NotNull ConfigCommand configCommand, + @NotNull DocumentCommand documentCommand, + @NotNull RegionCommand regionCommand, + @NotNull SetMaintenanceCommand setMaintenanceCommand, + @NotNull ItemInfoCommand itemInfoCommand, + @NotNull ProtectAllCommand protectAllCommand, + @NotNull ChunkCommand chunkCommand + + ) { super("usb", null, marktr("Ultimate SkyBlock Admin")); - OnlinePlayerTabCompleter playerCompleter = new OnlinePlayerTabCompleter(); - TabCompleter challengeCompleter = new ChallengeTabCompleter(); - TabCompleter allPlayerCompleter = new AllPlayerTabCompleter(playerCompleter); - TabCompleter biomeCompleter = new BiomeTabCompleter(biomeConfig); + addTab("oplayer", playerCompleter); addTab("player", allPlayerCompleter); addTab("island", allPlayerCompleter); addTab("leader", allPlayerCompleter); addTab("challenge", challengeCompleter); addTab("biome", biomeCompleter); - addTab("rank", new RankTabCompleter(plugin)); - add(new ReloadCommand()); - add(new ImportCommand()); - add(new GenTopTenCommand(plugin)); - //add(new RegisterIslandToPlayerCommand()); - add(new AdminChallengeCommand(plugin)); - add(new OrphanCommand(plugin)); - add(new AdminIslandCommand(plugin, confirmHandler)); - add(new PurgeCommand(plugin)); - add(new GotoIslandCommand(plugin)); - add(new AbstractPlayerInfoCommand("info", "usb.admin.info", marktr("show player-information")) { - @Override - protected void doExecute(CommandSender sender, PlayerInfo playerInfo) { - sender.sendMessage(playerInfo.toString()); - } - }); - add(new FlatlandFixCommand(plugin)); - add(new DebugCommand(plugin)); - add(new WGCommand(plugin)); - add(new VersionCommand(plugin)); - add(new CooldownCommand(plugin)); - add(new PerkCommand(plugin)); - add(new LanguageCommand(plugin)); - add(new FlushCommand(plugin)); - add(new JobsCommand(plugin)); - add(new ConfigCommand(plugin)); - add(new DocumentCommand(plugin, "doc", "usb.admin.doc")); - add(new RegionCommand(plugin, animationHandler)); - add(new SetMaintenanceCommand(plugin)); - add(new ItemInfoCommand()); - add(new ProtectAllCommand(plugin)); - add(new ChunkCommand(plugin)); + addTab("rank", rankTabCompleter); + + add(reloadCommand); + add(importCommand); + add(genTopTenCommand); + add(adminChallengeCommand); + add(orphanCommand); + add(adminIslandCommand); + add(purgeCommand); + add(gotoIslandCommand); + add(playerInfoCommand); + add(flatlandFixCommand); + add(debugCommand); + add(wgCommand); + add(versionCommand); + add(cooldownCommand); + add(perkCommand); + add(languageCommand); + add(flushCommand); + add(jobsCommand); + add(configCommand); + add(documentCommand); + add(regionCommand); + add(setMaintenanceCommand); + add(itemInfoCommand); + add(protectAllCommand); + add(chunkCommand); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/ChallengeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/ChallengeCommand.java index 4d4c3f715..f4bff12b3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/ChallengeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/ChallengeCommand.java @@ -1,14 +1,21 @@ package us.talabrek.ultimateskyblock.command; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.command.BaseCommandExecutor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.command.challenge.ChallengeCompleteCommand; import us.talabrek.ultimateskyblock.command.challenge.ChallengeInfoCommand; import us.talabrek.ultimateskyblock.command.completion.AvailableChallengeTabCompleter; +import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.player.PlayerLogic; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.world.WorldManager; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -16,15 +23,34 @@ /** * Primary challenges command */ +@Singleton public class ChallengeCommand extends BaseCommandExecutor { private final uSkyBlock plugin; + private final ChallengeLogic challengeLogic; + private final WorldManager worldManager; + private final PlayerLogic playerLogic; + private final SkyBlockMenu mainMenu; - public ChallengeCommand(uSkyBlock plugin) { + @Inject + public ChallengeCommand( + @NotNull uSkyBlock plugin, + @NotNull ChallengeCompleteCommand challengeCompleteCommand, + @NotNull AvailableChallengeTabCompleter availableChallengeTabCompleter, + @NotNull ChallengeInfoCommand challengeInfoCommand, + @NotNull ChallengeLogic challengeLogic, + @NotNull WorldManager worldManager, + @NotNull PlayerLogic playerLogic, + @NotNull SkyBlockMenu mainMenu + ) { super("challenges|c", "usb.island.challenges", marktr("complete and list challenges")); this.plugin = plugin; - addTab("challenge", new AvailableChallengeTabCompleter()); - add(new ChallengeCompleteCommand(plugin)); - add(new ChallengeInfoCommand(plugin)); + this.challengeLogic = challengeLogic; + this.worldManager = worldManager; + this.playerLogic = playerLogic; + this.mainMenu = mainMenu; + addTab("challenge", availableChallengeTabCompleter); + add(challengeCompleteCommand); + add(challengeInfoCommand); } @Override @@ -32,26 +58,25 @@ public boolean onCommand(CommandSender sender, Command command, String alias, St if (!plugin.isRequirementsMet(sender, this, args)) { return true; } - if (!(sender instanceof Player)) { + if (!(sender instanceof Player player)) { sender.sendMessage(tr("\u00a7cCommand only available for players.")); return false; } - if (!plugin.getChallengeLogic().isEnabled()) { + if (!challengeLogic.isEnabled()) { sender.sendMessage(tr("\u00a7eChallenges has been disabled. Contact an administrator.")); return false; } - Player player = (Player) sender; - if (!plugin.getWorldManager().isSkyAssociatedWorld(player.getWorld())) { + if (!worldManager.isSkyAssociatedWorld(player.getWorld())) { player.sendMessage(tr("\u00a74You can only submit challenges in the skyblock world!")); return true; } - PlayerInfo playerInfo = plugin.getPlayerInfo(player); + PlayerInfo playerInfo = playerLogic.getPlayerInfo(player); if (!playerInfo.getHasIsland()) { player.sendMessage(tr("\u00a74You can only submit challenges when you have an island!")); return true; } if (args.length == 0) { - player.openInventory(plugin.getMenu().displayChallengeGUI(player, 1, null)); + player.openInventory(mainMenu.displayChallengeGUI(player, 1, null)); return true; } else { return super.onCommand(sender, command, alias, args); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java index 568616fad..b076772c8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java @@ -1,6 +1,9 @@ package us.talabrek.ultimateskyblock.command; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -8,6 +11,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.AcceptEvent; import us.talabrek.ultimateskyblock.api.event.InviteEvent; import us.talabrek.ultimateskyblock.api.event.RejectEvent; @@ -15,7 +19,6 @@ import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; import java.util.Collection; import java.util.HashMap; @@ -29,13 +32,14 @@ /** * Responsible for holding out-standing invites, and carrying out a transfer of invitation. */ -@SuppressWarnings("deprecation") +@Singleton public class InviteHandler implements Listener { private final Map inviteMap = new HashMap<>(); private final Map> waitingInvites = new HashMap<>(); private final uSkyBlock plugin; - public InviteHandler(uSkyBlock plugin) { + @Inject + public InviteHandler(@NotNull uSkyBlock plugin) { this.plugin = plugin; } @@ -65,17 +69,12 @@ private synchronized void invite(Player player, final IslandInfo island, Player waitingInvites.put(island.getName(), invites); player.sendMessage(tr("\u00a7aInvite sent to {0}", otherPlayer.getDisplayName())); otherPlayer.sendMessage(new String[]{ - tr("{0}\u00a7e has invited you to join their island!", player.getDisplayName()), - tr("\u00a7f/island [accept/reject]\u00a7e to accept or reject the invite."), - tr("\u00a74WARNING: You will lose your current island if you accept!") + tr("{0}\u00a7e has invited you to join their island!", player.getDisplayName()), + tr("\u00a7f/island [accept/reject]\u00a7e to accept or reject the invite."), + tr("\u00a74WARNING: You will lose your current island if you accept!") }); long timeout = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.party.invite-timeout", 30)); - BukkitTask timeoutTask = plugin.async(new Runnable() { - @Override - public void run() { - uninvite(island, uniqueId); - } - }, timeout); + BukkitTask timeoutTask = plugin.async(() -> uninvite(island, uniqueId), timeout); invite.setTimeoutTask(timeoutTask); island.sendMessageToIslandGroup(true, I18nUtil.marktr("{0}\u00a7d invited {1}"), player.getDisplayName(), otherPlayer.getDisplayName()); } @@ -121,14 +120,11 @@ private synchronized boolean accept(final Player player) { if (uuids != null) { uuids.remove(uuid); } - Runnable joinIsland = new Runnable() { - @Override - public void run() { - player.sendMessage(tr("\u00a7aYou have joined an island! Use /island party to see the other members.")); - addPlayerToParty(player, island); - plugin.getTeleportLogic().homeTeleport(player, true); - plugin.clearPlayerInventory(player); - } + Runnable joinIsland = () -> { + player.sendMessage(tr("\u00a7aYou have joined an island! Use /island party to see the other members.")); + addPlayerToParty(player, island); + plugin.getTeleportLogic().homeTeleport(player, true); + plugin.clearPlayerInventory(player); }; if (deleteOldIsland) { plugin.deletePlayerIsland(player.getName(), joinIsland); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java index a2030bf55..62ae8c7a1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java @@ -1,12 +1,13 @@ package us.talabrek.ultimateskyblock.command; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.command.BaseCommandExecutor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.biome.BiomeConfig; -import us.talabrek.ultimateskyblock.biome.Biomes; import us.talabrek.ultimateskyblock.command.completion.AllPlayerTabCompleter; import us.talabrek.ultimateskyblock.command.completion.BiomeTabCompleter; import us.talabrek.ultimateskyblock.command.completion.MemberTabCompleter; @@ -47,60 +48,94 @@ /** * The main /island command */ +@Singleton public class IslandCommand extends BaseCommandExecutor { private final uSkyBlock plugin; private final SkyBlockMenu menu; - public IslandCommand(uSkyBlock plugin, SkyBlockMenu menu, Biomes biomes, BiomeConfig biomeConfig) { + @Inject + public IslandCommand( + @NotNull uSkyBlock plugin, + @NotNull SkyBlockMenu menu, + + @NotNull OnlinePlayerTabCompleter onlinePlayerTabCompleter, + @NotNull AllPlayerTabCompleter allPlayerTabCompleter, + @NotNull BiomeTabCompleter biomeTabCompleter, + @NotNull MemberTabCompleter memberTabCompleter, + @NotNull SchematicTabCompleter schematicTabCompleter, + @NotNull PermissionTabCompleter permissionTabCompleter, + + @NotNull HomeCommand homeCommand, + @NotNull LevelCommand levelCommand, + @NotNull InfoCommand infoCommand, + @NotNull InviteCommand inviteCommand, + @NotNull AcceptRejectCommand acceptRejectCommand, + @NotNull LeaveCommand leaveCommand, + @NotNull KickCommand kickCommand, + @NotNull PartyCommand partyCommand, + @NotNull MakeLeaderCommand makeLeaderCommand, + @NotNull SpawnCommand spawnCommand, + @NotNull TrustCommand trustCommand, + @NotNull MobLimitCommand mobLimitCommand, + @NotNull AutoCommand autoCommand, + @NotNull PermCommand permCommand, + @NotNull RestartCommand restartCommand, + @NotNull LogCommand logCommand, + @NotNull CreateCommand createCommand, + @NotNull SetHomeCommand setHomeCommand, + @NotNull SetWarpCommand setWarpCommand, + @NotNull WarpCommand warpCommand, + @NotNull ToggleWarp toggleWarpCommand, + @NotNull BanCommand banCommand, + @NotNull LockUnlockCommand lockUnlockCommand, + @NotNull TopCommand topCommand, + @NotNull BiomeCommand biomeCommand + ) { super("island|is", "usb.island.create", marktr("general island command")); this.plugin = plugin; this.menu = menu; + addFeaturePermission("usb.mod.bypasscooldowns", tr("allows user to bypass cooldowns")); addFeaturePermission("usb.mod.bypassprotection", tr("allows user to bypass visitor-protections")); addFeaturePermission("usb.mod.bypassteleport", tr("allows user to bypass teleport-delay")); addFeaturePermission("usb.island.signs.use", tr("allows user to use [usb] signs")); addFeaturePermission("usb.island.signs.place", tr("allows user to place [usb] signs")); - InviteHandler inviteHandler = new InviteHandler(plugin); - plugin.getServer().getPluginManager().registerEvents(inviteHandler, plugin); - OnlinePlayerTabCompleter onlinePlayerTabCompleter = new OnlinePlayerTabCompleter(); - AllPlayerTabCompleter playerTabCompleter = new AllPlayerTabCompleter(onlinePlayerTabCompleter); - addTab("island", playerTabCompleter); - addTab("player", playerTabCompleter); + addTab("island", allPlayerTabCompleter); + addTab("player", allPlayerTabCompleter); addTab("oplayer", onlinePlayerTabCompleter); - addTab("biome", new BiomeTabCompleter(biomeConfig)); - addTab("member", new MemberTabCompleter(plugin)); - addTab("schematic", new SchematicTabCompleter(plugin)); - addTab("perm", new PermissionTabCompleter(plugin)); - add(new RestartCommand(plugin)); - add(new LogCommand(plugin, menu)); - CreateCommand createCommand = new CreateCommand(plugin); + addTab("biome", biomeTabCompleter); + addTab("member", memberTabCompleter); + addTab("schematic", schematicTabCompleter); + addTab("perm", permissionTabCompleter); + + add(restartCommand); + add(logCommand); add(createCommand); - add(new SetHomeCommand(plugin)); - HomeCommand homeCommand = new HomeCommand(plugin); + add(setHomeCommand); add(homeCommand); - add(new SetWarpCommand(plugin)); - add(new WarpCommand(plugin)); - add(new ToggleWarp(plugin)); - add(new BanCommand(plugin)); - add(new LockUnlockCommand(plugin)); + add(setWarpCommand); + add(warpCommand); + add(toggleWarpCommand); + add(banCommand); + add(lockUnlockCommand); if (Settings.island_useTopTen) { - add(new TopCommand(plugin)); + add(topCommand); } - add(new BiomeCommand(plugin, biomes, biomeConfig)); - add(new LevelCommand(plugin)); - add(new InfoCommand(plugin)); - add(new InviteCommand(plugin, inviteHandler)); - add(new AcceptRejectCommand(plugin)); - add(new LeaveCommand(plugin)); - add(new KickCommand(plugin)); - add(new PartyCommand(plugin, menu, inviteHandler)); - add(new MakeLeaderCommand(plugin)); - add(new SpawnCommand(plugin)); - add(new TrustCommand(plugin)); - add(new MobLimitCommand(plugin)); - add(new AutoCommand(plugin, createCommand, homeCommand)); - add(new PermCommand(plugin)); + add(biomeCommand); + add(levelCommand); + add(infoCommand); + add(inviteCommand); + add(acceptRejectCommand); + add(leaveCommand); + add(kickCommand); + add(partyCommand); + add(makeLeaderCommand); + add(spawnCommand); + add(trustCommand); + add(mobLimitCommand); + add(autoCommand); + add(permCommand); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java index 6b7eab6aa..7919d7155 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java @@ -1,11 +1,13 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import dk.lockfuglsang.minecraft.util.FormatUtil; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -24,7 +26,8 @@ public class AdminChallengeCommand extends CompositeCommand { private final uSkyBlock plugin; - public AdminChallengeCommand(final uSkyBlock plugin) { + @Inject + public AdminChallengeCommand(@NotNull uSkyBlock plugin) { super("challenge|ch", "usb.mod.challenges", "player", marktr("Manage challenges for a player")); this.plugin = plugin; add(new ChallengeCommand("complete", null, "completes the challenge for the player") { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java index d9b4b6dcc..a5870dc4d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminIslandCommand.java @@ -1,11 +1,13 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import org.bukkit.Bukkit; import org.bukkit.block.Biome; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; @@ -23,7 +25,8 @@ public class AdminIslandCommand extends CompositeCommand { private final uSkyBlock plugin; - public AdminIslandCommand(final uSkyBlock plugin, final ConfirmHandler confirmHandler) { + @Inject + public AdminIslandCommand(@NotNull uSkyBlock plugin, @NotNull ConfirmHandler confirmHandler) { super("island|is", "usb.admin.island", marktr("manage islands")); this.plugin = plugin; add(new AbstractIslandInfoCommand("protect", "usb.admin.protect", marktr("protects the island")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java index d44ec6ec4..6109409b0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java @@ -1,11 +1,13 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import org.bukkit.Chunk; import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -14,11 +16,10 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class ChunkCommand extends CompositeCommand { - private final uSkyBlock plugin; - public ChunkCommand(uSkyBlock plugin) { + @Inject + public ChunkCommand(@NotNull uSkyBlock plugin) { super("chunk", "usb.admin.chunk", marktr("various chunk commands")); - this.plugin = plugin; add(new RequireChunkCommand("regen", marktr("regenerate current chunk")) { @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java index 293a544cf..b60dc20c6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; @@ -8,6 +9,7 @@ import org.bukkit.command.TabCompleter; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Arrays; @@ -25,7 +27,8 @@ public class ConfigCommand extends CompositeCommand { private final uSkyBlock plugin; public static final List CONFIGS = Arrays.asList("config", "levelConfig", "challenges", "signs"); - public ConfigCommand(uSkyBlock plugin) { + @Inject + public ConfigCommand(@NotNull uSkyBlock plugin) { super("config|c", "usb.admin.config", "?config", marktr("open GUI for config")); add(new AbstractCommand("search", marktr("searches config for a specific key")) { @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java index 3f92c8bf7..0f934ad96 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java @@ -1,11 +1,13 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.TimeUtil; @@ -21,7 +23,9 @@ * Manages player cooldowns */ public class CooldownCommand extends CompositeCommand { - public CooldownCommand(final uSkyBlock plugin) { + + @Inject + public CooldownCommand(@NotNull uSkyBlock plugin) { super("cooldown|cd", "usb.admin.cooldown", marktr("Controls player-cooldowns")); add(new AbstractCommand("clear|c", null, "player command", marktr("clears the cooldown on a command (* = all)")) { @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/DebugCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/DebugCommand.java index 80ec135dd..5bd0dae67 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/DebugCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/DebugCommand.java @@ -1,11 +1,14 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.FormatUtil; +import us.talabrek.ultimateskyblock.util.PluginInfo; import java.io.File; import java.io.IOException; @@ -26,11 +29,17 @@ * Debug control. */ public class DebugCommand extends CompositeCommand { + + private final PluginInfo pluginInfo; + public static final Logger log = Logger.getLogger("us.talabrek.ultimateskyblock"); private static Handler logHandler = null; - public DebugCommand(final uSkyBlock plugin) { + @Inject + public DebugCommand(@NotNull uSkyBlock plugin, @NotNull PluginInfo pluginInfo) { super("debug", "usb.admin.debug", marktr("control debugging")); + this.pluginInfo = pluginInfo; + add(new AbstractCommand("setlevel", null, "level", marktr("set debug-level")) { @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { @@ -72,7 +81,7 @@ public boolean execute(CommandSender sender, String alias, Map d } } - public static void setLogLevel(CommandSender sender, String arg) { + public void setLogLevel(CommandSender sender, String arg) { try { Level level = Level.parse(arg.toUpperCase()); log.setLevel(level); @@ -96,7 +105,7 @@ public static void disableLogging(CommandSender sender) { logHandler = null; } - public static void enableLogging(CommandSender sender, uSkyBlock plugin) { + public void enableLogging(CommandSender sender, uSkyBlock plugin) { if (logHandler != null) { log.removeHandler(logHandler); plugin.getLogger().removeHandler(logHandler); @@ -104,13 +113,13 @@ public static void enableLogging(CommandSender sender, uSkyBlock plugin) { File logFolder = new File(plugin.getDataFolder(), "logs"); logFolder.mkdirs(); try { - String logFile = logFolder.toString() + File.separator + "uskyblock.%u.log"; + String logFile = logFolder + File.separator + "uskyblock.%u.log"; logHandler = new FileHandler(logFile, true); logHandler.setFormatter(new SingleLineFormatter()); log.addHandler(logHandler); plugin.getLogger().addHandler(logHandler); Level level = log.getLevel() != null ? log.getLevel() : Level.FINER; - log.log(level, FormatUtil.stripFormatting(plugin.getVersionInfo(true))); + log.log(level, FormatUtil.stripFormatting(pluginInfo.getVersionInfo(true))); sender.sendMessage("\u00a7eLogging to " + logFile); } catch (IOException e) { log.log(Level.WARNING, "Unable to enable logging", e); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java index 17724fd14..6436917d1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java @@ -1,10 +1,12 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -21,7 +23,8 @@ public class FlatlandFixCommand extends AbstractCommand { private final uSkyBlock plugin; - public FlatlandFixCommand(uSkyBlock plugin) { + @Inject + public FlatlandFixCommand(@NotNull uSkyBlock plugin) { super("fix-flatland", "usb.admin.remove", "?player", marktr("tries to fix the the area of flatland.")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlushCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlushCommand.java index a22b801b3..74e2a35af 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlushCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlushCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -12,7 +14,8 @@ public class FlushCommand extends AbstractCommand { private final uSkyBlock plugin; - public FlushCommand(uSkyBlock plugin) { + @Inject + public FlushCommand(@NotNull uSkyBlock plugin) { super("flush", "usb.admin.cache", marktr("flushes all caches to files")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GenTopTenCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GenTopTenCommand.java index 41cd60da9..c4a6d3808 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GenTopTenCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GenTopTenCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -15,7 +17,8 @@ public class GenTopTenCommand extends AbstractCommand { private final uSkyBlock plugin; - public GenTopTenCommand(uSkyBlock plugin) { + @Inject + public GenTopTenCommand(@NotNull uSkyBlock plugin) { super("topten", "usb.mod.topten", marktr("manually update the top 10 list")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java index 3e6422cae..003d7428c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/GotoIslandCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -15,7 +17,8 @@ public class GotoIslandCommand extends AbstractPlayerInfoCommand { private final uSkyBlock plugin; - public GotoIslandCommand(uSkyBlock plugin) { + @Inject + public GotoIslandCommand(@NotNull uSkyBlock plugin) { super("goto", "usb.mod.goto", marktr("teleport to another players island")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ImportCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ImportCommand.java index d7aa61dc5..4e0bfe1e2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ImportCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ImportCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; @@ -17,6 +18,7 @@ public class ImportCommand extends AbstractCommand { private final ImportTabCompleter completer; + @Inject public ImportCommand() { super("import", "usb.admin.import", "format", marktr("imports players and islands from other formats")); completer = new ImportTabCompleter(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java index 71768a8d7..9063c990a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ItemInfoCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -16,6 +17,8 @@ * Command for querying items reg. NBT stuff */ public class ItemInfoCommand extends CompositeCommand { + + @Inject public ItemInfoCommand() { super("iteminfo", "usb.admin.iteminfo", marktr("advanced info about items")); add(new AbstractCommand("info|i", marktr("shows the component format for the currently held item")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java index f51b6fdf0..aae41ca8a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.async.JobManager; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.TimeUtil; @@ -21,7 +23,8 @@ public class JobsCommand extends CompositeCommand { private final uSkyBlock plugin; - public JobsCommand(uSkyBlock plugin) { + @Inject + public JobsCommand(@NotNull uSkyBlock plugin) { super("jobs|j", "usb.admin.jobs", marktr("controls async jobs")); this.plugin = plugin; /* diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java index 5c303e9b8..a4addd89b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -22,7 +24,8 @@ public class LanguageCommand extends AbstractCommand { private final uSkyBlock plugin; - public LanguageCommand(uSkyBlock plugin) { + @Inject + public LanguageCommand(@NotNull uSkyBlock plugin) { super("lang|l", "usb.admin.lang", "language", marktr("changes the language of the plugin, and reloads")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java index 4c89306bf..118c4b741 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java @@ -1,9 +1,11 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.OrphanLogic; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -16,7 +18,9 @@ * Handles Orphans. */ public class OrphanCommand extends CompositeCommand { - public OrphanCommand(final uSkyBlock plugin) { + + @Inject + public OrphanCommand(@NotNull uSkyBlock plugin) { super("orphan", "usb.admin.orphan", marktr("manage orphans")); add(new AbstractCommand("count", marktr("count orphans")) { @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java index bbfa7c271..db22a09d0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java @@ -1,9 +1,11 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.player.Perk; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -14,7 +16,9 @@ import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; public class PerkCommand extends CompositeCommand { - public PerkCommand(final uSkyBlock plugin) { + + @Inject + public PerkCommand(@NotNull uSkyBlock plugin) { super("perk", "usb.admin.perk", marktr("shows perk-information")); add(new AbstractCommand("list", "lists all perks") { @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PlayerInfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PlayerInfoCommand.java new file mode 100644 index 000000000..30ffe7562 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PlayerInfoCommand.java @@ -0,0 +1,20 @@ +package us.talabrek.ultimateskyblock.command.admin; + +import com.google.inject.Inject; +import org.bukkit.command.CommandSender; +import us.talabrek.ultimateskyblock.player.PlayerInfo; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; + +public class PlayerInfoCommand extends AbstractPlayerInfoCommand { + + @Inject + public PlayerInfoCommand() { + super("info", "usb.admin.info", marktr("show player-information")); + } + + @Override + protected void doExecute(CommandSender sender, PlayerInfo playerInfo) { + sender.sendMessage(playerInfo.toString()); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java index 78edcfd45..1526e23cb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java @@ -1,8 +1,11 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.admin.task.ProtectAllTask; +import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.ProgressTracker; @@ -16,11 +19,14 @@ */ public class ProtectAllCommand extends AbstractCommand { private final uSkyBlock plugin; + private final IslandLogic islandLogic; private ProtectAllTask task; - public ProtectAllCommand(uSkyBlock plugin) { + @Inject + public ProtectAllCommand(@NotNull uSkyBlock plugin, @NotNull IslandLogic islandLogic) { super("protectall", "usb.admin.protectall", marktr("protects all islands (time consuming)")); this.plugin = plugin; + this.islandLogic = islandLogic; } private boolean isProtectAllActive() { @@ -42,7 +48,7 @@ public boolean execute(CommandSender sender, String alias, Map d } sender.sendMessage(tr("\u00a7eStarting a protect-all task. It will take a while.")); ProgressTracker tracker = new ProgressTracker(sender, "\u00a77- Protect-All {0,number,##}% ({1}/{2}, failed:{3}, skipped:{4}) ~ {5}", 10, plugin.getConfig().getInt("async.long.feedbackEvery", 30000)); - task = new ProtectAllTask(plugin, sender, tracker); + task = new ProtectAllTask(plugin, sender, islandLogic.getIslandDirectory(), tracker); task.runTaskAsynchronously(plugin); return true; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java index 89edecec0..2dcfe66c4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java @@ -1,10 +1,13 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.admin.task.PurgeScanTask; import us.talabrek.ultimateskyblock.command.admin.task.PurgeTask; +import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.uSkyBlock; import dk.lockfuglsang.minecraft.util.TimeUtil; @@ -18,14 +21,17 @@ */ public class PurgeCommand extends AbstractCommand { private final uSkyBlock plugin; + private final IslandLogic islandLogic; private PurgeScanTask scanTask; private PurgeTask purgeTask; private String days = null; - public PurgeCommand(uSkyBlock plugin) { + @Inject + public PurgeCommand(@NotNull uSkyBlock plugin, @NotNull IslandLogic islandLogic) { super("purge", "usb.admin.purge", "time-in-days|stop|confirm ?level ?force", marktr("purges all abandoned islands")); this.plugin = plugin; + this.islandLogic = islandLogic; } @Override @@ -52,7 +58,7 @@ public boolean execute(final CommandSender sender, String alias, Map { + scanTask = new PurgeScanTask(plugin, islandLogic.getIslandDirectory().toFile(), time, purgeLevel, sender, () -> { if (force) { doPurge(sender); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java index 2108fb3be..924497de9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegionCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -15,6 +16,7 @@ import org.bukkit.World; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -36,7 +38,8 @@ public class RegionCommand extends CompositeCommand { private int dash; private Material material; - public RegionCommand(uSkyBlock plugin, final AnimationHandler animationHandler) { + @Inject + public RegionCommand(@NotNull AnimationHandler animationHandler) { super("region|rg", "usb.admin.region", marktr("region manipulations")); this.animationHandler = animationHandler; add(new AbstractCommand("show", marktr("shows the borders of the current island")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegisterIslandToPlayerCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegisterIslandToPlayerCommand.java index 2c55a8716..54caf61b5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegisterIslandToPlayerCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/RegisterIslandToPlayerCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; @@ -14,19 +15,21 @@ * Registers an island to a player. */ public class RegisterIslandToPlayerCommand extends AbstractCommand { + + @Inject public RegisterIslandToPlayerCommand() { super("register", "usb.admin.register", "player", marktr("set a player''s island to your location")); } + @Override public boolean execute(final CommandSender sender, String alias, Map data, final String... args) { - if (!(sender instanceof Player)) { + if (!(sender instanceof Player player)) { return false; } if (args.length < 1) { return false; } String playerName = args[0]; - Player player = (Player) sender; if (uSkyBlock.getInstance().devSetPlayerIsland(player, player.getLocation(), playerName)) { sender.sendMessage(I18nUtil.tr("\u00a7aSet {0}''s island to the current island.", playerName)); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ReloadCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ReloadCommand.java index 72855524e..057368474 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ReloadCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ReloadCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; @@ -13,6 +14,8 @@ * Reloads the config-files for USB. */ public class ReloadCommand extends AbstractCommand { + + @Inject public ReloadCommand() { super("reload", "usb.admin.reload", marktr("reload configuration from file.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/SetMaintenanceCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/SetMaintenanceCommand.java index aec4da6ac..7f348d27d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/SetMaintenanceCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/SetMaintenanceCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -16,7 +18,8 @@ public class SetMaintenanceCommand extends AbstractCommand { private final uSkyBlock plugin; - public SetMaintenanceCommand(uSkyBlock plugin) { + @Inject + public SetMaintenanceCommand(@NotNull uSkyBlock plugin) { super("maintenance", "usb.admin.maintenance", "true|false", marktr("toggles maintenance mode")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/VersionCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/VersionCommand.java index 4fec092f9..e23e57b7f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/VersionCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/VersionCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; -import us.talabrek.ultimateskyblock.uSkyBlock; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.util.PluginInfo; import java.util.Map; import java.util.UUID; @@ -13,17 +15,18 @@ * Displays detailed version information. */ public class VersionCommand extends AbstractCommand { - private final uSkyBlock plugin; - public VersionCommand(uSkyBlock plugin) { + private final PluginInfo pluginInfo; + + @Inject + public VersionCommand(@NotNull PluginInfo pluginInfo) { super("version|v", "usb.admin.version", null, marktr("displays version information"), null, UUID.fromString("97e8584c-438c-43cf-8b58-4e56c52398ed")); - this.plugin = plugin; + this.pluginInfo = pluginInfo; } @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { - sender.sendMessage(plugin.getVersionInfo(true).split("\n")); + sender.sendMessage(pluginInfo.getVersionInfo(true).split("\n")); return true; } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/WGCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/WGCommand.java index 5eb18b7ed..795726e6e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/WGCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/WGCommand.java @@ -1,9 +1,11 @@ package us.talabrek.ultimateskyblock.command.admin; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.World; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.island.RequirePlayerCommand; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; @@ -22,7 +24,8 @@ public class WGCommand extends CompositeCommand { private final uSkyBlock plugin; - public WGCommand(final uSkyBlock plugin) { + @Inject + public WGCommand(@NotNull final uSkyBlock plugin) { super("wg", "usb.admin.wg", marktr("various WorldGuard utilities")); this.plugin = plugin; add(new RequirePlayerCommand("refresh", null, marktr("refreshes the chunks around the player")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java index fcc57f9fb..4f308a4b3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java @@ -12,6 +12,7 @@ import us.talabrek.ultimateskyblock.util.ProgressTracker; import dk.lockfuglsang.minecraft.util.TimeUtil; +import java.nio.file.Path; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,13 +26,15 @@ public class ProtectAllTask extends BukkitRunnable { private final CommandSender sender; private final uSkyBlock plugin; private final ProgressTracker tracker; + private final Path islandDirectory; private volatile boolean active; - public ProtectAllTask(final uSkyBlock plugin, final CommandSender sender, ProgressTracker tracker) { + public ProtectAllTask(final uSkyBlock plugin, final CommandSender sender, Path islandDirectory, ProgressTracker tracker) { this.plugin = plugin; this.tracker = tracker; this.sender = sender; + this.islandDirectory = islandDirectory; } public boolean isActive() { @@ -50,7 +53,7 @@ public void run() { long skipped = 0; long tStart = System.currentTimeMillis(); try { - String[] list = plugin.directoryIslands.list(IslandUtil.createIslandFilenameFilter()); + String[] list = islandDirectory.toFile().list(IslandUtil.createIslandFilenameFilter()); long total = list != null ? list.length : 0; if (list != null) { for (String fileName : list) { @@ -79,7 +82,7 @@ public void run() { active = false; } String message = tr("\u00a7eCompleted protect-all in {0}, {1} new regions were created!", getElapsed(tStart), success); - if (sender instanceof Player && ((Player)sender).isOnline()) { + if (sender instanceof Player && ((Player) sender).isOnline()) { sender.sendMessage(message); } LogUtil.log(Level.INFO, message); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeCompleteCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeCompleteCommand.java index a9450e50e..2ee27a8b3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeCompleteCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeCompleteCommand.java @@ -1,9 +1,11 @@ package us.talabrek.ultimateskyblock.command.challenge; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import java.util.Map; @@ -14,11 +16,12 @@ * Complete Challenge Command */ public class ChallengeCompleteCommand extends AbstractCommand { - private final uSkyBlock plugin; + private final ChallengeLogic challengeLogic; - public ChallengeCompleteCommand(uSkyBlock plugin) { + @Inject + public ChallengeCompleteCommand(@NotNull ChallengeLogic challengeLogic) { super("complete|c", "usb.island.challenges", "challenge", marktr("try to complete a challenge")); - this.plugin = plugin; + this.challengeLogic = challengeLogic; } @Override @@ -30,11 +33,8 @@ public boolean execute(CommandSender sender, String alias, Map d if (args == null || args.length == 0) { return false; } - String challengeName = ""; - for (String arg : args) { - challengeName += " " + arg; - } - plugin.getChallengeLogic().completeChallenge((Player) sender, challengeName.trim()); + String challengeName = String.join(" ", args); + challengeLogic.completeChallenge((Player) sender, challengeName); return true; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeInfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeInfoCommand.java index fabd25f72..eff0dfca6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeInfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/challenge/ChallengeInfoCommand.java @@ -1,15 +1,17 @@ package us.talabrek.ultimateskyblock.command.challenge; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.player.PlayerLogic; import java.util.Map; @@ -20,28 +22,29 @@ * Shows information about a challenge */ public class ChallengeInfoCommand extends AbstractCommand { - private final uSkyBlock plugin; - public ChallengeInfoCommand(uSkyBlock plugin) { + private final ChallengeLogic challengeLogic; + private final PlayerLogic playerLogic; + + @Inject + public ChallengeInfoCommand( + @NotNull ChallengeLogic challengeLogic, + @NotNull PlayerLogic playerLogic + ) { super("info|i", null, "challenge", marktr("show information about the challenge")); - this.plugin = plugin; + this.challengeLogic = challengeLogic; + this.playerLogic = playerLogic; } @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (!(sender instanceof Player)) { + if (!(sender instanceof Player player)) { sender.sendMessage(tr("\u00a7cCommand only available for players.")); return false; } - String challengeName = ""; - for (String arg : args) { - challengeName += " " + arg; - } - challengeName = challengeName.trim(); - ChallengeLogic challengeLogic = plugin.getChallengeLogic(); - Player player = (Player) sender; + String challengeName = String.join(" ", args); Challenge challenge = challengeLogic.getChallenge(challengeName); - PlayerInfo playerInfo = plugin.getPlayerInfo(player); + PlayerInfo playerInfo = playerLogic.getPlayerInfo(player); if (challenge != null && challenge.getRank().isAvailable(playerInfo)) { player.sendMessage("\u00a7eChallenge Name: " + ChatColor.WHITE + challengeName.toLowerCase()); if (challengeLogic.getRanks().size() > 1) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AllPlayerTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AllPlayerTabCompleter.java index 3b6ecc5dc..996ea4c12 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AllPlayerTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AllPlayerTabCompleter.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -15,6 +16,7 @@ public class AllPlayerTabCompleter extends AbstractTabCompleter { private final OnlinePlayerTabCompleter online; + @Inject public AllPlayerTabCompleter(OnlinePlayerTabCompleter online) { this.online = online; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AvailableChallengeTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AvailableChallengeTabCompleter.java index 1344eb957..5986b9a33 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AvailableChallengeTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/AvailableChallengeTabCompleter.java @@ -1,10 +1,13 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.player.PlayerLogic; import java.util.List; @@ -12,15 +15,27 @@ * TabCompleter for challenge-names */ public class AvailableChallengeTabCompleter extends AbstractTabCompleter { + + private final PlayerLogic playerLogic; + private final ChallengeLogic challengeLogic; + + @Inject + public AvailableChallengeTabCompleter( + @NotNull PlayerLogic playerLogic, + @NotNull ChallengeLogic challengeLogic + ) { + this.playerLogic = playerLogic; + this.challengeLogic = challengeLogic; + } + @Override protected List getTabList(CommandSender commandSender, String term) { - PlayerInfo pi = null; if (commandSender instanceof Player) { - pi = uSkyBlock.getInstance().getPlayerInfo((Player)commandSender); + PlayerInfo pi = playerLogic.getPlayerInfo((Player) commandSender); if (pi != null) { - uSkyBlock.getInstance().getChallengeLogic().getAvailableChallengeNames(pi); + return challengeLogic.getAvailableChallengeNames(pi); } } - return uSkyBlock.getInstance().getChallengeLogic().getAllChallengeNames(); + return challengeLogic.getAllChallengeNames(); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java index d8098116a..4e9678f17 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/BiomeTabCompleter.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.biome.BiomeConfig; import java.util.ArrayList; @@ -14,7 +16,8 @@ public class BiomeTabCompleter extends AbstractTabCompleter { private final BiomeConfig biomeConfig; - public BiomeTabCompleter(BiomeConfig biomeConfig) { + @Inject + public BiomeTabCompleter(@NotNull BiomeConfig biomeConfig) { this.biomeConfig = biomeConfig; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/MemberTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/MemberTabCompleter.java index a330c246e..351ea1759 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/MemberTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/MemberTabCompleter.java @@ -1,12 +1,17 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.api.IslandInfo; +import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.player.PlayerLogic; import java.util.ArrayList; import java.util.List; @@ -15,20 +20,26 @@ * Only list members of your current party. */ public class MemberTabCompleter implements TabCompleter { - private final uSkyBlock plugin; + private final PlayerLogic playerLogic; + private final IslandLogic islandLogic; - public MemberTabCompleter(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public MemberTabCompleter( + @NotNull PlayerLogic playerLogic, + @NotNull IslandLogic islandLogic + ) { + this.playerLogic = playerLogic; + this.islandLogic = islandLogic; } @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) { if (sender instanceof Player) { - PlayerInfo playerInfo = plugin.getPlayerInfo((Player) sender); + PlayerInfo playerInfo = playerLogic.getPlayerInfo((Player) sender); if (playerInfo != null && playerInfo.getHasIsland()) { - us.talabrek.ultimateskyblock.api.IslandInfo islandInfo = plugin.getIslandInfo(playerInfo); + IslandInfo islandInfo = islandLogic.getIslandInfo(playerInfo); if (islandInfo != null) { - String member = args.length > 0 ? args[args.length-1] : ""; + String member = args.length > 0 ? args[args.length - 1] : ""; return AbstractTabCompleter.filter(new ArrayList<>(islandInfo.getMembers()), member); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/PermissionTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/PermissionTabCompleter.java index 72245c391..89f8532ca 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/PermissionTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/PermissionTabCompleter.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; import us.talabrek.ultimateskyblock.menu.PartyPermissionMenuItem; @@ -9,8 +10,9 @@ import java.util.List; public class PermissionTabCompleter extends AbstractTabCompleter { - private uSkyBlock plugin; + private final uSkyBlock plugin; + @Inject public PermissionTabCompleter(uSkyBlock plugin) { this.plugin = plugin; } @@ -23,5 +25,4 @@ protected List getTabList(CommandSender commandSender, String term) { } return list; } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/RankTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/RankTabCompleter.java index ead7505c2..51de52ec5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/RankTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/RankTabCompleter.java @@ -1,9 +1,11 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; import us.talabrek.ultimateskyblock.challenge.Rank; -import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.ArrayList; import java.util.List; @@ -14,16 +16,17 @@ * Rank name tab completer */ public class RankTabCompleter extends AbstractTabCompleter { - private final uSkyBlock plugin; + private final ChallengeLogic challengeLogic; - public RankTabCompleter(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public RankTabCompleter(@NotNull ChallengeLogic challengeLogic) { + this.challengeLogic = challengeLogic; } @Override protected List getTabList(CommandSender commandSender, String term) { List rankNames = new ArrayList<>(); - for (Rank rank : plugin.getChallengeLogic().getRanks()) { + for (Rank rank : challengeLogic.getRanks()) { rankNames.add(stripFormatting(rank.getRankKey())); } return rankNames; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/SchematicTabCompleter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/SchematicTabCompleter.java index 204e0b47c..d97b9a9fd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/SchematicTabCompleter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/completion/SchematicTabCompleter.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.completion; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -13,6 +14,7 @@ public class SchematicTabCompleter extends AbstractTabCompleter { private final uSkyBlock plugin; + @Inject public SchematicTabCompleter(uSkyBlock plugin) { this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AcceptRejectCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AcceptRejectCommand.java index 653f4d18e..0534a9d9c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AcceptRejectCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AcceptRejectCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.AcceptEvent; import us.talabrek.ultimateskyblock.api.event.RejectEvent; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -13,7 +15,8 @@ public class AcceptRejectCommand extends RequirePlayerCommand { private final uSkyBlock plugin; - public AcceptRejectCommand(uSkyBlock plugin) { + @Inject + public AcceptRejectCommand(@NotNull uSkyBlock plugin) { super("accept|reject", "usb.party.join", marktr("accept/reject an invitation.")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AutoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AutoCommand.java index deae88d82..e65f2e779 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AutoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/AutoCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -18,7 +20,8 @@ public class AutoCommand extends AbstractCommand { private final CreateCommand create; private final HomeCommand home; - public AutoCommand(uSkyBlock plugin, CreateCommand create, HomeCommand home) { + @Inject + public AutoCommand(@NotNull uSkyBlock plugin, @NotNull CreateCommand create, @NotNull HomeCommand home) { super("auto", "usb.island.create", marktr("teleports you to your island (or create one)")); this.plugin = plugin; this.create = create; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BanCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BanCommand.java index a303b8a48..676767eed 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BanCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BanCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -14,7 +16,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class BanCommand extends RequireIslandCommand { - public BanCommand(uSkyBlock plugin) { + + @Inject + public BanCommand(@NotNull uSkyBlock plugin) { super(plugin, "ban|unban", "usb.island.ban", "player", marktr("ban/unban a player from your island.")); addFeaturePermission("usb.exempt.ban", tr("exempts user from being banned")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index 127ab664e..e07f844b3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.bukkit.Chunk; @@ -7,6 +8,7 @@ import org.bukkit.Registry; import org.bukkit.block.Biome; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.biome.BiomeConfig; import us.talabrek.ultimateskyblock.biome.Biomes; @@ -25,7 +27,8 @@ public class BiomeCommand extends RequireIslandCommand { private final Biomes biomes; private final BiomeConfig biomeConfig; - public BiomeCommand(uSkyBlock plugin, Biomes biomes, BiomeConfig biomeConfig) { + @Inject + public BiomeCommand(@NotNull uSkyBlock plugin, @NotNull Biomes biomes, @NotNull BiomeConfig biomeConfig) { super(plugin, "biome|b", null, "biome ?radius", marktr("change the biome of the island")); this.biomes = biomes; this.biomeConfig = biomeConfig; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java index d9401a724..7a5f21c8d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.event.CreateIslandEvent; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -14,7 +16,8 @@ public class CreateCommand extends RequirePlayerCommand { private final uSkyBlock plugin; - public CreateCommand(uSkyBlock plugin) { + @Inject + public CreateCommand(@NotNull uSkyBlock plugin) { super("create|c", "usb.island.create", "?schematic", marktr("create an island")); this.plugin = plugin; addFeaturePermission("usb.exempt.cooldown.create", tr("exempt player from create-cooldown")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/HomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/HomeCommand.java index cb318c741..205098a57 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/HomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/HomeCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -11,7 +13,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; public class HomeCommand extends RequireIslandCommand { - public HomeCommand(uSkyBlock plugin) { + + @Inject + public HomeCommand(@NotNull uSkyBlock plugin) { super(plugin, "home|h", "usb.island.home", marktr("teleport to the island home")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java index 2010f2933..bc7655576 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.model.BlockScore; @@ -19,7 +21,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class InfoCommand extends RequireIslandCommand { - public InfoCommand(uSkyBlock plugin) { + + @Inject + public InfoCommand(@NotNull uSkyBlock plugin) { super(plugin, "info", "usb.island.info", "?island", marktr("check your or another''s island info")); addFeaturePermission("usb.island.info.other", tr("allows user to see others island info")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java index a611269bd..6e1c3a645 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InviteCommand.java @@ -1,10 +1,11 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.InviteEvent; -import us.talabrek.ultimateskyblock.command.InviteHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -14,11 +15,10 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; public class InviteCommand extends RequireIslandCommand { - private final InviteHandler inviteHandler; - public InviteCommand(uSkyBlock plugin, InviteHandler inviteHandler) { + @Inject + public InviteCommand(@NotNull uSkyBlock plugin) { super(plugin, "invite", "usb.party.invite", "oplayer", marktr("invite a player to your island")); - this.inviteHandler = inviteHandler; } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java index 980c54ac2..77486ffee 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/KickCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -12,7 +14,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; public class KickCommand extends RequireIslandCommand { - public KickCommand(uSkyBlock plugin) { + + @Inject + public KickCommand(@NotNull uSkyBlock plugin) { super(plugin, "kick|remove", "usb.party.kick", "player", marktr("remove a member from your island.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java index e2944ed0b..bd1c515eb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LeaveCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -13,7 +15,8 @@ public class LeaveCommand extends RequireIslandCommand { - public LeaveCommand(uSkyBlock plugin) { + @Inject + public LeaveCommand(@NotNull uSkyBlock plugin) { super(plugin, "leave", "usb.party.leave", marktr("leave your party")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LevelCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LevelCommand.java index 55baa93b0..62b6cb407 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LevelCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LevelCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.IslandRank; import us.talabrek.ultimateskyblock.api.async.Callback; @@ -14,7 +16,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class LevelCommand extends RequireIslandCommand { - public LevelCommand(uSkyBlock plugin) { + + @Inject + public LevelCommand(@NotNull uSkyBlock plugin) { super(plugin, "level", "usb.island.level", "?island", marktr("check your or anothers island level")); addFeaturePermission("usb.island.level.other", tr("allows user to query for others levels")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LockUnlockCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LockUnlockCommand.java index c5a7604d3..634624b63 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LockUnlockCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LockUnlockCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -12,7 +14,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class LockUnlockCommand extends RequireIslandCommand { - public LockUnlockCommand(uSkyBlock plugin) { + + @Inject + public LockUnlockCommand(@NotNull uSkyBlock plugin) { super(plugin, "lock|unlock", "usb.island.lock", marktr("lock your island to non-party members.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LogCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LogCommand.java index afeb53a92..6be8bacc0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LogCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/LogCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; @@ -13,6 +14,7 @@ public class LogCommand extends RequireIslandCommand { private final SkyBlockMenu menu; + @Inject public LogCommand(uSkyBlock plugin, SkyBlockMenu menu) { super(plugin, "log|l", "usb.island.log", marktr("display log")); this.menu = menu; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MakeLeaderCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MakeLeaderCommand.java index 2e222d004..f1148a4e5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MakeLeaderCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MakeLeaderCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -12,7 +14,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class MakeLeaderCommand extends RequireIslandCommand { - public MakeLeaderCommand(uSkyBlock plugin) { + + @Inject + public MakeLeaderCommand(@NotNull uSkyBlock plugin) { super(plugin, "makeleader|transfer", "usb.island.makeleader", "member", marktr("transfer leadership to another member")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MobLimitCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MobLimitCommand.java index c1af011e7..ff77fb556 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MobLimitCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/MobLimitCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.admin.AbstractIslandInfoCommand; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -11,7 +13,8 @@ public class MobLimitCommand extends AbstractIslandInfoCommand { private final uSkyBlock plugin; - public MobLimitCommand(uSkyBlock plugin) { + @Inject + public MobLimitCommand(@NotNull uSkyBlock plugin) { super("limits", "usb.island.limit", marktr("show the islands limits")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PartyCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PartyCommand.java index ac3e7f899..e15824b23 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PartyCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PartyCommand.java @@ -1,10 +1,12 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.InviteHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; @@ -20,7 +22,8 @@ public class PartyCommand extends CompositeCommand { private final uSkyBlock plugin; private final SkyBlockMenu menu; - public PartyCommand(final uSkyBlock plugin, SkyBlockMenu menu, final InviteHandler inviteHandler) { + @Inject + public PartyCommand(@NotNull uSkyBlock plugin, @NotNull SkyBlockMenu menu, @NotNull InviteHandler inviteHandler) { super("party", null, marktr("show party information")); this.plugin = plugin; this.menu = menu; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PermCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PermCommand.java index 30a50f129..5e3228bb6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PermCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/PermCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.menu.PartyPermissionMenuItem; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -14,7 +16,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class PermCommand extends RequireIslandCommand { - public PermCommand(uSkyBlock plugin) { + + @Inject + public PermCommand(@NotNull uSkyBlock plugin) { super(plugin, "perm", "usb.island.perm", "member ?perm", marktr("changes a members island-permissions")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java index f038a88fd..ba7377ff7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.event.RestartIslandEvent; import us.talabrek.ultimateskyblock.island.IslandInfo; @@ -13,7 +15,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class RestartCommand extends RequireIslandCommand { - public RestartCommand(uSkyBlock plugin) { + + @Inject + public RestartCommand(@NotNull uSkyBlock plugin) { super(plugin, "restart|reset", "usb.island.restart", "?schematic", marktr("delete your island and start a new one.")); addFeaturePermission("usb.exempt.cooldown.restart", tr("exempt player from restart-cooldown")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java index 3f91f07fd..f904a01e7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetHomeCommand.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -12,6 +13,8 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class SetHomeCommand extends RequireIslandCommand { + + @Inject public SetHomeCommand(uSkyBlock plugin) { super(plugin, "sethome|tpset", "usb.island.sethome", marktr("set the island-home")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetWarpCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetWarpCommand.java index f5f9f4eae..043b5edd4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetWarpCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SetWarpCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -11,7 +13,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; public class SetWarpCommand extends RequireIslandCommand { - public SetWarpCommand(uSkyBlock plugin) { + + @Inject + public SetWarpCommand(@NotNull uSkyBlock plugin) { super(plugin, "setwarp|warpset", "usb.island.setwarp", marktr("set your island''s warp location")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SpawnCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SpawnCommand.java index 8f8156b9c..003b5af65 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SpawnCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/SpawnCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -13,7 +15,8 @@ public class SpawnCommand extends RequirePlayerCommand { private final uSkyBlock plugin; - public SpawnCommand(uSkyBlock plugin) { + @Inject + public SpawnCommand(@NotNull uSkyBlock plugin) { super("spawn", "usb.island.spawn", marktr("teleports you to the skyblock spawn")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/ToggleWarp.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/ToggleWarp.java index f36002c6d..8dc21e4fa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/ToggleWarp.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/ToggleWarp.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -11,6 +12,8 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class ToggleWarp extends RequireIslandCommand { + + @Inject public ToggleWarp(uSkyBlock plugin) { super(plugin, "togglewarp|tw", "usb.island.togglewarp", marktr("enable/disable warping to your island.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TopCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TopCommand.java index f4845569c..c2f2fbfd4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TopCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TopCommand.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Map; @@ -12,7 +14,8 @@ public class TopCommand extends AbstractCommand { private final uSkyBlock plugin; - public TopCommand(uSkyBlock plugin) { + @Inject + public TopCommand(@NotNull uSkyBlock plugin) { super("top", "usb.island.top", "?page", marktr("display the top10 of islands")); this.plugin = plugin; addFeaturePermission("usb.admin.topten", tr("enables user to all-ways generate top-ten (no caching)")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java index 044062621..d5e025749 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -16,7 +18,9 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class TrustCommand extends RequireIslandCommand { - public TrustCommand(uSkyBlock plugin) { + + @Inject + public TrustCommand(@NotNull uSkyBlock plugin) { super(plugin, "trust|untrust", "usb.island.trust", "?player", marktr("trust/untrust a player to help on your island.")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/WarpCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/WarpCommand.java index ee4ad5823..d5c03fd4f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/WarpCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/WarpCommand.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.command.island; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -14,7 +16,8 @@ public class WarpCommand extends RequirePlayerCommand { private final uSkyBlock plugin; - public WarpCommand(uSkyBlock plugin) { + @Inject + public WarpCommand(@NotNull uSkyBlock plugin) { super("warp|w", "usb.island.warp", "island", marktr("warp to another player''s island")); this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ExploitEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ExploitEvents.java index 667b08013..ffb745c1a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ExploitEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ExploitEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -12,6 +14,7 @@ import org.bukkit.event.vehicle.VehicleDamageEvent; import org.bukkit.event.vehicle.VehicleDestroyEvent; import org.bukkit.event.vehicle.VehicleEnterEvent; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -19,6 +22,7 @@ /** * This class is handling the event listeners for stopping various exploits. */ +@Singleton public class ExploitEvents implements Listener { private final uSkyBlock plugin; @@ -28,7 +32,8 @@ public class ExploitEvents implements Listener { private final boolean breakVehicleEnabled; private final boolean anyVillagerTradingAllowed; - public ExploitEvents(uSkyBlock plugin) { + @Inject + public ExploitEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; FileConfiguration config = plugin.getConfig(); visitorVillagerTradingProtected = config.getBoolean("options.protection.visitors.villager-trading", true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java index 281ca685a..10ffc38a9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Location; import org.bukkit.Material; @@ -38,6 +40,7 @@ /** * Handling of mob-related events. */ +@Singleton public class GriefEvents implements Listener { private final uSkyBlock plugin; @@ -49,7 +52,8 @@ public class GriefEvents implements Listener { private final boolean witherEnabled; private final boolean hatchingEnabled; - public GriefEvents(uSkyBlock plugin) { + @Inject + public GriefEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; FileConfiguration config = plugin.getConfig(); creeperEnabled = config.getBoolean("options.protection.creepers", true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/InternalEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/InternalEvents.java index 870402289..57638f3c5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/InternalEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/InternalEvents.java @@ -1,8 +1,11 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.event.CreateIslandEvent; import us.talabrek.ultimateskyblock.api.event.IslandInfoEvent; import us.talabrek.ultimateskyblock.api.event.MemberJoinedEvent; @@ -17,11 +20,12 @@ /** * Main event-handler for internal uSkyBlock events */ -@SuppressWarnings("WeakerAccess") +@Singleton public class InternalEvents implements Listener { private final uSkyBlock plugin; - public InternalEvents(uSkyBlock plugin) { + @Inject + public InternalEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java index 4c6c4e8dd..dc56979d9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -11,6 +13,7 @@ import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.ArrayList; @@ -21,11 +24,13 @@ /** * Handles the internal item-drop protection. */ +@Singleton public class ItemDropEvents implements Listener { private final uSkyBlock plugin; private final boolean visitorsCanDrop; - public ItemDropEvents(uSkyBlock plugin) { + @Inject + public ItemDropEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; visitorsCanDrop = plugin.getConfig().getBoolean("options.protection.visitors.item-drops", true); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java index 106dea0a6..0f4786271 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java @@ -1,26 +1,34 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.menu.ConfigMenu; +import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.UltimateHolder; -import us.talabrek.ultimateskyblock.uSkyBlock; +@Singleton public class MenuEvents implements Listener { - private final uSkyBlock plugin; + private final SkyBlockMenu mainMenu; + private final ConfigMenu configMenu; - public MenuEvents(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public MenuEvents(@NotNull SkyBlockMenu mainMenu, @NotNull ConfigMenu configMenu) { + this.mainMenu = mainMenu; + this.configMenu = configMenu; } @EventHandler(priority = EventPriority.MONITOR) public void guiClick(final InventoryClickEvent event) { if (event.getInventory().getHolder() instanceof UltimateHolder holder) { if (holder.getMenuType() == UltimateHolder.MenuType.CONFIG) { - plugin.getConfigMenu().onClick(event); + configMenu.onClick(event); } else { - plugin.getMenu().onClick(event); + mainMenu.onClick(event); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java index 6c4bebe70..dcb74ddfb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import org.bukkit.GameMode; import org.bukkit.Location; @@ -20,6 +22,7 @@ import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; @@ -36,6 +39,7 @@ /** * Responsible for forming the correct blocks in nether on block-breaks. */ +@Singleton public class NetherTerraFormEvents implements Listener { private final uSkyBlock plugin; private final Map> terraFormMap = new HashMap<>(); @@ -50,7 +54,8 @@ public class NetherTerraFormEvents implements Listener { private final double minPitch; private final double maxPitch; - public NetherTerraFormEvents(uSkyBlock plugin) { + @Inject + public NetherTerraFormEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; // TODO: 23/09/2015 - R4zorax: Allow this to be perk-based? terraformEnabled = plugin.getConfig().getBoolean("nether.terraform-enabled", true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index cc230a133..3a6e6f51b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; import org.bukkit.Material; @@ -26,6 +28,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.projectiles.ProjectileSource; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.api.event.IslandInfoEvent; @@ -42,6 +45,7 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +@Singleton public class PlayerEvents implements Listener { private static final Set FIRE_TRAP = new HashSet<>(Arrays.asList( EntityDamageEvent.DamageCause.LAVA, @@ -66,7 +70,8 @@ public class PlayerEvents implements Listener { Material.JUNGLE_LEAVES, Material.JUNGLE_SAPLING, Material.DARK_OAK_LEAVES, Material.DARK_OAK_SAPLING); - public PlayerEvents(uSkyBlock plugin) { + @Inject + public PlayerEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; FileConfiguration config = plugin.getConfig(); visitorFallProtected = config.getBoolean("options.protection.visitors.fall", true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index 25d5f252b..6744a0cc0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -36,6 +38,7 @@ /** * Responsible for controlling spawns on uSkyBlock islands. */ +@Singleton public class SpawnEvents implements Listener { private static final Set RIGHT_CLICKS = Set.of(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK); @@ -44,7 +47,8 @@ public class SpawnEvents implements Listener { private boolean phantomsInOverworld; private boolean phantomsInNether; - public SpawnEvents(uSkyBlock plugin) { + @Inject + public SpawnEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; phantomsInOverworld = plugin.getConfig().getBoolean("options.spawning.phantoms.overworld", true); phantomsInNether = plugin.getConfig().getBoolean("options.spawning.phantoms.nether", false); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java index 4dc3c2569..5a0b8d958 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ToolMenuEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.GameMode; import org.bukkit.Material; @@ -11,6 +13,7 @@ import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -20,13 +23,15 @@ /** * Events triggering the tool-menu */ +@Singleton public class ToolMenuEvents implements Listener { public static final String COMPLETE_CHALLENGE_CMD = "challenges complete "; private final uSkyBlock plugin; private final ItemStack tool; - private final Map commandMap = new HashMap<>(); + private final Map commandMap = new HashMap<>(); - public ToolMenuEvents(uSkyBlock plugin) { + @Inject + public ToolMenuEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; tool = ItemStackUtil.createItemStack(plugin.getConfig().getString("tool-menu.tool", Material.OAK_SAPLING.toString())); registerChallenges(); @@ -92,6 +97,7 @@ private void doCmd(PlayerInteractEvent e, Player player, String itemId) { /** * Checks if the given {@link ItemStack} is the configured tool for the tool menu. + * * @param item ItemStack to check. * @return True if it is the configured tool, false otherwise. */ diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java index 87251dd02..caad720ad 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WitherTagEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.NamespacedKey; import org.bukkit.entity.Wither; @@ -8,15 +10,18 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +@Singleton public class WitherTagEvents implements Listener { static final String ENTITY_ORIGIN_METADATA = "from-island"; private final uSkyBlock plugin; - public WitherTagEvents(uSkyBlock plugin) { + @Inject + public WitherTagEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WorldGuardEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WorldGuardEvents.java index 48fd54c54..120280c72 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WorldGuardEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/WorldGuardEvents.java @@ -1,11 +1,14 @@ package us.talabrek.ultimateskyblock.event; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -15,10 +18,12 @@ /** * Replacement for the WG ENTRY/EXIT deny flags. */ +@Singleton public class WorldGuardEvents implements Listener { private final uSkyBlock plugin; - public WorldGuardEvents(uSkyBlock plugin) { + @Inject + public WorldGuardEvents(@NotNull uSkyBlock plugin) { this.plugin = plugin; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java index 02e1f02ee..34a1e6233 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiListener.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.gui; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; @@ -9,9 +11,11 @@ import static java.util.Objects.requireNonNull; +@Singleton public class GuiListener implements Listener { private final GuiManager guiManager; + @Inject public GuiListener(@NotNull GuiManager guiManager) { this.guiManager = requireNonNull(guiManager); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java index 331a25bd8..900334a85 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/gui/GuiManager.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.gui; +import com.google.inject.Singleton; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; @@ -17,6 +18,7 @@ * This system is designed to be more flexible, easier to use and extend, and to separate concerns. * All old GUIs from us.talabrek.ultimateskyblock.menu should be converted to this system. */ +@Singleton public class GuiManager { private final Map activeInventories = new HashMap<>(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java index 55ed18d92..64169809e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java @@ -1,10 +1,15 @@ package us.talabrek.ultimateskyblock.handler; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.Map; import java.util.UUID; import java.util.WeakHashMap; @@ -12,14 +17,21 @@ /** * Handles confirms. */ +@Singleton public class ConfirmHandler { private final Map confirmMap = new WeakHashMap<>(); - private final uSkyBlock plugin; - private final int timeout; + private final Scheduler scheduler; + private final PluginConfig config; + private final Duration timeout; - public ConfirmHandler(uSkyBlock plugin, int timeout) { - this.plugin = plugin; - this.timeout = timeout; + @Inject + public ConfirmHandler( + @NotNull Scheduler scheduler, + @NotNull PluginConfig config + ) { + this.scheduler = scheduler; + this.config = config; + this.timeout = Duration.ofSeconds(config.getYamlConfig().getInt("options.advanced.confirmTimeout", 10)); } public long millisLeft(final Player player, final String cmd) { @@ -27,7 +39,7 @@ public long millisLeft(final Player player, final String cmd) { if (confirmMap.containsKey(uuid)) { ConfirmCommand command = confirmMap.get(uuid); if (command != null && command.isValid(cmd, timeout)) { - return TimeUtil.secondsAsMillis(timeout) - (System.currentTimeMillis() - command.tstamp); + return timeout.minus(Duration.between(command.timeStamp, LocalDateTime.now())).toMillis(); } } return -1; @@ -46,34 +58,31 @@ public boolean checkCommand(final Player player, final String cmd) { } } confirmMap.put(uuid, new ConfirmCommand(cmd)); - plugin.async(new Runnable() { - @Override - public void run() { - ConfirmCommand confirmCommand = confirmMap.remove(player.getUniqueId()); - if (confirmCommand != null && player != null && player.isOnline()) { - player.sendMessage(I18nUtil.tr("\u00a79{0}\u00a77 timed out", cmd)); - } + scheduler.async(() -> { + ConfirmCommand confirmCommand = confirmMap.remove(player.getUniqueId()); + if (confirmCommand != null && player != null && player.isOnline()) { + player.sendMessage(I18nUtil.tr("\u00a79{0}\u00a77 timed out", cmd)); } - }, TimeUtil.secondsAsMillis(timeout)); + }, timeout); player.sendMessage(I18nUtil.tr("\u00a7eDoing \u00a79{0}\u00a7e is \u00a7cRISKY\u00a7e. Repeat the command within \u00a7a{1}\u00a7e seconds to accept!", cmd, timeout)); return false; } private boolean confirmationsActiveFor(String cmd) { - return plugin.getConfig().getBoolean("confirmation." + cmd.replaceAll("[^a-z\\ ]", ""), true); + return config.getYamlConfig().getBoolean("confirmation." + cmd.replaceAll("[^a-z\\ ]", ""), true); } private static class ConfirmCommand { - private final String cmd; - private final long tstamp; + private final String command; + private final LocalDateTime timeStamp; - private ConfirmCommand(String cmd) { - this.cmd = cmd; - this.tstamp = System.currentTimeMillis(); + private ConfirmCommand(String command) { + this.command = command; + this.timeStamp = LocalDateTime.now(); } - public boolean isValid(String cmd, long timeout) { - return this.cmd.equals(cmd) && tstamp >= (System.currentTimeMillis() - TimeUtil.secondsAsMillis(timeout)); + public boolean isValid(String command, Duration timeout) { + return this.command.equals(command) && timeStamp.plus(timeout).isAfter(LocalDateTime.now()); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java index 4184c17a1..4ef3d5ccd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java @@ -1,34 +1,33 @@ package us.talabrek.ultimateskyblock.handler; -import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.TimeUtil; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.UUID; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; /** * Responsible for handling various cooldowns on commands. */ +@Singleton public class CooldownHandler { - private final Map> cooldowns = new WeakHashMap<>(); - private final uSkyBlock plugin; + // TODO: flatten map to use as key, use time API instead of long + private final Map> cooldowns = new HashMap<>(); + private final Scheduler scheduler; - public CooldownHandler(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public CooldownHandler(@NotNull Scheduler scheduler) { + this.scheduler = scheduler; } - /** - * Returns the number of seconds left on the cooldown. - * 0 if it's not on cooldown anymore. - * @param player The player - * @param cmd The command to check - * @return - */ - public int getCooldown(org.bukkit.entity.Player player, String cmd) { + public int getCooldown(Player player, String cmd) { if (player.hasPermission("usb.mod.bypasscooldowns") || player.hasPermission("usb.exempt.cooldown." + cmd)) { return 0; } @@ -44,7 +43,7 @@ public int getCooldown(org.bukkit.entity.Player player, String cmd) { public void resetCooldown(final Player player, final String cmd, int cooldownSecs) { UUID uuid = player.getUniqueId(); if (!cooldowns.containsKey(uuid)) { - Map cdMap = new ConcurrentHashMap<>(); + Map cdMap = new HashMap<>(); cooldowns.put(uuid, cdMap); } if (cooldownSecs == 0) { @@ -52,15 +51,12 @@ public void resetCooldown(final Player player, final String cmd, int cooldownSec return; } cooldowns.get(uuid).put(cmd, System.currentTimeMillis() + TimeUtil.secondsAsMillis(cooldownSecs)); - plugin.async(new Runnable() { - @Override - public void run() { - Map cmdMap = cooldowns.get(player.getUniqueId()); - if (cmdMap != null) { - cmdMap.remove(cmd); - } + scheduler.sync((Runnable) () -> { + Map cmdMap = cooldowns.get(player.getUniqueId()); + if (cmdMap != null) { + cmdMap.remove(cmd); } - }, TimeUtil.secondsAsMillis(cooldownSecs)); + }, Duration.ofSeconds(cooldownSecs)); } public boolean clearCooldown(Player player, String cmd) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java index 8c28a5f98..2fe1aa63d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClear.java @@ -30,7 +30,7 @@ public class WorldEditClear extends IncrementalRunnable { private final List regions; public WorldEditClear(uSkyBlock plugin, World world, Set borderRegions, Runnable onCompletion) { - super(plugin, onCompletion); + super(plugin.getScheduler(), plugin.getPluginConfig(), onCompletion); this.world = world; log.log(Level.FINE, "Planning regen of borders: " + borderRegions); regions = createRegions(borderRegions); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java index 6871d0566..088841b34 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java @@ -12,14 +12,18 @@ import com.sk89q.worldedit.world.block.BlockTypes; import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.async.IncrementalRunnable; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.Iterator; import java.util.Set; import java.util.logging.Level; +import java.util.logging.Logger; import static java.util.Objects.requireNonNull; import static us.talabrek.ultimateskyblock.util.LogUtil.log; @@ -31,25 +35,33 @@ public class WorldEditClearFlatlandTask extends IncrementalRunnable { private static final BlockState AIR = requireNonNull(BlockTypes.AIR).getDefaultState(); + private final Logger logger; private final Set borderRegions; private final Set innerChunks; - private final uSkyBlock plugin; private final BukkitWorld bukkitWorld; private final int minY; private final int maxY; private final int maxBlocks; - public WorldEditClearFlatlandTask(final uSkyBlock plugin, final CommandSender commandSender, final Region region, final String format) { - super(plugin); + public WorldEditClearFlatlandTask( + @NotNull Scheduler scheduler, + @NotNull PluginConfig config, + @NotNull WorldManager worldManager, + @NotNull Logger logger, + @NotNull CommandSender commandSender, + @NotNull Region region, + @NotNull String format + ) { + super(scheduler, config); + this.logger = logger; setOnCompletion(() -> { String duration = TimeUtil.millisAsString(WorldEditClearFlatlandTask.this.getTimeElapsed()); - log(Level.INFO, String.format("Region %s was cleared in %s", region.toString(), duration)); + log(Level.INFO, String.format("Region %s was cleared in %s", region, duration)); commandSender.sendMessage(String.format(format, duration)); }); - this.plugin = plugin; innerChunks = WorldEditHandler.getInnerChunks(region); borderRegions = WorldEditHandler.getBorderRegions(region); - bukkitWorld = new BukkitWorld(plugin.getWorldManager().getWorld()); + bukkitWorld = new BukkitWorld(worldManager.getWorld()); minY = Math.min(region.getMinimumPoint().getBlockY(), region.getMaximumPoint().getBlockY()); maxY = Math.max(region.getMinimumPoint().getBlockY(), region.getMaximumPoint().getBlockY()); maxBlocks = 2 * Math.max(region.getLength(), region.getWidth()) * 16 * (maxY - minY); @@ -74,7 +86,7 @@ public boolean execute() { BlockVector3.at(x + 15, maxY, z + 15)), AIR); } catch (MaxChangedBlocksException e) { - plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); + logger.log(Level.WARNING, "Unable to clear flat-land", e); } } else if (border.hasNext()) { Region borderRegion = border.next(); @@ -82,7 +94,7 @@ public boolean execute() { try { editSession.setBlocks(borderRegion, AIR); } catch (MaxChangedBlocksException e) { - plugin.getLogger().log(Level.WARNING, "Unable to clear flat-land", e); + logger.log(Level.WARNING, "Unable to clear flat-land", e); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java index 27d79aa91..170060b2d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java @@ -1,5 +1,8 @@ package us.talabrek.ultimateskyblock.hook; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; @@ -8,22 +11,27 @@ import us.talabrek.ultimateskyblock.hook.world.MultiverseHook; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +@Singleton public class HookManager { private final uSkyBlock plugin; + private final Logger logger; private final Map hooks = new ConcurrentHashMap<>(); - public HookManager(@NotNull uSkyBlock plugin) { + @Inject + public HookManager(@NotNull uSkyBlock plugin, @NotNull Logger logger) { this.plugin = plugin; + this.logger = logger; } /** * Returns an {@link Optional} containing the requested {@link PluginHook}, or null if the hook is not available. + * * @param hook Name of the requested hook. * @return Optional containing the requested PluginHook, or null if unavailable. */ @@ -33,6 +41,7 @@ public Optional getHook(String hook) { /** * Short method for {@link #getHook(String)} to get the optional {@link EconomyHook}. + * * @return optional of EconomyHook. */ public Optional getEconomyHook() { @@ -41,6 +50,7 @@ public Optional getEconomyHook() { /** * Short method for {@link #getHook(String)} to get the optional {@link MultiverseHook}. + * * @return optional of MultiverseHook. */ public Optional getMultiverse() { @@ -49,6 +59,7 @@ public Optional getMultiverse() { /** * Short method for {@link #getHook(String)} to get the optional {@link PermissionsHook}. + * * @return optional of PermissionsHook. */ public Optional getPermissionsHook() { @@ -58,6 +69,7 @@ public Optional getPermissionsHook() { /** * Tries to enable the hook in the given {@link PluginHook}. Adds the plugin hook to the list of enabled hooks * if successfull. Throws a {@link HookFailedException} otherwise. + * * @param hook Hook to enable and register. * @throws HookFailedException if hooking into the plugin failes. */ @@ -66,67 +78,72 @@ public void registerHook(PluginHook hook) throws HookFailedException { hooks.put(hook.getHookName(), hook); } + public void setupHooks() { + setupMultiverse(); + setupEconomyHook(); + setupPermissionsHook(); + } + /** * Checks and hooks if there are compatible Economy plugins available. + * * @return True if a compatible Economy plugin has been found and hooking succeeded, false otherwise. */ public boolean setupEconomyHook() { try { - if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { + if (Bukkit.getPluginManager().isPluginEnabled("Vault")) { VaultEconomy vault = new VaultEconomy(plugin); registerHook(vault); - plugin.getLogger().info("Hooked into Vault economy"); + logger.info("Hooked into Vault economy"); return true; } } catch (HookFailedException ex) { - plugin.getLogger().warning("Failed to hook into Vault economy."); - ex.printStackTrace(); + logger.log(Level.SEVERE, "Failed to hook into Vault economy.", ex); } - plugin.getLogger().info("Failed to find a compatible economy system. Economy rewards will be disabled."); + logger.info("Failed to find a compatible economy system. Economy rewards will be disabled."); return false; } /** * Checks and hooks into Multiverse-Core. + * * @return True if hooking succeeded, false otherwise. */ public boolean setupMultiverse() { try { - if (plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Core")) { + if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core")) { MultiverseHook mvHook = new MultiverseHook(plugin); registerHook(mvHook); - plugin.getLogger().info("Hooked into Multiverse-Core"); + logger.info("Hooked into Multiverse-Core"); return true; } } catch (HookFailedException ex) { - plugin.getLogger().warning("Failed to hook into Multiverse-Core"); - ex.printStackTrace(); + logger.log(Level.SEVERE, "Failed to hook into Multiverse-Core", ex); } - plugin.getLogger().warning("Failed to find Multiverse-Core. Multiworld support will be limited."); + logger.warning("Failed to find Multiverse-Core. Multiworld support will be limited."); return false; } /** * Checks and hooks if there are compatible Permissions plugins available. + * * @return True if a compatible Permissions plugin has geen found and hooking succeeded, false otherwise. */ public boolean setupPermissionsHook() { try { - if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { + if (Bukkit.getPluginManager().isPluginEnabled("Vault")) { VaultPermissions vault = new VaultPermissions(plugin); registerHook(vault); - plugin.getLogger().info("Hooked into Vault permissions."); + logger.info("Hooked into Vault permissions."); return true; } } catch (HookFailedException ex) { - plugin.getLogger().warning("Failed to hook into Vault permissions plugin."); - ex.printStackTrace(); + logger.log(Level.SEVERE, "Failed to hook into Vault permissions plugin.", ex); } - plugin.getLogger().warning("Failed to find a compatible permissions system. Permission rewards " + - "will be disabled."); + logger.warning("Failed to find a compatible permissions system. Permission rewards will be disabled."); return false; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java index 176196686..dc2ee6965 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.imports; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -21,6 +23,7 @@ /** * Delegates and batches the import. */ +@Singleton public class USBImporterExecutor { private final uSkyBlock plugin; private final ProgressTracker progressTracker; @@ -30,6 +33,7 @@ public class USBImporterExecutor { private volatile int countSkip; private volatile int countFailed; + @Inject public USBImporterExecutor(uSkyBlock plugin) { this.plugin = plugin; double progressEveryPct = plugin.getConfig().getDouble("importer.progressEveryPct", 10); @@ -125,7 +129,7 @@ private void doImport(final CommandSender sender, final USBImporter importer, fi private void complete(CommandSender sender, USBImporter importer) { importer.completed(countSuccess, countFailed, countSkip); sender.sendMessage(tr("\u00a7eConverted {0}/{1} files in {2}", - countSuccess, (countSuccess + countFailed), TimeUtil.millisAsString(System.currentTimeMillis() - tStart))); + countSuccess, (countSuccess + countFailed), TimeUtil.millisAsString(System.currentTimeMillis() - tStart))); plugin.getConfig().set("importer." + importer.getName() + ".imported", true); plugin.saveConfig(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java index d36f515de..7ace8bec6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/fixuuidleader/UUIDLeaderImporter.java @@ -8,12 +8,12 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; -import java.io.FilenameFilter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; @@ -70,12 +70,10 @@ public Boolean importFile(File file) { @Override public File[] getFiles() { - return plugin.directoryIslands.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name != null && name.endsWith(".err"); - } - }); + var result = plugin.getDataFolder().toPath() + .resolve("islands").toFile() + .listFiles((dir, name) -> name != null && name.endsWith(".err")); + return Objects.requireNonNullElseGet(result, () -> new File[0]); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/update/USBUpdateImporter.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/update/USBUpdateImporter.java index 9fa78d4a2..ccbbb370e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/update/USBUpdateImporter.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/update/USBUpdateImporter.java @@ -6,6 +6,7 @@ import us.talabrek.ultimateskyblock.util.IslandUtil; import java.io.File; +import java.util.Objects; /** * An importer that simply loads all island-infos into memory - activating the built-in yml @@ -34,7 +35,10 @@ public Boolean importFile(File file) { @Override public File[] getFiles() { - return plugin.directoryIslands.listFiles(IslandUtil.createIslandFilenameFilter()); + var result = plugin.getDataFolder().toPath() + .resolve("islands").toFile() + .listFiles(IslandUtil.createIslandFilenameFilter()); + return Objects.requireNonNullElseGet(result, () -> new File[0]); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java index f5935c8b2..ad05ee6c4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java @@ -1,19 +1,23 @@ package us.talabrek.ultimateskyblock.island; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.api.model.BlockScore; import us.talabrek.ultimateskyblock.island.level.IslandScore; -import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; +@Singleton public class BlockLimitLogic { public enum CanPlace {YES, UNCERTAIN, NO} @@ -23,11 +27,14 @@ public enum CanPlace {YES, UNCERTAIN, NO} private final boolean limitsEnabled; - public BlockLimitLogic(uSkyBlock plugin) { - FileConfiguration config = plugin.getConfig(); - limitsEnabled = config.getBoolean("options.island.block-limits.enabled", false); + @Inject + public BlockLimitLogic( + @NotNull PluginConfig config, + @NotNull Logger logger + ) { + limitsEnabled = config.getYamlConfig().getBoolean("options.island.block-limits.enabled", false); if (limitsEnabled) { - ConfigurationSection section = config.getConfigurationSection("options.island.block-limits"); + ConfigurationSection section = config.getYamlConfig().getConfigurationSection("options.island.block-limits"); Set keys = section.getKeys(false); keys.remove("enabled"); for (String key : keys) { @@ -36,7 +43,7 @@ public BlockLimitLogic(uSkyBlock plugin) { if (material != null && limit >= 0) { blockLimits.put(material, limit); } else { - plugin.getLogger().warning("Unknown material " + key + " supplied for block-limit, or value not an integer"); + logger.warning("Unknown material " + key + " supplied for block-limit, or value not an integer"); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java index 6bf2a727b..2adb6503f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandGenerator.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.island; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -7,12 +9,13 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.Chest; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.bootstrap.PluginDataDir; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.player.Perk; import us.talabrek.ultimateskyblock.player.PlayerPerk; @@ -24,6 +27,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.nio.file.Path; import java.security.CodeSource; import java.util.ArrayList; import java.util.Arrays; @@ -37,31 +41,39 @@ /** * The factory for creating islands (actual blocks). */ +@Singleton public class IslandGenerator { - private static final Logger log = Logger.getLogger(IslandGenerator.class.getName()); + private final Logger logger; private final File[] schemFiles; private final File netherSchematic; private final File directorySchematics; - public IslandGenerator(@NotNull File dataFolder, @NotNull FileConfiguration config) { - directorySchematics = new File(dataFolder + File.separator + "schematics"); + @Inject + public IslandGenerator( + @NotNull Logger logger, + @NotNull @PluginDataDir Path dataFolder, + @NotNull PluginConfig config + ) { + this.logger = logger; + directorySchematics = dataFolder.resolve("schematics").toFile(); if (!directorySchematics.exists()) { //noinspection ResultOfMethodCallIgnored directorySchematics.mkdir(); } copySchematicsFromJar(); - netherSchematic = getSchematicFile(config.getString("nether.schematicName", "uSkyBlockNether")); + netherSchematic = getSchematicFile(config.getYamlConfig().getString("nether.schematicName", "uSkyBlockNether")); schemFiles = loadSchematics(config); if (schemFiles == null) { - log.info("[uSkyBlock] No schematic file loaded."); + logger.info("No schematic file loaded."); } else { - log.info("[uSkyBlock] " + schemFiles.length + " schematics loaded."); + logger.info(schemFiles.length + " schematics loaded."); } } /** * Gets a {@link List} of available schematic names. + * * @return List of available schematic names. */ public List getSchemeNames() { @@ -75,9 +87,10 @@ public List getSchemeNames() { /** * Generate an island at the given {@link Location}. + * * @param playerPerk PlayerPerk object for the island owner. - * @param next Location to generate an island. - * @param cSchem New island schematic. + * @param next Location to generate an island. + * @param cSchem New island schematic. * @return True if the island was generated, false otherwise. */ public boolean createIsland(@NotNull PlayerPerk playerPerk, @NotNull Location next, @Nullable String cSchem) { @@ -106,8 +119,9 @@ public boolean createIsland(@NotNull PlayerPerk playerPerk, @NotNull Location ne /** * Find the nearest chest at the given {@link Location} and fill the chest with the starter and {@link Perk} * based items. + * * @param location Location to search for a chest. - * @param perk Perk containing extra perk-based items to add. + * @param perk Perk containing extra perk-based items to add. * @return True if the chest is found and filled, false otherwise. */ public boolean findAndSetChest(@NotNull Location location, @NotNull Perk perk) { @@ -117,8 +131,9 @@ public boolean findAndSetChest(@NotNull Location location, @NotNull Perk perk) { /** * Fill the {@link Inventory} of the given chest {@link Location} with the starter and {@link Perk} based items. + * * @param chestLocation Location of the chest block. - * @param perk Perk containing extra perk-based items to add. + * @param perk Perk containing extra perk-based items to add. * @return True if the chest is found and filled, false otherwise. */ public boolean setChest(@Nullable Location chestLocation, @NotNull Perk perk) { @@ -159,36 +174,36 @@ private void copySchematicsFromJar() { try (InputStream inputStream = uSkyBlock.class.getClassLoader().getResourceAsStream(entry.getName())) { FileUtil.copy(inputStream, f); } catch (IOException e) { - log.log(Level.WARNING, "Unable to load schematic " + entry.getName(), e); + logger.log(Level.WARNING, "Unable to load schematic " + entry.getName(), e); } } } zin.closeEntry(); } } catch (IOException e) { - log.log(Level.WARNING, "Unable to find schematics in plugin JAR", e); + logger.log(Level.WARNING, "Unable to find schematics in plugin JAR", e); } } - private File[] loadSchematics(@NotNull FileConfiguration config) { + private File[] loadSchematics(@NotNull PluginConfig config) { return directorySchematics.listFiles((dir, name) -> { String basename = FileUtil.getBasename(name); - boolean enabled = config.getBoolean("island-schemes." + basename + ".enabled", true); + boolean enabled = config.getYamlConfig().getBoolean("island-schemes." + basename + ".enabled", true); return enabled && - name != null && - (name.endsWith(".schematic") || name.endsWith(".schem")) && - !name.startsWith("uSkyBlock") && - !basename.toLowerCase().endsWith("nether"); + name != null && + (name.endsWith(".schematic") || name.endsWith(".schem")) && + !name.startsWith("uSkyBlock") && + !basename.toLowerCase().endsWith("nether"); }); } private File getSchematicFile(String cSchem) { List extensions = Arrays.asList("schematic", "schem"); return extensions.stream() - .map(f -> new File(directorySchematics, cSchem + "." + f)) - .filter(f -> f.exists() && f.canRead()) - .findFirst() - .orElse(null); + .map(f -> new File(directorySchematics, cSchem + "." + f)) + .filter(f -> f.exists() && f.canRead()) + .findFirst() + .orElse(null); } private boolean isSchematicFile(ZipEntry entry, String prefix) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 485dc10ba..588f62618 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; @@ -59,7 +60,6 @@ public class IslandInfo implements us.talabrek.ultimateskyblock.api.IslandInfo { private static final Logger log = Logger.getLogger(IslandInfo.class.getName()); private static final Pattern OLD_LOG_PATTERN = Pattern.compile("\u00a7d\\[(?[^\\]]+)\\]\u00a77 (?.*)"); private static final int YML_VERSION = 3; - private static File directory = new File("."); private final uSkyBlock plugin; private File file; @@ -68,13 +68,13 @@ public class IslandInfo implements us.talabrek.ultimateskyblock.api.IslandInfo { private boolean dirty = false; private boolean toBeDeleted = false; - public IslandInfo(@NotNull String islandName, @NotNull uSkyBlock plugin) { + public IslandInfo(@NotNull String islandName, @NotNull uSkyBlock plugin, @NotNull Path islandDirectory) { Validate.notNull(islandName, "IslandName cannot be null"); Validate.notEmpty(islandName, "IslandName cannot be empty"); this.plugin = plugin; config = new YamlConfiguration(); - file = new File(directory, islandName + ".yml"); + file = islandDirectory.resolve(islandName + ".yml").toFile(); name = islandName; if (file.exists()) { readConfig(config, file); @@ -117,10 +117,6 @@ private void updateConfig() { save(); } - public static void setDirectory(@NotNull File dir) { - directory = dir; - } - public void resetIslandConfig(@NotNull final String leader) { Validate.notNull(leader, "Leader cannot be null"); Validate.notEmpty(leader, "Leader cannot be empty"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java index ef02af27a..2fee393e2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java @@ -1,17 +1,25 @@ package us.talabrek.ultimateskyblock.island; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.file.FileUtil; import org.bukkit.Location; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.bootstrap.PluginDataDir; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.time.Duration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; @@ -21,18 +29,34 @@ /** * Responsible for keeping track of and locating island locations for new islands. */ +@Singleton public class IslandLocatorLogic { - private static final Logger log = Logger.getLogger(IslandLocatorLogic.class.getName()); + private final Logger logger; + private final WorldManager worldManager; + private final Scheduler scheduler; + private final OrphanLogic orphanLogic; private final uSkyBlock plugin; private final File configFile; private final FileConfiguration config; private final Map reservations = new ConcurrentHashMap<>(); private Location lastIsland = null; - private long reservationTimeout; + private final Duration reservationTimeout; - public IslandLocatorLogic(final uSkyBlock plugin) { + @Inject + public IslandLocatorLogic( + @NotNull uSkyBlock plugin, + @NotNull @PluginDataDir Path pluginDir, + @NotNull Logger logger, + @NotNull WorldManager worldManager, + @NotNull Scheduler scheduler, + @NotNull OrphanLogic orphanLogic + ) { this.plugin = plugin; - this.configFile = new File(plugin.getDataFolder(), "lastIslandConfig.yml"); + this.configFile = pluginDir.resolve("lastIslandConfig.yml").toFile(); + this.logger = logger; + this.worldManager = worldManager; + this.scheduler = scheduler; + this.orphanLogic = orphanLogic; this.config = new YamlConfiguration(); FileUtil.readConfig(config, configFile); // Backward compatibility @@ -42,14 +66,14 @@ public IslandLocatorLogic(final uSkyBlock plugin) { plugin.getConfig().set("options.general.lastIslandX", null); plugin.getConfig().set("options.general.lastIslandZ", null); } - reservationTimeout = plugin.getConfig().getLong("options.island.reservationTimeout", 5 * 60000); + reservationTimeout = Duration.ofMillis(plugin.getConfig().getLong("options.island.reservationTimeout", 5 * 60000)); } private Location getLastIsland() { if (lastIsland == null) { - lastIsland = new Location(plugin.getWorldManager().getWorld(), - config.getInt("options.general.lastIslandX", 0), Settings.island_height, - config.getInt("options.general.lastIslandZ", 0)); + lastIsland = new Location(worldManager.getWorld(), + config.getInt("options.general.lastIslandX", 0), Settings.island_height, + config.getInt("options.general.lastIslandZ", 0)); } return LocationUtil.alignToDistance(lastIsland, Settings.island_distance); } @@ -64,14 +88,11 @@ private void reserve(Location islandLocation) { final String islandName = LocationUtil.getIslandName(islandLocation); final long tstamp = System.currentTimeMillis(); reservations.put(islandName, tstamp); - plugin.async(new Runnable() { - @Override - public void run() { - synchronized (reservations) { - Long tReserved = reservations.get(islandName); - if (tReserved != null && tReserved == tstamp) { - reservations.remove(islandName); - } + scheduler.async(() -> { + synchronized (reservations) { + Long tReserved = reservations.get(islandName); + if (tReserved != null && tReserved == tstamp) { + reservations.remove(islandName); } } }, reservationTimeout); @@ -79,7 +100,7 @@ public void run() { private synchronized Location getNext(Player player) { Location last = getLastIsland(); - if (plugin.getWorldManager().isSkyWorld(player.getWorld()) && !plugin.islandInSpawn(player.getLocation())) { + if (worldManager.isSkyWorld(player.getWorld()) && !plugin.islandInSpawn(player.getLocation())) { Location location = LocationUtil.alignToDistance(player.getLocation(), Settings.island_distance); if (isAvailableLocation(location)) { player.sendMessage(tr("\u00a79Creating an island at your location")); @@ -92,7 +113,7 @@ private synchronized Location getNext(Player player) { return location; } } - Location next = plugin.getOrphanLogic().getNextValidOrphan(); + Location next = orphanLogic.getNextValidOrphan(this); if (next == null) { next = last; // Ensure the found location is valid (or find one that is). @@ -107,16 +128,13 @@ private synchronized Location getNext(Player player) { private void save() { final Location locationToSave = lastIsland; - plugin.async(new Runnable() { - @Override - public void run() { - try { - config.set("options.general.lastIslandX", locationToSave.getBlockX()); - config.set("options.general.lastIslandZ", locationToSave.getBlockZ()); - config.save(configFile); - } catch (IOException e) { - log.warning("Unable to save " + configFile); - } + scheduler.async(() -> { + try { + config.set("options.general.lastIslandX", locationToSave.getBlockX()); + config.set("options.general.lastIslandZ", locationToSave.getBlockZ()); + config.save(configFile); + } catch (IOException e) { + logger.warning("Unable to save " + configFile); } }); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java index be230b852..2cd967369 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java @@ -5,6 +5,8 @@ import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -17,21 +19,30 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.IslandLevel; import us.talabrek.ultimateskyblock.api.IslandRank; import us.talabrek.ultimateskyblock.api.event.uSkyBlockEvent; +import us.talabrek.ultimateskyblock.bootstrap.PluginDataDir; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.handler.task.WorldEditClearFlatlandTask; import us.talabrek.ultimateskyblock.island.level.IslandScore; import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.player.TeleportLogic; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.IslandUtil; import us.talabrek.ultimateskyblock.util.LocationUtil; -import us.talabrek.ultimateskyblock.util.PlayerUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.uuid.PlayerDB; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -49,11 +60,17 @@ /** * Responsible for island creation, locating locations, purging, clearing etc. */ +@Singleton public class IslandLogic { - private static final Logger log = Logger.getLogger(IslandLogic.class.getName()); + private final Logger logger; private final uSkyBlock plugin; - private final File directoryIslands; + private final WorldManager worldManager; + private final TeleportLogic teleportLogic; + private final Scheduler scheduler; + private final PluginConfig config; + private final Path directoryIslands; private final OrphanLogic orphanLogic; + private final PlayerDB playerDB; private final LoadingCache cache; private final boolean showMembers; @@ -65,30 +82,53 @@ public class IslandLogic { private volatile long lastGenerate = 0; private final List ranks = new ArrayList<>(); - public IslandLogic(uSkyBlock plugin, File directoryIslands, OrphanLogic orphanLogic) { + @Inject + public IslandLogic( + @NotNull Logger logger, + @NotNull uSkyBlock plugin, + @NotNull WorldManager worldManager, + @NotNull TeleportLogic teleportLogic, + @NotNull Scheduler scheduler, + @NotNull PluginConfig config, + @NotNull @PluginDataDir Path dataPath, + @NotNull OrphanLogic orphanLogic, + @NotNull PlayerDB playerDB + ) { + this.logger = logger; this.plugin = plugin; - this.directoryIslands = directoryIslands; + this.worldManager = worldManager; + this.teleportLogic = teleportLogic; + this.scheduler = scheduler; + this.config = config; + this.playerDB = playerDB; + Path islandDirectory = dataPath.resolve("islands"); + try { + Files.createDirectories(islandDirectory); + } catch (IOException e) { + logger.severe("Unable to create island directory: " + islandDirectory); + } + this.directoryIslands = islandDirectory; this.orphanLogic = orphanLogic; - this.showMembers = plugin.getConfig().getBoolean("options.island.topTenShowMembers", true); - this.flatlandFix = plugin.getConfig().getBoolean("options.island.fixFlatland", false); - this.useDisplayNames = plugin.getConfig().getBoolean("options.advanced.useDisplayNames", false); - topTenCutoff = plugin.getConfig().getDouble("options.advanced.topTenCutoff", plugin.getConfig().getDouble("options.advanced.purgeLevel", 10)); + this.showMembers = config.getYamlConfig().getBoolean("options.island.topTenShowMembers", true); + this.flatlandFix = config.getYamlConfig().getBoolean("options.island.fixFlatland", false); + this.useDisplayNames = config.getYamlConfig().getBoolean("options.advanced.useDisplayNames", false); + topTenCutoff = config.getYamlConfig().getDouble("options.advanced.topTenCutoff", config.getYamlConfig().getDouble("options.advanced.purgeLevel", 10)); cache = CacheBuilder - .from(plugin.getConfig().getString("options.advanced.islandCache", - "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) - .removalListener((RemovalListener) removal -> { - log.fine("Removing island-info " + removal.getKey() + " from cache"); - removal.getValue().saveToFile(); - }) - .build(new CacheLoader<>() { - @Override - public @NotNull IslandInfo load(@NotNull String islandName) { - log.fine("Loading island-info " + islandName + " to cache!"); - return new IslandInfo(islandName, plugin); - } - }); - long every = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.advanced.island.saveEvery", 30)); - saveTask = plugin.async(this::saveDirtyToFiles, every, every); + .from(config.getYamlConfig().getString("options.advanced.islandCache", + "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) + .removalListener((RemovalListener) removal -> { + logger.fine("Removing island-info " + removal.getKey() + " from cache"); + removal.getValue().saveToFile(); + }) + .build(new CacheLoader<>() { + @Override + public @NotNull IslandInfo load(@NotNull String islandName) { + logger.fine("Loading island-info " + islandName + " to cache!"); + return new IslandInfo(islandName, plugin, directoryIslands); + } + }); + Duration every = Duration.ofSeconds(config.getYamlConfig().getInt("options.advanced.island.saveEvery", 30)); + saveTask = scheduler.async(this::saveDirtyToFiles, every, every); } private void saveDirtyToFiles() { @@ -119,45 +159,42 @@ public IslandInfo getIslandInfo(PlayerInfo playerInfo) { } public void clearIsland(final Location loc, final Runnable afterDeletion) { - log.log(Level.FINE, "clearing island at {0}", loc); - Runnable clearNether = new Runnable() { - @Override - public void run() { - Location netherIsland = getNetherLocation(loc); - ProtectedRegion netherRegion = WorldGuardHandler.getNetherRegionAt(netherIsland); - if (netherRegion != null) { - for (Player player : WorldGuardHandler.getPlayersInRegion(netherIsland.getWorld(), netherRegion)) { - if (player != null && player.isOnline() && plugin.getWorldManager().isSkyNether(player.getWorld()) && !player.isFlying()) { - player.sendMessage(tr("\u00a7cThe island owning this piece of nether is being deleted! Sending you to spawn.")); - plugin.getTeleportLogic().spawnTeleport(player, true); - } + logger.log(Level.FINE, "clearing island at {0}", loc); + Runnable clearNether = () -> { + Location netherIsland = getNetherLocation(loc); + ProtectedRegion netherRegion = WorldGuardHandler.getNetherRegionAt(netherIsland); + if (netherRegion != null) { + for (Player player : WorldGuardHandler.getPlayersInRegion(netherIsland.getWorld(), netherRegion)) { + if (player != null && player.isOnline() && worldManager.isSkyNether(player.getWorld()) && !player.isFlying()) { + player.sendMessage(tr("\u00a7cThe island owning this piece of nether is being deleted! Sending you to spawn.")); + teleportLogic.spawnTeleport(player, true); } - WorldEditHandler.clearIsland(netherIsland.getWorld(), netherRegion, afterDeletion); - } else { - afterDeletion.run(); } + WorldEditHandler.clearIsland(netherIsland.getWorld(), netherRegion, afterDeletion); + } else { + afterDeletion.run(); } }; - World skyBlockWorld = plugin.getWorldManager().getWorld(); + World skyBlockWorld = worldManager.getWorld(); ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(loc); if (region != null) { - for (Player player : WorldGuardHandler.getPlayersInRegion(plugin.getWorldManager().getWorld(), region)) { - if (player != null && player.isOnline() && plugin.getWorldManager().isSkyWorld(player.getWorld()) && !player.isFlying()) { + for (Player player : WorldGuardHandler.getPlayersInRegion(worldManager.getWorld(), region)) { + if (player != null && player.isOnline() && worldManager.isSkyWorld(player.getWorld()) && !player.isFlying()) { player.sendMessage(tr("\u00a7cThe island you are on is being deleted! Sending you to spawn.")); - plugin.getTeleportLogic().spawnTeleport(player, true); + teleportLogic.spawnTeleport(player, true); } } WorldEditHandler.clearIsland(skyBlockWorld, region, clearNether); } else { - log.log(Level.WARNING, "Trying to delete an island - with no WG region! ({0})", LocationUtil.asString(loc)); + logger.log(Level.WARNING, "Trying to delete an island - with no WG region! ({0})", LocationUtil.asString(loc)); clearNether.run(); } } private Location getNetherLocation(Location loc) { Location netherIsland = loc.clone(); - netherIsland.setWorld(plugin.getWorldManager().getNetherWorld()); - netherIsland.setY(loc.getY()/2); + netherIsland.setWorld(worldManager.getNetherWorld()); + netherIsland.setY(loc.getY() / 2); return netherIsland; } @@ -176,32 +213,32 @@ public void run() { final int pz = loc.getBlockZ(); final int py = 0; final int range = Math.max(Settings.island_protectionRange, Settings.island_distance) + 1; - final int radius = range/2; + final int radius = range / 2; // 5 sampling points... if (w.getBlockAt(px, py, pz).getType() == BEDROCK - || w.getBlockAt(px+radius, py, pz+radius).getType() == BEDROCK - || w.getBlockAt(px+radius, py, pz-radius).getType() == BEDROCK - || w.getBlockAt(px-radius, py, pz+radius).getType() == BEDROCK - || w.getBlockAt(px-radius, py, pz-radius).getType() == BEDROCK) - { + || w.getBlockAt(px + radius, py, pz + radius).getType() == BEDROCK + || w.getBlockAt(px + radius, py, pz - radius).getType() == BEDROCK + || w.getBlockAt(px - radius, py, pz + radius).getType() == BEDROCK + || w.getBlockAt(px - radius, py, pz - radius).getType() == BEDROCK) { sender.sendMessage(String.format("\u00a7c-----------------------------------\n\u00a7cFlatland detected under your island!\n\u00a7e Clearing it in %s, stay clear.\n\u00a7c-----------------------------------\n", TimeUtil.ticksAsString(delay))); - new WorldEditClearFlatlandTask(plugin, sender, new CuboidRegion(BlockVector3.at(px-radius, 0, pz-radius), - BlockVector3.at(px+radius, 4, pz+radius)), - "\u00a7eFlatland was cleared under your island (%s). Take care.").runTaskLater(plugin, delay); + new WorldEditClearFlatlandTask(scheduler, config, worldManager, logger, sender, + new CuboidRegion(BlockVector3.at(px - radius, 0, pz - radius), + BlockVector3.at(px + radius, 4, pz + radius)), + "\u00a7eFlatland was cleared under your island (%s). Take care.").runTaskLater(plugin, delay); } } }; if (Bukkit.isPrimaryThread()) { runnable.run(); } else { - plugin.sync(runnable); + scheduler.sync(runnable); } return false; } public void displayTopTen(final CommandSender sender, int page) { synchronized (ranks) { - int maxpage = (( ranks.size()-1) / 10) + 1; + int maxpage = ((ranks.size() - 1) / 10) + 1; if (page > maxpage) { page = maxpage; } @@ -222,23 +259,23 @@ public void displayTopTen(final CommandSender sender, int page) { if (playerInfo != null && playerInfo.getHasIsland()) { rank = getRank(playerInfo.locationForParty()); } - int offset = (page-1) * 10; + int offset = (page - 1) * 10; place += offset; - for (final IslandLevel level : ranks.subList(offset, Math.min(ranks.size(), 10*page))) { + for (final IslandLevel level : ranks.subList(offset, Math.min(ranks.size(), 10 * page))) { String members = ""; if (showMembers && !level.getMembers().isEmpty()) { - members = Arrays.toString(level.getMembers().toArray(new String[level.getMembers().size()])); + members = Arrays.toString(level.getMembers().toArray(new String[0])); } String message = String.format(tr("\u00a7a#%2d \u00a77(%5.2f): \u00a7e%s \u00a77%s"), - place, level.getScore(), level.getLeaderName(), members); + place, level.getScore(), level.getLeaderName(), members); if (sender instanceof Player target) { String warpString = getJsonWarpString( - message, - tr("Click to warp to the island!"), - String.format("/is w %s", level.getLeaderName()) + message, + tr("Click to warp to the island!"), + String.format("/is w %s", level.getLeaderName()) ); uSkyBlock.getInstance().execCommand(target, "console:tellraw " + - target.getName() + " " + warpString, false); + target.getName() + " " + warpString, false); } else { sender.sendMessage(message); } @@ -272,9 +309,9 @@ private String getJsonWarpString(String text, String hoverText, String command) public void showTopTen(final CommandSender sender, final int page) { long t = System.currentTimeMillis(); - if (t > (lastGenerate + (Settings.island_topTenTimeout*60000)) || (sender.hasPermission("usb.admin.topten") || sender.isOp())) { + if (t > (lastGenerate + (Settings.island_topTenTimeout * 60000)) || (sender.hasPermission("usb.admin.topten") || sender.isOp())) { lastGenerate = t; - plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + scheduler.async(() -> { generateTopTen(sender); displayTopTen(sender, page); }); @@ -289,13 +326,13 @@ public List getRanks(int offset, int length) { if (size <= offset) { return Collections.emptyList(); } - return ranks.subList(offset, Math.min(size-offset, length)); + return ranks.subList(offset, Math.min(size - offset, length)); } } public void generateTopTen(final CommandSender sender) { List topTen = new ArrayList<>(); - final String[] listOfFiles = directoryIslands.list(IslandUtil.createIslandFilenameFilter()); + final String[] listOfFiles = directoryIslands.toFile().list(IslandUtil.createIslandFilenameFilter()); for (String file : listOfFiles) { String islandName = FileUtil.getBasename(file); try { @@ -310,7 +347,7 @@ public void generateTopTen(final CommandSender sender) { cache.invalidate(islandName); } } catch (Exception e) { - plugin.getLogger().log(Level.WARNING, "Error during rank generation", e); + logger.log(Level.WARNING, "Error during rank generation", e); } } Collections.sort(topTen); @@ -329,15 +366,15 @@ private IslandLevel createIslandLevel(IslandInfo islandInfo, double level) { memberList.remove(partyLeader); List names = new ArrayList<>(); if (useDisplayNames) { - partyLeaderName = PlayerUtil.getPlayerDisplayName(partyLeader); - for (String name : memberList) { - String displayName = PlayerUtil.getPlayerDisplayName(name); - if (displayName != null) { - names.add(displayName); - } - } + partyLeaderName = playerDB.getDisplayName(partyLeader); + for (String name : memberList) { + String displayName = playerDB.getDisplayName(name); + if (displayName != null) { + names.add(displayName); + } + } } else { - names = memberList; + names = memberList; } return new IslandLevel(islandInfo.getName(), partyLeaderName, names, level); } @@ -376,7 +413,7 @@ public void updateRank(IslandInfo islandInfo, IslandScore score) { } public boolean hasIsland(Location loc) { - return loc == null || new File(directoryIslands, LocationUtil.getIslandName(loc) + ".yml").exists(); + return loc == null || new File(directoryIslands.toFile(), LocationUtil.getIslandName(loc) + ".yml").exists(); } public IslandRank getRank(String islandName) { @@ -384,7 +421,7 @@ public IslandRank getRank(String islandName) { for (int i = 0; i < rankList.size(); i++) { IslandLevel level = rankList.get(i); if (level.getIslandName().equalsIgnoreCase(islandName)) { - return new IslandRank(level, i+1); + return new IslandRank(level, i + 1); } } return null; @@ -419,7 +456,14 @@ public long flushCache() { } public int getSize() { - String[] list = directoryIslands.list(); - return list != null ? list.length : 0; + try (var stream = Files.list(directoryIslands)) { + return (int) stream.count(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public Path getIslandDirectory() { + return directoryIslands; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index 0ae7fbd56..f6e384877 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.island; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; @@ -15,8 +17,9 @@ import org.bukkit.entity.Villager; import org.bukkit.entity.WaterMob; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.HashMap; import java.util.LinkedHashMap; @@ -26,8 +29,10 @@ import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +@Singleton public class LimitLogic { - public enum CreatureType { UNKNOWN, ANIMAL, MONSTER, VILLAGER, GOLEM } + public enum CreatureType {UNKNOWN, ANIMAL, MONSTER, VILLAGER, GOLEM} + static { marktr("UNKNOWN"); marktr("ANIMAL"); @@ -36,10 +41,13 @@ public enum CreatureType { UNKNOWN, ANIMAL, MONSTER, VILLAGER, GOLEM } marktr("GOLEM"); } - private final uSkyBlock plugin; + private final WorldManager worldManager; + private final BlockLimitLogic blockLimitLogic; - public LimitLogic(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public LimitLogic(@NotNull WorldManager worldManager, @NotNull BlockLimitLogic blockLimitLogic) { + this.worldManager = worldManager; + this.blockLimitLogic = blockLimitLogic; } public Map getCreatureCount(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo) { @@ -51,9 +59,9 @@ public Map getCreatureCount(us.talabrek.ultimateskyblock. ProtectedRegion islandRegionAt = WorldGuardHandler.getIslandRegionAt(islandLocation); if (islandRegionAt != null) { // Nether and Overworld regions are more or less equal (same x,z coords) - List creatures = WorldGuardHandler.getCreaturesInRegion(plugin.getWorldManager().getWorld(), - islandRegionAt); - World nether = plugin.getWorldManager().getNetherWorld(); + List creatures = WorldGuardHandler.getCreaturesInRegion(worldManager.getWorld(), + islandRegionAt); + World nether = worldManager.getNetherWorld(); if (nether != null) { creatures.addAll(WorldGuardHandler.getCreaturesInRegion(nether, islandRegionAt)); } @@ -78,9 +86,9 @@ public Map getCreatureMax(us.talabrek.ultimateskyblock.ap public CreatureType getCreatureType(LivingEntity creature) { if (creature instanceof Monster - || creature instanceof WaterMob - || creature instanceof Slime - || creature instanceof Ghast) { + || creature instanceof WaterMob + || creature instanceof Slime + || creature instanceof Ghast) { return CreatureType.MONSTER; } else if (creature instanceof Animals) { return CreatureType.ANIMAL; @@ -94,10 +102,10 @@ public CreatureType getCreatureType(LivingEntity creature) { public CreatureType getCreatureType(EntityType entityType) { if (Monster.class.isAssignableFrom(entityType.getEntityClass()) - || WaterMob.class.isAssignableFrom(entityType.getEntityClass()) - || Slime.class.isAssignableFrom(entityType.getEntityClass()) - || Ghast.class.isAssignableFrom(entityType.getEntityClass()) - ) { + || WaterMob.class.isAssignableFrom(entityType.getEntityClass()) + || Slime.class.isAssignableFrom(entityType.getEntityClass()) + || Ghast.class.isAssignableFrom(entityType.getEntityClass()) + ) { return CreatureType.MONSTER; } else if (Animals.class.isAssignableFrom(entityType.getEntityClass())) { return CreatureType.ANIMAL; @@ -121,10 +129,14 @@ public boolean canSpawn(EntityType entityType, us.talabrek.ultimateskyblock.api. private int getMax(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo, CreatureType creatureType) { switch (creatureType) { - case ANIMAL: return islandInfo.getMaxAnimals(); - case MONSTER: return islandInfo.getMaxMonsters(); - case VILLAGER: return islandInfo.getMaxVillagers(); - case GOLEM: return islandInfo.getMaxGolems(); + case ANIMAL: + return islandInfo.getMaxAnimals(); + case MONSTER: + return islandInfo.getMaxMonsters(); + case VILLAGER: + return islandInfo.getMaxVillagers(); + case GOLEM: + return islandInfo.getMaxGolems(); } return Integer.MAX_VALUE; } @@ -139,21 +151,21 @@ public String getSummary(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo) } int cnt = count.containsKey(key) ? count.get(key) : 0; int max = creatureMax.get(key); - sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", tr(key.name()), cnt >= max ? tr("\u00a7c{0}",cnt) : cnt, max) + "\n"); + sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", tr(key.name()), cnt >= max ? tr("\u00a7c{0}", cnt) : cnt, max) + "\n"); } - Map blockLimits = plugin.getBlockLimitLogic().getLimits(); - for (Map.Entry entry : blockLimits.entrySet()) { - int blockCount = plugin.getBlockLimitLogic().getCount(entry.getKey(), islandInfo.getIslandLocation()); + Map blockLimits = blockLimitLogic.getLimits(); + for (Map.Entry entry : blockLimits.entrySet()) { + int blockCount = blockLimitLogic.getCount(entry.getKey(), islandInfo.getIslandLocation()); if (blockCount >= 0) { sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", - ItemStackUtil.getItemName(new ItemStack(entry.getKey())), - blockCount >= entry.getValue() ? tr("\u00a7c{0}", blockCount) : blockCount, - entry.getValue()) + "\n"); + ItemStackUtil.getItemName(new ItemStack(entry.getKey())), + blockCount >= entry.getValue() ? tr("\u00a7c{0}", blockCount) : blockCount, + entry.getValue()) + "\n"); } else { sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", - ItemStackUtil.getItemName(new ItemStack(entry.getKey())), - tr("\u00a7c{0}", "?"), - entry.getValue()) + "\n"); + ItemStackUtil.getItemName(new ItemStack(entry.getKey())), + tr("\u00a7c{0}", "?"), + entry.getValue()) + "\n"); } } return sb.toString().trim(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/OrphanLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/OrphanLogic.java index 0f0ab283b..b9cb6a2e2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/OrphanLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/OrphanLogic.java @@ -1,37 +1,52 @@ package us.talabrek.ultimateskyblock.island; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.file.FileUtil; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.Settings; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.bootstrap.PluginDataDir; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Responsible for storing, accessing and handling orphans. */ +@Singleton public class OrphanLogic { // Used in a HACKY way to indicate the origin of an island location as an orphan. public static final float ORPHAN_PITCH = -30; public static final float ORPHAN_YAW = 90; - private final uSkyBlock plugin; + private final Logger logger; + private final WorldManager worldManager; private final FileConfiguration config; private final File configFile; - private SortedSet orphaned = new TreeSet<>(new OrphanComparator()); - - public OrphanLogic(uSkyBlock plugin) { - this.plugin = plugin; - configFile = new File(plugin.getDataFolder(), "orphans.yml"); + private final SortedSet orphaned = new TreeSet<>(new OrphanComparator()); + + @Inject + public OrphanLogic( + @NotNull @PluginDataDir Path pluginDir, + @NotNull Logger logger, + @NotNull WorldManager worldManager + ) { + this.logger = logger; + this.worldManager = worldManager; + configFile = pluginDir.resolve("orphans.yml").toFile(); config = FileUtil.getYmlConfiguration("orphans.yml"); readOrphans(); } @@ -65,7 +80,7 @@ public void save() { try { config.save(configFile); } catch (IOException e) { - plugin.getLogger().warning("Unable to store orphans: " + e); + logger.log(Level.SEVERE, "Unable to store orphans", e); } } @@ -80,18 +95,19 @@ public void addOrphan(Location location) { } } - public Location getNextValidOrphan() { + // This is a hacky way to break the dependency cycle between OrphanLogic and IslandLocatorLogic. Refactor. + public @Nullable Location getNextValidOrphan(IslandLocatorLogic islandLocatorLogic) { if (orphaned.isEmpty()) { return null; } try { - World world = plugin.getWorldManager().getWorld(); + World world = worldManager.getWorld(); for (Iterator it = orphaned.iterator(); it.hasNext(); ) { Orphan candidate = it.next(); if (candidate != null) { it.remove(); Location loc = new Location(world, candidate.getX(), Settings.island_height, candidate.getZ(), ORPHAN_YAW, ORPHAN_PITCH); - if (plugin.getIslandLocatorLogic().isAvailableLocation(loc)) { + if (islandLocatorLogic.isAvailableLocation(loc)) { return loc; } } @@ -112,7 +128,7 @@ public boolean wasOrphan(Location loc) { } public List getOrphans() { - return Collections.unmodifiableList(new ArrayList<>(orphaned)); + return List.copyOf(orphaned); } public static class Orphan { @@ -139,7 +155,7 @@ public int getZ() { } public int distanceSquared() { - return x*x + z * z; + return x * x + z * z; } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java new file mode 100644 index 000000000..76c787f9f --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java @@ -0,0 +1,43 @@ +package us.talabrek.ultimateskyblock.island.level; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.island.task.RecalculateRunnable; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.time.Duration; + +import static dk.lockfuglsang.minecraft.util.TimeUtil.durationAsTicks; + +@Singleton +public class AutoIslandLevelRefresh { + + private final uSkyBlock plugin; + private final PluginConfig config; + + private BukkitTask autoRecalculateTask = null; + + @Inject + public AutoIslandLevelRefresh(@NotNull uSkyBlock plugin, @NotNull PluginConfig config) { + this.plugin = plugin; + this.config = config; + } + + public void startup() { + int refreshEveryMinute = config.getYamlConfig().getInt("options.island.autoRefreshScore", 0); + if (refreshEveryMinute > 0) { + long refreshTicks = durationAsTicks(Duration.ofMinutes(refreshEveryMinute)); + autoRecalculateTask = new RecalculateRunnable(plugin).runTaskTimer(plugin, refreshTicks, refreshTicks); + } + } + + public void shutdown() { + if (autoRecalculateTask != null) { + autoRecalculateTask.cancel(); + autoRecalculateTask = null; + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AweLevelLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AweLevelLogic.java index cd7147d94..32c68ad77 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AweLevelLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AweLevelLogic.java @@ -2,8 +2,10 @@ import org.bukkit.Location; import org.bukkit.configuration.file.FileConfiguration; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.HashSet; import java.util.Set; @@ -12,8 +14,8 @@ public class AweLevelLogic extends CommonLevelLogic { private Set running = new HashSet<>(); - public AweLevelLogic(uSkyBlock plugin, FileConfiguration config) { - super(plugin, config); + public AweLevelLogic(WorldManager worldManager, FileConfiguration config) { + super(config, worldManager); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java index c9ec97f7a..02ac60b3d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/ChunkSnapshotLevelLogic.java @@ -1,44 +1,70 @@ package us.talabrek.ultimateskyblock.island.level; +import com.google.inject.Inject; +import com.google.inject.Singleton; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import dk.lockfuglsang.minecraft.file.FileUtil; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.task.ChunkSnapShotTask; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.List; import java.util.logging.Level; +import java.util.logging.Logger; /** * Business logic regarding the calculation of level */ +@Singleton public class ChunkSnapshotLevelLogic extends CommonLevelLogic { - public ChunkSnapshotLevelLogic(uSkyBlock plugin, FileConfiguration config) { - super(plugin, config); + private final Plugin plugin; + private final PluginConfig pluginConfig; + private final Scheduler scheduler; + private final Logger logger; + + @Inject + public ChunkSnapshotLevelLogic( + @NotNull uSkyBlock plugin, + @NotNull WorldManager worldManager, + @NotNull PluginConfig pluginConfig, + @NotNull Scheduler scheduler, + @NotNull Logger logger + ) { + super(FileUtil.getYmlConfiguration("levelConfig.yml"), worldManager); + this.plugin = plugin; + this.pluginConfig = pluginConfig; + this.scheduler = scheduler; + this.logger = logger; } @Override public void calculateScoreAsync(final Location l, final Callback callback) { // TODO: 10/05/2015 - R4zorax: Ensure no overlapping calls to this one happen... - log.entering(CN, "calculateScoreAsync"); + logger.entering(this.getClass().getName(), "calculateScoreAsync"); // is further threading needed here? final ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(l); if (region == null) { return; } - new ChunkSnapShotTask(plugin, l, region, new Callback>() { + new ChunkSnapShotTask(scheduler, pluginConfig, l, region, new Callback<>() { @Override public void run() { final List snapshotsOverworld = getState(); Location netherLoc = getNetherLocation(l); final ProtectedRegion netherRegion = WorldGuardHandler.getNetherRegionAt(netherLoc); - new ChunkSnapShotTask(plugin, netherLoc, netherRegion, new Callback>() { + new ChunkSnapShotTask(scheduler, pluginConfig, netherLoc, netherRegion, new Callback<>() { @Override public void run() { final List snapshotsNether = getState(); @@ -57,8 +83,8 @@ public void run() { private void calculateScoreAndCallback(ProtectedRegion region, List snapshotsOverworld, ProtectedRegion netherRegion, List snapshotsNether, Callback callback) { IslandScore islandScore = calculateScore(region, snapshotsOverworld, netherRegion, snapshotsNether); callback.setState(islandScore); - plugin.sync(callback); - log.exiting(CN, "calculateScoreAsync"); + scheduler.sync(callback); + logger.exiting(this.getClass().getName(), "calculateScoreAsync"); } private IslandScore calculateScore(ProtectedRegion region, List snapshotsOverworld, ProtectedRegion netherRegion, List snapshotsNether) { @@ -75,7 +101,7 @@ private IslandScore calculateScore(ProtectedRegion region, List s ChunkSnapshot chunk = getChunkSnapshot(x >> 4, z >> 4, snapshotsOverworld); if (chunk == null) { // This should NOT happen! - log.log(Level.WARNING, "Missing chunk in snapshot for x,z = " + x + "," + z); + logger.log(Level.WARNING, "Missing chunk in snapshot for x,z = " + x + "," + z); continue; } int cx = (x & 0xf); @@ -101,7 +127,7 @@ private IslandScore calculateScore(ProtectedRegion region, List s ChunkSnapshot chunk = getChunkSnapshot(x >> 4, z >> 4, snapshotsNether); if (chunk == null) { // This should NOT happen! - log.log(Level.WARNING, "Missing nether-chunk in snapshot for x,z = " + x + "," + z); + logger.log(Level.WARNING, "Missing nether-chunk in snapshot for x,z = " + x + "," + z); continue; } int cx = (x & 0xf); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/CommonLevelLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/CommonLevelLogic.java index 66e0fff59..07e2bd3c7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/CommonLevelLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/CommonLevelLogic.java @@ -2,41 +2,39 @@ import org.bukkit.Location; import org.bukkit.configuration.file.FileConfiguration; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.api.model.BlockScore; import us.talabrek.ultimateskyblock.island.level.yml.LevelConfigYmlReader; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.util.List; -import java.util.logging.Logger; public abstract class CommonLevelLogic implements LevelLogic { - static final String CN = CommonLevelLogic.class.getName(); - protected static final Logger log = Logger.getLogger(CN); - protected final uSkyBlock plugin; - protected final FileConfiguration config; + FileConfiguration levelConfig; + private final WorldManager worldManager; BlockLevelConfigMap scoreMap; private final int pointsPerLevel; final int activateNetherAtLevel; - CommonLevelLogic(uSkyBlock plugin, FileConfiguration config) { - this.plugin = plugin; - this.config = config; - activateNetherAtLevel = config.getInt("nether.activate-at.level", 100); - pointsPerLevel = config.getInt("general.pointsPerLevel"); + CommonLevelLogic(FileConfiguration levelConfig, WorldManager worldManager) { + this.levelConfig = levelConfig; + activateNetherAtLevel = levelConfig.getInt("nether.activate-at.level", 100); + pointsPerLevel = levelConfig.getInt("general.pointsPerLevel"); + this.worldManager = worldManager; load(); } private void load() { - scoreMap = new LevelConfigYmlReader().readLevelConfig(config); + scoreMap = new LevelConfigYmlReader().readLevelConfig(levelConfig); } - Location getNetherLocation(Location l) { - Location netherLoc = l.clone(); - netherLoc.setWorld(plugin.getWorldManager().getNetherWorld()); - netherLoc.setY(Settings.nether_height); - return netherLoc; + Location getNetherLocation(Location location) { + Location netherLocation = location.clone(); + netherLocation.setWorld(worldManager.getNetherWorld()); + netherLocation.setY(Settings.nether_height); + return netherLocation; } IslandScore createIslandScore(BlockCountCollection blockCollection) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/ChunkSnapShotTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/ChunkSnapShotTask.java index 529f86bf8..19777e26d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/ChunkSnapShotTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/ChunkSnapShotTask.java @@ -6,10 +6,11 @@ import org.bukkit.Chunk; import org.bukkit.ChunkSnapshot; import org.bukkit.Location; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.api.async.Callback; import us.talabrek.ultimateskyblock.async.IncrementalRunnable; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; -import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import java.util.ArrayList; import java.util.List; @@ -20,10 +21,10 @@ public class ChunkSnapShotTask extends IncrementalRunnable { private final Location location; private final List chunks; - private List snapshots = new ArrayList<>(); + private final List snapshots = new ArrayList<>(); - public ChunkSnapShotTask(uSkyBlock plugin, Location location, ProtectedRegion region, final Callback> callback) { - super(plugin, callback); + public ChunkSnapShotTask(Scheduler scheduler, PluginConfig config, Location location, ProtectedRegion region, final Callback> callback) { + super(scheduler, config, callback); this.location = location; if (region != null) { chunks = new ArrayList<>(WorldEditHandler.getChunks(new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint()))); @@ -48,5 +49,4 @@ protected boolean execute() { } return chunks.isEmpty(); } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java index 32285da7b..a9b9739ae 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/SetBiomeTask.java @@ -26,7 +26,7 @@ public class SetBiomeTask extends IncrementalRunnable { private final Set chunks; public SetBiomeTask(uSkyBlock plugin, Location loc, Biome biome, Runnable onCompletion) { - super(plugin, onCompletion); + super(plugin.getScheduler(), plugin.getPluginConfig(), onCompletion); this.biome = biome; ProtectedRegion region = WorldGuardHandler.getIslandRegionAt(loc); if (region != null) { @@ -41,7 +41,7 @@ public SetBiomeTask(uSkyBlock plugin, Location loc, Biome biome, Runnable onComp } public SetBiomeTask(uSkyBlock plugin, World world, BlockVector3 minP, BlockVector3 maxP, Biome biome, Runnable onCompletion) { - super(plugin, onCompletion); + super(plugin.getScheduler(), plugin.getPluginConfig(), onCompletion); this.biome = biome; this.minP = minP; this.maxP = maxP; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java index 1a34d53af..231419c89 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java @@ -1,10 +1,13 @@ package us.talabrek.ultimateskyblock.menu; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.file.FileUtil; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.ArrayList; @@ -13,24 +16,27 @@ /** * A GUI for managing the uSkyBlock config-files */ +@Singleton public class ConfigMenu { - private final FileConfiguration menuConfig; - private final uSkyBlock plugin; - private final MenuItemFactory factory; - private final List editMenus = new ArrayList<>(); + private final List editMenus; private final MainConfigMenu mainMenu; - public ConfigMenu(uSkyBlock plugin) { - this.plugin = plugin; - menuConfig = new YamlConfiguration(); + @Inject + public ConfigMenu( + @NotNull uSkyBlock plugin, + @NotNull MenuItemFactory factory + ) { + FileConfiguration menuConfig = new YamlConfiguration(); FileUtil.readConfig(menuConfig, getClass().getClassLoader().getResourceAsStream("configmenu.yml")); - factory = new MenuItemFactory(); - mainMenu = new MainConfigMenu(plugin, menuConfig, factory, editMenus); - editMenus.add(new IntegerEditMenu(menuConfig, factory, mainMenu)); - editMenus.add(new BooleanEditMenu(menuConfig)); - editMenus.add(new StringEditMenu(menuConfig, mainMenu)); - editMenus.add(mainMenu); // mainMenu goes last (catch all) + this.editMenus = new ArrayList<>(); + this.mainMenu = new MainConfigMenu(plugin, menuConfig, factory, editMenus); + this.editMenus.addAll(List.of( + new IntegerEditMenu(menuConfig, factory, mainMenu), + new BooleanEditMenu(menuConfig), + new StringEditMenu(menuConfig, mainMenu), + mainMenu // mainMenu goes last (catch all) + )); } public void showMenu(Player player, String configName, int page) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java index ce7c07569..0f693311d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java @@ -5,7 +5,6 @@ import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 10edbae6e..72c940b63 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -1,6 +1,8 @@ package us.talabrek.ultimateskyblock.menu; import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; @@ -14,15 +16,23 @@ import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.profile.PlayerProfile; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; +import us.talabrek.ultimateskyblock.handler.ConfirmHandler; +import us.talabrek.ultimateskyblock.island.IslandGenerator; import us.talabrek.ultimateskyblock.island.IslandInfo; +import us.talabrek.ultimateskyblock.island.LimitLogic; import us.talabrek.ultimateskyblock.player.IslandPerk; +import us.talabrek.ultimateskyblock.player.PerkLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.GuiItemUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -45,11 +55,21 @@ /** * The UI menu of uSkyBlock (using the inventory UI). */ +@Singleton public class SkyBlockMenu { private final Pattern PERM_VALUE_PATTERN = Pattern.compile("(\\[(?(?[!])?[^\\]]+)\\])?(?.*)"); private final Pattern CHALLENGE_PAGE_HEADER = Pattern.compile(tr("Challenge Menu") + ".*\\((?

[0-9]+)/(?[0-9]+)\\)"); + private final uSkyBlock plugin; private final ChallengeLogic challengeLogic; + private final PluginConfig config; + private final PerkLogic perkLogic; + private final IslandGenerator islandGenerator; + private final LimitLogic limitLogic; + private final ConfirmHandler confirmHandler; + private final ConfigMenu configMenu; + private final Scheduler scheduler; + private final ItemStack sign = new ItemStack(Material.OAK_SIGN, 1); private final ItemStack biome = new ItemStack(Material.JUNGLE_SAPLING, 1); private final ItemStack lock = new ItemStack(Material.IRON_BARS, 1); @@ -84,9 +104,27 @@ public class SkyBlockMenu { the island leader.""")) ); - public SkyBlockMenu(uSkyBlock plugin, ChallengeLogic challengeLogic) { + @Inject + public SkyBlockMenu( + @NotNull uSkyBlock plugin, + @NotNull ChallengeLogic challengeLogic, + @NotNull PluginConfig config, + @NotNull PerkLogic perkLogic, + @NotNull IslandGenerator islandGenerator, + @NotNull LimitLogic limitLogic, + @NotNull ConfirmHandler confirmHandler, + @NotNull ConfigMenu configMenu, + @NotNull Scheduler scheduler + ) { this.plugin = plugin; this.challengeLogic = challengeLogic; + this.config = config; + this.perkLogic = perkLogic; + this.islandGenerator = islandGenerator; + this.limitLogic = limitLogic; + this.confirmHandler = confirmHandler; + this.configMenu = configMenu; + this.scheduler = scheduler; } public Inventory displayPartyPlayerGUI(final Player inventoryViewer, final PlayerProfile partyMember) { @@ -222,7 +260,7 @@ public Inventory displayLogGUI(final Player player) { } private void addExtraMenus(Player player, Inventory menu) { - ConfigurationSection extras = plugin.getConfig().getConfigurationSection("options.extra-menus"); + ConfigurationSection extras = config.getYamlConfig().getConfigurationSection("options.extra-menus"); if (extras == null) { return; } @@ -265,7 +303,7 @@ private void addExtraMenus(Player player, Inventory menu) { } private boolean isExtraMenuAction(Player player, ItemStack currentItem) { - ConfigurationSection extras = plugin.getConfig().getConfigurationSection("options.extra-menus"); + ConfigurationSection extras = config.getYamlConfig().getConfigurationSection("options.extra-menus"); if (extras == null || currentItem == null || currentItem.getItemMeta() == null) { return false; } @@ -360,7 +398,7 @@ public Inventory displayIslandGUI(final Player player) { } private Inventory createInitMenu(Player player) { - List schemeNames = plugin.getIslandGenerator().getSchemeNames(); + List schemeNames = islandGenerator.getSchemeNames(); int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d) * 9; String title = "\u00a79" + tr("Island Create Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); @@ -374,15 +412,15 @@ private Inventory createInitMenu(Player player) { menu.addItem(menuItem); lores.clear(); - if (plugin.getConfig().getBoolean("island-schemes-enabled", true) && schemeNames.size() > 1) { + if (config.getYamlConfig().getBoolean("island-schemes-enabled", true) && schemeNames.size() > 1) { int index = 1; for (String schemeName : schemeNames) { - IslandPerk islandPerk = plugin.getPerkLogic().getIslandPerk(schemeName); - boolean enabled = plugin.getConfig().getBoolean("island-schemes." + islandPerk.getSchemeName() + ".enabled", true); + IslandPerk islandPerk = perkLogic.getIslandPerk(schemeName); + boolean enabled = config.getYamlConfig().getBoolean("island-schemes." + islandPerk.getSchemeName() + ".enabled", true); if (!enabled) { continue; // Skip } - index = Math.max(plugin.getConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index), 1); + index = Math.max(config.getYamlConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index), 1); menuItem = islandPerk.getDisplayItem(); meta = requireNonNull(requireNonNull(menuItem.getItemMeta())); lores = meta.getLore(); @@ -423,7 +461,7 @@ private Inventory createInitMenu(Player player) { private int getMaxSchemeIndex(List schemeNames) { int index = 1; for (String schemeName : schemeNames) { - int nextIndex = plugin.getConfig().getInt("island-schemes." + schemeName + ".index", index); + int nextIndex = config.getYamlConfig().getInt("island-schemes." + schemeName + ".index", index); if (nextIndex > index) { index = nextIndex; } else { @@ -452,7 +490,7 @@ private Inventory createMainMenu(Player player) { meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lChallenges")); addLore(lores, "\u00a7f", tr("View a list of \u00a79challenges that\nyou can complete on your island\nto earn skybucks, items, perks,\nand titles.")); - if (plugin.getChallengeLogic().isEnabled()) { + if (challengeLogic.isEnabled()) { addLore(lores, tr("\u00a7e\u00a7lClick here to view challenges.")); } else { addLore(lores, tr("\u00a74\u00a7lChallenges disabled.")); @@ -466,7 +504,7 @@ private Inventory createMainMenu(Player player) { meta4 = requireNonNull(requireNonNull(menuItem.getItemMeta())); meta4.setDisplayName(tr("\u00a7a\u00a7lIsland Level")); addLore(lores, tr("\u00a7eCurrent Level: \u00a7a{0,number,##.#}", islandInfo.getLevel())); - addLore(lores, plugin.getLimitLogic().getSummary(islandInfo)); + addLore(lores, limitLogic.getSummary(islandInfo)); addLore(lores, "\u00a7f", tr("Gain island levels by expanding\nyour skyblock and completing\ncertain challenges. Rarer blocks\nwill add more to your level.\n\u00a7e\u00a7lClick here to refresh.\n\u00a7e\u00a7l(must be on island)")); meta4.setLore(lores); menuItem.setItemMeta(meta4); @@ -588,7 +626,7 @@ private Inventory createMainMenu(Player player) { menu.setItem(15, menuItem); lores.clear(); if (islandInfo.isLeader(player)) { - if (plugin.getConfig().getBoolean("island-schemes-enabled", true)) { + if (config.getYamlConfig().getBoolean("island-schemes-enabled", true)) { menuItem = new ItemStack(Material.PODZOL, 1); meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7c\u00a7lRestart Island")); @@ -608,7 +646,7 @@ private Inventory createMainMenu(Player player) { menuItem.setItemMeta(meta4); menu.setItem(17, menuItem); lores.clear(); - long millisLeft = plugin.getConfirmHandler().millisLeft(player, "/is leave"); + long millisLeft = confirmHandler.millisLeft(player, "/is leave"); if (millisLeft > 0) { updateLeaveMenuItemTimer(player, menu, menuItem); } @@ -645,7 +683,7 @@ public void onClick(InventoryClickEvent event) { } else if (inventoryName.equalsIgnoreCase(stripFormatting(tr("Island Restart Menu")))) { onClickRestartMenu(event, p, meta, slotIndex, currentItem); } else if (inventoryName.startsWith(stripFormatting(tr("Config:"))) && event.getWhoClicked() instanceof Player) { - plugin.getConfigMenu().onClick(event); + configMenu.onClick(event); } } @@ -655,9 +693,9 @@ private void onClickRestartMenu(final InventoryClickEvent event, final Player p, p.openInventory(createMainMenu(p)); } else if (currentItem != null && meta != null && meta.hasDisplayName()) { String schemeName = stripFormatting(meta.getDisplayName()); - IslandPerk islandPerk = plugin.getPerkLogic().getIslandPerk(schemeName); - if (plugin.getPerkLogic().getSchemes(p).contains(schemeName) && p.hasPermission(islandPerk.getPermission())) { - if (plugin.getConfirmHandler().millisLeft(p, "/is restart") > 0) { + IslandPerk islandPerk = perkLogic.getIslandPerk(schemeName); + if (perkLogic.getSchemes(p).contains(schemeName) && p.hasPermission(islandPerk.getPermission())) { + if (confirmHandler.millisLeft(p, "/is restart") > 0) { p.performCommand("island restart " + schemeName); } else { p.performCommand("island restart " + schemeName); @@ -669,16 +707,16 @@ private void onClickRestartMenu(final InventoryClickEvent event, final Player p, private void updateRestartMenuTimer(final Player p, final Inventory inventory) { final BukkitTask[] hackySharing = new BukkitTask[1]; - hackySharing[0] = plugin.sync(() -> { + hackySharing[0] = scheduler.sync(() -> { if (inventory.getViewers().contains(p)) { - updateRestartMenu(inventory, p, plugin.getIslandGenerator().getSchemeNames()); + updateRestartMenu(inventory, p, islandGenerator.getSchemeNames()); } - if (plugin.getConfirmHandler().millisLeft(p, "/is restart") <= 0 || !inventory.getViewers().contains(p)) { + if (confirmHandler.millisLeft(p, "/is restart") <= 0 || !inventory.getViewers().contains(p)) { if (hackySharing.length > 0 && hackySharing[0] != null) { hackySharing[0].cancel(); } } - }, 0, 1000); + }, Duration.ZERO, Duration.ofSeconds(1)); } private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta meta, int slotIndex, int menuSize) { @@ -691,7 +729,7 @@ private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta met p.performCommand("island accept"); } else if (meta != null && meta.hasDisplayName()) { String schemeName = stripFormatting(meta.getDisplayName()); - if (plugin.getPerkLogic().getSchemes(p).contains(schemeName)) { + if (perkLogic.getSchemes(p).contains(schemeName)) { p.performCommand("island create " + schemeName); } else { p.sendMessage(tr("\u00a7eYou do not have access to that island-schematic!")); @@ -736,10 +774,10 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P p.performCommand("island lock"); p.performCommand("island"); } else if (slotIndex == 17) { - if (islandInfo.isLeader(p) && plugin.getConfig().getBoolean("island-schemes-enabled", true)) { + if (islandInfo.isLeader(p) && config.getYamlConfig().getBoolean("island-schemes-enabled", true)) { p.openInventory(createRestartGUI(p)); } else { - if (plugin.getConfirmHandler().millisLeft(p, "/is leave") > 0) { + if (confirmHandler.millisLeft(p, "/is leave") > 0) { p.performCommand("island leave"); } else { p.performCommand("island leave"); @@ -755,8 +793,8 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P private void updateLeaveMenuItemTimer(final Player p, final Inventory inventory, final ItemStack currentItem) { final BukkitTask[] hackySharing = new BukkitTask[1]; - hackySharing[0] = plugin.sync(() -> { - long millisLeft = plugin.getConfirmHandler().millisLeft(p, "/is leave"); + hackySharing[0] = scheduler.sync(() -> { + long millisLeft = confirmHandler.millisLeft(p, "/is leave"); if (inventory.getViewers().contains(p)) { updateLeaveMenuItem(inventory, currentItem, millisLeft); } @@ -765,7 +803,7 @@ private void updateLeaveMenuItemTimer(final Player p, final Inventory inventory, hackySharing[0].cancel(); } } - }, 0, 1000); + }, Duration.ZERO, Duration.ofSeconds(1)); } private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, long millisLeft) { @@ -785,7 +823,7 @@ private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, lon } public Inventory createRestartGUI(Player player) { - List schemeNames = plugin.getIslandGenerator().getSchemeNames(); + List schemeNames = islandGenerator.getSchemeNames(); int menuSize = (int) Math.ceil(getMaxSchemeIndex(schemeNames) / 9d) * 9; String title = "\u00a79" + tr("Island Restart Menu"); Inventory menu = Bukkit.createInventory(new UltimateHolder(player, title, MenuType.DEFAULT), menuSize, title); @@ -799,7 +837,7 @@ public Inventory createRestartGUI(Player player) { lores.clear(); updateRestartMenu(menu, player, schemeNames); - if (plugin.getConfirmHandler().millisLeft(player, "/is restart") > 0) { + if (confirmHandler.millisLeft(player, "/is restart") > 0) { updateRestartMenuTimer(player, menu); } return menu; @@ -811,12 +849,12 @@ private void updateRestartMenu(Inventory menu, Player player, List schem List lores; int index = 1; for (String schemeName : schemeNames) { - IslandPerk islandPerk = plugin.getPerkLogic().getIslandPerk(schemeName); - boolean enabled = plugin.getConfig().getBoolean("island-schemes." + islandPerk.getSchemeName() + ".enabled", true); + IslandPerk islandPerk = perkLogic.getIslandPerk(schemeName); + boolean enabled = config.getYamlConfig().getBoolean("island-schemes." + islandPerk.getSchemeName() + ".enabled", true); if (!enabled) { continue; // Skip } - index = plugin.getConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index); + index = config.getYamlConfig().getInt("island-schemes." + islandPerk.getSchemeName() + ".index", index); menuItem = islandPerk.getDisplayItem(); meta = requireNonNull(menuItem.getItemMeta()); lores = meta.getLore(); @@ -824,7 +862,7 @@ private void updateRestartMenu(Inventory menu, Player player, List schem lores = new ArrayList<>(); } if (player.hasPermission(islandPerk.getPermission())) { - long millisLeft = plugin.getConfirmHandler().millisLeft(player, "/is restart"); + long millisLeft = confirmHandler.millisLeft(player, "/is restart"); if (millisLeft > 0) { addLore(lores, tr("\u00a7cClick within \u00a79{0}\u00a7c to restart!", TimeUtil.millisAsString(millisLeft))); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java index 48b864048..3954f6666 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/NotificationManager.java @@ -1,24 +1,25 @@ package us.talabrek.ultimateskyblock.player; +import com.google.inject.Inject; import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import us.talabrek.ultimateskyblock.uSkyBlock; public class NotificationManager { - private final uSkyBlock plugin; private final BukkitAudiences audiences; private LegacyComponentSerializer legacySerializer; - public NotificationManager(uSkyBlock plugin) { - this.plugin = plugin; + @Inject + public NotificationManager(Plugin plugin) { audiences = BukkitAudiences.create(plugin); } /** * Gets a {@link LegacyComponentSerializer} configured for uSkyBlock's (translatable) messages. + * * @return LegacyComponentSerializer configured for uSkyblock's (translatable) messages. */ public @NotNull LegacyComponentSerializer getLegacySerializer() { @@ -30,7 +31,8 @@ public NotificationManager(uSkyBlock plugin) { /** * Sends the given {@link String} as message to the {@link Player}'s ActionBar. - * @param player Player to send the given message to + * + * @param player Player to send the given message to * @param message Message to send to the given player */ public void sendActionBar(@NotNull Player player, @NotNull String message) { @@ -39,7 +41,8 @@ public void sendActionBar(@NotNull Player player, @NotNull String message) { /** * Sends the given {@link Component} as message to the {@link Player}'s ActionBar. - * @param player Player to send the given message to + * + * @param player Player to send the given message to * @param component Component to send to the given player */ public void sendActionBar(@NotNull Player player, @NotNull Component component) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java index e622913f4..a0a49ac22 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PerkLogic.java @@ -1,13 +1,16 @@ package us.talabrek.ultimateskyblock.player; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.island.IslandGenerator; -import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import java.util.Arrays; import java.util.Collections; @@ -20,26 +23,29 @@ /** * Responsible for calculating player specific perks based on permissions. */ +@Singleton public class PerkLogic { - private final uSkyBlock plugin; private final Perk defaultPerk; - private Map donorPerks; - private Map islandPerks; - - public PerkLogic(uSkyBlock plugin, IslandGenerator islandGenerator) { - this.plugin = plugin; + private final Map donorPerks; + private final Map islandPerks; + + @Inject + public PerkLogic( + @NotNull IslandGenerator islandGenerator, + @NotNull PluginConfig config + ) { defaultPerk = new Perk(Collections.emptyList(), Settings.general_maxPartySize, - plugin.getConfig().getInt("options.island.spawn-limits.animals", 30), - plugin.getConfig().getInt("options.island.spawn-limits.monsters", 50), - plugin.getConfig().getInt("options.island.spawn-limits.villagers", 16), - plugin.getConfig().getInt("options.island.spawn-limits.golems", 4), - 0, - 0, - null, null); + config.getYamlConfig().getInt("options.island.spawn-limits.animals", 30), + config.getYamlConfig().getInt("options.island.spawn-limits.monsters", 50), + config.getYamlConfig().getInt("options.island.spawn-limits.villagers", 16), + config.getYamlConfig().getInt("options.island.spawn-limits.golems", 4), + 0, + 0, + null, null); donorPerks = new ConcurrentHashMap<>(); - addDonorPerks(null, plugin.getConfig().getConfigurationSection("donor-perks")); - addExtraPermissionPerks(plugin.getConfig().getConfigurationSection("options.island.extraPermissions")); - addPartyPermissionPerks(null, plugin.getConfig().getConfigurationSection("options.party.maxPartyPermissions")); + addDonorPerks(null, config.getYamlConfig().getConfigurationSection("donor-perks")); + addExtraPermissionPerks(config.getYamlConfig().getConfigurationSection("options.island.extraPermissions")); + addPartyPermissionPerks(null, config.getYamlConfig().getConfigurationSection("options.party.maxPartyPermissions")); addHungerPerms(); addDonorRewardPerks(); List schemeNames = islandGenerator.getSchemeNames(); @@ -47,37 +53,37 @@ public PerkLogic(uSkyBlock plugin, IslandGenerator islandGenerator) { islandPerks = new ConcurrentHashMap<>(); - ConfigurationSection islandSchemes = plugin.getConfig().getConfigurationSection("island-schemes"); + ConfigurationSection islandSchemes = config.getYamlConfig().getConfigurationSection("island-schemes"); if (islandSchemes != null) { for (String schemeName : islandSchemes.getKeys(false)) { - ConfigurationSection config = islandSchemes.getConfigurationSection(schemeName); - String perm = config.getString("permission", "usb.schematic." + schemeName); + ConfigurationSection configSection = islandSchemes.getConfigurationSection(schemeName); + String perm = configSection.getString("permission", "usb.schematic." + schemeName); Perk perk = new PerkBuilder() - .schematics(schemeName) - .maxPartySize(config.getInt("maxPartySize", 0)) - .animals(config.getInt("animals", 0)) - .monsters(config.getInt("monsters", 0)) - .villagers(config.getInt("villagers", 0)) - .golems(config.getInt("golems", 0)) - .rewBonus(config.getInt("rewardBonus", 0)) - .hungerReduction(config.getInt("hungerReduction", 0)) - .extraItems(ItemStackUtil.createItemList(config.getStringList("extraItems"))) - .build(); + .schematics(schemeName) + .maxPartySize(configSection.getInt("maxPartySize", 0)) + .animals(configSection.getInt("animals", 0)) + .monsters(configSection.getInt("monsters", 0)) + .villagers(configSection.getInt("villagers", 0)) + .golems(configSection.getInt("golems", 0)) + .rewBonus(configSection.getInt("rewardBonus", 0)) + .hungerReduction(configSection.getInt("hungerReduction", 0)) + .extraItems(ItemStackUtil.createItemList(configSection.getStringList("extraItems"))) + .build(); ItemStack itemStack = ItemStackUtil.createItemStack( - config.getString("displayItem", Material.OAK_SAPLING.toString()), - schemeName, - config.getString("description", null) + configSection.getString("displayItem", Material.OAK_SAPLING.toString()), + schemeName, + configSection.getString("description", null) ); islandPerks.put(schemeName, new IslandPerk(schemeName, perm, itemStack, perk, - config.getDouble("scoreMultiply", 1d), config.getDouble("scoreOffset", 0d))); + configSection.getDouble("scoreMultiply", 1d), configSection.getDouble("scoreOffset", 0d))); } } for (String schemeName : schemeNames) { Perk perk = new PerkBuilder(defaultPerk).schematics(schemeName).build(); if (!islandPerks.containsKey(schemeName)) { islandPerks.put(schemeName, new IslandPerk(schemeName, "usb.schematic." + schemeName, - ItemStackUtil.createItemStack(Material.OAK_SAPLING.toString(), schemeName, null), perk, - 1d, 0d)); + ItemStackUtil.createItemStack(Material.OAK_SAPLING.toString(), schemeName, null), perk, + 1d, 0d)); } } } @@ -105,7 +111,7 @@ public IslandPerk getIslandPerk(String schemeName) { return islandPerks.get(schemeName); } return new IslandPerk(schemeName, "usb.schematic." + schemeName, - ItemStackUtil.createItemStack(Material.GRASS_BLOCK.toString(), schemeName, null), defaultPerk); + ItemStackUtil.createItemStack(Material.GRASS_BLOCK.toString(), schemeName, null), defaultPerk); } private Perk createPerk(Player player) { @@ -128,15 +134,15 @@ private void addDonorPerks(String perm, ConfigurationSection config) { } else { // Read leaf donorPerks.put(perm, new Perk( - ItemStackUtil.createItemList(config.getStringList("extraItems")), - config.getInt("maxPartySize", defaultPerk.getMaxPartySize()), - config.getInt("animals", defaultPerk.getAnimals()), - config.getInt("monsters", defaultPerk.getMonsters()), - config.getInt("villagers", defaultPerk.getVillagers()), - config.getInt("golems", defaultPerk.getGolems()), - config.getDouble("rewardBonus", defaultPerk.getRewBonus()), - config.getDouble("hungerReduction", defaultPerk.getHungerReduction()), - config.getStringList("schematics"), null)); + ItemStackUtil.createItemList(config.getStringList("extraItems")), + config.getInt("maxPartySize", defaultPerk.getMaxPartySize()), + config.getInt("animals", defaultPerk.getAnimals()), + config.getInt("monsters", defaultPerk.getMonsters()), + config.getInt("villagers", defaultPerk.getVillagers()), + config.getInt("golems", defaultPerk.getGolems()), + config.getDouble("rewardBonus", defaultPerk.getRewBonus()), + config.getDouble("hungerReduction", defaultPerk.getHungerReduction()), + config.getStringList("schematics"), null)); } } } @@ -150,20 +156,20 @@ private void addExtraPermissionPerks(ConfigurationSection config) { if (items != null && !items.isEmpty()) { String perm = "usb." + key; donorPerks.put(perm, new PerkBuilder(donorPerks.get(perm)) - .extraItems(items) - .build()); + .extraItems(items) + .build()); } } } private void addPartyPermissionPerks(String perm, ConfigurationSection config) { int[] values = {5, 6, 7, 8}; - String[] perms = {"usb.extra.partysize1","usb.extra.partysize2","usb.extra.partysize3","usb.extra.partysize"}; + String[] perms = {"usb.extra.partysize1", "usb.extra.partysize2", "usb.extra.partysize3", "usb.extra.partysize"}; for (int i = 0; i < values.length; i++) { donorPerks.put(perms[i], - new PerkBuilder(donorPerks.get(perms[i])) - .maxPartySize(values[i]) - .build()); + new PerkBuilder(donorPerks.get(perms[i])) + .maxPartySize(values[i]) + .build()); } if (config == null) { @@ -175,8 +181,8 @@ private void addPartyPermissionPerks(String perm, ConfigurationSection config) { } else if (config.isInt(key)) { // Read leaf donorPerks.put(perm, new PerkBuilder(donorPerks.get(perm)) - .maxPartySize(config.getInt(key, 0)) - .build()); + .maxPartySize(config.getInt(key, 0)) + .build()); } } } @@ -186,9 +192,9 @@ private void addHungerPerms() { String[] perms = {"usb.extra.hunger4", "usb.extra.hunger3", "usb.extra.hunger2", "usb.extra.hunger"}; for (int i = 0; i < values.length; i++) { donorPerks.put(perms[i], - new PerkBuilder(donorPerks.get(perms[i])) - .hungerReduction(values[i]) - .build()); + new PerkBuilder(donorPerks.get(perms[i])) + .hungerReduction(values[i]) + .build()); } } @@ -198,9 +204,9 @@ private void addDonorRewardPerks() { String[] perms = {"group.memberplus", "usb.donor.all", "usb.donor.25", "usb.donor.50", "usb.donor.75", "usb.donor.100"}; for (int i = 0; i < values.length; i++) { donorPerks.put(perms[i], - new PerkBuilder(donorPerks.get(perms[i])) - .rewBonus(values[i]) - .build()); + new PerkBuilder(donorPerks.get(perms[i])) + .rewBonus(values[i]) + .build()); } } @@ -211,8 +217,8 @@ private void addSchemePerks(List schemeNames) { for (String scheme : schemeNames) { String perm = "usb.schematic." + scheme; donorPerks.put(perm, new PerkBuilder(donorPerks.get(perm)) - .schematics(scheme) - .build()); + .schematics(scheme) + .build()); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index e9e7eee9e..18778bdb4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.Serial; import java.io.Serializable; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -57,13 +58,15 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private boolean islandGenerating = false; private boolean dirty = false; - public PlayerInfo(String currentPlayerName, UUID playerUUID, uSkyBlock plugin) { + public PlayerInfo(String currentPlayerName, UUID playerUUID, uSkyBlock plugin, Path playerDataDirectory) { this.plugin = plugin; this.uuid = playerUUID; this.playerName = currentPlayerName; // Prefer UUID over Name - playerConfigFile = new File(uSkyBlock.getInstance().directoryPlayers, UUIDUtil.asString(playerUUID) + ".yml"); - File nameFile = new File(uSkyBlock.getInstance().directoryPlayers, playerName + ".yml"); + // TODO: decouple serialization from player data. + // TODO: remove legacy player name support - all data should be converted by now. + playerConfigFile = playerDataDirectory.resolve(UUIDUtil.asString(playerUUID) + ".yml").toFile(); + File nameFile = playerDataDirectory.resolve(playerName + ".yml").toFile(); if (!playerConfigFile.exists() && nameFile.exists() && !currentPlayerName.equals(PlayerDB.UNKNOWN_PLAYER_NAME)) { nameFile.renameTo(playerConfigFile); } @@ -222,11 +225,11 @@ private PlayerInfo loadPlayer() { this.displayName = playerData.getString("player.displayName", playerName); this.uuid = UUIDUtil.fromString(playerData.getString("player.uuid", null)); this.islandLocation = new Location(uSkyBlock.getInstance().getWorldManager().getWorld(), - playerData.getInt("player.islandX"), playerData.getInt("player.islandY"), playerData.getInt("player.islandZ")); + playerData.getInt("player.islandX"), playerData.getInt("player.islandY"), playerData.getInt("player.islandZ")); this.homeLocation = new Location(uSkyBlock.getInstance().getWorldManager().getWorld(), - playerData.getInt("player.homeX") + 0.5, playerData.getInt("player.homeY") + 0.2, playerData.getInt("player.homeZ") + 0.5, - (float) playerData.getDouble("player.homeYaw", 0.0), - (float) playerData.getDouble("player.homePitch", 0.0)); + playerData.getInt("player.homeX") + 0.5, playerData.getInt("player.homeY") + 0.2, playerData.getInt("player.homeZ") + 0.5, + (float) playerData.getDouble("player.homeYaw", 0.0), + (float) playerData.getDouble("player.homePitch", 0.0)); log.exiting(CN, "loadPlayer"); return this; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java index fe8d304af..0eecc19a7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java @@ -4,15 +4,25 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.bootstrap.PluginDataDir; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; +import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; import us.talabrek.ultimateskyblock.uuid.PlayerDB; +import us.talabrek.ultimateskyblock.world.WorldManager; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.logging.Level; @@ -23,38 +33,70 @@ /** * Holds the active players */ +@Singleton public class PlayerLogic { - private static final Logger log = Logger.getLogger(PlayerLogic.class.getName()); - private static final PlayerInfo UNKNOWN_PLAYER = new PlayerInfo(PlayerDB.UNKNOWN_PLAYER_NAME, PlayerDB.UNKNOWN_PLAYER_UUID, uSkyBlock.getInstance()); private final LoadingCache playerCache; private final uSkyBlock plugin; private final BukkitTask saveTask; private final PlayerDB playerDB; + private final PerkLogic perkLogic; + private final IslandLogic islandLogic; + private final WorldManager worldManager; + private final TeleportLogic teleportLogic; + private final Scheduler scheduler; private final NotificationManager notificationManager; - - public PlayerLogic(uSkyBlock plugin) { + private final Logger logger; + private final Path playerDataDirectory; + + @Inject + public PlayerLogic( + @NotNull uSkyBlock plugin, + @NotNull PluginConfig config, + @NotNull PlayerDB playerDB, + @NotNull Logger logger, + @NotNull PerkLogic perkLogic, + @NotNull IslandLogic islandLogic, + @NotNull WorldManager worldManager, + @NotNull TeleportLogic teleportLogic, + @NotNull Scheduler scheduler, + @NotNull NotificationManager notificationManager, + @NotNull @PluginDataDir Path pluginDataDir + ) { this.plugin = plugin; - playerDB = plugin.getPlayerDB(); - playerCache = CacheBuilder - .from(plugin.getConfig().getString("options.advanced.playerCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) - .removalListener((RemovalListener) removal -> { - log.fine("Removing player-info for " + removal.getKey() + " from cache"); - PlayerInfo playerInfo = removal.getValue(); - if (playerInfo.isDirty()) { - playerInfo.saveToFile(); - } - }) - .build(new CacheLoader<>() { - @Override - public @NotNull PlayerInfo load(@NotNull UUID s) { - log.fine("Loading player-info from " + s + " into cache!"); - return loadPlayerData(s); - } + this.playerDB = playerDB; + this.perkLogic = perkLogic; + this.islandLogic = islandLogic; + this.worldManager = worldManager; + this.teleportLogic = teleportLogic; + this.scheduler = scheduler; + this.notificationManager = notificationManager; + this.logger = logger; + this.playerDataDirectory = pluginDataDir.resolve("players"); + try { + Files.createDirectories(playerDataDirectory); + } catch (IOException e) { + logger.log(Level.SEVERE, "Failed to create player data directory", e); + } + + this.playerCache = CacheBuilder + .from(config.getYamlConfig().getString("options.advanced.playerCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) + .removalListener((RemovalListener) removal -> { + logger.fine("Removing player-info for " + removal.getKey() + " from cache"); + PlayerInfo playerInfo = removal.getValue(); + if (playerInfo.isDirty()) { + playerInfo.saveToFile(); + } + }) + .build(new CacheLoader<>() { + @Override + public @NotNull PlayerInfo load(@NotNull UUID s) { + logger.fine("Loading player-info from " + s + " into cache!"); + return loadPlayerData(s); } - ); - long every = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.advanced.player.saveEvery", 2*60)); - saveTask = plugin.async(this::saveDirtyToFiles, every, every); - notificationManager = new NotificationManager(plugin); + } + ); + Duration every = Duration.ofSeconds(plugin.getConfig().getInt("options.advanced.player.saveEvery", 2 * 60)); + this.saveTask = scheduler.async(this::saveDirtyToFiles, every, every); } private void saveDirtyToFiles() { @@ -67,12 +109,16 @@ private void saveDirtyToFiles() { } private PlayerInfo loadPlayerData(UUID uuid) { - if (UNKNOWN_PLAYER.getUniqueId().equals(uuid)) { - return UNKNOWN_PLAYER; + if (PlayerDB.UNKNOWN_PLAYER_UUID.equals(uuid)) { + return loadUnknownPlayer(); } return loadPlayerData(uuid, playerDB.getName(uuid)); } + private PlayerInfo loadUnknownPlayer() { + return new PlayerInfo(PlayerDB.UNKNOWN_PLAYER_NAME, PlayerDB.UNKNOWN_PLAYER_UUID, plugin, playerDataDirectory); + } + private PlayerInfo loadPlayerData(UUID playerUUID, String playerName) { if (playerUUID == null) { playerUUID = PlayerDB.UNKNOWN_PLAYER_UUID; @@ -80,43 +126,40 @@ private PlayerInfo loadPlayerData(UUID playerUUID, String playerName) { if (playerName == null) { playerName = "__UNKNOWN__"; } - log.log(Level.FINER, "Loading player data for " + playerUUID + "/" + playerName); + logger.log(Level.FINER, "Loading player data for " + playerUUID + "/" + playerName); - final PlayerInfo playerInfo = new PlayerInfo(playerName, playerUUID, plugin); + final PlayerInfo playerInfo = new PlayerInfo(playerName, playerUUID, plugin, playerDataDirectory); final Player onlinePlayer = uSkyBlock.getInstance().getPlayerDB().getPlayer(playerUUID); if (onlinePlayer != null && onlinePlayer.isOnline()) { if (playerInfo.getHasIsland()) { IslandInfo islandInfo = plugin.getIslandInfo(playerInfo); if (islandInfo != null) { - islandInfo.updatePermissionPerks(onlinePlayer, plugin.getPerkLogic().getPerk(onlinePlayer)); + islandInfo.updatePermissionPerks(onlinePlayer, perkLogic.getPerk(onlinePlayer)); } } - plugin.sync(new Runnable() { - @Override - public void run() { - if (playerInfo.getHasIsland()) { - WorldGuardHandler.protectIsland(onlinePlayer, playerInfo); - plugin.getIslandLogic().clearFlatland(onlinePlayer, playerInfo.getIslandLocation(), 400); - } - if (plugin.getWorldManager().isSkyAssociatedWorld(onlinePlayer.getWorld()) && !plugin.playerIsOnIsland(onlinePlayer)) { - // Check if banned - String islandName = WorldGuardHandler.getIslandNameAt(onlinePlayer.getLocation()); - IslandInfo islandInfo = plugin.getIslandInfo(islandName); - if (islandInfo != null && islandInfo.isBanned(onlinePlayer)) { - onlinePlayer.sendMessage(tr("\u00a7eYou have been §cBANNED§e from {0}§e''s island.", islandInfo.getLeader()), - tr("\u00a7eSending you to spawn.")); - plugin.getTeleportLogic().spawnTeleport(onlinePlayer, true); - } else if (islandInfo != null && islandInfo.isLocked()) { - if (!onlinePlayer.hasPermission("usb.mod.bypassprotection")) { - onlinePlayer.sendMessage(tr("\u00a7eThe island has been §cLOCKED§e.", islandInfo.getLeader()), - tr("\u00a7eSending you to spawn.")); - plugin.getTeleportLogic().spawnTeleport(onlinePlayer, true); - } - } + scheduler.sync(() -> { + if (playerInfo.getHasIsland()) { + WorldGuardHandler.protectIsland(onlinePlayer, playerInfo); + islandLogic.clearFlatland(onlinePlayer, playerInfo.getIslandLocation(), 400); + } + if (worldManager.isSkyAssociatedWorld(onlinePlayer.getWorld()) && !plugin.playerIsOnIsland(onlinePlayer)) { + // Check if banned + String islandName = WorldGuardHandler.getIslandNameAt(onlinePlayer.getLocation()); + IslandInfo islandInfo = plugin.getIslandInfo(islandName); + if (islandInfo != null && islandInfo.isBanned(onlinePlayer)) { + onlinePlayer.sendMessage(tr("\u00a7eYou have been §cBANNED§e from {0}§e''s island.", islandInfo.getLeader()), + tr("\u00a7eSending you to spawn.")); + teleportLogic.spawnTeleport(onlinePlayer, true); + } else if (islandInfo != null && islandInfo.isLocked()) { + if (!onlinePlayer.hasPermission("usb.mod.bypassprotection")) { + onlinePlayer.sendMessage(tr("\u00a7eThe island has been §cLOCKED§e.", islandInfo.getLeader()), + tr("\u00a7eSending you to spawn.")); + teleportLogic.spawnTeleport(onlinePlayer, true); } } } + } ); } return playerInfo; @@ -143,12 +186,7 @@ public PlayerInfo getPlayerInfo(UUID uuid) { } public void loadPlayerDataAsync(final Player player) { - plugin.async(new Runnable() { - @Override - public void run() { - playerCache.refresh(player.getUniqueId()); - } - }); + scheduler.async(() -> playerCache.refresh(player.getUniqueId())); } public void removeActivePlayer(PlayerInfo pi) { @@ -168,8 +206,11 @@ public long flushCache() { } public int getSize() { - String[] list = plugin.directoryPlayers.list(); - return list != null ? list.length : 0; + try (var stream = Files.list(playerDataDirectory)) { + return (int) stream.count(); + } catch (IOException e) { + throw new RuntimeException(e); + } } public @NotNull NotificationManager getNotificationManager() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java index 7fb1e4b53..14fbcda4b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java @@ -3,8 +3,11 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import org.bukkit.configuration.file.FileConfiguration; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -13,23 +16,25 @@ /** * Notifier that tries to minimize spam. */ +@Singleton public class PlayerNotifier { private final long maxSpam; private final LoadingCache cache = CacheBuilder - .newBuilder() - .expireAfterAccess(10, TimeUnit.SECONDS) - .maximumSize(500) - .build( - new CacheLoader() { - @Override - public NotifyMessage load(UUID uuid) throws Exception { - return new NotifyMessage(null, 0); - } - } - ); + .newBuilder() + .expireAfterAccess(10, TimeUnit.SECONDS) + .maximumSize(500) + .build( + new CacheLoader<>() { + @Override + public @NotNull NotifyMessage load(@NotNull UUID uuid) { + return new NotifyMessage(null, 0); + } + } + ); - public PlayerNotifier(FileConfiguration config) { - maxSpam = config.getInt("general.maxSpam", 3000); // every 3 seconds. + @Inject + public PlayerNotifier(@NotNull PluginConfig config) { + maxSpam = config.getYamlConfig().getInt("general.maxSpam", 3000); // every 3 seconds. } public synchronized void notifyPlayer(Player player, String message) { @@ -37,7 +42,7 @@ public synchronized void notifyPlayer(Player player, String message) { try { NotifyMessage last = cache.get(uuid); long now = System.currentTimeMillis(); - if (now >= last.getTime() + maxSpam || !message.equals(last.getMessage())) { + if (now >= last.time() + maxSpam || !message.equals(last.message())) { cache.put(uuid, new NotifyMessage(message, now)); player.sendMessage("\u00a7e" + message); } @@ -46,21 +51,6 @@ public synchronized void notifyPlayer(Player player, String message) { } } - private static class NotifyMessage { - private final String message; - private final long time; - - private NotifyMessage(String message, long time) { - this.message = message; - this.time = time; - } - - public String getMessage() { - return message; - } - - public long getTime() { - return time; - } + private record NotifyMessage(String message, long time) { } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java index 9f3140eba..fbc963a49 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/TeleportLogic.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.player; +import com.google.inject.Inject; +import com.google.inject.Singleton; import io.papermc.lib.PaperLib; import org.apache.commons.lang3.Validate; import org.bukkit.Location; @@ -14,8 +16,10 @@ import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.world.WorldManager; +import java.time.Duration; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -27,31 +31,43 @@ /** * Responsible for teleporting (and cancelling teleporting) of players. */ +@Singleton public class TeleportLogic implements Listener { - private static final Logger log = Logger.getLogger(TeleportLogic.class.getName()); - + private final Logger logger; private final uSkyBlock plugin; - private final int teleportDelay; + private final WorldManager worldManager; + private final Scheduler scheduler; + private final Duration teleportDelay; private final Map pendingTeleports = new ConcurrentHashMap<>(); private final double cancelDistance; - public TeleportLogic(uSkyBlock plugin) { + @Inject + public TeleportLogic( + @NotNull Logger logger, + @NotNull uSkyBlock plugin, + @NotNull WorldManager worldManager, + @NotNull Scheduler scheduler + ) { + this.logger = logger; this.plugin = plugin; - teleportDelay = plugin.getConfig().getInt("options.island.islandTeleportDelay", 2); + teleportDelay = Duration.ofSeconds(plugin.getConfig().getInt("options.island.islandTeleportDelay", 2)); cancelDistance = plugin.getConfig().getDouble("options.island.teleportCancelDistance", 0.2); + this.worldManager = worldManager; + this.scheduler = scheduler; plugin.getServer().getPluginManager().registerEvents(this, plugin); } /** * Teleport the given {@link Player} to his island home. + * * @param player Player to teleport - * @param force True to override teleport delay, false otherwise. + * @param force True to override teleport delay, false otherwise. */ public void homeTeleport(@NotNull Player player, boolean force) { Validate.notNull(player, "Player cannot be null"); Location homeLocation = null; - PlayerInfo playerInfo = plugin.getPlayerLogic().getPlayerInfo(player); + PlayerInfo playerInfo = plugin.getPlayerInfo(player); if (playerInfo != null) { homeLocation = plugin.getSafeHomeLocation(playerInfo); @@ -66,7 +82,7 @@ public void homeTeleport(@NotNull Player player, boolean force) { return; } - plugin.getWorldManager().removeCreatures(homeLocation); + worldManager.removeCreatures(homeLocation); player.sendMessage(tr("\u00a7aTeleporting you to your island.")); safeTeleport(player, homeLocation, force); } @@ -74,24 +90,25 @@ public void homeTeleport(@NotNull Player player, boolean force) { /** * Teleport the given {@link Player} to the given {@link Location}, loading the {@link org.bukkit.Chunk} before * teleporting and with the configured teleport delay if applicable. - * @param player Player to teleport. + * + * @param player Player to teleport. * @param targetLocation Location to teleport the player to. - * @param force True to override teleport delay, false otherwise. + * @param force True to override teleport delay, false otherwise. */ public void safeTeleport(@NotNull Player player, @NotNull Location targetLocation, boolean force) { Validate.notNull(player, "Player cannot be null"); Validate.notNull(targetLocation, "TargetLocation cannot be null"); - log.log(Level.FINER, "safeTeleport " + player + " to " + targetLocation + (force ? " with force" : "")); + logger.log(Level.FINER, "safeTeleport " + player + " to " + targetLocation + (force ? " with force" : "")); final Location targetLoc = LocationUtil.centerOnBlock(targetLocation.clone()); - if (player.hasPermission("usb.mod.bypassteleport") || (teleportDelay == 0) || force) { + if (player.hasPermission("usb.mod.bypassteleport") || teleportDelay.isZero() || force) { PaperLib.teleportAsync(player, targetLoc); } else { player.sendMessage(tr("\u00a7aYou will be teleported in {0} seconds.", teleportDelay)); - BukkitTask tpTask = plugin.sync(() -> { + BukkitTask tpTask = scheduler.sync(() -> { pendingTeleports.remove(player.getUniqueId()); PaperLib.teleportAsync(player, targetLoc); - }, TimeUtil.secondsAsMillis(teleportDelay)); + }, teleportDelay); pendingTeleports.put(player.getUniqueId(), new PendingTeleport(player.getLocation(), tpTask)); } } @@ -99,14 +116,15 @@ public void safeTeleport(@NotNull Player player, @NotNull Location targetLocatio /** * Teleport the given {@link Player} to the spawn in the island world, loading the {@link org.bukkit.Chunk} before * teleporting and with the configured teleport delay if applicable. + * * @param player Player to teleport. - * @param force True to override teleport delay, false otherwise. + * @param force True to override teleport delay, false otherwise. */ public void spawnTeleport(@NotNull Player player, boolean force) { Validate.notNull(player, "Player cannot be null"); - Location spawnLocation = LocationUtil.centerOnBlock(plugin.getWorldManager().getWorld().getSpawnLocation()); - if (player.hasPermission("usb.mod.bypassteleport") || (teleportDelay == 0) || force) { + Location spawnLocation = LocationUtil.centerOnBlock(worldManager.getWorld().getSpawnLocation()); + if (player.hasPermission("usb.mod.bypassteleport") || teleportDelay.isZero() || force) { if (Settings.extras_sendToSpawn) { plugin.execCommand(player, "op:spawn", false); } else { @@ -114,23 +132,24 @@ public void spawnTeleport(@NotNull Player player, boolean force) { } } else { player.sendMessage(tr("\u00a7aYou will be teleported in {0} seconds.", teleportDelay)); - BukkitTask tpTask = plugin.sync(() -> { + BukkitTask tpTask = scheduler.sync(() -> { pendingTeleports.remove(player.getUniqueId()); if (Settings.extras_sendToSpawn) { plugin.execCommand(player, "op:spawn", false); } else { PaperLib.teleportAsync(player, spawnLocation); } - }, TimeUtil.secondsAsMillis(teleportDelay)); + }, teleportDelay); pendingTeleports.put(player.getUniqueId(), new PendingTeleport(player.getLocation(), tpTask)); } } /** * Teleport the given {@link Player} to the warp location for the given {@link PlayerInfo}. - * @param player Player to teleport. + * + * @param player Player to teleport. * @param playerInfo PlayerInfo to lookup the target warp location. - * @param force True to override teleport delay, false otherwise. + * @param force True to override teleport delay, false otherwise. */ public void warpTeleport(@NotNull Player player, @Nullable PlayerInfo playerInfo, boolean force) { Validate.notNull(player, "Player cannot be null"); @@ -150,7 +169,7 @@ public void warpTeleport(@NotNull Player player, @Nullable PlayerInfo playerInfo safeTeleport(player, warpLocation, force); } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @SuppressWarnings("unused") public void onPlayerMove(PlayerMoveEvent e) { PendingTeleport pendingTeleport = pendingTeleports.get(e.getPlayer().getUniqueId()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java index ecb6e70c1..d870faa37 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignEvents.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.signs; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.FormatUtil; import org.bukkit.GameMode; import org.bukkit.Location; @@ -21,16 +23,19 @@ import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerInteractEvent; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; /** * Handles USB Signs */ +@Singleton public class SignEvents implements Listener { private final uSkyBlock plugin; private final SignLogic logic; - public SignEvents(uSkyBlock plugin, SignLogic logic) { + @Inject + public SignEvents(@NotNull uSkyBlock plugin, @NotNull SignLogic logic) { this.plugin = plugin; this.logic = logic; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java index c832c0fa8..d756dca53 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/signs/SignLogic.java @@ -1,5 +1,7 @@ package us.talabrek.ultimateskyblock.signs; +import com.google.inject.Inject; +import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.file.FileUtil; import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.Location; @@ -14,6 +16,7 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.challenge.Challenge; import us.talabrek.ultimateskyblock.challenge.ChallengeCompletion; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; @@ -22,6 +25,8 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import us.talabrek.ultimateskyblock.world.WorldManager; import java.io.File; import java.io.IOException; @@ -37,19 +42,33 @@ /** * Responsible for keeping track of signs. */ +@Singleton public class SignLogic { - private static final Logger log = Logger.getLogger(SignLogic.class.getName()); private static final int SIGN_LINE_WIDTH = 11; // Actually more like 15, but we break after. + private final FileConfiguration config; private final File configFile; + private final Logger logger; private final uSkyBlock plugin; + private final Scheduler scheduler; private final ChallengeLogic challengeLogic; + private final WorldManager worldManager; - public SignLogic(uSkyBlock plugin) { + @Inject + public SignLogic( + @NotNull Logger logger, + @NotNull uSkyBlock plugin, + @NotNull Scheduler scheduler, + @NotNull ChallengeLogic challengeLogic, + @NotNull WorldManager worldManager + ) { + this.logger = logger; this.plugin = plugin; - configFile = new File(plugin.getDataFolder(), "signs.yml"); - config = FileUtil.getYmlConfiguration("signs.yml"); - challengeLogic = plugin.getChallengeLogic(); + this.scheduler = scheduler; + this.challengeLogic = challengeLogic; + this.worldManager = worldManager; + this.configFile = new File(plugin.getDataFolder(), "signs.yml"); + this.config = FileUtil.getYmlConfiguration("signs.yml"); } void addSign(Sign block, String[] lines, Chest chest) { @@ -79,7 +98,7 @@ void addSign(Sign block, String[] lines, Chest chest) { } void removeSign(final Location loc) { - plugin.async(() -> removeSignAsync(loc)); + scheduler.async(() -> removeSignAsync(loc)); } private void removeSignAsync(Location loc) { @@ -98,7 +117,7 @@ private void removeSignAsync(Location loc) { } void removeChest(final Location loc) { - plugin.async(() -> removeChestAsync(loc)); + scheduler.async(() -> removeChestAsync(loc)); } private void removeChestAsync(Location loc) { @@ -112,7 +131,7 @@ private void removeChestAsync(Location loc) { } void updateSignsOnContainer(final Location... containerLocations) { - plugin.async(() -> { + scheduler.async(() -> { for (Location loc : containerLocations) { if (loc == null) { continue; @@ -154,7 +173,7 @@ void updateSign(Location signLocation) { } private void updateSignAsync(final Location chestLoc) { - if (chestLoc == null || !plugin.getWorldManager().isSkyAssociatedWorld(chestLoc.getWorld())) { + if (chestLoc == null || !worldManager.isSkyAssociatedWorld(chestLoc.getWorld())) { return; } String locString = LocationUtil.asKey(chestLoc); @@ -202,7 +221,7 @@ private void updateSignAsync(final Location chestLoc, String islandName, String final boolean challengeLocked = !isChallengeAvailable; final Map requiredItemsFinal = requiredItems; // Back to sync - plugin.sync(() -> updateSignFromChestSync(chestLoc, signLocation, challenge, requiredItemsFinal, challengeLocked)); + scheduler.sync(() -> updateSignFromChestSync(chestLoc, signLocation, challenge, requiredItemsFinal, challengeLocked)); } private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challenge challenge, Map requiredItems, boolean challengeLocked) { @@ -219,7 +238,7 @@ private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challe int requiredAmount = required.getValue(); if (!chest.getInventory().containsAtLeast(requiredType, requiredAmount)) { // Max shouldn't be needed, provided containsAtLeast matches getCountOf... but it might not - missing += Math.max(0, requiredAmount - plugin.getChallengeLogic().getCountOf(chest.getInventory(), requiredType)); + missing += Math.max(0, requiredAmount - challengeLogic.getCountOf(chest.getInventory(), requiredType)); } } } @@ -250,7 +269,7 @@ private void updateSignFromChestSync(Location chestLoc, Location signLoc, Challe sign.setLine(3, ""); } if (!sign.update()) { - log.info("Unable to update sign at " + LocationUtil.asString(signLoc)); + logger.info("Unable to update sign at " + LocationUtil.asString(signLoc)); } } } @@ -260,7 +279,7 @@ private boolean isChest(Block chestBlock) { } private void saveAsync() { - plugin.async(this::save); + scheduler.async(this::save); } private void save() { @@ -268,13 +287,13 @@ private void save() { try { config.save(configFile); } catch (IOException e) { - log.info("Unable to save to " + configFile); + logger.info("Unable to save to " + configFile); } } } void signClicked(final Player player, final Location location) { - plugin.async(() -> tryCompleteAsync(player, location)); + scheduler.async(() -> tryCompleteAsync(player, location)); } private void tryCompleteAsync(final Player player, Location location) { @@ -297,7 +316,7 @@ private void tryCompleteAsync(final Player player, Location location) { player.sendMessage(tr("\u00a74The {0} challenge is not available yet!", challenge.getDisplayName())); return; } - plugin.sync(() -> tryComplete(player, chestLoc, challenge)); + scheduler.sync(() -> tryComplete(player, chestLoc, challenge)); } } } @@ -323,10 +342,10 @@ private void tryComplete(Player player, Location chestLoc, Challenge challenge) int requiredAmount = required.getValue(); int diff = 0; if (!player.getInventory().containsAtLeast(requiredType, requiredAmount)) { - diff = requiredAmount - plugin.getChallengeLogic().getCountOf(player.getInventory(), requiredType); + diff = requiredAmount - challengeLogic.getCountOf(player.getInventory(), requiredType); } if (diff > 0 && !chest.getInventory().containsAtLeast(requiredType, diff)) { - diff -= plugin.getChallengeLogic().getCountOf(chest.getInventory(), requiredType); + diff -= challengeLogic.getCountOf(chest.getInventory(), requiredType); } else { diff = 0; } @@ -335,7 +354,7 @@ private void tryComplete(Player player, Location chestLoc, Challenge challenge) if (missing == 0) { boolean successfulItemTransfer = attemptToMoveItemsToPlayerInventory(player.getInventory(), chest.getInventory(), requiredItems); if (successfulItemTransfer) { - plugin.getChallengeLogic().completeChallenge(player, challenge.getName()); + challengeLogic.completeChallenge(player, challenge.getName()); } else { player.sendMessage(tr("\u00a7cWARNING:\u00a7e Could not transfer all the required items to your inventory!")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index fabe9b474..ecacad130 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock; +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import dk.lockfuglsang.minecraft.animation.AnimationHandler; import dk.lockfuglsang.minecraft.command.Command; import dk.lockfuglsang.minecraft.command.CommandManager; import dk.lockfuglsang.minecraft.file.FileUtil; @@ -16,10 +18,8 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.ServicePriority; @@ -38,36 +38,14 @@ import us.talabrek.ultimateskyblock.api.event.uSkyBlockScoreChangedEvent; import us.talabrek.ultimateskyblock.api.impl.UltimateSkyblockApi; import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; -import us.talabrek.ultimateskyblock.biome.BiomeConfig; -import us.talabrek.ultimateskyblock.biome.Biomes; +import us.talabrek.ultimateskyblock.bootstrap.SkyblockApp; +import us.talabrek.ultimateskyblock.bootstrap.SkyblockModule; import us.talabrek.ultimateskyblock.challenge.ChallengeLogic; -import us.talabrek.ultimateskyblock.chat.ChatEvents; -import us.talabrek.ultimateskyblock.chat.ChatLogic; -import us.talabrek.ultimateskyblock.chat.IslandTalkCommand; -import us.talabrek.ultimateskyblock.chat.PartyTalkCommand; import us.talabrek.ultimateskyblock.command.AdminCommand; -import us.talabrek.ultimateskyblock.command.ChallengeCommand; -import us.talabrek.ultimateskyblock.command.IslandCommand; -import us.talabrek.ultimateskyblock.command.admin.DebugCommand; import us.talabrek.ultimateskyblock.command.admin.SetMaintenanceCommand; -import us.talabrek.ultimateskyblock.event.ExploitEvents; -import us.talabrek.ultimateskyblock.event.GriefEvents; -import us.talabrek.ultimateskyblock.event.InternalEvents; -import us.talabrek.ultimateskyblock.event.ItemDropEvents; -import us.talabrek.ultimateskyblock.event.MenuEvents; -import us.talabrek.ultimateskyblock.event.NetherTerraFormEvents; -import us.talabrek.ultimateskyblock.event.PlayerEvents; -import us.talabrek.ultimateskyblock.event.SpawnEvents; -import us.talabrek.ultimateskyblock.event.ToolMenuEvents; -import us.talabrek.ultimateskyblock.event.WitherTagEvents; -import us.talabrek.ultimateskyblock.event.WorldGuardEvents; -import us.talabrek.ultimateskyblock.gui.GuiListener; -import us.talabrek.ultimateskyblock.gui.GuiManager; -import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.ConfirmHandler; import us.talabrek.ultimateskyblock.handler.CooldownHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; -import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.hook.HookManager; import us.talabrek.ultimateskyblock.imports.BlockRequirementConverter; import us.talabrek.ultimateskyblock.imports.ItemComponentConverter; @@ -79,11 +57,9 @@ import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.island.LimitLogic; import us.talabrek.ultimateskyblock.island.OrphanLogic; -import us.talabrek.ultimateskyblock.island.level.ChunkSnapshotLevelLogic; import us.talabrek.ultimateskyblock.island.level.IslandScore; import us.talabrek.ultimateskyblock.island.level.LevelLogic; import us.talabrek.ultimateskyblock.island.task.CreateIslandTask; -import us.talabrek.ultimateskyblock.island.task.RecalculateRunnable; import us.talabrek.ultimateskyblock.island.task.SetBiomeTask; import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; @@ -94,19 +70,14 @@ import us.talabrek.ultimateskyblock.player.PlayerNotifier; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.player.TeleportLogic; -import us.talabrek.ultimateskyblock.signs.SignEvents; -import us.talabrek.ultimateskyblock.signs.SignLogic; import us.talabrek.ultimateskyblock.util.IslandUtil; import us.talabrek.ultimateskyblock.util.LocationUtil; -import us.talabrek.ultimateskyblock.util.PlayerUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; import us.talabrek.ultimateskyblock.util.ServerUtil; -import us.talabrek.ultimateskyblock.uuid.BukkitPlayerDB; -import us.talabrek.ultimateskyblock.uuid.FilePlayerDB; -import us.talabrek.ultimateskyblock.uuid.MemoryPlayerDB; import us.talabrek.ultimateskyblock.uuid.PlayerDB; import us.talabrek.ultimateskyblock.world.WorldManager; -import java.io.File; +import java.time.Duration; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -116,14 +87,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; import static java.util.Objects.requireNonNull; import static us.talabrek.ultimateskyblock.util.LogUtil.log; public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManager.RequirementChecker { private static final String CN = uSkyBlock.class.getName(); - private static final String[][] depends = new String[][]{ + public static final String[][] depends = new String[][]{ new String[]{"Vault", "1.7.1", "optional"}, new String[]{"WorldEdit", "7.2.12", "optionalIf", "FastAsyncWorldEdit"}, new String[]{"WorldGuard", "7.0.8"}, @@ -135,83 +105,73 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private static String missingRequirements = null; private static final Random RND = new Random(System.currentTimeMillis()); + private SkyblockApp skyBlock; + + // TODO: eventually get rid of these global references and move them to a proper API instead + @Inject private SkyBlockMenu menu; + @Inject private ConfigMenu configMenu; + @Inject private ChallengeLogic challengeLogic; + @Inject private EventLogic eventLogic; + @Inject private LevelLogic levelLogic; + @Inject private IslandLogic islandLogic; + @Inject private OrphanLogic orphanLogic; + @Inject private PerkLogic perkLogic; + @Inject private TeleportLogic teleportLogic; + @Inject private LimitLogic limitLogic; - private GuiManager guiManager; - private Biomes biomes; - private BiomeConfig biomeConfig; - - /* MANAGERS */ + @Inject private HookManager hookManager; - private MetricsManager metricsManager; + @Inject private WorldManager worldManager; - + @Inject private IslandGenerator islandGenerator; + @Inject private PlayerNotifier notifier; - + @Inject private USBImporterExecutor importer; - - private static uSkyBlock instance; - // TODO: 28/06/2016 - R4zorax: These two should probably be moved to the proper classes - public File directoryPlayers; - public File directoryIslands; - - private BukkitTask autoRecalculateTask; - + @Inject private IslandLocatorLogic islandLocatorLogic; + @Inject private PlayerDB playerDB; + @Inject private ConfirmHandler confirmHandler; - private AnimationHandler animationHandler; - + @Inject private CooldownHandler cooldownHandler; + @Inject private PlayerLogic playerLogic; - private ChatLogic chatLogic; - - private volatile boolean maintenanceMode = false; + // TODO: don't assign value directly, but use injection instead. Currently, legacy code in PlaceholderHandler accesses it too early for injection to work. + @Inject + private PluginConfig config = new PluginConfig(); + @Inject private BlockLimitLogic blockLimitLogic; + @Inject + private SkyUpdateChecker updateChecker; private UltimateSkyblockApi api; - private SkyUpdateChecker updateChecker; - public uSkyBlock() { - } + private volatile boolean maintenanceMode = false; + + private static uSkyBlock instance; @Override public void onDisable() { deregisterApi(api); api = null; - - HandlerList.unregisterAll(this); - Bukkit.getScheduler().cancelTasks(this); - try { - WorldManager.skyBlockWorld = null; // Force a reload on config. - } catch (Exception e) { - log(Level.INFO, tr("Something went wrong saving the island and/or party data!"), e); - } - PlaceholderHandler.unregister(this); - if (animationHandler != null) { - animationHandler.stop(); - } - challengeLogic.shutdown(); - eventLogic.shutdown(); - playerLogic.shutdown(); - islandLogic.shutdown(); - playerDB.shutdown(); // Must be before playerNameChangeManager!! - AsyncWorldEditHandler.onDisable(this); - DebugCommand.disableLogging(null); + shutdown(); } @Override public @NotNull FileConfiguration getConfig() { - return FileUtil.getYmlConfiguration("config.yml"); + return config.getYamlConfig(); } private void convertConfigItemsTo1_20_6IfRequired() { @@ -226,8 +186,6 @@ private void convertConfigToBlockRequirements() { @Override public void onEnable() { - WorldManager.skyBlockWorld = null; // Force a re-import or what-ever... - WorldManager.skyBlockNetherWorld = null; missingRequirements = null; instance = this; @@ -235,43 +193,24 @@ public void onEnable() { convertConfigItemsTo1_20_6IfRequired(); convertConfigToBlockRequirements(); - CommandManager.registerRequirements(this); - FileUtil.setDataFolder(getDataFolder()); - FileUtil.setAlwaysOverwrite("levelConfig.yml"); - I18nUtil.setDataFolder(getDataFolder()); - reloadConfigs(); + reloadLegacyStuff(); + startup(); api = new UltimateSkyblockApi(this); registerApi(api); - getServer().getScheduler().runTaskLater(getInstance(), new Runnable() { - @Override - public void run() { - ServerUtil.init(uSkyBlock.this); - if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { - return; - } - uSkyBlock.this.getHookManager().setupMultiverse(); - uSkyBlock.this.getHookManager().setupEconomyHook(); - uSkyBlock.this.getHookManager().setupPermissionsHook(); - AsyncWorldEditHandler.onEnable(uSkyBlock.this); - WorldGuardHandler.setupGlobal(getWorldManager().getWorld()); - if (getWorldManager().getNetherWorld() != null) { - WorldGuardHandler.setupGlobal(getWorldManager().getNetherWorld()); - } - registerEventsAndCommands(uSkyBlock.this.guiManager, uSkyBlock.this.biomes, uSkyBlock.this.biomeConfig); - - getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 - log(Level.INFO, getVersionInfo(false)); + getScheduler().sync(() -> { + ServerUtil.init(uSkyBlock.this); + if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { + return; } - }, getConfig().getLong("init.initDelay", 50L)); - updateChecker = new SkyUpdateChecker(this); - // Runs every 4 hours - long FOUR_HOURS_IN_TICKS = 4L * 60L * 60L * 20L; - getServer().getScheduler().runTaskTimerAsynchronously(this, () -> getUpdateChecker().checkForUpdates(), 0L, FOUR_HOURS_IN_TICKS); + delayedEnable(); - metricsManager = new MetricsManager(this); + getServer().dispatchCommand(getServer().getConsoleSender(), "usb flush"); // See uskyblock#4 + }, TimeUtil.ticksAsDuration(getConfig().getLong("init.initDelay", 50L))); + + getScheduler().async(() -> getUpdateChecker().checkForUpdates(), Duration.ZERO, Duration.ofHours(4)); } public synchronized boolean isRequirementsMet(CommandSender sender, Command command, String... args) { @@ -314,58 +253,16 @@ public synchronized boolean isRequirementsMet(CommandSender sender, Command comm } } - private void createFolders() { + private void createDataFolder() { if (!getDataFolder().exists()) { getDataFolder().mkdirs(); } - directoryPlayers = new File(getDataFolder() + File.separator + "players"); - if (!directoryPlayers.exists()) { - directoryPlayers.mkdirs(); - } - directoryIslands = new File(getDataFolder() + File.separator + "islands"); - if (!directoryIslands.exists()) { - directoryIslands.mkdirs(); - } - IslandInfo.setDirectory(directoryIslands); } public static uSkyBlock getInstance() { return uSkyBlock.instance; } - public void registerEvents(GuiManager guiManager) { - final PluginManager manager = getServer().getPluginManager(); - manager.registerEvents(new InternalEvents(this), this); - manager.registerEvents(new PlayerEvents(this), this); - manager.registerEvents(new MenuEvents(this), this); - manager.registerEvents(new GuiListener(guiManager), this); - manager.registerEvents(new ExploitEvents(this), this); - manager.registerEvents(new WitherTagEvents(this), this); - if (getConfig().getBoolean("options.protection.enabled", true)) { - manager.registerEvents(new GriefEvents(this), this); - if (getConfig().getBoolean("options.protection.item-drops", true)) { - manager.registerEvents(new ItemDropEvents(this), this); - } - } - if (getConfig().getBoolean("options.island.spawn-limits.enabled", true)) { - manager.registerEvents(new SpawnEvents(this), this); - } - if (getConfig().getBoolean("options.protection.visitors.block-banned-entry", true)) { - manager.registerEvents(new WorldGuardEvents(this), this); - } - if (Settings.nether_enabled) { - manager.registerEvents(new NetherTerraFormEvents(this), this); - } - if (getConfig().getBoolean("tool-menu.enabled", true)) { - manager.registerEvents(new ToolMenuEvents(this), this); - } - if (getConfig().getBoolean("signs.enabled", true)) { - manager.registerEvents(new SignEvents(this, new SignLogic(this)), this); - } - PlaceholderHandler.register(this); - manager.registerEvents(new ChatEvents(chatLogic, this), this); - } - public Location getSafeHomeLocation(final PlayerInfo p) { Location home = LocationUtil.findNearestSafeLocation(p.getHomeLocation(), null); if (home == null) { @@ -399,13 +296,10 @@ private void postDelete(final IslandInfo islandInfo) { public boolean deleteEmptyIsland(String islandName, final Runnable runner) { final IslandInfo islandInfo = getIslandInfo(islandName); if (islandInfo != null && islandInfo.getMembers().isEmpty()) { - islandLogic.clearIsland(islandInfo.getIslandLocation(), new Runnable() { - @Override - public void run() { - postDelete(islandInfo); - if (runner != null) { - runner.run(); - } + islandLogic.clearIsland(islandInfo.getIslandLocation(), () -> { + postDelete(islandInfo); + if (runner != null) { + runner.run(); } }); return true; @@ -443,12 +337,7 @@ public boolean restartPlayerIsland(final Player player, final Location next, fin // Clear first, since the player could log out and we NEED to make sure their inventory gets cleared. clearPlayerInventory(player); } - islandLogic.clearIsland(next, new Runnable() { - @Override - public void run() { - generateIsland(player, playerInfo, next, cSchem); - } - }); + islandLogic.clearIsland(next, () -> generateIsland(player, playerInfo, next, cSchem)); return true; } @@ -732,90 +621,58 @@ public IslandLocatorLogic getIslandLocatorLogic() { @Override public void reloadConfig() { - reloadConfigs(); - registerEventsAndCommands(this.guiManager, this.biomes, this.biomeConfig); + reload(); } - private void reloadConfigs() { - createFolders(); - HandlerList.unregisterAll(this); - hookManager = new HookManager(this); - if (challengeLogic != null) { - challengeLogic.shutdown(); - } - if (playerLogic != null) { - playerLogic.shutdown(); - } - if (islandLogic != null) { - islandLogic.shutdown(); - } - PlaceholderHandler.unregister(this); - if (Settings.loadPluginConfig(getConfig())) { - saveConfig(); - } - I18nUtil.clearCache(); - // Update all of the loaded configs. - FileUtil.reload(); + private void reload() { + shutdown(); + reloadLegacyStuff(); + startup(); + delayedEnable(); + } - String playerDbStorage = getConfig().getString("options.advanced.playerdb.storage", "yml"); - if (playerDbStorage.equalsIgnoreCase("yml")) { - playerDB = new FilePlayerDB(this); - } else if (playerDbStorage.equalsIgnoreCase("memory")) { - playerDB = new MemoryPlayerDB(getConfig()); - } else { - playerDB = new BukkitPlayerDB(); + private void shutdown() { + if (this.skyBlock != null) { + this.skyBlock.shutdown(this); + this.skyBlock = null; } + WorldManager.skyBlockWorld = null; // Force a reload on config. + } - getServer().getPluginManager().registerEvents(playerDB, this); - worldManager = new WorldManager(this); - eventLogic = new EventLogic(this); - teleportLogic = new TeleportLogic(this); - PlayerUtil.loadConfig(playerDB, getConfig()); - islandGenerator = new IslandGenerator(getDataFolder(), getConfig()); - perkLogic = new PerkLogic(this, islandGenerator); - challengeLogic = new ChallengeLogic(FileUtil.getYmlConfiguration("challenges.yml"), this); - menu = new SkyBlockMenu(this, challengeLogic); - configMenu = new ConfigMenu(this); - FileConfiguration levelConfig = FileUtil.getYmlConfiguration("levelConfig.yml"); - // Disabled until AWE/FAWE supports 1.13 - //levelLogic = AsyncWorldEditHandler.isAWE() ? new AweLevelLogic(this, levelConfig) : new ChunkSnapshotLevelLogic(this, levelConfig); - levelLogic = new ChunkSnapshotLevelLogic(this, levelConfig); - orphanLogic = new OrphanLogic(this); - islandLocatorLogic = new IslandLocatorLogic(this); - islandLogic = new IslandLogic(this, directoryIslands, orphanLogic); - limitLogic = new LimitLogic(this); - blockLimitLogic = new BlockLimitLogic(this); - notifier = new PlayerNotifier(getConfig()); - playerLogic = new PlayerLogic(this); - if (autoRecalculateTask != null) { - autoRecalculateTask.cancel(); + private void startup() { + if (this.skyBlock != null) { + throw new IllegalStateException("Skyblock already started"); } - chatLogic = new ChatLogic(this); - this.guiManager = new GuiManager(); - this.biomeConfig = new BiomeConfig(getLogger()); - this.biomes = new Biomes(this.guiManager, this.biomeConfig); + + WorldManager.skyBlockWorld = null; // Force a re-import or what-ever... + WorldManager.skyBlockNetherWorld = null; + + Injector injector = Guice.createInjector(new SkyblockModule(this)); + this.skyBlock = injector.getInstance(SkyblockApp.class); + injector.injectMembers(this); + this.skyBlock.startup(this); } - public void registerEventsAndCommands(GuiManager guiManager, Biomes biomes, BiomeConfig biomeConfig) { - if (!isRequirementsMet(Bukkit.getConsoleSender(), null)) { - return; - } - registerEvents(guiManager); - int refreshEveryMinute = getConfig().getInt("options.island.autoRefreshScore", 0); - if (refreshEveryMinute > 0) { - int refreshTicks = refreshEveryMinute * 1200; // Ticks per minute - autoRecalculateTask = new RecalculateRunnable(this).runTaskTimer(this, refreshTicks, refreshTicks); - } else { - autoRecalculateTask = null; - } - confirmHandler = new ConfirmHandler(this, getConfig().getInt("options.advanced.confirmTimeout", 10)); - cooldownHandler = new CooldownHandler(this); - animationHandler = new AnimationHandler(this); - getCommand("island").setExecutor(new IslandCommand(this, menu, biomes, biomeConfig)); - getCommand("challenges").setExecutor(new ChallengeCommand(this)); - getCommand("usb").setExecutor(new AdminCommand(this, confirmHandler, animationHandler, biomeConfig)); - getCommand("islandtalk").setExecutor(new IslandTalkCommand(this, chatLogic)); - getCommand("partytalk").setExecutor(new PartyTalkCommand(this, chatLogic)); + private void delayedEnable() { + this.skyBlock.delayedEnable(this); + } + + /** + * Initializes/reloads the legacy static services. This has to be done before the object-oriented services are + * created, as some use the static services in their constructors. This should be refactored and integrated with + * the new system in the future. + */ + private void reloadLegacyStuff() { + createDataFolder(); + CommandManager.registerRequirements(this); + FileUtil.setDataFolder(getDataFolder()); + FileUtil.setAlwaysOverwrite("levelConfig.yml"); + Settings.loadPluginConfig(new PluginConfig().getYamlConfig()); + I18nUtil.setDataFolder(getDataFolder()); + saveConfig(); + // Update all of the loaded configs. + FileUtil.reload(); + I18nUtil.getI18n(); } public IslandLogic getIslandLogic() { @@ -982,48 +839,6 @@ public void fireAsyncEvent(final Event event) { ); } - public String getVersionInfo(boolean checkEnabled) { - PluginDescriptionFile description = getDescription(); - StringBuilder msg = new StringBuilder(pre("\u00a77Name: \u00a7b{0}\n", description.getName())); - msg.append(pre("\u00a77Version: \u00a7b{0}\n", description.getVersion())); - msg.append(pre("\u00a77Description: \u00a7b{0}\n", description.getDescription())); - msg.append(pre("\u00a77Language: \u00a7b{0} ({1})\n", getConfig().get("language", "en"), I18nUtil.getI18n().getLocale())); - msg.append(pre("\u00a79 State: d={0}, r={1}, i={2}, p={3}, n={4}, awe={5}\n", Settings.island_distance, Settings.island_radius, - islandLogic.getSize(), playerLogic.getSize(), - Settings.nether_enabled, AsyncWorldEditHandler.isAWE())); - msg.append(pre("\u00a77Server: \u00a7e{0} {1}\n", getServer().getName(), getServer().getVersion())); - msg.append(pre("\u00a79 State: online={0}, bungee={1}\n", ServerUtil.isOnlineMode(), - ServerUtil.isBungeeEnabled())); - msg.append(pre("\u00a77------------------------------\n")); - for (String[] dep : depends) { - Plugin dependency = getServer().getPluginManager().getPlugin(dep[0]); - if (dependency != null) { - String status = pre("N/A"); - if (checkEnabled) { - if (dependency.isEnabled()) { - if (VersionUtil.getVersion(dependency.getDescription().getVersion()).isLT(dep[1])) { - status = pre("\u00a7eWRONG-VERSION"); - } else { - status = pre("\u00a72ENABLED"); - } - } else { - status = pre("\u00a74DISABLED"); - } - } - msg.append(pre("\u00a77\u00a7d{0} \u00a7f{1} \u00a77({2}\u00a77)\n", dependency.getName(), - dependency.getDescription().getVersion(), status)); - } - } - msg.append(pre("\u00a77------------------------------\n")); - - if (getConfig().getBoolean("plugin-updates.check", true) && getUpdateChecker().isUpdateAvailable()) { - msg.append(pre("\u00a7bA new update of uSkyBlock is available: \u00a7f{0}\n", getUpdateChecker().getLatestVersion())); - msg.append(pre("\u00a7fVisit {0} to download.\n", "https://www.uskyblock.ovh/get")); - } - - return msg.toString(); - } - public PlayerDB getPlayerDB() { return playerDB; } @@ -1094,6 +909,8 @@ public boolean isMaintenanceMode() { return maintenanceMode; } + // TODO: minoneer 06.02.2025: Do we need this? It is currently very buggy and makes a lot of the logic more complex. + /** * CAUTION! If anyone calls this with true, they MUST ensure it is later called with false, * or the plugin will effectively be in a locked state. @@ -1171,4 +988,12 @@ private void deregisterApi(UltimateSkyblock api) { UltimateSkyblockProvider.deregisterPlugin(); getServer().getServicesManager().unregister(api); } + + public PluginConfig getPluginConfig() { + return config; + } + + public Scheduler getScheduler() { + return new Scheduler(this); + } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PlayerUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PlayerUtil.java deleted file mode 100644 index 3b30bf757..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PlayerUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -package us.talabrek.ultimateskyblock.util; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.metadata.FixedMetadataValue; -import org.bukkit.metadata.MetadataValue; -import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.uuid.PlayerDB; - -import java.util.List; - -/** - * Wrappers for most player-related functionality. - */ -public enum PlayerUtil {; - private static boolean skipDisplayName = false; - private static PlayerDB playerDB; - - public static String getPlayerDisplayName(String playerName) { - if (skipDisplayName) { - return playerName; - } - if (playerDB != null) { - return playerDB.getDisplayName(playerName); - } - return playerName; - } - - public static String getMetadata(Player player, String key, String defaultValue) { - if (player.hasMetadata(key) && !player.getMetadata(key).isEmpty()) { - List metadata = player.getMetadata(key); - return metadata.get(0).asString(); - } - return defaultValue; - } - - public static void setMetadata(Player player, String key, String value) { - player.setMetadata(key, new FixedMetadataValue(uSkyBlock.getInstance(), value)); - } - - public static void loadConfig(PlayerDB playerDB, FileConfiguration config) { - PlayerUtil.playerDB = playerDB; - skipDisplayName = config.getBoolean("options.advanced.useDisplayNames", false); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PluginInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PluginInfo.java new file mode 100644 index 000000000..a1c37a2c4 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/PluginInfo.java @@ -0,0 +1,93 @@ +package us.talabrek.ultimateskyblock.util; + +import com.google.inject.Inject; +import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.FormatUtil; +import dk.lockfuglsang.minecraft.util.VersionUtil; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.api.plugin.UpdateChecker; +import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; +import us.talabrek.ultimateskyblock.island.IslandLogic; +import us.talabrek.ultimateskyblock.player.PlayerLogic; + +import java.util.logging.Logger; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; +import static us.talabrek.ultimateskyblock.uSkyBlock.depends; + +public class PluginInfo { + + private final Plugin plugin; + private final IslandLogic islandLogic; + private final PluginConfig config; + private final UpdateChecker updateChecker; + private final PlayerLogic playerLogic; + private final Logger logger; + + @Inject + public PluginInfo( + @NotNull Plugin plugin, + @NotNull IslandLogic islandLogic, + @NotNull PluginConfig config, + @NotNull UpdateChecker updateChecker, + @NotNull PlayerLogic playerLogic, Logger logger + ) { + this.plugin = plugin; + this.islandLogic = islandLogic; + this.config = config; + this.updateChecker = updateChecker; + this.playerLogic = playerLogic; + this.logger = logger; + } + + public void startup() { + logger.info(FormatUtil.stripFormatting(getVersionInfo(false))); + } + + public String getVersionInfo(boolean checkEnabled) { + PluginDescriptionFile description = plugin.getDescription(); + StringBuilder msg = new StringBuilder(pre("\u00a77Name: \u00a7b{0}\n", description.getName())); + msg.append(pre("\u00a77Version: \u00a7b{0}\n", description.getVersion())); + msg.append(pre("\u00a77Description: \u00a7b{0}\n", description.getDescription())); + msg.append(pre("\u00a77Language: \u00a7b{0} ({1})\n", config.getYamlConfig().get("language", "en"), I18nUtil.getI18n().getLocale())); + msg.append(pre("\u00a79 State: d={0}, r={1}, i={2}, p={3}, n={4}, awe={5}\n", Settings.island_distance, Settings.island_radius, + islandLogic.getSize(), playerLogic.getSize(), + Settings.nether_enabled, AsyncWorldEditHandler.isAWE())); + msg.append(pre("\u00a77Server: \u00a7e{0} {1}\n", Bukkit.getName(), Bukkit.getVersion())); + msg.append(pre("\u00a79 State: online={0}, bungee={1}\n", ServerUtil.isOnlineMode(), + ServerUtil.isBungeeEnabled())); + msg.append(pre("\u00a77------------------------------\n")); + for (String[] dep : depends) { + Plugin dependency = Bukkit.getPluginManager().getPlugin(dep[0]); + if (dependency != null) { + String status = pre("N/A"); + if (checkEnabled) { + if (dependency.isEnabled()) { + if (VersionUtil.getVersion(dependency.getDescription().getVersion()).isLT(dep[1])) { + status = pre("\u00a7eWRONG-VERSION"); + } else { + status = pre("\u00a72ENABLED"); + } + } else { + status = pre("\u00a74DISABLED"); + } + } + msg.append(pre("\u00a77\u00a7d{0} \u00a7f{1} \u00a77({2}\u00a77)\n", dependency.getName(), + dependency.getDescription().getVersion(), status)); + } + } + msg.append(pre("\u00a77------------------------------\n")); + + if (config.getYamlConfig().getBoolean("plugin-updates.check", true) && updateChecker.isUpdateAvailable()) { + msg.append(pre("\u00a7bA new update of uSkyBlock is available: \u00a7f{0}\n", updateChecker.getLatestVersion())); + msg.append(pre("\u00a7fVisit {0} to download.\n", "https://www.uskyblock.ovh/get")); + } + + return msg.toString(); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/Scheduler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/Scheduler.java new file mode 100644 index 000000000..1550c8367 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/Scheduler.java @@ -0,0 +1,45 @@ +package us.talabrek.ultimateskyblock.util; + +import com.google.inject.Inject; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; + +import static dk.lockfuglsang.minecraft.util.TimeUtil.durationAsTicks; + +public class Scheduler { + + private final Plugin plugin; + + @Inject + public Scheduler(@NotNull Plugin plugin) { + this.plugin = plugin; + } + + public BukkitTask async(Runnable runnable) { + return Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable); + } + + public BukkitTask async(Runnable runnable, Duration delay) { + return Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, durationAsTicks(delay)); + } + + public BukkitTask async(Runnable runnable, Duration delay, Duration every) { + return Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, durationAsTicks(delay), durationAsTicks(every)); + } + + public BukkitTask sync(Runnable runnable) { + return Bukkit.getScheduler().runTask(plugin, runnable); + } + + public BukkitTask sync(Runnable runnable, Duration delay) { + return Bukkit.getScheduler().runTaskLater(plugin, runnable, durationAsTicks(delay)); + } + + public BukkitTask sync(Runnable runnable, Duration delay, Duration every) { + return Bukkit.getScheduler().runTaskTimer(plugin, runnable, durationAsTicks(delay), durationAsTicks(every)); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java index f03cfe371..66a94c630 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java @@ -10,13 +10,15 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import us.talabrek.ultimateskyblock.util.UUIDUtil; import java.io.File; import java.io.IOException; +import java.time.Duration; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -29,45 +31,43 @@ * PlayerDB backed by a simple yml-uuid2NameFile. */ public class FilePlayerDB implements PlayerDB { - private static final Logger log = Logger.getLogger(FilePlayerDB.class.getName()); + private final Logger logger; + private final Scheduler scheduler; private final File uuid2NameFile; private final FileConfiguration uuid2NameConfig; - private final uSkyBlock plugin; private boolean isShuttingDown = false; private volatile BukkitTask saveTask; - private final long saveDelay; + private final Duration saveDelay; // These caches should NOT be guavaCaches, we need them alive most of the time private final Map name2uuidCache = new ConcurrentHashMap<>(); private final Map uuid2nameCache = new ConcurrentHashMap<>(); - public FilePlayerDB(uSkyBlock plugin) { - this.plugin = plugin; + public FilePlayerDB(@NotNull uSkyBlock plugin, @NotNull Scheduler scheduler, @NotNull Logger logger) { + this.scheduler = scheduler; + this.logger = logger; uuid2NameFile = new File(plugin.getDataFolder(), "uuid2name.yml"); uuid2NameConfig = new YamlConfiguration(); if (uuid2NameFile.exists()) { FileUtil.readConfig(uuid2NameConfig, uuid2NameFile); } // Save max every 10 seconds - saveDelay = plugin.getConfig().getInt("playerdb.saveDelay", 10000); - plugin.async(new Runnable() { - @Override - public void run() { - synchronized (uuid2NameConfig) { - Set uuids = uuid2NameConfig.getKeys(false); - for (String uuid : uuids) { - UUID id = UUIDUtil.fromString(uuid); - String name = uuid2NameConfig.getString(uuid + ".name", null); - if (name != null && id != null) { - uuid2nameCache.put(id, name); - name2uuidCache.put(name, id); - List akas = uuid2NameConfig.getStringList(uuid + ".aka"); - for (String aka : akas) { - if (!name2uuidCache.containsKey(aka)) { - name2uuidCache.put(aka, id); - } + saveDelay = Duration.ofMillis(plugin.getConfig().getInt("playerdb.saveDelay", 10000)); + plugin.async(() -> { + synchronized (uuid2NameConfig) { + Set uuids = uuid2NameConfig.getKeys(false); + for (String uuid : uuids) { + UUID id = UUIDUtil.fromString(uuid); + String name = uuid2NameConfig.getString(uuid + ".name", null); + if (name != null && id != null) { + uuid2nameCache.put(id, name); + name2uuidCache.put(name, id); + List akas = uuid2NameConfig.getStringList(uuid + ".aka"); + for (String aka : akas) { + if (!name2uuidCache.containsKey(aka)) { + name2uuidCache.put(aka, id); } } } @@ -147,12 +147,7 @@ public String getDisplayName(String playerName) { public Set getNames(String search) { HashSet names = new HashSet<>(uuid2nameCache.values()); String lowerSearch = search != null ? search.toLowerCase() : null; - for (Iterator it = names.iterator(); it.hasNext(); ) { - String name = it.next(); - if (name == null || (search != null && !name.toLowerCase().startsWith(lowerSearch))) { - it.remove(); - } - } + names.removeIf(name -> name == null || (search != null && !name.toLowerCase().startsWith(lowerSearch))); return names; } @@ -164,12 +159,7 @@ public void updatePlayer(final UUID id, final String name, final String displayN } else { if (saveTask == null) { // Only have one pending save-task at a time - saveTask = plugin.async(new Runnable() { - @Override - public void run() { - saveToFile(); - } - }, saveDelay); + saveTask = scheduler.async(this::saveToFile, saveDelay); } } } @@ -213,7 +203,7 @@ private void saveToFile() { uuid2NameConfig.save(uuid2NameFile); } } catch (IOException e) { - log.log(Level.INFO, "Error saving playerdb", e); + logger.log(Level.INFO, "Error saving playerdb", e); } finally { saveTask = null; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/MemoryPlayerDB.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/MemoryPlayerDB.java index fd2fff293..fd3818a91 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/MemoryPlayerDB.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/MemoryPlayerDB.java @@ -5,11 +5,11 @@ import com.google.common.cache.LoadingCache; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; import java.util.HashSet; -import java.util.Iterator; import java.util.Set; import java.util.UUID; @@ -21,31 +21,31 @@ public class MemoryPlayerDB implements PlayerDB { private final LoadingCache uuidCache; private static final OfflinePlayer NULL_PLAYER = NullPlayer.INSTANCE; - public MemoryPlayerDB(FileConfiguration config) { + public MemoryPlayerDB(PluginConfig config) { nameCache = CacheBuilder - .from(config.getString("options.advanced.playerdb.nameCache", "maximumSize=1500,expireAfterWrite=30m,expireAfterAccess=15m")) - .build(new CacheLoader() { - @Override - public OfflinePlayer load(String name) throws Exception { - //noinspection deprecation - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name); - uuidCache.put(offlinePlayer.getUniqueId(), offlinePlayer); - return offlinePlayer; - } - }); + .from(config.getYamlConfig().getString("options.advanced.playerdb.nameCache", "maximumSize=1500,expireAfterWrite=30m,expireAfterAccess=15m")) + .build(new CacheLoader<>() { + @Override + public @NotNull OfflinePlayer load(@NotNull String name) { + //noinspection deprecation + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name); + uuidCache.put(offlinePlayer.getUniqueId(), offlinePlayer); + return offlinePlayer; + } + }); uuidCache = CacheBuilder - .from(config.getString("options.advanced.playerdb.uuidCache", "maximumSize=1500,expireAfterWrite=30m,expireAfterAccess=15m")) - .build(new CacheLoader() { - @Override - public OfflinePlayer load(UUID uuid) throws Exception { - OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - if (offlinePlayer.getName() != null) { - nameCache.put(offlinePlayer.getName(), offlinePlayer); - return offlinePlayer; - } - return NULL_PLAYER; + .from(config.getYamlConfig().getString("options.advanced.playerdb.uuidCache", "maximumSize=1500,expireAfterWrite=30m,expireAfterAccess=15m")) + .build(new CacheLoader<>() { + @Override + public @NotNull OfflinePlayer load(@NotNull UUID uuid) { + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); + if (offlinePlayer.getName() != null) { + nameCache.put(offlinePlayer.getName(), offlinePlayer); + return offlinePlayer; } - }); + return NULL_PLAYER; + } + }); } @Override @@ -93,29 +93,24 @@ public OfflinePlayer getOfflinePlayer(UUID uuid) { @Override public String getDisplayName(UUID uuid) { OfflinePlayer offlinePlayer = getOfflinePlayer(uuid); - return offlinePlayer != null && offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null - ? offlinePlayer.getPlayer().getDisplayName() - : null; + return offlinePlayer != null && offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null + ? offlinePlayer.getPlayer().getDisplayName() + : null; } @Override public String getDisplayName(String playerName) { OfflinePlayer offlinePlayer = getOfflinePlayer(playerName, true); - return offlinePlayer != null && offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null - ? offlinePlayer.getPlayer().getDisplayName() - : null; + return offlinePlayer != null && offlinePlayer.isOnline() && offlinePlayer.getPlayer() != null + ? offlinePlayer.getPlayer().getDisplayName() + : null; } @Override public Set getNames(String search) { Set names = new HashSet<>(nameCache.asMap().keySet()); String lowerSearch = search != null ? search.toLowerCase() : null; - for (Iterator it = names.iterator(); it.hasNext(); ) { - String name = it.next(); - if (name == null || (search != null && !name.toLowerCase().startsWith(lowerSearch))) { - it.remove(); - } - } + names.removeIf(name -> name == null || (search != null && !name.toLowerCase().startsWith(lowerSearch))); return names; } @@ -143,4 +138,4 @@ public void shutdown() { nameCache.cleanUp(); uuidCache.cleanUp(); } -} \ No newline at end of file +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java index 8e9c75289..c9e61dca2 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/world/WorldManager.java @@ -1,5 +1,8 @@ package us.talabrek.ultimateskyblock.world; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.apache.commons.lang3.Validate; import org.bukkit.Bukkit; import org.bukkit.Chunk; @@ -15,21 +18,29 @@ import org.bukkit.generator.ChunkGenerator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; +import us.talabrek.ultimateskyblock.hook.HookManager; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; -import java.io.File; import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; import static us.talabrek.ultimateskyblock.Settings.island_height; +@Singleton public class WorldManager { - private final uSkyBlock plugin; + private final Path schematicPath; + private final HookManager hookManager; + private final PluginConfig config; + private final Scheduler scheduler; private final Logger logger; public static volatile World skyBlockWorld; @@ -39,13 +50,24 @@ public class WorldManager { skyBlockWorld = null; } - public WorldManager(@NotNull uSkyBlock plugin) { - this.plugin = plugin; - this.logger = plugin.getLogger(); + @Inject + public WorldManager( + @NotNull uSkyBlock plugin, + @NotNull Logger logger, + @NotNull PluginConfig config, + @NotNull HookManager hookManager, + @NotNull Scheduler scheduler + ) { + this.schematicPath = plugin.getDataFolder().toPath().resolve("schematics").resolve("spawn.schem"); + this.hookManager = hookManager; + this.config = config; + this.logger = logger; + this.scheduler = scheduler; } /** * Get the {@link ChunkRegenerator} for the given {@link World}. + * * @param world World to get the ChunkRegenerator for. * @return ChunkRegenerator for the given world. */ @@ -56,6 +78,7 @@ public ChunkRegenerator getChunkRegenerator(@NotNull World world) { /** * Removes all unnamed {@link Monster}'s at the given {@link Location}. + * * @param target Location to remove unnamed monsters. */ public void removeCreatures(@Nullable final Location target) { @@ -69,12 +92,12 @@ public void removeCreatures(@Nullable final Location target) { for (int x = -1; x <= 1; ++x) { for (int z = -1; z <= 1; ++z) { Chunk chunk = target.getWorld().getChunkAt( - new Location(target.getWorld(), (px + x * 16), py, (pz + z * 16))); + new Location(target.getWorld(), (px + x * 16), py, (pz + z * 16))); Arrays.stream(chunk.getEntities()) - .filter(entity -> entity instanceof Monster) - .filter(entity -> entity.getCustomName() == null) - .forEach(Entity::remove); + .filter(entity -> entity instanceof Monster) + .filter(entity -> entity.getCustomName() == null) + .forEach(Entity::remove); } } } @@ -82,13 +105,14 @@ public void removeCreatures(@Nullable final Location target) { /** * Sets the spawn location for the given {@link World} if currently unset. Creates a safe spawn location if * necessary by calling {@link WorldManager#createSpawn(Location)}. - * @param world World to setup. + * + * @param world World to setup. * @param islandHeight Height at which islands will be created. */ private void setupWorld(@NotNull World world, int islandHeight) { Validate.notNull(world, "World cannot be null"); - if (!plugin.getConfig().getBoolean("options.advanced.manageSpawn")) { + if (!config.getYamlConfig().getBoolean("options.advanced.manageSpawn")) { return; } @@ -99,7 +123,7 @@ private void setupWorld(@NotNull World world, int islandHeight) { Location spawnLocation = world.getSpawnLocation(); if (!LocationUtil.isSafeLocation(spawnLocation)) { // Warn the user why we're doing this, because it's a FAQ on the forums: - plugin.getLogger().warning("Spawn location in " + world.getName() + " is considered unsafe. " + + logger.warning("Spawn location in " + world.getName() + " is considered unsafe. " + "Placing default spawn. This check can be disabled in config.yml, option manageSpawn."); createSpawn(spawnLocation); } @@ -108,18 +132,17 @@ private void setupWorld(@NotNull World world, int islandHeight) { /** * Creates the world spawn at the given {@link Location}. Places the spawn schematic if * configured and when it exists on disk. Places a gold block with two air above it otherwise. + * * @param spawnLocation Location to create the spawn at. */ private void createSpawn(@NotNull Location spawnLocation) { Validate.notNull(spawnLocation, "SpawnLocation cannot be null"); Validate.notNull(spawnLocation.getWorld(), "SpawnLocation#world cannot be null"); - File schematic = new File(plugin.getDataFolder() + File.separator + "schematics" + - File.separator + "spawn.schem"); World world = spawnLocation.getWorld(); - if (plugin.getConfig().getInt("options.general.spawnSize", 0) > 32 && schematic.exists()) { - AsyncWorldEditHandler.loadIslandSchematic(schematic, spawnLocation, null); + if (config.getYamlConfig().getInt("options.general.spawnSize", 0) > 32 && Files.exists(schematicPath)) { + AsyncWorldEditHandler.loadIslandSchematic(schematicPath.toFile(), spawnLocation, null); } else { Block spawnBlock = world.getBlockAt(spawnLocation).getRelative(BlockFace.DOWN); spawnBlock.setType(Material.GOLD_BLOCK); @@ -131,50 +154,55 @@ private void createSpawn(@NotNull Location spawnLocation) { /** * Gets the {@link ChunkGenerator} responsible for generating chunks in the overworld skyworld. + * * @return ChunkGenerator for overworld skyworld. */ @NotNull private ChunkGenerator getOverworldGenerator() { try { - String clazz = plugin.getConfig().getString("options.advanced.chunk-generator", - "us.talabrek.ultimateskyblock.world.SkyBlockChunkGenerator"); + String clazz = config.getYamlConfig().getString("options.advanced.chunk-generator", + "us.talabrek.ultimateskyblock.world.SkyBlockChunkGenerator"); Object generator = Class.forName(clazz).getDeclaredConstructor().newInstance(); if (generator instanceof ChunkGenerator) { return (ChunkGenerator) generator; } } catch (ClassNotFoundException ex) { logger.log(Level.WARNING, "Invalid overworld chunk-generator configured: " + ex); - } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex) { - plugin.getLogger().log(Level.WARNING, "Unable to instantiate overworld chunk-generator: " + ex); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException | + NoSuchMethodException ex) { + logger.log(Level.WARNING, "Unable to instantiate overworld chunk-generator: " + ex); } return new SkyBlockChunkGenerator(); } /** * Gets the {@link ChunkGenerator} responsible for generating chunks in the nether skyworld. + * * @return ChunkGenerator for nether skyworld. */ @NotNull private ChunkGenerator getNetherGenerator() { try { - String clazz = plugin.getConfig().getString("nether.chunk-generator", - "us.talabrek.ultimateskyblock.world.SkyBlockNetherChunkGenerator"); + String clazz = config.getYamlConfig().getString("nether.chunk-generator", + "us.talabrek.ultimateskyblock.world.SkyBlockNetherChunkGenerator"); Object generator = Class.forName(clazz).getDeclaredConstructor().newInstance(); if (generator instanceof ChunkGenerator) { return (ChunkGenerator) generator; } } catch (ClassNotFoundException ex) { logger.log(Level.WARNING, "Invalid nether chunk-generator configured: " + ex); - } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex) { - plugin.getLogger().log(Level.WARNING, "Unable to instantiate nether chunk-generator: " + ex); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException | + NoSuchMethodException ex) { + logger.log(Level.WARNING, "Unable to instantiate nether chunk-generator: " + ex); } return new SkyBlockNetherChunkGenerator(); } /** * Gets a {@link ChunkGenerator} for use in a default world, as specified in the server configuration + * * @param worldName Name of the world that this will be applied to - * @param id Unique ID, if any, that was specified to indicate which generator was requested + * @param id Unique ID, if any, that was specified to indicate which generator was requested * @return ChunkGenerator for use in the default world generation */ @Nullable @@ -182,13 +210,14 @@ public ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nulla Validate.notNull(worldName, "WorldName cannot be null"); return ((id != null && id.endsWith("nether")) || (worldName.endsWith("nether"))) - && Settings.nether_enabled - ? getNetherGenerator() - : getOverworldGenerator(); + && Settings.nether_enabled + ? getNetherGenerator() + : getOverworldGenerator(); } /** * Gets the skyblock island {@link World}. Creates and/or imports the world if necessary. + * * @return Skyblock island world. */ @NotNull @@ -198,24 +227,24 @@ public synchronized World getWorld() { ChunkGenerator skyGenerator = getOverworldGenerator(); ChunkGenerator worldGenerator = skyBlockWorld != null ? skyBlockWorld.getGenerator() : null; if (skyBlockWorld == null - || skyBlockWorld.canGenerateStructures() - || worldGenerator == null - || !worldGenerator.getClass().getName().equals(skyGenerator.getClass().getName())) { + || skyBlockWorld.canGenerateStructures() + || worldGenerator == null + || !worldGenerator.getClass().getName().equals(skyGenerator.getClass().getName())) { skyBlockWorld = WorldCreator - .name(Settings.general_worldName) - .type(WorldType.NORMAL) - .generateStructures(false) - .environment(World.Environment.NORMAL) - .generator(skyGenerator) - .createWorld(); + .name(Settings.general_worldName) + .type(WorldType.NORMAL) + .generateStructures(false) + .environment(World.Environment.NORMAL) + .generator(skyGenerator) + .createWorld(); skyBlockWorld.save(); } - plugin.getServer().getScheduler().runTaskLater(plugin, () -> - plugin.getHookManager().getMultiverse().ifPresent(hook -> { + scheduler.sync(() -> + hookManager.getMultiverse().ifPresent(hook -> { hook.registerOverworld(skyBlockWorld); setupWorld(skyBlockWorld, Settings.island_height); - }), plugin.getConfig().getLong("init.initDelay", 50L) + 40L); + }), TimeUtil.ticksAsDuration(config.getYamlConfig().getLong("init.initDelay", 50L) + 40L)); } return skyBlockWorld; @@ -224,6 +253,7 @@ public synchronized World getWorld() { /** * Gets the skyblock nether island {@link World}. Creates and/or imports the world if necessary. Returns null if * the nether is not enabled in the plugin configuration. + * * @return Skyblock nether island world, or null if nether is disabled. */ @Nullable @@ -237,24 +267,24 @@ public synchronized World getNetherWorld() { ChunkGenerator skyGenerator = getNetherGenerator(); ChunkGenerator worldGenerator = skyBlockNetherWorld != null ? skyBlockNetherWorld.getGenerator() : null; if (skyBlockNetherWorld == null - || skyBlockNetherWorld.canGenerateStructures() - || worldGenerator == null - || !worldGenerator.getClass().getName().equals(skyGenerator.getClass().getName())) { + || skyBlockNetherWorld.canGenerateStructures() + || worldGenerator == null + || !worldGenerator.getClass().getName().equals(skyGenerator.getClass().getName())) { skyBlockNetherWorld = WorldCreator - .name(Settings.general_worldName + "_nether") - .type(WorldType.NORMAL) - .generateStructures(false) - .environment(World.Environment.NETHER) - .generator(skyGenerator) - .createWorld(); + .name(Settings.general_worldName + "_nether") + .type(WorldType.NORMAL) + .generateStructures(false) + .environment(World.Environment.NETHER) + .generator(skyGenerator) + .createWorld(); skyBlockNetherWorld.save(); } - plugin.getServer().getScheduler().runTaskLater(plugin, () -> - plugin.getHookManager().getMultiverse().ifPresent(hook -> { + scheduler.sync(() -> + hookManager.getMultiverse().ifPresent(hook -> { hook.registerNetherworld(skyBlockNetherWorld); setupWorld(skyBlockNetherWorld, island_height / 2); - }), plugin.getConfig().getLong("init.initDelay", 50L) + 100L); + }), TimeUtil.ticksAsDuration(config.getYamlConfig().getLong("init.initDelay", 50L) + 100L)); } return skyBlockNetherWorld; @@ -262,6 +292,7 @@ public synchronized World getNetherWorld() { /** * Checks if the given {@link World} is the skyblock island world. + * * @param world World to check. * @return True if the given world is the skyblock island world, false otherwise. */ @@ -275,6 +306,7 @@ public boolean isSkyWorld(@Nullable World world) { /** * Checks if the given {@link World} is the skyblock nether island world. + * * @param world World to check. * @return True if the given world is the skyblock nether island world, false otherwise. */ @@ -289,6 +321,7 @@ public boolean isSkyNether(@Nullable World world) { /** * Checks if the given {@link World} is associated with Ultimate Skyblock. + * * @param world World to check. * @return True if the given world is associated with the plugin, false otherwise. */ @@ -298,7 +331,7 @@ public boolean isSkyAssociatedWorld(@Nullable World world) { } return world.getName().startsWith(WorldManager.skyBlockWorld.getName()) - && !(world.getEnvironment() == World.Environment.NETHER && !Settings.nether_enabled) - && !(world.getEnvironment() == World.Environment.THE_END); + && !(world.getEnvironment() == World.Environment.NETHER && !Settings.nether_enabled) + && !(world.getEnvironment() == World.Environment.THE_END); } } diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 5191e092e..a92ed219c 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -20,6 +20,7 @@ softdepend: api-version: 1.20.6 libraries: - com.google.code.gson:gson:${gson.version} + - com.google.inject:guice:${guice.version} - com.google.guava:guava:${guava.version} - net.kyori:adventure-api:${adventure-api.version} - net.kyori:adventure-platform-bukkit:${adventure-bukkit.version} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java index 8b8c04053..1405b8bf9 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java @@ -14,7 +14,6 @@ import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; -import us.talabrek.ultimateskyblock.uSkyBlock; import java.util.UUID; @@ -28,17 +27,13 @@ public class MenuEventsTest { @Before public void setUp() { - uSkyBlock fakePlugin = mock(uSkyBlock.class); fakeConfigMenu = mock(ConfigMenu.class); fakeMenu = mock(SkyBlockMenu.class); doNothing().when(fakeConfigMenu).onClick(any(InventoryClickEvent.class)); doNothing().when(fakeMenu).onClick(any(InventoryClickEvent.class)); - doReturn(fakeConfigMenu).when(fakePlugin).getConfigMenu(); - doReturn(fakeMenu).when(fakePlugin).getMenu(); - - menuEvents = new MenuEvents(fakePlugin); + menuEvents = new MenuEvents(fakeMenu, fakeConfigMenu); } @Test diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java index ba72060c9..7efab3daa 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogicTest.java @@ -5,7 +5,9 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.stubbing.Answer; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -29,6 +31,10 @@ import static org.mockito.Mockito.when; public class IslandLocatorLogicTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + @Test public void testNextIslandLocation() throws Exception { Settings.island_distance = 1; @@ -46,7 +52,7 @@ public void testNextIslandLocation() throws Exception { public void testNextIslandLocationReservation() throws Exception { Settings.island_distance = 10; uSkyBlock plugin = createPluginMock(); - IslandLocatorLogic locator = new IslandLocatorLogic(plugin); + IslandLocatorLogic locator = new IslandLocatorLogic(plugin, tempFolder.newFolder().toPath(), mock(), mock(), mock(), mock()); Player player = createPlayerMock(); Location location1 = locator.getNextIslandLocation(player); assertThat(location1, notNullValue()); @@ -59,7 +65,7 @@ public void testNextIslandLocationReservation() throws Exception { public void testNextIslandLocationReservationConcurrency() throws Exception { Settings.island_distance = 10; uSkyBlock plugin = createPluginMock(); - final IslandLocatorLogic locator = new IslandLocatorLogic(plugin); + final IslandLocatorLogic locator = new IslandLocatorLogic(plugin, tempFolder.newFolder().toPath(), mock(), mock(), mock(), mock()); final List locations = new ArrayList<>(); ThreadGroup threadGroup = new ThreadGroup("My"); for (int i = 0; i < 10; i++) { From a3a8580ff8f60ad5281048c624775e7f74c55da0 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 01:24:31 +0100 Subject: [PATCH 149/190] Refactor and test CooldownHandler --- .../lockfuglsang/minecraft/util/TimeUtil.java | 12 ++-- .../talabrek/ultimateskyblock/Settings.java | 21 +++--- .../bootstrap/SkyblockModule.java | 2 + .../command/admin/CooldownCommand.java | 56 +++++++-------- .../command/island/BiomeCommand.java | 7 +- .../command/island/CreateCommand.java | 18 ++--- .../command/island/RestartCommand.java | 7 +- .../handler/CooldownHandler.java | 72 ++++++++----------- .../handler/CooldownHandlerTest.java | 37 ++++++++++ .../ultimateskyblock/test/MutableClock.java | 33 +++++++++ 10 files changed, 168 insertions(+), 97 deletions(-) create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/CooldownHandlerTest.java create mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/test/MutableClock.java diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java index d60c8c64c..5dac6d6be 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java @@ -39,10 +39,14 @@ public static long stringAsMillis(String s) { } public static String millisAsString(long millis) { - long d = millis / DAYS; - long h = (millis % DAYS) / HOUR; - long m = (millis % HOUR) / MIN; - long s = (millis % MIN) / SEC; + return durationAsString(Duration.ofMillis(millis)); + } + + public static String durationAsString(Duration duration) { + long d = duration.toDaysPart(); + long h = duration.toHoursPart(); + long m = duration.toMinutesPart(); + long s = duration.toSecondsPart(); String str = ""; if (d > 0) { str += " " + d + tr("d"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index 13858905a..547f7df93 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -8,6 +8,7 @@ import org.bukkit.inventory.ItemStack; import us.talabrek.ultimateskyblock.handler.WorldEditHandler; +import java.time.Duration; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -32,8 +33,8 @@ public class Settings { public static boolean island_useIslandLevel; public static boolean island_useTopTen; public static int general_cooldownInfo; - public static int general_cooldownRestart; - public static int general_biomeChange; + public static Duration general_cooldownRestart; + public static Duration general_biomeChange; public static Biome general_defaultBiome; public static Biome general_defaultNetherBiome; public static boolean extras_sendToSpawn; @@ -83,23 +84,23 @@ public static boolean loadPluginConfig(FileConfiguration config) { general_cooldownInfo = 60; } try { - general_biomeChange = config.getInt("options.general.biomeChange"); - if (general_biomeChange < 0) { - general_biomeChange = 0; + general_biomeChange = Duration.ofSeconds(config.getInt("options.general.biomeChange")); + if (general_biomeChange.isNegative()) { + general_biomeChange = Duration.ZERO; } } catch (Exception e) { - general_biomeChange = 3600; + general_biomeChange = Duration.ofHours(1); } general_defaultBiome = loadBiome(config, "options.general.defaultBiome", Biome.OCEAN); general_defaultNetherBiome = loadBiome(config, "options.general.defaultNetherBiome", Biome.NETHER_WASTES); try { - general_cooldownRestart = config.getInt("options.general.cooldownRestart"); - if (general_cooldownRestart < 0) { - general_cooldownRestart = 0; + general_cooldownRestart = Duration.ofSeconds(config.getInt("options.general.cooldownRestart")); + if (general_cooldownRestart.isNegative()) { + general_cooldownRestart = Duration.ZERO; } } catch (Exception e) { - general_cooldownRestart = 60; + general_cooldownRestart = Duration.ofHours(1); } try { island_height = config.getInt("options.island.height"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java index 13225d5b2..a7236c8dd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java @@ -20,6 +20,7 @@ import us.talabrek.ultimateskyblock.uuid.PlayerDB; import java.nio.file.Path; +import java.time.Clock; import java.util.logging.Logger; public class SkyblockModule extends AbstractModule { @@ -38,6 +39,7 @@ protected void configure() { bind(Path.class).annotatedWith(PluginDataDir.class).toInstance(plugin.getDataFolder().toPath()); bind(LevelLogic.class).to(ChunkSnapshotLevelLogic.class); bind(UpdateChecker.class).to(SkyUpdateChecker.class); + bind(Clock.class).toInstance(Clock.systemUTC()); } @Provides diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java index 0f934ad96..e5b64efbb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/CooldownCommand.java @@ -4,14 +4,16 @@ import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import java.time.Duration; +import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -33,17 +35,16 @@ public boolean execute(CommandSender sender, String alias, Map d if (args.length < 2) { return false; } - //noinspection deprecation - Player p = Bukkit.getPlayer(args[0]); - if (p == null || !p.isOnline()) { + Player player = Bukkit.getPlayer(args[0]); + if (player == null || !player.isOnline()) { sender.sendMessage(tr("\u00a7eThe player is not currently online")); return false; } if ("restart|biome".contains(args[1])) { - if (plugin.getCooldownHandler().clearCooldown(p, args[1])) { - sender.sendMessage(tr("Cleared cooldown on {0} for {1}", args[1], p.getDisplayName())); + if (plugin.getCooldownHandler().clearCooldown(player, args[1])) { + sender.sendMessage(tr("Cleared cooldown on {0} for {1}", args[1], player.getDisplayName())); } else { - sender.sendMessage(tr("No active cooldown on {0} for {1} detected!", args[1], p.getDisplayName())); + sender.sendMessage(tr("No active cooldown on {0} for {1} detected!", args[1], player.getDisplayName())); } return true; } else { @@ -58,16 +59,15 @@ public boolean execute(CommandSender sender, String alias, Map d if (args.length < 2) { return false; } - //noinspection deprecation - Player p = Bukkit.getPlayer(args[0]); - if (p == null || !p.isOnline()) { + Player player = Bukkit.getPlayer(args[0]); + if (player == null || !player.isOnline()) { sender.sendMessage(tr("\u00a7eThe player is not currently online")); return false; } if ("restart|biome".contains(args[1])) { - int cooldown = getCooldown(args[1]); - plugin.getCooldownHandler().resetCooldown(p, args[1], cooldown); - sender.sendMessage(tr("\u00a7eReset cooldown on {0} for {1}\u00a7e to {2} seconds", args[1], p.getDisplayName(), cooldown)); + Duration cooldown = getCooldown(args[1]); + plugin.getCooldownHandler().resetCooldown(player, args[1], cooldown); + sender.sendMessage(tr("\u00a7eReset cooldown on {0} for {1}\u00a7e to {2} seconds", args[1], player.getDisplayName(), cooldown)); return true; } else { sender.sendMessage(tr("Invalid command supplied, only restart and biome supported!")); @@ -81,19 +81,20 @@ public boolean execute(CommandSender sender, String alias, Map d if (args.length < 1) { return false; } - //noinspection deprecation - Player p = Bukkit.getPlayer(args[0]); - if (p == null || !p.isOnline()) { + Player player = Bukkit.getPlayer(args[0]); + if (player == null || !player.isOnline()) { sender.sendMessage(tr("\u00a7eThe player is not currently online")); return false; } - Map map = plugin.getCooldownHandler().getCooldowns(p.getUniqueId()); + Map map = plugin.getCooldownHandler().getCooldowns(player.getUniqueId()); StringBuilder sb = new StringBuilder(); if (map != null && !map.isEmpty()) { - long now = System.currentTimeMillis(); - sb.append(tr("\u00a7eCmd Cooldown") + "\n"); - for (String cmd : map.keySet()) { - sb.append(tr("\u00a7a{0} \u00a7c{1}", cmd, TimeUtil.millisAsString(map.get(cmd) - now)) + "\n"); + Instant now = Instant.now(); + sb.append(tr("\u00a7eCmd Cooldown")).append("\n"); + for (var entry : map.entrySet()) { + String cmd = entry.getKey(); + Duration remainingCooldown = Duration.between(now, entry.getValue()); + sb.append(tr("\u00a7a{0} \u00a7c{1}", cmd, TimeUtil.durationAsString(remainingCooldown))).append("\n"); } } else { sb.append(tr("\u00a7eNo active cooldowns for \u00a79{0}\u00a7e found.", data.get("playerName"))); @@ -110,12 +111,11 @@ protected List getTabList(CommandSender commandSender, String term) { }); } - private int getCooldown(String cmd) { - switch (cmd) { - case "restart": return Settings.general_cooldownRestart; - case "biome": return Settings.general_biomeChange; - } - return 0; + private Duration getCooldown(String cmd) { + return switch (cmd) { + case "restart" -> Settings.general_cooldownRestart; + case "biome" -> Settings.general_biomeChange; + default -> Duration.ZERO; + }; } - } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index e07f844b3..1d7078524 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -18,6 +18,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -64,9 +65,9 @@ protected boolean doExecute(String alias, final Player player, PlayerInfo pi, fi player.sendMessage(tr("\u00a7cYou have misspelled the biome name. Must be one of {0}", biomeConfig.getConfiguredBiomeKeys())); return true; } - int cooldown = plugin.getCooldownHandler().getCooldown(player, "biome"); - if (cooldown > 0) { - player.sendMessage(tr("\u00a7eYou can change your biome again in {0,number,#} minutes.", cooldown / 60)); + Duration cooldown = plugin.getCooldownHandler().getCooldown(player, "biome"); + if (cooldown.isPositive()) { + player.sendMessage(tr("\u00a7eYou can change your biome again in {0,number,#} seconds.", cooldown.toSeconds())); return true; } if (!player.hasPermission("usb.biome." + biomeKey.toLowerCase())) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java index 7a5f21c8d..962e5a963 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/CreateCommand.java @@ -4,10 +4,12 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.Settings; +import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.api.event.CreateIslandEvent; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -26,23 +28,23 @@ public CreateCommand(@NotNull uSkyBlock plugin) { @Override protected boolean doExecute(String alias, Player player, Map data, String... args) { PlayerInfo pi = plugin.getPlayerInfo(player); - int cooldown = plugin.getCooldownHandler().getCooldown(player, "restart"); - if (!pi.getHasIsland() && cooldown == 0) { + Duration cooldown = plugin.getCooldownHandler().getCooldown(player, "restart"); + if (!pi.getHasIsland() && cooldown.isZero()) { String cSchem = args != null && args.length > 0 ? args[0] : Settings.island_schematicName; plugin.getServer().getPluginManager().callEvent(new CreateIslandEvent(player, cSchem)); } else if (pi.getHasIsland()) { - us.talabrek.ultimateskyblock.api.IslandInfo island = plugin.getIslandInfo(pi); + IslandInfo island = plugin.getIslandInfo(pi); if (island.isLeader(player)) { player.sendMessage(tr("\u00a74Island found!" + - "\u00a7e You already have an island. If you want a fresh island, type" + - "\u00a7b /is restart\u00a7e to get one")); + "\u00a7e You already have an island. If you want a fresh island, type" + + "\u00a7b /is restart\u00a7e to get one")); } else { player.sendMessage(tr("\u00a74Island found!" + - "\u00a7e You are already a member of an island. To start your own, first" + - "\u00a7b /is leave")); + "\u00a7e You are already a member of an island. To start your own, first" + + "\u00a7b /is leave")); } } else { - player.sendMessage(tr("\u00a7eYou can create a new island in {0,number,#} seconds.", cooldown)); + player.sendMessage(tr("\u00a7eYou can create a new island in {0,number,#} seconds.", cooldown.toSeconds())); } return true; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java index ba7377ff7..a343a4d79 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/RestartCommand.java @@ -9,6 +9,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -32,9 +33,9 @@ protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandIn } return true; } - int cooldown = plugin.getCooldownHandler().getCooldown(player, "restart"); - if (cooldown > 0) { - player.sendMessage(tr("\u00a7cYou can restart your island in {0} seconds.", cooldown)); + Duration cooldown = plugin.getCooldownHandler().getCooldown(player, "restart"); + if (cooldown.isPositive()) { + player.sendMessage(tr("\u00a7cYou can restart your island in {0} seconds.", cooldown.toSeconds())); return true; } else { if (pi.isIslandGenerating()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java index 4ef3d5ccd..1a1d7e439 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/CooldownHandler.java @@ -2,75 +2,65 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Clock; import java.time.Duration; -import java.util.Collections; +import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; /** * Responsible for handling various cooldowns on commands. */ @Singleton public class CooldownHandler { - // TODO: flatten map to use as key, use time API instead of long - private final Map> cooldowns = new HashMap<>(); + + private final Map cooldownExpires = new HashMap<>(); + private final Clock clock; private final Scheduler scheduler; + private record KeyPair(@NotNull UUID uuid, @NotNull String cmd) { + } + @Inject - public CooldownHandler(@NotNull Scheduler scheduler) { + public CooldownHandler(@NotNull Clock clock, @NotNull Scheduler scheduler) { + this.clock = clock; this.scheduler = scheduler; } - public int getCooldown(Player player, String cmd) { + public Duration getCooldown(@NotNull Player player, @NotNull String cmd) { if (player.hasPermission("usb.mod.bypasscooldowns") || player.hasPermission("usb.exempt.cooldown." + cmd)) { - return 0; - } - Map map = cooldowns.get(player.getUniqueId()); - if (map != null) { - Long timeout = map.get(cmd); - long now = System.currentTimeMillis(); - return timeout != null && timeout > now ? TimeUtil.millisAsSeconds(timeout - now) : 0; + return Duration.ZERO; } - return 0; + var now = clock.instant(); + var end = cooldownExpires.getOrDefault(new KeyPair(player.getUniqueId(), cmd), now); + var remaining = Duration.between(now, end); + return remaining.isNegative() ? Duration.ZERO : remaining; } - public void resetCooldown(final Player player, final String cmd, int cooldownSecs) { - UUID uuid = player.getUniqueId(); - if (!cooldowns.containsKey(uuid)) { - Map cdMap = new HashMap<>(); - cooldowns.put(uuid, cdMap); + public void resetCooldown(@NotNull Player player, @NotNull String cmd, @NotNull Duration cooldown) { + var key = new KeyPair(player.getUniqueId(), cmd); + if (cooldown.isZero() || cooldown.isNegative()) { + cooldownExpires.remove(key); + } else { + cooldownExpires.put(key, clock.instant().plus(cooldown)); + scheduler.sync(() -> cooldownExpires.remove(key), cooldown.plusSeconds(1)); } - if (cooldownSecs == 0) { - cooldowns.get(uuid).remove(cmd); - return; - } - cooldowns.get(uuid).put(cmd, System.currentTimeMillis() + TimeUtil.secondsAsMillis(cooldownSecs)); - scheduler.sync((Runnable) () -> { - Map cmdMap = cooldowns.get(player.getUniqueId()); - if (cmdMap != null) { - cmdMap.remove(cmd); - } - }, Duration.ofSeconds(cooldownSecs)); } - public boolean clearCooldown(Player player, String cmd) { - Map cmdMap = cooldowns.get(player.getUniqueId()); - if (cmdMap != null) { - return cmdMap.remove(cmd) != null; - } - return false; + public boolean clearCooldown(@NotNull Player player, @NotNull String cmd) { + var key = new KeyPair(player.getUniqueId(), cmd); + return cooldownExpires.remove(key) != null; } - public Map getCooldowns(UUID uuid) { - if (cooldowns.containsKey(uuid)) { - return cooldowns.get(uuid); - } - return Collections.emptyMap(); + public Map getCooldowns(@NotNull UUID uuid) { + return cooldownExpires.entrySet().stream() + .filter(e -> e.getKey().uuid().equals(uuid)) + .collect(Collectors.toMap(e -> e.getKey().cmd(), Map.Entry::getValue)); } } diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/CooldownHandlerTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/CooldownHandlerTest.java new file mode 100644 index 000000000..8eb408a64 --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/CooldownHandlerTest.java @@ -0,0 +1,37 @@ +package us.talabrek.ultimateskyblock.handler; + +import org.bukkit.entity.Player; +import org.junit.Test; +import us.talabrek.ultimateskyblock.test.MutableClock; + +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CooldownHandlerTest { + + @Test + public void testCommandCooldown() { + Instant fixedInstant = Instant.parse("2025-02-10T12:00:00Z"); + MutableClock testClock = new MutableClock(fixedInstant); + var cooldownHandler = new CooldownHandler(testClock, mock()); + UUID testId = new UUID(1, 2); + Player mockPlayer = mock(); + when(mockPlayer.getUniqueId()).thenReturn(testId); + + assertEquals(Duration.ZERO, cooldownHandler.getCooldown(mockPlayer, "test")); + + cooldownHandler.resetCooldown(mockPlayer, "test", Duration.ofSeconds(1)); + assertEquals(Duration.ofSeconds(1), cooldownHandler.getCooldown(mockPlayer, "test")); + + testClock.advance(Duration.ofSeconds(1)); + assertEquals(Duration.ZERO, cooldownHandler.getCooldown(mockPlayer, "test")); + + testClock.advance(Duration.ofSeconds(1)); + assertEquals(Duration.ZERO, cooldownHandler.getCooldown(mockPlayer, "test")); + } +} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/test/MutableClock.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/test/MutableClock.java new file mode 100644 index 000000000..bdec2bebf --- /dev/null +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/test/MutableClock.java @@ -0,0 +1,33 @@ +package us.talabrek.ultimateskyblock.test; + +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneId; + +public class MutableClock extends Clock { + private Instant instant; + + public MutableClock(Instant initialInstant) { + this.instant = initialInstant; + } + + @Override + public ZoneId getZone() { + return ZoneId.of("UTC"); + } + + @Override + public Clock withZone(ZoneId zone) { + return this; + } + + @Override + public Instant instant() { + return instant; + } + + public void advance(Duration duration) { + this.instant = this.instant.plus(duration); + } +} From d07d584b5afdb5163a5a227009b3b7a6885b2ddd Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 10:45:38 +0100 Subject: [PATCH 150/190] Remove unsafe concurrency from MakeLeaderCommand Many of the accessed objects (e.g., playerinfo, islandinfo, location, player, commandsender) are not threat-safe. --- .../command/admin/MakeLeaderCommand.java | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/MakeLeaderCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/MakeLeaderCommand.java index c038cdace..97e7ef618 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/MakeLeaderCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/MakeLeaderCommand.java @@ -4,6 +4,7 @@ import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Location; import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; @@ -19,7 +20,7 @@ public class MakeLeaderCommand extends AbstractCommand { private final uSkyBlock plugin; - public MakeLeaderCommand(uSkyBlock plugin) { + public MakeLeaderCommand(@NotNull uSkyBlock plugin) { super("makeleader|transfer", "usb.admin.makeleader", "leader oplayer", marktr("transfer leadership to another player")); this.plugin = plugin; } @@ -27,40 +28,35 @@ public MakeLeaderCommand(uSkyBlock plugin) { @Override public boolean execute(final CommandSender sender, String alias, Map data, final String... args) { if (args.length == 2) { - plugin.async(new Runnable() { - @Override - public void run() { - String islandPlayerName = args[0]; - String playerName = args[1]; - PlayerInfo currentLeader = plugin.getPlayerInfo(islandPlayerName); - PlayerInfo newLeader = plugin.getPlayerInfo(playerName); + String islandPlayerName = args[0]; + String playerName = args[1]; + PlayerInfo currentLeader = plugin.getPlayerInfo(islandPlayerName); + PlayerInfo newLeader = plugin.getPlayerInfo(playerName); - if (currentLeader == null || !currentLeader.getHasIsland()) { - sender.sendMessage(I18nUtil.tr("\u00a74Player {0} has no island to transfer!", islandPlayerName)); - return; - } - IslandInfo islandInfo = plugin.getIslandInfo(currentLeader); - if (islandInfo == null) { - sender.sendMessage(I18nUtil.tr("\u00a74Player {0} has no island to transfer!", islandPlayerName)); - return; - } - if (newLeader != null && newLeader.getHasIsland() && !newLeader.locationForParty().equals(islandInfo.getName())) { - sender.sendMessage(I18nUtil.tr("\u00a7ePlayer \u00a7d{0}\u00a7e already has an island.\u00a7eUse \u00a7d/usb island remove \u00a7e to remove him first.", playerName)); - return; - } - newLeader.setJoinParty(islandInfo.getIslandLocation()); - Location homeLocation = currentLeader.getHomeLocation(); - islandInfo.removeMember(currentLeader); // Remove leader - islandInfo.setupPartyLeader(newLeader.getPlayerName()); // Promote member - islandInfo.addMember(currentLeader); - newLeader.setHomeLocation(homeLocation); - currentLeader.save(); - newLeader.save(); - WorldGuardHandler.updateRegion(islandInfo); - plugin.getEventLogic().fireIslandLeaderChangedEvent(islandInfo, currentLeader, newLeader); - islandInfo.sendMessageToIslandGroup(true, marktr("\u00a7bLeadership transferred by {0}\u00a7b to {1}"), sender.getName(), playerName); - } - }); + if (currentLeader == null || !currentLeader.getHasIsland()) { + sender.sendMessage(I18nUtil.tr("\u00a74Player {0} has no island to transfer!", islandPlayerName)); + return true; + } + IslandInfo islandInfo = plugin.getIslandInfo(currentLeader); + if (islandInfo == null) { + sender.sendMessage(I18nUtil.tr("\u00a74Player {0} has no island to transfer!", islandPlayerName)); + return true; + } + if (newLeader != null && newLeader.getHasIsland() && !newLeader.locationForParty().equals(islandInfo.getName())) { + sender.sendMessage(I18nUtil.tr("\u00a7ePlayer \u00a7d{0}\u00a7e already has an island.\u00a7eUse \u00a7d/usb island remove \u00a7e to remove him first.", playerName)); + return true; + } + newLeader.setJoinParty(islandInfo.getIslandLocation()); + Location homeLocation = currentLeader.getHomeLocation(); + islandInfo.removeMember(currentLeader); // Remove leader + islandInfo.setupPartyLeader(newLeader.getPlayerName()); // Promote member + islandInfo.addMember(currentLeader); + newLeader.setHomeLocation(homeLocation); + currentLeader.save(); + newLeader.save(); + WorldGuardHandler.updateRegion(islandInfo); + plugin.getEventLogic().fireIslandLeaderChangedEvent(islandInfo, currentLeader, newLeader); + islandInfo.sendMessageToIslandGroup(true, marktr("\u00a7bLeadership transferred by {0}\u00a7b to {1}"), sender.getName(), playerName); return true; } return false; From a0404c3e039b23894bab9f1cbfe59cc5bd8eaa28 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 11:35:50 +0100 Subject: [PATCH 151/190] Move all scheduling to Scheduler Clean separation of concerns, de-clutter main plugin class, use improved Durations API --- .../command/InviteHandler.java | 12 +++-- .../command/island/InfoCommand.java | 21 ++++---- .../handler/AsyncWorldEditHandler.java | 2 +- .../island/level/AutoIslandLevelRefresh.java | 15 ++++-- .../island/task/GenerateTask.java | 52 ++++++++++--------- .../island/task/LocateChestTask.java | 11 ++-- .../island/task/RecalculateRunnable.java | 2 +- .../island/task/RecalculateTopTen.java | 25 ++++----- .../ultimateskyblock/menu/ConfigMenu.java | 6 ++- .../ultimateskyblock/menu/MainConfigMenu.java | 36 ++++++------- .../ultimateskyblock/player/PlayerInfo.java | 8 ++- .../talabrek/ultimateskyblock/uSkyBlock.java | 47 ++++------------- .../ultimateskyblock/uuid/FilePlayerDB.java | 2 +- .../handler/asyncworldedit/FAWEAdaptor.java | 13 ++--- 14 files changed, 120 insertions(+), 132 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java index b076772c8..194cb31ef 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java @@ -3,7 +3,6 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.po.I18nUtil; -import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -19,7 +18,9 @@ import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -37,10 +38,12 @@ public class InviteHandler implements Listener { private final Map inviteMap = new HashMap<>(); private final Map> waitingInvites = new HashMap<>(); private final uSkyBlock plugin; + private final Scheduler scheduler; @Inject - public InviteHandler(@NotNull uSkyBlock plugin) { + public InviteHandler(@NotNull uSkyBlock plugin, @NotNull Scheduler scheduler) { this.plugin = plugin; + this.scheduler = scheduler; } private synchronized void invite(Player player, final IslandInfo island, Player otherPlayer) { @@ -73,8 +76,8 @@ private synchronized void invite(Player player, final IslandInfo island, Player tr("\u00a7f/island [accept/reject]\u00a7e to accept or reject the invite."), tr("\u00a74WARNING: You will lose your current island if you accept!") }); - long timeout = TimeUtil.secondsAsMillis(plugin.getConfig().getInt("options.party.invite-timeout", 30)); - BukkitTask timeoutTask = plugin.async(() -> uninvite(island, uniqueId), timeout); + Duration timeout = Duration.ofSeconds(plugin.getConfig().getInt("options.party.invite-timeout", 30)); + BukkitTask timeoutTask = scheduler.async(() -> uninvite(island, uniqueId), timeout); invite.setTimeoutTask(timeoutTask); island.sendMessageToIslandGroup(true, I18nUtil.marktr("{0}\u00a7d invited {1}"), player.getDisplayName(), otherPlayer.getDisplayName()); } @@ -212,6 +215,7 @@ public void onRejectEvent(RejectEvent e) { } } + // TODO: cleanup @SuppressWarnings("UnusedDeclaration") private static class Invite { private final long time; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java index bc7655576..88b19bc48 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/InfoCommand.java @@ -12,19 +12,22 @@ import us.talabrek.ultimateskyblock.player.PatienceTester; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.LogUtil; import java.util.Map; import java.util.logging.Level; +import java.util.logging.Logger; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class InfoCommand extends RequireIslandCommand { + private final Logger logger; + @Inject - public InfoCommand(@NotNull uSkyBlock plugin) { + public InfoCommand(@NotNull uSkyBlock plugin, @NotNull Logger logger) { super(plugin, "info", "usb.island.info", "?island", marktr("check your or another''s island info")); + this.logger = logger; addFeaturePermission("usb.island.info.other", tr("allows user to see others island info")); } @@ -96,14 +99,12 @@ public void run() { PatienceTester.stopRunning(player, "usb.island.info.active"); } }; - plugin.sync(() -> { - try { - PatienceTester.startRunning(player, "usb.island.info.active"); - plugin.calculateScoreAsync(player, playerInfo.locationForParty(), showInfo); - } catch (Exception e) { - LogUtil.log(Level.SEVERE, "Error while calculating Island Level", e); - } - }, 1L); + try { + PatienceTester.startRunning(player, "usb.island.info.active"); + plugin.calculateScoreAsync(player, playerInfo.locationForParty(), showInfo); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error while calculating Island Level", e); + } return true; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java index 02ff035dd..e35c0554b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/AsyncWorldEditHandler.java @@ -110,7 +110,7 @@ public EditSession createEditSession(World world, int maxBlocks) { @Override public void regenerate(final Region region, final Runnable onCompletion) { - uSkyBlock.getInstance().sync(() -> { + uSkyBlock.getInstance().getScheduler().sync(() -> { try (EditSession editSession = WorldEditHandler.createEditSession(region.getWorld(), (int) region.getVolume())) { editSession.setReorderMode(EditSession.ReorderMode.MULTI_STAGE); editSession.setSideEffectApplier(SideEffectSet.defaults()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java index 76c787f9f..ee2c22c88 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/level/AutoIslandLevelRefresh.java @@ -7,30 +7,35 @@ import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.island.task.RecalculateRunnable; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import java.time.Duration; -import static dk.lockfuglsang.minecraft.util.TimeUtil.durationAsTicks; - @Singleton public class AutoIslandLevelRefresh { private final uSkyBlock plugin; private final PluginConfig config; + private final Scheduler scheduler; private BukkitTask autoRecalculateTask = null; @Inject - public AutoIslandLevelRefresh(@NotNull uSkyBlock plugin, @NotNull PluginConfig config) { + public AutoIslandLevelRefresh( + @NotNull uSkyBlock plugin, + @NotNull PluginConfig config, + @NotNull Scheduler scheduler + ) { this.plugin = plugin; this.config = config; + this.scheduler = scheduler; } public void startup() { int refreshEveryMinute = config.getYamlConfig().getInt("options.island.autoRefreshScore", 0); if (refreshEveryMinute > 0) { - long refreshTicks = durationAsTicks(Duration.ofMinutes(refreshEveryMinute)); - autoRecalculateTask = new RecalculateRunnable(plugin).runTaskTimer(plugin, refreshTicks, refreshTicks); + Duration refreshRate = Duration.ofMinutes(refreshEveryMinute); + autoRecalculateTask = scheduler.sync(new RecalculateRunnable(plugin), refreshRate, refreshRate); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/GenerateTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/GenerateTask.java index 0e10d8a38..99046fa67 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/GenerateTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/GenerateTask.java @@ -11,6 +11,9 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; + +import java.time.Duration; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -19,6 +22,7 @@ */ public class GenerateTask extends BukkitRunnable { private final uSkyBlock plugin; + private final Scheduler scheduler; private final Player player; private final PlayerInfo pi; private final Location next; @@ -29,6 +33,7 @@ public class GenerateTask extends BukkitRunnable { public GenerateTask(uSkyBlock plugin, final Player player, final PlayerInfo pi, final Location next, PlayerPerk playerPerk, String schematicName) { this.plugin = plugin; + this.scheduler = plugin.getScheduler(); this.player = player; this.pi = pi; this.next = next; @@ -59,33 +64,30 @@ public void run() { WorldGuardHandler.updateRegion(islandInfo); plugin.getCooldownHandler().resetCooldown(player, "restart", Settings.general_cooldownRestart); - plugin.sync(new Runnable() { - @Override - public void run() { - if (pi != null) { - pi.setIslandGenerating(false); - } - plugin.clearPlayerInventory(player); - if (player != null && player.isOnline()) { - if (plugin.getConfig().getBoolean("options.restart.teleportWhenReady", true)) { - player.sendMessage(tr("\u00a7aCongratulations! \u00a7eYour island has appeared.")); - if (AsyncWorldEditHandler.isAWE()) { - player.sendMessage(tr("\u00a7cNote:\u00a7e Construction might still be ongoing.")); - } - plugin.getTeleportLogic().homeTeleport(player, true); - } else { - player.sendMessage(new String[]{ - tr("\u00a7aCongratulations! \u00a7eYour island has appeared."), - tr("Use \u00a79/is h\u00a7r or the \u00a79/is\u00a7r menu to go there."), - tr("\u00a7cNote:\u00a7e Construction might still be ongoing.")}); - } - } - for (String command : plugin.getConfig().getStringList("options.restart.extra-commands")) { - plugin.execCommand(player, command, true); + scheduler.sync(() -> { + if (pi != null) { + pi.setIslandGenerating(false); + } + plugin.clearPlayerInventory(player); + if (player != null && player.isOnline()) { + if (plugin.getConfig().getBoolean("options.restart.teleportWhenReady", true)) { + player.sendMessage(tr("\u00a7aCongratulations! \u00a7eYour island has appeared.")); + if (AsyncWorldEditHandler.isAWE()) { + player.sendMessage(tr("\u00a7cNote:\u00a7e Construction might still be ongoing.")); } + plugin.getTeleportLogic().homeTeleport(player, true); + } else { + player.sendMessage( + tr("\u00a7aCongratulations! \u00a7eYour island has appeared."), + tr("Use \u00a79/is h\u00a7r or the \u00a79/is\u00a7r menu to go there."), + tr("\u00a7cNote:\u00a7e Construction might still be ongoing.") + ); } - }, plugin.getConfig().getInt("options.restart.teleportDelay", 2000) + } + for (String command : plugin.getConfig().getStringList("options.restart.extra-commands")) { + plugin.execCommand(player, command, true); + } + }, Duration.ofMillis(plugin.getConfig().getInt("options.restart.teleportDelay", 2000)) ); } } - diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java index ea6fc1802..230bec12e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java @@ -1,27 +1,28 @@ package us.talabrek.ultimateskyblock.island.task; import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; /** * A task that looks for a chest at an island location. */ public class LocateChestTask extends BukkitRunnable { - private final uSkyBlock plugin; private final Player player; private final Location islandLocation; private final GenerateTask onCompletion; + private final Scheduler scheduler; private final long timeout; private long tStart; public LocateChestTask(uSkyBlock plugin, Player player, Location islandLocation, GenerateTask onCompletion) { - this.plugin = plugin; + this.scheduler = plugin.getScheduler(); this.player = player; this.islandLocation = islandLocation; this.onCompletion = onCompletion; @@ -40,11 +41,11 @@ public void run() { } else { cancel(); if (chestLocation == null && player != null && player.isOnline()) { - player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.millisAsString(timeout-tStart))); + player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.millisAsString(timeout - tStart))); } if (onCompletion != null) { onCompletion.setChestLocation(chestLocation); - plugin.sync(onCompletion); + scheduler.sync(onCompletion); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateRunnable.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateRunnable.java index 7b2628e70..1b4ee07dc 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateRunnable.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateRunnable.java @@ -23,7 +23,7 @@ public void run() { } } if (!recalcIslands.isEmpty()) { - RecalculateTopTen runnable = new RecalculateTopTen(plugin, recalcIslands); + RecalculateTopTen runnable = new RecalculateTopTen(plugin, plugin.getScheduler(), recalcIslands); runnable.runTaskAsynchronously(plugin); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java index 3d69a2925..3b19352d1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/RecalculateTopTen.java @@ -1,34 +1,35 @@ package us.talabrek.ultimateskyblock.island.task; import org.bukkit.scheduler.BukkitRunnable; -import us.talabrek.ultimateskyblock.api.event.uSkyBlockEvent; import us.talabrek.ultimateskyblock.api.async.Callback; +import us.talabrek.ultimateskyblock.api.event.uSkyBlockEvent; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import java.util.Collection; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; -/** - */ public class RecalculateTopTen extends BukkitRunnable { - private final List locations; + private final Queue locations; private final uSkyBlock plugin; + private final Scheduler scheduler; - public RecalculateTopTen(uSkyBlock plugin, Set locations) { + public RecalculateTopTen(uSkyBlock plugin, Scheduler scheduler, Collection locations) { + this.locations = new ConcurrentLinkedQueue<>(locations); this.plugin = plugin; - this.locations = new ArrayList<>(locations); + this.scheduler = scheduler; } @Override public void run() { - if (!locations.isEmpty()) { - String islandName = locations.remove(0); + String islandName = locations.poll(); + if (islandName != null) { plugin.calculateScoreAsync(null, islandName, new Callback<>() { @Override public void run() { // We use the deprecated on purpose (the other would fail). - plugin.async(RecalculateTopTen.this); + scheduler.async(RecalculateTopTen.this); } }); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java index 231419c89..c513f7fc8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java @@ -9,6 +9,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import java.util.ArrayList; import java.util.List; @@ -25,12 +26,13 @@ public class ConfigMenu { @Inject public ConfigMenu( @NotNull uSkyBlock plugin, - @NotNull MenuItemFactory factory + @NotNull MenuItemFactory factory, + @NotNull Scheduler scheduler ) { FileConfiguration menuConfig = new YamlConfiguration(); FileUtil.readConfig(menuConfig, getClass().getClassLoader().getResourceAsStream("configmenu.yml")); this.editMenus = new ArrayList<>(); - this.mainMenu = new MainConfigMenu(plugin, menuConfig, factory, editMenus); + this.mainMenu = new MainConfigMenu(plugin, menuConfig, factory, scheduler, editMenus); this.editMenus.addAll(List.of( new IntegerEditMenu(menuConfig, factory, mainMenu), new BooleanEditMenu(menuConfig), diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java index 0f693311d..85f0a1b87 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java @@ -13,6 +13,7 @@ import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import java.io.File; import java.io.IOException; @@ -35,12 +36,14 @@ public class MainConfigMenu extends AbstractConfigMenu implements EditMenu { private final uSkyBlock plugin; private final MenuItemFactory factory; + private final Scheduler scheduler; private final List editMenus; - public MainConfigMenu(uSkyBlock plugin, FileConfiguration menuConfig, MenuItemFactory factory, List editMenus) { + public MainConfigMenu(uSkyBlock plugin, FileConfiguration menuConfig, MenuItemFactory factory, Scheduler scheduler, List editMenus) { super(menuConfig); this.plugin = plugin; this.factory = factory; + this.scheduler = scheduler; this.editMenus = editMenus; } @@ -131,27 +134,20 @@ else if (parent != null && parent.getType() == Material.PAPER) { } private void saveConfig(final Player player, final String configName, final int page) { - plugin.async(new Runnable() { - @Override - public void run() { - try { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - config.set("dirty", null); - config.save(new File(plugin.getDataFolder(), configName)); - plugin.sync(new Runnable() { - @Override - public void run() { - plugin.reloadConfig(); - player.sendMessage(tr("\u00a7eConfiguration saved and reloaded.")); - player.openInventory(createEditMenu(configName, null, page)); - } - }); - } catch (IOException e) { - player.sendMessage(tr("\u00a7cError! \u00a79Unable to save config file!")); - } + scheduler.async(() -> { + try { + FileConfiguration config = FileUtil.getYmlConfiguration(configName); + config.set("dirty", null); + config.save(new File(plugin.getDataFolder(), configName)); + scheduler.sync(() -> { + plugin.reloadConfig(); + player.sendMessage(tr("\u00a7eConfiguration saved and reloaded.")); + player.openInventory(createEditMenu(configName, null, page)); + }); + } catch (IOException e) { + player.sendMessage(tr("\u00a7cError! \u00a79Unable to save config file!")); } }); - } private Inventory createFileMenu(String filename, int page) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 18778bdb4..9c5d3eb89 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock.player; import dk.lockfuglsang.minecraft.file.FileUtil; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.apache.commons.lang3.Validate; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -19,6 +20,7 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; import us.talabrek.ultimateskyblock.util.LogUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; import us.talabrek.ultimateskyblock.util.UUIDUtil; import us.talabrek.ultimateskyblock.uuid.PlayerDB; @@ -44,6 +46,7 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap private static final long serialVersionUID = 1L; private static final int YML_VERSION = 1; private final uSkyBlock plugin; + private final Scheduler scheduler; private final String playerName; private String displayName; private UUID uuid; @@ -60,6 +63,7 @@ public class PlayerInfo implements Serializable, us.talabrek.ultimateskyblock.ap public PlayerInfo(String currentPlayerName, UUID playerUUID, uSkyBlock plugin, Path playerDataDirectory) { this.plugin = plugin; + this.scheduler = plugin.getScheduler(); this.uuid = playerUUID; this.playerName = currentPlayerName; // Prefer UUID over Name @@ -408,11 +412,11 @@ public boolean isClearInventoryOnNextEntry() { public void onTeleport(final Player player) { if (isClearInventoryOnNextEntry()) { - uSkyBlock.getInstance().sync(() -> uSkyBlock.getInstance().clearPlayerInventory(player), 50); + scheduler.sync(() -> plugin.clearPlayerInventory(player), TimeUtil.ticksAsDuration(1)); } List pending = playerData.getStringList("pending-commands"); if (!pending.isEmpty()) { - uSkyBlock.getInstance().execCommands(player, pending); + plugin.execCommands(player, pending); playerData.set("pending-commands", null); save(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index ecacad130..cf4e6c984 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -25,7 +25,6 @@ import org.bukkit.plugin.ServicePriority; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandLevel; @@ -155,6 +154,8 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage private BlockLimitLogic blockLimitLogic; @Inject private SkyUpdateChecker updateChecker; + @Inject + private Scheduler scheduler; private UltimateSkyblockApi api; @@ -713,9 +714,9 @@ public void execCommand(Player player, String command, boolean onlyInSky) { } } m = Pattern.compile("^\\{d=(?[0-9]+)\\}(.*)$").matcher(command); - int delay = 0; + Duration delay = Duration.ZERO; if (m.matches()) { - delay = Integer.parseInt(m.group("delay")); + delay = Duration.ofMillis(Long.parseLong(m.group("delay"))); command = m.group(2); } if (command.contains("{party}")) { @@ -729,11 +730,11 @@ public void execCommand(Player player, String command, boolean onlyInSky) { } } - private void doExecCommand(final Player player, final String command, int delay) { - if (delay == 0) { - sync(() -> doExecCommand(player, command)); - } else if (delay > 0) { - sync(() -> doExecCommand(player, command), delay); + private void doExecCommand(final Player player, final String command, Duration delay) { + if (delay.isZero()) { + scheduler.sync(() -> doExecCommand(player, command)); + } else if (delay.isPositive()) { + scheduler.sync(() -> doExecCommand(player, command), delay); } else { log(Level.INFO, "WARN: Misconfigured command found, with negative delay! " + command); } @@ -937,36 +938,6 @@ public boolean onCommand(@NotNull CommandSender sender, org.bukkit.command.@NotN return true; } - public BukkitTask async(Runnable runnable) { - return Bukkit.getScheduler().runTaskAsynchronously(this, runnable); - } - - public BukkitTask async(Runnable runnable, long delayMs) { - return Bukkit.getScheduler().runTaskLaterAsynchronously(this, runnable, - TimeUtil.millisAsTicks(delayMs)); - } - - public BukkitTask async(Runnable runnable, long delay, long every) { - return Bukkit.getScheduler().runTaskTimerAsynchronously(this, runnable, - TimeUtil.millisAsTicks(delay), - TimeUtil.millisAsTicks(every)); - } - - public BukkitTask sync(Runnable runnable) { - return Bukkit.getScheduler().runTask(this, runnable); - } - - public BukkitTask sync(Runnable runnable, long delayMs) { - return Bukkit.getScheduler().runTaskLater(this, runnable, - TimeUtil.millisAsTicks(delayMs)); - } - - public BukkitTask sync(Runnable runnable, long delay, long every) { - return Bukkit.getScheduler().runTaskTimer(this, runnable, - TimeUtil.millisAsTicks(delay), - TimeUtil.millisAsTicks(every)); - } - public void execCommands(Player player, List cmdList) { for (String cmd : cmdList) { execCommand(player, cmd, false); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java index 66a94c630..82a44c744 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/FilePlayerDB.java @@ -55,7 +55,7 @@ public FilePlayerDB(@NotNull uSkyBlock plugin, @NotNull Scheduler scheduler, @No } // Save max every 10 seconds saveDelay = Duration.ofMillis(plugin.getConfig().getInt("playerdb.saveDelay", 10000)); - plugin.async(() -> { + scheduler.async(() -> { synchronized (uuid2NameConfig) { Set uuids = uuid2NameConfig.getKeys(false); for (String uuid : uuids) { diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index 5e538560a..3ed2d1622 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.handler.asyncworldedit; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; @@ -12,6 +12,7 @@ import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; +import us.talabrek.ultimateskyblock.util.Scheduler; import java.io.File; import java.io.IOException; @@ -23,16 +24,16 @@ */ public class FAWEAdaptor implements AWEAdaptor { private static final Logger log = Logger.getLogger(FAWEAdaptor.class.getName()); - private uSkyBlock plugin; + private Scheduler scheduler; @Override public void onEnable(uSkyBlock plugin) { - this.plugin = plugin; + this.scheduler = plugin.getScheduler(); } @Override public void onDisable(uSkyBlock plugin) { - this.plugin = null; + this.scheduler = null; } @Override @@ -41,7 +42,7 @@ public synchronized void registerCompletion(Player player) { @Override public void loadIslandSchematic(final File file, final Location origin, final PlayerPerk playerPerk) { - plugin.async(() -> { + scheduler.async(() -> { if (file == null || !file.exists() || !file.canRead()) { log.log(Level.WARNING, "Unable to load schematic {}", file); return; @@ -77,7 +78,7 @@ public EditSession createEditSession(World bukkitWorld, int maxBlocks) { @Override public void regenerate(final Region region, final Runnable onCompletion) { // NOTE: Running this asynchronous MIGHT be a bit dangereous! Since pasting could interfere - plugin.async(() -> { + scheduler.async(() -> { try { EditSession editSession = createEditSession(region.getWorld(), -1); editSession.regenerate(region); From 6c5d661f2ebd22338fee23924dcf667f58af4282 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 16:23:56 +0100 Subject: [PATCH 152/190] Refactor time-related methods to use the java.time API instead of long magic --- .../lockfuglsang/minecraft/util/TimeUtil.java | 106 +++++---------- .../dk/lockfuglsang/minecraft/util/Timer.java | 31 +++++ .../api/ChallengeCompletion.java | 42 +++++- .../talabrek/ultimateskyblock/Settings.java | 4 +- .../async/IncrementalRunnable.java | 127 +++++++++--------- .../ultimateskyblock/async/JobManager.java | 36 ++--- .../ultimateskyblock/challenge/Challenge.java | 51 ++++--- .../challenge/ChallengeCompletion.java | 36 ++--- .../challenge/ChallengeCompletionLogic.java | 55 ++++---- .../challenge/ChallengeDefaults.java | 8 +- .../challenge/ChallengeFactory.java | 14 +- .../challenge/ChallengeLogic.java | 10 +- .../ultimateskyblock/challenge/Rank.java | 9 +- .../ultimateskyblock/challenge/Reward.java | 18 +-- .../command/InviteHandler.java | 77 +++-------- .../command/admin/FlatlandFixCommand.java | 3 +- .../command/admin/JobsCommand.java | 43 ++---- .../command/admin/ProtectAllCommand.java | 4 +- .../command/admin/PurgeCommand.java | 33 +++-- .../command/admin/task/ProtectAllTask.java | 10 +- .../command/admin/task/PurgeScanTask.java | 21 +-- .../command/admin/task/PurgeTask.java | 23 ++-- .../event/NetherTerraFormEvents.java | 2 +- .../ultimateskyblock/event/PlayerEvents.java | 38 ++++-- .../handler/ConfirmHandler.java | 34 ++--- .../handler/WorldEditHandler.java | 8 +- .../handler/asyncworldedit/PlayerJob.java | 40 +++--- .../task/WorldEditClearFlatlandTask.java | 2 +- .../imports/USBImporterExecutor.java | 18 ++- .../ultimateskyblock/island/IslandInfo.java | 45 ++++--- .../island/IslandLocatorLogic.java | 11 +- .../ultimateskyblock/island/IslandLogic.java | 54 ++++---- .../island/task/CreateIslandTask.java | 10 +- .../island/task/LocateChestTask.java | 19 +-- .../ultimateskyblock/menu/SkyBlockMenu.java | 88 ++++++------ .../player/PatienceTester.java | 31 +++-- .../ultimateskyblock/player/PlayerLogic.java | 2 +- .../player/PlayerNotifier.java | 14 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 2 +- .../util/ProgressTracker.java | 21 +-- 40 files changed, 609 insertions(+), 591 deletions(-) create mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/Timer.java diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java index 5dac6d6be..30afe24ad 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/TimeUtil.java @@ -1,5 +1,8 @@ package dk.lockfuglsang.minecraft.util; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.time.Duration; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -9,97 +12,60 @@ public enum TimeUtil { ; private static final Pattern TIME_PATTERN = Pattern.compile("((?[0-9]+)d)?\\s*((?[0-9]+)h)?\\s*((?[0-9]+)m)?\\s*((?[0-9]+)s)?\\s*((?[0-9]+)ms)?"); - private static final long SEC = 1000; - private static final long MIN = 60 * SEC; - private static final long HOUR = 60 * MIN; - private static final long DAYS = 24 * HOUR; - public static long stringAsMillis(String s) { - Matcher m = TIME_PATTERN.matcher(s); - if (m.matches()) { - long t = 0; - if (m.group("d") != null) { - t += Integer.parseInt(m.group("d"), 10) * DAYS; + public static @Nullable Duration stringAsDuration(@NotNull String specification) { + Matcher matcher = TIME_PATTERN.matcher(specification); + if (matcher.matches()) { + Duration result = Duration.ZERO; + if (matcher.group("d") != null) { + result = result.plusDays(Long.parseLong(matcher.group("d"))); } - if (m.group("h") != null) { - t += Integer.parseInt(m.group("h"), 10) * HOUR; + if (matcher.group("h") != null) { + result = result.plusHours(Long.parseLong(matcher.group("h"))); } - if (m.group("m") != null) { - t += Integer.parseInt(m.group("m"), 10) * MIN; + if (matcher.group("m") != null) { + result = result.plusMinutes(Long.parseLong(matcher.group("m"))); } - if (m.group("s") != null) { - t += Integer.parseInt(m.group("s"), 10) * SEC; + if (matcher.group("s") != null) { + result = result.plusSeconds(Long.parseLong(matcher.group("s"))); } - if (m.group("ms") != null) { - t += Integer.parseInt(m.group("ms"), 10); + if (matcher.group("ms") != null) { + result = result.plusMillis(Long.parseLong(matcher.group("ms"))); } - return t; + return result; } - return -1; - } - - public static String millisAsString(long millis) { - return durationAsString(Duration.ofMillis(millis)); + return null; } - public static String durationAsString(Duration duration) { - long d = duration.toDaysPart(); - long h = duration.toHoursPart(); - long m = duration.toMinutesPart(); - long s = duration.toSecondsPart(); - String str = ""; - if (d > 0) { - str += " " + d + tr("d"); + public static @NotNull String durationAsString(@NotNull Duration duration) { + String result = ""; + if (duration.toDaysPart() > 0) { + result += " " + duration.toDaysPart() + tr("d"); } - if (h > 0) { - str += " " + h + tr("h"); + if (duration.toHoursPart() > 0) { + result += " " + duration.toHoursPart() + tr("h"); } - if (m > 0) { - str += " " + m + tr("m"); + if (duration.toMinutesPart() > 0) { + result += " " + duration.toMinutesPart() + tr("m"); } - if (s > 0 || str.isEmpty()) { - str += " " + s + tr("s"); + if (duration.toSecondsPart() > 0 || result.isEmpty()) { + result += " " + duration.toSecondsPart() + tr("s"); } - return str.trim(); + return result.trim(); } - public static String millisAsShort(long millis) { - long m = millis / MIN; - long s = (millis % MIN) / SEC; - long ms = millis % SEC; + public static @NotNull String durationAsShort(@NotNull Duration duration) { + long m = duration.toMinutes(); + long s = duration.toSecondsPart(); + long ms = duration.toMillisPart(); return String.format(tr("{0,number,0}:{1,number,00}.{2,number,000}", m, s, ms)); } - public static String ticksAsString(int ticks) { - return millisAsString(ticks * 50); - } - - public static long secondsAsTicks(int secs) { - // 20 ticks per second = 50 ms per tick - return (secs * 100) / 5; - } - - public static long secondsAsMillis(long timeout) { - return timeout * 1000; - } - - public static int millisAsSeconds(long millis) { - return (int) Math.ceil(millis / 1000f); - } - - public static long millisAsTicks(long ms) { - return ms / 50; - } - - public static long ticksAsMillis(int ticks) { - return ticks * 50; - } - - public static long durationAsTicks(Duration duration) { + public static long durationAsTicks(@NotNull Duration duration) { return duration.toMillis() / 50; } - public static Duration ticksAsDuration(long ticks) { + public static @NotNull Duration ticksAsDuration(long ticks) { return Duration.ofMillis(ticks * 50); } } diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/Timer.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/Timer.java new file mode 100644 index 000000000..f271fec34 --- /dev/null +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/Timer.java @@ -0,0 +1,31 @@ +package dk.lockfuglsang.minecraft.util; + +import org.jetbrains.annotations.NotNull; + +import java.time.Duration; +import java.time.Instant; + +public class Timer { + + private final Instant start; + + public Timer(@NotNull Instant start) { + this.start = start; + } + + public Instant getStart() { + return start; + } + + public Duration elapsed() { + return Duration.between(start, Instant.now()); + } + + public String elapsedAsString() { + return TimeUtil.durationAsString(elapsed()); + } + + public static Timer start() { + return new Timer(Instant.now()); + } +} diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/ChallengeCompletion.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/ChallengeCompletion.java index 9d988c1c2..8139172c8 100644 --- a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/ChallengeCompletion.java +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/ChallengeCompletion.java @@ -1,12 +1,20 @@ package us.talabrek.ultimateskyblock.api; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.time.Duration; +import java.time.Instant; + /** * Represents a challenge-completion. + * * @since 2.7.0 */ public interface ChallengeCompletion { /** * The name of the challenge. + * * @return name of the challenge. * @since 2.7.0 */ @@ -14,13 +22,28 @@ public interface ChallengeCompletion { /** * The timestamp at which the cooldown runs out. + * * @return The timestamp at which the cooldown runs out. * @since 2.7.0 + * @deprecated Use {@link #cooldownUntil()} instead. */ - long getCooldownUntil(); + @Deprecated(since = "3.2.0") + default long getCooldownUntil() { + Instant cooldownUntil = cooldownUntil(); + return cooldownUntil == null ? 0 : cooldownUntil.toEpochMilli(); + } + + /** + * The timestamp at which the cooldown runs out. + * + * @return The timestamp at which the cooldown runs out, or null if there is no cooldown. + * @since 3.2.0 + */ + @Nullable Instant cooldownUntil(); /** * Whether or not the challenge is currently on cooldown. + * * @return Whether or not the challenge is currently on cooldown. * @since 2.7.0 */ @@ -28,13 +51,27 @@ public interface ChallengeCompletion { /** * How many milliseconds of the cooldown is left + * * @return How many milliseconds of the cooldown is left * @since 2.7.0 + * @deprecated Use {@link #getCooldown()} instead. + */ + @Deprecated(since = "3.2.0") + default long getCooldownInMillis() { + return getCooldown().toMillis(); + } + + /** + * How much of the cooldown is left + * + * @return The duration of the cooldown that is left + * @since 3.2.0 */ - long getCooldownInMillis(); + @NotNull Duration getCooldown(); /** * Total number of times the challenge has been completed + * * @return Total number of times the challenge has been completed * @since 2.7.0 */ @@ -42,6 +79,7 @@ public interface ChallengeCompletion { /** * Number of times the challenge has been completed within this cooldown. + * * @return Number of times the challenge has been completed within this cooldown. * @since 2.7.0 */ diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index 547f7df93..970b7b43d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -41,7 +41,7 @@ public class Settings { public static boolean extras_respawnAtIsland; public static boolean extras_obsidianToLava; public static String island_schematicName; - public static long island_topTenTimeout; + public static Duration island_topTenTimeout; public static boolean island_allowPvP; public static Locale locale = Locale.getDefault(); public static boolean nether_enabled; @@ -141,7 +141,7 @@ public static boolean loadPluginConfig(FileConfiguration config) { general_worldName = config.getString("options.general.worldName", "skyworld"); island_removeCreaturesByTeleport = config.getBoolean("options.island.removeCreaturesByTeleport"); island_allowIslandLock = config.getBoolean("options.island.allowIslandLock"); - island_topTenTimeout = config.getInt("options.island.topTenTimeout", 7); // Every 7 minutes + island_topTenTimeout = Duration.ofMinutes(config.getLong("options.island.topTenTimeout", 7)); island_allowPvP = config.getString("options.island.allowPvP", "deny").equalsIgnoreCase("allow") || config.getString("options.island.allowPvP", "false").equalsIgnoreCase("true"); Locale loc = I18nUtil.getLocale(config.getString("language", null)); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java index 9f200ea35..625fc13b4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/IncrementalRunnable.java @@ -1,10 +1,19 @@ package us.talabrek.ultimateskyblock.async; import dk.lockfuglsang.minecraft.util.TimeUtil; +import dk.lockfuglsang.minecraft.util.Timer; import org.bukkit.scheduler.BukkitRunnable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.lang.Math.max; + /** * Convenience template class for executing heavy tasks on the main thread. * @@ -24,98 +33,87 @@ * */ public abstract class IncrementalRunnable extends BukkitRunnable { + private final Scheduler scheduler; private Runnable onCompletion; - /** - * The maximum number of consecutive ms to execute a task. - */ - private final int maxMs; - private final int maxConsecutive; - private final int yieldDelay; - /** - * The time of creation + * The maximum number of consecutive ms to execute a task. */ - private double tStart = 0; + private final Duration maxIterationTime; + private final long maxConsecutiveRuns; + private final Duration yieldDelay; + private Timer lifetimeTimer = null; /** * The time of completion. */ - private double tCompleted = 0; + private Instant completed = null; /** - * Millis used in processing. + * Time used in processing. */ - private double tUsed = 0; + private Duration processingTimeUsed = Duration.ZERO; /** * The time of the current incremental run. */ - private double tRunning = 0; + private Timer iterationTimer = null; private volatile boolean isCancelled = false; - private int consecutiveRuns = 0; + private final AtomicInteger consecutiveRuns = new AtomicInteger(0); /** * Number of iterations in total (calls to tick()) */ - private volatile int iterations = 0; + private final AtomicInteger iterations = new AtomicInteger(0); /** * Number of server-ticks consumed. */ - private volatile int ticks = 0; + private final AtomicInteger ticksConsumed = new AtomicInteger(0); - public IncrementalRunnable(Scheduler scheduler, PluginConfig config) { - this(scheduler, null, - config.getYamlConfig().getInt("async.maxMs", 15), - config.getYamlConfig().getInt("async.maxConsecutiveTicks", 20), - config.getYamlConfig().getInt("async.yieldDelay", 2) - ); + public IncrementalRunnable(@NotNull Scheduler scheduler, @NotNull PluginConfig config) { + this(scheduler, config, null); } - public IncrementalRunnable(Scheduler scheduler, PluginConfig config, Runnable onCompletion) { + public IncrementalRunnable(@NotNull Scheduler scheduler, @NotNull PluginConfig config, @Nullable Runnable onCompletion) { this(scheduler, onCompletion, - config.getYamlConfig().getInt("async.maxMs", 15), - config.getYamlConfig().getInt("async.maxConsecutiveTicks", 20), - config.getYamlConfig().getInt("async.yieldDelay", 2) + Duration.ofMillis(config.getYamlConfig().getInt("async.maxMs", 15)), + config.getYamlConfig().getLong("async.maxConsecutiveTicks", 20), + TimeUtil.ticksAsDuration(config.getYamlConfig().getLong("async.yieldDelay", 2)) ); } - public IncrementalRunnable(Scheduler scheduler, Runnable onCompletion, int maxMs, int maxConsecutive, int yieldDelay) { + public IncrementalRunnable(@NotNull Scheduler scheduler, @Nullable Runnable onCompletion, @NotNull Duration maxIterationTime, long maxConsecutiveRuns, @NotNull Duration yieldDelay) { this.scheduler = scheduler; this.onCompletion = onCompletion; - this.maxMs = maxMs; - this.maxConsecutive = maxConsecutive; + this.maxIterationTime = maxIterationTime; + this.maxConsecutiveRuns = maxConsecutiveRuns; this.yieldDelay = yieldDelay; } - protected boolean hasTime() { - return millisActive() < maxMs && !isCancelled; - } - /** - * Used by sub-classes to see how much time they have left. + * Used by subclasses to see how much time they have left. * * @return The number of ms the current #execute() has been running. */ - protected long millisActive() { - return Math.round(t() - tRunning); + protected @NotNull Duration millisActive() { + return iterationTimer != null ? iterationTimer.elapsed() : Duration.ZERO; } - protected double millisLeft() { - return maxMs - millisActive(); + protected @NotNull Duration millisLeft() { + return maxIterationTime.minus(millisActive()); } public boolean stillTime() { - double millisPerTick = getTimeUsed() / (iterations != 0 ? iterations : 1); - return millisPerTick < millisLeft(); + Duration millisPerTick = getProcessingTimeUsed().dividedBy(max(iterations.get(), 1)); + return millisLeft().minus(millisPerTick).isPositive(); } protected boolean tick() { - iterations++; + iterations.incrementAndGet(); return stillTime(); } @@ -131,14 +129,15 @@ protected boolean tick() { * * @return the number of ms the task has been active. */ - public long getTimeElapsed() { - if (tCompleted != 0d) { - return Math.round(tCompleted - tStart); + public @NotNull Duration getTimeElapsed() { + if (completed != null) { + assert lifetimeTimer != null; + return Duration.between(lifetimeTimer.getStart(), completed); } - if (tStart == 0) { - return -1; + if (lifetimeTimer == null) { + return Duration.ZERO; } - return Math.round(t() - tStart); + return lifetimeTimer.elapsed(); } /** @@ -146,8 +145,8 @@ public long getTimeElapsed() { * * @return the number of ms the task has been actively executing. */ - public double getTimeUsed() { - return tUsed + (tRunning != 0 ? t() - tRunning : 0); + public @NotNull Duration getProcessingTimeUsed() { + return processingTimeUsed.plus(millisActive()); } public void cancel() { @@ -156,15 +155,15 @@ public void cancel() { @Override public final void run() { - tRunning = t(); - if (tStart == 0d) { - tStart = tRunning; + iterationTimer = Timer.start(); + if (lifetimeTimer == null) { + lifetimeTimer = Timer.start(); JobManager.addJob(this); } + int consecutiveRuns = this.consecutiveRuns.incrementAndGet(); try { - consecutiveRuns++; if (!execute() && !isCancelled) { - scheduler.sync(this, TimeUtil.ticksAsDuration(consecutiveRuns < maxConsecutive ? 0 : yieldDelay)); + scheduler.sync(this, consecutiveRuns < maxConsecutiveRuns ? Duration.ZERO : yieldDelay); } else { if (onCompletion != null && !isCancelled) { scheduler.sync(onCompletion); @@ -172,29 +171,25 @@ public final void run() { complete(); } } finally { - tUsed += (t() - tRunning); - tRunning = 0; - if (consecutiveRuns > maxConsecutive) { - consecutiveRuns = 0; + processingTimeUsed = processingTimeUsed.plus(iterationTimer.elapsed()); + iterationTimer = null; + if (consecutiveRuns > maxConsecutiveRuns) { + this.consecutiveRuns.set(0); } - ticks++; + ticksConsumed.incrementAndGet(); } } - private static double t() { - return System.nanoTime() / 1000000d; - } - protected void setOnCompletion(Runnable onCompletion) { this.onCompletion = onCompletion; } private void complete() { - tCompleted = t(); + completed = Instant.now(); JobManager.completeJob(this); } - public int getTicks() { - return ticks; + public int getTicksConsumed() { + return ticksConsumed.get(); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java index c3c6cbc14..0be42e7f6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java @@ -1,15 +1,19 @@ package us.talabrek.ultimateskyblock.async; +import java.time.Duration; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static java.lang.Math.max; + /** * Responsible for holding ongoing jobs, and recording status. */ -public enum JobManager {; - private static final ConcurrentMap jobStats = new ConcurrentHashMap<>(); +public enum JobManager { + ; + private static final ConcurrentMap jobStats = new ConcurrentHashMap<>(); public static void addJob(IncrementalRunnable runnable) { String jobName = runnable.getClass().getSimpleName(); @@ -27,7 +31,7 @@ public static void completeJob(IncrementalRunnable runnable) { jobStats.get(jobName).complete(runnable); } - public static Map getStats() { + public static Map getStats() { return Collections.unmodifiableMap(jobStats); } @@ -35,8 +39,8 @@ public static class Stats { private int jobs; private int jobsRunning; private long ticks; - private double timeActive; - private double timeElapsed; + private Duration timeActive; + private Duration timeElapsed; public Stats() { } @@ -48,9 +52,9 @@ public synchronized void add(IncrementalRunnable runnable) { public synchronized void complete(IncrementalRunnable runnable) { jobsRunning--; - ticks += runnable.getTicks(); - timeActive += runnable.getTimeUsed(); - timeElapsed += runnable.getTimeElapsed(); + ticks += runnable.getTicksConsumed(); + timeActive = timeActive.plus(runnable.getProcessingTimeUsed()); + timeElapsed = timeElapsed.plus(runnable.getTimeElapsed()); } public int getJobs() { @@ -61,24 +65,24 @@ public long getTicks() { return ticks; } - public double getTimeActive() { + public Duration getTimeActive() { return timeActive; } - public double getTimeElapsed() { + public Duration getTimeElapsed() { return timeElapsed; } - public double getAvgMsActivePerTick() { - return timeActive / (ticks > 0 ? ticks : 1); + public Duration getAvgRunningTimePerTick() { + return timeActive.dividedBy(max(1, ticks)); } - public double getAvgMsActivePerJob() { - return timeActive / (jobs > 0 ? jobs : 1); + public Duration getAvgRunningTimePerJob() { + return timeActive.dividedBy(max(1, jobs)); } - public double getAvgMsElapsedPerJob() { - return timeElapsed *1d / (jobs > 0 ? jobs : 1); + public Duration getAvgTimeElapsedPerJob() { + return timeElapsed.dividedBy(max(1, jobs)); } public int getRunningJobs() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java index b047b6b13..9d5b7b5c9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java @@ -10,6 +10,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -17,7 +18,9 @@ import java.util.stream.Collectors; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.*; +import static dk.lockfuglsang.minecraft.util.FormatUtil.join; +import static dk.lockfuglsang.minecraft.util.FormatUtil.prefix; +import static dk.lockfuglsang.minecraft.util.FormatUtil.wordWrap; /** * The data-object for a challenge @@ -49,7 +52,7 @@ static Type from(String s) { private final List requiredChallenges; private final double requiredLevel; private final Rank rank; - private final int resetInHours; + private final Duration resetDuration; private final ItemStack displayItem; private final String tool; private final ItemStack lockedItem; @@ -63,7 +66,7 @@ static Type from(String s) { public Challenge(String name, String displayName, String description, Type type, List requiredItems, @NotNull List requiredBlocks, List requiredEntities, List requiredChallenges, double requiredLevel, Rank rank, - int resetInHours, ItemStack displayItem, String tool, ItemStack lockedItem, int offset, + Duration resetDuration, ItemStack displayItem, String tool, ItemStack lockedItem, int offset, boolean takeItems, int radius, Reward reward, Reward repeatReward, int repeatLimit) { this.name = name; this.displayName = displayName; @@ -74,7 +77,7 @@ public Challenge(String name, String displayName, String description, Type type, this.requiredChallenges = requiredChallenges; this.requiredLevel = requiredLevel; this.rank = rank; - this.resetInHours = resetInHours; + this.resetDuration = resetDuration; this.displayItem = displayItem; this.tool = tool; this.lockedItem = lockedItem; @@ -140,8 +143,8 @@ public Rank getRank() { return rank; } - public int getResetInHours() { - return resetInHours; + public Duration getResetDuration() { + return resetDuration; } public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurrency) { @@ -153,32 +156,26 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr if (completion.getTimesCompleted() > 0 && isRepeatable()) { currentChallengeItem.setAmount(completion.getTimesCompleted() < currentChallengeItem.getMaxStackSize() ? completion.getTimesCompleted() : currentChallengeItem.getMaxStackSize()); if (completion.isOnCooldown()) { - long cooldown = completion.getCooldownInMillis(); + Duration cooldown = completion.getCooldown(); if (timesCompleted < getRepeatLimit() || getRepeatLimit() <= 0) { if (getRepeatLimit() > 0) { lores.add(tr("\u00a74You can complete this {0} more time(s).", getRepeatLimit() - timesCompleted)); } - if (cooldown >= ChallengeLogic.MS_DAY) { - final int days = (int) (cooldown / ChallengeLogic.MS_DAY); - lores.add(tr("\u00a74Requirements will reset in {0} days.", days)); - } else if (cooldown >= ChallengeLogic.MS_HOUR) { - final int hours = (int) (cooldown / ChallengeLogic.MS_HOUR); - lores.add(tr("\u00a74Requirements will reset in {0} hours.", hours)); - } else if (cooldown >= 0) { - final int minutes = Math.round((float) cooldown / ChallengeLogic.MS_MIN); - lores.add(tr("\u00a74Requirements will reset in {0} minutes.", minutes)); + if (cooldown.toDays() > 0) { + lores.add(tr("\u00a74Requirements will reset in {0} days.", cooldown.toDays())); + } else if (cooldown.toHours() > 0) { + lores.add(tr("\u00a74Requirements will reset in {0} hours.", cooldown.toHours())); + } else { + lores.add(tr("\u00a74Requirements will reset in {0} minutes.", cooldown.toMinutes())); } } else { lores.add(tr("\u00a74This challenge is currently unavailable.")); - if (cooldown >= ChallengeLogic.MS_DAY) { - final int days = (int) (cooldown / ChallengeLogic.MS_DAY); - lores.add(tr("\u00a74You can complete this again in {0} days.", days)); - } else if (cooldown >= ChallengeLogic.MS_HOUR) { - final int hours = (int) (cooldown / ChallengeLogic.MS_HOUR); - lores.add(tr("\u00a74You can complete this again in {0} hours.", hours)); - } else if (cooldown >= 0) { - final int minutes = Math.round((float) cooldown / ChallengeLogic.MS_MIN); - lores.add(tr("\u00a74You can complete this again in {0} minutes.", minutes)); + if (cooldown.toDays() > 0) { + lores.add(tr("\u00a74You can complete this again in {0} days.", cooldown.toDays())); + } else if (cooldown.toHours() > 0) { + lores.add(tr("\u00a74You can complete this again in {0} hours.", cooldown.toHours())); + } else { + lores.add(tr("\u00a74You can complete this again in {0} minutes.", cooldown.toMinutes())); } } } @@ -234,7 +231,7 @@ public ItemStack getDisplayItem(ChallengeCompletion completion, boolean withCurr lores.add(tr("\u00a7eMust be within {0} meters.", getRadius())); } List lines = wordWrap("\u00a7a" + reward.getRewardText(), 20, MAX_LINE); - lores.add(tr("\u00a76Item Reward: \u00a7a") + lines.get(0)); + lores.add(tr("\u00a76Item Reward: \u00a7a") + lines.getFirst()); lores.addAll(lines.subList(1, lines.size())); if (withCurrency) { lores.add(tr("\u00a76Currency Reward: \u00a7a{0}", reward.getCurrencyReward())); @@ -298,7 +295,7 @@ public String toString() { ", type=" + type + ", requiredItems='" + requiredItems + '\'' + ", rank='" + rank + '\'' + - ", resetInHours=" + resetInHours + + ", resetDuration=" + resetDuration + ", displayItem=" + displayItem + ", takeItems=" + takeItems + ", reward=" + reward + diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletion.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletion.java index bde4b07fa..33c479b95 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletion.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletion.java @@ -1,19 +1,18 @@ package us.talabrek.ultimateskyblock.challenge; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.time.Duration; +import java.time.Instant; + public class ChallengeCompletion implements us.talabrek.ultimateskyblock.api.ChallengeCompletion { private String name; - private long cooldownUntil; + private Instant cooldownUntil; private int timesCompleted; private int timesCompletedInCooldown; - public ChallengeCompletion(final String name) { - super(); - this.name = name; - this.cooldownUntil = 0L; - this.timesCompleted = 0; - } - - public ChallengeCompletion(final String name, final long cooldownUntil, final int timesCompleted, final int timesCompletedInCooldown) { + public ChallengeCompletion(final String name, @Nullable Instant cooldownUntil, final int timesCompleted, final int timesCompletedInCooldown) { super(); this.name = name; this.cooldownUntil = cooldownUntil; @@ -26,22 +25,23 @@ public String getName() { return this.name; } - public long getCooldownUntil() { + @Override + public @Nullable Instant cooldownUntil() { return this.cooldownUntil; } @Override public boolean isOnCooldown() { - return cooldownUntil < 0 || cooldownUntil > System.currentTimeMillis(); + return getCooldown().isPositive(); } @Override - public long getCooldownInMillis() { - if (cooldownUntil < 0) { - return -1; + public @NotNull Duration getCooldown() { + if (cooldownUntil == null) { + return Duration.ZERO; } - long now = System.currentTimeMillis(); - return cooldownUntil > now ? cooldownUntil - now : 0; + Duration remainingCooldown = Duration.between(Instant.now(), cooldownUntil); + return remainingCooldown.isNegative() ? Duration.ZERO : remainingCooldown; } @Override @@ -53,8 +53,8 @@ public int getTimesCompletedInCooldown() { return isOnCooldown() ? this.timesCompletedInCooldown : timesCompleted > 0 ? 1 : 0; } - public void setCooldownUntil(final long newCompleted) { - this.cooldownUntil = newCompleted; + public void setCooldownUntil(@Nullable Instant newCooldown) { + this.cooldownUntil = newCooldown; this.timesCompletedInCooldown = 0; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletionLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletionLogic.java index e09316eb5..d82904e71 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletionLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeCompletionLogic.java @@ -4,17 +4,19 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; import dk.lockfuglsang.minecraft.file.FileUtil; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import java.io.File; import java.io.IOException; +import java.time.Duration; +import java.time.Instant; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -34,20 +36,15 @@ public ChallengeCompletionLogic(uSkyBlock plugin, FileConfiguration config) { this.plugin = plugin; storeOnIsland = config.getString("challengeSharing", "island").equalsIgnoreCase("island"); completionCache = CacheBuilder - .from(plugin.getConfig().getString("options.advanced.completionCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) - .removalListener(new RemovalListener>() { - @Override - public void onRemoval(RemovalNotification> removal) { - saveToFile(removal.getKey(), removal.getValue()); - } - }) - .build(new CacheLoader>() { - @Override - public Map load(String id) throws Exception { - return loadFromFile(id); - } + .from(plugin.getConfig().getString("options.advanced.completionCache", "maximumSize=200,expireAfterWrite=15m,expireAfterAccess=10m")) + .removalListener((RemovalListener>) removal -> saveToFile(removal.getKey(), removal.getValue())) + .build(new CacheLoader<>() { + @Override + public @NotNull Map load(@NotNull String id) { + return loadFromFile(id); } - ); + } + ); storageFolder = new File(plugin.getDataFolder(), "completion"); if (!storageFolder.exists() || !storageFolder.isDirectory()) { storageFolder.mkdirs(); @@ -70,7 +67,9 @@ private void saveToConfiguration(FileConfiguration configuration, Map loadFromConfiguration(ConfigurationSect plugin.getChallengeLogic().populateChallenges(challengeMap); if (root != null) { for (String challengeName : challengeMap.keySet()) { + long firstCompleted = root.getLong(challengeName + ".firstCompleted", 0); + Instant firstCompletedDuration = firstCompleted > 0 ? Instant.ofEpochMilli(firstCompleted) : null; challengeMap.put(challengeName, new ChallengeCompletion( - challengeName, - root.getLong(challengeName + ".firstCompleted", 0), - root.getInt(challengeName + ".timesCompleted", 0), - root.getInt(challengeName + ".timesCompletedSinceTimer", 0) + challengeName, + firstCompletedDuration, + root.getInt(challengeName + ".timesCompleted", 0), + root.getInt(challengeName + ".timesCompletedSinceTimer", 0) )); } } @@ -135,10 +136,10 @@ public Map getChallenges(PlayerInfo playerInfo) { } catch (ExecutionException e) { plugin.getLogger().log(Level.WARNING, "Error fetching challenge-completion for id " + id); } - if ((challengeMap == null || challengeMap.isEmpty())) { + if (challengeMap.isEmpty()) { // Fetch from the player-yml file challengeMap = loadFromConfiguration(playerInfo.getConfig().getConfigurationSection("player.challenges")); - if (challengeMap != null && !challengeMap.isEmpty()) { + if (!challengeMap.isEmpty()) { completionCache.put(id, challengeMap); } // Wipe it @@ -157,12 +158,12 @@ public void completeChallenge(PlayerInfo playerInfo, String challengeName) { if (challenges.containsKey(challengeName)) { ChallengeCompletion completion = challenges.get(challengeName); if (!completion.isOnCooldown()) { - long resetInMillis = uSkyBlock.getInstance().getChallengeLogic().getResetInMillis(challengeName); - if (resetInMillis >= 0) { - long now = System.currentTimeMillis(); - completion.setCooldownUntil(now + resetInMillis); + Duration resetDuration = plugin.getChallengeLogic().getResetDuration(challengeName); + if (resetDuration.isPositive()) { + Instant now = Instant.now(); + completion.setCooldownUntil(now.plus(resetDuration)); } else { - completion.setCooldownUntil(resetInMillis); + completion.setCooldownUntil(null); } } completion.addTimesCompleted(); @@ -173,7 +174,7 @@ public void resetChallenge(PlayerInfo playerInfo, String challenge) { Map challenges = getChallenges(playerInfo); if (challenges.containsKey(challenge)) { challenges.get(challenge).setTimesCompleted(0); - challenges.get(challenge).setCooldownUntil(0L); + challenges.get(challenge).setCooldownUntil(null); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java index 9c6b80ea1..345200889 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeDefaults.java @@ -1,7 +1,9 @@ package us.talabrek.ultimateskyblock.challenge; +import java.time.Duration; + public class ChallengeDefaults { - public final int resetInHours; + public final Duration resetDuration; public final String displayItem = "LIME_STAINED_GLASS_PANE"; public final boolean requiresPreviousRank; public final String repeatableColor; @@ -14,10 +16,10 @@ public class ChallengeDefaults { public final boolean showLockedChallengeName; public final int repeatLimit; - ChallengeDefaults(int resetInHours, boolean requiresPreviousRank, String repeatableColor, String finishedColor, + ChallengeDefaults(Duration resetDuration, boolean requiresPreviousRank, String repeatableColor, String finishedColor, String challengeColor, int rankLeeway, boolean enableEconomyPlugin, boolean broadcastCompletion, int radius, boolean showLockedChallengeName, int repeatLimit) { - this.resetInHours = resetInHours; + this.resetDuration = resetDuration; this.requiresPreviousRank = requiresPreviousRank; this.repeatableColor = repeatableColor; this.finishedColor = finishedColor; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index ecace5327..2435da82c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -9,7 +9,13 @@ import org.bukkit.inventory.ItemStack; import us.talabrek.ultimateskyblock.util.MetaUtil; -import java.util.*; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,7 +36,7 @@ public static void setLogger(Logger log) { public static ChallengeDefaults createDefaults(ConfigurationSection section) { return new ChallengeDefaults( - section.getInt("defaultResetInHours", 144), + Duration.ofHours(section.getLong("defaultResetInHours", 144L)), section.getBoolean("requiresPreviousRank", true), normalize(section.getString("repeatableColor", "&a")), normalize(section.getString("finishedColor", "&2")), @@ -55,7 +61,7 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, List requiredBlocks = section.getStringList("requiredBlocks").stream() .map(ItemStackUtil::createBlockRequirement).toList(); List requiredEntities = createEntities(section.getStringList("requiredEntities")); - int resetInHours = section.getInt("resetInHours", rank.getResetInHours()); + Duration resetDuration = Duration.ofHours(section.getLong("resetInHours", rank.getResetDuration().toHours())); String description = section.getString("description"); ItemStack displayItem = createItemStack( section.getString("displayItem", defaults.displayItem), @@ -73,7 +79,7 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, int repeatLimit = section.getInt("repeatLimit", 0); return new Challenge(name, displayName, description, type, requiredItems, requiredBlocks, requiredEntities, requiredChallenges, section.getDouble("requiredLevel", 0d), - rank, resetInHours, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, + rank, resetDuration, displayItem, section.getString("tool", null), lockedItem, offset, takeItems, radius, reward, repeatReward, repeatLimit); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index d60edc28f..8c29a2daa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -31,6 +31,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -56,9 +57,6 @@ */ @Singleton public class ChallengeLogic implements Listener { - public static final long MS_MIN = 60 * 1000; - public static final long MS_HOUR = 60 * MS_MIN; - public static final long MS_DAY = 24 * MS_HOUR; public static final int COLS_PER_ROW = 9; public static final int ROWS_OF_RANKS = 5; public static final int CHALLENGE_PAGESIZE = ROWS_OF_RANKS * COLS_PER_ROW; @@ -428,8 +426,8 @@ private boolean giveReward(Player player, Challenge challenge) { return true; } - public long getResetInMillis(String challenge) { - return getChallenge(challenge).getResetInHours() * MS_HOUR; + public Duration getResetDuration(String challenge) { + return getChallenge(challenge).getResetDuration(); } public ItemStack getItemStack(PlayerInfo playerInfo, String challengeName) { @@ -457,7 +455,7 @@ public void populateChallenges(Map challengeMap) { for (Challenge challenge : rank.getChallenges()) { String key = challenge.getName().toLowerCase(); if (!challengeMap.containsKey(key)) { - challengeMap.put(key, new ChallengeCompletion(key, 0L, 0, 0)); + challengeMap.put(key, new ChallengeCompletion(key, null, 0, 0)); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Rank.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Rank.java index b11e2e011..154e85547 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Rank.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Rank.java @@ -1,12 +1,13 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.util.FormatUtil; +import dk.lockfuglsang.minecraft.util.ItemStackUtil; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import us.talabrek.ultimateskyblock.player.PlayerInfo; -import dk.lockfuglsang.minecraft.util.FormatUtil; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -110,7 +111,7 @@ private int getLeeway(PlayerInfo playerInfo) { return leeway; } - public int getResetInHours() { - return config.getInt("resetInHours", defaults.resetInHours); + public Duration getResetDuration() { + return Duration.ofHours(config.getLong("resetInHours", defaults.resetDuration.toHours())); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java index 7ee0bc1f5..8ba5bfe2f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Reward.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.challenge; -import org.bukkit.inventory.ItemStack; import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; @@ -11,7 +11,7 @@ * A reward record */ public class Reward { - private static final Random RND = new Random(System.currentTimeMillis()); + private static final Random RND = new Random(); private final List itemReward; private final String permissionReward; @@ -62,13 +62,13 @@ public List getCommands() { @Override public String toString() { return "Reward{" + - "itemReward=" + itemReward + - ", permissionReward='" + permissionReward + '\'' + - ", currencyReward=" + currencyReward + - ", xpReward=" + xpReward + - ", rewardText='" + rewardText + '\'' + - ", commands=" + commands + - '}'; + "itemReward=" + itemReward + + ", permissionReward='" + permissionReward + '\'' + + ", currencyReward=" + currencyReward + + ", xpReward=" + xpReward + + ", rewardText='" + rewardText + '\'' + + ", commands=" + commands + + '}'; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java index 194cb31ef..52e025e6f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/InviteHandler.java @@ -67,33 +67,28 @@ private synchronized void invite(Player player, final IslandInfo island, Player } final UUID uniqueId = otherPlayer.getUniqueId(); invites.put(uniqueId, otherPlayer.getName()); - final Invite invite = new Invite(island.getName(), uniqueId, player.getDisplayName()); - inviteMap.put(uniqueId, invite); - waitingInvites.put(island.getName(), invites); player.sendMessage(tr("\u00a7aInvite sent to {0}", otherPlayer.getDisplayName())); - otherPlayer.sendMessage(new String[]{ - tr("{0}\u00a7e has invited you to join their island!", player.getDisplayName()), + otherPlayer.sendMessage(tr("{0}\u00a7e has invited you to join their island!", player.getDisplayName()), tr("\u00a7f/island [accept/reject]\u00a7e to accept or reject the invite."), - tr("\u00a74WARNING: You will lose your current island if you accept!") - }); + tr("\u00a74WARNING: You will lose your current island if you accept!")); Duration timeout = Duration.ofSeconds(plugin.getConfig().getInt("options.party.invite-timeout", 30)); BukkitTask timeoutTask = scheduler.async(() -> uninvite(island, uniqueId), timeout); - invite.setTimeoutTask(timeoutTask); + final Invite invite = new Invite(island.getName(), player.getDisplayName(), timeoutTask); + inviteMap.put(uniqueId, invite); + waitingInvites.put(island.getName(), invites); island.sendMessageToIslandGroup(true, I18nUtil.marktr("{0}\u00a7d invited {1}"), player.getDisplayName(), otherPlayer.getDisplayName()); } private synchronized boolean reject(Player player) { Invite invite = inviteMap.remove(player.getUniqueId()); if (invite != null) { - if (invite.getTimeoutTask() != null) { - invite.getTimeoutTask().cancel(); - } - IslandInfo island = plugin.getIslandInfo(invite.getIslandName()); + invite.timeoutTask().cancel(); + IslandInfo island = plugin.getIslandInfo(invite.islandName()); if (island != null) { island.sendMessageToIslandGroup(true, marktr("{0}\u00a7e has rejected the invitation."), player.getDisplayName()); } - if (waitingInvites.containsKey(invite.getIslandName())) { - waitingInvites.get(invite.getIslandName()).remove(player.getUniqueId()); + if (waitingInvites.containsKey(invite.islandName())) { + waitingInvites.get(invite.islandName()).remove(player.getUniqueId()); } return true; } @@ -109,17 +104,15 @@ private synchronized boolean accept(final Player player) { } Invite invite = inviteMap.remove(uuid); if (invite != null) { - if (invite.getTimeoutTask() != null) { - invite.getTimeoutTask().cancel(); - } + invite.timeoutTask().cancel(); PlayerInfo pi = plugin.getPlayerInfo(player); - final IslandInfo island = plugin.getIslandInfo(invite.getIslandName()); + final IslandInfo island = plugin.getIslandInfo(invite.islandName()); boolean deleteOldIsland = false; if (pi.getHasIsland() && pi.getIslandLocation() != null) { String islandName = WorldGuardHandler.getIslandNameAt(pi.getIslandLocation()); deleteOldIsland = !island.getName().equals(islandName); } - Map uuids = waitingInvites.get(invite.getIslandName()); + Map uuids = waitingInvites.get(invite.islandName()); if (uuids != null) { uuids.remove(uuid); } @@ -173,10 +166,10 @@ private synchronized boolean uninvite(IslandInfo islandInfo, UUID uuid) { if (invites != null && invites.contains(uuid)) { Invite invite = inviteMap.remove(uuid); invites.remove(uuid); - if (invite != null && invite.getTimeoutTask() != null) { - invite.getTimeoutTask().cancel(); + if (invite != null) { + invite.timeoutTask().cancel(); } - islandInfo.sendMessageToIslandGroup(true, marktr("\u00a7eInvitation for {0}\u00a7e has timedout or been cancelled."), invite.getDisplayName()); + islandInfo.sendMessageToIslandGroup(true, marktr("\u00a7eInvitation for {0}\u00a7e has timedout or been cancelled."), invite.displayName()); Player player = Bukkit.getPlayer(uuid); if (player != null && player.isOnline()) { player.sendMessage(tr("\u00a7eInvitation for {0}''s island has timedout or been cancelled.", islandInfo.getLeader())); @@ -215,44 +208,6 @@ public void onRejectEvent(RejectEvent e) { } } - // TODO: cleanup - @SuppressWarnings("UnusedDeclaration") - private static class Invite { - private final long time; - private final String islandName; - private final UUID uniqueId; - private final String displayName; - private BukkitTask timeoutTask; - - public Invite(String islandName, UUID uniqueId, String displayName) { - this.islandName = islandName; - this.uniqueId = uniqueId; - this.displayName = displayName; - time = System.currentTimeMillis(); - } - - public long getTime() { - return time; - } - - public String getIslandName() { - return islandName; - } - - public UUID getUniqueId() { - return uniqueId; - } - - public String getDisplayName() { - return displayName; - } - - public BukkitTask getTimeoutTask() { - return timeoutTask; - } - - public void setTimeoutTask(BukkitTask timeoutTask) { - this.timeoutTask = timeoutTask; - } + private record Invite(String islandName, String displayName, BukkitTask timeoutTask) { } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java index 6436917d1..845ce4689 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/FlatlandFixCommand.java @@ -12,6 +12,7 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -52,7 +53,7 @@ public boolean execute(CommandSender sender, String alias, Map d private boolean tryFlatlandFix(CommandSender sender, Location islandLocation) { // TODO: 29/12/2014 - R4zorax: Load chunks first? - if (!plugin.getIslandLogic().clearFlatland(sender, islandLocation, 0)) { + if (!plugin.getIslandLogic().clearFlatland(sender, islandLocation, Duration.ZERO)) { sender.sendMessage(tr("\u00a74No flatland detected at {0}''s island!", LocationUtil.asString(islandLocation))); } return true; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java index aae41ca8a..635d3b3fc 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/JobsCommand.java @@ -3,11 +3,9 @@ import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; import dk.lockfuglsang.minecraft.command.CompositeCommand; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.async.JobManager; -import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; import java.util.ArrayList; import java.util.Collections; @@ -21,53 +19,36 @@ * Command for reporting and controlling async jobs. */ public class JobsCommand extends CompositeCommand { - private final uSkyBlock plugin; @Inject - public JobsCommand(@NotNull uSkyBlock plugin) { + public JobsCommand() { super("jobs|j", "usb.admin.jobs", marktr("controls async jobs")); - this.plugin = plugin; - /* - add(new AbstractCommand("list|l", "usb.admin.jobs.list", "list all jobs") { - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - return false; - } - }); - */ + add(new AbstractCommand("stats|s", "usb.admin.jobs.stats", "show statistics") { @Override public boolean execute(CommandSender sender, String alias, Map data, String... args) { StringBuilder sb = new StringBuilder(); - sb.append(tr("\u00a79Job Statistics") + "\n"); - sb.append(tr("\u00a77----------------") + "\n"); + sb.append(tr("\u00a79Job Statistics")).append("\n"); + sb.append(tr("\u00a77----------------")).append("\n"); Map stats = JobManager.getStats(); List jobs = new ArrayList<>(stats.keySet()); Collections.sort(jobs); sb.append(String.format("\u00a77%-6s %-8s %-8s %-8s %-8s %-8s %-20s\n", - tr("#"), tr("ms/job"), tr("ms/tick"), tr("ticks"), tr("act"), tr("time"), tr("name"))); + tr("#"), tr("ms/job"), tr("ms/tick"), tr("ticks"), tr("act"), tr("time"), tr("name"))); for (String jobName : jobs) { JobManager.Stats stat = stats.get(jobName); sb.append(String.format("\u00a77%6d %8s %8s %8d \u00a7c%8d \u00a77%8s \u00a79%-20s \n", stat.getJobs(), - TimeUtil.millisAsShort(Math.round(stat.getAvgMsActivePerJob())), - TimeUtil.millisAsShort(Math.round(stat.getAvgMsActivePerTick())), - stat.getTicks(), - stat.getRunningJobs(), - TimeUtil.millisAsShort(Math.round(stat.getAvgMsElapsedPerJob())), - tr(jobName) + TimeUtil.durationAsShort(stat.getAvgRunningTimePerJob()), + TimeUtil.durationAsShort(stat.getAvgRunningTimePerTick()), + stat.getTicks(), + stat.getRunningJobs(), + TimeUtil.durationAsShort(stat.getAvgTimeElapsedPerJob()), + tr(jobName) )); } sender.sendMessage(sb.toString().split("\n")); return true; } }); - /* - add(new AbstractCommand("report|r", "usb.admin.jobs.report", "dump report to file") { - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - return false; - } - }); - */ } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java index 1526e23cb..283b8c0b0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ProtectAllCommand.java @@ -9,6 +9,7 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.ProgressTracker; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -47,7 +48,8 @@ public boolean execute(CommandSender sender, String alias, Map d } } sender.sendMessage(tr("\u00a7eStarting a protect-all task. It will take a while.")); - ProgressTracker tracker = new ProgressTracker(sender, "\u00a77- Protect-All {0,number,##}% ({1}/{2}, failed:{3}, skipped:{4}) ~ {5}", 10, plugin.getConfig().getInt("async.long.feedbackEvery", 30000)); + Duration feedbackFrequency = Duration.ofMillis(plugin.getConfig().getLong("async.long.feedbackEvery", 30000)); + ProgressTracker tracker = new ProgressTracker(sender, "\u00a77- Protect-All {0,number,##}% ({1}/{2}, failed:{3}, skipped:{4}) ~ {5}", 10, feedbackFrequency); task = new ProtectAllTask(plugin, sender, islandLogic.getIslandDirectory(), tracker); task.runTaskAsynchronously(plugin); return true; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java index 2dcfe66c4..7c5a9619c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PurgeCommand.java @@ -2,15 +2,16 @@ import com.google.inject.Inject; import dk.lockfuglsang.minecraft.command.AbstractCommand; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.command.CommandSender; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.command.admin.task.PurgeScanTask; import us.talabrek.ultimateskyblock.command.admin.task.PurgeTask; import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -22,16 +23,17 @@ public class PurgeCommand extends AbstractCommand { private final uSkyBlock plugin; private final IslandLogic islandLogic; + private final Scheduler scheduler; private PurgeScanTask scanTask; private PurgeTask purgeTask; - private String days = null; @Inject - public PurgeCommand(@NotNull uSkyBlock plugin, @NotNull IslandLogic islandLogic) { + public PurgeCommand(@NotNull uSkyBlock plugin, @NotNull IslandLogic islandLogic, Scheduler scheduler) { super("purge", "usb.admin.purge", "time-in-days|stop|confirm ?level ?force", marktr("purges all abandoned islands")); this.plugin = plugin; this.islandLogic = islandLogic; + this.scheduler = scheduler; } @Override @@ -44,7 +46,7 @@ public boolean execute(final CommandSender sender, String alias, Map 1 && args[1].matches("[0-9]+([.,][0-9]+)?")) { try { @@ -54,25 +56,22 @@ public boolean execute(final CommandSender sender, String alias, Map { if (force) { doPurge(sender); } else { - int timeout = plugin.getConfig().getInt("options.advanced.purgeTimeout", 600000); - sender.sendMessage(tr("\u00a74PURGE:\u00a7e Do \u00a79usb purge confirm\u00a7e within {0} to accept.", TimeUtil.millisAsString(timeout))); - new BukkitRunnable() { - @Override - public void run() { - if (scanTask.isActive()) { - sender.sendMessage("\u00a77purge timed out"); - scanTask.stop(); - } + Duration timeout = Duration.ofMillis(plugin.getConfig().getLong("options.advanced.purgeTimeout", 600000)); // TODO: this option does not have an entry in plugin.yml + sender.sendMessage(tr("\u00a74PURGE:\u00a7e Do \u00a79usb purge confirm\u00a7e within {0} to accept.", TimeUtil.durationAsString(timeout))); + scheduler.async(() -> { + if (scanTask.isActive()) { + sender.sendMessage("\u00a77purge timed out"); + scanTask.stop(); } - }.runTaskLaterAsynchronously(plugin, TimeUtil.millisAsTicks(timeout)); + }, timeout); } }); scanTask.runTaskAsynchronously(plugin); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java index 4f308a4b3..e318a4189 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/ProtectAllTask.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock.command.admin.task; import dk.lockfuglsang.minecraft.file.FileUtil; +import dk.lockfuglsang.minecraft.util.TimeUtil; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; @@ -10,9 +11,10 @@ import us.talabrek.ultimateskyblock.util.IslandUtil; import us.talabrek.ultimateskyblock.util.LogUtil; import us.talabrek.ultimateskyblock.util.ProgressTracker; -import dk.lockfuglsang.minecraft.util.TimeUtil; import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; import java.util.logging.Level; import java.util.logging.Logger; @@ -51,7 +53,7 @@ public void run() { long failed = 0; long success = 0; long skipped = 0; - long tStart = System.currentTimeMillis(); + Instant tStart = Instant.now(); try { String[] list = islandDirectory.toFile().list(IslandUtil.createIslandFilenameFilter()); long total = list != null ? list.length : 0; @@ -88,7 +90,7 @@ public void run() { LogUtil.log(Level.INFO, message); } - private String getElapsed(long tStart) { - return TimeUtil.millisAsString(System.currentTimeMillis() - tStart); + private String getElapsed(Instant tStart) { + return TimeUtil.durationAsString(Duration.between(tStart, Instant.now())); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeScanTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeScanTask.java index 3c79fc911..575dc92a6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeScanTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeScanTask.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.command.admin.task; import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import dk.lockfuglsang.minecraft.util.Timer; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; @@ -12,6 +12,8 @@ import us.talabrek.ultimateskyblock.uuid.PlayerDB; import java.io.File; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,31 +28,32 @@ /** * Scans for all players on a list of islands. */ +// TODO: test this class!!! public class PurgeScanTask extends BukkitRunnable { private final List islandList; private final List purgeList; - private final long cutOff; + private final Instant cutOff; private final uSkyBlock plugin; private final CommandSender sender; private final Runnable callback; private final double purgeLevel; private final ProgressTracker tracker; - private final long tStart; + private final Timer timer; private final PlayerDB playerDB; private volatile boolean active; private boolean done; - public PurgeScanTask(uSkyBlock plugin, File islandDir, int time, double purgeLevel, CommandSender sender, Runnable callback) { + public PurgeScanTask(uSkyBlock plugin, File islandDir, Duration time, double purgeLevel, CommandSender sender, Runnable callback) { this.plugin = plugin; this.sender = sender; this.callback = callback; - this.cutOff = System.currentTimeMillis() - (time * 3600000L); + this.cutOff = Instant.now().minus(time); String[] islandList = islandDir.list(IslandUtil.createIslandFilenameFilter()); this.islandList = new ArrayList<>(Arrays.asList(islandList)); purgeList = new ArrayList<>(); this.purgeLevel = purgeLevel; - int feedbackEvery = plugin.getConfig().getInt("async.long.feedbackEvery", 30000); - tStart = System.currentTimeMillis(); + Duration feedbackEvery = Duration.ofMillis(plugin.getConfig().getLong("async.long.feedbackEvery", 30000)); + timer = Timer.start(); tracker = new ProgressTracker(sender, marktr("\u00a77- SCANNING: {0,number,##}% ({1}/{2} failed: {3}) ~ {4}"), 25, feedbackEvery); active = true; playerDB = plugin.getPlayerDB(); @@ -78,7 +81,7 @@ private void generatePurgeList() { failed++; } progress++; - tracker.progressUpdate(progress, total, failed, TimeUtil.millisAsString(System.currentTimeMillis()-tStart)); + tracker.progressUpdate(progress, total, failed, timer.elapsedAsString()); } } @@ -101,7 +104,7 @@ public List getPurgeList() { private boolean abandonedSince(Set members) { for (UUID member : members) { OfflinePlayer player = playerDB.getOfflinePlayer(member); - if (player == null || player.getLastPlayed() > cutOff) { + if (player == null || Instant.ofEpochMilli(player.getLastPlayed()).isAfter(cutOff)) { return false; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeTask.java index 018bf7de2..556f7347d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/task/PurgeTask.java @@ -1,12 +1,14 @@ package us.talabrek.ultimateskyblock.command.admin.task; import dk.lockfuglsang.minecraft.po.I18nUtil; +import dk.lockfuglsang.minecraft.util.TimeUtil; +import dk.lockfuglsang.minecraft.util.Timer; import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.ProgressTracker; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import java.time.Duration; import java.util.List; import java.util.logging.Level; @@ -20,34 +22,33 @@ public class PurgeTask extends BukkitRunnable { private final List purgeList; private final uSkyBlock plugin; private final CommandSender sender; - private final int feedbackEvery; private final ProgressTracker tracker; - private final long tStart; + private final Timer timer; private boolean active; public PurgeTask(uSkyBlock plugin, List purgeList, CommandSender sender) { this.plugin = plugin; this.sender = sender; this.purgeList = purgeList; - tStart = System.currentTimeMillis(); - feedbackEvery = plugin.getConfig().getInt("async.long.feedbackEvery", 30000); + this.timer = Timer.start(); + Duration feedbackEvery = Duration.ofMillis(plugin.getConfig().getInt("async.long.feedbackEvery", 30000)); tracker = new ProgressTracker(sender, marktr("- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}"), 25, feedbackEvery); active = true; } private void doPurge() { int total = purgeList.size(); - int cnt = 0; + int completed = 0; while (!purgeList.isEmpty()) { if (!active) { break; } - final String islandName = purgeList.remove(0); + String islandName = purgeList.removeFirst(); plugin.getIslandLogic().purge(islandName); - cnt++; - long elapsed = System.currentTimeMillis() - tStart; - long eta = (elapsed/cnt) * (total-cnt); - tracker.progressUpdate(cnt, total, TimeUtil.millisAsString(elapsed), TimeUtil.millisAsString(eta)); + completed++; + Duration elapsed = timer.elapsed(); + Duration eta = elapsed.dividedBy(completed).multipliedBy(total - completed); + tracker.progressUpdate(completed, total, TimeUtil.durationAsString(elapsed), TimeUtil.durationAsTicks(eta)); } plugin.getOrphanLogic().save(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java index dcb74ddfb..7f945ca8d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/NetherTerraFormEvents.java @@ -44,7 +44,7 @@ public class NetherTerraFormEvents implements Listener { private final uSkyBlock plugin; private final Map> terraFormMap = new HashMap<>(); private final Map toolWeights = new HashMap<>(); - private static final Random RND = new Random(System.currentTimeMillis()); + private static final Random RND = new Random(); private final double maxScan; private final double chanceWither; private final double chanceSkeleton; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index 3a6e6f51b..a1fb14548 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -20,7 +20,11 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.*; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerRespawnEvent; @@ -41,7 +45,15 @@ import us.talabrek.ultimateskyblock.util.LocationUtil; import us.talabrek.ultimateskyblock.world.WorldManager; -import java.util.*; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.UUID; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -53,14 +65,14 @@ public class PlayerEvents implements Listener { EntityDamageEvent.DamageCause.FIRE_TICK, EntityDamageEvent.DamageCause.HOT_FLOOR)); private static final Random RANDOM = new Random(); - private static final int OBSIDIAN_SPAM = 10000; // Max once every 10 seconds. + private static final Duration OBSIDIAN_SPAM = Duration.ofSeconds(10); private final uSkyBlock plugin; private final boolean visitorFallProtected; private final boolean visitorFireProtected; private final boolean visitorMonsterProtected; private final boolean protectLava; - private final Map obsidianClick = new WeakHashMap<>(); + private final Map obsidianClick = new HashMap<>(); private final boolean blockLimitsEnabled; private final Map leafSaplings = Map.of( Material.OAK_LEAVES, Material.OAK_SAPLING, @@ -105,9 +117,9 @@ public void onClickOnObsidian(final PlayerInteractEvent event) { && block != null && block.getType() == Material.OBSIDIAN && !testForObsidian(block)) { - long now = System.currentTimeMillis(); - Long lastClick = obsidianClick.get(player.getUniqueId()); - if (lastClick != null && (lastClick + OBSIDIAN_SPAM) >= now) { + Instant now = Instant.now(); + Instant lastClick = obsidianClick.get(player.getUniqueId()); + if (lastClick != null && lastClick.plus(OBSIDIAN_SPAM).isAfter(now)) { plugin.notifyPlayer(player, tr("\u00a74You can only convert obsidian once every 10 seconds")); return; } @@ -152,9 +164,9 @@ public boolean testForObsidian(final Block block) { @EventHandler(ignoreCancelled = true) public void onLavaPlace(final PlayerBucketEmptyEvent event) { if (Settings.extras_obsidianToLava && event.getBucket() == Material.LAVA_BUCKET) { - long now = System.currentTimeMillis(); - Long lastClick = obsidianClick.get(event.getPlayer().getUniqueId()); - if (lastClick != null && (now - lastClick < 50)) { + Instant now = Instant.now(); + Instant lastClick = obsidianClick.get(event.getPlayer().getUniqueId()); + if (lastClick != null && lastClick.plus(Duration.ofMillis(50)).isAfter(now)) { event.setCancelled(true); } } @@ -240,8 +252,7 @@ public void onMemberDamage(final EntityDamageByEntityEvent event) { if (event.getEntity() instanceof Player victim && plugin.getWorldManager().isSkyAssociatedWorld(victim.getWorld())) { if (event.getDamager() instanceof Player attacker) { cancelMemberDamage(attacker, victim, event); - } - else if (event.getDamager() instanceof Projectile && !(event.getDamager() instanceof EnderPearl)) { + } else if (event.getDamager() instanceof Projectile && !(event.getDamager() instanceof EnderPearl)) { ProjectileSource shooter = ((Projectile) event.getDamager()).getShooter(); if (shooter instanceof Player attacker) { cancelMemberDamage(attacker, victim, event); @@ -312,6 +323,7 @@ public void onTeleport(PlayerTeleportEvent event) { * This EventHandler handles {@link BlockBreakEvent} to detect if a player broke leaves in the skyworld, * and will drop a sapling if so. This will prevent cases where the default generated tree on a new * island drops no saplings. + * * @param event BlockBreakEvent to handle. */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) @@ -363,7 +375,7 @@ public void run() { } @EventHandler(ignoreCancelled = true) - public void onBlockBreak(BlockBreakEvent event){ + public void onBlockBreak(BlockBreakEvent event) { if (!blockLimitsEnabled || !plugin.getWorldManager().isSkyAssociatedWorld(event.getBlock().getWorld())) { return; // Skip } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java index 64169809e..a2435b498 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ConfirmHandler.java @@ -9,7 +9,7 @@ import us.talabrek.ultimateskyblock.util.Scheduler; import java.time.Duration; -import java.time.LocalDateTime; +import java.time.Instant; import java.util.Map; import java.util.UUID; import java.util.WeakHashMap; @@ -34,55 +34,55 @@ public ConfirmHandler( this.timeout = Duration.ofSeconds(config.getYamlConfig().getInt("options.advanced.confirmTimeout", 10)); } - public long millisLeft(final Player player, final String cmd) { + public @NotNull Duration durationLeft(@NotNull Player player, @NotNull String cmd) { UUID uuid = player.getUniqueId(); if (confirmMap.containsKey(uuid)) { ConfirmCommand command = confirmMap.get(uuid); if (command != null && command.isValid(cmd, timeout)) { - return timeout.minus(Duration.between(command.timeStamp, LocalDateTime.now())).toMillis(); + return timeout.minus(Duration.between(command.timeStamp, Instant.now())); } } - return -1; + return Duration.ZERO; } - public boolean checkCommand(final Player player, final String cmd) { - if (!confirmationsActiveFor(cmd)) { + public boolean checkCommand(@NotNull Player player, @NotNull String command) { + if (!confirmationsActiveFor(command)) { return true; } UUID uuid = player.getUniqueId(); if (confirmMap.containsKey(uuid)) { ConfirmCommand confirmCommand = confirmMap.get(uuid); - if (confirmCommand != null && confirmCommand.isValid(cmd, timeout)) { + if (confirmCommand != null && confirmCommand.isValid(command, timeout)) { confirmMap.remove(uuid); return true; } } - confirmMap.put(uuid, new ConfirmCommand(cmd)); + confirmMap.put(uuid, new ConfirmCommand(command)); scheduler.async(() -> { - ConfirmCommand confirmCommand = confirmMap.remove(player.getUniqueId()); - if (confirmCommand != null && player != null && player.isOnline()) { - player.sendMessage(I18nUtil.tr("\u00a79{0}\u00a77 timed out", cmd)); + ConfirmCommand confirmCommand = confirmMap.remove(uuid); + if (confirmCommand != null && player.isOnline()) { + player.sendMessage(I18nUtil.tr("\u00a79{0}\u00a77 timed out", command)); } }, timeout); - player.sendMessage(I18nUtil.tr("\u00a7eDoing \u00a79{0}\u00a7e is \u00a7cRISKY\u00a7e. Repeat the command within \u00a7a{1}\u00a7e seconds to accept!", cmd, timeout)); + player.sendMessage(I18nUtil.tr("\u00a7eDoing \u00a79{0}\u00a7e is \u00a7cRISKY\u00a7e. Repeat the command within \u00a7a{1}\u00a7e seconds to accept!", command, timeout)); return false; } - private boolean confirmationsActiveFor(String cmd) { - return config.getYamlConfig().getBoolean("confirmation." + cmd.replaceAll("[^a-z\\ ]", ""), true); + private boolean confirmationsActiveFor(@NotNull String command) { + return config.getYamlConfig().getBoolean("confirmation." + command.replaceAll("[^a-z\\ ]", ""), true); } private static class ConfirmCommand { private final String command; - private final LocalDateTime timeStamp; + private final Instant timeStamp; private ConfirmCommand(String command) { this.command = command; - this.timeStamp = LocalDateTime.now(); + this.timeStamp = Instant.now(); } public boolean isValid(String command, Duration timeout) { - return this.command.equals(command) && timeStamp.plus(timeout).isAfter(LocalDateTime.now()); + return this.command.equals(command) && timeStamp.plus(timeout).isAfter(Instant.now()); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java index 4b9ed7541..eff9f34c8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldEditHandler.java @@ -16,6 +16,7 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import dk.lockfuglsang.minecraft.util.Timer; import org.apache.commons.lang3.Validate; import org.bukkit.Chunk; import org.bukkit.Location; @@ -32,6 +33,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.time.Duration; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -228,12 +230,12 @@ public static void clearIsland(@NotNull final World islandWorld, @NotNull final log.finer("Clearing island " + region); uSkyBlock plugin = uSkyBlock.getInstance(); - final long t = System.currentTimeMillis(); + final Timer timer = Timer.start(); final Region cube = getRegion(islandWorld, region); Runnable onCompletion = () -> { - long diff = System.currentTimeMillis() - t; + Duration elapsed = timer.elapsed(); LogUtil.log(Level.INFO, String.format("Cleared island on %s in %d.%03d seconds", - islandWorld.getName(), (diff / 1000), (diff % 1000))); + islandWorld.getName(), elapsed.toSeconds(), elapsed.toMillisPart())); if (afterDeletion != null) { afterDeletion.run(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java index 9f32b0031..d40d8748e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/PlayerJob.java @@ -4,6 +4,8 @@ import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; +import java.time.Instant; import java.util.logging.Logger; /** @@ -12,9 +14,9 @@ class PlayerJob { private static final Logger log = Logger.getLogger(PlayerJob.class.getName()); private final Player player; - private final long progressEveryMs; + private final Duration progressInterval; private final double progressEveryPct; - private long lastProgressMs; + private Instant lastProgress; private double percentage; private double lastProgressPct; private final uSkyBlock plugin; @@ -27,13 +29,13 @@ class PlayerJob { private int maxQueuedBlocks; private int startOffset; - PlayerJob(Player player, long progressEveryMs, double progressEveryPct, uSkyBlock plugin) { + PlayerJob(Player player, Duration progressInterval, double progressEveryPct, uSkyBlock plugin) { this.player = player; this.plugin = plugin; - this.progressEveryMs = progressEveryMs; + this.progressInterval = progressInterval; this.progressEveryPct = progressEveryPct; - lastProgressMs = System.currentTimeMillis(); + lastProgress = Instant.now(); lastProgressPct = 0; placedBlocks = 0; maxQueuedBlocks = 0; @@ -58,19 +60,19 @@ public int progress(int blocksPlaced) { log.finer("waiting: " + this); return blocksPlaced; } - this.placedBlocks = Math.min(blocksPlaced-startOffset, (maxQueuedBlocks-offset)); + this.placedBlocks = Math.min(blocksPlaced - startOffset, (maxQueuedBlocks - offset)); this.percentage = Math.floor(Math.min((100d * getPlacedBlocks() / maxQueuedBlocks), 100)); showProgress(I18nUtil.tr("\u00a79Creating island...\u00a7e{0,number,###}%", percentage)); log.finer("progress: " + this); - return blocksPlaced-placedBlocks; + return blocksPlaced - placedBlocks; } private void showProgress(String message) { - long t = System.currentTimeMillis(); - if (t > (lastProgressMs + progressEveryMs) || percentage > (lastProgressPct + progressEveryPct)) { + Instant now = Instant.now(); + if (now.isAfter(lastProgress.plus(progressInterval)) || percentage > (lastProgressPct + progressEveryPct)) { plugin.getPlayerLogic().getNotificationManager().sendActionBar(player, message); - lastProgressMs = t; - lastProgressPct = Math.floor(percentage/ progressEveryPct) * progressEveryPct; + lastProgress = now; + lastProgressPct = Math.floor(percentage / progressEveryPct) * progressEveryPct; } } @@ -92,18 +94,18 @@ public int mark(int max, int startAt) { @Override public String toString() { return "PlayerJob{" + - "player=" + player + - ", startOffset=" + startOffset + - ", offset=" + offset + - ", placedBlocks=" + placedBlocks + - ", maxQueuedBlocks=" + maxQueuedBlocks + - ", percentage=" + percentage + - '}'; + "player=" + player + + ", startOffset=" + startOffset + + ", offset=" + offset + + ", placedBlocks=" + placedBlocks + + ", maxQueuedBlocks=" + maxQueuedBlocks + + ", percentage=" + percentage + + '}'; } @Override public boolean equals(Object o) { - return o instanceof PlayerJob && ((PlayerJob)o).getPlayer().getUniqueId().equals(player.getUniqueId()); + return o instanceof PlayerJob && ((PlayerJob) o).getPlayer().getUniqueId().equals(player.getUniqueId()); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java index 088841b34..93519e253 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/task/WorldEditClearFlatlandTask.java @@ -55,7 +55,7 @@ public WorldEditClearFlatlandTask( super(scheduler, config); this.logger = logger; setOnCompletion(() -> { - String duration = TimeUtil.millisAsString(WorldEditClearFlatlandTask.this.getTimeElapsed()); + String duration = TimeUtil.durationAsShort(WorldEditClearFlatlandTask.this.getTimeElapsed()); log(Level.INFO, String.format("Region %s was cleared in %s", region, duration)); commandSender.sendMessage(String.format(format, duration)); }); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java index dc2ee6965..a68505711 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/imports/USBImporterExecutor.java @@ -2,7 +2,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import dk.lockfuglsang.minecraft.util.Timer; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import us.talabrek.ultimateskyblock.imports.fixuuidleader.UUIDLeaderImporter; @@ -11,6 +11,7 @@ import us.talabrek.ultimateskyblock.util.ProgressTracker; import java.io.File; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; @@ -28,7 +29,7 @@ public class USBImporterExecutor { private final uSkyBlock plugin; private final ProgressTracker progressTracker; private List importers; - private volatile long tStart; + private volatile Timer timer; private volatile int countSuccess; private volatile int countSkip; private volatile int countFailed; @@ -37,8 +38,8 @@ public class USBImporterExecutor { public USBImporterExecutor(uSkyBlock plugin) { this.plugin = plugin; double progressEveryPct = plugin.getConfig().getDouble("importer.progressEveryPct", 10); - long progressEveryMs = plugin.getConfig().getLong("importer.progressEveryMs", 10000); - progressTracker = new ProgressTracker(Bukkit.getConsoleSender(), marktr("\u00a7eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) ~ {6}"), progressEveryPct, progressEveryMs); + Duration progressInterval = Duration.ofMillis(plugin.getConfig().getLong("importer.progressEveryMs", 10000)); + progressTracker = new ProgressTracker(Bukkit.getConsoleSender(), marktr("\u00a7eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) ~ {6}"), progressEveryPct, progressInterval); } public List getImporterNames() { @@ -84,7 +85,7 @@ public void importUSB(final CommandSender sender, String name) { } private void doImport(CommandSender sender, USBImporter importer) { - tStart = System.currentTimeMillis(); + this.timer = Timer.start(); importer.init(plugin); countSuccess = 0; countFailed = 0; @@ -117,9 +118,7 @@ private void doImport(final CommandSender sender, final USBImporter importer, fi countFailed++; log(Level.WARNING, "Could not import file " + file, t); } - progressTracker.progressUpdate(countSuccess + countFailed + countSkip, files.length, - countSuccess, countFailed, countSkip, - TimeUtil.millisAsString(System.currentTimeMillis() - tStart)); + progressTracker.progressUpdate(countSuccess + countFailed + countSkip, files.length, countSuccess, countFailed, countSkip, timer.elapsedAsString()); } } finally { complete(sender, importer); @@ -128,8 +127,7 @@ private void doImport(final CommandSender sender, final USBImporter importer, fi private void complete(CommandSender sender, USBImporter importer) { importer.completed(countSuccess, countFailed, countSkip); - sender.sendMessage(tr("\u00a7eConverted {0}/{1} files in {2}", - countSuccess, (countSuccess + countFailed), TimeUtil.millisAsString(System.currentTimeMillis() - tStart))); + sender.sendMessage(tr("\u00a7eConverted {0}/{1} files in {2}", countSuccess, (countSuccess + countFailed), timer.elapsedAsString())); plugin.getConfig().set("importer." + importer.getName() + ".imported", true); plugin.saveConfig(); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 588f62618..289f6393e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -35,8 +35,9 @@ import java.nio.file.Path; import java.text.DateFormat; import java.text.ParseException; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -97,7 +98,7 @@ private void updateConfig() { int oldMaxSize = config.getInt("maxSize"); if (oldMaxSize > Settings.general_maxPartySize) { ConfigurationSection leaderSection = config.getConfigurationSection("party.members." + - UUIDUtil.asString(getLeaderUniqueId())); + UUIDUtil.asString(getLeaderUniqueId())); if (leaderSection != null) { leaderSection.set("maxPartySizePermission", oldMaxSize); } @@ -240,7 +241,7 @@ public void updatePermissionPerks(@NotNull final Player member, @NotNull Perk pe section.set("blockLimits ", null); if (!blockLimits.isEmpty()) { ConfigurationSection maxBlocks = section.createSection("blockLimits"); - for (Map.Entry limit : blockLimits.entrySet()) { + for (Map.Entry limit : blockLimits.entrySet()) { maxBlocks.set(limit.getKey().name(), limit.getValue()); } } @@ -283,31 +284,31 @@ public void saveToFile() { @Override public int getMaxPartySize() { return getMaxPartyIntValue("maxPartySizePermission", - plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getMaxPartySize()); + plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getMaxPartySize()); } @Override public int getMaxAnimals() { return getMaxPartyIntValue("maxAnimals", - plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getAnimals()); + plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getAnimals()); } @Override public int getMaxMonsters() { return getMaxPartyIntValue("maxMonsters", - plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getMonsters()); + plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getMonsters()); } @Override public int getMaxVillagers() { return getMaxPartyIntValue("maxVillagers", - plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getVillagers()); + plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getVillagers()); } @Override public int getMaxGolems() { return getMaxPartyIntValue("maxGolems", - plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getGolems()); + plugin.getPerkLogic().getIslandPerk(getSchematicName()).getPerk().getGolems()); } @Override @@ -327,7 +328,7 @@ public Map getBlockLimits() { blockLimitMap.computeIfAbsent(type, (k) -> { int memberMax = blockLimits.getInt(material, 0); return blockLimitMap.compute(type, (key, oldValue) -> - oldValue != null && memberMax > 0 ? Math.max(memberMax, oldValue) : null); + oldValue != null && memberMax > 0 ? Math.max(memberMax, oldValue) : null); }); } } @@ -576,6 +577,7 @@ public void setWarp(boolean active) { /** * Locks the island. Might get cancelled via the fired {@link IslandLockEvent}. + * * @param player {@link Player} initializing the lock. * @return True if the island was locked, false otherwise, e.g. when the event is cancelled. */ @@ -602,6 +604,7 @@ public boolean lock(@NotNull Player player) { /** * Unlocks the island. Might get cancelled via the fired {@link IslandUnlockEvent}. + * * @param player {@link Player} initializing the unlock. * @return True if the island was unlocked, false otherwise, e.g. when the event is cancelled. */ @@ -926,28 +929,28 @@ public List getLog() { log.addAll(config.getStringList("log")); } List convertedList = new ArrayList<>(); - long t = System.currentTimeMillis(); + Instant now = Instant.now(); for (String logEntry : log) { String[] split = logEntry.split(";"); if (split.length >= 2) { - long then = Long.parseLong(split[0]); + Instant then = Instant.ofEpochMilli(Long.parseLong(split[0])); String msg = split[1]; Object[] args = new Object[split.length - 2]; System.arraycopy(split, 2, args, 0, args.length); - convertedList.add(tr("\u00a79{1} \u00a77- {0}", TimeUtil.millisAsString(t - then), tr(msg, args))); + convertedList.add(tr("\u00a79{1} \u00a77- {0}", TimeUtil.durationAsString(Duration.between(then, now)), tr(msg, args))); } else { Matcher m = OLD_LOG_PATTERN.matcher(logEntry); if (m.matches()) { String date = m.group("date"); - Date parsedDate = null; + Instant parsedDate = null; try { - parsedDate = DateFormat.getDateInstance(3).parse(date); + parsedDate = DateFormat.getDateInstance(DateFormat.SHORT).parse(date).toInstant(); } catch (ParseException e) { // Ignore } String msg = m.group("msg"); if (parsedDate != null) { - convertedList.add(tr("\u00a79{1} \u00a77- {0}", TimeUtil.millisAsString(t - parsedDate.getTime()), msg)); + convertedList.add(tr("\u00a79{1} \u00a77- {0}", TimeUtil.durationAsString(Duration.between(parsedDate, now)), msg)); } else { convertedList.add(logEntry); } @@ -969,11 +972,11 @@ public boolean isParty() { public Location getWarpLocation() { if (hasWarp()) { return new Location(plugin.getWorldManager().getWorld(), - config.getInt("general.warpLocationX", 0), - config.getInt("general.warpLocationY", 0), - config.getInt("general.warpLocationZ", 0), - (float) config.getDouble("general.warpYaw", 0), - (float) config.getDouble("general.warpPitch", 0)); + config.getInt("general.warpLocationX", 0), + config.getInt("general.warpLocationY", 0), + config.getInt("general.warpLocationZ", 0), + (float) config.getDouble("general.warpYaw", 0), + (float) config.getDouble("general.warpPitch", 0)); } return null; } @@ -1134,6 +1137,7 @@ public void setHopperCount(int i) { /** * If you need to inject a custom {@link File} for e.g. unit tests, do it here. + * * @param file Custom File */ public void setFile(File file) { @@ -1142,6 +1146,7 @@ public void setFile(File file) { /** * If you need to inject a custom {@link FileConfiguration} for e.g. unit tests, do it here. + * * @param config Custom FileConfiguration */ public void setConfig(FileConfiguration config) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java index 2fee393e2..a8637fb51 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLocatorLogic.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.file.Path; import java.time.Duration; +import java.time.Instant; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; @@ -38,7 +39,7 @@ public class IslandLocatorLogic { private final uSkyBlock plugin; private final File configFile; private final FileConfiguration config; - private final Map reservations = new ConcurrentHashMap<>(); + private final Map reservations = new ConcurrentHashMap<>(); private Location lastIsland = null; private final Duration reservationTimeout; @@ -86,12 +87,12 @@ public synchronized Location getNextIslandLocation(Player player) { private void reserve(Location islandLocation) { final String islandName = LocationUtil.getIslandName(islandLocation); - final long tstamp = System.currentTimeMillis(); - reservations.put(islandName, tstamp); + final Instant timeStamp = Instant.now(); + reservations.put(islandName, timeStamp); scheduler.async(() -> { synchronized (reservations) { - Long tReserved = reservations.get(islandName); - if (tReserved != null && tReserved == tstamp) { + Instant tReserved = reservations.get(islandName); + if (tReserved != null && tReserved == timeStamp) { reservations.remove(islandName); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java index 2cd967369..2ccddf907 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandLogic.java @@ -43,6 +43,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -79,7 +80,7 @@ public class IslandLogic { private final BukkitTask saveTask; private final double topTenCutoff; - private volatile long lastGenerate = 0; + private volatile Instant lastUpdated = Instant.MIN; private final List ranks = new ArrayList<>(); @Inject @@ -198,34 +199,31 @@ private Location getNetherLocation(Location loc) { return netherIsland; } - public boolean clearFlatland(final CommandSender sender, final Location loc, final int delay) { + public boolean clearFlatland(final CommandSender sender, final Location loc, Duration delay) { if (loc == null) { return false; } - if (delay > 0 && !flatlandFix) { + if (delay.isPositive() && !flatlandFix) { return false; // Skip } - Runnable runnable = new Runnable() { - @Override - public void run() { - final World w = loc.getWorld(); - final int px = loc.getBlockX(); - final int pz = loc.getBlockZ(); - final int py = 0; - final int range = Math.max(Settings.island_protectionRange, Settings.island_distance) + 1; - final int radius = range / 2; - // 5 sampling points... - if (w.getBlockAt(px, py, pz).getType() == BEDROCK - || w.getBlockAt(px + radius, py, pz + radius).getType() == BEDROCK - || w.getBlockAt(px + radius, py, pz - radius).getType() == BEDROCK - || w.getBlockAt(px - radius, py, pz + radius).getType() == BEDROCK - || w.getBlockAt(px - radius, py, pz - radius).getType() == BEDROCK) { - sender.sendMessage(String.format("\u00a7c-----------------------------------\n\u00a7cFlatland detected under your island!\n\u00a7e Clearing it in %s, stay clear.\n\u00a7c-----------------------------------\n", TimeUtil.ticksAsString(delay))); - new WorldEditClearFlatlandTask(scheduler, config, worldManager, logger, sender, - new CuboidRegion(BlockVector3.at(px - radius, 0, pz - radius), - BlockVector3.at(px + radius, 4, pz + radius)), - "\u00a7eFlatland was cleared under your island (%s). Take care.").runTaskLater(plugin, delay); - } + Runnable runnable = () -> { + final World w = loc.getWorld(); + final int px = loc.getBlockX(); + final int pz = loc.getBlockZ(); + final int py = 0; + final int range = Math.max(Settings.island_protectionRange, Settings.island_distance) + 1; + final int radius = range / 2; + // 5 sampling points... + if (w.getBlockAt(px, py, pz).getType() == BEDROCK + || w.getBlockAt(px + radius, py, pz + radius).getType() == BEDROCK + || w.getBlockAt(px + radius, py, pz - radius).getType() == BEDROCK + || w.getBlockAt(px - radius, py, pz + radius).getType() == BEDROCK + || w.getBlockAt(px - radius, py, pz - radius).getType() == BEDROCK) { + sender.sendMessage(String.format("\u00a7c-----------------------------------\n\u00a7cFlatland detected under your island!\n\u00a7e Clearing it in %s, stay clear.\n\u00a7c-----------------------------------\n", TimeUtil.durationAsString(delay))); + scheduler.sync(new WorldEditClearFlatlandTask(scheduler, config, worldManager, logger, sender, + new CuboidRegion(BlockVector3.at(px - radius, 0, pz - radius), + BlockVector3.at(px + radius, 4, pz + radius)), + "\u00a7eFlatland was cleared under your island (%s). Take care."), delay); } }; if (Bukkit.isPrimaryThread()) { @@ -308,9 +306,9 @@ private String getJsonWarpString(String text, String hoverText, String command) } public void showTopTen(final CommandSender sender, final int page) { - long t = System.currentTimeMillis(); - if (t > (lastGenerate + (Settings.island_topTenTimeout * 60000)) || (sender.hasPermission("usb.admin.topten") || sender.isOp())) { - lastGenerate = t; + Instant now = Instant.now(); + if (now.isAfter(lastUpdated.plus(Settings.island_topTenTimeout)) || (sender.hasPermission("usb.admin.topten") || sender.isOp())) { + lastUpdated = now; scheduler.async(() -> { generateTopTen(sender); displayTopTen(sender, page); @@ -352,7 +350,7 @@ public void generateTopTen(final CommandSender sender) { } Collections.sort(topTen); synchronized (ranks) { - lastGenerate = System.currentTimeMillis(); + lastUpdated = Instant.now(); ranks.clear(); ranks.addAll(topTen); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java index da1632797..9f2f3799b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java @@ -5,7 +5,9 @@ import org.bukkit.scheduler.BukkitRunnable; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; -import dk.lockfuglsang.minecraft.util.TimeUtil; +import us.talabrek.ultimateskyblock.util.Scheduler; + +import java.time.Duration; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -18,9 +20,11 @@ public class CreateIslandTask extends BukkitRunnable { private final PlayerPerk playerPerk; private final Location next; private final String cSchem; + private final Scheduler scheduler; public CreateIslandTask(uSkyBlock plugin, Player player, PlayerPerk playerPerk, Location next, String cSchem) { this.plugin = plugin; + this.scheduler = plugin.getScheduler(); this.player = player; this.playerPerk = playerPerk; this.next = next; @@ -33,8 +37,8 @@ public void run() { player.sendMessage(tr("Unable to locate schematic {0}, contact a server-admin", cSchem)); } GenerateTask generateTask = new GenerateTask(plugin, player, playerPerk.getPlayerInfo(), next, playerPerk, cSchem); - final int heartBeatTicks = (int) TimeUtil.millisAsTicks(plugin.getConfig().getInt("asyncworldedit.watchDog.heartBeatMs", 2000)); + Duration heartBeat = Duration.ofMillis(plugin.getConfig().getInt("asyncworldedit.watchDog.heartBeatMs", 2000)); final BukkitRunnable completionWatchDog = new LocateChestTask(plugin, player, next, generateTask); - completionWatchDog.runTaskTimer(plugin, 0, heartBeatTicks); + scheduler.sync(completionWatchDog, Duration.ZERO, heartBeat); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java index 230bec12e..7b553fa70 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java @@ -9,6 +9,9 @@ import us.talabrek.ultimateskyblock.util.LocationUtil; import us.talabrek.ultimateskyblock.util.Scheduler; +import java.time.Duration; +import java.time.Instant; + /** * A task that looks for a chest at an island location. */ @@ -17,31 +20,31 @@ public class LocateChestTask extends BukkitRunnable { private final Location islandLocation; private final GenerateTask onCompletion; private final Scheduler scheduler; - private final long timeout; + private final Instant timeout; - private long tStart; + private Instant start; public LocateChestTask(uSkyBlock plugin, Player player, Location islandLocation, GenerateTask onCompletion) { this.scheduler = plugin.getScheduler(); this.player = player; this.islandLocation = islandLocation; this.onCompletion = onCompletion; - timeout = System.currentTimeMillis() + TimeUtil.stringAsMillis(plugin.getConfig().getString("asyncworldedit.watchDog.timeout", "5m")); + this.timeout = Instant.now().plus(TimeUtil.stringAsDuration(plugin.getConfig().getString("asyncworldedit.watchDog.timeout", "5m"))); } @Override public void run() { - long now = System.currentTimeMillis(); - if (tStart == 0) { - tStart = now; + if (start == null) { + start = Instant.now(); } Location chestLocation = LocationUtil.findChestLocation(islandLocation); - if (chestLocation == null && now < timeout) { + if (chestLocation == null && Instant.now().isBefore(timeout)) { // Just run again + // TODO: this is hacky, waiting for async generation to complete. Should ideally be launched once the generation has finished. } else { cancel(); if (chestLocation == null && player != null && player.isOnline()) { - player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.millisAsString(timeout - tStart))); + player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.durationAsString(Duration.between(start, timeout)))); } if (onCompletion != null) { onCompletion.setChestLocation(chestLocation); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 72c940b63..363d0e60a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -646,8 +646,8 @@ private Inventory createMainMenu(Player player) { menuItem.setItemMeta(meta4); menu.setItem(17, menuItem); lores.clear(); - long millisLeft = confirmHandler.millisLeft(player, "/is leave"); - if (millisLeft > 0) { + Duration durationLeft = confirmHandler.durationLeft(player, "/is leave"); + if (durationLeft.isPositive()) { updateLeaveMenuItemTimer(player, menu, menuItem); } } @@ -695,7 +695,7 @@ private void onClickRestartMenu(final InventoryClickEvent event, final Player p, String schemeName = stripFormatting(meta.getDisplayName()); IslandPerk islandPerk = perkLogic.getIslandPerk(schemeName); if (perkLogic.getSchemes(p).contains(schemeName) && p.hasPermission(islandPerk.getPermission())) { - if (confirmHandler.millisLeft(p, "/is restart") > 0) { + if (confirmHandler.durationLeft(p, "/is restart").isPositive()) { p.performCommand("island restart " + schemeName); } else { p.performCommand("island restart " + schemeName); @@ -711,7 +711,7 @@ private void updateRestartMenuTimer(final Player p, final Inventory inventory) { if (inventory.getViewers().contains(p)) { updateRestartMenu(inventory, p, islandGenerator.getSchemeNames()); } - if (confirmHandler.millisLeft(p, "/is restart") <= 0 || !inventory.getViewers().contains(p)) { + if (!confirmHandler.durationLeft(p, "/is restart").isPositive() || !inventory.getViewers().contains(p)) { if (hackySharing.length > 0 && hackySharing[0] != null) { hackySharing[0].cancel(); } @@ -737,68 +737,68 @@ private void onClickCreateMenu(InventoryClickEvent event, Player p, ItemMeta met } } - private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, Player p, int slotIndex) { + private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, Player player, int slotIndex) { event.setCancelled(true); if (slotIndex < 0 || slotIndex > 35) { return; } - PlayerInfo playerInfo = plugin.getPlayerInfo(p); + PlayerInfo playerInfo = plugin.getPlayerInfo(player); IslandInfo islandInfo = plugin.getIslandInfo(playerInfo); if (currentItem.getType() == Material.JUNGLE_SAPLING) { - p.performCommand("island biome"); + player.performCommand("island biome"); } else if (currentItem.getType() == Material.PLAYER_HEAD) { - p.performCommand("island party"); + player.performCommand("island party"); } else if (currentItem.getType() == Material.RED_BED) { - p.performCommand("island sethome"); - p.performCommand("island"); + player.performCommand("island sethome"); + player.performCommand("island"); } else if (currentItem.getType() == Material.SHORT_GRASS) { - p.performCommand("island spawn"); + player.performCommand("island spawn"); } else if (currentItem.getType() == Material.HOPPER) { - p.performCommand("island setwarp"); - p.performCommand("island"); + player.performCommand("island setwarp"); + player.performCommand("island"); } else if (currentItem.getType() == Material.WRITABLE_BOOK) { - p.performCommand("island log"); + player.performCommand("island log"); } else if (currentItem.getType() == Material.OAK_DOOR) { - p.performCommand("island home"); + player.performCommand("island home"); } else if (currentItem.getType() == Material.EXPERIENCE_BOTTLE) { - p.performCommand("island level"); + player.performCommand("island level"); } else if (currentItem.getType() == Material.DIAMOND_ORE) { - p.performCommand("c"); + player.performCommand("c"); } else if (currentItem.getType() == Material.END_STONE || currentItem.getType() == Material.END_PORTAL_FRAME) { - p.performCommand("island togglewarp"); - p.performCommand("island"); + player.performCommand("island togglewarp"); + player.performCommand("island"); } else if (currentItem.getType() == Material.IRON_BARS && islandInfo.isLocked()) { - p.performCommand("island unlock"); - p.performCommand("island"); + player.performCommand("island unlock"); + player.performCommand("island"); } else if (currentItem.getType() == Material.IRON_BARS && !islandInfo.isLocked()) { - p.performCommand("island lock"); - p.performCommand("island"); + player.performCommand("island lock"); + player.performCommand("island"); } else if (slotIndex == 17) { - if (islandInfo.isLeader(p) && config.getYamlConfig().getBoolean("island-schemes-enabled", true)) { - p.openInventory(createRestartGUI(p)); + if (islandInfo.isLeader(player) && config.getYamlConfig().getBoolean("island-schemes-enabled", true)) { + player.openInventory(createRestartGUI(player)); } else { - if (confirmHandler.millisLeft(p, "/is leave") > 0) { - p.performCommand("island leave"); + if (confirmHandler.durationLeft(player, "/is leave").isPositive()) { + player.performCommand("island leave"); } else { - p.performCommand("island leave"); - updateLeaveMenuItemTimer(p, event.getInventory(), currentItem); + player.performCommand("island leave"); + updateLeaveMenuItemTimer(player, event.getInventory(), currentItem); } } } else { - if (!isExtraMenuAction(p, currentItem)) { - p.performCommand("island"); + if (!isExtraMenuAction(player, currentItem)) { + player.performCommand("island"); } } } - private void updateLeaveMenuItemTimer(final Player p, final Inventory inventory, final ItemStack currentItem) { - final BukkitTask[] hackySharing = new BukkitTask[1]; + private void updateLeaveMenuItemTimer(final Player player, final Inventory inventory, final ItemStack currentItem) { + BukkitTask[] hackySharing = new BukkitTask[1]; hackySharing[0] = scheduler.sync(() -> { - long millisLeft = confirmHandler.millisLeft(p, "/is leave"); - if (inventory.getViewers().contains(p)) { - updateLeaveMenuItem(inventory, currentItem, millisLeft); + Duration durationLeft = confirmHandler.durationLeft(player, "/is leave"); + if (inventory.getViewers().contains(player)) { + updateLeaveMenuItem(inventory, currentItem, durationLeft); } - if (millisLeft <= 0 || !inventory.getViewers().contains(p)) { + if (!durationLeft.isPositive() || !inventory.getViewers().contains(player)) { if (hackySharing.length > 0 && hackySharing[0] != null) { hackySharing[0].cancel(); } @@ -806,14 +806,14 @@ private void updateLeaveMenuItemTimer(final Player p, final Inventory inventory, }, Duration.ZERO, Duration.ofSeconds(1)); } - private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, long millisLeft) { + private void updateLeaveMenuItem(Inventory inventory, ItemStack currentItem, Duration durationLeft) { if (currentItem == null || currentItem.getItemMeta() == null || currentItem.getItemMeta().getLore() == null) { return; } ItemMeta meta = requireNonNull(currentItem.getItemMeta()); List lore = meta.getLore(); - if (millisLeft >= 0) { - lore.set(lore.size() - 1, tr("\u00a7cClick within \u00a79{0}\u00a7c to leave!", TimeUtil.millisAsString(millisLeft))); + if (!durationLeft.isNegative()) { + lore.set(lore.size() - 1, tr("\u00a7cClick within \u00a79{0}\u00a7c to leave!", TimeUtil.durationAsString(durationLeft))); } else { lore.set(lore.size() - 1, tr("\u00a7cClick to leave")); } @@ -837,7 +837,7 @@ public Inventory createRestartGUI(Player player) { lores.clear(); updateRestartMenu(menu, player, schemeNames); - if (confirmHandler.millisLeft(player, "/is restart") > 0) { + if (confirmHandler.durationLeft(player, "/is restart").isPositive()) { updateRestartMenuTimer(player, menu); } return menu; @@ -862,9 +862,9 @@ private void updateRestartMenu(Inventory menu, Player player, List schem lores = new ArrayList<>(); } if (player.hasPermission(islandPerk.getPermission())) { - long millisLeft = confirmHandler.millisLeft(player, "/is restart"); - if (millisLeft > 0) { - addLore(lores, tr("\u00a7cClick within \u00a79{0}\u00a7c to restart!", TimeUtil.millisAsString(millisLeft))); + Duration durationLeft = confirmHandler.durationLeft(player, "/is restart"); + if (durationLeft.isPositive()) { + addLore(lores, tr("\u00a7cClick within \u00a79{0}\u00a7c to restart!", TimeUtil.durationAsString(durationLeft))); } else { addLore(lores, tr("\u00a7aClick to restart!")); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PatienceTester.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PatienceTester.java index 9e35de074..58c9e673a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PatienceTester.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PatienceTester.java @@ -5,40 +5,45 @@ import org.bukkit.metadata.MetadataValue; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.time.Duration; +import java.time.Instant; import java.util.List; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; public class PatienceTester { - private static final long maxRunning = 30000; + + private static final Duration COOLDOWN = Duration.ofSeconds(30); public static boolean isRunning(Player player, String key) { if (player.hasMetadata(key)) { List metadata = player.getMetadata(key); - MetadataValue metadataValue = metadata.size() > 0 ? metadata.get(0) : null; - if (metadataValue == null || metadataValue.asLong() < System.currentTimeMillis()) { + MetadataValue metadataValue = !metadata.isEmpty() ? metadata.getFirst() : null; + Instant cooldownEnd = metadataValue != null ? (Instant) metadataValue.value() : null; + if (cooldownEnd == null || Instant.now().isAfter(cooldownEnd)) { player.removeMetadata(key, uSkyBlock.getInstance()); return false; + } else { + player.sendMessage(getMessage()); + return true; } - player.sendMessage(getMessage()); - return true; } return false; } private static String getMessage() { - String[] messages = new String[] { - tr("\u00a79Hold your horses! You have to be patient..."), - tr("\u00a79Not really patient, are you?"), - tr("\u00a79Be patient, young padawan"), - tr("\u00a79Patience you MUST have, young padawan"), - tr("\u00a79The two most powerful warriors are patience and time."), + String[] messages = new String[]{ + tr("\u00a79Hold your horses! You have to be patient..."), + tr("\u00a79Not really patient, are you?"), + tr("\u00a79Be patient, young padawan"), + tr("\u00a79Patience you MUST have, young padawan"), + tr("\u00a79The two most powerful warriors are patience and time."), }; - return messages[(int)Math.floor(Math.random() * messages.length)]; + return messages[(int) Math.floor(Math.random() * messages.length)]; } public static void startRunning(Player player, String key) { - player.setMetadata(key, new FixedMetadataValue(uSkyBlock.getInstance(), System.currentTimeMillis() + maxRunning)); + player.setMetadata(key, new FixedMetadataValue(uSkyBlock.getInstance(), Instant.now().plus(COOLDOWN))); } public static void stopRunning(Player player, String key) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java index 0eecc19a7..fe1fe457d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerLogic.java @@ -141,7 +141,7 @@ private PlayerInfo loadPlayerData(UUID playerUUID, String playerName) { scheduler.sync(() -> { if (playerInfo.getHasIsland()) { WorldGuardHandler.protectIsland(onlinePlayer, playerInfo); - islandLogic.clearFlatland(onlinePlayer, playerInfo.getIslandLocation(), 400); + islandLogic.clearFlatland(onlinePlayer, playerInfo.getIslandLocation(), Duration.ofSeconds(20)); } if (worldManager.isSkyAssociatedWorld(onlinePlayer.getWorld()) && !plugin.playerIsOnIsland(onlinePlayer)) { // Check if banned diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java index 14fbcda4b..82c50c703 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerNotifier.java @@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.PluginConfig; +import java.time.Duration; +import java.time.Instant; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -18,7 +20,7 @@ */ @Singleton public class PlayerNotifier { - private final long maxSpam; + private final Duration spawnThreshold; private final LoadingCache cache = CacheBuilder .newBuilder() .expireAfterAccess(10, TimeUnit.SECONDS) @@ -27,22 +29,22 @@ public class PlayerNotifier { new CacheLoader<>() { @Override public @NotNull NotifyMessage load(@NotNull UUID uuid) { - return new NotifyMessage(null, 0); + return new NotifyMessage(null, Instant.MIN); } } ); @Inject public PlayerNotifier(@NotNull PluginConfig config) { - maxSpam = config.getYamlConfig().getInt("general.maxSpam", 3000); // every 3 seconds. + spawnThreshold = Duration.ofMillis(config.getYamlConfig().getInt("general.maxSpam", 3000)); // every 3 seconds. } public synchronized void notifyPlayer(Player player, String message) { UUID uuid = player.getUniqueId(); try { NotifyMessage last = cache.get(uuid); - long now = System.currentTimeMillis(); - if (now >= last.time() + maxSpam || !message.equals(last.message())) { + Instant now = Instant.now(); + if (now.isAfter(last.time().plus(spawnThreshold)) || !message.equals(last.message())) { cache.put(uuid, new NotifyMessage(message, now)); player.sendMessage("\u00a7e" + message); } @@ -51,6 +53,6 @@ public synchronized void notifyPlayer(Player player, String message) { } } - private record NotifyMessage(String message, long time) { + private record NotifyMessage(String message, Instant time) { } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index cf4e6c984..14443f179 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -102,7 +102,7 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage new String[]{"Multiverse-NetherPortals", "4.2.1", "optional"}, }; private static String missingRequirements = null; - private static final Random RND = new Random(System.currentTimeMillis()); + private static final Random RND = new Random(); private SkyblockApp skyBlock; diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java index 0db27f8a5..c7fda0e37 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java @@ -2,34 +2,37 @@ import org.bukkit.command.CommandSender; +import java.time.Duration; +import java.time.Instant; + import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; /** * General progress tracker using throttling */ public class ProgressTracker { - private double progressEveryPct; - private long progressEveryMs; + private final double progressEveryPct; + private final Duration progressEvery; private final String format; private final CommandSender sender; - private long lastProgressTime; + private Instant lastProgressTime; private float lastProgressPct; - public ProgressTracker(CommandSender sender, String format, double progressEveryPct, long progressEveryMs) { + public ProgressTracker(CommandSender sender, String format, double progressEveryPct, Duration progressEvery) { this.progressEveryPct = progressEveryPct; - this.progressEveryMs = progressEveryMs; + this.progressEvery = progressEvery; this.format = format; this.sender = sender; } public void progressUpdate(long progress, long total, Object... args) { - long now = System.currentTimeMillis(); - float pct = 100f * progress / (total > 0 ? total : 1); - if (now > (lastProgressTime + progressEveryMs) || pct > (lastProgressPct + progressEveryPct)) { + Instant now = Instant.now(); + float pct = 100f * progress / (total > 0 ? total : 1f); + if (now.isAfter(lastProgressTime.plus(progressEvery)) || pct > (lastProgressPct + progressEveryPct)) { lastProgressPct = pct; lastProgressTime = now; - Object[] newArgs = new Object[args.length+3]; + Object[] newArgs = new Object[args.length + 3]; newArgs[0] = pct; newArgs[1] = progress; newArgs[2] = total; From 438070cf0135ca8defe01b70f40185acf90feb31 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 17:32:19 +0100 Subject: [PATCH 153/190] Delete unused classes --- .../minecraft/command/LanguageCommand.java | 64 ------------------- .../completion/CompositeTabCompleter.java | 26 -------- .../completion/OfflinePlayerTabCompleter.java | 24 ------- .../completion/OnlinePlayerTabCompleter.java | 24 ------- .../lockfuglsang/minecraft/util/UUIDUtil.java | 32 ---------- .../ultimateskyblock/util/BiomeUtil.java | 28 -------- .../ultimateskyblock/util/BiomeUtilTest.java | 15 ----- 7 files changed, 213 deletions(-) delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java delete mode 100644 bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/BiomeUtil.java delete mode 100644 uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BiomeUtilTest.java diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java deleted file mode 100644 index ea3d1a645..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/LanguageCommand.java +++ /dev/null @@ -1,64 +0,0 @@ -package dk.lockfuglsang.minecraft.command; - -import dk.lockfuglsang.minecraft.po.I18nUtil; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Locale; -import java.util.Map; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -public class LanguageCommand extends AbstractCommand { - private JavaPlugin plugin; - - public LanguageCommand(JavaPlugin plugin, String name, String permission) { - super(name, permission, "language", marktr("changes the language of the plugin, and reloads")); - this.plugin = plugin; - } - - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (args.length == 1) { - Locale loc = I18nUtil.getLocale(args[0]); - I18nUtil.clearCache(); - plugin.getConfig().set("language", args[0]); - plugin.saveConfig(); - plugin.reloadConfig(); - if (I18nUtil.getLocale().equals(I18nUtil.getI18n().getLocale())) { - sender.sendMessage(tr("\u00a7aSuccessfully changed language to \u00a7e{0}", loc)); - } else { - sender.sendMessage(tr("\u00a7cFailed to change language to \u00a7e{0}", loc)); - } - return true; - } else if (args.length == 0) { - try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("gettext-report.txt"); - BufferedReader rdr = new BufferedReader(new InputStreamReader(inputStream))) { - String line = null; - boolean header = true; - StringBuilder sb = new StringBuilder(); - sb.append(tr("\u00a79Supported Languages:\n")); - while ((line = rdr.readLine()) != null) { - if (line.startsWith("---")) { - header = false; - } else if (!header && line.contains("|")) { - String[] parts = line.split("\\|"); - if (parts.length == 7) { - sb.append(tr("\u00a7f{0} \u00a77{1} \u00a79 by {2} \u00a77{3}\n", parts[1].trim(), parts[0].trim(), parts[6].trim(), parts[2].trim())); - } - } - } - sender.sendMessage(sb.toString().split("\n")); - } catch (IOException e) { - sender.sendMessage(tr("\u00a7cUnable to locate any languages.")); - } - return true; - } - return false; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java deleted file mode 100644 index 1a31e3e8f..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/CompositeTabCompleter.java +++ /dev/null @@ -1,26 +0,0 @@ -package dk.lockfuglsang.minecraft.command.completion; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; - -import java.util.List; - -/** - * TabCompleter that supports multiple tab-completers for different arguments. - */ -public class CompositeTabCompleter implements TabCompleter { - private final TabCompleter[] completers; - - public CompositeTabCompleter(TabCompleter... completers) { - this.completers = completers; - } - - @Override - public List onTabComplete(CommandSender commandSender, Command command, String alias, String[] args) { - if (completers.length <= args.length) { - return completers[args.length-1].onTabComplete(commandSender, command, alias, args); - } - return null; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java deleted file mode 100644 index 6e6215824..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OfflinePlayerTabCompleter.java +++ /dev/null @@ -1,24 +0,0 @@ -package dk.lockfuglsang.minecraft.command.completion; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; - -import java.util.ArrayList; -import java.util.List; - -/** - * Convenience implementation of a tab-completer for all offline players - */ -public class OfflinePlayerTabCompleter extends AbstractTabCompleter { - @Override - protected List getTabList(CommandSender commandSender, String term) { - List tabList = new ArrayList<>(); - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { - if (player != null) { - tabList.add(player.getName()); - } - } - return tabList; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java deleted file mode 100644 index 211a51684..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/command/completion/OnlinePlayerTabCompleter.java +++ /dev/null @@ -1,24 +0,0 @@ -package dk.lockfuglsang.minecraft.command.completion; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -/** - * Convenience implementation of a tab-completer for all online players - */ -public class OnlinePlayerTabCompleter extends AbstractTabCompleter { - @Override - protected List getTabList(CommandSender commandSender, String term) { - List tabList = new ArrayList<>(); - for (Player player : Bukkit.getOnlinePlayers()) { - if (player != null && player.isOnline()) { - tabList.add(player.getName()); - } - } - return tabList; - } -} diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java deleted file mode 100644 index 20a988bb6..000000000 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/UUIDUtil.java +++ /dev/null @@ -1,32 +0,0 @@ -package dk.lockfuglsang.minecraft.util; - -import java.util.UUID; -import java.util.logging.Logger; - -/** - * Utility for handling UUIDs. - */ -public enum UUIDUtil {; - private static final Logger log = Logger.getLogger(UUIDUtil.class.getName()); - public static UUID fromString(String id) { - if (id == null || id.isEmpty()) { - return null; - } - if (id.length() == 32) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); - } - try { - return UUID.fromString(id); - } catch (IllegalArgumentException e) { - // ignore, do logging elsewhere - } - return null; - } - - public static String asString(UUID uuid) { - if (uuid == null) { - return ""; - } - return uuid.toString(); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/BiomeUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/BiomeUtil.java deleted file mode 100644 index d1247ea53..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/BiomeUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package us.talabrek.ultimateskyblock.util; - -import org.bukkit.block.Biome; - -import java.util.HashMap; -import java.util.Map; - -/** - * Wrapper to support the idiotic compatibility issues reg. biomes - */ -public enum BiomeUtil {; - private static final Map biomeAlias = new HashMap<>(); - static { - biomeAlias.put("ICE_PLAINS", "ICE_FLATS"); // Bukkit 1.9 -> 1.10 - biomeAlias.put("FLOWER_FOREST", "MUTATED_FOREST"); // Bukkit 1.8 -> 1.9 - } - - public static Biome getBiome(String name) { - try { - return Biome.valueOf(name.toUpperCase()); - } catch (IllegalArgumentException e) { - if (biomeAlias.containsKey(name)) { - return getBiome(biomeAlias.get(name)); - } - } - return null; - } -} diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BiomeUtilTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BiomeUtilTest.java deleted file mode 100644 index 204ebaa67..000000000 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/util/BiomeUtilTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package us.talabrek.ultimateskyblock.util; - -import org.bukkit.block.Biome; -import org.junit.Assert; -import org.junit.Test; - -public class BiomeUtilTest { - @Test - public void getBiomeTest() throws Exception { - Assert.assertEquals(Biome.DARK_FOREST, BiomeUtil.getBiome("DARK_FOREST")); - Assert.assertEquals(Biome.JUNGLE, BiomeUtil.getBiome("JUNGLE")); - - Assert.assertNull(BiomeUtil.getBiome("INVALID_BIOME")); - } -} From 6f6ef519b7cb98d2b771403fcb827a47122220b3 Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 10 Feb 2025 17:53:29 +0100 Subject: [PATCH 154/190] Remove config edit menu #80 The config menu is currently broken. It is not worth maintaining, configs can be edited directly in-file. Closes #80 --- .../command/AdminCommand.java | 3 - .../command/admin/ConfigCommand.java | 96 ----- .../ultimateskyblock/event/MenuEvents.java | 13 +- .../menu/AbstractConfigMenu.java | 74 ---- .../ultimateskyblock/menu/BiomeMenuItem.java | 34 -- .../menu/BooleanEditMenu.java | 33 -- .../ultimateskyblock/menu/ConfigMenu.java | 56 --- .../ultimateskyblock/menu/EditMenu.java | 25 -- .../menu/IntegerEditMenu.java | 174 --------- .../ultimateskyblock/menu/MainConfigMenu.java | 329 ------------------ .../menu/MenuItemFactory.java | 62 ---- .../ultimateskyblock/menu/SkyBlockMenu.java | 5 - .../ultimateskyblock/menu/StringEditMenu.java | 174 --------- .../talabrek/ultimateskyblock/uSkyBlock.java | 7 - .../src/main/resources/configmenu.yml | 180 ---------- .../event/MenuEventsTest.java | 26 +- 16 files changed, 11 insertions(+), 1280 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/EditMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java delete mode 100644 uSkyBlock-Core/src/main/resources/configmenu.yml diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java index b9f1b4084..d48fb6d82 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/AdminCommand.java @@ -9,7 +9,6 @@ import us.talabrek.ultimateskyblock.command.admin.AdminChallengeCommand; import us.talabrek.ultimateskyblock.command.admin.AdminIslandCommand; import us.talabrek.ultimateskyblock.command.admin.ChunkCommand; -import us.talabrek.ultimateskyblock.command.admin.ConfigCommand; import us.talabrek.ultimateskyblock.command.admin.CooldownCommand; import us.talabrek.ultimateskyblock.command.admin.DebugCommand; import us.talabrek.ultimateskyblock.command.admin.FlatlandFixCommand; @@ -76,7 +75,6 @@ public AdminCommand( @NotNull LanguageCommand languageCommand, @NotNull FlushCommand flushCommand, @NotNull JobsCommand jobsCommand, - @NotNull ConfigCommand configCommand, @NotNull DocumentCommand documentCommand, @NotNull RegionCommand regionCommand, @NotNull SetMaintenanceCommand setMaintenanceCommand, @@ -113,7 +111,6 @@ public AdminCommand( add(languageCommand); add(flushCommand); add(jobsCommand); - add(configCommand); add(documentCommand); add(regionCommand); add(setMaintenanceCommand); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java deleted file mode 100644 index b60dc20c6..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ConfigCommand.java +++ /dev/null @@ -1,96 +0,0 @@ -package us.talabrek.ultimateskyblock.command.admin; - -import com.google.inject.Inject; -import dk.lockfuglsang.minecraft.command.AbstractCommand; -import dk.lockfuglsang.minecraft.command.CompositeCommand; -import dk.lockfuglsang.minecraft.command.completion.AbstractTabCompleter; -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import us.talabrek.ultimateskyblock.uSkyBlock; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -/** - * Command for showing the config-gui. - */ -public class ConfigCommand extends CompositeCommand { - private final uSkyBlock plugin; - public static final List CONFIGS = Arrays.asList("config", "levelConfig", "challenges", "signs"); - - @Inject - public ConfigCommand(@NotNull uSkyBlock plugin) { - super("config|c", "usb.admin.config", "?config", marktr("open GUI for config")); - add(new AbstractCommand("search", marktr("searches config for a specific key")) { - @Override - public boolean execute(CommandSender commandSender, String alias, Map map, String... args) { - if (args.length > 0) { - FileConfiguration config = FileUtil.getYmlConfiguration(map.get("config") + ".yml"); - String searchTerms = String.join(" ", args); - List results = config.getKeys(true).stream() - .filter(f -> f.contains(searchTerms)) - .map(m -> tr("\u00a79{0}\u00a78: \u00a7e{1}", m.replace(searchTerms, tr("\u00a7c{0}\u00a79", searchTerms)), ConfigCommand.toString(config, m))) - .collect(Collectors.toList()); - results.add(0, tr("Found the following matching {0}:", searchTerms)); - commandSender.sendMessage(results.toArray(new String[0])); - return true; - } - return false; - } - }); - this.plugin = plugin; - } - - private static String toString(FileConfiguration config, String key) { - if (config.isConfigurationSection(key)) { - return tr("\u00a7a

"); - } else if (config.isDouble(key)) { - return tr("\u00a73{0,number,#.##}", config.getDouble(key)); - } else if (config.isBoolean(key)) { - return tr("\u00a72{0}", config.getBoolean(key)); - } else if (config.isList(key)) { - return "\n - " + String.join("\n - ", config.getStringList(key)); - } - return config.get(key).toString(); - } - - @Override - public TabCompleter getTabCompleter() { - return new AbstractTabCompleter() { - @Override - protected List getTabList(CommandSender commandSender, String term) { - return CONFIGS; - } - }; - } - - @Override - public boolean execute(CommandSender sender, String alias, Map data, String... args) { - if (args.length > 0 && CONFIGS.contains(args[0])) { - data.put("config", args[0]); - } - if (sender instanceof Player && args.length <= 1) { - String configName = "config"; - if (args.length > 0) { - if (CONFIGS.contains(args[0])) { - configName = args[0]; - } else { - sender.sendMessage(tr("\u00a7eInvalid configuration name")); - return false; - } - } - plugin.getConfigMenu().showMenu((Player) sender, configName + ".yml", 1); - return true; - } - return super.execute(sender, alias, data, args); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java index 0f4786271..be6648db9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/MenuEvents.java @@ -7,29 +7,22 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.jetbrains.annotations.NotNull; -import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.UltimateHolder; @Singleton public class MenuEvents implements Listener { private final SkyBlockMenu mainMenu; - private final ConfigMenu configMenu; @Inject - public MenuEvents(@NotNull SkyBlockMenu mainMenu, @NotNull ConfigMenu configMenu) { + public MenuEvents(@NotNull SkyBlockMenu mainMenu) { this.mainMenu = mainMenu; - this.configMenu = configMenu; } @EventHandler(priority = EventPriority.MONITOR) public void guiClick(final InventoryClickEvent event) { - if (event.getInventory().getHolder() instanceof UltimateHolder holder) { - if (holder.getMenuType() == UltimateHolder.MenuType.CONFIG) { - configMenu.onClick(event); - } else { - mainMenu.onClick(event); - } + if (event.getInventory().getHolder() instanceof UltimateHolder holder && holder.getMenuType() == UltimateHolder.MenuType.DEFAULT) { + mainMenu.onClick(event); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java deleted file mode 100644 index 61e8ad924..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/AbstractConfigMenu.java +++ /dev/null @@ -1,74 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import us.talabrek.ultimateskyblock.util.GuiItemUtil; - -import java.text.MessageFormat; -import java.text.ParseException; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; - -/** - * Created by R4zorax on 03/10/2015. - */ -public class AbstractConfigMenu { - private final FileConfiguration menuConfig; - - public AbstractConfigMenu(FileConfiguration menuConfig) { - this.menuConfig = menuConfig; - } - - public FileConfiguration getMenuConfig() { - return menuConfig; - } - - protected static void ensureCapacity(List menuList, int index) { - if (index >= menuList.size()) { - menuList.addAll(Arrays.asList(new ItemStack[Math.max(index - menuList.size(), 9)])); - } - } - - protected static int getIndex(int row, int col) { - return row * 9 + col; - } - - boolean isBlackListed(String file, String currentPath) { - return menuConfig.getStringList(file + ".blacklist").contains(currentPath); - } - - boolean isReadonly(String file, String path) { - return menuConfig.getStringList(file + ".readonly").contains(path); - } - - protected int getPage(String s) { - String format = tr("\u00a77Page {0}"); - try { - Object[] parsed = new MessageFormat(format).parse(s); - if (parsed != null && parsed.length > 0) { - return Integer.parseInt("" + parsed[0]); - } - } catch (ParseException e) { - // Ignore - } - return 1; - } - - protected ItemStack createItemFromComponentString(String components) { - return GuiItemUtil.createItemFromComponentString(components); - } - - protected ItemStack createItem(Material icon, String title, List lore) { - ItemStack itemStack = new ItemStack(icon, 1); - ItemMeta meta = Objects.requireNonNull(itemStack.getItemMeta()); - meta.setDisplayName(title); - meta.setLore(lore); - itemStack.setItemMeta(meta); - return itemStack; - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java deleted file mode 100644 index cf8a07b3d..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BiomeMenuItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import org.bukkit.block.Biome; -import org.bukkit.inventory.ItemStack; - -public class BiomeMenuItem { - private final ItemStack icon; - private final Biome biome; - private final String title; - private final String description; - - public BiomeMenuItem(ItemStack icon, Biome biome, String title, String description) { - this.icon = icon; - this.biome = biome; - this.title = title; - this.description = description; - } - - public ItemStack getIcon() { - return icon.clone(); - } - - public Biome getBiome() { - return biome; - } - - public String getTitle() { - return title; - } - - public String getDescription() { - return description; - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java deleted file mode 100644 index ec44970dd..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/BooleanEditMenu.java +++ /dev/null @@ -1,33 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; - -/** - * Simple menu-less editor for boolean values. - */ -public class BooleanEditMenu extends AbstractConfigMenu implements EditMenu { - public BooleanEditMenu(FileConfiguration menuConfig) { - super(menuConfig); - } - - @Override - public boolean onClick(InventoryClickEvent e) { - // The boolean menu is never active - return false; - } - - @Override - public Inventory createEditMenu(String configName, String path, int page) { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - if (config.isBoolean(path)) { - boolean value = config.getBoolean(path); - config.set(path, !value); - config.set("dirty", true); - } - // never returns an editor... - return null; - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java deleted file mode 100644 index c513f7fc8..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/ConfigMenu.java +++ /dev/null @@ -1,56 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import com.google.inject.Inject; -import com.google.inject.Singleton; -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.jetbrains.annotations.NotNull; -import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.Scheduler; - -import java.util.ArrayList; -import java.util.List; - -/** - * A GUI for managing the uSkyBlock config-files - */ -@Singleton -public class ConfigMenu { - - private final List editMenus; - private final MainConfigMenu mainMenu; - - @Inject - public ConfigMenu( - @NotNull uSkyBlock plugin, - @NotNull MenuItemFactory factory, - @NotNull Scheduler scheduler - ) { - FileConfiguration menuConfig = new YamlConfiguration(); - FileUtil.readConfig(menuConfig, getClass().getClassLoader().getResourceAsStream("configmenu.yml")); - this.editMenus = new ArrayList<>(); - this.mainMenu = new MainConfigMenu(plugin, menuConfig, factory, scheduler, editMenus); - this.editMenus.addAll(List.of( - new IntegerEditMenu(menuConfig, factory, mainMenu), - new BooleanEditMenu(menuConfig), - new StringEditMenu(menuConfig, mainMenu), - mainMenu // mainMenu goes last (catch all) - )); - } - - public void showMenu(Player player, String configName, int page) { - player.openInventory(mainMenu.createEditMenu(configName, null, page)); - } - - public void onClick(InventoryClickEvent event) { - event.setCancelled(true); - for (EditMenu editMenu : editMenus) { - if (editMenu.onClick(event)) { - break; - } - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/EditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/EditMenu.java deleted file mode 100644 index 08b478f2c..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/EditMenu.java +++ /dev/null @@ -1,25 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; - -/** - * Common interface for menus. - */ -public interface EditMenu { - /** - * Returns true if the action belonged to the menu. - * @param e A click on an item, not sure if it belongs on this menu. - * @return true if no further processing is needed. - */ - boolean onClick(InventoryClickEvent e); - - /** - * Creates an edit menu for this type. - * @param configName Configuration name (filename) - * @param path Path to node - * @param page The page to show (for multi-page editors) - * @return An editor or null if this is not the right edit-menu. - */ - Inventory createEditMenu(String configName, String path, int page); -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java deleted file mode 100644 index 3227860f3..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/IntegerEditMenu.java +++ /dev/null @@ -1,174 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import dk.lockfuglsang.minecraft.util.ItemStackUtil; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import us.talabrek.ultimateskyblock.player.UltimateHolder; -import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; -import us.talabrek.ultimateskyblock.util.GuiItemUtil; - -import java.util.*; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; - -/** - * Editor for integer nodes. - */ -public class IntegerEditMenu extends AbstractConfigMenu implements EditMenu { - private static final Material DEFAULT_NUMBER_ICON = Material.BLUE_STAINED_GLASS_PANE; - private final FileConfiguration menuConfig; - private final MenuItemFactory factory; - private final EditMenu parent; - - private final Map increments = new LinkedHashMap<>(); - - public IntegerEditMenu(FileConfiguration menuConfig, MenuItemFactory factory, EditMenu parent) { - super(menuConfig); - this.menuConfig = menuConfig; - this.factory = factory; - this.parent = parent; - ConfigurationSection incSection = menuConfig.getConfigurationSection("integer-menu.increment"); - if (incSection != null) { - for (String inc : incSection.getKeys(false)) { - int incValue = Integer.parseInt(inc, 10); - String itemType = incSection.getString(inc, Material.IRON_INGOT.name()); - String displayName = incValue < 0 ? tr("\u00a7c{0,number,#}", incValue) : tr("\u00a7a+{0,number,#}", incValue); - ItemStack displayItem = GuiItemUtil.createGuiDisplayItem(itemType, displayName); - increments.put(inc, displayItem); - } - } - } - - @Override - public boolean onClick(InventoryClickEvent event) { - if (!(event.getInventory().getHolder() instanceof UltimateHolder) || - ((UltimateHolder) event.getInventory().getHolder()).getTitle() == null || - !stripFormatting(((UltimateHolder) event.getInventory().getHolder()).getTitle()).contains(stripFormatting(getTitle()))) { - return false; - } - if (event.getSlotType() != InventoryType.SlotType.CONTAINER) { - return true; - } - Player player = (Player) event.getWhoClicked(); - Inventory menu = event.getInventory(); - ItemStack returnItem = menu.getItem(getIndex(5, 0)); - String configName = returnItem.getItemMeta().getLore().get(0); - String path = returnItem.getItemMeta().getLore().get(1); - int page = getPage(returnItem.getItemMeta().getLore().get(2)); - int slot = event.getSlot(); - int row = slot / 9; - int col = slot % 9; - ItemStack clickedItem = event.getCurrentItem(); - if (slot >= getIndex(3, 0) && slot <= getIndex(3, 8)) { - // increment buttons - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - int value = config.getInt(path, 0); - int increment = getDisplayNameAsInt(clickedItem); - if (event.getClick() == ClickType.LEFT) { - value += increment; - } else if (event.getClick() == ClickType.RIGHT) { - value = increment; - } - config.set(path, value); - config.set("dirty", true); - } - if (slot != getIndex(5, 0)) { - player.openInventory(createEditMenu(configName, path, page)); - } else { - player.openInventory(parent.createEditMenu(configName, path, page)); - } - return true; - } - - private int getDisplayNameAsInt(ItemStack clickedItem) { - int number = 0; - try { - number = Integer.parseInt(stripFormatting(clickedItem.getItemMeta().getDisplayName()).replaceAll("[^0-9\\-]+", ""), 10); - } catch (NumberFormatException ex) { - } - return number; - } - - /** - * An editor for integers. - *
-     *     Config: Integer Editor
-     *     +---+---+---+---+---+---+---+---+---+
-     *  0  |   |   |   |   |   |   |   | G |   |
-     *     +---+---+---+---+---+---+---+---+---+
-     *  1  | R | R | R |   | I |   | G | G | G |
-     *     +---+---+---+---+---+---+---+---+---+
-     *  2  |   |   |   |   |   |   |   | G |   |
-     *     +---+---+---+---+---+---+---+---+---+
-     *  3  |-1k|100|-10|-1 | 0 |+1 |+10|100|+1k|
-     *     +---+---+---+---+---+---+---+---+---+
-     *  4  |   |   |   |   |   |   | ^ |   |   |
-     *     +---+---+---+---+---+---+---+---+---+
-     *  5  |SAV|   |   |   |   |   |   |   |   |
-     *     +---+---+---+---+---+---+---+---+---+
-     *       0   1   2   3   4   5   6   7   8
-     * 
- */ - @Override - public Inventory createEditMenu(String configName, String path, int page) { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - if (!config.isInt(path)) { - return null; - } - int value = config.getInt(path, 0); - Inventory menu = Bukkit.createInventory(new UltimateHolder(null, getTitle(), MenuType.CONFIG), 6 * 9, getTitle()); - menu.setMaxStackSize(MenuItemFactory.MAX_INT_VALUE); - ItemStack frame = createItem(Material.BLACK_STAINED_GLASS_PANE, null, null); - for (int i = 0; i < 27; i++) { - menu.setItem(i, frame); - } - int nvalue = Math.abs(value); - int col = 7; - do { - int tenValue = nvalue % 10; - String itemType = menuConfig.getString("integer-menu.number-items." + tenValue, DEFAULT_NUMBER_ICON.name()); - String displayName = value < 0 ? tr("\u00a7c{0,number,#}", value) : tr("\u00a7a{0,number,#}", value); - ItemStack displayItem = GuiItemUtil.createGuiDisplayItem(itemType, displayName); - menu.setItem(getIndex(1, col), displayItem); - nvalue = (nvalue - tenValue) / 10; - col--; - } while (nvalue != 0 && col > 0); - if (value < 0) { - menu.setItem(getIndex(1, col), createItem(Material.RED_CARPET, MenuItemFactory.INT + value, null)); - } - ItemStack valueItem = factory.createIntegerItem(value, path, config, false); - List lore = valueItem.getItemMeta().getLore(); - menu.setItem(getIndex(3, 4), valueItem); - col = 0; - for (ItemStack inc : increments.values()) { - if (col == 4) { // Skip center - col++; - } - int incValue = getDisplayNameAsInt(inc); - ItemStack icon = ItemStackUtil.builder(inc) - .lore(tr("&aLeft:&7 Increment with {0}", inc.getItemMeta().getDisplayName())) - .lore(tr("&cRight-Click:&7 Set to {0}", incValue)) - .lore(lore) - .build(); - menu.setItem(getIndex(3, col), icon); - col++; - } - menu.setItem(getIndex(5, 0), createItem(Material.OAK_DOOR, "\u00a79" + tr("Return"), - Arrays.asList(configName, path, tr("\u00a77Page {0}", page)))); - return menu; - } - - private String getTitle() { - return tr("Config:") + " " + tr("\u00a79Integer Editor"); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java deleted file mode 100644 index 85f0a1b87..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MainConfigMenu.java +++ /dev/null @@ -1,329 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import us.talabrek.ultimateskyblock.player.UltimateHolder; -import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; -import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.Scheduler; - -import java.io.File; -import java.io.IOException; -import java.text.MessageFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.pre; -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static us.talabrek.ultimateskyblock.menu.MenuItemFactory.READONLY; -import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; -import static dk.lockfuglsang.minecraft.util.FormatUtil.wordWrap; -import static dk.lockfuglsang.minecraft.util.ItemStackUtil.builder; - -/** - * The primary config menu. - */ -public class MainConfigMenu extends AbstractConfigMenu implements EditMenu { - private final uSkyBlock plugin; - private final MenuItemFactory factory; - private final Scheduler scheduler; - private final List editMenus; - - public MainConfigMenu(uSkyBlock plugin, FileConfiguration menuConfig, MenuItemFactory factory, Scheduler scheduler, List editMenus) { - super(menuConfig); - this.plugin = plugin; - this.factory = factory; - this.scheduler = scheduler; - this.editMenus = editMenus; - } - - @Override - public boolean onClick(InventoryClickEvent event) { - if (!(event.getInventory().getHolder() instanceof UltimateHolder)) - return false; - String title = stripFormatting(((UltimateHolder) event.getInventory().getHolder()).getTitle()); - final Player player = (Player) event.getWhoClicked(); - if (!title.contains(".yml")) { - return false; - } - ItemStack item = event.getCurrentItem(); - if (item == null) { - return true; - } - if(event.getInventory().equals(event.getView().getBottomInventory())) { - return true; //we clicked on the players inventory, lets not try to do anyting - } - if (event.getSlot() % 9 == 0 && (item.getType() == Material.BOOK || item.getType() == Material.WRITABLE_BOOK)) { - String configName = getConfigName(item); - int page = getConfigPage(item); - if (event.isShiftClick()) { - if (event.getSlot() == getIndex(1,0) && page > 10) { - page -= 10; - } else if (event.getSlot() == getIndex(3,0)) { - page += 10; - } - } - Inventory menu = createFileMenu(configName, page); - player.openInventory(menu); - } else if (event.getSlot() == getIndex(5, 0) && item.getType() == Material.ENDER_CHEST) { - ItemStack currentMenu = getCurrentMenu(event); - String configName = getConfigName(currentMenu); - int page = getConfigPage(currentMenu); - player.closeInventory(); - saveConfig(player, configName, page); - } else { - ItemStack currentMenu = getCurrentMenu(event); - String configName = getConfigName(currentMenu); - int page = getConfigPage(currentMenu); - String path = findPath(event.getInventory(), event.getSlot()); - if (path != null && !isReadonly(configName, path)) { - Inventory editor = null; - for (EditMenu editMenu : editMenus) { - if (editMenu != this) { - editor = editMenu.createEditMenu(configName, path, page); - } - if (editor != null) { - break; - } - } - if (editor == null) { - player.openInventory(createFileMenu(configName, page)); - } else { - player.openInventory(editor); - } - } - } - return true; - } - - private String findPath(Inventory inventory, int slot) { - ItemStack item = inventory.getItem(slot); - if (item == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - sb.append(stripFormatting(item.getItemMeta().getDisplayName())); - int row = slot / 9; - int col = slot % 9; - while (col >= 1) { - ItemStack parent = inventory.getItem(getIndex(row, col)); - if(parent != null && parent.getType() != Material.PAPER) { - col--; - parent = inventory.getItem(getIndex(row, col)); - } - else if(parent == null || parent.getType() != Material.PAPER) { - row--; - parent = inventory.getItem(getIndex(row, col)); - } - else if (parent != null && parent.getType() == Material.PAPER) { - sb.insert(0, stripFormatting(parent.getItemMeta().getDisplayName()) + "."); - col--; - } - } - return sb.toString(); - } - - private void saveConfig(final Player player, final String configName, final int page) { - scheduler.async(() -> { - try { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - config.set("dirty", null); - config.save(new File(plugin.getDataFolder(), configName)); - scheduler.sync(() -> { - plugin.reloadConfig(); - player.sendMessage(tr("\u00a7eConfiguration saved and reloaded.")); - player.openInventory(createEditMenu(configName, null, page)); - }); - } catch (IOException e) { - player.sendMessage(tr("\u00a7cError! \u00a79Unable to save config file!")); - } - }); - } - - private Inventory createFileMenu(String filename, int page) { - FileConfiguration config = FileUtil.getYmlConfiguration(filename); - int row = 0; - int col = 1; - ArrayList menuList = new ArrayList<>(54); - for (String key : config.getKeys(false)) { - if (config.isConfigurationSection(key)) { - row = addSection(menuList, config.getConfigurationSection(key), row, col, config, filename); - } - } - int maxPages = (int) Math.ceil(menuList.size() / 54d); - if (page < 1) { - page = 1; - } - if (page > maxPages) { - page = maxPages; - } - String title = tr("Config:") + " " + pre("{0} ({1}/{2})", filename, page, maxPages); - Inventory menu = Bukkit.createInventory(new UltimateHolder(null, title, MenuType.CONFIG), 6 * 9, title); - menu.setMaxStackSize(MenuItemFactory.MAX_INT_VALUE); - int startOffset = (page-1)*54; - // Add section markers on top line - for (int i = 1; i <= 8; i++) { - if (menuList.get(startOffset+i) != null) { - break; // Already an item here... we are done - } - int offset = 9; - while (menuList.get(startOffset+i) == null) { - // find on "higher (hidden) row" - if (menuList.get(startOffset+i-offset) != null) { - menuList.set(startOffset+i, menuList.get(startOffset+i-offset).clone()); - break; - } - offset += 9; - } - } - for (int i = startOffset; i < (page*54); i++) { - if (i >= menuList.size()) { - break; - } - ItemStack itemStack = menuList.get(i); - if (itemStack != null) { - menu.setItem(i-startOffset, itemStack); - } - } - menu.setItem(0, builder(new ItemStack(page == 1 ? Material.WRITABLE_BOOK : Material.BOOK, 1)) - .displayName(filename) - .lore(tr("\u00a77Page {0}", 1)) - .lore(tr("\u00a73First Page")) - .build()); - int offset = 2; - if (page > 3) { - offset = page-1; - } - if (offset > maxPages-3 && maxPages > 5) { - offset = maxPages-3; - } - for (int i = offset; maxPages > offset && i <= Math.min(offset+2, maxPages-1); i++) { - menu.setItem((1 + i - offset) * 9, builder(new ItemStack(page == i ? Material.WRITABLE_BOOK : Material.BOOK, i)) - .displayName(filename) - .lore(tr("\u00a77Page {0}", i)) - .build()); - } - menu.setItem(getIndex(4,0), builder(new ItemStack(page == maxPages ? Material.WRITABLE_BOOK : Material.BOOK, maxPages)) - .displayName(filename) - .lore(tr("\u00a77Page {0}", maxPages)) - .lore(tr("\u00a73Last Page")) - .build()); - ItemStack itemStack = builder(new ItemStack(Material.ENDER_CHEST, 1)) - .displayName(tr("\u00a7cSave & Reload config")) - .lore(Arrays.asList(tr("\u00a77Saves the settings to\n\u00a77file & reloads again.\n\u00a7cNote: \u00a77Use with care!").split("\n"))) - .select(config.getBoolean("dirty", false)) - .build(); - menu.setItem(getIndex(5, 0), itemStack); - return menu; - } - - private String getConfigName(ItemStack currentMenu) { - if (currentMenu != null && currentMenu.getItemMeta().getDisplayName() != null) { - return stripFormatting(currentMenu.getItemMeta().getDisplayName()); - } - return "config.yml"; - } - - private int getConfigPage(ItemStack currentMenu) { - if (currentMenu != null && currentMenu.getItemMeta() != null - && currentMenu.getItemMeta().getLore() != null - && !currentMenu.getItemMeta().getLore().isEmpty()) { - try { - Object[] parts = new MessageFormat(tr("\u00a77Page {0}")).parse(currentMenu.getItemMeta().getLore().get(0)); - if (parts != null && parts.length == 1) { - return Integer.parseInt("" + parts[0]); - } - } catch (ParseException e) { - // Ignore - } - } - return 1; - } - private ItemStack getCurrentMenu(InventoryClickEvent event) { - int index = 0; - ItemStack currentMenu = event.getInventory().getItem(index); - while (currentMenu != null && currentMenu.getType() != Material.WRITABLE_BOOK) { - index += 9; - currentMenu = event.getInventory().getItem(index); - } - return currentMenu; - } - - @Override - public Inventory createEditMenu(String configName, String path, int page) { - return createFileMenu(configName, page); - } - - private int addSection(ArrayList menuList, ConfigurationSection sec, int row, int col, FileConfiguration config, String filename) { - if (isBlackListed(filename, sec.getCurrentPath())) { - return row; - } - ItemStack item = new ItemStack(Material.PAPER, 1); - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName("\u00a77\u00a7o" + sec.getName()); - List comments = config.getComments(sec.getCurrentPath()); - if (!comments.isEmpty()) { - meta.setLore(wordWrap(String.join(" ", comments), 20, 20)); - } - item.setItemMeta(meta); - int index = getIndex(row, col); - ensureCapacity(menuList, index); - menuList.set(index, item); - int colbase = ++col; - boolean lastWasSection = true; - for (String key : sec.getKeys(false)) { - index = getIndex(row, col); - ensureCapacity(menuList, index); - if (sec.isConfigurationSection(key)) { - if (!lastWasSection && col != colbase) { - row++; - col = colbase; - } - row = addSection(menuList, sec.getConfigurationSection(key), row, col, config, filename); - col = colbase; - lastWasSection = true; - } else { - String path = sec.getCurrentPath() + "." + key; - if (isBlackListed(filename, path)) { - continue; // Skip - } - boolean readonly = isReadonly(filename, path); - item = null; - if (sec.isBoolean(key)) { - item = factory.createBooleanItem(sec.getBoolean(key), path, config, readonly); - } else if (sec.isInt(key)) { - item = factory.createIntegerItem(sec.getInt(key), path, config, readonly); - } else { - item = factory.createStringItem(sec.getString(key, ""), path, config, readonly); - } - if (item != null) { - if (readonly) { - ItemMeta itemMeta = item.getItemMeta(); - List lore = itemMeta.getLore(); - lore.set(0, READONLY + lore.get(0) + tr("\u00a77 (readonly)")); - itemMeta.setLore(lore); - item.setItemMeta(itemMeta); - } - menuList.set(index, item); - col++; - lastWasSection = false; - } - } - if (col >= 9) { - row++; - col = colbase; - } - } - return col != colbase ? row+1 : row; - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java deleted file mode 100644 index a129c0096..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/MenuItemFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import org.bukkit.Material; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.ArrayList; -import java.util.List; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.wordWrap; - -/** - * A convenience factory for creating the itemstacks used in menus. - */ -public class MenuItemFactory { - public static final String INT = "\u00a7b"; - public static final String FALSE = "\u00a7c"; - public static final String TRUE = "\u00a7a"; - public static final String STRING = "\u00a79"; - public static final int MAX_INT_VALUE = 64; - public static final String READONLY = "\u00a77"; - - public ItemStack createStringItem(String value, String path, FileConfiguration config, boolean readonly) { - return createLeafItem(new ItemStack(readonly ? Material.FLINT_AND_STEEL : Material.NAME_TAG, 1), value, path, config); - } - - public ItemStack createLeafItem(ItemStack item, String value, String path, FileConfiguration config) { - ItemMeta meta = item.getItemMeta(); - meta.setDisplayName("\u00a77\u00a7o" + path.substring(path.lastIndexOf('.')+1)); - List lore = new ArrayList<>(); - lore.add(STRING + value); - List comments = config.getComments(path); - if (!comments.isEmpty()) { - lore.addAll(wordWrap(String.join(" ", comments), 20, 20)); - } - meta.setLore(lore); - item.setItemMeta(meta); - return item; - } - - public ItemStack createIntegerItem(int value, String path, FileConfiguration config, boolean readonly) { - ItemStack item = createIntegerIcon(value, readonly); - return createLeafItem( - item, - INT + value, - path, config); - } - - public ItemStack createIntegerIcon(int value, boolean readonly) { - return Math.abs(value) <= MAX_INT_VALUE - ? (readonly ? new ItemStack(Material.DETECTOR_RAIL, value) : new ItemStack(Material.RAIL, value)) - : (readonly ? new ItemStack(Material.IRON_BARS, 1) : new ItemStack(Material.ACTIVATOR_RAIL, 1)); - } - - public ItemStack createBooleanItem(boolean value, String path, FileConfiguration config, boolean readonly) { - ItemStack icon = new ItemStack(readonly ? (value ? Material.GREEN_WOOL : Material.RED_WOOL) : (value ? Material.LIME_WOOL : Material.PINK_WOOL), 1); - return createLeafItem(icon, value ? TRUE + tr("true") : FALSE + tr("false"), - path, config); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 363d0e60a..47fa57167 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -67,7 +67,6 @@ public class SkyBlockMenu { private final IslandGenerator islandGenerator; private final LimitLogic limitLogic; private final ConfirmHandler confirmHandler; - private final ConfigMenu configMenu; private final Scheduler scheduler; private final ItemStack sign = new ItemStack(Material.OAK_SIGN, 1); @@ -113,7 +112,6 @@ public SkyBlockMenu( @NotNull IslandGenerator islandGenerator, @NotNull LimitLogic limitLogic, @NotNull ConfirmHandler confirmHandler, - @NotNull ConfigMenu configMenu, @NotNull Scheduler scheduler ) { this.plugin = plugin; @@ -123,7 +121,6 @@ public SkyBlockMenu( this.islandGenerator = islandGenerator; this.limitLogic = limitLogic; this.confirmHandler = confirmHandler; - this.configMenu = configMenu; this.scheduler = scheduler; } @@ -682,8 +679,6 @@ public void onClick(InventoryClickEvent event) { onClickCreateMenu(event, p, meta, slotIndex, menuSize); } else if (inventoryName.equalsIgnoreCase(stripFormatting(tr("Island Restart Menu")))) { onClickRestartMenu(event, p, meta, slotIndex, currentItem); - } else if (inventoryName.startsWith(stripFormatting(tr("Config:"))) && event.getWhoClicked() instanceof Player) { - configMenu.onClick(event); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java deleted file mode 100644 index 7435deaf2..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/StringEditMenu.java +++ /dev/null @@ -1,174 +0,0 @@ -package us.talabrek.ultimateskyblock.menu; - -import dk.lockfuglsang.minecraft.file.FileUtil; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import us.talabrek.ultimateskyblock.player.UltimateHolder; -import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.stripFormatting; - -/** - * Complex editor for string values (only simple keyboard, no extended). - */ -public class StringEditMenu extends AbstractConfigMenu implements EditMenu { - private final EditMenu parent; - private final List keyboard = new ArrayList<>(); - private final List capslockOverlay = new ArrayList<>(); - - private final ItemStack capsOn; - private final ItemStack capsOff; - - private final int capsIndex; - private final int backspaceIndex; - private final int returnIndex; - - public StringEditMenu(FileConfiguration menuConfig, EditMenu parent) { - super(menuConfig); - this.parent = parent; - List characterMap = menuConfig.getList("keyboard.en"); - ensureCapacity(keyboard, 9 * 6); - ensureCapacity(capslockOverlay, 9 * 6); - int row = 0; - for (Object o : characterMap) { - int col = 0; - if (o instanceof List) { - for (String item : (List) o) { - ItemStack character = createItemFromComponentString(item); - if (character != null) { - keyboard.set(getIndex(row, col), character); - } - col++; - } - } - row++; - } - ConfigurationSection overlay = menuConfig.getConfigurationSection("keyboard.capslock.overlay"); - if (overlay != null) { - for (String key : overlay.getKeys(false)) { - int index = Integer.parseInt(key, 10); - ItemStack item = createItemFromComponentString(overlay.getString(key)); - if (item != null) { - capslockOverlay.set(index, item); - } - } - } - capsOn = createItemFromComponentString(menuConfig.getString("keyboard.capslock.true")); - capsOff = createItemFromComponentString(menuConfig.getString("keyboard.capslock.false")); - keyboard.set(getIndex(0, 0), createItem(Material.OAK_DOOR, "\u00a79" + tr("Return"), null)); - capsIndex = getIndex(5, 0); - keyboard.set(capsIndex, capsOff); - backspaceIndex = getIndex(0, 5); - returnIndex = 0; - } - - @Override - public boolean onClick(InventoryClickEvent e) { - if (!(e.getInventory().getHolder() instanceof UltimateHolder) || - !stripFormatting(((UltimateHolder) e.getInventory().getHolder()).getTitle()).equals(stripFormatting(getTitle()))) { - return false; - } - Player player = (Player) e.getWhoClicked(); - ItemStack returnItem = e.getInventory().getItem(0); - String configName = returnItem.getItemMeta().getLore().get(0); - String path = returnItem.getItemMeta().getLore().get(1); - int page = getPage(returnItem.getItemMeta().getLore().get(2)); - ItemStack currentItem = e.getCurrentItem(); - boolean isCaps = e.getInventory().getItem(capsIndex).getItemMeta().getDisplayName().equals(tr("Caps On")); - if (currentItem != null) { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - String value = config.getString(path); - if (e.getSlot() == capsIndex) { - // Toggle caps - ItemStack capsItem = isCaps ? capsOff.clone() : capsOn.clone(); - ItemMeta meta = capsItem.getItemMeta(); - meta.setLore(Collections.singletonList(value)); - capsItem.setItemMeta(meta); - e.getInventory().setItem(capsIndex, capsItem); - isCaps = !isCaps; - } else if (e.getSlot() == backspaceIndex) { - if (value.length() > 0) { - value = value.substring(0, value.length() - 1); - config.set(path, value); - config.set("dirty", true); - } - } else if (e.getSlot() == returnIndex) { - player.openInventory(parent.createEditMenu(configName, path, page)); - return true; - } else if (currentItem.getType() == Material.PLAYER_HEAD) { - String character = stripFormatting(currentItem.getItemMeta().getDisplayName()); - if (character.isEmpty()) { - character = " "; - } - value += isCaps ? character.toUpperCase() : character.toLowerCase(); - config.set(path, value); - config.set("dirty", true); - } - // re-load the ui (refresh) - player.openInventory(createEditMenuInternal(configName, path, page, isCaps)); - } - return true; - } - - @Override - public Inventory createEditMenu(String configName, String path, int page) { - return createEditMenuInternal(configName, path, page, false); - } - - private Inventory createEditMenuInternal(String configName, String path, int page, boolean isCaps) { - FileConfiguration config = FileUtil.getYmlConfiguration(configName); - if (!config.isString(path)) { - return null; - } - String value = config.getString(path, ""); - Inventory menu = Bukkit.createInventory(new UltimateHolder(null, getTitle(), MenuType.DEFAULT), 9 * 6, getTitle()); - setCharacters(menu, value, keyboard); - if (isCaps) { - setCharacters(menu, value, capslockOverlay); - } - ItemStack returnItem = menu.getItem(0).clone(); - ItemMeta meta = returnItem.getItemMeta(); - meta.setLore(Arrays.asList(configName, path, tr("\u00a77Page {0}", page))); - returnItem.setItemMeta(meta); - menu.setItem(0, returnItem); - - ItemStack capsItem = isCaps ? capsOn.clone() : capsOff.clone(); - ItemMeta itemMeta = capsItem.getItemMeta(); - itemMeta.setLore(List.of(value)); - capsItem.setItemMeta(itemMeta); - menu.setItem(capsIndex, capsItem); - - return menu; - } - - private void setCharacters(Inventory menu, String value, List itemList) { - int index = 0; - for (ItemStack item : itemList) { - if (item != null) { - ItemStack clone = item.clone(); - ItemMeta itemMeta = clone.getItemMeta(); - itemMeta.setLore(Collections.singletonList(value)); - clone.setItemMeta(itemMeta); - menu.setItem(index, clone); - } - index++; - } - } - - private String getTitle() { - return tr("Config:") + " " + tr("\u00a79Text Editor"); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 14443f179..0e7e1be4c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -60,7 +60,6 @@ import us.talabrek.ultimateskyblock.island.level.LevelLogic; import us.talabrek.ultimateskyblock.island.task.CreateIslandTask; import us.talabrek.ultimateskyblock.island.task.SetBiomeTask; -import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.IslandPerk; import us.talabrek.ultimateskyblock.player.PerkLogic; @@ -110,8 +109,6 @@ public class uSkyBlock extends JavaPlugin implements uSkyBlockAPI, CommandManage @Inject private SkyBlockMenu menu; @Inject - private ConfigMenu configMenu; - @Inject private ChallengeLogic challengeLogic; @Inject private EventLogic eventLogic; @@ -600,10 +597,6 @@ public SkyBlockMenu getMenu() { return menu; } - public ConfigMenu getConfigMenu() { - return configMenu; - } - public ChallengeLogic getChallengeLogic() { return challengeLogic; } diff --git a/uSkyBlock-Core/src/main/resources/configmenu.yml b/uSkyBlock-Core/src/main/resources/configmenu.yml deleted file mode 100644 index 4b0f529ab..000000000 --- a/uSkyBlock-Core/src/main/resources/configmenu.yml +++ /dev/null @@ -1,180 +0,0 @@ -# -# Config Menu -# =========== -# This file holds configuration of the /usb config menu. -config.yml: - # blacklist contains paths that should be totally excluded from the menu - blacklist: - - version - - force-replace - - dirty - - # readonly contains paths that should not be editable from the menu - readonly: - - options.general.spawnSize - - options.general.worldName - - options.island.protectionRange - - options.island.distance - - options.island.height - - nether.enabled - -integer-menu: - increment: - '-1000': 'EMERALD' - '-100': 'DIAMOND' - '-10': 'GOLD_INGOT' - '-1': 'IRON_INGOT' - '1': 'IRON_INGOT' - '10': 'GOLD_INGOT' - '100': 'DIAMOND' - '1000': 'EMERALD' - number-items: - 0: 'ENDER_PEARL' - 1: 'LEVER' - -keyboard: - en: - - # row 0 - - null - - > - minecraft:player_head[minecraft:custom_name='{"text":"-","color":"white","italic":false}',minecraft:profile={id:[I;-711236940,169690229,-1514922064,-1249482241],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg2YzljOTc3YTM2ZDg5ZjVmNGU5ZDJhNmQ4YjhkNTg5YTc1MTE4YjFjZjllMzZjNGVhYzdlOWE2MTE2YSJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"!","color":"white","italic":false}',minecraft:profile={id:[I;171321584,-172668305,-2141682176,113936178],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODdkMTlhYWJmY2ZkOTlmZmFiYTQyMTRjYWVmMjk5NTE2Y2U1MmU2ZDEzYmYyZGRhMTI1OTg1ZTQ4MWI3MmY5In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":":","color":"white","italic":false}',minecraft:profile={id:[I;792203082,1690520364,-1357353911,378725961],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ4OThjNDBlNDdjNWQyZDc2OTI0MDY1MzYwNzY4MDY1ZDYyNGVlNWI5ZWUwYmU5ZTEyYjk4ZmI3N2M3NiJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"?","color":"white","italic":false}',minecraft:profile={id:[I;-2138389994,2040155458,-1117225825,203327953],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FhYjI3Mjg0MGQ3OTBjMmVkMmJlNWM4NjAyODlmOTVkODhlMzE2YjY1YzQ1NmZmNmEzNTE4MGQyZTViZmY2In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"Backspace","color":"white","italic":false}',minecraft:profile={id:[I;-2015138023,1082802278,-1796230949,632908872],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjI1OTliZDk4NjY1OWI4Y2UyYzQ5ODg1MjVjOTRlMTlkZGQzOWZhZDA4YTM4Mjg0YTE5N2YxYjcwNjc1YWNjIn19fQ=="}]}] - - - > - minecraft:player_head[minecraft:custom_name='{"text":"7","color":"white","italic":false}',minecraft:profile={id:[I;-878939587,912477939,-1472411840,1608374210],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDRiYTZhYzA3ZDQyMjM3N2E4NTU3OTNmMzZkZWEyZWQyNDAyMjNmNTJmZDE2NDgxODE2MTJlY2QxYTBjZmQ1In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"8","color":"white","italic":false}',minecraft:profile={id:[I;907120039,1770604034,-1354530216,-1642146097],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzYxYThhNjQxNDM3YmU5YWVhMjA3MjUzZGQzZjI1NDQwZDk1NGVhMmI1ODY2YzU1MmYzODZiMjlhYzRkMDQ5In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"9","color":"white","italic":false}',minecraft:profile={id:[I;-1954120080,306858575,-1753072811,-2119470949],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE5MjhlMWJmZDg2YTliNzkzOTdjNGNiNGI2NWVmOTlhZjQ5YjdkNWY3OTU3YWQ2MmMwYzY5OWE2MjJjZmJlIn19fQ=="}]}] - - - # row 1 - - > - minecraft:player_head[minecraft:custom_name='{"text":"A","color":"white","italic":false}',minecraft:profile={id:[I;-387904571,-1186053256,-1521701775,-1503461687],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTY3ZDgxM2FlN2ZmZTViZTk1MWE0ZjQxZjJhYTYxOWE1ZTM4OTRlODVlYTVkNDk4NmY4NDk0OWM2M2Q3NjcyZSJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"B","color":"white","italic":false}',minecraft:profile={id:[I;-789081089,-1337900420,-1138473976,887719674],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTBjMWI1ODRmMTM5ODdiNDY2MTM5Mjg1YjJmM2YyOGRmNjc4NzEyM2QwYjMyMjgzZDg3OTRlMzM3NGUyMyJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"C","color":"white","italic":false}',minecraft:profile={id:[I;-611460024,-2066264168,-1125969998,-734210851],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJlOTgzZWM0NzgwMjRlYzZmZDA0NmZjZGZhNDg0MjY3NjkzOTU1MWI0NzM1MDQ0N2M3N2MxM2FmMThlNmYifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"D","color":"white","italic":false}',minecraft:profile={id:[I;-1052582957,-606122170,-1533996522,758791822],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5M2RjMGQ0YzVlODBmZjlhOGEwNWQyZmNmZTI2OTUzOWNiMzkyNzE5MGJhYzE5ZGEyZmNlNjFkNzEifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"E","color":"white","italic":false}',minecraft:profile={id:[I;-1762997702,253904975,-1160296939,899146129],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiMjczN2VjYmY5MTBlZmUzYjI2N2RiN2Q0YjMyN2YzNjBhYmM3MzJjNzdiZDBlNGVmZjFkNTEwY2RlZiJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"F","color":"white","italic":false}',minecraft:profile={id:[I;1560904243,1546079882,-1552968292,-1640692709],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjE4M2JhYjUwYTMyMjQwMjQ4ODZmMjUyNTFkMjRiNmRiOTNkNzNjMjQzMjU1OWZmNDllNDU5YjRjZDZhIn19fQ=="}]}] - - - > - minecraft:player_head[minecraft:custom_name='{"text":"4","color":"white","italic":false}',minecraft:profile={id:[I;-1027958042,2089700528,-1636219490,795580140],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiZmNmYjQ4OWRhODY3ZGNlOTZlM2MzYzE3YTNkYjdjNzljYWU4YWMxZjlhNWE4YzhhYzk1ZTRiYTMifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"5","color":"white","italic":false}',minecraft:profile={id:[I;1178264348,1943227287,-1528822921,2139767762],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY0ZWNmMTEwYjBhY2VlNGFmMWRhMzQzZmIxMzZmMWYyYzIxNjg1N2RmZGE2OTYxZGVmZGJlZTdiOTUyOCJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"6","color":"white","italic":false}',minecraft:profile={id:[I;-473210008,1283935899,-1557529636,-1601781775],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMzMWE2YTZmY2Q2OTk1YjYyMDg4ZDM1M2JmYjY4ZDliODlhZTI1ODMyNWNhZjNmMjg4NjQ2NGY1NGE3MzI5In19fQ=="}]}] - - - # row 2 - - > - minecraft:player_head[minecraft:custom_name='{"text":"G","color":"white","italic":false}',minecraft:profile={id:[I;184647342,-850573077,-1811446210,2035043244],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWNhM2YzMjRiZWVlZmI2YTBlMmM1YjNjNDZhYmM5MWNhOTFjMTRlYmE0MTlmYTQ3NjhhYzMwMjNkYmI0YjIifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"H","color":"white","italic":false}',minecraft:profile={id:[I;-1166385348,-613332953,-2045587861,-668014190],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFmMzQ2MmE0NzM1NDlmMTQ2OWY4OTdmODRhOGQ0MTE5YmM3MWQ0YTVkODUyZTg1YzI2YjU4OGE1YzBjNzJmIn19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"I","color":"white","italic":false}',minecraft:profile={id:[I;716329816,-559266121,-1286481549,709136369],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDYxNzhhZDUxZmQ1MmIxOWQwYTM4ODg3MTBiZDkyMDY4ZTkzMzI1MmFhYzZiMTNjNzZlN2U2ZWE1ZDMyMjYifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"J","color":"white","italic":false}',minecraft:profile={id:[I;-1105258889,-1352380583,-2051136433,686494470],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2E3OWRiOTkyMzg2N2U2OWMxZGJmMTcxNTFlNmY0YWQ5MmNlNjgxYmNlZGQzOTc3ZWViYmM0NGMyMDZmNDkifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"K","color":"white","italic":false}',minecraft:profile={id:[I;1327910285,-2019341974,-1390547552,-1574293264],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTQ2MWIzOGM4ZTQ1NzgyYWRhNTlkMTYxMzJhNDIyMmMxOTM3NzhlN2Q3MGM0NTQyYzk1MzYzNzZmMzdiZTQyIn19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"L","color":"white","italic":false}',minecraft:profile={id:[I;1974340903,-197377683,-1767834154,-608535888],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzE5ZjUwYjQzMmQ4NjhhZTM1OGUxNmY2MmVjMjZmMzU0MzdhZWI5NDkyYmNlMTM1NmM5YWE2YmIxOWEzODYifX19"}]}] - - - > - minecraft:player_head[minecraft:custom_name='{"text":"1","color":"white","italic":false}',minecraft:profile={id:[I;-865041524,-1727705171,-2040559009,-2092760462],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFhOTQ2M2ZkM2M0MzNkNWUxZDlmZWM2ZDVkNGIwOWE4M2E5NzBiMGI3NGRkNTQ2Y2U2N2E3MzM0OGNhYWIifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"2","color":"white","italic":false}',minecraft:profile={id:[I;-1923919687,1684295499,-1717680598,-229783438],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWNiNDE5ZDk4NGQ4Nzk2MzczYzk2NDYyMzNjN2EwMjY2NGJkMmNlM2ExZDM0NzZkZDliMWM1NDYzYjE0ZWJlIn19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"3","color":"white","italic":false}',minecraft:profile={id:[I;1984431880,-410301511,-1719200993,1331384566],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjhlYmFiNTdiNzYxNGJiMjJhMTE3YmU0M2U4NDhiY2QxNGRhZWNiNTBlOGY1ZDA5MjZlNDg2NGRmZjQ3MCJ9fX0="}]}] - - - # row 3 - - > - minecraft:player_head[minecraft:custom_name='{"text":"M","color":"white","italic":false}',minecraft:profile={id:[I;-1567507456,-388545841,-1923655550,-1846285374],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDljNDVhMjRhYWFiZjQ5ZTIxN2MxNTQ4MzIwNDg0OGE3MzU4MmFiYTdmYWUxMGVlMmM1N2JkYjc2NDgyZiJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"N","color":"white","italic":false}',minecraft:profile={id:[I;1134513528,-555924865,-1720466544,1817048361],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzViOGIzZDhjNzdkZmI4ZmJkMjQ5NWM4NDJlYWM5NGZmZmE2ZjU5M2JmMTVhMjU3NGQ4NTRkZmYzOTI4In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"O","color":"white","italic":false}',minecraft:profile={id:[I;1321491696,-1188608949,-2047085167,200991382],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDExZGUxY2FkYjJhZGU2MTE0OWU1ZGVkMWJkODg1ZWRmMGRmNjI1OTI1NWIzM2I1ODdhOTZmOTgzYjJhMSJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"P","color":"white","italic":false}',minecraft:profile={id:[I;1814173995,1526287623,-1452279461,-1635659421],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTBhNzk4OWI1ZDZlNjIxYTEyMWVlZGFlNmY0NzZkMzUxOTNjOTdjMWE3Y2I4ZWNkNDM2MjJhNDg1ZGMyZTkxMiJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"Q","color":"white","italic":false}',minecraft:profile={id:[I;75184246,-356302517,-1988617208,1071177606],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDM2MDlmMWZhZjgxZWQ0OWM1ODk0YWMxNGM5NGJhNTI5ODlmZGE0ZTFkMmE1MmZkOTQ1YTU1ZWQ3MTllZDQifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"R","color":"white","italic":false}',minecraft:profile={id:[I;-1695480630,-541374954,-1862151936,381858074],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTVjZWQ5OTMxYWNlMjNhZmMzNTEzNzEzNzliZjA1YzYzNWFkMTg2OTQzYmMxMzY0NzRlNGU1MTU2YzRjMzcifX19"}]}] - - - > - minecraft:player_head[minecraft:custom_name='{"text":"/","color":"white","italic":false}',minecraft:profile={id:[I;22998734,-863025503,-1395273983,141587210],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2Y5NWQ3YzFiYmYzYWZhMjg1ZDhkOTY3NTdiYjU1NzIyNTlhM2FlODU0ZjUzODlkYzUzMjA3Njk5ZDk0ZmQ4In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"0","color":"white","italic":false}',minecraft:profile={id:[I;-1517430014,645611810,-1194567057,-1090921724],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTVhMjI0ODA3NjkzOTc4ZWQ4MzQzNTVmOWU1MTQ1ZjljNTZlZjY4Y2Y2ZjJjOWUxNzM0YTQ2ZTI0NmFhZTEifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":".","color":"white","italic":false}',minecraft:profile={id:[I;907960704,-827570120,-1981432250,-79626620],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzMzYWEyNDkxNmM4ODY5NmVlNzFkYjdhYzhjZDMwNmFkNzMwOTZiNWI2ZmZkODY4ZTFjMzg0YjFkNjJjZmIzYyJ9fX0="}]}] - - - # row 4 - - > - minecraft:player_head[minecraft:custom_name='{"text":"S","color":"white","italic":false}',minecraft:profile={id:[I;-2106851793,947668183,-1663828944,1185292365],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2U0MWM2MDU3MmM1MzNlOTNjYTQyMTIyODkyOWU1NGQ2Yzg1NjUyOTQ1OTI0OWMyNWMzMmJhMzNhMWIxNTE3In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"T","color":"white","italic":false}',minecraft:profile={id:[I;146837491,-1779219252,-1918643999,857535593],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTU2MmU4YzFkNjZiMjFlNDU5YmU5YTI0ZTVjMDI3YTM0ZDI2OWJkY2U0ZmJlZTJmNzY3OGQyZDNlZTQ3MTgifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"U","color":"white","italic":false}',minecraft:profile={id:[I;-583573452,825050389,-1670321413,-1172696348],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjA3ZmJjMzM5ZmYyNDFhYzNkNjYxOWJjYjY4MjUzZGZjM2M5ODc4MmJhZjNmMWY0ZWZkYjk1NGY5YzI2In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"V","color":"white","italic":false}',minecraft:profile={id:[I;410144666,-1968484545,-1593891100,-1224420033],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2M5YTEzODYzOGZlZGI1MzRkNzk5Mjg4NzZiYWJhMjYxYzdhNjRiYTc5YzQyNGRjYmFmY2M5YmFjNzAxMGI4In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"W","color":"white","italic":false}',minecraft:profile={id:[I;545352292,1464026660,-1923219372,-1704716389],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjY5YWQxYTg4ZWQyYjA3NGUxMzAzYTEyOWY5NGU0YjcxMGNmM2U1YjRkOTk1MTYzNTY3ZjY4NzE5YzNkOTc5MiJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"X","color":"white","italic":false}',minecraft:profile={id:[I;867538028,550585967,-1915416160,-36867835],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE2Nzg3YmEzMjU2NGU3YzJmM2EwY2U2NDQ5OGVjYmIyM2I4OTg0NWU1YTY2YjVjZWM3NzM2ZjcyOWVkMzcifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"Y","color":"white","italic":false}',minecraft:profile={id:[I;1470022907,196036374,-1984291817,1606250044],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzUyZmIzODhlMzMyMTJhMjQ3OGI1ZTE1YTk2ZjI3YWNhNmM2MmFjNzE5ZTFlNWY4N2ExY2YwZGU3YjE1ZTkxOCJ9fX0="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":"Z","color":"white","italic":false}',minecraft:profile={id:[I;255475266,1141917862,-1656318151,779775527],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA1ODJiOWI1ZDk3OTc0YjExNDYxZDYzZWNlZDg1ZjQzOGEzZWVmNWRjMzI3OWY5YzQ3ZTFlMzhlYTU0YWU4ZCJ9fX0="}]}] - - null - - null - - - # row 5 - - null # capslock - - null - - > - minecraft:player_head[minecraft:custom_name='{"text":"<","color":"white","italic":false}',minecraft:profile={id:[I;566900106,196691009,-1677152513,-145415000],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZjOWYyYWE4ZTk3OTg3NDIxZTdmYWIyNDhhZmMyNDJjYmU1MWY5ZWRiZmE0NzFjYTZjMDE0OTRlZGVkYTcifX19"}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] - - > - minecraft:player_head[minecraft:custom_name='{"text":" ","color":"white","italic":false}',minecraft:profile={id:[I;-1748051773,1786594424,-1348733826,1615983447],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTZiNGI0MjMwYzhmYTI1NGJlNzUyNmEyYjI1M2RjMzUyYTUzYTVhOGVhZTZlZmI1MmVhMzRhOGY5YmQ5In19fQ=="}]}] - - null - - > - minecraft:player_head[minecraft:custom_name='{"text":"&","color":"white","italic":false}',minecraft:profile={id:[I;-1174836421,-15646697,-1328627511,-2027080362],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJmMTQzZTgxZWM4NzI1YmQyNjcyOTNmMmY5N2EzZGFlMTNiNmE4NDhlNjZhZjAxZjJhNTk0ZGUwYzAzYjY4In19fQ=="}]}] - capslock: - on: > - minecraft:player_head[minecraft:custom_name='{"text":"Caps On","color":"white","italic":false}',minecraft:profile={id:[I;-1359390673,1123042662,-2044311694,1161260194],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmE0ODUxYzg3OGJmNDJhMWNkYzAzYmMwNjcxZDExZTlkZDY5NzdlNzM4MTNhZmFmNTRjMjQzMjg5MjFiMSJ9fX0="}]}] - off: > - minecraft:player_head[minecraft:custom_name='{"text":"Caps Off","color":"white","italic":false}',minecraft:profile={id:[I;-1465327569,821513044,-1391332870,-1887948566],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWE4ZWY5MmVmYTE1NjY5ZGY0ODMzMmQxMThhMmY3MDU3NzJhMmEzZmNkMGZiODJhNjFmMjc3Yjg0OWEyYmQ2In19fQ=="}]}] - - overlay: - 1: > - minecraft:player_head[minecraft:custom_name='{"text":"+","color":"white","italic":false}',minecraft:profile={id:[I;-2132637750,1772571139,-2012138934,1183873465],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWUzOTVlNzVlMmViOGM0YjcyNDRkY2RiNzVjNTdhNmQ3YWRmMzc1NTNmMjFkNDRlZmM3YmQ3MTQxODQzNDVkIn19fQ=="}]}] - 7: > - minecraft:player_head[minecraft:custom_name='{"text":"(","color":"white","italic":false}',minecraft:profile={id:[I;-597560724,2045789624,-1102251303,-17375023],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA3MWNiMTc3ZDQ1OTdkNGY1MWE2NjM3NWVmOWIwMTQyY2Q2OGMzZTljNjRhZWJiNjJmMTZlM2MzOTAxNDJmIn19fQ=="}]}] - 8: > - minecraft:player_head[minecraft:custom_name='{"text":")","color":"white","italic":false}',minecraft:profile={id:[I;-640573698,-879341974,-1482675794,-695298676],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzNjNzJlZjBlOTQ0MmM1YjY3YTUwYTY5YjI5ZWUxMDRmODExZmFkYTZiZmVkZTJlY2RiM2I1YjU1NTAifX19"}]}] - 16: > - minecraft:player_head[minecraft:custom_name='{"text":"{","color":"white","italic":false}',minecraft:profile={id:[I;1578330289,-933738680,-1296307924,1987052884],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY5OTMyY2ZhZTc1ZDM4ZjdjNzFmN2Y5NTNkMThmNmI2MGZjYjg4NThkMWQ5YjQ5YTE1ZDc2NmJjY2IyNThmNiJ9fX0="}]}] - 17: > - minecraft:player_head[minecraft:custom_name='{"text":"}","color":"white","italic":false}',minecraft:profile={id:[I;1337656702,2129349883,-1929597657,972938975],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGJiOGIxMWQ2NWUwZDA2OGQzYTk0OWM0MWVmNGQxMmUxODNjZmFlZWE0NGZmYzY4ZWM0MzliNWQ5NzcxMjcifX19"}]}] - 25: > - minecraft:player_head[minecraft:custom_name='{"text":"[","color":"white","italic":false}',minecraft:profile={id:[I;1760752564,-519747449,-1754961888,242909979],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTM0YTlmYTlkMmNlNTY4YWUyYjIxZWRhMGNiMzM5NGZlNTJkNjc4M2I0ZmViYWFhOTFmMjg2ZmY5MzMyIn19fQ=="}]}] - 26: > - minecraft:player_head[minecraft:custom_name='{"text":"]","color":"white","italic":false}',minecraft:profile={id:[I;9839908,1100301440,-1709442586,1903746217],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTQ4YjY5ZWMxNTViMTg3Mzc2Yjg4YmMwMzg0ZDI1NTM4ZGRlZDlkYjgzOWVhYmI1OWU0NjE4ZWE0NiJ9fX0="}]}] - 31: > - minecraft:player_head[minecraft:custom_name='{"text":"*","color":"white","italic":false}',minecraft:profile={id:[I;262336475,-808826797,-2093637878,-504951991],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmYwZThlZmExY2QwNzI4Mjk3NDdhNjk3NzM3OTE2OTVmODBjZmFlOGJmYTg3MmZiMWIyOGEyMTFlZDAzMSJ9fX0="}]}] - 47: > - minecraft:player_head[minecraft:custom_name='{"text":">","color":"white","italic":false}',minecraft:profile={id:[I;1835665637,-508736383,-1261639685,-293116197],properties:[{name:"textures",value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzEwZTE0OWI2NTE2MzgyZTM2ZGQ2YzRjOTk3ZDg4OWQwNDZkMTNiNTQzM2Y1YWZlYjNiYTVmYjlkYWI0MmY5In19fQ=="}]}] -# DO NOT TOUCH THESE -version: 3 diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java index 1405b8bf9..5aefa84d7 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/MenuEventsTest.java @@ -10,40 +10,32 @@ import org.bukkit.inventory.InventoryView; import org.junit.Before; import org.junit.Test; -import us.talabrek.ultimateskyblock.menu.ConfigMenu; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.player.UltimateHolder; import us.talabrek.ultimateskyblock.player.UltimateHolder.MenuType; import java.util.UUID; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; public class MenuEventsTest { - private ConfigMenu fakeConfigMenu; private SkyBlockMenu fakeMenu; private MenuEvents menuEvents; @Before public void setUp() { - fakeConfigMenu = mock(ConfigMenu.class); fakeMenu = mock(SkyBlockMenu.class); - doNothing().when(fakeConfigMenu).onClick(any(InventoryClickEvent.class)); doNothing().when(fakeMenu).onClick(any(InventoryClickEvent.class)); - menuEvents = new MenuEvents(fakeMenu, fakeConfigMenu); - } - - @Test - public void testOnGuiClick_configMenu() { - UltimateHolder holder = new UltimateHolder(getFakePlayer(), "Config: config.yml (1/2)", MenuType.CONFIG); - InventoryClickEvent event = getEvent(holder); - - menuEvents.guiClick(event); - verify(fakeConfigMenu).onClick(event); - verify(fakeMenu, times(0)).onClick(any()); + menuEvents = new MenuEvents(fakeMenu); } @Test @@ -52,7 +44,6 @@ public void testOnGuiClick_regularMenu() { InventoryClickEvent event = getEvent(holder); menuEvents.guiClick(event); - verify(fakeConfigMenu, times(0)).onClick(any()); verify(fakeMenu).onClick(event); } @@ -62,7 +53,6 @@ public void testOnGuiClick_noUltimateHolder() { InventoryClickEvent event = getEvent(holder); menuEvents.guiClick(event); - verify(fakeConfigMenu, times(0)).onClick(any()); verify(fakeMenu, times(0)).onClick(event); } From 1c04216ce855096b0e9dc8041beac229252cc602 Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 21:50:22 +0100 Subject: [PATCH 155/190] Make inner classes static to eliminate unneeded reference to outer class --- .../ultimateskyblock/command/admin/AdminChallengeCommand.java | 2 +- .../talabrek/ultimateskyblock/command/admin/ChunkCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java index 7919d7155..510d9f5f6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java @@ -117,7 +117,7 @@ public boolean execute(CommandSender sender, String alias, Map d return super.execute(sender, alias, data, args); } - private abstract class ChallengeCommand extends AbstractCommand { + private abstract static class ChallengeCommand extends AbstractCommand { public ChallengeCommand(String name, String permission, String description) { super(name, permission, "challenge", description); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java index 6109409b0..f5e58b101 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/ChunkCommand.java @@ -47,7 +47,7 @@ void doChunkCommand(Player player, Chunk chunk) { }); } - public abstract class RequireChunkCommand extends AbstractCommand { + public abstract static class RequireChunkCommand extends AbstractCommand { public RequireChunkCommand(String name, String description) { super(name, null, "?x ?z ?r", description); } From 158903169a27ebcb6450c5457125fde9c9b42de3 Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 21:50:45 +0100 Subject: [PATCH 156/190] Fix math precision issues --- .../talabrek/ultimateskyblock/challenge/ChallengeLogic.java | 6 +++--- .../ultimateskyblock/command/admin/OrphanCommand.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java index 8c29a2daa..1617393e0 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeLogic.java @@ -378,10 +378,10 @@ private boolean giveReward(Player player, Challenge challenge) { player.sendMessage(tr("\u00a7eItem reward(s): \u00a7f{0}", reward.getRewardText())); player.sendMessage(tr("\u00a7eExp reward: \u00a7f{0,number,#.#}", reward.getXpReward())); if (defaults.enableEconomyPlugin) { - float rewBonus = 1; + double rewBonus = 1; Perk perk = perkLogic.getPerk(player); - rewBonus += perk.getRewBonus(); - float currencyReward = reward.getCurrencyReward() * rewBonus; + rewBonus +=perk.getRewBonus(); + double currencyReward = reward.getCurrencyReward() * rewBonus; double percentage = (rewBonus - 1.0) * 100.0; hookManager.getEconomyHook().ifPresent((hook) -> { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java index 118c4b741..685cc04c1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/OrphanCommand.java @@ -45,7 +45,7 @@ public boolean execute(CommandSender sender, String alias, Map d sender.sendMessage(I18nUtil.tr("\u00a7eNo orphans currently registered.")); } else { int pageSize = 50; - int pages = (int)Math.ceil(orphans.size() / pageSize); + int pages = (int) Math.ceil((double) orphans.size() / pageSize); int page = args.length > 0 && args[0].matches("[0-9]+") ? Integer.parseInt(args[0], 10) : 1; if (page < 1) page = 1; if (page > pages) page = pages; From af22c1da467f90ebc7d1ffde634fef1157d9948b Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 22:00:50 +0100 Subject: [PATCH 157/190] Performance improvements --- .../command/admin/PerkCommand.java | 8 ++-- .../handler/placeholder/TextPlaceholder.java | 2 +- .../ultimateskyblock/island/LimitLogic.java | 6 +-- .../ultimateskyblock/player/PlayerInfo.java | 4 +- .../handler/WorldEditHandlerTest.java | 38 ++++++------------- .../placeholder/TextPlaceholderTest.java | 6 +-- 6 files changed, 22 insertions(+), 42 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java index db22a09d0..101b8e88d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/PerkCommand.java @@ -25,9 +25,9 @@ public PerkCommand(@NotNull uSkyBlock plugin) { public boolean execute(CommandSender sender, String alias, Map data, String... args) { StringBuilder sb = new StringBuilder(); for (Map.Entry entry : plugin.getPerkLogic().getPerkMap().entrySet()) { - sb.append("\u00a79" + entry.getKey() + ":\n"); + sb.append("\u00a79").append(entry.getKey()).append(":\n"); String value = (entry.getValue().toString().replaceAll("\n", "\n ")).trim(); - sb.append(" " + value + "\n"); + sb.append(" ").append(value).append("\n"); } sender.sendMessage(sb.toString().split("\n")); return true; @@ -41,9 +41,9 @@ public boolean execute(CommandSender sender, String alias, Map d if (player != null) { StringBuilder sb = new StringBuilder(); Perk perk = plugin.getPerkLogic().getPerk(player); - sb.append("\u00a79" + player.getName() + ":\n"); + sb.append("\u00a79").append(player.getName()).append(":\n"); String value = (perk.toString().replaceAll("\n", "\n ")).trim(); - sb.append(" " + value + "\n"); + sb.append(" ").append(value).append("\n"); sender.sendMessage(sb.toString().split("\n")); return true; } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java index ce41921de..7c139bce5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java @@ -45,7 +45,7 @@ private String replacePlaceholdersInternal(Player player, String message) { sb.append(message.substring(matcher.start(), matcher.end())); } } else { - sb.append("{" + placeholderString + "}"); + sb.append("{").append(placeholderString).append("}"); } ix = matcher.end(); } while (matcher.find()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index f6e384877..1246cbf14 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -151,7 +151,7 @@ public String getSummary(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo) } int cnt = count.containsKey(key) ? count.get(key) : 0; int max = creatureMax.get(key); - sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", tr(key.name()), cnt >= max ? tr("\u00a7c{0}", cnt) : cnt, max) + "\n"); + sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", tr(key.name()), cnt >= max ? tr("\u00a7c{0}", cnt) : cnt, max)).append("\n"); } Map blockLimits = blockLimitLogic.getLimits(); for (Map.Entry entry : blockLimits.entrySet()) { @@ -160,12 +160,12 @@ public String getSummary(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo) sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", ItemStackUtil.getItemName(new ItemStack(entry.getKey())), blockCount >= entry.getValue() ? tr("\u00a7c{0}", blockCount) : blockCount, - entry.getValue()) + "\n"); + entry.getValue())).append("\n"); } else { sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", ItemStackUtil.getItemName(new ItemStack(entry.getKey())), tr("\u00a7c{0}", "?"), - entry.getValue()) + "\n"); + entry.getValue())).append("\n"); } } return sb.toString().trim(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java index 9c5d3eb89..9b21f9089 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/player/PlayerInfo.java @@ -312,9 +312,7 @@ public void saveToFile() { @Override public Collection getChallenges() { - Collection copy = new ArrayList<>(); - copy.addAll(uSkyBlock.getInstance().getChallengeLogic().getChallenges(this)); - return copy; + return new ArrayList<>(uSkyBlock.getInstance().getChallengeLogic().getChallenges(this)); } @Override diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java index 7ca17c512..f91874621 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/WorldEditHandlerTest.java @@ -9,7 +9,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Set; import static org.hamcrest.CoreMatchers.is; @@ -36,10 +35,9 @@ public class WorldEditHandlerTest { * -16 -1 0 15 * X * - * @throws Exception */ @Test - public void testGetBorderRegionsAligned() throws Exception { + public void testGetBorderRegionsAligned() { // A Region region = new CuboidRegion(BlockVector3.at(0,0,0), BlockVector3.at(15, 15, 15)); Set borderRegions = WorldEditHandler.getBorderRegions(region); @@ -65,9 +63,7 @@ public void testGetBorderRegionsAligned() throws Exception { public void testBorderXPosMax() { Region region = new CuboidRegion(BlockVector3.at(0,0,0), BlockVector3.at(16, 15, 15)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expected = new HashSet<>(Arrays.asList( - new CuboidRegion(BlockVector3.at(16,0,0), BlockVector3.at(16,15,15)) - )); + Set expected = Set.of(new CuboidRegion(BlockVector3.at(16,0,0), BlockVector3.at(16,15,15))); verifySame(borderRegions, expected); } @@ -75,9 +71,7 @@ public void testBorderXPosMax() { public void testBorderXPosMin() { Region region = new CuboidRegion(BlockVector3.at(15,0,0), BlockVector3.at(31, 15, 15)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expected = new HashSet<>(Arrays.asList( - new CuboidRegion(BlockVector3.at(15,0,0), BlockVector3.at(15,15,15)) - )); + Set expected = Set.of(new CuboidRegion(BlockVector3.at(15,0,0), BlockVector3.at(15,15,15))); verifySame(borderRegions, expected); } @@ -85,9 +79,7 @@ public void testBorderXPosMin() { public void testBorderXNegMax() { Region region = new CuboidRegion(BlockVector3.at(-16,0,-16), BlockVector3.at(0, 15, -1)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expected = new HashSet<>(Arrays.asList( - new CuboidRegion(BlockVector3.at(0,0,-16), BlockVector3.at(0,15,-1)) - )); + Set expected = Set.of(new CuboidRegion(BlockVector3.at(0,0,-16), BlockVector3.at(0,15,-1))); verifySame(borderRegions, expected); } @@ -95,9 +87,7 @@ public void testBorderXNegMax() { public void testBorderXNegMin() { Region region = new CuboidRegion(BlockVector3.at(-17,0,-16), BlockVector3.at(-1, 15, -1)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expected = new HashSet<>(Arrays.asList( - new CuboidRegion(BlockVector3.at(-17,0,-16), BlockVector3.at(-17,15,-1)) - )); + Set expected = Set.of(new CuboidRegion(BlockVector3.at(-17,0,-16), BlockVector3.at(-17,15,-1))); verifySame(borderRegions, expected); } @@ -105,9 +95,7 @@ public void testBorderXNegMin() { public void testBorderZPos() { Region region = new CuboidRegion(BlockVector3.at(0,0,0), BlockVector3.at(15, 15, 16)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expected = new HashSet<>(Arrays.asList( - new CuboidRegion(BlockVector3.at(0,0,16), BlockVector3.at(15,15,16)) - )); + Set expected = Set.of(new CuboidRegion(BlockVector3.at(0,0,16), BlockVector3.at(15,15,16))); verifySame(borderRegions, expected); } @@ -184,21 +172,20 @@ private void verifySame(Set borderRegions, Set expected) { * A = 1, 1 * B = 32, 32 * - * @throws Exception */ @Test - public void testGetBorderRegionsUnalignedPos() throws Exception { + public void testGetBorderRegionsUnalignedPos() { Region region = new CuboidRegion(BlockVector3.at(1,0,1), BlockVector3.at(32, 15, 32)); Set borderRegions = WorldEditHandler.getBorderRegions(region); - Set expectedBorder = new HashSet<>(Arrays.asList( + Set expectedBorder = Set.of( new CuboidRegion(BlockVector3.at(1,0,1), BlockVector3.at(15,15,32)), new CuboidRegion(BlockVector3.at(32,0,1), BlockVector3.at(32,15,32)), new CuboidRegion(BlockVector3.at(16,0,1), BlockVector3.at(31,15,15)), new CuboidRegion(BlockVector3.at(16,0,32), BlockVector3.at(31,15,32)) - )); - Set expectedInner = new HashSet<>(Arrays.asList( + ); + Set expectedInner = Set.of( BlockVector2.at(1, 1) - )); + ); verifySame(borderRegions, expectedBorder); Set innerChunks = WorldEditHandler.getInnerChunks(region); assertThat(innerChunks, is(expectedInner)); @@ -242,10 +229,9 @@ public void testGetBorderRegionsAligned4Quadrants() throws Exception { * A = -31, -31 * B = 32, 32 * - * @throws Exception */ @Test - public void testGetBorderRegionsUnaligned4Quadrants() throws Exception { + public void testGetBorderRegionsUnaligned4Quadrants() { Region region = new CuboidRegion(BlockVector3.at(-31,0,-31), BlockVector3.at(32, 15, 32)); Set borderRegions = WorldEditHandler.getBorderRegions(region); Set expectedBorder = new HashSet<>(Arrays.asList( diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java index ab8ea2150..0c2629b84 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java @@ -4,8 +4,6 @@ import org.bukkit.entity.Player; import org.junit.Test; -import java.util.Arrays; -import java.util.HashSet; import java.util.Set; import static org.hamcrest.CoreMatchers.nullValue; @@ -22,7 +20,7 @@ public void replacePlaceholders() throws Exception { placeholder.registerPlaceholder(null, new PlaceholderAPI.PlaceholderReplacer() { @Override public Set getPlaceholders() { - return new HashSet<>(Arrays.asList("usb_replaceme")); + return Set.of("usb_replaceme"); } @Override @@ -35,6 +33,4 @@ public String replace(OfflinePlayer offlinePlayer, Player player, String placeho assertThat(placeholder.replacePlaceholders(null, "Hi {usb_island_level}"), is("Hi {usb_island_level}")); assertThat(placeholder.replacePlaceholders(null, "Hi {usb_replaceme} please"), is("Hi replaced string please")); } - - } From c39dff2ebc5d25165448a5d42b3e227fcf16b16b Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 22:05:01 +0100 Subject: [PATCH 158/190] Remove redundant methods --- .../java/dk/lockfuglsang/minecraft/util/FormatUtil.java | 9 --------- .../dk/lockfuglsang/minecraft/util/ItemStackUtil.java | 2 +- .../talabrek/ultimateskyblock/challenge/Challenge.java | 3 +-- .../command/admin/AdminChallengeCommand.java | 2 +- .../us/talabrek/ultimateskyblock/util/GuiItemUtil.java | 9 --------- 5 files changed, 3 insertions(+), 22 deletions(-) diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java index d56334cdc..a980bccb8 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/FormatUtil.java @@ -136,15 +136,6 @@ private static String getFormat(String s) { return format; } - public static String join(List list, String separator) { - String joined = ""; - for (String s : list) { - joined += s + separator; - } - joined = !list.isEmpty() ? joined.substring(0, joined.length() - separator.length()) : joined; - return joined; - } - public static List prefix(List list, String prefix) { List prefixed = new ArrayList<>(list.size()); for (String s : list) { diff --git a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java index 03b5a554b..62c564467 100644 --- a/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java +++ b/bukkit-utils/src/main/java/dk/lockfuglsang/minecraft/util/ItemStackUtil.java @@ -173,7 +173,7 @@ public static String asShortString(List items) { for (ItemStack item : items) { shorts.add(asShortString(item)); } - return "[" + FormatUtil.join(shorts, ", ") + "]"; + return "[" + String.join(", ", shorts) + "]"; } public static String asShortString(ItemStack item) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java index 9d5b7b5c9..490c63d6d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/Challenge.java @@ -18,7 +18,6 @@ import java.util.stream.Collectors; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; -import static dk.lockfuglsang.minecraft.util.FormatUtil.join; import static dk.lockfuglsang.minecraft.util.FormatUtil.prefix; import static dk.lockfuglsang.minecraft.util.FormatUtil.wordWrap; @@ -249,7 +248,7 @@ public int getOffset() { } private List wrappedDetails(List details) { - return wordWrap(join(details, ", "), MAX_LINE); + return wordWrap(String.join(", ", details), MAX_LINE); } public ItemStack getDisplayItem() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java index 510d9f5f6..7617c5caa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/AdminChallengeCommand.java @@ -151,7 +151,7 @@ public RankCommand(String name, String permission, String description) { public boolean execute(CommandSender sender, String alias, Map data, String... args) { PlayerInfo playerInfo = (PlayerInfo) data.get("playerInfo"); if (playerInfo != null && args.length > 0) { - String rankName = FormatUtil.join(Arrays.asList(args), " "); + String rankName = String.join(" ", args); List challenges = plugin.getChallengeLogic().getChallengesForRank(rankName); if (challenges == null || challenges.isEmpty()) { sender.sendMessage(I18nUtil.tr("\u00a74No rank named {0} was found!", rankName)); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java index 933e3aabb..dd65039a1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/GuiItemUtil.java @@ -1,7 +1,6 @@ package us.talabrek.ultimateskyblock.util; import dk.lockfuglsang.minecraft.util.FormatUtil; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -13,14 +12,6 @@ private GuiItemUtil() { // Uninstantiable static utility class } - // TODO: Replace calls to this specific method with a more general one - public static ItemStack createItemFromComponentString(String components) { - if (components == null) { - return null; - } - return Bukkit.getItemFactory().createItemStack(components); - } - public static ItemStack createGuiDisplayItem(String material, String name) { return createGuiDisplayItem(material, name, null); } From 827a78a347546d8bc53eb963abfa9421369a9cff Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 22:06:13 +0100 Subject: [PATCH 159/190] Remove redundant chunk comparator --- .../handler/ChunkComparator.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ChunkComparator.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ChunkComparator.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ChunkComparator.java deleted file mode 100644 index aede1edb0..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/ChunkComparator.java +++ /dev/null @@ -1,25 +0,0 @@ -package us.talabrek.ultimateskyblock.handler; - -import com.sk89q.worldedit.math.BlockVector2; - -import java.util.Comparator; - -public class ChunkComparator implements Comparator { - private BlockVector2 origin; - - public ChunkComparator(BlockVector2 origin) { - this.origin = origin; - } - - @Override - public int compare(BlockVector2 o1, BlockVector2 o2) { - int cmp = (int) Math.round(origin.distanceSq(o1) - origin.distanceSq(o2)); - if (cmp == 0) { - cmp = o1.getBlockX() - o2.getBlockX(); - } - if (cmp == 0) { - cmp = o1.getBlockZ() - o2.getBlockZ(); - } - return cmp; - } -} From 1563fbc8ff9acd49f3d1d1b462d5aa8900d8ac54 Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 13 Feb 2025 22:11:55 +0100 Subject: [PATCH 160/190] Properly cleanup closeable resources --- .../us/talabrek/ultimateskyblock/SkyUpdateChecker.java | 6 ++---- .../handler/asyncworldedit/FAWEAdaptor.java | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java index 9e2e8d350..d7fc3af39 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/SkyUpdateChecker.java @@ -5,7 +5,6 @@ import com.google.inject.Inject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClients; @@ -83,9 +82,8 @@ public boolean isUpdateAvailable() { public CompletableFuture fetchLatestVersion(URI uri) { CompletableFuture future = new CompletableFuture<>(); future.completeAsync(() -> { - try { - String userAgent = "uSkyBlock-Plugin/v" + getCurrentVersion() + " (www.uskyblock.ovh)"; - HttpClient httpclient = HttpClients.custom().setUserAgent(userAgent).build(); + String userAgent = "uSkyBlock-Plugin/v" + getCurrentVersion() + " (www.uskyblock.ovh)"; + try (var httpclient = HttpClients.custom().setUserAgent(userAgent).build()) { int CONNECTION_TIMEOUT_MS = 10 * 1000; // Timeout in millis. RequestConfig requestConfig = RequestConfig.custom() diff --git a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java index 3ed2d1622..fb495b684 100644 --- a/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java +++ b/uSkyBlock-FAWE/src/main/java/us/talabrek/ultimateskyblock/handler/asyncworldedit/FAWEAdaptor.java @@ -56,10 +56,8 @@ public void loadIslandSchematic(final File file, final Location origin, final Pl BlockVector3 to = BlockVector3.at(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); EditSession editSession = getEditSession(playerPerk, origin); - try { - format - .load(file) - .paste(editSession, to, false); + try(var schematic = format.load(file)) { + schematic.paste(editSession, to, false); editSession.flushQueue(); } catch (IOException ex) { log.log(Level.INFO, "Unable to paste schematic " + file, ex); @@ -79,8 +77,7 @@ public EditSession createEditSession(World bukkitWorld, int maxBlocks) { public void regenerate(final Region region, final Runnable onCompletion) { // NOTE: Running this asynchronous MIGHT be a bit dangereous! Since pasting could interfere scheduler.async(() -> { - try { - EditSession editSession = createEditSession(region.getWorld(), -1); + try(var editSession = createEditSession(region.getWorld(), -1)) { editSession.regenerate(region); editSession.flushQueue(); } finally { From da1c604fd200aa7b5fd621921758bb9d732cd38c Mon Sep 17 00:00:00 2001 From: minoneer Date: Mon, 17 Feb 2025 22:32:23 +0100 Subject: [PATCH 161/190] Enforce initialization order of I18nUtil, make it safe for multi-threading --- .../command/BaseCommandExecutorTest.java | 4 ++ .../command/CompositeCommandTest.java | 4 ++ .../lockfuglsang/minecraft/po/I18nUtil.java | 64 ++++++++++++------- .../minecraft/po/I18nUtilTest.java | 4 +- .../talabrek/ultimateskyblock/Settings.java | 1 - .../bootstrap/SkyblockApp.java | 2 - .../command/admin/LanguageCommand.java | 2 +- .../talabrek/ultimateskyblock/uSkyBlock.java | 3 +- .../challenge/ChallengeFormatTest.java | 4 ++ .../ultimateskyblock/chat/ChatEventsTest.java | 4 ++ .../event/GriefEventsTest.java | 3 + 11 files changed, 63 insertions(+), 32 deletions(-) diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java index e502fe5a9..fe211a7d5 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/BaseCommandExecutorTest.java @@ -1,5 +1,6 @@ package dk.lockfuglsang.minecraft.command; +import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; import org.junit.BeforeClass; import org.junit.Test; @@ -7,7 +8,9 @@ import org.mockito.Mockito; import org.mockito.stubbing.Answer; +import java.io.File; import java.util.Arrays; +import java.util.Locale; import java.util.Map; import static org.hamcrest.CoreMatchers.is; @@ -22,6 +25,7 @@ public class BaseCommandExecutorTest { @BeforeClass public static void setUp() { + I18nUtil.initialize(new File("."), Locale.ENGLISH); mycmd = new BaseCommandExecutor("mycmd", "myplugin.perm.mycmd", "main myplugin command"); mycmd.add(new AbstractCommand("hello|h", "myplugin.perm.hello", "say hello to the player") { @Override diff --git a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java index 6fb59e129..d58da4262 100644 --- a/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java +++ b/bukkit-utils/src/test/java/dk/lockfuglsang/minecraft/command/CompositeCommandTest.java @@ -1,5 +1,6 @@ package dk.lockfuglsang.minecraft.command; +import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.hamcrest.Matchers; @@ -7,9 +8,11 @@ import org.junit.Test; import org.mockito.stubbing.Answer; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -25,6 +28,7 @@ public class CompositeCommandTest { @BeforeClass public static void setupAll() { + I18nUtil.initialize(new File("."), Locale.ENGLISH); executor = new BaseCommandExecutor("plugin", "plugin", null, "does stuff", ownerUUID); CompositeCommand sut = new CompositeCommand("admin", "admin.admin.superadmin", null, "super important admin command", adminUUID) { @Override diff --git a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java index cdc138a3a..ce9f45487 100644 --- a/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java +++ b/po-utils/src/main/java/dk/lockfuglsang/minecraft/po/I18nUtil.java @@ -24,9 +24,13 @@ public enum I18nUtil { ; private static final Logger log = Logger.getLogger(I18nUtil.class.getName()); - private static I18n i18n; - private static Locale locale; - private static File dataFolder = new File("."); + + // Dedicated lock for synchronizing modifications + private static final Object LOCK = new Object(); + + private static volatile I18n i18n; + private static volatile Locale locale; + private static volatile File dataFolder; /** * Translates the given {@link String} to the configured language. Returns the given String if no translation is @@ -56,7 +60,7 @@ public static String tr(@Nullable String s, @Nullable Object... args) { * @param key String to mark. * @return Input String. */ - @Contract("null -> null") + @Contract(value = "null -> null", pure = true) public static String marktr(@Nullable String key) { return key; } @@ -82,14 +86,30 @@ public static String pre(@Nullable String s, @Nullable Object... args) { * @return I18n instance for the configured locale. */ public static I18n getI18n() { - if (i18n == null) { + I18n result = i18n; + if (result == null) { + throw new IllegalStateException("I18nUtil not initialized!"); + } + return result; + } + + /** + * Initializes the I18nUtil. This method is called whenever the plugin loads or reloads. + * Thread safety is ensured by synchronizing modifications of shared fields. + * + * @param folder The plugin's data folder. + * @param loc The desired Locale. If null, Locale.ENGLISH is used. + */ + public static void initialize(@NotNull File folder, @Nullable Locale loc) { + synchronized (LOCK) { + dataFolder = folder; + locale = loc; i18n = new I18n(getLocale()); } - return i18n; } /** - * Returns the configured {@link Locale} or the default if unset. + * Returns the configured {@link Locale} or the default (Locale.ENGLISH) if unset. * @return Configured Locale. */ @NotNull @@ -99,28 +119,24 @@ public static Locale getLocale() { /** * Sets the {@link Locale}. Resets to the default locale if NULL is given. - * @param locale Locale to set. + * The I18n cache is cleared so that translations are reloaded. + * + * @param loc Locale to set. */ - public static void setLocale(@Nullable Locale locale) { - I18nUtil.locale = locale; - clearCache(); - } - - /** - * Sets the datafolder that is used to look for .po files. - * @param folder Location of the datafolder. - */ - public static void setDataFolder(@NotNull File folder) { - dataFolder = folder; - clearCache(); + public static void setLocale(@Nullable Locale loc) { + synchronized (LOCK) { + locale = loc; + clearCache(); + } } /** - * Clears the I18n cache, forces a reload of the .po files the next time that {@link I18nUtil#getLocale()} is - * accessed. + * Clears the I18n cache, forcing a reload of the .po files the next time that {@link I18nUtil#getLocale()} is accessed. */ public static void clearCache() { - i18n = null; + synchronized (LOCK) { + i18n = new I18n(getLocale()); + } } /** @@ -128,7 +144,7 @@ public static void clearCache() { * @param lang Language code.. * @return Locale based on the given string. */ - @Contract("null -> null") + @Contract(value = "null -> null", pure = true) public static Locale getLocale(@Nullable String lang) { if (lang != null) { String[] parts = lang.split("[-_]"); diff --git a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java index d5416f68d..e0953aef9 100644 --- a/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java +++ b/po-utils/src/test/java/dk/lockfuglsang/minecraft/po/I18nUtilTest.java @@ -13,9 +13,9 @@ public class I18nUtilTest { @Before - public void setUp() throws Exception { + public void setUp() { URL dataFolderUrl = getClass().getClassLoader().getResource(""); - I18nUtil.setDataFolder(new File(dataFolderUrl.getFile())); + I18nUtil.initialize(new File(dataFolderUrl.getFile()), Locale.ENGLISH); } @Test diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index 970b7b43d..e5d0edb59 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -147,7 +147,6 @@ public static boolean loadPluginConfig(FileConfiguration config) { Locale loc = I18nUtil.getLocale(config.getString("language", null)); if (loc != null) { locale = loc; - I18nUtil.setLocale(locale); } nether_enabled = config.getBoolean("nether.enabled", false); if (nether_enabled && !WorldEditHandler.isOuterPossible()) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java index 2ec71e06a..2d40d12b7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java @@ -43,7 +43,5 @@ public void shutdown(uSkyBlock plugin) { Bukkit.getScheduler().cancelTasks(plugin); listeners.unregisterListeners(plugin); services.shutdown(plugin); - - I18nUtil.clearCache(); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java index a4addd89b..dbac57823 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/admin/LanguageCommand.java @@ -35,7 +35,7 @@ public boolean execute(CommandSender sender, String alias, Map d if (args.length == 1) { Locale loc = I18nUtil.getLocale(args[0]); Settings.locale = loc; - I18nUtil.clearCache(); + I18nUtil.setLocale(loc); plugin.getConfig().set("language", args[0]); plugin.saveConfig(); plugin.reloadConfig(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index 0e7e1be4c..fcc26662b 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -662,11 +662,10 @@ private void reloadLegacyStuff() { FileUtil.setDataFolder(getDataFolder()); FileUtil.setAlwaysOverwrite("levelConfig.yml"); Settings.loadPluginConfig(new PluginConfig().getYamlConfig()); - I18nUtil.setDataFolder(getDataFolder()); + I18nUtil.initialize(getDataFolder(), Settings.locale); saveConfig(); // Update all of the loaded configs. FileUtil.reload(); - I18nUtil.getI18n(); } public IslandLogic getIslandLogic() { diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java index 1996eee2e..6657aae30 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/challenge/ChallengeFormatTest.java @@ -1,12 +1,15 @@ package us.talabrek.ultimateskyblock.challenge; +import dk.lockfuglsang.minecraft.po.I18nUtil; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.mockito.hamcrest.MockitoHamcrest; import us.talabrek.ultimateskyblock.player.PlayerInfo; +import java.io.File; import java.util.Arrays; +import java.util.Locale; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; @@ -20,6 +23,7 @@ public class ChallengeFormatTest { @BeforeClass public static void beforeAll() { + I18nUtil.initialize(new File("."), Locale.ENGLISH); playerInfo = Mockito.mock(PlayerInfo.class); challengeLogic = Mockito.mock(ChallengeLogic.class); diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java index 96f61342a..2e726c2fa 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/chat/ChatEventsTest.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.chat; +import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Server; import org.bukkit.entity.Player; import org.bukkit.event.player.AsyncPlayerChatEvent; @@ -11,7 +12,9 @@ import us.talabrek.ultimateskyblock.api.event.IslandChatEvent; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.io.File; import java.util.HashSet; +import java.util.Locale; import java.util.Set; import java.util.UUID; @@ -25,6 +28,7 @@ public class ChatEventsTest { @Before public void setUp() { + I18nUtil.initialize(new File("."), Locale.ENGLISH); uSkyBlock fakePlugin = mock(uSkyBlock.class); Server fakeServer = mock(Server.class); when(fakePlugin.getServer()).thenReturn(fakeServer); diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java index fac131725..42fef2fb7 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/event/GriefEventsTest.java @@ -4,8 +4,10 @@ import org.hamcrest.CoreMatchers; import org.junit.Test; +import java.io.File; import java.text.MessageFormat; import java.text.ParseException; +import java.util.Locale; import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -14,6 +16,7 @@ public class GriefEventsTest { @Test public void testWitherNaming() throws ParseException { + I18nUtil.initialize(new File("."), Locale.ENGLISH); String name = I18nUtil.tr("{0}''s Wither", "R4zorax"); assertThat(name, is("R4zorax's Wither")); From e2aea54c94a2f07addb7d5dca8fea396e57c3cb9 Mon Sep 17 00:00:00 2001 From: minoneer Date: Thu, 20 Feb 2025 12:13:28 +0100 Subject: [PATCH 162/190] Make placeholder object oriented --- .../ultimateskyblock/bootstrap/Services.java | 9 +- .../bootstrap/SkyblockApp.java | 8 +- .../bootstrap/SkyblockModule.java | 6 + .../ultimateskyblock/chat/ChatLogic.java | 11 +- .../handler/placeholder/ChatPlaceholder.java | 26 --- .../placeholder/ChatReplaceListener.java | 27 +++ .../placeholder/MVdWPlaceholderAPI.java | 45 ++-- .../placeholder/MvdwPlacehoderProvider.java | 19 ++ .../handler/placeholder/PlaceholderAPI.java | 19 +- .../placeholder/PlaceholderHandler.java | 65 ++---- .../placeholder/PlaceholderModule.java | 52 +++++ .../placeholder/PlaceholderReplacerImpl.java | 209 ++++++++---------- .../placeholder/ServerCommandPlaceholder.java | 28 --- .../ServerCommandReplaceListener.java | 29 +++ .../handler/placeholder/TextPlaceholder.java | 30 ++- .../placeholder/TextPlaceholderTest.java | 9 +- 16 files changed, 309 insertions(+), 283 deletions(-) delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatPlaceholder.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatReplaceListener.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MvdwPlacehoderProvider.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderModule.java delete mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandPlaceholder.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandReplaceListener.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java index abd45d4cf..fe4fbf2a6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/Services.java @@ -10,6 +10,7 @@ import us.talabrek.ultimateskyblock.command.admin.DebugCommand; import us.talabrek.ultimateskyblock.handler.AsyncWorldEditHandler; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; +import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderModule; import us.talabrek.ultimateskyblock.hook.HookManager; import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.island.level.AutoIslandLevelRefresh; @@ -29,6 +30,7 @@ public class Services { private final MetricsManager metricsManager; private final HookManager hookManager; private final AutoIslandLevelRefresh autoIslandLevelRefresh; + private final PlaceholderModule placeholderModule; @Inject public Services( @@ -40,7 +42,8 @@ public Services( @NotNull PlayerDB playerDB, @NotNull MetricsManager metricsManager, @NotNull HookManager hookManager, - @NotNull AutoIslandLevelRefresh autoIslandLevelRefresh + @NotNull AutoIslandLevelRefresh autoIslandLevelRefresh, + @NotNull PlaceholderModule placeholderModule ) { this.animationHandler = animationHandler; this.challengeLogic = challengeLogic; @@ -51,11 +54,13 @@ public Services( this.metricsManager = metricsManager; this.hookManager = hookManager; this.autoIslandLevelRefresh = autoIslandLevelRefresh; + this.placeholderModule = placeholderModule; } - public void startup() { + public void startup(uSkyBlock plugin) { metricsManager.setup(); autoIslandLevelRefresh.startup(); + placeholderModule.startup(plugin); } public void delayedEnable(uSkyBlock plugin) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java index 2d40d12b7..198c13be9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockApp.java @@ -2,10 +2,8 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import dk.lockfuglsang.minecraft.po.I18nUtil; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; -import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderHandler; import us.talabrek.ultimateskyblock.uSkyBlock; @Singleton @@ -24,7 +22,7 @@ public SkyblockApp(@NotNull Services services, @NotNull Commands commands, @NotN public void startup(uSkyBlock plugin) { - services.startup(); + services.startup(plugin); } public void delayedEnable(uSkyBlock plugin) { @@ -33,13 +31,9 @@ public void delayedEnable(uSkyBlock plugin) { // do these really have to be delayed? commands.registerCommands(plugin); listeners.registerListeners(plugin); - - // TODO: make this object oriented - PlaceholderHandler.register(plugin); } public void shutdown(uSkyBlock plugin) { - PlaceholderHandler.unregister(plugin); Bukkit.getScheduler().cancelTasks(plugin); listeners.unregisterListeners(plugin); services.shutdown(plugin); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java index a7236c8dd..0160f6cc6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/bootstrap/SkyblockModule.java @@ -10,6 +10,10 @@ import us.talabrek.ultimateskyblock.PluginConfig; import us.talabrek.ultimateskyblock.SkyUpdateChecker; import us.talabrek.ultimateskyblock.api.plugin.UpdateChecker; +import us.talabrek.ultimateskyblock.handler.placeholder.MVdWPlaceholderAPI; +import us.talabrek.ultimateskyblock.handler.placeholder.MvdwPlacehoderProvider; +import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderAPI; +import us.talabrek.ultimateskyblock.handler.placeholder.PlaceholderReplacerImpl; import us.talabrek.ultimateskyblock.island.level.ChunkSnapshotLevelLogic; import us.talabrek.ultimateskyblock.island.level.LevelLogic; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -40,6 +44,8 @@ protected void configure() { bind(LevelLogic.class).to(ChunkSnapshotLevelLogic.class); bind(UpdateChecker.class).to(SkyUpdateChecker.class); bind(Clock.class).toInstance(Clock.systemUTC()); + bind(PlaceholderAPI.PlaceholderReplacer.class).to(PlaceholderReplacerImpl.class); + bind(MVdWPlaceholderAPI.class).toProvider(MvdwPlacehoderProvider.class); } @Provides diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java index 10f48b0b5..08af01c35 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/chat/ChatLogic.java @@ -38,13 +38,20 @@ public class ChatLogic { ); private final uSkyBlock plugin; private final WorldManager worldManager; + private final PlaceholderHandler placeholderHandler; private final Map formats = new EnumMap<>(Type.class); private final Map toggled = new HashMap<>(); @Inject - public ChatLogic(@NotNull uSkyBlock plugin, @NotNull PluginConfig config, @NotNull WorldManager worldManager) { + public ChatLogic( + @NotNull uSkyBlock plugin, + @NotNull PluginConfig config, + @NotNull WorldManager worldManager, + @NotNull PlaceholderHandler placeholderHandler + ) { this.plugin = plugin; this.worldManager = worldManager; + this.placeholderHandler = placeholderHandler; formats.put(Type.PARTY, config.getYamlConfig().getString("options.party.chat-format", "&9PARTY &r{DISPLAYNAME} &f>&d {MESSAGE}")); formats.put(Type.ISLAND, @@ -86,7 +93,7 @@ public void sendMessage(Player sender, Type type, String message) { format = FormatUtil.normalize(format); format = format.replaceAll("\\{DISPLAYNAME}", Matcher.quoteReplacement(sender.getDisplayName())); String msg = format.replaceAll("\\{MESSAGE}", Matcher.quoteReplacement(message)); - msg = PlaceholderHandler.replacePlaceholders(sender, msg); + msg = placeholderHandler.replacePlaceholders(sender, msg); List onlineMembers = getRecipients(sender, type); if (onlineMembers.size() <= 1) { sender.sendMessage(I18nUtil.tr("\u00a7cSorry! {0}", "\u00a79" + diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatPlaceholder.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatPlaceholder.java deleted file mode 100644 index d28b6ea58..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatPlaceholder.java +++ /dev/null @@ -1,26 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.placeholder; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerChatEvent; -import us.talabrek.ultimateskyblock.uSkyBlock; - -/** - * Our native chat-placeholder handler. - */ -public class ChatPlaceholder extends TextPlaceholder implements Listener { - @Override - public boolean registerPlaceholder(uSkyBlock plugin, PlaceholderReplacer replacer) { - Bukkit.getPluginManager().registerEvents(this, plugin); - return super.registerPlaceholder(plugin, replacer); - } - - @EventHandler - public void onChatEvent(AsyncPlayerChatEvent e) { - Player player = e.getPlayer(); - e.setFormat(PlaceholderHandler.replacePlaceholders(player, e.getFormat())); - e.setMessage(PlaceholderHandler.replacePlaceholders(player, e.getMessage())); - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatReplaceListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatReplaceListener.java new file mode 100644 index 000000000..dae1b8b62 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ChatReplaceListener.java @@ -0,0 +1,27 @@ +package us.talabrek.ultimateskyblock.handler.placeholder; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.jetbrains.annotations.NotNull; + +@Singleton +public class ChatReplaceListener implements Listener { + + private final PlaceholderHandler placeholderHandler; + + @Inject + public ChatReplaceListener(@NotNull PlaceholderHandler placeholderHandler) { + this.placeholderHandler = placeholderHandler; + } + + @EventHandler + public void onChatEvent(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + event.setFormat(placeholderHandler.replacePlaceholders(player, event.getFormat())); + event.setMessage(placeholderHandler.replacePlaceholders(player, event.getMessage())); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MVdWPlaceholderAPI.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MVdWPlaceholderAPI.java index 45844e65a..0ec4a81ad 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MVdWPlaceholderAPI.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MVdWPlaceholderAPI.java @@ -1,45 +1,38 @@ package us.talabrek.ultimateskyblock.handler.placeholder; -import org.bukkit.Bukkit; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.uSkyBlock; /** * MVdWPlaceholder proxy */ +@Singleton public class MVdWPlaceholderAPI implements PlaceholderAPI { - public boolean isAvailable() { - // Might not be enabled yet... - return Bukkit.getPluginManager().getPlugin("MVdWPlaceholderAPI") != null; + + private final PlaceholderReplacer replacer; + + @Inject + MVdWPlaceholderAPI(@NotNull PlaceholderReplacer replacer) { + this.replacer = replacer; } - @Override - public boolean registerPlaceholder(uSkyBlock plugin, final PlaceholderReplacer replacer) { - if (isAvailable()) { - be.maximvdw.placeholderapi.PlaceholderReplacer proxy = e -> { - if (replacer.getPlaceholders().contains(e.getPlaceholder())) { - return replacer.replace(e.getOfflinePlayer(), e.getPlayer(), e.getPlaceholder()); - } - return null; - }; - for (String placeholder : replacer.getPlaceholders()) { - be.maximvdw.placeholderapi.PlaceholderAPI.registerPlaceholder(plugin, placeholder, proxy); + public void setup(uSkyBlock plugin) { + be.maximvdw.placeholderapi.PlaceholderReplacer proxy = e -> { + if (replacer.getPlaceholders().contains(e.getPlaceholder())) { + return replacer.replace(e.getOfflinePlayer(), e.getPlayer(), e.getPlaceholder()); } - return true; + return null; + }; + for (String placeholder : replacer.getPlaceholders()) { + be.maximvdw.placeholderapi.PlaceholderAPI.registerPlaceholder(plugin, placeholder, proxy); } - return false; - } - - @Override - public void unregisterPlaceholder(uSkyBlock plugin, PlaceholderReplacer placeholderReplacer) { - // Not implemented. } @Override public String replacePlaceholders(Player player, String message) { - if (isAvailable()) { - return be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, message); - } - return message; + return be.maximvdw.placeholderapi.PlaceholderAPI.replacePlaceholders(player, message); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MvdwPlacehoderProvider.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MvdwPlacehoderProvider.java new file mode 100644 index 000000000..16764ec02 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/MvdwPlacehoderProvider.java @@ -0,0 +1,19 @@ +package us.talabrek.ultimateskyblock.handler.placeholder; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +public class MvdwPlacehoderProvider implements Provider { + + private final PlaceholderAPI.PlaceholderReplacer replacer; + + @Inject + public MvdwPlacehoderProvider(PlaceholderAPI.PlaceholderReplacer replacer) { + this.replacer = replacer; + } + + @Override + public MVdWPlaceholderAPI get() { + return new MVdWPlaceholderAPI(replacer); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderAPI.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderAPI.java index 8796d74c2..8dab1cf70 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderAPI.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderAPI.java @@ -2,18 +2,19 @@ import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Set; +import java.util.Collection; -/** - */ public interface PlaceholderAPI { + interface PlaceholderReplacer { - Set getPlaceholders(); - String replace(OfflinePlayer offlinePlayer, Player player, String placeholder); + + @NotNull Collection getPlaceholders(); + + @Nullable String replace(@Nullable OfflinePlayer offlinePlayer, @Nullable Player player, @Nullable String placeholder); } - String replacePlaceholders(Player player, String message); - boolean registerPlaceholder(uSkyBlock plugin, PlaceholderReplacer replacer); - void unregisterPlaceholder(uSkyBlock plugin, PlaceholderReplacer placeholderReplacer); + + @Nullable String replacePlaceholders(@Nullable Player player, @Nullable String message); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java index 21ded1e60..43fc765e6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderHandler.java @@ -1,70 +1,31 @@ package us.talabrek.ultimateskyblock.handler.placeholder; -import dk.lockfuglsang.minecraft.file.FileUtil; +import com.google.inject.Singleton; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.Collection; +@Singleton public class PlaceholderHandler { - private static final String[] ADAPTORS = { - ChatPlaceholder.class.getName(), - ServerCommandPlaceholder.class.getName(), - "us.talabrek.ultimateskyblock.handler.placeholder.MVdWPlaceholderAPI", - }; - private static PlaceholderAPI.PlaceholderReplacer replacer; - private static final List apis = new ArrayList<>(); + private final Collection apis = new ArrayList<>(); - public static void register(uSkyBlock plugin) { - PlaceholderAPI.PlaceholderReplacer placeholderReplacer = getReplacer(plugin); - for (String className : ADAPTORS) { - String baseName = FileUtil.getExtension(className); - if (plugin.getConfig().getBoolean("placeholder." + baseName.toLowerCase(), false)) { - try { - Class clazz = Class.forName(className); - Object o = clazz.getDeclaredConstructor().newInstance(); - if (o instanceof PlaceholderAPI api) { - if (api.registerPlaceholder(plugin, placeholderReplacer)) { - plugin.getLogger().info("uSkyBlock hooked into " + baseName); - apis.add(api); - } else { - plugin.getLogger().info("uSkyBlock failed to hook into " + baseName); - } - } - } catch (Exception e) { - plugin.getLogger().info("uSkyBlock failed to hook into " + baseName); - } - } - } - } - - public static void unregister(uSkyBlock plugin) { - PlaceholderAPI.PlaceholderReplacer placeholderReplacer = getReplacer(plugin); - for (Iterator it = apis.iterator(); it.hasNext(); ) { - it.next().unregisterPlaceholder(plugin, placeholderReplacer); - it.remove(); - } - replacer = null; + public void registerPlaceholders(PlaceholderAPI api) { + apis.add(api); } - public static String replacePlaceholders(Player player, String message) { + @Contract("_, null -> null") + public String replacePlaceholders(Player player, @Nullable String message) { if (message == null) { return null; } - String msg = message; + String replacedMessage = message; for (PlaceholderAPI api : apis) { - msg = api.replacePlaceholders(player, msg); - } - return msg; - } - - private static PlaceholderAPI.PlaceholderReplacer getReplacer(uSkyBlock plugin) { - if (replacer == null) { - replacer = new PlaceholderReplacerImpl(plugin); + replacedMessage = api.replacePlaceholders(player, replacedMessage); } - return replacer; + return replacedMessage; } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderModule.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderModule.java new file mode 100644 index 000000000..44121866b --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderModule.java @@ -0,0 +1,52 @@ +package us.talabrek.ultimateskyblock.handler.placeholder; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.PluginConfig; +import us.talabrek.ultimateskyblock.uSkyBlock; + +public class PlaceholderModule { + + private final PlaceholderHandler placeholderHandler; + private final PluginConfig config; + private final ChatReplaceListener chatReplaceListener; + private final ServerCommandReplaceListener serverCommandListener; + private final TextPlaceholder textPlaceholder; + private final Provider mvdwPlaceholderProvider; + + @Inject + public PlaceholderModule( + @NotNull PlaceholderHandler placeholderHandler, + @NotNull PluginConfig config, + @NotNull ChatReplaceListener chatReplaceListener, + @NotNull ServerCommandReplaceListener serverCommandListener, + @NotNull TextPlaceholder textPlaceholder, + @NotNull Provider mvdwPlaceholderProvider + ) { + this.placeholderHandler = placeholderHandler; + this.config = config; + this.chatReplaceListener = chatReplaceListener; + this.serverCommandListener = serverCommandListener; + this.textPlaceholder = textPlaceholder; + this.mvdwPlaceholderProvider = mvdwPlaceholderProvider; + } + + public void startup(uSkyBlock plugin) { + if (config.getYamlConfig().getBoolean("placeholder.chatplaceholder", false)) { + plugin.getServer().getPluginManager().registerEvents(chatReplaceListener, plugin); + } + if (config.getYamlConfig().getBoolean("placeholder.servercommandplaceholder", false)) { + plugin.getServer().getPluginManager().registerEvents(serverCommandListener, plugin); + } + + if (config.getYamlConfig().getBoolean("placeholder.mvdwplaceholderapi", false) + && Bukkit.getPluginManager().getPlugin("MVdWPlaceholderAPI") != null) { + MVdWPlaceholderAPI mvdwPlaceholder = mvdwPlaceholderProvider.get(); + mvdwPlaceholder.setup(plugin); + placeholderHandler.registerPlaceholders(mvdwPlaceholder); + } + placeholderHandler.registerPlaceholders(textPlaceholder); + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java index 1e3692ab4..1a8e1993c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/PlaceholderReplacerImpl.java @@ -3,17 +3,22 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandRank; import us.talabrek.ultimateskyblock.island.IslandInfo; +import us.talabrek.ultimateskyblock.island.IslandLogic; import us.talabrek.ultimateskyblock.island.LimitLogic; import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.player.PlayerLogic; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import java.util.Arrays; -import java.util.HashSet; +import java.util.Collection; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -24,58 +29,72 @@ /** * The actual replacer for placeholders */ +@Singleton public class PlaceholderReplacerImpl implements PlaceholderAPI.PlaceholderReplacer { - private static final Set PLACEHOLDERS = new HashSet<>(Arrays.asList( - "usb_version", - "usb_island_level", - "usb_island_level_int", - "usb_island_rank", - "usb_island_leader", - "usb_island_golems_max", - "usb_island_monsters_max", - "usb_island_animals_max", - "usb_island_villagers_max", - "usb_island_partysize_max", - "usb_island_golems", - "usb_island_monsters", - "usb_island_animals", - "usb_island_villagers", - "usb_island_partysize", - "usb_island_biome", - "usb_island_bans", - "usb_island_members", - "usb_island_trustees", - "usb_island_location", - "usb_island_location_x", - "usb_island_location_y", - "usb_island_location_z", - "usb_island_schematic" - )); + private static final Collection PLACEHOLDERS = Set.of( + "usb_version", + "usb_island_level", + "usb_island_level_int", + "usb_island_rank", + "usb_island_leader", + "usb_island_golems_max", + "usb_island_monsters_max", + "usb_island_animals_max", + "usb_island_villagers_max", + "usb_island_partysize_max", + "usb_island_golems", + "usb_island_monsters", + "usb_island_animals", + "usb_island_villagers", + "usb_island_partysize", + "usb_island_biome", + "usb_island_bans", + "usb_island_members", + "usb_island_trustees", + "usb_island_location", + "usb_island_location_x", + "usb_island_location_y", + "usb_island_location_z", + "usb_island_schematic" + ); private final uSkyBlock plugin; + private final PlayerLogic playerLogic; + private final IslandLogic islandLogic; + private final LimitLogic limitLogic; private final LoadingCache cache; - public PlaceholderReplacerImpl(uSkyBlock plugin) { + @Inject + public PlaceholderReplacerImpl( + @NotNull uSkyBlock plugin, + @NotNull PlayerLogic playerLogic, + @NotNull IslandLogic islandLogic, + @NotNull LimitLogic limitLogic + ) { this.plugin = plugin; - cache = CacheBuilder - .from(plugin.getConfig().getString("options.advanced.placeholderCache", - "maximumSize=200,expireAfterWrite=20s")) - .build(new CacheLoader() { - @Override - public String load(CacheEntry cacheEntry) throws Exception { - try { - return lookup(cacheEntry); - } catch (RuntimeException e) { - throw new ExecutionException(e.getMessage(), e); - } + this.playerLogic = playerLogic; + this.islandLogic = islandLogic; + this.limitLogic = limitLogic; + + this.cache = CacheBuilder + .from(plugin.getConfig().getString("options.advanced.placeholderCache", + "maximumSize=200,expireAfterWrite=20s")) + .build(new CacheLoader<>() { + @Override + public @NotNull String load(@NotNull CacheEntry cacheEntry) throws Exception { + try { + return lookup(cacheEntry); + } catch (RuntimeException e) { + throw new ExecutionException(e.getMessage(), e); } - }); + } + }); } private String lookup(CacheEntry entry) { - String placeholder = entry.getPlaceholder(); + String placeholder = entry.placeholder(); if (placeholder.startsWith("usb_island")) { - PlayerInfo playerInfo = plugin.getPlayerLogic().getPlayerInfo(entry.getUuid()); - IslandInfo islandInfo = plugin.getIslandLogic().getIslandInfo(playerInfo); + PlayerInfo playerInfo = playerLogic.getPlayerInfo(entry.uuid()); + IslandInfo islandInfo = islandLogic.getIslandInfo(playerInfo); if (playerInfo == null || islandInfo == null) { return tr("N/A"); } @@ -87,43 +106,46 @@ private String lookup(CacheEntry entry) { } private String lookup(String placeholder) { - switch (placeholder) { - case "usb_version": return plugin.getDescription().getVersion(); + if (placeholder.equals("usb_version")) { + return plugin.getDescription().getVersion(); } throw new IllegalArgumentException("Unsupported placeholder " + placeholder); } private String lookup(IslandInfo islandInfo, String placeholder) { - switch (placeholder) { - case "usb_island_level": return pre("{0,number,##.#}", islandInfo.getLevel()); - case "usb_island_level_int": return pre("{0,number,#}", islandInfo.getLevel()); - case "usb_island_rank": return getRank(islandInfo); - case "usb_island_leader": return islandInfo.getLeader(); - case "usb_island_golems_max": return "" + islandInfo.getMaxGolems(); - case "usb_island_monsters_max": return "" + islandInfo.getMaxMonsters(); - case "usb_island_animals_max": return "" + islandInfo.getMaxAnimals(); - case "usb_island_villagers_max": return "" + islandInfo.getMaxVillagers(); - case "usb_island_partysize_max": return "" + islandInfo.getMaxPartySize(); - case "usb_island_golems": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.GOLEM); - case "usb_island_monsters": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.MONSTER); - case "usb_island_animals": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.ANIMAL); - case "usb_island_villagers": return "" + plugin.getLimitLogic().getCreatureCount(islandInfo).get(LimitLogic.CreatureType.VILLAGER); - case "usb_island_partysize": return "" + islandInfo.getPartySize(); - case "usb_island_biome": return islandInfo.getBiomeName(); - case "usb_island_bans": return ""+islandInfo.getBans(); - case "usb_island_members": return ""+islandInfo.getMembers(); - case "usb_island_trustees": return ""+islandInfo.getTrustees(); - case "usb_island_location": return LocationUtil.asString(islandInfo.getIslandLocation()); - case "usb_island_location_x": return pre("{0,number,#}", islandInfo.getIslandLocation().getBlockX()); - case "usb_island_location_y": return pre("{0,number,#}", islandInfo.getIslandLocation().getBlockY()); - case "usb_island_location_z": return pre("{0,number,#}", islandInfo.getIslandLocation().getBlockZ()); - case "usb_island_schematic": return islandInfo.getSchematicName(); - } - throw new IllegalArgumentException("Unsupported placeholder " + placeholder); + return switch (placeholder) { + case "usb_island_level" -> pre("{0,number,##.#}", islandInfo.getLevel()); + case "usb_island_level_int" -> pre("{0,number,#}", islandInfo.getLevel()); + case "usb_island_rank" -> getRank(islandInfo); + case "usb_island_leader" -> islandInfo.getLeader(); + case "usb_island_golems_max" -> "" + islandInfo.getMaxGolems(); + case "usb_island_monsters_max" -> "" + islandInfo.getMaxMonsters(); + case "usb_island_animals_max" -> "" + islandInfo.getMaxAnimals(); + case "usb_island_villagers_max" -> "" + islandInfo.getMaxVillagers(); + case "usb_island_partysize_max" -> "" + islandInfo.getMaxPartySize(); + case "usb_island_golems" -> "" + limitLogic.getCreatureCount(islandInfo).get(LimitLogic.CreatureType.GOLEM); + case "usb_island_monsters" -> + "" + limitLogic.getCreatureCount(islandInfo).get(LimitLogic.CreatureType.MONSTER); + case "usb_island_animals" -> + "" + limitLogic.getCreatureCount(islandInfo).get(LimitLogic.CreatureType.ANIMAL); + case "usb_island_villagers" -> + "" + limitLogic.getCreatureCount(islandInfo).get(LimitLogic.CreatureType.VILLAGER); + case "usb_island_partysize" -> "" + islandInfo.getPartySize(); + case "usb_island_biome" -> islandInfo.getBiomeName(); + case "usb_island_bans" -> "" + islandInfo.getBans(); + case "usb_island_members" -> "" + islandInfo.getMembers(); + case "usb_island_trustees" -> "" + islandInfo.getTrustees(); + case "usb_island_location" -> LocationUtil.asString(islandInfo.getIslandLocation()); + case "usb_island_location_x" -> pre("{0,number,#}", islandInfo.getIslandLocation().getBlockX()); + case "usb_island_location_y" -> pre("{0,number,#}", islandInfo.getIslandLocation().getBlockY()); + case "usb_island_location_z" -> pre("{0,number,#}", islandInfo.getIslandLocation().getBlockZ()); + case "usb_island_schematic" -> islandInfo.getSchematicName(); + default -> throw new IllegalArgumentException("Unsupported placeholder " + placeholder); + }; } private String getRank(IslandInfo islandInfo) { - IslandRank rank = plugin.getIslandLogic().getRank(islandInfo.getName()); + IslandRank rank = islandLogic.getRank(islandInfo.getName()); if (rank != null) { return pre("{0,number,#}", rank.getRank()); } else { @@ -132,12 +154,12 @@ private String getRank(IslandInfo islandInfo) { } @Override - public Set getPlaceholders() { + public @NotNull Collection getPlaceholders() { return PLACEHOLDERS; } @Override - public String replace(OfflinePlayer offlinePlayer, Player player, String placeholder) { + public @Nullable String replace(@Nullable OfflinePlayer offlinePlayer, @Nullable Player player, @Nullable String placeholder) { if (placeholder == null || !placeholder.startsWith("usb_")) { return null; } @@ -156,41 +178,6 @@ public String replace(OfflinePlayer offlinePlayer, Player player, String placeho } } - private static class CacheEntry { - private final UUID uuid; - private final String placeholder; - - private CacheEntry(UUID uuid, String placeholder) { - this.uuid = uuid; - this.placeholder = placeholder; - } - - public UUID getUuid() { - return uuid; - } - - public String getPlaceholder() { - return placeholder; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - CacheEntry that = (CacheEntry) o; - - if (!placeholder.equals(that.placeholder)) return false; - if (!uuid.equals(that.uuid)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = uuid.hashCode(); - result = 31 * result + placeholder.hashCode(); - return result; - } + private record CacheEntry(UUID uuid, String placeholder) { } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandPlaceholder.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandPlaceholder.java deleted file mode 100644 index 5bd1a34d2..000000000 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandPlaceholder.java +++ /dev/null @@ -1,28 +0,0 @@ -package us.talabrek.ultimateskyblock.handler.placeholder; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.server.ServerCommandEvent; -import us.talabrek.ultimateskyblock.uSkyBlock; - -/** - * Replaces placeholders in server-commands - */ -public class ServerCommandPlaceholder extends TextPlaceholder implements Listener { - @Override - public boolean registerPlaceholder(uSkyBlock plugin, PlaceholderReplacer replacer) { - Bukkit.getPluginManager().registerEvents(this, plugin); - return super.registerPlaceholder(plugin, replacer); - } - - @EventHandler - public void onCmd(ServerCommandEvent e) { - String cmd = e.getCommand(); - String replacement = PlaceholderHandler.replacePlaceholders(e.getSender() instanceof Player ? (Player) e.getSender() : null, cmd); - if (replacement != null && !cmd.equals(replacement)) { - e.setCommand(cmd); - } - } -} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandReplaceListener.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandReplaceListener.java new file mode 100644 index 000000000..1e0efae02 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/ServerCommandReplaceListener.java @@ -0,0 +1,29 @@ +package us.talabrek.ultimateskyblock.handler.placeholder; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.ServerCommandEvent; +import org.jetbrains.annotations.NotNull; + +@Singleton +public class ServerCommandReplaceListener implements Listener { + + private final PlaceholderHandler placeholderHandler; + + @Inject + public ServerCommandReplaceListener(@NotNull PlaceholderHandler placeholderHandler) { + this.placeholderHandler = placeholderHandler; + } + + @EventHandler + public void onCommand(ServerCommandEvent event) { + String command = event.getCommand(); + String replacement = placeholderHandler.replacePlaceholders(event.getSender() instanceof Player ? (Player) event.getSender() : null, command); + if (replacement != null && !command.equals(replacement)) { + event.setCommand(command); + } + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java index 7c139bce5..d85554915 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholder.java @@ -1,7 +1,10 @@ package us.talabrek.ultimateskyblock.handler.placeholder; +import com.google.inject.Inject; +import com.google.inject.Singleton; import org.bukkit.entity.Player; -import us.talabrek.ultimateskyblock.uSkyBlock; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -9,23 +12,23 @@ /** * Common PlaceholderAPI for internal placeholders. */ +@Singleton public class TextPlaceholder implements PlaceholderAPI { + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{(?usb_[^}]*)\\}"); - private uSkyBlock plugin; - private PlaceholderReplacer replacer; + private final PlaceholderReplacer replacer; - @Override - public boolean registerPlaceholder(uSkyBlock plugin, PlaceholderReplacer replacer) { - this.plugin = plugin; + @Inject + public TextPlaceholder(@NotNull PlaceholderReplacer replacer) { this.replacer = replacer; - return true; } - public String replacePlaceholders(Player player, String message) { + @Override + public @Nullable String replacePlaceholders(@Nullable Player player, @Nullable String message) { return replacePlaceholdersInternal(player, message); } - private String replacePlaceholdersInternal(Player player, String message) { + private @Nullable String replacePlaceholdersInternal(@Nullable Player player, @Nullable String message) { if (message == null) { return null; } @@ -35,14 +38,14 @@ private String replacePlaceholdersInternal(Player player, String message) { int ix = 0; StringBuilder sb = new StringBuilder(); do { - sb.append(message.substring(ix, matcher.start())); + sb.append(message, ix, matcher.start()); String placeholderString = matcher.group("placeholder"); if (placeholderString != null && replacer.getPlaceholders().contains(placeholderString)) { String replacement = replacer.replace(null, player, placeholderString); if (replacement != null) { sb.append(replacement); } else { - sb.append(message.substring(matcher.start(), matcher.end())); + sb.append(message, matcher.start(), matcher.end()); } } else { sb.append("{").append(placeholderString).append("}"); @@ -56,9 +59,4 @@ private String replacePlaceholdersInternal(Player player, String message) { } return result; } - - @Override - public void unregisterPlaceholder(uSkyBlock plugin, PlaceholderReplacer placeholderReplacer) { - // Not needed, since the plugin will unregister all handlers - } } diff --git a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java index 0c2629b84..133dd9c46 100644 --- a/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java +++ b/uSkyBlock-Core/src/test/java/us/talabrek/ultimateskyblock/handler/placeholder/TextPlaceholderTest.java @@ -2,13 +2,15 @@ import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import org.junit.Test; +import java.util.Collection; import java.util.Set; import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; /** * Created by R4zorax on 26/04/2016. @@ -16,10 +18,9 @@ public class TextPlaceholderTest { @Test public void replacePlaceholders() throws Exception { - TextPlaceholder placeholder = new TextPlaceholder(); - placeholder.registerPlaceholder(null, new PlaceholderAPI.PlaceholderReplacer() { + TextPlaceholder placeholder = new TextPlaceholder(new PlaceholderAPI.PlaceholderReplacer() { @Override - public Set getPlaceholders() { + public @NotNull Collection getPlaceholders() { return Set.of("usb_replaceme"); } From 66ef26563a589022ee43217d689b55d5dc26f833 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:39:26 +0800 Subject: [PATCH 163/190] migrate maven to gradle --- .github/workflows/build.yml | 8 +- build.gradle.kts | 55 +++ bukkit-utils/.github/workflows/build.yml | 8 +- bukkit-utils/build.gradle.kts | 21 + bukkit-utils/pom.xml | 151 ------- gradle.properties | 5 + gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 240 ++++++++++ gradlew.bat | 91 ++++ po-utils/build.gradle.kts | 18 + po-utils/pom.xml | 101 ----- pom.xml | 265 ----------- settings.gradle.kts | 13 + uSkyBlock-API/build.gradle.kts | 16 + uSkyBlock-API/pom.xml | 97 ---- uSkyBlock-APIv2/build.gradle.kts | 15 + uSkyBlock-APIv2/pom.xml | 75 ---- uSkyBlock-Core/build.gradle.kts | 43 ++ uSkyBlock-Core/pom.xml | 550 ----------------------- uSkyBlock-FAWE/build.gradle.kts | 14 + uSkyBlock-FAWE/pom.xml | 107 ----- uSkyBlock-Plugin/build.gradle.kts | 12 + uSkyBlock-Plugin/pom.xml | 73 --- 23 files changed, 551 insertions(+), 1433 deletions(-) create mode 100644 build.gradle.kts create mode 100644 bukkit-utils/build.gradle.kts delete mode 100644 bukkit-utils/pom.xml create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 po-utils/build.gradle.kts delete mode 100644 po-utils/pom.xml delete mode 100644 pom.xml create mode 100644 settings.gradle.kts create mode 100644 uSkyBlock-API/build.gradle.kts delete mode 100644 uSkyBlock-API/pom.xml create mode 100644 uSkyBlock-APIv2/build.gradle.kts delete mode 100644 uSkyBlock-APIv2/pom.xml create mode 100644 uSkyBlock-Core/build.gradle.kts delete mode 100644 uSkyBlock-Core/pom.xml create mode 100644 uSkyBlock-FAWE/build.gradle.kts delete mode 100644 uSkyBlock-FAWE/pom.xml create mode 100644 uSkyBlock-Plugin/build.gradle.kts delete mode 100644 uSkyBlock-Plugin/pom.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 55e1a9cae..0d30a3531 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,14 +29,8 @@ jobs: distribution: 'temurin' - name: Install gettext run: sudo apt-get install -y gettext - - name: Cache Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - name: Build with Maven - run: mvn -U -Pi18n clean deploy + run: gradle build # Install our SSH key: - name: Install SSH key diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..f501ed62a --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,55 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + `maven-publish` + kotlin("jvm") version "2.1.10" +} + +subprojects { + apply(plugin = "kotlin") + dependencies { + api(rootProject) + api(kotlin("script-runtime")) + kotlinScriptDef(rootProject) + } +} + +allprojects { + repositories { + gradlePluginPortal() + mavenLocal() + mavenCentral() + maven("https://hub.spigotmc.org/nexus/content/repositories/public") + maven("https://papermc.io/repo/repository/maven-public/") + maven("https://maven.enginehub.org/repo/") + maven("https://oss.sonatype.org/content/repositories/snapshots/") + maven("https://repo.codemc.org/repository/maven-public") + maven("https://repo.mvdw-software.com/content/groups/public/") + maven("https://www.uskyblock.ovh/maven/dependencies/") + maven("https://www.uskyblock.ovh/maven/uskyblock/") + maven("https://repo.maven.apache.org/maven2/") + maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") + + maven("https://repo.onarandombox.com/content/groups/public") + maven("https://hub.spigotmc.org/nexus/content/groups/public/") + maven("https://jitpack.io") + maven("https://repo.minebench.de/") + maven("https://repo.maven.apache.org/maven2/") + } +} + +group = "ovh.uskyblock" +version = "3.2.0-SNAPSHOT" +java.sourceCompatibility = JavaVersion.VERSION_1_8 + +publishing { + publications.create("maven") { + from(components["java"]) + } +} + +tasks.withType() { + options.encoding = "UTF-8" +} diff --git a/bukkit-utils/.github/workflows/build.yml b/bukkit-utils/.github/workflows/build.yml index 21604b115..e131b318c 100644 --- a/bukkit-utils/.github/workflows/build.yml +++ b/bukkit-utils/.github/workflows/build.yml @@ -18,14 +18,8 @@ jobs: with: java-version: '16' distribution: 'adopt' - - name: Cache Maven repository - uses: actions/cache@v2 - with: - path: ~/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - name: Build with Maven - run: mvn -U clean deploy + run: gradle build # Deploy steps when pushed to master - name: Install SSH key diff --git a/bukkit-utils/build.gradle.kts b/bukkit-utils/build.gradle.kts new file mode 100644 index 000000000..b754192d7 --- /dev/null +++ b/bukkit-utils/build.gradle.kts @@ -0,0 +1,21 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +dependencies { + implementation(project(":po-utils")) + implementation("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") + implementation("net.milkbowl.vault:VaultAPI:1.7") + testImplementation("org.hamcrest:hamcrest-core:1.3") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("junit:junit:4.13.2") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("com.google.code.gson:gson:2.8.7") +} + +description = "bukkit-utils" + +val testsJar by tasks.registering(Jar::class) { + archiveClassifier.set("tests") + from(sourceSets["test"].output) +} diff --git a/bukkit-utils/pom.xml b/bukkit-utils/pom.xml deleted file mode 100644 index d6c78ae12..000000000 --- a/bukkit-utils/pom.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - 4.0.0 - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - bukkit-utils - - - 1.7 - - UTF-8 - - - - scm:git:git://github.com/uskyblock/bukkit-utils.git - scm:git:git://github.com/uskyblock/bukkit-utils.git - https://github.com/uskyblock/bukkit-utils.git - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - - - - spigotmc.org - https://hub.spigotmc.org/nexus/content/repositories/public - - - uskyblock-dependencies - https://www.uskyblock.ovh/maven/dependencies/ - - - - - - apache-snapshots - https://repository.apache.org/snapshots/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - - javadoc - - deploy - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - - - - ovh.uskyblock - po-utils - 3.2.0-SNAPSHOT - - - org.spigotmc - spigot-api - ${spigotapi.version} - true - compile - - - net.milkbowl.vault - VaultAPI - ${vaultapi.version} - true - - - org.hamcrest - hamcrest-core - 1.3 - test - - - org.hamcrest - hamcrest-library - 1.3 - test - - - junit - junit - ${junit.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - com.google.code.gson - gson - 2.8.7 - test - - - diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..c5574b867 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,5 @@ +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=7890 + +systemProp.https.proxyHost=127.0.0.1 +systemProp.https.proxyPort=7890 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..52e7c5f0f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Apr 26 12:58:38 CST 2025 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 000000000..a69d9cb6c --- /dev/null +++ b/gradlew @@ -0,0 +1,240 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000..f127cfd49 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,91 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/po-utils/build.gradle.kts b/po-utils/build.gradle.kts new file mode 100644 index 000000000..e179685ee --- /dev/null +++ b/po-utils/build.gradle.kts @@ -0,0 +1,18 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") +} + +description = "po-utils" + +java { + withJavadocJar() +} diff --git a/po-utils/pom.xml b/po-utils/pom.xml deleted file mode 100644 index 1701740b3..000000000 --- a/po-utils/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - 4.0.0 - jar - po-utils - - - - org.jetbrains - annotations - - - - junit - junit - ${junit.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-vintage-engine.version} - test - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${hamcrest.version} - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - attach-javadocs - - jar - - - - - javadoc - - deploy - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - diff --git a/pom.xml b/pom.xml deleted file mode 100644 index d44536ff8..000000000 --- a/pom.xml +++ /dev/null @@ -1,265 +0,0 @@ - - 4.0.0 - ovh.uskyblock - uSkyBlock - pom - 3.2.0-SNAPSHOT - Ultimate SkyBlock - - - 4.16.0 - 4.3.2 - 3.14.0 - 1.12.0 - 4.5.14 - 2.10.1 - 33.1.0-jre - 23.0.0 - 3.8.6 - ${project.version} - 1.0.8 - 1.20.6-R0.1-SNAPSHOT - 1.7 - 7.2.19 - 7.0.9 - 7.0.0 - - UTF-8 - ${project.artifactId} - invalid - dev - msgfmt - msgmerge - - - 2.2 - 4.13.2 - 5.9.0 - 5.14.2 - - - - po-utils - bukkit-utils - uSkyBlock-API - uSkyBlock-APIv2 - uSkyBlock-Core - uSkyBlock-Plugin - uSkyBlock-FAWE - - - - scm:git:git://github.com/uskyblock/uSkyBlock.git - scm:git:git://github.com/uskyblock/uSkyBlock.git - https://github.com/uskyblock/uSkyBlock.git - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - - - ${finalName} - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - 21 - UTF-8 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.11.2 - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - org.apache.maven.plugins - maven-source-plugin - 3.3.1 - - - org.apache.maven.plugins - maven-clean-plugin - 3.4.0 - - - org.apache.maven.plugins - maven-surefire-plugin - 3.5.2 - - - org.apache.maven.plugins - maven-failsafe-plugin - 3.5.2 - - - org.apache.maven.plugins - maven-assembly-plugin - 3.7.1 - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.5.0 - - - enforce-maven - - enforce - - - - - 3.8.1 - - - - - - - - - - - spigotmc.org - https://hub.spigotmc.org/nexus/content/repositories/public - - - papermc - https://papermc.io/repo/repository/maven-public/ - - - sk89q-repo - - https://maven.enginehub.org/repo/ - - - sonatype-oss-snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - - CodeMC - https://repo.codemc.org/repository/maven-public - - - mvdw-software - https://repo.mvdw-software.com/content/groups/public/ - - - uskyblock-dependencies - https://www.uskyblock.ovh/maven/dependencies/ - - - uskyblock-maven - https://www.uskyblock.ovh/maven/uskyblock/ - - - - - apache-snapshots - https://repository.apache.org/snapshots/ - - - uskyblock-dependencies - https://www.uskyblock.ovh/maven/dependencies/ - - - - - - net.milkbowl.vault - VaultAPI - true - ${vault.version} - - - org.bukkit - bukkit - - - - - com.github.rlf - uSkyBlock-API - ${api.version} - - - ovh.uskyblock - uSkyBlock-APIv2 - ${project.version} - - - ovh.uskyblock - uSkyBlock-Core - ${project.version} - - - ovh.uskyblock - uSkyBlock-FAWE - ${project.version} - - - ovh.uskyblock - po-utils - ${project.version} - - - org.jetbrains - annotations - ${jbannotations.version} - - - io.papermc - paperlib - ${paperlib.version} - - - net.kyori - adventure-api - ${adventure-api.version} - - - net.kyori - adventure-platform-bukkit - ${adventure-bukkit.version} - - - com.google.code.gson - gson - ${gson.version} - - - org.apache.httpcomponents - httpclient - ${apache-http.version} - - - org.apache.maven - maven-artifact - ${maven-artifact.version} - - - - diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..e250c6b30 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,13 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = "uSkyBlock" +include(":bukkit-utils") +include(":po-utils") +include(":uSkyBlock-APIv2") +include(":uSkyBlock-FAWE") +include(":uSkyBlock-Core") +include(":bukkit-utils") +include(":uSkyBlock-Plugin") +include(":uSkyBlock-API") diff --git a/uSkyBlock-API/build.gradle.kts b/uSkyBlock-API/build.gradle.kts new file mode 100644 index 000000000..e097930b0 --- /dev/null +++ b/uSkyBlock-API/build.gradle.kts @@ -0,0 +1,16 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") +} + +group = "com.github.rlf" +description = "uSkyBlock-API" + +java { + withJavadocJar() +} diff --git a/uSkyBlock-API/pom.xml b/uSkyBlock-API/pom.xml deleted file mode 100644 index 25cd4787c..000000000 --- a/uSkyBlock-API/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - 4.0.0 - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - com.github.rlf - uSkyBlock-API - 3.2.0-SNAPSHOT - - - UTF-8 - - - - - internal.repo - Temporary Staging Repository - file://${project.build.directory}/mvn-repo - - - - - - spigotmc.org - https://hub.spigotmc.org/nexus/content/repositories/public - - - - - - org.spigotmc - spigot-api - ${spigotapi.version} - provided - true - - - - org.jetbrains - annotations - 23.0.0 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - attach-javadocs - - jar - - - - - javadoc - - deploy - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - diff --git a/uSkyBlock-APIv2/build.gradle.kts b/uSkyBlock-APIv2/build.gradle.kts new file mode 100644 index 000000000..61434a538 --- /dev/null +++ b/uSkyBlock-APIv2/build.gradle.kts @@ -0,0 +1,15 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") +} + +description = "uSkyBlock-APIv2" + +java { + withJavadocJar() +} diff --git a/uSkyBlock-APIv2/pom.xml b/uSkyBlock-APIv2/pom.xml deleted file mode 100644 index 471465ef1..000000000 --- a/uSkyBlock-APIv2/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - 4.0.0 - jar - uSkyBlock-APIv2 - - - - org.spigotmc - spigot-api - ${spigotapi.version} - provided - true - - - org.jetbrains - annotations - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - attach-javadocs - - jar - - - - - javadoc - - deploy - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts new file mode 100644 index 000000000..d171a533b --- /dev/null +++ b/uSkyBlock-Core/build.gradle.kts @@ -0,0 +1,43 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +dependencies { + implementation(project(":bukkit-utils")) + implementation(project(":po-utils")) + implementation(project(":uSkyBlock-API")) + implementation(project(":uSkyBlock-APIv2")) + implementation("io.papermc:paperlib:1.0.8") + implementation("org.bstats:bstats-bukkit:3.0.1") + implementation("com.google.inject:guice:7.0.0") + implementation("org.jetbrains:annotations:23.0.0") + testImplementation(project(":bukkit-utils")) + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") + testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.mockito:mockito-core:5.14.2") + compileOnly("net.milkbowl.vault:VaultAPI:1.7") + compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") + compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") + compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + compileOnly("com.google.guava:guava:33.1.0-jre") + compileOnly("com.google.code.gson:gson:2.10.1") + compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.0.1-SNAPSHOT") { + exclude("*", "*") + } + compileOnly("net.kyori:adventure-api:4.16.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.2") + compileOnly("org.apache.commons:commons-lang3:3.14.0") + compileOnly("org.apache.commons:commons-text:1.12.0") + compileOnly("org.apache.httpcomponents:httpclient:4.5.14") + compileOnly("org.apache.maven:maven-artifact:3.8.6") +} + +description = "uSkyBlock-Core" + +java { + withJavadocJar() +} diff --git a/uSkyBlock-Core/pom.xml b/uSkyBlock-Core/pom.xml deleted file mode 100644 index f34e779ee..000000000 --- a/uSkyBlock-Core/pom.xml +++ /dev/null @@ -1,550 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - 4.0.0 - jar - uSkyBlock-Core - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - com.google.code.maven-replacer-plugin - replacer - 1.5.3 - - - cleanup-po-files - process-resources - - replace - - - ${basedir}/src/main/po - *.po, *.pot - - - #: .*\n - - - - "POT-Creation-Date:.*\n - - - - - - - - - org.codehaus.mojo - buildnumber-maven-plugin - 3.2.1 - - - generate-resources - - create - - - - - 7 - false - false - DEV - - - - org.apache.maven.plugins - maven-shade-plugin - - - package - - shade - - - false - true - - - ovh.uskyblock:bukkit-utils - io.papermc:paperlib - org.bstats:* - ovh.uskyblock:po-utils - - - - - dk.lockfuglsang.minecraft - us.talabrek.ultimateskyblock.utils - - - io.papermc.lib - us.talabrek.ultimateskyblock.paperlib - - - org.bstats - us.talabrek.ultimateskyblock.metrics - - - - - *:* - - META-INF/*.MF - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - module-info.class - META-INF.* - - - - - - - - - org.apache.maven.plugins - maven-clean-plugin - - - - src/main/po - - *~ - - - *.po - *.pot - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - 3.1.0 - - - prepare-package - run - - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - public - false - none - - - - attach-javadocs - - jar - - - - - javadoc - - deploy - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - - . - true - src/main/resources - - *.yml - README.md - **/*.properties - - - - . - false - src/main/resources - - schematics/* - structures/* - - - - . - ${basedir} - - README.md - LICENSE.txt - - - - - - . - src/test/resources - false - - - imported - src/main/resources - true - - levelConfig.yml - - - - - - - - i18n - - false - - - - - com.github.rlf - gettext-maven-plugin - 1.2.10 - - - find-bukkit-utils-msgids - generate-sources - - gettext - - - ${project.parent.basedir}/bukkit-utils/src/main/java - - - - find-msgids - generate-sources - - gettext - - - - -j - - - - - update-po-files - generate-resources - - merge - - - ${msgmergeCmd} - - -N - - - - - clear-fuzzy - generate-resources - - attrib - - - - --clear-fuzzy - --empty - --no-obsolete - - - xx_PIRATE.po - xx_lol_US.po - - - - - report-po-completion - process-resources - - report - - - ${msgfmtCmd} - - - - - ${project.build.directory}/classes - 2 - ${project.basedir}/src/main/po - us.talabrek.ultimateskyblock.i18n.Messages - properties - - --no-location - - - - - - - - - - - ovh.uskyblock - bukkit-utils - 3.2.0-SNAPSHOT - - - ovh.uskyblock - bukkit-utils - 3.2.0-SNAPSHOT - test-jar - test - - - ovh.uskyblock - po-utils - - - com.github.rlf - uSkyBlock-API - - - ovh.uskyblock - uSkyBlock-APIv2 - - - net.milkbowl.vault - VaultAPI - provided - true - - - - org.spigotmc - spigot-api - ${spigotapi.version} - provided - true - - - com.google.code.gson - gson - - - - - - io.papermc - paperlib - compile - - - - com.onarandombox.multiversecore - Multiverse-Core - 4.3.1 - provided - true - - - * - * - - - - - com.onarandombox.multiverseinventories - Multiverse-Inventories - 4.2.3 - provided - true - - - * - * - - - - - - com.sk89q.worldedit - worldedit-bukkit - ${worldedit.version} - provided - - - org.bukkit - bukkit - - - - - - com.sk89q.worldguard - worldguard-bukkit - ${worldguard.version} - provided - - - com.sk89q - worldedit - - - - - - org.bstats - bstats-bukkit - 3.0.1 - compile - - - - com.google.guava - guava - ${guava.version} - provided - - - - com.google.code.gson - gson - provided - - - com.google.inject - guice - ${guice.version} - - - be.maximvdw - MVdWPlaceholderAPI - 3.0.1-SNAPSHOT - provided - - - - * - * - - - - - net.kyori - adventure-api - provided - - - net.kyori - adventure-platform-bukkit - provided - - - - org.jetbrains - annotations - - - org.apache.commons - commons-lang3 - ${apache-commons.version} - provided - - - org.apache.commons - commons-text - ${apache-commons-text.version} - provided - - - - org.apache.httpcomponents - httpclient - provided - - - org.apache.maven - maven-artifact - provided - - - - org.hamcrest - hamcrest - ${hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${hamcrest.version} - test - - - junit - junit - ${junit.version} - test - - - org.junit.vintage - junit-vintage-engine - ${junit-vintage-engine.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - diff --git a/uSkyBlock-FAWE/build.gradle.kts b/uSkyBlock-FAWE/build.gradle.kts new file mode 100644 index 000000000..86a9c611d --- /dev/null +++ b/uSkyBlock-FAWE/build.gradle.kts @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + + +dependencies { + implementation(project(":uSkyBlock-Core")) + compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core:2.13.0") + compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit:2.13.0") + compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") + compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") +} + +description = "uSkyBlock-FAWE" diff --git a/uSkyBlock-FAWE/pom.xml b/uSkyBlock-FAWE/pom.xml deleted file mode 100644 index 23315ca13..000000000 --- a/uSkyBlock-FAWE/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - 4.0.0 - uSkyBlock-FAWE - - - - com.fastasyncworldedit - FastAsyncWorldEdit-Core - 2.4.3 - provided - - - net.kyori - adventure-text-minimessage - - - - - com.fastasyncworldedit - FastAsyncWorldEdit-Bukkit - 2.4.3 - provided - - - FastAsyncWorldEdit-Core - * - - - - - ovh.uskyblock - uSkyBlock-Core - - - org.spigotmc - spigot-api - ${spigotapi.version} - true - provided - - - - com.sk89q.worldedit - worldedit-bukkit - ${worldedit.version} - provided - - - org.bukkit - bukkit - - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - - - package - - shade - - - false - true - - - dk.lockfuglsang.minecraft:po-utils - - - - - dk.lockfuglsang.minecraft - us.talabrek.ultimateskyblock.utils - - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - - diff --git a/uSkyBlock-Plugin/build.gradle.kts b/uSkyBlock-Plugin/build.gradle.kts new file mode 100644 index 000000000..414db6fee --- /dev/null +++ b/uSkyBlock-Plugin/build.gradle.kts @@ -0,0 +1,12 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + + +dependencies { + implementation(project(":uSkyBlock-API")) + implementation(project(":uSkyBlock-Core")) + implementation(project(":uSkyBlock-FAWE")) +} + +description = "uSkyBlock-Plugin" diff --git a/uSkyBlock-Plugin/pom.xml b/uSkyBlock-Plugin/pom.xml deleted file mode 100644 index a342cfdbd..000000000 --- a/uSkyBlock-Plugin/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - uSkyBlock - ovh.uskyblock - 3.2.0-SNAPSHOT - - 4.0.0 - jar - uSkyBlock-Plugin - - - uSkyBlock-${project.version} - - - maven-assembly-plugin - - - distro-assembly - compile - - single - - - - src/assembly/plugin.xml - - - - - - - maven-jar-plugin - - ${project.build.directory}/uSkyBlock-${project.version}-Plugin - - - - - - src/main/resources - true - - **/version.json - - - - src/main/resources - false - - **/version.json - - - - - - - - com.github.rlf - uSkyBlock-API - - - ovh.uskyblock - uSkyBlock-Core - - - ovh.uskyblock - uSkyBlock-FAWE - - - From 9ad044445be58411bcf703698f753d231caa2730 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:48:27 +0800 Subject: [PATCH 164/190] =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uSkyBlock-Core/src/main/po/zh_CN.po | 3107 +++++++++++++-------------- 1 file changed, 1471 insertions(+), 1636 deletions(-) diff --git a/uSkyBlock-Core/src/main/po/zh_CN.po b/uSkyBlock-Core/src/main/po/zh_CN.po index 241c0c894..4c8ba92de 100644 --- a/uSkyBlock-Core/src/main/po/zh_CN.po +++ b/uSkyBlock-Core/src/main/po/zh_CN.po @@ -6,325 +6,377 @@ msgid "" msgstr "" "Project-Id-Version: v2.3-HF3\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2015-04-27 13:13+0100\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2025-04-25 21:25+0800\n" "Last-Translator: Miku_Snow \n" "Language-Team: 915mc \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.7.6\n" +"X-Generator: Poedit 3.6\n" -msgid "d" -msgstr "天" - -msgid "h" -msgstr "小时" +#, java-format +msgid "§eYou do not have access (§4{0}§e)" +msgstr "§e您无权访问(§4{0}§e)" -msgid "m" -msgstr "分" +#, java-format +msgid "§eInvalid command: {0}" +msgstr "§e无效命令: {0}" -msgid "s" -msgstr "秒" +msgid "changes the language of the plugin, and reloads" +msgstr "更改插件的语言,并重新加载" #, java-format -msgid "{0,number,0}:{1,number,00}.{2,number,000}" -msgstr "" +msgid "§aSuccessfully changed language to §e{0}" +msgstr "§a已成功将语言更改为§e{0}" #, java-format -msgid "§f{0}x §7{1}" -msgstr "" +msgid "§cFailed to change language to §e{0}" +msgstr "§c无法将语言更改为§e{0}" -#, java-format -msgid "§7{0}" -msgstr "" +msgid "§9Supported Languages:\n" +msgstr "§9支持的语言:\n" #, java-format -msgid "§eYou do not have access (§4{0}§e)" -msgstr "" +msgid "§f{0} §7{1} §9 by {2} §7{3}\n" +msgstr "§f{0}§7{1}§9由{2}§7{3}\n" -#, java-format -msgid "§eInvalid command: {0}" -msgstr "" +msgid "§cUnable to locate any languages." +msgstr "§c找不到任何语言。" msgid "Command" -msgstr "" +msgstr "命令" msgid "Permission" -msgstr "" +msgstr "许可" msgid "Description" -msgstr "" +msgstr "描述" + +msgid "saves documentation of the commands to a file" +msgstr "将命令文档保存到文件中" + +#, java-format +msgid "Wrote documentation to {0}" +msgstr "为 {0} 编写文档" + +#, java-format +msgid "§4Error writing documentation: {0}" +msgstr "§4编写文档时出错: {0} " #, java-format msgid "§7Usage: {0}" -msgstr "" +msgstr "§7用法: {0} " #, java-format msgid "§7Use §3/{0} ? {1}§7 to display next page\n" -msgstr "" +msgstr "§7使用§3/{0}?{1} §7显示下一页\n" #, java-format msgid "§7Use §3/{0} ? {1} §7 to display previous page\n" -msgstr "" +msgstr "§7使用§3/{0}?{1} §7显示上一页\n" -msgid "saves documentation of the commands to a file" -msgstr "" +msgid "d" +msgstr "天" -#, java-format -msgid "Wrote documentation to {0}" -msgstr "" +msgid "h" +msgstr "小时" -#, java-format -msgid "§4Error writing documentation: {0}" -msgstr "" +msgid "m" +msgstr "分" -msgid "§cWither Despawned!§e It wandered too far from your island." -msgstr "" +msgid "s" +msgstr "秒" #, java-format -msgid "{0}''s Wither" -msgstr "" +msgid "{0,number,0}:{1,number,00}.{2,number,000}" +msgstr "{0,number,0}:{1,number,00}.{2,number,000}" -msgid "§eYou can not use another island''s portals!" -msgstr "" +#, java-format +msgid "§f{0}x §7{1}" +msgstr "§f{0}x §7{1}" -msgid "§eVillager-trading isn't allowed." -msgstr "" +#, java-format +msgid "§7{0}" +msgstr "§7{0}" -msgid "§eTrading isn't allowed on other islands. Do it in spawn." -msgstr "" +#, java-format +msgid "§4You can complete this {0} more time(s)." +msgstr "§4您可以再完成 {0} 次。" -msgid "§eRiding is only allowed on your own island!" -msgstr "" +#, java-format +msgid "§4Requirements will reset in {0} days." +msgstr "§4需求将在 {0} 天后重置." -msgid "§eYou cannot break vehicles while being a visitor!" -msgstr "" +#, java-format +msgid "§4Requirements will reset in {0} hours." +msgstr "§4任务将在{0} 小时后重置" -msgid "§4You can only convert obsidian once every 10 seconds" -msgstr "" +#, java-format +msgid "§4Requirements will reset in {0} minutes." +msgstr "§4任务将在{0} 分钟后重置" -msgid "§eChanging your obsidian back into lava. Be careful!" -msgstr "§e已经将你的黑曜石变为岩浆.请务必当心!" +msgid "§4This challenge is currently unavailable." +msgstr "§4此挑战目前不可用。" -msgid "§eYour inventory must have another empty space!" -msgstr "" +#, java-format +msgid "§4You can complete this again in {0} days." +msgstr "§4您可以在 {0} 天后再次完成此操作。" -msgid "§4It''s a bad idea to replace your lava!" -msgstr "§4替换岩浆真是一个§f'不错'§4的注意呢~" +#, java-format +msgid "§4You can complete this again in {0} hours." +msgstr "§4您可以在 {0} 小时内再次完成此操作。" -msgid "§eYou cannot hurt island-members." -msgstr "" +#, java-format +msgid "§4You can complete this again in {0} minutes." +msgstr "§4您可以在 {0} 分钟内再次完成此操作。" -msgid "§4That player has forbidden you from teleporting to their island." -msgstr "§4玩家禁止你传送到他们的岛屿上." +msgid "§eThis challenge requires:" +msgstr "§e此挑战需要:" -msgid "§4That island is §clocked.§e No teleporting to the island." -msgstr "" +msgid "§7and more..." +msgstr "§7以及更多..." + +msgid "§eItems will be traded for reward." +msgstr "§e物品将被交易以获得奖励。" #, java-format -msgid "" -"§4{0} is limited. §eScanning your island to see if you are allowed to place " -"more, please be patient" -msgstr "" +msgid "§eMust be within {0} meters." +msgstr "§e必须在 {0} 米以内。" -msgid "§e... Scanning complete, you can try again" -msgstr "" +msgid "§6Item Reward: §a" +msgstr "§6物品奖励:" #, java-format -msgid "" -"§4You''ve hit the {0} limit!§e You can''t have more of that type on your " -"island!§9 Max: {1,number}" -msgstr "" - -msgid "§eYou can only use spawn-eggs on your own island." -msgstr "" +msgid "§6Currency Reward: §a{0}" +msgstr "§6货币奖励: §a{0}" -msgid "§cYou have reached your spawn-limit for your island." -msgstr "" +#, java-format +msgid "§6Exp Reward: §a{0}" +msgstr "§6经验奖励: §a{0}" -msgid "§eVisitors can't drop items!" -msgstr "" +#, java-format +msgid "§dTotal times completed: §f{0}" +msgstr "§d总完成次数: §f{0}" #, java-format -msgid "Owner: {0}" -msgstr "" +msgid "§7Requires {0}" +msgstr "§7需要 {0} " -msgid "You cannot pick up other players' loot when you are a visitor!" -msgstr "" +#, java-format +msgid "§7Complete {0} more {1} §7challenges" +msgstr "§7完成 {0} 更多 {1} §7挑战" -msgid "§cBanned:§e You are banned from this island." -msgstr "" +#, java-format +msgid "§7Complete {0}" +msgstr "§7完成 {0} " -msgid "§cLocked:§e That island is locked! No entry allowed." -msgstr "" +msgid "to unlock this rank" +msgstr "解锁此排名" -msgid "Something went wrong saving the island and/or party data!" -msgstr "在存储岛屿或者团队记录的时候发生了一些错误!" +#, java-format +msgid "§4No challenge named {0} found" +msgstr "§4未找到名为 {0} 的挑战" -msgid "Converting data to UUID, this make take a while!" -msgstr "" +msgid "§4You must be on your island to do that!" +msgstr "§4你必须在你的岛屿上才能这样做!" -msgid "§cMAINTENANCE:§e uSkyBlock is currently in maintenance mode" -msgstr "" +#, java-format +msgid "§4The {0} challenge is not available yet!" +msgstr "§4 {0} 挑战尚不可用!" #, java-format -msgid "" -"§buSkyBlock§e depends on §9{0}§e >= §av{1}§e but only §cv{2}§e was found!\n" -msgstr "" +msgid "§4The {0} challenge is not repeatable!" +msgstr "§4挑战:§e{0} §4不可重复完成!" #, java-format -msgid "§buSkyBlock§e depends on §9{0}§e >= §av{1}" -msgstr "" +msgid "§4You cannot complete the {0} challenge again yet!" +msgstr "§4您还不能再次完成 {0} 挑战!" -msgid "§eYou do not have access to that island-schematic!" -msgstr "" +#, java-format +msgid "§eTrying to complete challenge §a{0}" +msgstr "§e尝试完成挑战§a {0} " -msgid "§4Player is already assigned to this island!" -msgstr "§4玩家早就已经分配给这个岛屿了!" +#, java-format +msgid "§4{0}" +msgstr "§4{0}" -msgid "§4You must be closer to your island to set your skyblock home!" -msgstr "§4你必须在岛屿上才能设置你的家!" +#, java-format +msgid "§4You must be standing within {0} blocks of all required items." +msgstr "§4在你周围 {0} 格以内必须包含挑战所需物品。" -msgid "§aYour skyblock home has been set to your current location." -msgstr "§a你岛屿家的位置已经设置在你当前位置." +#, java-format +msgid "§4Your island must be level {0} to complete this challenge!" +msgstr "§4您的岛屿必须达到 {0} 级,才能完成当前挑战!" -msgid "§4Your current location is not a safe home-location." -msgstr "" +#, java-format +msgid "§4Unknown type of challenge: {0}" +msgstr "§4未知难度的挑战: {0}" #, java-format msgid "" -"§7The pixies are busy changing the biome of your island to §9{0}§7, be " -"patient." -msgstr "" - -msgid "§cYour island is in the process of generating, you cannot create now." +"§eStill the following entities short:\n" +"{0}" msgstr "" +"§e你缺少以下物品完成此任务:\n" +"{0}" -msgid "Could not create your Island. Please contact a server moderator." -msgstr "无法为你创建岛屿.请联系管理员." +#, java-format +msgid " §4{0} §b{1}" +msgstr "§4{0}§b{1}" -msgid "§eGetting your island ready, please be patient, it can take a while." -msgstr "" +#, java-format +msgid "§eYou are the following items short:{0}" +msgstr "§e你缺少以下物品: {0}" -msgid "§cCommand is currently disabled!" -msgstr "" +#, java-format +msgid "§aYou have completed the {0} challenge!" +msgstr "§a你完成了挑战:§e {0}" #, java-format -msgid " §f{0}x §7{1}" -msgstr "" +msgid "§9{0}§f has completed the §9{1}§f challenge!" +msgstr "§9{0}§f已完成§9{1}§f挑战!" #, java-format -msgid "§eStill the following blocks short: {0}" -msgstr "§e任然缺少以下方块: {0}" +msgid "§eItem reward(s): §f{0}" +msgstr "§e物品奖励: §f{0}" #, java-format -msgid "§9{0}§7 timed out" -msgstr "§9{0}§7超时" +msgid "§eExp reward: §f{0,number,#.#}" +msgstr "§e经验奖励: §f{0,number,#.#}" #, java-format -msgid "" -"§eDoing §9{0}§e is §cRISKY§e. Repeat the command within §a{1}§e seconds to " -"accept!" -msgstr "§9{0}§e是§c危险的§e.请等待§a{1}§e秒后在这样做." +msgid "§eCurrency reward: §f{0,number,###.##} {1} §a ({2,number,##.##})%" +msgstr "§e货币奖励: §f{0,number,###.##} {1} §a ({2,number,##.##})%" -msgid "§4** You are entering a protected - but abandoned - island area." -msgstr "" +msgid "§eYour inventory is §4full§e. Items dropped on the ground." +msgstr "§e背包§4已满§e 多出的奖励物品将掉落到地上" -#, java-format -msgid "§d** You are entering §b{0}''s §disland." -msgstr "" +msgid "§e§lClick to complete this challenge." +msgstr "§e§l点击来完成这个挑战。" -msgid "§4** You are leaving an abandoned island." -msgstr "" +msgid "§4§lYou can't repeat this challenge." +msgstr "§4§l你无法重复完成这个挑战。" #, java-format -msgid "§d** You are leaving §b{0}''s §disland." -msgstr "" +msgid "Rank: {0}" +msgstr "排名: {0} " -msgid "§eYour island is now locked. Only your party members may enter." -msgstr "§e你的岛屿当前处于锁定状态.只有团队成员才能进入." +msgid "§fComplete most challenges in" +msgstr "§f完成大部分挑战在" -msgid "§4You must be the party leader to lock your island!" -msgstr "§4你必须为岛屿主人才能锁定岛屿!" +msgid "§fthis rank to unlock the next rank." +msgstr "§f这个难度中,才能解锁下一个等级。" -msgid "" -"§eYour island is unlocked and anyone may enter, however only you and your " -"party members may build or remove blocks." -msgstr "" -"§e你岛屿当前处于未锁定状态,s所有人都可以访问你的岛屿不过只有你和岛屿成员才能" -"进行建造." +msgid "§eClick here to show previous page" +msgstr "§e单击此处显示上一页" -msgid "§4You must be the party leader to unlock your island!" -msgstr "§4你必须得是岛屿的主人才能解锁你的岛屿!" +msgid "§eClick here to show next page" +msgstr "§e单击此处显示下一页" -#, java-format -msgid "§eWaiting for our turn §c{0,number,###}%" -msgstr "" +msgid "§4§lLocked Challenge" +msgstr "§4§l挑战锁定" + +msgid "Return" +msgstr "返回" + +msgid "Caps On" +msgstr "大写锁定已开启" #, java-format -msgid "§9Creating island...§e{0,number,###}%" -msgstr "" +msgid "§7Page {0}" +msgstr "§7第 {0} 页" -msgid "N/A" -msgstr "" +msgid "Config:" +msgstr "配置:" -msgid "§4§lLocked Challenge" -msgstr "§4§l挑战锁定" +msgid "§9Text Editor" +msgstr "§9文本编辑器" -msgid "READY" -msgstr "" +msgid "§eConfiguration saved and reloaded." +msgstr "§e配置已保存并重新加载。" -#, java-format -msgid "§4The {0} challenge is not available yet!" -msgstr "" +msgid "§cError! §9Unable to save config file!" +msgstr "§c错误!§9无法保存配置文件!" + +msgid "§3First Page" +msgstr "§3第一页" + +msgid "§3Last Page" +msgstr "§3最后一页" + +msgid "§cSave & Reload config" +msgstr "§c保存并重新加载配置" msgid "" -"§cWARNING:§e Could not transfer all the required items to your inventory!" +"§7Saves the settings to\n" +"§7file & reloads again.\n" +"§cNote: §7Use with care!" msgstr "" +"§7将设置保存到\n" +"§7文件并再次重新加载。\n" +"§c注意:§7请谨慎使用!" -msgid "§cNot enough items in chest to complete challenge!" -msgstr "" +msgid "§7 (readonly)" +msgstr "§7(只读)" -msgid "true" -msgstr "" +#, java-format +msgid "§c{0,number,#}" +msgstr "§c{0,number,#}" -msgid "false" -msgstr "" +#, java-format +msgid "§a+{0,number,#}" +msgstr "§a+{0,number,#}" + +#, java-format +msgid "§a{0,number,#}" +msgstr "§a{0,number,#}" + +#, java-format +msgid "&aLeft:&7 Increment with {0}" +msgstr "&aLeft:使用 {0} 递增7" + +#, java-format +msgid "&cRight-Click:&7 Set to {0}" +msgstr "&c右键单击:&7设置为 {0} " + +msgid "§9Integer Editor" +msgstr "§9整数编辑器" msgid "Challenge Menu" -msgstr "" +msgstr "挑战菜单" msgid "Change Biome" -msgstr "" +msgstr "更改生物群系" msgid "change the island''s biome." -msgstr "" +msgstr "改变岛上的生物群系" msgid "Toggle Island Lock" -msgstr "" +msgstr "岛屿锁" msgid "toggle the island''s lock." -msgstr "" +msgstr "锁定/解锁岛屿" msgid "Set Island Warp" -msgstr "" +msgstr "设置岛屿传送点" msgid "set the island''s warp." -msgstr "" +msgstr "设置岛屿传送点" msgid "" "set the island''s warp,\n" "which allows non-group\n" "members to teleport to\n" "the island." -msgstr "" +msgstr "设置岛屿传送点,岛屿未锁定时,非岛屿成员可以传送至此" msgid "Toggle Island Warp" -msgstr "" +msgstr "切换岛屿传送" msgid "toggle the island''s warp." -msgstr "" +msgstr "打开/关闭岛屿传送功能" msgid "" "toggle the island''s warp,\n" @@ -332,203 +384,54 @@ msgid "" "on or off at anytime, but\n" "not set the location." msgstr "" +"切换岛屿的传送功能,\n" +"可以随时开启或关闭,\n" +"不是设置传送点位置。" msgid "Invite Players" -msgstr "" +msgstr "邀请玩家" msgid "invite others to the island." -msgstr "" +msgstr "邀请其他人到岛上。" msgid "" "invite\n" "other players to the island if\n" "there is enough room for more\n" "members" -msgstr "" +msgstr "邀请" msgid "Kick Players" -msgstr "" +msgstr "踢出玩家" msgid "kick others from the island." -msgstr "" +msgstr "把其他人踢出岛屿" msgid "" "kick\n" "other players from the island,\n" "but they are unable to kick\n" "the island leader." -msgstr "" - -msgid "Ocean" -msgstr "" - -msgid "" -"The ocean biome is the basic\n" -"starting biome for all islands.\n" -"passive mobs like animals will\n" -"not spawn. Hostile mobs will\n" -"spawn normally." -msgstr "" - -msgid "Forest" -msgstr "" - -msgid "" -"The forest biome will allow\n" -"your island to spawn passive.\n" -"mobs like animals (including\n" -"wolves). Hostile mobs will\n" -"spawn normally." -msgstr "" - -msgid "Desert" -msgstr "" - -msgid "" -"The desert biome makes it so\n" -"that there is no rain or snow\n" -"on your island. Passive mobs\n" -"won't spawn. Hostile mobs will\n" -"spawn normally." -msgstr "" - -msgid "Jungle" -msgstr "" - -msgid "" -"The jungle biome is bright\n" -"and colorful. Passive mobs\n" -"(including ocelots) will\n" -"spawn. Hostile mobs will\n" -"spawn normally." -msgstr "" - -msgid "Swampland" -msgstr "" - -msgid "" -"The swamp biome is dark\n" -"and dull. Passive mobs\n" -"will spawn normally and\n" -"slimes have a small chance\n" -"to spawn at night depending\n" -"on the moon phase." -msgstr "" - -msgid "Taiga" -msgstr "" - -msgid "" -"The taiga biome has snow\n" -"instead of rain. Passive\n" -"mobs will spawn normally\n" -"(including wolves) and\n" -"hostile mobs will spawn." -msgstr "" - -msgid "Mushroom" -msgstr "" - -msgid "" -"The mushroom biome is\n" -"bright and colorful.\n" -"Mooshrooms are the only\n" -"mobs that will spawn.\n" -"No other passive or\n" -"hostile mobs will spawn." -msgstr "" - -msgid "Hell" -msgstr "" - -msgid "" -"The hell biome looks\n" -"dark and dead. Some\n" -"mobs from the nether will\n" -"spawn in this biome\n" -"(excluding ghasts and\n" -"blazes)." -msgstr "" - -msgid "Sky" -msgstr "" - -msgid "" -"The sky biome gives your\n" -"island a special dark sky.\n" -"Only endermen will spawn\n" -"in this biome." -msgstr "" - -msgid "Plains" -msgstr "" - -msgid "" -"The plains biome has rain\n" -"instead of snow. Passive\n" -"mobs will spawn normally\n" -"(including horses) and\n" -"hostile mobs will spawn." -msgstr "" - -msgid "Extreme Hills" -msgstr "" - -msgid "" -"The extreme hills biome.\n" -"Passive mobs will spawn \n" -"normally and hostile\n" -"mobs will spawn." -msgstr "" - -msgid "Flower Forest" -msgstr "" - -msgid "" -"The flower forest biome.\n" -"Passive mobs will spawn \n" -"normally and hostile\n" -"mobs will spawn." -msgstr "" - -msgid "Deep Ocean" -msgstr "" - -msgid "" -"The deep-ocean biome is an advanced\n" -"biome. Passive mobs like animals will\n" -"not spawn. Hostile mobs \n" -"(including Guardians) will\n" -"spawn normally." -msgstr "" - -msgid "Ice Plains" -msgstr "" - -msgid "" -"The ice-plains biome is an advanced biome.\n" -"Mobs will spawn naturally.\n" -"including polar-bears" -msgstr "" +msgstr "将其他玩家从岛上踢出,但他们无法踢出岛主。" msgid "Permissions" -msgstr "" +msgstr "权限" #, java-format msgid "{0} <{1}>" -msgstr "" +msgstr "{0} <{1}>" msgid "§9Player Permissions" -msgstr "" +msgstr "§9玩家权限" msgid "" "§eClick here to return to\n" "§eyour island group''s info." -msgstr "" +msgstr "§e单击此处返回" #, java-format msgid "§e{0}''§9s Permissions" -msgstr "" +msgstr "§e {0} “”§9s权限" msgid "" "§eHover over an icon to view\n" @@ -540,23 +443,23 @@ msgstr "" "§e即可更改权限状态." msgid "§fThis player §acan" -msgstr "" +msgstr "§f此玩家§acan" msgid "Click here to remove this permission." -msgstr "" +msgstr "单击此处删除此权限。" msgid "§fThis player §ccannot" -msgstr "" +msgstr "§f这个玩家§ccannot" msgid "Click here to grant this permission." -msgstr "" +msgstr "单击此处授予此权限。" msgid "Island Group Members" -msgstr "" +msgstr "岛屿成员列表" #, java-format msgid "Group Members: §2{0}§7/§e{1}" -msgstr "" +msgstr "岛屿成员:§2{0}§7/§e{1}" msgid "§aMore players can be invited to this island." msgstr "§a可以邀请更多的玩家加入岛屿." @@ -570,30 +473,32 @@ msgid "" "§eleader can change permissions\n" "§eby clicking a player''s icon." msgstr "" +"将鼠标悬停在玩家的图标上以查看其权限。\n" +"岛主可以通过点击玩家的图标来更改权限。" #, java-format msgid "§e{0}''s§9 Permissions" -msgstr "" +msgstr "§e {0} 的§9权限" msgid "Leader" -msgstr "" +msgstr "岛主" msgid "Member" -msgstr "" +msgstr "成员" #, java-format msgid "Can {0}" -msgstr "" +msgstr "可以 {0} " #, java-format msgid "Cannot {0}" -msgstr "" +msgstr "无法 {0} " msgid "§e" msgstr "§e<点击将更改玩家的权限>" msgid "Island Log" -msgstr "" +msgstr "岛屿日志" msgid "" "§eClick here to return to\n" @@ -605,63 +510,17 @@ msgstr "" msgid "§e§lIsland Log" msgstr "§e§l岛屿日志" -msgid "Island Biome" -msgstr "岛屿生物群系" - -#, java-format -msgid "Biome: {0}" -msgstr "" - -msgid "§2§lThis is your current biome." -msgstr "§2§l这是你当前的生物群系." - -msgid "§e§lClick to change to this biome." -msgstr "§e§l点击将会更改为这个生物群系." - -msgid "You cannot use this biome." -msgstr "" - -msgid "§2chunk" -msgstr "" - -msgid "§call" -msgstr "" - -#, java-format -msgid "§e{0}" -msgstr "" - -msgid "§c-" -msgstr "" - -msgid "Decrease radius of biome-change" -msgstr "" - -#, java-format -msgid "Current radius: {0}" -msgstr "" - -msgid "§2+" -msgstr "" - -msgid "Increase radius of biome-change" -msgstr "" - msgid "§7Current page" -msgstr "" - -#, java-format -msgid "§7Page {0}" -msgstr "" +msgstr "§7当前页面" msgid "§7First Page" -msgstr "" +msgstr "§7第一页" msgid "§7Last Page" -msgstr "" +msgstr "§7最后一页" msgid "Island Create Menu" -msgstr "" +msgstr "岛屿创建菜单" msgid "§a§lStart an Island" msgstr "§a§l开始岛屿生涯" @@ -676,21 +535,30 @@ msgid "" "building your island empire!\n" "§e§lClick here to start!" msgstr "" +"开启你的空岛之旅,\n" +"从创建自己的岛屿开始。\n" +"完成挑战以赚取物品和空岛币,\n" +"助力扩展你的空岛。\n" +"你可以邀请他人加入,\n" +"共同打造你的岛屿帝国!\n" +"§e§l点击此处开始!" msgid "§aClick to create!" -msgstr "" +msgstr "§a单击创建!" #, java-format msgid "" "§cNo access!\n" "§7({0})" msgstr "" +"§c禁止进入!\n" +"§7({0})" msgid "§a§lReturn to Spawn" -msgstr "" +msgstr "§a§l返回大厅" msgid "Teleport to the spawn area." -msgstr "" +msgstr "传送到大厅" msgid "§a§lJoin an Island" msgstr "§a§l加入一个岛屿" @@ -705,9 +573,14 @@ msgid "" "§e§lClick here to accept an invite!\n" "§e§l(You must be invited first)" msgstr "" +"想要加入另一个玩家的岛屿而不是自己创建一个吗?\n" +"如果另一个玩家邀请您去他们的岛屿,\n" +"您可以点击此处或使用§e/island accept§f 来加入他们。\n" +"§e§l点击此处接受邀请!\n" +"§e§l(您必须先被邀请)" msgid "Island Menu" -msgstr "" +msgstr "岛屿菜单" msgid "§a§lReturn Home" msgstr "§a§l返回你的岛屿" @@ -719,6 +592,10 @@ msgid "" "island using §b/island sethome\n" "§e§lClick here to return home." msgstr "" +"返回您的岛屿出生点。\n" +"您可以使用§b/island sethome\n" +"将您的家园点更改为您岛屿上的任何位置\n" +"§e§l点击此处返回岛屿。" msgid "§a§lChallenges" msgstr "§a§l挑战" @@ -729,12 +606,14 @@ msgid "" "to earn skybucks, items, perks,\n" "and titles." msgstr "" +"查看§9任务列表\n" +"完成任务以赚取天空币、物品、经验值和称号" msgid "§e§lClick here to view challenges." -msgstr "§e§l点击图标查询所有挑战." +msgstr "§e点击图标打开任务列表" msgid "§4§lChallenges disabled." -msgstr "§4§l挑战不可用" +msgstr "§4§l任务已锁定" msgid "§a§lIsland Level" msgstr "§a§l岛屿等级" @@ -751,13 +630,17 @@ msgid "" "§e§lClick here to refresh.\n" "§e§l(must be on island)" msgstr "" +"通过扩展您的空岛并完成某些挑战来提升岛屿等级。\n" +"更稀有的方块会为您的等级增加更多分数。\n" +"§e§l点击此处刷新。\n" +"§e§l(你必须在岛上)" msgid "Island Group" -msgstr "" +msgstr "岛屿队伍" #, java-format msgid "§eMembers: §2{0}/{1}" -msgstr "" +msgstr "§e成员:§2{0}/{1}" msgid "" "View the members of your island\n" @@ -766,25 +649,30 @@ msgid "" "can change the member permissions.\n" "§e§lClick here to view or change." msgstr "" +"查看您的岛屿队伍的成员及其权限。\n" +"如果您是岛主,您可以更改成员权限。\n" +"§e点击此处查看或更改。" msgid "Change Island Biome" -msgstr "" +msgstr "更改岛屿生物群落" #, java-format msgid "§eCurrent Biome: §b{0}" -msgstr "" +msgstr "§e当前生物群系:§b {0} " msgid "" "The island biome affects things\n" "like grass color and spawning\n" "of both animals and monsters." msgstr "" +"该岛屿生物群系会影响诸如草的颜色\n" +"以及动物和怪物的生成等事物。" msgid "§e§lClick here to change biomes." -msgstr "§e§l点击图标更改生物群系." +msgstr "§e点击图标更改生物群系." msgid "§c§lYou can't change the biome." -msgstr "§c§l你没有权限更改生物群系." +msgstr "§c你没有权限更改生物群系." msgid "§a§lIsland Lock" msgstr "§a§l岛屿锁定" @@ -800,7 +688,7 @@ msgstr "" "§f非岛屿成员将无法访问你的岛屿." msgid "§e§lClick here to unlock your island." -msgstr "§e§l点击这里将可以解锁你的岛屿." +msgstr "§e§l点击这里解锁你的岛屿." msgid "§c§lYou can't change the lock." msgstr "§c§l你无法更改锁定状态." @@ -861,6 +749,9 @@ msgid "" "biome, and warp changes.\n" "§e§lClick to view the log." msgstr "" +"查看您岛屿上的事件日志,\n" +"例如成员、生物群系和传送点的变化。\n" +"§e§l点击以查看日志。" msgid "§a§lChange Home Location" msgstr "§a§l更改岛屿家" @@ -871,6 +762,8 @@ msgid "" "this location.\n" "§e§lClick here to change." msgstr "" +"当你传送到你的岛屿时,你将被传送到这个位置。\n" +"§e§l点击此处进行更改。" msgid "§a§lChange Warp Location" msgstr "§a§l更改传送点" @@ -880,684 +773,674 @@ msgid "" "other players will be taken to\n" "this point when they teleport\n" "to your island." -msgstr "" +msgstr "当你启用岛屿传送时,其他玩家在传送到你的岛屿时将被带到此处。" msgid "§e§lClick here to change." -msgstr "" +msgstr "§e§l单击此处进行更改。" msgid "§c§lRestart Island" -msgstr "" +msgstr "§c重置岛屿" msgid "" "Restarts your island.\n" "§4WARNING! §cwill remove your items and island!" msgstr "" +"重置您的岛屿\n" +"§4 警告!§c 将移除您的所有物品和岛屿!" msgid "§c§lLeave Island" -msgstr "" +msgstr "退出岛屿" msgid "" "Leaves your island.\n" "§4WARNING! §cwill remove all your items!" msgstr "" +"离开你的岛屿。\n" +"§4 警告!§c 将移除您的所有物品" msgid "§cClick to leave" -msgstr "" +msgstr "§c点击退出" msgid "Island Restart Menu" -msgstr "" +msgstr "岛屿重启菜单" -msgid "Config:" -msgstr "" +msgid "§eYou do not have access to that island-schematic!" +msgstr "§e您无权访问该岛屿蓝图!" #, java-format msgid "§cClick within §9{0}§c to leave!" -msgstr "" +msgstr "§c点击§9 {0} §c离开!" msgid "§a§lReturn to the main menu" -msgstr "" +msgstr "§a§l返回主菜单" #, java-format msgid "§cClick within §9{0}§c to restart!" -msgstr "" +msgstr "§c单击§9 {0} §c重新启动!" msgid "§aClick to restart!" -msgstr "" +msgstr "§a单击重新启动!" + +msgid "true" +msgstr "启用" + +msgid "false" +msgstr "禁用" + +msgid "Either send a message directly to your group, or toggle it on/off." +msgstr "发送队内消息,或将其打开/关闭此功能" + +msgid "party" +msgstr "岛屿队伍" + +msgid "island" +msgstr "岛" #, java-format -msgid "§c{0,number,#}" -msgstr "" +msgid "§cToggled chat to {0} §aON" +msgstr "§c已将聊天切换到 {0} §aON" #, java-format -msgid "§a+{0,number,#}" -msgstr "" +msgid "§cRepeat §9{0}§c to toggle it off" +msgstr "§c重复§9{0}§c将其关闭" #, java-format -msgid "§a{0,number,#}" -msgstr "" - -#, java-format -msgid "&aLeft:&7 Increment with {0}" -msgstr "" - -#, java-format -msgid "&cRight-Click:&7 Set to {0}" -msgstr "" +msgid "§aToggled chat §cOFF§a for {0}" +msgstr "§a切换聊天§cOFF§a用于 {0} " -msgid "Return" -msgstr "" +msgid "§cCommand only available to players" +msgstr "§c命令仅对玩家可用" -msgid "§9Integer Editor" -msgstr "" +msgid "talk to your island party" +msgstr "与你的岛方交谈" -msgid "Caps On" -msgstr "" +msgid "But you are ALLLLLLL ALOOOOONE!" +msgstr "但你只有一个人~" -msgid "§9Text Editor" -msgstr "" +msgid "But you are Yelling in the wind!" +msgstr "但你只能对着空气自说自话~" -msgid "§eConfiguration saved and reloaded." -msgstr "" +msgid "But your fantasy friends are gone!" +msgstr "醒醒,不要幻想你有朋友了~" -msgid "§cError! §9Unable to save config file!" -msgstr "" +msgid "But you are Talking to your self!" +msgstr "你在自言自语啥呢,杂鱼~" -msgid "§3First Page" -msgstr "" +#, java-format +msgid "§cSorry! {0}" +msgstr "§c对不起!{0}" -msgid "§3Last Page" -msgstr "" +msgid "talk to players on your island" +msgstr "与岛上的玩家交谈" -msgid "§cSave & Reload config" -msgstr "" +msgid "READY" +msgstr "准备好了" msgid "" -"§7Saves the settings to\n" -"§7file & reloads again.\n" -"§cNote: §7Use with care!" -msgstr "" - -msgid "§7 (readonly)" -msgstr "" +"§cWARNING:§e Could not transfer all the required items to your inventory!" +msgstr "§c警告:§e无法将所有必需的物品转移到您的库存中!" -#, java-format -msgid "" -"§eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) " -"~ {6}" -msgstr "" +msgid "§cNot enough items in chest to complete challenge!" +msgstr "§c箱子里没有足够的物品来完成挑战!" -#, java-format -msgid "§4No importer named §e{0}§4 found" -msgstr "§4输入的名字§e{0}§4未找到" +msgid "Island Biome" +msgstr "岛屿生物群系" #, java-format -msgid "§eConverted {0}/{1} files in {2}" -msgstr "" +msgid "Biome: {0}" +msgstr "生物群系: {0} " -#, java-format -msgid "§7PlayerDB: Filtering {0} players from uuid2name.yml" -msgstr "" +msgid "§2§lThis is your current biome." +msgstr "§2§l这是你当前的生物群系." -#, java-format -msgid "§7 - {0,number,##}% ({1}/{2}) ~ {3}" -msgstr "" +msgid "§e§lClick to change to this biome." +msgstr "§e§l点击将会更改为这个生物群系." -#, java-format -msgid "§7PlayerDB: Filtered {0} names" -msgstr "" +msgid "§c-" +msgstr "§c-" -#, java-format -msgid "" -"§7 - MojangAPI:{4}: {0,number,##}% ({1}/{2}, failed:{3} ~ {5,number,##}%), " -"{6}" -msgstr "" +msgid "Decrease radius of biome change" +msgstr "减小生物群落变化半径" #, java-format -msgid "§7MojangAPI: Trying to fetch {0} players from Mojang" -msgstr "" +msgid "Current radius: {0}" +msgstr "当前半径: {0} " -msgid "SUCCESS" -msgstr "" +msgid "§2+" +msgstr "§2+" -msgid "FAILED" -msgstr "" +msgid "Increase radius of biome change" +msgstr "增加生物群落变化半径" -#, java-format -msgid "§7 - MojangAPI:§aCOMPLETED: {0}" -msgstr "" +msgid "§2chunk" +msgstr "§2章" -#, java-format -msgid "§7 - MojangAPI:§cERROR: {0}" -msgstr "" +msgid "§call" +msgstr "§呼叫" #, java-format -msgid "Too many requests for Mojangs API ({0} within {1}), sleeping {2}" -msgstr "" - -msgid "North" -msgstr "" - -msgid "North-East" -msgstr "" - -msgid "East" -msgstr "" +msgid "§e{0}" +msgstr "§e{0}" -msgid "South-East" -msgstr "" +msgid "§cBack to Main Menu" +msgstr "§c返回主菜单" -msgid "South" -msgstr "" +msgid "§eClick here to return to the main island screen." +msgstr "§e单击此处返回主岛屏幕。" -msgid "South-West" -msgstr "" +msgid "try to complete a challenge" +msgstr "尝试完成挑战" -msgid "West" -msgstr "" +msgid "§cCommand only available for players." +msgstr "§c命令仅适用于玩家。" -msgid "North-West" -msgstr "" +msgid "show information about the challenge" +msgstr "显示有关挑战的信息" -msgid "The island has been created." -msgstr "" +msgid "§eRank: " +msgstr "§eRank:" -#, java-format -msgid "§b{0}§d locked the island." -msgstr "" +msgid "§4This Challenge is not repeatable!" +msgstr "§4此任务仅可完成一次" -msgid "§4Since your island is locked, your incoming warp has been deactivated." -msgstr "§4因为你的岛屿处于锁定状态,岛屿传送点也将禁用." +msgid "§4You will lose all required items when you complete this challenge!" +msgstr "§4任务物品会从你的背包中扣除" #, java-format -msgid "§b{0}§d deactivated the island warp." -msgstr "§b{0}§d禁止了岛屿传送点." +msgid "" +"§4All required items must be placed on your island, within {0} blocks of you." +msgstr "§4所有必需物品必须放置在您的岛屿上,距离您{0}个方块以内。" #, java-format -msgid "§b{0}§d unlocked the island." -msgstr "" +msgid "§eTo complete this challenge, use §f/c c {0}" +msgstr "§e要完成此挑战,请使用§f/c c{0}" -#, java-format -msgid "§cSKY §f> §7 {0}" -msgstr "" +msgid "§4Invalid challenge name! Use /c help for more information" +msgstr "§4错误的挑战名!输入/c help 获取更多信息" -#, java-format -msgid "§b{0}§d has been removed from the island group." -msgstr "" +msgid "manage islands" +msgstr "管理岛屿" -#, java-format -msgid "§9{1} §7- {0}" -msgstr "" +msgid "protects the island" +msgstr "保护岛屿" -msgid "§9Creating an island at your location" -msgstr "" +msgid "delete the island (removes the blocks)" +msgstr "删除岛屿(移除所有方块)" -#, java-format -msgid "§9Creating an island §7{0}§9 of you" -msgstr "" +msgid "§9Deleted abandoned island at your current location." +msgstr "§9你当前位置的岛屿已经删除。" -msgid "§aCongratulations! §eYour island has appeared." +msgid "" +"§4Island at this location has members!\n" +"§eUse §9/usb island delete §e to delete it." msgstr "" +"§4这个岛上有其他成员!\n" +"§e输入§9/usb island delete <玩家名> §e来删除" -msgid "§cNote:§e Construction might still be ongoing." -msgstr "" +msgid "removes the player from the island" +msgstr "将玩家从岛上移除" -msgid "Use §9/is h§r or the §9/is§r menu to go there." -msgstr "" +msgid "adds the player to the island" +msgstr "将玩家添加到岛上" #, java-format -msgid "Unable to locate schematic {0}, contact a server-admin" -msgstr "" +msgid "§b{0}§d has joined your island group." +msgstr "§b{0}§d加入了你的岛屿团队。" #, java-format -msgid "§cWatchdog!§9 Unable to locate a chest within {0}, bailing out." -msgstr "" +msgid "§4No player named {0} found!" +msgstr "§4未找到名为 {0} 的玩家!" -msgid "UNKNOWN" -msgstr "" +msgid "" +"§4No valid island provided, either stand within one, or provide an island " +"name" +msgstr "§4未提供有效岛屿,请站在一个岛上,或提供岛屿名称" -msgid "ANIMAL" -msgstr "" +msgid "print out info about the island" +msgstr "列出此岛屿信息" -msgid "MONSTER" -msgstr "" +msgid "sets the biome of the island" +msgstr "设置岛上的生物群落" -msgid "VILLAGER" -msgstr "" +msgid "§4That player has no island." +msgstr "§4玩家仍未拥有岛屿。" -msgid "GOLEM" -msgstr "" +msgid "§4No valid island at your location" +msgstr "§4此处岛屿无效" -#, java-format -msgid "§c{0}" -msgstr "" +msgid "purges the island" +msgstr "清理该岛屿" -#, java-format -msgid "§7{0}: §a{1}§7 (max. {2})" -msgstr "" +msgid "§4Error! §9No valid island found for purging." +msgstr "§4错误!§9未找到可清理的有效岛屿。" -msgid "" -"§cThe island owning this piece of nether is being deleted! Sending you to " -"spawn." -msgstr "" +#, java-format +msgid "§cPURGE: §9Purged island at {0}" +msgstr "§cPURGE: §9 清理:在 {0} 处清理的岛屿" -msgid "§cThe island you are on is being deleted! Sending you to spawn." -msgstr "§c你所处的岛屿正在被删除!将你传送到出生点." +msgid "toggles the islands ignore status" +msgstr "切换岛屿忽略状态" #, java-format -msgid "§eWALL OF FAME (page {0} of {1}):" -msgstr "§e荣誉墙 (页数 {0} - {1}):" +msgid "§cSet {0}s island to be ignored on top-ten and purge." +msgstr "§cSet{0}s该岛在前十名中被忽视并被清理。" #, java-format -msgid "§4Top ten list is empty! Only islands above level {0} is considered." -msgstr "" - -msgid "§4Island level has been disabled, contact an administrator." -msgstr "§4岛屿等级系统未启用,请联系管理员." - -msgid "§a#%2d §7(%5.2f): §e%s §7%s" -msgstr "§a#%2d §7(%5.2f): §e%s §7%s" - -msgid "Click to warp to the island!" -msgstr "" +msgid "" +"§cRemoved ignore-flag of {0}s island, it will now show up on top-ten and " +"purge." +msgstr "§c删除了忽略标志{0}s,现在它将出现在前十名并被清理。" -#, java-format -msgid "§eYour rank is: §f{0}" -msgstr "§e你的排名是: §f{0}" +msgid "§4No valid player-name supplied." +msgstr "§4无效的玩家名" #, java-format -msgid "§7Complete {0} more {1} §7challenges" -msgstr "" +msgid "Removing {0} from island" +msgstr "从岛屿上移除了 {0}" #, java-format -msgid "§7Complete {0}" -msgstr "" +msgid "§eChanged biome of {0}s island to {1}." +msgstr "§e将 {0} 的岛屿的生物群系更改为 {1}" -msgid "to unlock this rank" -msgstr "" +msgid "§aYou may need to go to spawn, or relog, to see the changes." +msgstr "§a你需要返回出生点,或者重新登录才能看到改变。" #, java-format -msgid "§4You can complete this {0} more time(s)." -msgstr "" +msgid "§e{0} has had their biome changed to {1}." +msgstr "§e{0} 将他们的生物群系更改为了 {1}" #, java-format -msgid "§4Requirements will reset in {0} days." -msgstr "§4需求将在 {0} 天后重置." +msgid "§eRemoving {0}''s island." +msgstr "§e移除了 {0} 的岛屿。" + +msgid "Error: That player does not have an island!" +msgstr "错误: 玩家未拥有岛屿。" #, java-format -msgid "§4Requirements will reset in {0} hours." -msgstr "§4需求将在 {0} 小时后重置" +msgid "§e{0}s island at {1} has been protected" +msgstr "§e{0} 的岛屿在 {1} 被保护" #, java-format -msgid "§4Requirements will reset in {0} minutes." -msgstr "§4需求将在 {0} 分钟后重置" +msgid "§4{0}s island at {1} was already protected" +msgstr "§4{0}s位于{1}的岛屿已经受到保护" -msgid "§4This challenge is currently unavailable." -msgstr "" +msgid "flushes all caches to files" +msgstr "将所有缓存刷新为文件" #, java-format -msgid "§4You can complete this again in {0} days." -msgstr "" +msgid "" +"§eFlushed §a{0} islands§e, §b{1} players and §6{2} challenge-completions." +msgstr "§eFlushed§a {0} 个岛屿§e、§b {1} 个玩家和§6 {2} 个挑战完成。" -#, java-format -msgid "§4You can complete this again in {0} hours." -msgstr "" +msgid "Controls player-cooldowns" +msgstr "控制玩家冷却时间" + +msgid "clears the cooldown on a command (* = all)" +msgstr "根据命令清除冷却时间(*=all)" + +msgid "§eThe player is not currently online" +msgstr "§e玩家未在线" #, java-format -msgid "§4You can complete this again in {0} minutes." -msgstr "" +msgid "Cleared cooldown on {0} for {1}" +msgstr "清除冷却时间在{0} ~ {1}" -msgid "§eThis challenge requires:" -msgstr "" +#, java-format +msgid "No active cooldown on {0} for {1} detected!" +msgstr "在{0} ~ {1} 之间没有活跃的冷却时间" -msgid "§7and more..." -msgstr "" +msgid "Invalid command supplied, only restart and biome supported!" +msgstr "无效的命令,只支持restart 和 biome" -msgid "§eItems will be traded for reward." -msgstr "" +msgid "restarts the cooldown on the command" +msgstr "根据命令重新启动冷却" #, java-format -msgid "§eMust be within {0} meters." -msgstr "" +msgid "§eReset cooldown on {0} for {1}§e to {2} seconds" +msgstr "§e重置冷却时间在{0} ~ {1} §e ~ {2} 秒" -msgid "§6Item Reward: §a" -msgstr "§6物品奖励:" +msgid "lists all the active cooldowns" +msgstr "列出所有活动冷却" -#, java-format -msgid "§6Currency Reward: §a{0}" -msgstr "§6货币奖励: §a{0}" +msgid "§eCmd Cooldown" +msgstr "§e 指令冷却时间" #, java-format -msgid "§6Exp Reward: §a{0}" -msgstr "§6经验奖励: §a{0}" +msgid "§a{0} §c{1}" +msgstr "§a{0} §c{1}" #, java-format -msgid "§dTotal times completed: §f{0}" -msgstr "§d总完成次数: §f{0}" +msgid "§eNo active cooldowns for §9{0}§e found." +msgstr "§e没有活跃的冷却时间 §9{0} 被找到" -#, java-format -msgid "§7Requires {0}" -msgstr "" +msgid "region manipulations" +msgstr "区域操纵" -#, java-format -msgid "§4No challenge named {0} found" -msgstr "" +msgid "shows the borders of the current island" +msgstr "显示了当前岛屿的边界" -msgid "§4You must be on your island to do that!" -msgstr "§4你必须在你的岛屿上才能这样做!" +msgid "§eNo island found at your current location" +msgstr "§e 在您当前位置未找到岛屿" -#, java-format -msgid "§4The {0} challenge is not repeatable!" -msgstr "§4挑战:§e{0} §4不可重复完成!" +msgid "§eCan only be executed as a player" +msgstr "§e只能作为玩家执行" -#, java-format -msgid "§4You cannot complete the {0} challenge again yet!" -msgstr "" +msgid "shows the borders of the current chunk" +msgstr "显示当前块的边界" -#, java-format -msgid "§eTrying to complete challenge §a{0}" -msgstr "" +msgid "shows the borders of the inner-chunks" +msgstr "显示了内部块的边界" -#, java-format -msgid "§4{0}" -msgstr "§4{0}" +msgid "shows the non-chunk-aligned borders" +msgstr "显示了非块对齐的边框" -#, java-format -msgid "§4You must be standing within {0} blocks of all required items." -msgstr "§4在你周围 {0} 格以内必须包含挑战所需物品。" +msgid "shows the borders of the outer-chunks" +msgstr "显示了外部块的边界" -#, java-format -msgid "§4Your island must be level {0} to complete this challenge!" -msgstr "§4您的岛屿必须达到 {0} 级,才能完成当前挑战!" +msgid "hides the regions again" +msgstr "再次隐藏区域" -#, java-format -msgid "§4Unknown type of challenge: {0}" -msgstr "§4未知难度的挑战: {0}" +msgid "§eStopped displaying regions" +msgstr "§电子停止显示区域" -#, java-format -msgid "" -"§eStill the following entities short:\n" -"{0}" -msgstr "" -"§e任然缺少以下物品:\n" -"{0}" +msgid "§eNo currently shown regions for this player" +msgstr "§目前没有显示此玩家的区域" -#, java-format -msgid " §4{0} §b{1}" -msgstr "" +msgid "set the ticks between animations" +msgstr "设置动画之间的刻度" #, java-format -msgid "§eYou are the following items short:{0}" -msgstr "§e你缺少以下物品: {0}" +msgid "§eAnimation-tick changed to {0}." +msgstr "§eAnimation标记更改为 {0} 。" -#, java-format -msgid "§aYou have completed the {0} challenge!" -msgstr "§a你完成了挑战:§e {0}" +msgid "§eAnimation-tick must be a valid integer." +msgstr "§eAnimation勾号必须是有效整数。" -#, java-format -msgid "§9{0}§f has completed the §9{1}§f challenge!" -msgstr "" +msgid "refreshes the existing animations" +msgstr "刷新现有动画" -#, java-format -msgid "§eItem reward(s): §f{0}" -msgstr "§e物品奖励: §f{0}" +msgid "teleport to another players island" +msgstr "传送到另一个玩家岛" -#, java-format -msgid "§eExp reward: §f{0,number,#.#}" -msgstr "§e经验奖励: §f{0,number,#.#}" +msgid "§4Only supported for players" +msgstr "§4近支持玩家" + +msgid "§4That player does not have an island!" +msgstr "§4玩家仍未拥有岛屿。" #, java-format -msgid "§eCurrency reward: §f{0,number,###.##} {1} §a ({2,number,##.##})%" -msgstr "§e货币奖励: §f{0,number,###.##} {1} §a ({2,number,##.##})%" +msgid "§aTeleporting to {0}''s island." +msgstr "§a 传送到 {0}的岛屿。" -msgid "§eYour inventory is §4full§e. Items dropped on the ground." -msgstr "§e背包§4已满§e。奖励物品掉落到了地上。" +msgid "various WorldGuard utilities" +msgstr "各种WorldGuard实用程序" -msgid "§e§lClick to complete this challenge." -msgstr "§e§l点击来完成这个挑战。" +msgid "refreshes the chunks around the player" +msgstr "刷新玩家周围的区块" -msgid "§4§lYou can't repeat this challenge." -msgstr "§4§l你无法重复完成这个挑战。" +msgid "§eResending chunks to the client" +msgstr "§e重新发送区块数据至客户端" + +msgid "load the region chunks" +msgstr "加载区域块" #, java-format -msgid "Rank: {0}" -msgstr "" +msgid "§eLoading chunks at {0}" +msgstr "§e加载区块在{0}" -msgid "§fComplete most challenges in" -msgstr "§f完成大部分挑战在" +#, java-format +msgid "§eUnloading chunks at {0}" +msgstr "§e卸载区块在{0}" -msgid "§fthis rank to unlock the next rank." -msgstr "§f这个难度中,才能解锁下一个等级。" +msgid "update the WG regions" +msgstr "更新工作组区域" -msgid "§eClick here to show previous page" -msgstr "" +#, java-format +msgid "§eIsland world-guard regions updated for {0}" +msgstr "§e岛屿世界保护区域已更新为{0}" -msgid "§eClick here to show next page" -msgstr "" +msgid "§eNo island found at your location!" +msgstr "§在您的位置没有发现小岛!" -msgid "But you are ALLLLLLL ALOOOOONE!" -msgstr "" +msgid "refreshes the chunk around the player" +msgstr "刷新玩家周围的区块" -msgid "But you are Yelling in the wind!" -msgstr "" +msgid "advanced info about items" +msgstr "有关项目的高级信息" -msgid "But your fantasy friends are gone!" -msgstr "" +msgid "shows the component format for the currently held item" +msgstr "显示当前持有项目的组件格式" -msgid "But you are Talking to your self!" -msgstr "" +msgid "§cNo item in hand!" +msgstr "§c手中没有物品!" #, java-format -msgid "§cSorry! {0}" -msgstr "" +msgid "§eInfo for §9{0}" +msgstr "§9 {0} 的信息" -msgid "Either send a message directly to your group, or toggle it on/off." -msgstr "" +#, java-format +msgid "§7 - name: §9{0}" +msgstr "§7-名称:§9{0}" -msgid "party" +msgid "manage orphans" msgstr "" -msgid "island" +msgid "count orphans" msgstr "" #, java-format -msgid "§cToggled chat to {0} §aON" -msgstr "" +msgid "§e{0} old island locations will be used before new ones." +msgstr "§e{0} 旧的岛屿位置将会被新岛屿所替换。" -#, java-format -msgid "§cRepeat §9{0}§c to toggle it off" +msgid "clear orphans" msgstr "" -#, java-format -msgid "§aToggled chat §cOFF§a for {0}" -msgstr "" +msgid "§eClearing all old (empty) island locations." +msgstr "§e清理所有旧(空)的岛屿坐标。" -msgid "§cCommand only available to players" +msgid "list orphans" msgstr "" -msgid "talk to your island party" +msgid "§eNo orphans currently registered." msgstr "" -msgid "talk to players on your island" -msgstr "" +#, java-format +msgid "§eOrphans ({0}/{1}): {2}" +msgstr "§eOrphans ({0}/{1}): {2}" -msgid "manually update the top 10 list" -msgstr "" +msgid "open GUI for config" +msgstr "打开GUI进行配置" -msgid "§eGenerating the Top Ten list" -msgstr "§e生存排行榜前十名单" +msgid "searches config for a specific key" +msgstr "在配置中搜索特定密钥" -msgid "§eFinished generation of the Top Ten list" -msgstr "§e排行榜前十名单生成完毕" +#, java-format +msgid "§c{0}§9" +msgstr "§c{0}§9" -msgid "purges all abandoned islands" -msgstr "" +#, java-format +msgid "§9{0}§8: §e{1}" +msgstr "§9{0}§8:§e{1}" -msgid "§4You must provide the age in days to purge!" -msgstr "§4你必须指定一个天数来删除。" +#, java-format +msgid "Found the following matching {0}:" +msgstr "找到以下匹配项 {0} :" -msgid "§4The level must be a valid number" -msgstr "" +msgid "§a
" +msgstr "§a<区域>" #, java-format -msgid "" -"§eFinding all islands that have been abandoned for more than {0} days below " -"level {1}" -msgstr "" +msgid "§3{0,number,#.##}" +msgstr "§3{0,number,#.##}" #, java-format -msgid "§4PURGE:§e Do §9usb purge confirm§e within {0} to accept." -msgstr "" +msgid "§2{0}" +msgstr "§2{0}" -msgid "§4Trying to abort purge" -msgstr "" +msgid "§eInvalid configuration name" +msgstr "§e有效配置名称" -msgid "§4Purge aborted!" -msgstr "" +msgid "set a player''s island to your location" +msgstr "将玩家的岛屿设置为您的位置" -msgid "§4A purge is already running.§e Either §9confirm§e or §9stop§e it." -msgstr "" +#, java-format +msgid "§aSet {0}''s island to the current island." +msgstr "§a将 {0} 的岛屿设置为当前岛屿。" -msgid "§4Starting purge..." -msgstr "" +msgid "§4Island not found: unable to set the island!" +msgstr "§4未找到岛屿:无法设置岛屿!" -msgid "Controls player-cooldowns" -msgstr "" +#, java-format +msgid "§eInvalid player {0} supplied." +msgstr "§e无效的玩家 {0}" -msgid "clears the cooldown on a command (* = all)" -msgstr "" +msgid "toggles maintenance mode" +msgstr "切换维护模式" -msgid "§eThe player is not currently online" -msgstr "§e玩家未在线" +msgid "§cMAINTENANCE: §aActivated§e all uSkyBlock features currently disabled." +msgstr "§c维护:§a激活§e当前禁用的所有uSkyBlock功能。" -#, java-format -msgid "Cleared cooldown on {0} for {1}" -msgstr "清除冷却时间在{0} ~ {1}" +msgid "" +"§cMAINTENANCE: §4Deactivated§e all uSkyBlock features back to operational." +msgstr "§c维护:§4停用§e所有uSkyBlock功能恢复运行。" -#, java-format -msgid "No active cooldown on {0} for {1} detected!" -msgstr "在{0} ~ {1} 之间没有活跃的冷却时间" +msgid "§cMaintenance mode can only be changed from console!" +msgstr "§c维护模式只能从控制台更改!" -msgid "Invalid command supplied, only restart and biome supported!" -msgstr "无效的命令,只支持restart 和 biome" +msgid "protects all islands (time consuming)" +msgstr "保护所有岛屿(耗时)" -msgid "restarts the cooldown on the command" +msgid "§cTrying to abort protect-all task." +msgstr "§c试图中止保护所有任务。" + +msgid "" +"§4Sorry!§e A protect-all is already running. Let it complete first, or use " +"§9usb protectall §cstop" msgstr "" +"§4抱歉!§e 一个全方位保护程序已经在运行。请先让它完成,或者使用 §9usb " +"protectall stop 命令来停止它。" -#, java-format -msgid "§eReset cooldown on {0} for {1}§e to {2} seconds" -msgstr "§e重置冷却时间在{0} ~ {1} §e ~ {2} 秒" +msgid "§eStarting a protect-all task. It will take a while." +msgstr "§e开始执行 全局保护,将会花费一定时间。" -msgid "lists all the active cooldowns" -msgstr "" +msgid "manually update the top 10 list" +msgstr "手动更新前10名列表" -msgid "§eCmd Cooldown" -msgstr "§e 指令冷却时间" +msgid "§eGenerating the Top Ten list" +msgstr "§e生存排行榜前十名单" -#, java-format -msgid "§a{0} §c{1}" -msgstr "§a{0} §c{1}" +msgid "§eFinished generation of the Top Ten list" +msgstr "§e排行榜前十名单生成完毕" #, java-format -msgid "§eNo active cooldowns for §9{0}§e found." -msgstr "§e没有活跃的冷却时间 §9{0} 被找到" - -msgid "toggles maintenance mode" -msgstr "" +msgid "" +"- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}" +msgstr "- 清理:{0,number,##}%({1}/{2}),已用时间 {3},预计完成时间约 ~{4}" -msgid "§cMAINTENANCE: §aActivated§e all uSkyBlock features currently disabled." -msgstr "" +msgid "§4PURGE:§9 Finished purging abandoned islands." +msgstr "§4清理:§9已完成对废弃岛屿的清理。" -msgid "" -"§cMAINTENANCE: §4Deactivated§e all uSkyBlock features back to operational." -msgstr "" +msgid "§4PURGE:§9 Aborted purging abandoned islands." +msgstr "§4清理:§9废弃岛屿的清理被中止。" -msgid "§cMaintenance mode can only be changed from console!" -msgstr "" +#, java-format +msgid "§7- SCANNING: {0,number,##}% ({1}/{2} failed: {3}) ~ {4}" +msgstr "§7-扫描: {0,number,##}% ({1}/{2} 失败: {3}) ~ {4}" -msgid "controls async jobs" -msgstr "" +msgid "§4PURGE:§9 Scanning aborted." +msgstr "§4清理:§9扫描中止。" -msgid "§9Job Statistics" +#, java-format +msgid "" +"§4PURGE:§9 Scanning done, found {0} candidates, below level {1}, ready for " +"purgatory." msgstr "" +"§4PURGE:§9 扫描已完成,发现 {0} 个候选对象,低于 {1} 级,准备进入下界。" -msgid "§7----------------" -msgstr "" +msgid "§cABORTED:§e Protect-All was aborted!" +msgstr "§cABORTED:§e保护所有已中止!" -msgid "#" -msgstr "" +#, java-format +msgid "§eCompleted protect-all in {0}, {1} new regions were created!" +msgstr "§已在{0}, {1} 个新区域中完成全部保护!" -msgid "ms/job" -msgstr "" +msgid "shows perk-information" +msgstr "显示福利信息" -msgid "ms/tick" -msgstr "" +msgid "shows a specific players perks" +msgstr "显示特定玩家的福利" -msgid "ticks" -msgstr "" +#, java-format +msgid "§4No player named {0} was found!" +msgstr "§4没有名字为 {0} 的玩家被找到" -msgid "act" -msgstr "" +#, java-format +msgid "additional perks {0}" +msgstr "额外福利{0}" -msgid "time" -msgstr "" +msgid "advanced command for getting island-data" +msgstr "获取岛屿数据的高级命令" -msgid "name" -msgstr "" +#, java-format +msgid "§eCurrent value for {0} is ''{1}''" +msgstr "§e{0}的e当前值为“{1}”" #, java-format -msgid "§ePlayer {0} has no island!" -msgstr "§e玩家 {0} 还未获得岛屿!" +msgid "§cUnable to get state for {0}" +msgstr "§c无法获取{0}的状态" #, java-format -msgid "§eInvalid player {0} supplied." -msgstr "§e无效的玩家 {0}" +msgid "§eValid fields are {0}" +msgstr "§eValid字段为{0}" -msgid "flushes all caches to files" -msgstr "" +msgid "control debugging" +msgstr "控制调试" -#, java-format -msgid "" -"§eFlushed §a{0} islands§e, §b{1} players and §6{2} challenge-completions." -msgstr "" +msgid "set debug-level" +msgstr "设置调试级别" -msgid "tries to fix the the area of flatland." -msgstr "" +msgid "toggle debug-logging" +msgstr "切换调试日志记录" -msgid "§4No valid island found" -msgstr "§4没有找到有效的岛屿" +msgid "§4Logging wasn't active, so you can't disable it!" +msgstr "§4记录未启用,所以你无法关闭。" -#, java-format -msgid "§4No flatland detected at {0}''s island!" -msgstr "§4在{0} 的岛上未检测到平地。" +msgid "flush current content of the logger to file." +msgstr "将记录器的当前内容刷新到文件中。" -msgid "manage orphans" -msgstr "" +msgid "§eLog-file has been flushed." +msgstr "§e日志文件已经更新。" -msgid "count orphans" -msgstr "" +msgid "§4Logging is not enabled, use §d/usb debug enable" +msgstr "§4记录未启用,输入§d/usb debug 启用" -#, java-format -msgid "§e{0} old island locations will be used before new ones." -msgstr "§e{0} 旧的岛屿位置将会被新岛屿所替换。" +msgid "§4Invalid argument, try INFO, FINE, FINER, FINEST" +msgstr "§4未知参数,请尝试 INFO, FINE, FINER, FINEST" -msgid "clear orphans" -msgstr "" +msgid "§eLogging disabled!" +msgstr "§e记录已经关闭" -msgid "§eClearing all old (empty) island locations." -msgstr "§e清除所有旧(空)的岛屿坐标。" +msgid "advanced command for setting island-data" +msgstr "设置岛屿数据的高级命令" -msgid "list orphans" -msgstr "" +#, java-format +msgid "§c{0} was set to ''{1}''" +msgstr "§c{0}已设置为“{1}”" -msgid "§eNo orphans currently registered." -msgstr "" +#, java-format +msgid "§cUnable to set field {0} to ''{1}''" +msgstr "§c无法将字段{0}设置为“{1}”" #, java-format -msgid "§eOrphans ({0}/{1}): {2}" -msgstr "" +msgid "§cUnable to set field {0} to ''{1}'', a number was expected" +msgstr "§c无法将字段{0}设置为“{1}”,需要一个数字" + +#, java-format +msgid "§cInvalid field {0}" +msgstr "§c无效字段{0}" msgid "transfer leadership to another player" -msgstr "" +msgstr "将领导权转移给另一名球员" #, java-format msgid "§4Player {0} has no island to transfer!" @@ -1573,621 +1456,575 @@ msgstr "" #, java-format msgid "§bLeadership transferred by {0}§b to {1}" -msgstr "§b岛屿主人由{0} 变更为{1}" +msgstr "§b岛主已由{0} 变更为{1}" -msgid "open GUI for config" -msgstr "" +msgid "purges all abandoned islands" +msgstr "清理所有废弃岛屿" -msgid "searches config for a specific key" -msgstr "" +msgid "§4You must provide the age in days to purge!" +msgstr "§4你必须指定一个天数来删除。" -#, java-format -msgid "§c{0}§9" -msgstr "" +msgid "§4The level must be a valid number" +msgstr "§4级别必须是有效数字" #, java-format -msgid "§9{0}§8: §e{1}" -msgstr "" +msgid "" +"§eFinding all islands that have been abandoned for more than {0} days below " +"level {1}" +msgstr "§e查找级别{0}以下被遗弃超过{1}天的所有岛屿" #, java-format -msgid "Found the following matching {0}:" -msgstr "" +msgid "§4PURGE:§e Do §9usb purge confirm§e within {0} to accept." +msgstr "§4清理:§e执行§9usb purge comfirm§e在{0}内接受。" -msgid "§a
" -msgstr "" +msgid "§4Trying to abort purge" +msgstr "§4试图中止清理" + +msgid "§4Purge aborted!" +msgstr "§4清理中止!" + +msgid "§4A purge is already running.§e Either §9confirm§e or §9stop§e it." +msgstr "§4A清理已在运行。§e§9确认§e或§9停止§e。" + +msgid "§4Starting purge..." +msgstr "§4开始清洗。。。" + +msgid "various chunk commands" +msgstr "各种区块命令" + +msgid "regenerate current chunk" +msgstr "重新生成当前区块" #, java-format -msgid "§3{0,number,#.##}" -msgstr "" +msgid "successfully regenerated chunk at {0},{1}" +msgstr "已成功在{0}、{1}处重新生成区块" + +msgid "unload current chunk" +msgstr "卸载当前区块" #, java-format -msgid "§2{0}" -msgstr "" +msgid "successfully unloaded chunk at {0},{1}" +msgstr "已成功卸载{0}、{1}处的区块" -msgid "§eInvalid configuration name" -msgstr "" +#, java-format +msgid "§4FAILED!§e could not unload chunk at {0},{1}" +msgstr "§4失败!§e无法在{0}、{1}卸载区块" -msgid "teleport to another players island" -msgstr "" +msgid "load current chunk" +msgstr "正在加载所在区块" -msgid "§4Only supported for players" -msgstr "§4近支持玩家" +#, java-format +msgid "loaded chunk at {0},{1}" +msgstr "已在{0}、{1}加载块" -msgid "§4That player does not have an island!" -msgstr "§4玩家仍未拥有岛屿。" +msgid "only available for players" +msgstr "仅适用于玩家" #, java-format -msgid "§aTeleporting to {0}''s island." -msgstr "" +msgid "§4ERROR:§e {0}" +msgstr "§4错误:§e{0}" -msgid "various WorldGuard utilities" -msgstr "" +msgid "imports players and islands from other formats" +msgstr "从其他格式导入玩家和岛屿" -msgid "refreshes the chunks around the player" -msgstr "" +msgid "Manage challenges for a player" +msgstr "管理玩家的挑战" -msgid "§eResending chunks to the client" -msgstr "§e重新发送区块数据至客户端" +msgid "resets the challenge for the player" +msgstr "为玩家重置挑战" -msgid "load the region chunks" -msgstr "" +msgid "§4Challenge has never been completed" +msgstr "§4挑战从未完成过" #, java-format -msgid "§eLoading chunks at {0}" -msgstr "§e加载区块在{0}" +msgid "§echallenge: {0} has been reset for {1}" +msgstr "§e挑战: {0} 已经为玩家 {1} 重置" + +msgid "resets all challenges for the player" +msgstr "重置玩家的所有挑战" #, java-format -msgid "§eUnloading chunks at {0}" -msgstr "§e卸载区块在{0}" +msgid "§e{0} has had all challenges reset." +msgstr "§e{0} 的所有挑战已经重置" -msgid "update the WG regions" -msgstr "" +msgid "complete all challenges in the rank" +msgstr "完成排名中的所有挑战" #, java-format -msgid "§eIsland world-guard regions updated for {0}" -msgstr "" +msgid "§4Challenge {0} has already been completed" +msgstr "§4挑战{0}已完成" -msgid "§eNo island found at your location!" -msgstr "" +#, java-format +msgid "§eChallenge {0} has been completed for {1}" +msgstr "§e挑战 {0} 已为 {1} 完成" -msgid "refreshes the chunk around the player" -msgstr "" +#, java-format +msgid "§4No challenge named {0} was found!" +msgstr "§4挑战: {0} 未找到!" -msgid "region manipulations" -msgstr "" +#, java-format +msgid "§4No rank named {0} was found!" +msgstr "§4未找到名为{0}的排名!" -msgid "shows the borders of the current island" -msgstr "" +msgid "displays version information" +msgstr "显示版本信息" -msgid "§eNo island found at your current location" -msgstr "" +msgid "controls async jobs" +msgstr "控制异步作业" -msgid "§eCan only be executed as a player" -msgstr "" +msgid "§9Job Statistics" +msgstr "§9工作统计" -msgid "shows the borders of the current chunk" -msgstr "" +msgid "§7----------------" +msgstr "§7----------------" -msgid "shows the borders of the inner-chunks" -msgstr "" +msgid "#" +msgstr "#" -msgid "shows the non-chunk-aligned borders" -msgstr "" +msgid "ms/job" +msgstr "ms/job" -msgid "shows the borders of the outer-chunks" -msgstr "" - -msgid "hides the regions again" -msgstr "" +msgid "ms/tick" +msgstr "ms/tick" -msgid "§eStopped displaying regions" -msgstr "" +msgid "ticks" +msgstr "ticks" -msgid "§eNo currently shown regions for this player" -msgstr "" +msgid "act" +msgstr "行为" -msgid "set the ticks between animations" -msgstr "" +msgid "time" +msgstr "时间" -#, java-format -msgid "§eAnimation-tick changed to {0}." -msgstr "" +msgid "name" +msgstr "名称" -msgid "§eAnimation-tick must be a valid integer." -msgstr "" +msgid "tries to fix the the area of flatland." +msgstr "试图修复平地的面积。" -msgid "refreshes the existing animations" -msgstr "" +msgid "§4No valid island found" +msgstr "§4没有找到有效的岛屿" #, java-format -msgid "" -"- PURGING: {0,number,##}% ({1}/{2}), elapsed {3}, estimated completion ~{4}" -msgstr "" +msgid "§4No flatland detected at {0}''s island!" +msgstr "§4在{0} 的岛上未检测到平地。" -msgid "§4PURGE:§9 Finished purging abandoned islands." -msgstr "" +msgid "reload configuration from file." +msgstr "从文件重新加载配置。" -msgid "§4PURGE:§9 Aborted purging abandoned islands." -msgstr "" +msgid "§eConfiguration reloaded from file." +msgstr "§e配置重读。" #, java-format -msgid "§7- SCANNING: {0,number,##}% ({1}/{2} failed: {3}) ~ {4}" -msgstr "" +msgid "§ePlayer {0} has no island!" +msgstr "§e玩家 {0} 还未获得岛屿!" -msgid "§4PURGE:§9 Scanning aborted." -msgstr "" +msgid "Ultimate SkyBlock Admin" +msgstr "空岛超级管理员" -#, java-format -msgid "" -"§4PURGE:§9 Scanning done, found {0} candidates, below level {1}, ready for " -"purgatory." -msgstr "" +msgid "show player-information" +msgstr "显示玩家信息" -msgid "§cABORTED:§e Protect-All was aborted!" -msgstr "" +msgid "complete and list challenges" +msgstr "完成并列出挑战" -#, java-format -msgid "§eCompleted protect-all in {0}, {1} new regions were created!" -msgstr "" +msgid "§eChallenges has been disabled. Contact an administrator." +msgstr "§e挑战不可用,请联系服务器管理员." -msgid "control debugging" -msgstr "" +msgid "§4You can only submit challenges in the skyblock world!" +msgstr "§4你只能在空岛世界提交挑战。" -msgid "set debug-level" -msgstr "" +msgid "§4You can only submit challenges when you have an island!" +msgstr "§4你只能在拥有一个岛屿的情况下提交挑战。" -msgid "toggle debug-logging" -msgstr "" +msgid "" +"§4Your island is full, or you have too many pending invites. You can't " +"invite anyone else." +msgstr "§4你的岛屿已经满员,或者你有太多等待邀请请求。你无法再邀请其他人。" -msgid "§4Logging wasn't active, so you can't disable it!" -msgstr "§4记录未启用,所以你无法关闭。" +msgid "§4That player is already member on another island. " +msgstr "§4该玩家已经是另一个岛屿的会员。" -msgid "flush current content of the logger to file." +#, java-format +msgid "" +"§e{0}§e tried to invite you, but you are already in a party.To leave your " +"current party, use: /island leave." msgstr "" +"§e{0}§e试图邀请你,但你已经参加了一个聚会。要离开当前的聚会,请使用:/island " +"leave。" -msgid "§eLog-file has been flushed." -msgstr "§e日志文件已经更新。" - -msgid "§4Logging is not enabled, use §d/usb debug enable" -msgstr "§4记录未启用,输入§d/usb debug 启用" +#, java-format +msgid "§aInvite sent to {0}" +msgstr "§a邀请已发送到{0}" -msgid "§4Invalid argument, try INFO, FINE, FINER, FINEST" -msgstr "§4未知参数,请尝试 INFO, FINE, FINER, FINEST" +#, java-format +msgid "{0}§e has invited you to join their island!" +msgstr "{0}§e邀请你加入他们的岛屿。" -msgid "§eLogging disabled!" -msgstr "§e记录已经关闭" +msgid "§f/island [accept/reject]§e to accept or reject the invite." +msgstr "§f/island [accept/reject]§e 接受或者拒绝一个邀请。" -msgid "advanced command for setting island-data" -msgstr "" +msgid "§4WARNING: You will lose your current island if you accept!" +msgstr "§4警告: 如果你接受请求,你当前的岛屿将会被清空!" #, java-format -msgid "§c{0} was set to ''{1}''" -msgstr "" +msgid "{0}§d invited {1}" +msgstr "{0}§d邀请了{1}" #, java-format -msgid "§cUnable to set field {0} to ''{1}''" -msgstr "" +msgid "{0}§e has rejected the invitation." +msgstr "{0}§e拒绝了邀请" -#, java-format -msgid "§cUnable to set field {0} to ''{1}'', a number was expected" -msgstr "" +msgid "§4You can't use that command right now. Leave your current party first." +msgstr "§4你无法使用当前命令。请先离开你当前的团队。" -#, java-format -msgid "§cInvalid field {0}" -msgstr "" +msgid "" +"§aYou have joined an island! Use /island party to see the other members." +msgstr "§a你加入了一个岛屿!输入/island party 来查看团队成员。" #, java-format -msgid "§eCurrent value for {0} is ''{1}''" -msgstr "" +msgid "§eInvitation for {0}§e has timedout or been cancelled." +msgstr "§e来自{0}§e的邀请已经过时或被取消。" #, java-format -msgid "§cUnable to get state for {0}" -msgstr "" +msgid "§eInvitation for {0}''s island has timedout or been cancelled." +msgstr "§e来自{0}§e岛屿的邀请已经过时或被取消。" -#, java-format -msgid "§eValid fields are {0}" -msgstr "" +msgid "§eYou have accepted the invitation to join an island." +msgstr "§e你接受了加入岛屿的邀请." -msgid "set a player''s island to your location" -msgstr "" +msgid "§4You haven't been invited." +msgstr "§4你没有被任何人邀请." -#, java-format -msgid "§aSet {0}''s island to the current island." -msgstr "" +msgid "§eYou have rejected the invitation to join an island." +msgstr "§e你拒绝了加入岛屿的邀请" -msgid "§4Island not found: unable to set the island!" -msgstr "" +msgid "general island command" +msgstr "岛屿综合控制台" -msgid "advanced info about NBT stuff" -msgstr "" +msgid "allows user to bypass cooldowns" +msgstr "允许用户绕过冷却" -msgid "shows the NBTTag for the currently held item" -msgstr "" +msgid "allows user to bypass visitor-protections" +msgstr "允许用户绕过访问者保护" -#, java-format -msgid "§eInfo for §9{0}" -msgstr "" +msgid "allows user to bypass teleport-delay" +msgstr "允许用户绕过传送延迟" -#, java-format -msgid "§7 - name: §9{0}" -msgstr "" +msgid "allows user to use [usb] signs" +msgstr "允许用户使用[usb]符号" -#, java-format -msgid "§7 - nbttag: §9{0}" -msgstr "" +msgid "allows user to place [usb] signs" +msgstr "允许用户放置[usb]标志" -msgid "§cNo item in hand!" -msgstr "" +msgid "lock your island to non-party members." +msgstr "当你的岛上没有成员时锁定你的岛屿" -msgid "sets the NBTTag on the currently held item" -msgstr "" +msgid "§4You do not have permission to lock your island!" +msgstr "§4你没有权限锁定你的岛屿!" -#, java-format -msgid "§eSet §9{0}§e to §c{1}" -msgstr "" +msgid "§4You don't have access to this command!" +msgstr "§4你无法使用当前指令。" -msgid "adds the NBTTag on the currently held item" -msgstr "" +msgid "§4You do not have permission to unlock your island!" +msgstr "§4你没有权限解锁你的岛屿!" -#, java-format -msgid "§eAdded §9{0}§e to §c{1}" -msgstr "" +msgid "check your or another''s island info" +msgstr "查看您或他人的岛屿信息" -msgid "Manage challenges for a player" -msgstr "" +msgid "allows user to see others island info" +msgstr "允许用户查看其他岛屿信息" -msgid "resets the challenge for the player" -msgstr "" +msgid "§4Island level has been disabled, contact an administrator." +msgstr "§4岛屿等级系统未启用,请联系管理员." -msgid "§4Challenge has never been completed" -msgstr "§4挑战从未完成过" +msgid "§4Hold your horses! §eYou have to be patient..." +msgstr "§4把你的马拉下马!§e你必须有耐心。。。" -#, java-format -msgid "§echallenge: {0} has been reset for {1}" -msgstr "§e挑战: {0} 已经为玩家 {1} 重置" +msgid "§eYou must be on your island to use this command." +msgstr "§e你必须在你的岛屿上来使用这个指令." -msgid "resets all challenges for the player" -msgstr "" +msgid "§4You do not have an island!" +msgstr "§4你还未拥有一个岛屿!" -#, java-format -msgid "§e{0} has had all challenges reset." -msgstr "§e{0} 的所有挑战已经重置" +msgid "§4You do not have access to that command!" +msgstr "§4你没有权限使用这个指令!" -msgid "complete all challenges in the rank" -msgstr "" +msgid "§4That player is invalid or does not have an island!" +msgstr "§4玩家不存在或仍未拥有一个岛屿!" #, java-format -msgid "§4No player named {0} was found!" -msgstr "§4没有名字为 {0} 的玩家被找到" +msgid "§eBlocks on {0}s Island (page {1,number} of {2,number}):" +msgstr "§e在{0}岛上的方块(第{1,number}页,共{2,number}页):" -#, java-format -msgid "§4Challenge {0} has already been completed" -msgstr "" +msgid "Score Count Block" +msgstr "计分方块" #, java-format -msgid "§eChallenge {0} has been completed for {1}" -msgstr "" +msgid "{0,number,00.00} {1,number,#} {2}" +msgstr "{0,number,00.00} {1,number,#} {2}" #, java-format -msgid "§4No challenge named {0} was found!" -msgstr "§4挑战: {0} 未找到!" +msgid "§aIsland level is {0,number,###.##}" +msgstr "§a岛屿等级: {0,number,###.##}" -#, java-format -msgid "§4No rank named {0} was found!" -msgstr "" +msgid "teleports you to your island (or create one)" +msgstr "将你传送到你的岛屿(或创建一个)" -msgid "various chunk commands" -msgstr "" +msgid "§4This command can only be executed by a player" +msgstr "§4这个指令只能由玩家来执行." -msgid "regenerate current chunk" -msgstr "" +msgid "changes a members island-permissions" +msgstr "更改成员岛权限" #, java-format -msgid "successfully regenerated chunk at {0},{1}" -msgstr "" +msgid "§ePermissions for §9{0}§e:" +msgstr "§e§9{0}§e的许可:" -#, java-format -msgid "§4FAILED!§e could not regenerate chunk at {0},{1}" -msgstr "" +msgid "§aON" +msgstr "§aoon" -msgid "unload current chunk" -msgstr "" +msgid "§cOFF" +msgstr "§cOFF" #, java-format -msgid "successfully unloaded chunk at {0},{1}" -msgstr "" +msgid "§7 - §6{0}§7 : {1}" +msgstr "§7 - §6{0}§7 : {1}" #, java-format -msgid "§4FAILED!§e could not unload chunk at {0},{1}" -msgstr "" - -msgid "load current chunk" -msgstr "" +msgid "§cInvalid permission {0}. Must be one of {1}" +msgstr "§c权限{0}无效。必须是{1}之一" #, java-format -msgid "loaded chunk at {0},{1}" -msgstr "" - -msgid "only available for players" -msgstr "" +msgid "§eToggled permission §9{0}§e for §9{1}§e to {2}" +msgstr "§e为§9{1}§e至{2}记录了许可§9{0}§e" #, java-format -msgid "§4ERROR:§e {0}" -msgstr "" - -msgid "protects all islands (time consuming)" -msgstr "" - -msgid "§cTrying to abort protect-all task." -msgstr "" - -msgid "" -"§4Sorry!§e A protect-all is already running. Let it complete first, or use " -"§9usb protectall §cstop" -msgstr "" - -msgid "§eStarting a protect-all task. It will take a while." -msgstr "§e开始执行 全局保护,将会花费一定时间。" +msgid "§eUnable to toggle permission §9{0}§e for §9{1}" +msgstr "§e 无法切换权限 §9{0}§e 对于 §9{1}" -msgid "reload configuration from file." -msgstr "" +msgid "accept/reject an invitation." +msgstr "接受/拒绝邀请。" -msgid "§eConfiguration reloaded from file." -msgstr "§e配置重读。" +msgid "set the island-home" +msgstr "设置岛屿出生点" -msgid "manage islands" -msgstr "" +msgid "§4You must be closer to your island to set your skyblock home!" +msgstr "§4你必须在岛屿上才能设置你的家!" -msgid "protects the island" -msgstr "" +msgid "§4Your current location is not a safe home-location." +msgstr "§4您当前的位置不是一个安全的家。" -msgid "delete the island (removes the blocks)" -msgstr "" +msgid "§aYour skyblock home has been set to your current location." +msgstr "§a你岛屿家的位置已经设置在你当前位置." -msgid "§9Deleted abandoned island at your current location." -msgstr "§9你当前位置的岛屿已经删除。" +msgid "remove a member from your island." +msgstr "从您的岛屿中删除一个成员。" -msgid "" -"§4Island at this location has members!\n" -"§eUse §9/usb island delete §e to delete it." -msgstr "" -"§4当前位置的岛屿拥有其他的成员!\n" -"§e输入§9/usb island delete <玩家名> §e来删除" +msgid "§4You do not have permission to kick others from this island!" +msgstr "§4你没有在当前岛屿踢出玩家的权限!" -msgid "removes the player from the island" -msgstr "" +msgid "§4You can't remove the leader from the Island!" +msgstr "§4你无法将岛屿的主人移除!" -msgid "adds the player to the island" -msgstr "" +msgid "§4Stop kickin' yourself!" +msgstr "§4请不要尝试踢出你自己!" #, java-format -msgid "§b{0}§d has joined your island group." -msgstr "§b{0}§d加入了你的岛屿团队。" +msgid "§4{0} has removed you from their island!" +msgstr "§4{0}把你从他们的岛上赶走了!" #, java-format -msgid "§4No player named {0} found!" -msgstr "" - -msgid "" -"§4No valid island provided, either stand within one, or provide an island " -"name" -msgstr "" - -msgid "print out info about the island" -msgstr "" +msgid "§4{0} has been removed from the island." +msgstr "§4{0}被从当前岛屿上移除." -msgid "sets the biome of the island" -msgstr "" +#, java-format +msgid "§4{0} tried to kick you from their island!" +msgstr "§4{0}试图把你踢出他们的岛!" -msgid "§4That player has no island." -msgstr "§4玩家仍未拥有岛屿。" +#, java-format +msgid "§4{0} is exempt from being kicked." +msgstr "§4{0}免于被踢。" -msgid "§4No valid island at your location" -msgstr "§4无效的岛屿在你的位置上。" +#, java-format +msgid "§4{0} has kicked you from their island!" +msgstr "§4{0}把你踢出了他们的岛!" -msgid "purges the island" -msgstr "" +#, java-format +msgid "§4{0} has been kicked from the island." +msgstr "§4{0}被从当前岛屿上踢出." -msgid "§4Error! §9No valid island found for purging." -msgstr "" +msgid "§4That player is not part of your island group, and not on your island!" +msgstr "§4玩家不是你岛屿上的一员,并且不在你的岛屿上!" -#, java-format -msgid "§cPURGE: §9Purged island at {0}" -msgstr "" +msgid "change the biome of the island" +msgstr "改变岛上的生物群落" -msgid "toggles the islands ignore status" -msgstr "" +msgid "exempt player from biome-cooldown" +msgstr "免除玩家生物群系冷却时间" #, java-format -msgid "§cSet {0}s island to be ignored on top-ten and purge." -msgstr "" +msgid "Let the player change their islands biome to {0}" +msgstr "让玩家将他们的岛屿生物群系更改为{0}" -#, java-format msgid "" -"§cRemoved ignore-flag of {0}s island, it will now show up on top-ten and " -"purge." -msgstr "" +"§cYou do not have permission to change the biome of your current island." +msgstr "§c你没有权限更改你当前岛屿的生物群系." -msgid "§4No valid player-name supplied." -msgstr "§4无效的玩家名" +msgid "§4You do not have permission to change the biome of this island!" +msgstr "§4你没有权限去变更岛屿的生物群系!" -#, java-format -msgid "Removing {0} from island" -msgstr "从岛屿上移除了 {0}" +msgid "§eYou must be on your island to change the biome!" +msgstr "§e你必须在你的岛屿上才能更改生物群系!" #, java-format -msgid "§eChanged biome of {0}s island to {1}." -msgstr "§e将 {0} 的岛屿的生物群系更改为 {1}" +msgid "§cYou have misspelled the biome name. Must be one of {0}" +msgstr "§c你拼错了生物群名。必须是{0}之一" #, java-format -msgid "§eChanged biome of {0}s island to OCEAN." -msgstr "" +msgid "§eYou can change your biome again in {0,number,#} minutes." +msgstr "§e你需要等待{0,number,#}分钟才能再次更改生物群系." -msgid "§aYou may need to go to spawn, or relog, to see the changes." -msgstr "§a你需要返回出生点,或者重新登录才能看到改变。" +msgid "§cYou do not have permission to change your biome to that type." +msgstr "§c您无权将您的生物群落更改为该类型。" #, java-format -msgid "§e{0} has had their biome changed to {1}." -msgstr "§e{0} 将他们的生物群系更改为了 {1}" +msgid "" +"§7The pixies are busy changing the biome near you to §9{0}§7, be patient." +msgstr "§7小精灵们正忙着把你附近的生物群系改成§9{0}§7,耐心点。" #, java-format -msgid "§e{0} has had their biome changed to OCEAN." -msgstr "§e{0} 将他们的生物群系更改为了 OCEAN(海洋生物群系)" +msgid "" +"§7The pixies are busy changing the biome in your current chunk to §9{0}§7, " +"be patient." +msgstr "§7小精灵们正忙于将你当前区块中的生物群系更改为§9{0}§7,请耐心等待。" #, java-format -msgid "§eRemoving {0}''s island." -msgstr "§e移除了 {0} 的岛屿。" +msgid "" +"§7The pixies are busy changing the biome of your island to §9{0}§7, be " +"patient." +msgstr "§7小精灵们正忙着把你岛上的生物群系改成§9{0}§7,耐心点。" -msgid "Error: That player does not have an island!" -msgstr "错误: 玩家未拥有岛屿。" +msgid "§cInvalid arguments. Use /is biome [radius|chunk|all]" +msgstr "§c无效的参数。使用 /is biome <群落名称> [半径|区块|全部]" #, java-format -msgid "§e{0}s island at {1} has been protected" -msgstr "§e{0} 的岛屿在 {1} 被保护" +msgid "§aYou have changed your island''s biome to {0}" +msgstr "§a您已将岛屿的生物群系更改为{0}" #, java-format -msgid "§4{0}s island at {1} was already protected" -msgstr "" - -msgid "displays version information" -msgstr "" - -msgid "imports players and islands from other formats" -msgstr "" - -msgid "shows perk-information" -msgstr "" - -msgid "shows a specific players perks" -msgstr "" +msgid "{0} changed the island biome to {1}" +msgstr "{0}将岛屿的生物群系更改为{1}" #, java-format -msgid "additional perks {0}" -msgstr "" - -msgid "changes the language of the plugin, and reloads" -msgstr "" +msgid "§aYou have changed {0} blocks around you to the {1} biome" +msgstr "§a您已将周围的{0}个方块更改为{1}个生物群系" #, java-format -msgid "§aSuccessfully changed language to §e{0}" -msgstr "" +msgid "{0} created an area with {1} biome" +msgstr "{0}创建了一个包含{1}个生物群系的区域" -#, java-format -msgid "§cFailed to change language to §e{0}" -msgstr "" +msgid "enable/disable warping to your island." +msgstr "启用/禁用传送到您的岛屿。" -msgid "§9Supported Languages:\n" -msgstr "" +msgid "§4Your island is locked. You must unlock it before enabling your warp." +msgstr "§4你的岛屿已经锁定,在启用传送点之前请先解锁." #, java-format -msgid "§f{0} §7{1} §9 by {2} §7{3}\n" -msgstr "" - -msgid "§cUnable to locate any languages." -msgstr "" - -msgid "advanced command for getting island-data" -msgstr "" +msgid "§b{0}§d activated the island warp." +msgstr "§b{0}§d激活了岛屿传送。" -msgid "Ultimate SkyBlock Admin" -msgstr "" +#, java-format +msgid "§b{0}§d deactivated the island warp." +msgstr "§b{0}§d禁止了岛屿传送." -msgid "show player-information" -msgstr "" +msgid "§cYou do not have permission to enable/disable your island''s warp!" +msgstr "§c你没有权限启用/禁用岛屿的传送点!" -msgid "" -"§4Your island is full, or you have too many pending invites. You can't " -"invite anyone else." -msgstr "§4你的岛屿已经满员,或者你有太多等待邀请请求。你无法再邀请其他人。" +msgid "teleports you to the skyblock spawn" +msgstr "将你传送到空岛大厅" -msgid "§4That player is already leader on another island." -msgstr "§4那个玩家早就是另外岛屿的主人了。" +msgid "set your island''s warp location" +msgstr "设置岛屿的传送点位置" -#, java-format -msgid "§e{0}§e tried to invite you, but you are already in a party." -msgstr "§e{0}§e 尝试邀请你加入他的岛屿,但是你早就在其他团队了。" +msgid "§cYou do not have permission to set your island''s warp point!" +msgstr "§c你没有权限设置你岛屿的传送点!" -#, java-format -msgid "§aInvite sent to {0}" -msgstr "" +msgid "§cYou need to be on your own island to set the warp!" +msgstr "§c你需要在你的岛屿上才能设置传送点!" #, java-format -msgid "{0}§e has invited you to join their island!" -msgstr "{0}§e邀请你加入他们的岛屿。" +msgid "§b{0}§d changed the island warp location." +msgstr "§b{0}§d更改岛屿传送坐标." -msgid "§f/island [accept/reject]§e to accept or reject the invite." -msgstr "§f/island [accept/reject]§e 接受或者拒绝一个邀请。" +msgid "§4No Island. §eUse §b/is create§e to get one" +msgstr "§4未拥有岛屿.§e输入§b/is create§e创建一个岛屿" -msgid "§4WARNING: You will lose your current island if you accept!" -msgstr "§4警告: 你当前的岛屿将会被清空,如果你接受请求的话。" +msgid "transfer leadership to another member" +msgstr "将领导权移交给另一名成员" -#, java-format -msgid "{0}§d invited {1}" -msgstr "{0}§d邀请了{1}" +msgid "§4You can only transfer ownership to party-members!" +msgstr "§4你只能将岛主的权限转移给成员玩家!" #, java-format -msgid "{0}§e has rejected the invitation." -msgstr "{0}§e拒绝了邀请" - -msgid "§4You can't use that command right now. Leave your current party first." -msgstr "§4你无法使用当前命令。请先离开你当前的团队。" - -msgid "" -"§aYou have joined an island! Use /island party to see the other members." -msgstr "§a你加入了一个岛屿!输入/island party 来查看团队成员。" +msgid "{0}§e is already leader of your island!" +msgstr "{0}§e早就是你们岛屿的成员了!" -#, java-format -msgid "§eInvitation for {0}§e has timedout or been cancelled." -msgstr "§e来自{0}§e的邀请已经过时或被取消。" +msgid "§4Only leader can transfer leadership!" +msgstr "§4只有岛主才能转移权限!" #, java-format -msgid "§eInvitation for {0}''s island has timedout or been cancelled." -msgstr "§e来自{0}§e岛屿的邀请已经过时或被取消。" - -msgid "§eYou have accepted the invitation to join an island." -msgstr "§e你接受了加入岛屿的邀请." +msgid "{0} tried to take over the island!" +msgstr "{0}试图接管当前岛屿!" -msgid "§4You haven't been invited." -msgstr "§4你没有被任何人邀请." +msgid "ban/unban a player from your island." +msgstr "封禁/解禁您所在岛屿的玩家。" -msgid "§eYou have rejected the invitation to join an island." -msgstr "§e你拒接了加入岛屿的邀请" +msgid "exempts user from being banned" +msgstr "使用户免于被封禁" -msgid "general island command" -msgstr "" +msgid "§eThe following players are banned from warping to your island:" +msgstr "§e下列玩家被禁止传送到你的岛屿:" -msgid "allows user to bypass cooldowns" -msgstr "" +msgid "§eTo ban/unban from your island, use /island ban " +msgstr "§e禁止/允许一个玩家前往你的岛屿,输入§c/island ban §a<玩家名字>" -msgid "allows user to bypass visitor-protections" -msgstr "" +msgid "§4You can't ban members. Remove them first!" +msgstr "§4你无法封禁玩家.请先将他们从你的岛屿上移除!" -msgid "allows user to bypass teleport-delay" -msgstr "" +msgid "§4You do not have permission to kick/ban players." +msgstr "§4你没有权限踢出/禁止一个玩家" -msgid "allows user to use [usb] signs" -msgstr "" +#, java-format +msgid "§eUnable to ban unknown player {0}" +msgstr "§e无法禁止未知玩家{0}" -msgid "allows user to place [usb] signs" -msgstr "" +#, java-format +msgid "§4{0} tried to ban you from their island!" +msgstr "§4{0}试图禁止你进入他们的岛屿!" -msgid "complete and list challenges" -msgstr "" +#, java-format +msgid "§4{0} is exempt from being banned." +msgstr "§4{0}免于被禁止。" -msgid "§cCommand only available for players." -msgstr "" +#, java-format +msgid "§eYou have banned §4{0}§e from warping to your island." +msgstr "§e你禁止了玩家§4{0}§e前往你的岛屿上." -msgid "§eChallenges has been disabled. Contact an administrator." -msgstr "§e挑战不可用,请联系服务器管理员." +#, java-format +msgid "§eYou have been §cBANNED§e from {0}§e''s island." +msgstr "§e你已被{0}§e岛的§c禁止§e。" -msgid "§4You can only submit challenges in the skyblock world!" -msgstr "§4你只能在空岛世界提交挑战。" +#, java-format +msgid "§eYou have unbanned §a{0}§e from warping to your island." +msgstr "§e你解除了玩家§a{0}§e的封禁状态,现在他可以访问你的岛屿了." -msgid "§4You can only submit challenges when you have an island!" -msgstr "§4你只能在拥有一个岛屿的情况下提交挑战。" +#, java-format +msgid "§eYou have been §aUNBANNED§e from {0}§e''s island." +msgstr "§e您已被{0}§e岛禁止入境。" msgid "warp to another player''s island" -msgstr "" +msgstr "传送到另一个玩家的岛屿" msgid "§aYour incoming warp is active, players may warp to your island." msgstr "§a你启用了传送点,玩家可以传送到你的岛屿上了." @@ -2196,7 +2033,7 @@ msgid "§4Your incoming warp is inactive, players may not warp to your island." msgstr "§4你禁用了传送点,玩家无法传送到你的岛屿上." msgid "§fSet incoming warp to your current location using §e/island setwarp" -msgstr "§f设置岛屿传送点在你当前位置上请收入与§e/island setwarp" +msgstr "§f要设置岛屿传送点在你当前位置上,请输入§e/island setwarp" msgid "§fToggle your warp on/off using §e/island togglewarp" msgstr "§f启用/禁止岛屿的传送点请输入§e/island togglewarp" @@ -2213,7 +2050,7 @@ msgstr "§4你没有权限传送到其他玩家的岛屿上" msgid "" "§cYour island is in the process of generating, you cannot warp to other " "players islands right now." -msgstr "" +msgstr "§c你的岛屿正在生成过程中,你现在不能传送到其他玩家的岛屿。" msgid "§4That player does not exist!" msgstr "§4玩家不存在!" @@ -2224,23 +2061,126 @@ msgstr "§4玩家未拥有激活的传送点." msgid "" "§cThat players island is in the process of generating, you cannot warp to it " "right now." -msgstr "" +msgstr "§c玩家岛正在生成过程中,您现在不能传送到他。" #, java-format msgid "§cWARNING: §9{0}§e is warping to your island!" -msgstr "" +msgstr "§c警告:§9{0}§e正在传送到你的岛屿!" msgid "§4That player has forbidden you from warping to their island." msgstr "§4玩家禁止你传送到他们的岛屿上." -msgid "§4No Island. §eUse §b/is create§e to get one" -msgstr "§4未拥有岛屿.§e输入§b/is create§e创建一个岛屿" +msgid "create an island" +msgstr "创建一个岛屿" + +msgid "exempt player from create-cooldown" +msgstr "免除玩家创建冷却时间" + +msgid "" +"§4Island found!§e You already have an island. If you want a fresh island, " +"type§b /is restart§e to get one" +msgstr "" +"§4岛屿已存在!§e你已经拥有一个岛屿了,你可以输入§b /is restart §e来重新开始岛" +"屿生涯." + +msgid "" +"§4Island found!§e You are already a member of an island. To start your own, " +"first§b /is leave" +msgstr "" +"§4岛屿已存在!§e你已经加入了一个岛屿.如果你想开始一个属于自己的岛屿生涯,请先" +"输入§b /is leave §e来离开当前团队." + +#, java-format +msgid "§eYou can create a new island in {0,number,#} seconds." +msgstr "§e你需要等待{0,number,#}秒才能创建一个新的岛屿." + +msgid "show party information" +msgstr "显示聚会信息" + +msgid "shows information about your party" +msgstr "显示有关您聚会的信息" + +msgid "show pending invites" +msgstr "显示待处理的邀请" + +msgid "§eNo pending invites" +msgstr "§e没有等待的邀请" + +msgid "withdraw an invite" +msgstr "撤回邀请" + +msgid "§4You don't have permissions to uninvite players." +msgstr "§4您无权邀请未受邀请的玩家。" + +msgid "teleport to the island home" +msgstr "传送到岛上的家" + +msgid "" +"§cYour island is in the process of generating, you cannot teleport home " +"right now." +msgstr "§c你的岛屿正在生成过程中,你现在无法传送回家。" + +msgid "check your or anothers island level" +msgstr "查看你的岛屿等级" + +msgid "allows user to query for others levels" +msgstr "允许用户查询其他级别" + +#, java-format +msgid "§eInformation about {0}''s Island:" +msgstr "§e有关{0}岛屿的信息:" + +#, java-format +msgid "§9Rank is {0}" +msgstr "§9排名: {0}" + +#, java-format +msgid "§4Could not locate rank of {0}" +msgstr "§4无法定位{0}的排名" + +msgid "display the top10 of islands" +msgstr "显示前10个岛屿" + +msgid "enables user to all-ways generate top-ten (no caching)" +msgstr "使用户能够以各种方式生成前十名(无缓存)" + +msgid "trust/untrust a player to help on your island." +msgstr "信任/不信任玩家在你的岛上帮忙。" + +msgid "§eThe following players are trusted on your island:" +msgstr "§e在您的岛屿上,以下玩家值得信赖:" + +msgid "§eThe following leaders trusts you:" +msgstr "§e以下领导信任您:" + +msgid "§eTo trust/untrust from your island, use /island trust " +msgstr "§e要信任/不信任您的岛屿,请使用/岛屿信任" + +msgid "§4Members are already trusted!" +msgstr "§4会员已被信任!" + +#, java-format +msgid "§4Unknown player {0}" +msgstr "§4未知玩家{0}" + +#, java-format +msgid "§eYou are now trusted on §4{0}''s §eisland." +msgstr "§e您现在在§4{0}的§eisland上受到信任。" + +#, java-format +msgid "§a{0} trusted {1} on the island" +msgstr "§岛上{0}个受信任的{1}" + +#, java-format +msgid "§eYou are no longer trusted on §4{0}''s §eisland." +msgstr "§e您在§4{0}的§eisland上不再被信任。" -msgid "accept/reject an invitation." -msgstr "" +#, java-format +msgid "§c{0} revoked trust in {1} on the island" +msgstr "§c{0}撤销了对岛上{1}的信任" msgid "leave your party" -msgstr "" +msgstr "离开你的聚会" msgid "" "§4You can't leave your island if you are the only person. Try using /island " @@ -2250,7 +2190,7 @@ msgstr "" "restart" msgid "§eYou own this island, use /island remove instead." -msgstr "§e你拥有了当前岛屿,输入/island remove <玩家ID> 来取代他" +msgstr "§e这个岛屿属于你,输入/island remove <玩家ID> 来转让归属权" msgid "§eYou have left the island and returned to the player spawn." msgstr "§e你离开了当前岛屿,并且传送到了玩家出生点." @@ -2262,66 +2202,39 @@ msgstr "§4{0}离开了你的岛屿!" msgid "§4You must be in the skyblock world to leave your party!" msgstr "§4你必须在岛屿世界才能离开你的团队!" -msgid "check your or anothers island level" -msgstr "" - -msgid "allows user to query for others levels" -msgstr "" - -msgid "§eYou must be on your island to use this command." -msgstr "§e你必须在你的岛屿上来使用这个指令." - -msgid "§4You do not have an island!" -msgstr "§4你还未拥有一个岛屿!" - -msgid "§4You do not have access to that command!" -msgstr "§4你没有权限使用这个指令!" - -msgid "§4That player is invalid or does not have an island!" -msgstr "§4玩家不存在或仍未拥有一个岛屿!" - -#, java-format -msgid "§eInformation about {0}''s Island:" -msgstr "" - -#, java-format -msgid "§aIsland level is {0,number,###.##}" -msgstr "§a岛屿等级: {0,number,###.##}" - -#, java-format -msgid "§9Rank is {0}" -msgstr "§9排名: {0}" - -#, java-format -msgid "§4Could not locate rank of {0}" -msgstr "" - -msgid "create an island" -msgstr "" +msgid "delete your island and start a new one." +msgstr "删除你的岛屿,开始一个新的岛屿。" -msgid "exempt player from create-cooldown" -msgstr "" +msgid "exempt player from restart-cooldown" +msgstr "免除玩家重新启动冷却时间" msgid "" -"§4Island found!§e You already have an island. If you want a fresh island, " -"type§b /is restart§e to get one" +"§4Only the owner may restart this island. Leave this island in order to " +"start your own (/island leave)." msgstr "" -"§4岛屿已存在!§e你早就拥有一个岛屿了.如果你想要一个权限的岛屿,输入§b /is " -"restart §e来重新开始岛屿生涯." +"§4只有岛主才能重置岛屿.若要离开当前岛屿开始属于你自己的岛屿生涯请输入(/" +"island leave)" msgid "" -"§4Island found!§e You are already a member of an island. To start your own, " -"first§b /is leave" +"§eYou must remove all players from your island before you can restart it (/" +"island kick ). See a list of players currently part of your island " +"using /island party." msgstr "" -"§4岛屿已存在!§e你已经加入了一个岛屿.如果你想开始一个属于自己的岛屿生涯,请先" -"输入§b /is leave §e来离开当前团队." +"§e想要重新开始你的岛屿,你必须移除所有岛屿成员(/island kick <玩家ID>).查看当" +"前岛屿玩家列表请输入/island party" #, java-format -msgid "§eYou can create a new island in {0,number,#} seconds." -msgstr "§e你需要等待{0,number,#}秒才能创建一个新的岛屿." +msgid "§cYou can restart your island in {0} seconds." +msgstr "§c您可以在{0}秒内重新启动您的岛屿。" + +msgid "§cYour island is in the process of generating, you cannot restart now." +msgstr "§c您的岛屿正在生成过程中,现在无法重新启动。" + +msgid "§eNOTE: Your entire island and all your belongings will be RESET!" +msgstr "§e注意: 你所有财产和你的岛屿将被§c§l重置" msgid "invite a player to your island" -msgstr "" +msgstr "邀请玩家到您的岛屿" msgid "" "§eUse§f /island invite §e to invite a player to your island." @@ -2349,440 +2262,362 @@ msgstr "§4你无法邀请你自己!" msgid "§4That player is the leader of your island!" msgstr "§4玩家是你当前所处岛屿的主人!" -msgid "lock your island to non-party members." -msgstr "" - -msgid "§4You do not have permission to lock your island!" -msgstr "§4你没有权限锁定你的岛屿!" - -msgid "§4You don't have access to this command!" -msgstr "§4你无法使用当前指令。" - -msgid "§4You do not have permission to unlock your island!" -msgstr "§4你没有权限解锁你的岛屿!" - -msgid "display the top10 of islands" -msgstr "" - -msgid "enables user to all-ways generate top-ten (no caching)" -msgstr "" - -msgid "remove a member from your island." -msgstr "" - -msgid "§4You do not have permission to kick others from this island!" -msgstr "§4你没有在当前岛屿踢出玩家的权限!" - -msgid "§4You can't remove the leader from the Island!" -msgstr "§4你无法将岛屿的主人移除!" - -msgid "§4Stop kickin' yourself!" -msgstr "§4请不要尝试踢出你自己!" +msgid "display log" +msgstr "显示日志" -#, java-format -msgid "§4{0} has removed you from their island!" -msgstr "" +msgid "show the islands limits" +msgstr "查询岛屿生物/方块数量限制" #, java-format -msgid "§4{0} has been removed from the island." -msgstr "§4{0}被从当前岛屿上移除." +msgid " §f{0}x §7{1}" +msgstr "§f{0}x §7{1}" #, java-format -msgid "§4{0} tried to kick you from their island!" -msgstr "" +msgid "§eStill the following blocks short: {0}" +msgstr "§e任然缺少以下方块: {0}" #, java-format -msgid "§4{0} is exempt from being kicked." -msgstr "" +msgid "" +"§eProgress: {0,number,##}% ({1}/{2} - success:{3}, failed:{4}, skipped:{5}) " +"~ {6}" +msgstr "§e进程: {0,number,##}% ({1}/{2} - 成功:{3},失败:{4}, 跳过:{5}) ~ {6}" #, java-format -msgid "§4{0} has kicked you from their island!" -msgstr "" +msgid "§4No importer named §e{0}§4 found" +msgstr "§4输入的名字§e{0}§4未找到" #, java-format -msgid "§4{0} has been kicked from the island." -msgstr "§4{0}被从当前岛屿上踢出." +msgid "§eConverted {0}/{1} files in {2}" +msgstr "§在{2}中转换了 {0}/{1} 个文件" -msgid "§4That player is not part of your island group, and not on your island!" -msgstr "§4玩家不是你岛屿上的一员,并且不在你的岛屿上!" +msgid "§9Hold your horses! You have to be patient..." +msgstr "§9把你的马牵起来!你必须耐心点..." -msgid "teleport to the island home" -msgstr "" +msgid "§9Not really patient, are you?" +msgstr "§9你真的没有耐心,是吗?" -msgid "" -"§cYour island is in the process of generating, you cannot teleport home " -"right now." -msgstr "" +msgid "§9Be patient, young padawan" +msgstr "§9耐心点,年轻学徒" -msgid "§4This command can only be executed by a player" -msgstr "§4这个指令只能由玩家来执行." +msgid "§9Patience you MUST have, young padawan" +msgstr "§9你必须有耐心,年轻的学徒" -msgid "transfer leadership to another member" -msgstr "" +msgid "§9The two most powerful warriors are patience and time." +msgstr "§9最强大的两个战士是耐心和时间。" -msgid "§4You can only transfer ownership to party-members!" -msgstr "§4你只能将岛屿主人的权限转移给他们的成员玩家!" +msgid "§4Unable to find a safe home-location on your island!" +msgstr "§4在你的岛上找不到安全的家!" -#, java-format -msgid "{0}§e is already leader of your island!" -msgstr "{0}§e早就是你们岛屿的成员了!" +msgid "§cWARNING: §eTeleporting you to mid-air." +msgstr "§c警告:§e将你吊到半空中。" -msgid "§4Only leader can transfer leadership!" -msgstr "§4只有岛屿的主人才能转移权限!" +msgid "§aTeleporting you to your island." +msgstr "§a将你传送回自己的岛屿." #, java-format -msgid "{0} tried to take over the island!" -msgstr "{0}试图接管当前岛屿!" - -msgid "show party information" -msgstr "" - -msgid "shows information about your party" -msgstr "" - -msgid "show pending invites" -msgstr "" - -msgid "§eNo pending invites" -msgstr "§e没有等待的邀请" - -msgid "withdraw an invite" -msgstr "" +msgid "§aYou will be teleported in {0} seconds." +msgstr "§a将在 {0} 秒后进行传送." -msgid "§4You don't have permissions to uninvite players." -msgstr "" +msgid "§4Unable to warp you to that player''s island!" +msgstr "§4无法传送至玩家的岛屿!" -msgid "check your or another''s island info" -msgstr "" +#, java-format +msgid "§aTeleporting you to {0}''s island." +msgstr "§a将您传送到 {0}的岛屿。" -msgid "allows user to see others island info" -msgstr "" +msgid "§7Teleport cancelled" +msgstr "§7 Teleport已取消" -msgid "§4Hold your horses! §eYou have to be patient..." -msgstr "" +msgid "§eSending you to spawn." +msgstr "§e将你传送到空岛大厅" -#, java-format -msgid "§eBlocks on {0}s Island (page {1,number} of {2,number}):" -msgstr "eBlocks on {0}s Island (page {1,number} of {2,number}):" +msgid "§eThe island has been §cLOCKED§e." +msgstr "§e该岛已被锁定。" -msgid "Score Count Block" -msgstr "计分方块" +msgid "§eVisitors can't drop items!" +msgstr "§e非岛屿成员不能在此丢弃物品!" #, java-format -msgid "{0,number,00.00} {1,number,#} {2}" -msgstr "" +msgid "Owner: {0}" +msgstr "所有者: {0}" -msgid "trust/untrust a player to help on your island." -msgstr "" +msgid "You cannot pick up other players' loot when you are a visitor!" +msgstr "非岛屿成员不能拾取此岛屿成员丢弃的物品!" -msgid "§eThe following players are trusted on your island:" -msgstr "" +msgid "§cWither Despawned!§e It wandered too far from your island." +msgstr "§c凋零已被清理!§e它离你的岛太远了。" -msgid "§eThe following leaders trusts you:" -msgstr "" +msgid "§4You can only convert obsidian once every 10 seconds" +msgstr "§4每10秒只能转换一次黑曜石" -msgid "§eTo trust/untrust from your island, use /island trust " -msgstr "" +msgid "§eChanging your obsidian back into lava. Be careful!" +msgstr "§e已经将你的黑曜石变为岩浆.请务必当心!" -msgid "§4Members are already trusted!" -msgstr "" +msgid "§eYour inventory must have another empty space!" +msgstr "§e您的库存必须有另一个空位!" -#, java-format -msgid "§4Unknown player {0}" -msgstr "" +msgid "§4It''s a bad idea to replace your lava!" +msgstr "§4替换岩浆真是一个§f'不错'§4的注意呢~" -#, java-format -msgid "§eYou are now trusted on §4{0}''s §eisland." -msgstr "" +msgid "§eYou cannot hurt island-members." +msgstr "§e你不能伤害岛屿成员。" -#, java-format -msgid "§a{0} trusted {1} on the island" -msgstr "" +msgid "§4That player has forbidden you from teleporting to their island." +msgstr "§4玩家禁止你传送到他们的岛屿上." -#, java-format -msgid "§eYou are no longer trusted on §4{0}''s §eisland." -msgstr "" +msgid "§4That island is §clocked.§e No teleporting to the island." +msgstr "§4目标岛屿已锁定。§e不得传送到岛上。" #, java-format -msgid "§c{0} revoked trust in {1} on the island" -msgstr "" - -msgid "delete your island and start a new one." -msgstr "" - -msgid "exempt player from restart-cooldown" -msgstr "" - msgid "" -"§4Only the owner may restart this island. Leave this island in order to " -"start your own (/island leave)." -msgstr "" -"§4只有岛屿的主人才能重新开始岛屿.离开当前岛屿开始属于你自己的岛屿生涯请输入(/" -"island leave)" +"§4{0} is limited. §eScanning your island to see if you are allowed to place " +"more, please be patient" +msgstr "§4{0}已达上限。§e检查你的到,看看是否允许您放置更多,请耐心等待" -msgid "" -"§eYou must remove all players from your island before you can restart it (/" -"island kick ). See a list of players currently part of your island " -"using /island party." -msgstr "" -"§e想要重新开始你的岛屿,你必须移除所有岛屿成员(/island kick <玩家ID>).查看当" -"前岛屿玩家列表请输入/island party" +msgid "§e... Scanning complete, you can try again" +msgstr "§e...扫描完成,您可以重试" #, java-format -msgid "§cYou can restart your island in {0} seconds." -msgstr "" - -msgid "§cYour island is in the process of generating, you cannot restart now." +msgid "" +"§4You''ve hit the {0} limit!§e You can''t have more of that type on your " +"island!§9 Max: {1,number}" msgstr "" +"§4 您已达到 {0} 限制!§e 您的岛上不能有更多该类型的东西!§9 最大值:" +"{1,number}" -msgid "§eNOTE: Your entire island and all your belongings will be RESET!" -msgstr "§e注意: 你所有财产和你的岛屿将被§c§l重置" +msgid "§eYou can only use spawn-eggs on your own island." +msgstr "§e您只能在自己的岛上使用刷怪蛋" -msgid "teleports you to the skyblock spawn" -msgstr "" +msgid "§cYou have reached your spawn-limit for your island." +msgstr "§c您的岛屿已达到刷怪数量限制" -msgid "change the biome of the island" -msgstr "" +msgid "§eYou can not use another island''s portals!" +msgstr "§e你不能使用其他岛屿的物品!" -msgid "exempt player from biome-cooldown" -msgstr "" +msgid "§eVillager-trading isn't allowed." +msgstr "§e村民交易已禁止。" -#, java-format -msgid "Let the player change their islands biome to {0}" -msgstr "" +msgid "§eTrading isn't allowed on other islands. Do it in spawn." +msgstr "§e在其他岛屿时不允许交易。回到大厅中执行此操作。" -msgid "" -"§cYou do not have permission to change the biome of your current island." -msgstr "§c你没有权限更改你当前岛屿的生物群系." +msgid "§eRiding is only allowed on your own island!" +msgstr "§e在您自己的岛屿上才允许骑行!" -msgid "§4You do not have permission to change the biome of this island!" -msgstr "§4你没有权限去变更岛屿的生物群系!" +msgid "§eYou cannot break vehicles while being a visitor!" +msgstr "§e非岛屿成员不能破坏矿车!" -msgid "§eYou must be on your island to change the biome!" -msgstr "§e你必须在你的岛屿上才能更改生物群系!" +msgid "§cBanned:§e You are banned from this island." +msgstr "§c禁止:§e你被禁止进入这个岛。" -#, java-format -msgid "§cYou have misspelled the biome name. Must be one of {0}" -msgstr "" +msgid "§cLocked:§e That island is locked! No entry allowed." +msgstr "§c锁定:§e此空岛已锁定!不允许进入。" #, java-format -msgid "§eYou can change your biome again in {0,number,#} minutes." -msgstr "§e你需要等待{0,number,#}分钟才能再次更改生物群系." +msgid "{0}''s Wither" +msgstr "{0}的凋零" -msgid "§cYou do not have permission to change your biome to that type." -msgstr "" +msgid "Something went wrong saving the island and/or party data!" +msgstr "在存储岛屿或者团队记录的时候发生了一些错误!" -#, java-format -msgid "" -"§7The pixies are busy changing the biome near you to §9{0}§7, be patient." -msgstr "" +msgid "§cMAINTENANCE:§e uSkyBlock is currently in maintenance mode" +msgstr "§c维护:§uSkyBlock目前处于维护模式" #, java-format msgid "" -"§7The pixies are busy changing the biome in your current chunk to §9{0}§7, " -"be patient." -msgstr "" - -#, java-format -msgid "§eInvalid biome {0} supplied!" +"§buSkyBlock§e depends on §9{0}§e >= §av{1}§e but only §cv{2}§e was found!\n" msgstr "" +"“§buSkyBlock插件§e 依赖于 §9{0}§e >= §av{1}§e,但只发现了 §cv{2}§e!”\n" #, java-format -msgid "§aYou have changed your island''s biome to {0}" -msgstr "" +msgid "§buSkyBlock§e depends on §9{0}§e >= §av{1}" +msgstr "§buSkyBlock§e取决于§9{0}§e>=§av{1}" -#, java-format -msgid "{0} changed the island biome to {1}" -msgstr "{0}将岛屿的生物群系更改为{1}" +msgid "§4Player is already assigned to this island!" +msgstr "§4玩家已经分配给这个岛屿了!" -#, java-format -msgid "§aYou have changed {0} blocks around you to the {1} biome" -msgstr "" +msgid "§cYour island is in the process of generating, you cannot create now." +msgstr "§c你的岛屿正在生成过程中,你现在无法创建。" -#, java-format -msgid "{0} created an area with {1} biome" -msgstr "" +msgid "Could not create your Island. Please contact a server moderator." +msgstr "无法为你创建岛屿.请联系管理员." -msgid "set your island''s warp location" -msgstr "" +msgid "§eGetting your island ready, please be patient, it can take a while." +msgstr "§e准备好你的岛屿,请耐心等待,这可能需要一段时间。" -msgid "§cYou do not have permission to set your island''s warp point!" -msgstr "§c你没有权限设置你岛屿的传送点!" +msgid "§cCommand is currently disabled!" +msgstr "§cCommand当前已禁用!" -msgid "§cYou need to be on your own island to set the warp!" -msgstr "§c你需要在你的岛屿上才能设置传送点!" +msgid "North" +msgstr "北" -#, java-format -msgid "§b{0}§d changed the island warp location." -msgstr "§b{0}§d更改岛屿传送坐标." +msgid "North-East" +msgstr "东北" -msgid "teleports you to your island (or create one)" -msgstr "" +msgid "East" +msgstr "东" -msgid "ban/unban a player from your island." -msgstr "" +msgid "South-East" +msgstr "东南" -msgid "exempts user from being banned" -msgstr "" +msgid "South" +msgstr "南" -msgid "§eThe following players are banned from warping to your island:" -msgstr "§e下列玩家被禁止传送到你的岛屿:" +msgid "South-West" +msgstr "西南" -msgid "§eTo ban/unban from your island, use /island ban " -msgstr "§e禁止/允许一个玩家前往你的岛屿,输入§c/island ban §a<玩家名字>" +msgid "West" +msgstr "西" -msgid "§4You can't ban members. Remove them first!" -msgstr "§4你无法封禁玩家.请先将他们从你的岛屿上移除!" +msgid "North-West" +msgstr "西北" -msgid "§4You do not have permission to kick/ban players." -msgstr "§4你没有权限踢出/禁止一个玩家" +msgid "N/A" +msgstr "无数据" #, java-format -msgid "§eUnable to ban unknown player {0}" -msgstr "" +msgid "§9{0}§7 timed out" +msgstr "§9{0}§7超时" #, java-format -msgid "§4{0} tried to ban you from their island!" -msgstr "" +msgid "" +"§eDoing §9{0}§e is §cRISKY§e. Repeat the command within §a{1}§e seconds to " +"accept!" +msgstr "§9{0}§e属于§c危险操作§e.请在§a{1}§e秒内重复命令以确认操作." #, java-format -msgid "§4{0} is exempt from being banned." -msgstr "" +msgid "§eWaiting for our turn §c{0,number,###}%" +msgstr "§e等待轮到我们§c{0,number,###}%" #, java-format -msgid "§eYou have banned §4{0}§e from warping to your island." -msgstr "§e你禁止了玩家§4{0}§e前往你的岛屿上." +msgid "§9Creating island...§e{0,number,###}%" +msgstr "§9创建岛屿...§e{0,number,###}%" -#, java-format -msgid "§eYou have been §cBANNED§e from {0}§e''s island." -msgstr "" +msgid "§4** You are entering a protected - but abandoned - island area." +msgstr "§4您正在进入一个受保护但被遗弃的岛屿地区" #, java-format -msgid "§eYou have unbanned §a{0}§e from warping to your island." -msgstr "§e你解除了玩家§a{0}§e的封禁状态,现在他可以访问你的岛屿了." +msgid "§d** You are entering §b{0}''s §disland." +msgstr "§d您正在进入§b{0}的§d岛屿" -#, java-format -msgid "§eYou have been §aUNBANNED§e from {0}§e''s island." -msgstr "" +msgid "§4** You are leaving an abandoned island." +msgstr "§4你离开了一个荒岛" -msgid "display log" -msgstr "" +#, java-format +msgid "§d** You are leaving §b{0}''s §disland." +msgstr "§d你离开了§b{0}的§d岛屿" -msgid "changes a members island-permissions" -msgstr "" +msgid "§eYour island is now locked. Only your party members may enter." +msgstr "§e你的岛屿当前处于锁定状态.只有团队成员才能进入." -#, java-format -msgid "§ePermissions for §9{0}§e:" -msgstr "" +msgid "§4You must be the party leader to lock your island!" +msgstr "§4你必须为岛屿主人才能锁定岛屿!" -msgid "§aON" +msgid "" +"§eYour island is unlocked and anyone may enter, however only you and your " +"party members may build or remove blocks." msgstr "" +"§e你岛屿当前处于未锁定状态,s所有人都可以访问你的岛屿,不过只有你和岛屿成员才" +"能进行建造." -msgid "§cOFF" -msgstr "" +msgid "§4You must be the party leader to unlock your island!" +msgstr "§4你必须得是岛屿的主人才能解锁你的岛屿!" -#, java-format -msgid "§7 - §6{0}§7 : {1}" -msgstr "" +msgid "" +"§cThe island owning this piece of nether is being deleted! Sending you to " +"spawn." +msgstr "§c 该拥有这片下界区域的岛屿正在被删除!将您传送至出生点。" -#, java-format -msgid "§cInvalid permission {0}. Must be one of {1}" -msgstr "" +msgid "§cThe island you are on is being deleted! Sending you to spawn." +msgstr "§c你所处的岛屿正在被删除!将你传送到出生点." #, java-format -msgid "§eToggled permission §9{0}§e for §9{1}§e to {2}" -msgstr "" +msgid "§eWALL OF FAME (page {0} of {1}):" +msgstr "§e岛屿排行 (页数 {0} - {1}):" #, java-format -msgid "§eUnable to toggle permission §9{0}§e for §9{1}" -msgstr "" - -msgid "set the island-home" -msgstr "" - -msgid "show the islands limits" -msgstr "" +msgid "§4Top ten list is empty! Only islands above level {0} is considered." +msgstr "§4前十名列表为空!仅考虑级别{0}以上的岛屿。" -msgid "enable/disable warping to your island." -msgstr "" +#, java-printf-format +msgid "§a#%2d §7(%5.2f): §e%s §7%s" +msgstr "§a#%2d §7(%5.2f): §e%s §7%s" -msgid "§4Your island is locked. You must unlock it before enabling your warp." -msgstr "§4你的岛屿已经锁定,在启用传送点之前请先解锁." +msgid "Click to warp to the island!" +msgstr "点击以传送到岛上!" #, java-format -msgid "§b{0}§d activated the island warp." -msgstr "" +msgid "§eYour rank is: §f{0}" +msgstr "§e你的排名是: §f{0}" -msgid "§cYou do not have permission to enable/disable your island''s warp!" -msgstr "§c你没有权限启用/禁用岛屿的传送点!" +msgid "§9Creating an island at your location" +msgstr "§9在您的位置创建一个岛屿" -msgid "try to complete a challenge" -msgstr "" +#, java-format +msgid "§9Creating an island §7{0}§9 of you" +msgstr "§9 创建一个属于你的岛屿 §7{0}§9" -msgid "show information about the challenge" -msgstr "" +msgid "The island has been created." +msgstr "岛屿已创建!" -msgid "§eRank: " -msgstr "" +#, java-format +msgid "§b{0}§d locked the island." +msgstr "§b{0}§d锁定了该岛。" -msgid "§4This Challenge is not repeatable!" -msgstr "§4当前任务不可重复。" +msgid "§4Since your island is locked, your incoming warp has been deactivated." +msgstr "§4因为你的岛屿处于锁定状态,岛屿传送点也将禁用." -msgid "§4You will lose all required items when you complete this challenge!" -msgstr "§4挑战所需物品将会从你背包内移除。" +#, java-format +msgid "§b{0}§d unlocked the island." +msgstr "§b{0}§d解锁了该岛。" #, java-format -msgid "" -"§4All required items must be placed on your island, within {0} blocks of you." -msgstr "" +msgid "§cSKY §f> §7 {0}" +msgstr "§cSKY§f>§7{0}" #, java-format -msgid "§eTo complete this challenge, use §f/c c {0}" -msgstr "" +msgid "§b{0}§d has been removed from the island group." +msgstr "§b{0}§d已从岛群中删除。" -msgid "§4Invalid challenge name! Use /c help for more information" -msgstr "§4错误的挑战名!输入/c help 获取更多信息" +#, java-format +msgid "§9{1} §7- {0}" +msgstr "§9{1} §7- {0}" -msgid "§eSending you to spawn." -msgstr "" +msgid "§aCongratulations! §eYour island has appeared." +msgstr "§a恭喜!§e您的岛屿已出现。" -msgid "§eThe island has been §cLOCKED§e." -msgstr "" +msgid "§cNote:§e Construction might still be ongoing." +msgstr "§c 注意:§e 建设工作可能仍在进行中。" -msgid "§9Hold your horses! You have to be patient..." -msgstr "" +msgid "Use §9/is h§r or the §9/is§r menu to go there." +msgstr "使用§9/is-h§r或§9/is§r菜单前往那里。" -msgid "§9Not really patient, are you?" -msgstr "" +#, java-format +msgid "Unable to locate schematic {0}, contact a server-admin" +msgstr "找不到蓝图 {0},请与服务器管理员联系" -msgid "§9Be patient, young padawan" -msgstr "" +#, java-format +msgid "§cWatchdog!§9 Unable to locate a chest within {0}, bailing out." +msgstr "§c看门狗!§9 无法在 {0} 内找到一个箱子,正在退出。" -msgid "§9Patience you MUST have, young padawan" -msgstr "" +msgid "UNKNOWN" +msgstr "未知" -msgid "§9The two most powerful warriors are patience and time." -msgstr "" +msgid "ANIMAL" +msgstr "动物" -msgid "§4Unable to find a safe home-location on your island!" -msgstr "" +msgid "MONSTER" +msgstr "怪物" -msgid "§cWARNING: §eTeleporting you to mid-air." -msgstr "" +msgid "VILLAGER" +msgstr "村民" -msgid "§aTeleporting you to your island." -msgstr "§a将你传送回自己的岛屿." +msgid "GOLEM" +msgstr "铁傀儡" #, java-format -msgid "§aYou will be teleported in {0} seconds." -msgstr "§a将在 {0} 秒后进行传送." - -msgid "§4Unable to warp you to that player''s island!" -msgstr "§4无法传送至玩家的岛屿!" +msgid "§c{0}" +msgstr "§c{0}" #, java-format -msgid "§aTeleporting you to {0}''s island." -msgstr "" - -msgid "§7Teleport cancelled" -msgstr "" +msgid "§7{0}: §a{1}§7 (max. {2})" +msgstr "§7{0}:§a{1}§7(最多{2})" From 3965f6fec3fe582398000a73fb491fc9304ac967 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:54:49 +0800 Subject: [PATCH 165/190] 8 -> 21 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index f501ed62a..6fbd68b9c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,7 +42,7 @@ allprojects { group = "ovh.uskyblock" version = "3.2.0-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_1_8 +java.sourceCompatibility = JavaVersion.VERSION_21 publishing { publications.create("maven") { From 4e45d717a8ae0b8fd6e911c533c5078eff6e2095 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:56:55 +0800 Subject: [PATCH 166/190] 21 -> 17 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6fbd68b9c..e9ab72910 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,7 +42,7 @@ allprojects { group = "ovh.uskyblock" version = "3.2.0-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_21 +java.sourceCompatibility = JavaVersion.VERSION_17 publishing { publications.create("maven") { From d35bdad4d050e13fbdffefee24e7679f63efcb66 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 14:33:10 +0800 Subject: [PATCH 167/190] =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 9 ++++++++- bukkit-utils/build.gradle.kts | 8 ++++++++ gradle.properties | 2 ++ uSkyBlock-API/build.gradle.kts | 3 --- uSkyBlock-APIv2/build.gradle.kts | 3 --- uSkyBlock-Core/build.gradle.kts | 8 +++----- uSkyBlock-FAWE/build.gradle.kts | 2 ++ 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e9ab72910..d75cf5c7c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,11 +38,18 @@ allprojects { maven("https://repo.minebench.de/") maven("https://repo.maven.apache.org/maven2/") } + + java.sourceCompatibility = JavaVersion.VERSION_21 + java.targetCompatibility = JavaVersion.VERSION_21 + kotlin.jvmToolchain(21) + + tasks.withType().configureEach { + enabled = false + } } group = "ovh.uskyblock" version = "3.2.0-SNAPSHOT" -java.sourceCompatibility = JavaVersion.VERSION_17 publishing { publications.create("maven") { diff --git a/bukkit-utils/build.gradle.kts b/bukkit-utils/build.gradle.kts index b754192d7..09a35db74 100644 --- a/bukkit-utils/build.gradle.kts +++ b/bukkit-utils/build.gradle.kts @@ -19,3 +19,11 @@ val testsJar by tasks.registering(Jar::class) { archiveClassifier.set("tests") from(sourceSets["test"].output) } + +configurations { + create("testsJar") { + isCanBeConsumed = true + isCanBeResolved = false + outgoing.artifact(testsJar) + } +} diff --git a/gradle.properties b/gradle.properties index c5574b867..d9c76c6b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,3 +3,5 @@ systemProp.http.proxyPort=7890 systemProp.https.proxyHost=127.0.0.1 systemProp.https.proxyPort=7890 + +org.gradle.java.installations.paths=D:/Java/jdk-21.0.3 diff --git a/uSkyBlock-API/build.gradle.kts b/uSkyBlock-API/build.gradle.kts index e097930b0..5f60352d9 100644 --- a/uSkyBlock-API/build.gradle.kts +++ b/uSkyBlock-API/build.gradle.kts @@ -11,6 +11,3 @@ dependencies { group = "com.github.rlf" description = "uSkyBlock-API" -java { - withJavadocJar() -} diff --git a/uSkyBlock-APIv2/build.gradle.kts b/uSkyBlock-APIv2/build.gradle.kts index 61434a538..6ca5ac442 100644 --- a/uSkyBlock-APIv2/build.gradle.kts +++ b/uSkyBlock-APIv2/build.gradle.kts @@ -10,6 +10,3 @@ dependencies { description = "uSkyBlock-APIv2" -java { - withJavadocJar() -} diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index d171a533b..4cbcf8c4b 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -11,12 +11,14 @@ dependencies { implementation("org.bstats:bstats-bukkit:3.0.1") implementation("com.google.inject:guice:7.0.0") implementation("org.jetbrains:annotations:23.0.0") - testImplementation(project(":bukkit-utils")) + testImplementation(project(":bukkit-utils", "testsJar")) testImplementation("org.hamcrest:hamcrest:2.2") testImplementation("org.hamcrest:hamcrest-library:2.2") testImplementation("junit:junit:4.13.2") testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") compileOnly("net.milkbowl.vault:VaultAPI:1.7") compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") @@ -37,7 +39,3 @@ dependencies { } description = "uSkyBlock-Core" - -java { - withJavadocJar() -} diff --git a/uSkyBlock-FAWE/build.gradle.kts b/uSkyBlock-FAWE/build.gradle.kts index 86a9c611d..5d97a5a1d 100644 --- a/uSkyBlock-FAWE/build.gradle.kts +++ b/uSkyBlock-FAWE/build.gradle.kts @@ -4,6 +4,8 @@ dependencies { + implementation(project(":bukkit-utils")) + implementation(project(":uSkyBlock-API")) implementation(project(":uSkyBlock-Core")) compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core:2.13.0") compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit:2.13.0") From 6401e7a50d353c53fe040a4f2bd5f2d710ead7d5 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 15:41:38 +0800 Subject: [PATCH 168/190] =?UTF-8?q?=E6=9E=84=E5=BB=BA=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uSkyBlock-Core/src/main/resources/plugin.yml | 22 ++++++++--------- uSkyBlock-Plugin/build.gradle.kts | 24 +++++++++++++++++++ .../src/main/resources/version.json | 2 +- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index a92ed219c..7f37b919e 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: uSkyBlock main: us.talabrek.ultimateskyblock.uSkyBlock -version: ${project.version} -description: Ultimate SkyBlock v${project.version}-${buildNumber} +version: cong +description: Ultimate SkyBlock author: R4zorax (and more) load: STARTUP softdepend: @@ -19,15 +19,15 @@ softdepend: - MVdWPlaceholderAPI api-version: 1.20.6 libraries: - - com.google.code.gson:gson:${gson.version} - - com.google.inject:guice:${guice.version} - - com.google.guava:guava:${guava.version} - - net.kyori:adventure-api:${adventure-api.version} - - net.kyori:adventure-platform-bukkit:${adventure-bukkit.version} - - org.apache.commons:commons-lang3:${apache-commons.version} - - org.apache.commons:commons-text:${apache-commons-text.version} - - org.apache.httpcomponents:httpclient:${apache-http.version} - - org.apache.maven:maven-artifact:${maven-artifact.version} + - com.google.code.gson:gson:2.10.1 + - com.google.inject:guice:7.0.0 + - com.google.guava:guava:33.1.0-jre + - net.kyori:adventure-api:4.16.0 + - net.kyori:adventure-platform-bukkit:4.3.2 + - org.apache.commons:commons-lang3:3.14.0 + - org.apache.commons:commons-text:1.12.0 + - org.apache.httpcomponents:httpclient:4.5.14 + - org.apache.maven:maven-artifact:3.8.6 commands: challenges: diff --git a/uSkyBlock-Plugin/build.gradle.kts b/uSkyBlock-Plugin/build.gradle.kts index 414db6fee..57d2e20fa 100644 --- a/uSkyBlock-Plugin/build.gradle.kts +++ b/uSkyBlock-Plugin/build.gradle.kts @@ -1,8 +1,32 @@ +import java.time.LocalDate +import java.time.format.DateTimeFormatter + /* * This file was generated by the Gradle 'init' task. */ +plugins { + java + `maven-publish` + id("com.gradleup.shadow") version "8.3.6" +} + +val version = "cong-" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) // 替换为实际版本号 + + +tasks { + register("buildPlugin") { + group = "plugin" + from(sourceSets.main.map { it.output }) + archiveClassifier.set("") + configurations = listOf(project.configurations.runtimeClasspath.get()) + doLast { + println(archiveFile.get()) + } + } +} + dependencies { implementation(project(":uSkyBlock-API")) implementation(project(":uSkyBlock-Core")) diff --git a/uSkyBlock-Plugin/src/main/resources/version.json b/uSkyBlock-Plugin/src/main/resources/version.json index 5dc94a354..28fc1049e 100644 --- a/uSkyBlock-Plugin/src/main/resources/version.json +++ b/uSkyBlock-Plugin/src/main/resources/version.json @@ -1 +1 @@ -{"version": "${project.version}", "build": "${env.GITHUB_RUN_NUMBER}", "minecraft-version": "${spigotapi.version}"} +{"version": "cong", "minecraft-version": "1.21.4-R0.1-SNAPSHOT"} From 131cf3b33000d6149c56554ab396aa608a97a252 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 15:43:45 +0800 Subject: [PATCH 169/190] =?UTF-8?q?=E7=B4=AB=E7=8F=80=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=BD=9C=E5=BD=B1=E8=B4=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ultimateskyblock/event/SpawnEvents.java | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index 6744a0cc0..177c98204 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -8,11 +8,7 @@ import org.bukkit.Registry; import org.bukkit.World; import org.bukkit.block.Biome; -import org.bukkit.entity.EntitySnapshot; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Phantom; -import org.bukkit.entity.Player; -import org.bukkit.entity.WaterMob; +import org.bukkit.entity.*; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; @@ -29,9 +25,7 @@ import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; -import java.util.Collection; -import java.util.Objects; -import java.util.Set; +import java.util.*; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -107,11 +101,35 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { checkLimits(event, event.getEntity().getType(), event.getLocation()); if (event.getEntity() instanceof WaterMob) { Location loc = event.getLocation(); - if (isDeepOceanBiome(loc) && isPrismarineRoof(loc)) { + if (isPrismarineRoof(loc)) { loc.getWorld().spawnEntity(loc, EntityType.GUARDIAN); event.setCancelled(true); } } + if (!event.isCancelled() && event.getEntity() instanceof Enderman) { + Location loc = event.getLocation(); + + if(isPurpurFloor(loc)) { + if (isEndBiome(loc)) { + Random r = new Random(); + if (r.nextInt(10) == 0) { + loc.getWorld().spawnEntity(loc, EntityType.SHULKER); + event.setCancelled(true); + } + } else { + loc.getWorld().spawnEntity(loc, EntityType.SHULKER); + event.setCancelled(true); + } + } + } + } + + private boolean isPurpurFloor(Location loc){ + List purpurBlocks = Arrays.asList(Material.PURPUR_BLOCK, Material.PURPUR_PILLAR, Material.PURPUR_SLAB); + loc.setY(loc.getY()-1); + boolean ret=purpurBlocks.contains(loc.getBlock().getType()); + loc.setY(loc.getY()+1); + return ret; } private boolean isPrismarineRoof(Location loc) { @@ -119,9 +137,8 @@ private boolean isPrismarineRoof(Location loc) { return prismarineBlocks.contains(LocationUtil.findRoofBlock(loc).getType()); } - private boolean isDeepOceanBiome(Location loc) { - Collection deepOceans = Set.of(Biome.DEEP_OCEAN, Biome.DEEP_COLD_OCEAN, Biome.DEEP_FROZEN_OCEAN, Biome.DEEP_LUKEWARM_OCEAN); - return deepOceans.contains(loc.getWorld().getBiome(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); + private boolean isEndBiome(Location loc) { + return loc.getWorld().getBiome(loc.getBlockX(), loc.getBlockZ())==Biome.THE_END; } private void checkLimits(Cancellable event, EntityType entityType, Location location) { From 66a91b94301b4123739c9b921d622149a4d36986 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 15:46:10 +0800 Subject: [PATCH 170/190] =?UTF-8?q?=E5=88=A0=E7=82=B9=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 47fa57167..49d5b9546 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -530,7 +530,7 @@ private Inventory createMainMenu(Player player) { } meta4.setLore(lores); menuItem.setItemMeta(meta4); - menu.addItem(menuItem); + //menu.addItem(menuItem); lores.clear(); menuItem = new ItemStack(Material.IRON_BARS, 1); @@ -553,7 +553,7 @@ private Inventory createMainMenu(Player player) { } meta4.setLore(lores); menuItem.setItemMeta(meta4); - menu.addItem(menuItem); + //menu.addItem(menuItem); lores.clear(); if (plugin.getIslandInfo(player).hasWarp()) { @@ -620,7 +620,7 @@ private Inventory createMainMenu(Player player) { } meta4.setLore(lores); menuItem.setItemMeta(meta4); - menu.setItem(15, menuItem); + menu.setItem(13, menuItem); lores.clear(); if (islandInfo.isLeader(player)) { if (config.getYamlConfig().getBoolean("island-schemes-enabled", true)) { From 2bbfbd8273f716ebf283d97bedf0fe960a4e57c3 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:09:20 +0800 Subject: [PATCH 171/190] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=9B=E5=87=BA?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/IslandCommand.java | 32 +++------------- .../command/island/FarewellCommand.java | 34 +++++++++++++++++ .../command/island/GreetingCommand.java | 37 +++++++++++++++++++ 3 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/FarewellCommand.java create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/GreetingCommand.java diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java index 62ae8c7a1..70a331dbb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java @@ -14,31 +14,7 @@ import us.talabrek.ultimateskyblock.command.completion.OnlinePlayerTabCompleter; import us.talabrek.ultimateskyblock.command.completion.PermissionTabCompleter; import us.talabrek.ultimateskyblock.command.completion.SchematicTabCompleter; -import us.talabrek.ultimateskyblock.command.island.AcceptRejectCommand; -import us.talabrek.ultimateskyblock.command.island.AutoCommand; -import us.talabrek.ultimateskyblock.command.island.BanCommand; -import us.talabrek.ultimateskyblock.command.island.BiomeCommand; -import us.talabrek.ultimateskyblock.command.island.CreateCommand; -import us.talabrek.ultimateskyblock.command.island.HomeCommand; -import us.talabrek.ultimateskyblock.command.island.InfoCommand; -import us.talabrek.ultimateskyblock.command.island.InviteCommand; -import us.talabrek.ultimateskyblock.command.island.KickCommand; -import us.talabrek.ultimateskyblock.command.island.LeaveCommand; -import us.talabrek.ultimateskyblock.command.island.LevelCommand; -import us.talabrek.ultimateskyblock.command.island.LockUnlockCommand; -import us.talabrek.ultimateskyblock.command.island.LogCommand; -import us.talabrek.ultimateskyblock.command.island.MakeLeaderCommand; -import us.talabrek.ultimateskyblock.command.island.MobLimitCommand; -import us.talabrek.ultimateskyblock.command.island.PartyCommand; -import us.talabrek.ultimateskyblock.command.island.PermCommand; -import us.talabrek.ultimateskyblock.command.island.RestartCommand; -import us.talabrek.ultimateskyblock.command.island.SetHomeCommand; -import us.talabrek.ultimateskyblock.command.island.SetWarpCommand; -import us.talabrek.ultimateskyblock.command.island.SpawnCommand; -import us.talabrek.ultimateskyblock.command.island.ToggleWarp; -import us.talabrek.ultimateskyblock.command.island.TopCommand; -import us.talabrek.ultimateskyblock.command.island.TrustCommand; -import us.talabrek.ultimateskyblock.command.island.WarpCommand; +import us.talabrek.ultimateskyblock.command.island.*; import us.talabrek.ultimateskyblock.menu.SkyBlockMenu; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -89,7 +65,9 @@ public IslandCommand( @NotNull BanCommand banCommand, @NotNull LockUnlockCommand lockUnlockCommand, @NotNull TopCommand topCommand, - @NotNull BiomeCommand biomeCommand + @NotNull BiomeCommand biomeCommand, + @NotNull GreetingCommand greetingCommand, + @NotNull FarewellCommand farewellCommand ) { super("island|is", "usb.island.create", marktr("general island command")); this.plugin = plugin; @@ -136,6 +114,8 @@ public IslandCommand( add(mobLimitCommand); add(autoCommand); add(permCommand); + add(greetingCommand); + add(farewellCommand); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/FarewellCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/FarewellCommand.java new file mode 100644 index 000000000..202b99c41 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/FarewellCommand.java @@ -0,0 +1,34 @@ +package us.talabrek.ultimateskyblock.command.island; + +import com.google.inject.Inject; +import org.bukkit.entity.Player; +import us.talabrek.ultimateskyblock.island.IslandInfo; +import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +public class FarewellCommand extends RequireIslandCommand { + @Inject + public FarewellCommand(uSkyBlock plugin) { + super(plugin, "farewell", null, "?msg", marktr("Change farewell message of your island")); + } + + @Override + protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandInfo island, Map data, String... args) { + us.talabrek.ultimateskyblock.api.IslandInfo islandInfo = uSkyBlock.getInstance().getIslandInfo(player); + StringBuilder str= new StringBuilder(); + for (String arg:args){ + str.append(arg).append(" "); + } + String cmd = "console:rg flag -w skyworld " + islandInfo.getName() + "island farewell "+str; + uSkyBlock.getInstance().execCommand(player, cmd,false); + + str = new StringBuilder(str.toString().replaceAll("&(?=[0-9a-fA-FkKlLmMnNoOrR])", "\u00a7")); + player.sendMessage(tr("\u00a7bYour island farewell message has changed to: \u00a7r")+str); + return true; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/GreetingCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/GreetingCommand.java new file mode 100644 index 000000000..20541de08 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/GreetingCommand.java @@ -0,0 +1,37 @@ +package us.talabrek.ultimateskyblock.command.island; + +import com.google.inject.Inject; +import dk.lockfuglsang.minecraft.command.AbstractCommand; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.talabrek.ultimateskyblock.api.IslandInfo; +import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +public class GreetingCommand extends RequireIslandCommand { + @Inject + public GreetingCommand(@NotNull uSkyBlock plugin) { + super(plugin, "greeting", null, "?msg", marktr("Change greeting message of your island")); + } + + @Override + protected boolean doExecute(String alias, Player player, PlayerInfo pi, us.talabrek.ultimateskyblock.island.IslandInfo island, Map data, String... args) { + IslandInfo islandInfo = uSkyBlock.getInstance().getIslandInfo(player); + StringBuilder str= new StringBuilder(); + for (String arg:args){ + str.append(arg).append(" "); + } + String cmd = "console:rg flag -w skyworld " + islandInfo.getName() + "island greeting "+str; + uSkyBlock.getInstance().execCommand(player, cmd,false); + + str = new StringBuilder(str.toString().replaceAll("&(?=[0-9a-fA-FkKlLmMnNoOrR])", "\u00a7")); + player.sendMessage(tr("\u00a7bYour island greeting message has changed to: \u00a7r")+str); + return true; + } +} From acaf22d08ebc47a94ee44c741207260c060a1ae3 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:09:44 +0800 Subject: [PATCH 172/190] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BF=E5=AE=A2?= =?UTF-8?q?=E5=9C=A8=E5=9C=B0=E7=8B=B1=E5=8F=AF=E4=BB=A5=E6=8D=A1=E4=B8=9C?= =?UTF-8?q?=E8=A5=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java index dc56979d9..d8639a1d5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java @@ -114,7 +114,7 @@ public void onPickupEvent(EntityPickupItemEvent event) { return; } Player player = (Player) event.getEntity(); - if (event.isCancelled() || !plugin.getWorldManager().isSkyWorld(player.getWorld())) { + if (event.isCancelled() || !plugin.getWorldManager().isSkyWorld(player.getWorld()) || !plugin.getWorldManager().isSkyNether(player.getWorld() )) { clearDropInfo(event.getItem()); return; } From 1007367fbdb2ab274da9326009f6df83fca548c0 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:12:58 +0800 Subject: [PATCH 173/190] =?UTF-8?q?tmd=E9=B1=BC=E7=AE=97=E4=BB=80=E4=B9=88?= =?UTF-8?q?=E6=80=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/us/talabrek/ultimateskyblock/island/LimitLogic.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index 1246cbf14..6ccfdcef4 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -86,11 +86,12 @@ public Map getCreatureMax(us.talabrek.ultimateskyblock.ap public CreatureType getCreatureType(LivingEntity creature) { if (creature instanceof Monster - || creature instanceof WaterMob || creature instanceof Slime || creature instanceof Ghast) { return CreatureType.MONSTER; - } else if (creature instanceof Animals) { + } else if (creature instanceof Animals + || creature instanceof WaterMob + ) { return CreatureType.ANIMAL; } else if (creature instanceof Villager) { return CreatureType.VILLAGER; From bac070c0bb22503727af7966ab7a7fb798aa8f2b Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:14:55 +0800 Subject: [PATCH 174/190] =?UTF-8?q?tmd=E8=BF=99=E6=80=AA=E7=89=A9=E4=B8=8A?= =?UTF-8?q?=E9=99=90=E6=80=8E=E4=B9=88=E7=AE=97=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ultimateskyblock/island/LimitLogic.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index 6ccfdcef4..cfc4d54f5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -7,15 +7,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.entity.Animals; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Ghast; -import org.bukkit.entity.Golem; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Monster; -import org.bukkit.entity.Slime; -import org.bukkit.entity.Villager; -import org.bukkit.entity.WaterMob; +import org.bukkit.entity.*; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; @@ -87,15 +79,16 @@ public Map getCreatureMax(us.talabrek.ultimateskyblock.ap public CreatureType getCreatureType(LivingEntity creature) { if (creature instanceof Monster || creature instanceof Slime - || creature instanceof Ghast) { + || creature instanceof Ghast + || creature instanceof Shulker) { return CreatureType.MONSTER; } else if (creature instanceof Animals - || creature instanceof WaterMob - ) { + || creature instanceof WaterMob) { return CreatureType.ANIMAL; } else if (creature instanceof Villager) { return CreatureType.VILLAGER; - } else if (creature instanceof Golem) { + } else if (creature instanceof IronGolem + || creature instanceof Snowman) { return CreatureType.GOLEM; } return CreatureType.UNKNOWN; From 4090f63b6e8821a12dce2e43eb9e46ea5eb9dbcc Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:16:32 +0800 Subject: [PATCH 175/190] =?UTF-8?q?=E8=AE=BF=E5=AE=A2=E6=94=BB=E5=87=BB?= =?UTF-8?q?=E6=BD=9C=E5=BD=B1=E8=B4=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ultimateskyblock/event/GriefEvents.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java index 10ffc38a9..769fd6cff 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java @@ -7,16 +7,7 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Animals; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Monster; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.entity.Wither; -import org.bukkit.entity.WitherSkull; +import org.bukkit.entity.*; import org.bukkit.event.Cancellable; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -134,7 +125,8 @@ public void onEntityDamage(EntityDamageByEntityEvent event) { private void cancelMobDamage(EntityDamageByEntityEvent event) { if (killAnimalsEnabled && event.getEntity() instanceof Animals) { event.setCancelled(true); - } else if (killMonstersEnabled && event.getEntity() instanceof Monster) { + } else if (killMonstersEnabled && (event.getEntity() instanceof Monster + || event.getEntity() instanceof Shulker)) { event.setCancelled(true); } } From 8b2095c14f7db6b8a8c1ab18d221235690004e67 Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Sun, 27 Apr 2025 17:47:00 +0800 Subject: [PATCH 176/190] =?UTF-8?q?=E4=B9=B0=E6=BC=8F=E6=96=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ultimateskyblock/api/IslandInfo.java | 3 + .../command/IslandCommand.java | 4 +- .../command/island/BuyHopperLimitCommand.java | 73 +++++++++++++++++++ .../ultimateskyblock/event/PlayerEvents.java | 5 +- .../island/BlockLimitLogic.java | 3 + .../ultimateskyblock/island/IslandInfo.java | 9 +++ .../ultimateskyblock/island/LimitLogic.java | 10 ++- .../island/task/LocateChestTask.java | 2 +- .../ultimateskyblock/menu/SkyBlockMenu.java | 16 +++- 9 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java diff --git a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java index 70649b32b..3ea824561 100644 --- a/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java +++ b/uSkyBlock-API/src/main/java/us/talabrek/ultimateskyblock/api/IslandInfo.java @@ -310,4 +310,7 @@ default String getBiome() { */ double getScoreOffset(); + public int getHopperLimit(); + public void setHopperLimit(int limit); + } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java index 70a331dbb..f15f4a027 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/IslandCommand.java @@ -67,7 +67,8 @@ public IslandCommand( @NotNull TopCommand topCommand, @NotNull BiomeCommand biomeCommand, @NotNull GreetingCommand greetingCommand, - @NotNull FarewellCommand farewellCommand + @NotNull FarewellCommand farewellCommand, + @NotNull BuyHopperLimitCommand buyHopperLimitCommand ) { super("island|is", "usb.island.create", marktr("general island command")); this.plugin = plugin; @@ -116,6 +117,7 @@ public IslandCommand( add(permCommand); add(greetingCommand); add(farewellCommand); + add(buyHopperLimitCommand); } @Override diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java new file mode 100644 index 000000000..313783bf6 --- /dev/null +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java @@ -0,0 +1,73 @@ +package us.talabrek.ultimateskyblock.command.island; + +import com.google.inject.Inject; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.economy.EconomyResponse; +import org.bukkit.entity.Player; +import us.talabrek.ultimateskyblock.island.IslandInfo; +import us.talabrek.ultimateskyblock.player.PlayerInfo; +import us.talabrek.ultimateskyblock.uSkyBlock; + +import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; +import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; + +import java.util.Map; + +import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; +import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; + +public class BuyHopperLimitCommand extends RequireIslandCommand { + + @Inject + public BuyHopperLimitCommand(uSkyBlock plugin) { + super(plugin, "hopper", "usb.island.create", "?oper", marktr("Pay to add hopper limits.")); + } + + private int calcPrice(int curlimit) { + int price; + if (curlimit <= 40) price = 25 * curlimit; + else if (curlimit >= 90) price = 10000; + else { + price = (int) (1000 * Math.pow(1.05, curlimit - 40)); + if (price > 10000) price = 10000; + } + return price; + } + + @Override + protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandInfo island, Map data, String... args) { + us.talabrek.ultimateskyblock.api.IslandInfo islandInfo = uSkyBlock.getInstance().getIslandInfo(player); + int curlimit = islandInfo.getHopperLimit(); + if (args.length > 0 && args[0].equals("buy")) { + int price = calcPrice(curlimit); + uSkyBlock.getInstance().getHookManager().getEconomyHook().ifPresent((hook) -> { + if (hook.getBalance(player) >= price) { + boolean success; + if (price == 0) { + success = true; + } else { + success = hook.withdrawPlayer(player, price); + } + if (success) { + islandInfo.setHopperLimit(curlimit + 1); + player.sendMessage(tr("\u00a7a\u00a7lBuy Extra Hopper Success!")); + player.sendMessage(tr("\u00a77======================")); + } else { + player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); + } + } else { + player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); + player.sendMessage(tr("\u00a7dYou do not have enough money!")); + player.sendMessage(tr("\u00a7dYou have {0}", hook.getBalance(player))); + } + }); + } else { + player.sendMessage(tr("\u00a7b\u00a7lBuy Extra Hopper Limit")); + player.sendMessage(tr("\u00a77======================")); + } + player.sendMessage(tr("\u00a7bCurrent Extra Limit is {0}", islandInfo.getHopperLimit())); + player.sendMessage(tr("\u00a7bPrice to buy another hopper limit is {0}", calcPrice(islandInfo.getHopperLimit()))); + plugin.execCommand(player, "console:tellraw " + player.getName() + " [{\"text\":\"click to buy hopper\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/is hopper buy\"}}]", false); + return true; + } +} diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index a1fb14548..81a5315aa 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -368,7 +368,10 @@ public void run() { } if (canPlace == BlockLimitLogic.CanPlace.NO) { event.setCancelled(true); - player.sendMessage(tr("\u00a74You''ve hit the {0} limit!\u00a7e You can''t have more of that type on your island!\u00a79 Max: {1,number}", ItemStackUtil.getItemName(new ItemStack(type)), plugin.getBlockLimitLogic().getLimit(type))); + if (type == Material.HOPPER) + player.sendMessage(tr("\u00a74You''ve hit the {0} limit!\u00a7e You can''t have more of that type on your island!\u00a79 Max: {1,number}", ItemStackUtil.getItemName(new ItemStack(type)), (plugin.getBlockLimitLogic().getLimit(type)+islandInfo.getHopperLimit()))); + else + player.sendMessage(tr("\u00a74You''ve hit the {0} limit!\u00a7e You can''t have more of that type on your island!\u00a79 Max: {1,number}", ItemStackUtil.getItemName(new ItemStack(type)), plugin.getBlockLimitLogic().getLimit(type))); return; } plugin.getBlockLimitLogic().incBlockCount(islandInfo.getIslandLocation(), type); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java index ad05ee6c4..a3f4e41d6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/BlockLimitLogic.java @@ -96,6 +96,9 @@ public CanPlace canPlace(Material type, IslandInfo islandInfo) { } else if (count == -2) { return CanPlace.UNCERTAIN; } + if (type == Material.HOPPER){ + count -= islandInfo.getHopperLimit(); + } return count < blockLimits.getOrDefault(type, Integer.MAX_VALUE) ? CanPlace.YES : CanPlace.NO; } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 289f6393e..65c0b672d 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -1096,6 +1096,15 @@ public void setLeafBreaks(int breaks) { dirty = true; } + public int getHopperLimit() { + return config.getInt("blocks.hopperLimits", 0); + } + + public void setHopperLimit(int limit) { + config.set("blocks.hopperLimits", limit); + dirty = true; + } + @Override public String getSchematicName() { return config.getString("general.schematicName", Settings.island_schematicName); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index cfc4d54f5..c33cbd38e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -150,16 +150,20 @@ public String getSummary(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo) Map blockLimits = blockLimitLogic.getLimits(); for (Map.Entry entry : blockLimits.entrySet()) { int blockCount = blockLimitLogic.getCount(entry.getKey(), islandInfo.getIslandLocation()); + int val = entry.getValue(); + if (entry.getKey() == Material.HOPPER){ + val += islandInfo.getHopperLimit(); + } if (blockCount >= 0) { sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", ItemStackUtil.getItemName(new ItemStack(entry.getKey())), - blockCount >= entry.getValue() ? tr("\u00a7c{0}", blockCount) : blockCount, - entry.getValue())).append("\n"); + blockCount >= val ? tr("\u00a7c{0}", blockCount) : blockCount, + val)).append("\n"); } else { sb.append(tr("\u00a77{0}: \u00a7a{1}\u00a77 (max. {2})", ItemStackUtil.getItemName(new ItemStack(entry.getKey())), tr("\u00a7c{0}", "?"), - entry.getValue())).append("\n"); + val)).append("\n"); } } return sb.toString().trim(); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java index 7b553fa70..bab2c1214 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java @@ -42,7 +42,7 @@ public void run() { // Just run again // TODO: this is hacky, waiting for async generation to complete. Should ideally be launched once the generation has finished. } else { - cancel(); + if (!this.isCancelled()) cancel(); if (chestLocation == null && player != null && player.isOnline()) { player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.durationAsString(Duration.between(start, timeout)))); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java index 49d5b9546..de61a9089 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/menu/SkyBlockMenu.java @@ -582,6 +582,15 @@ private Inventory createMainMenu(Player player) { menu.addItem(menuItem); lores.clear(); + menuItem = new ItemStack(Material.HOPPER, 1); + meta4 = menuItem.getItemMeta(); + meta4.setDisplayName(tr("\u00a7b\u00a7lBuy Extra Hopper Limit")); + addLore(lores, tr("\u00a7eCurrent Limit: \u00a7a{0,number,##}\u00a77(Default) + \u00a7a{1,number,##}\u00a77(Extra)", plugin.getBlockLimitLogic().getLimits().getOrDefault(Material.HOPPER, 0),islandInfo.getHopperLimit())); + meta4.setLore(lores); + menuItem.setItemMeta(meta4); + menu.addItem(menuItem); + lores.clear(); + menuItem = new ItemStack(Material.SHORT_GRASS, 1); meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lReturn to Spawn")); @@ -609,7 +618,7 @@ private Inventory createMainMenu(Player player) { menu.setItem(9, menuItem); // First item, 2nd line lores.clear(); - menuItem = new ItemStack(Material.HOPPER, 1); + menuItem = new ItemStack(Material.BEACON, 1); meta4 = requireNonNull(menuItem.getItemMeta()); meta4.setDisplayName(tr("\u00a7a\u00a7lChange Warp Location")); addLore(lores, "\u00a7f", tr("When your warp is activated,\nother players will be taken to\nthis point when they teleport\nto your island.")); @@ -748,9 +757,12 @@ private void onClickMainMenu(InventoryClickEvent event, ItemStack currentItem, P player.performCommand("island"); } else if (currentItem.getType() == Material.SHORT_GRASS) { player.performCommand("island spawn"); - } else if (currentItem.getType() == Material.HOPPER) { + } else if (currentItem.getType() == Material.BEACON) { player.performCommand("island setwarp"); player.performCommand("island"); + } else if (currentItem.getType() == Material.HOPPER) { + player.closeInventory(); + player.performCommand("island hopper"); } else if (currentItem.getType() == Material.WRITABLE_BOOK) { player.performCommand("island log"); } else if (currentItem.getType() == Material.OAK_DOOR) { From fb603caca70749ef162f20623f5bffa86e72ee71 Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Sun, 27 Apr 2025 17:48:40 +0800 Subject: [PATCH 177/190] gradle --- build.gradle.kts | 38 +++++++++++++++++++ bukkit-utils/build.gradle.kts | 7 ---- po-utils/build.gradle.kts | 13 ------- uSkyBlock-API/build.gradle.kts | 6 --- uSkyBlock-APIv2/build.gradle.kts | 6 --- uSkyBlock-Core/build.gradle.kts | 28 -------------- .../handler/WorldGuardHandler.java | 2 + 7 files changed, 40 insertions(+), 60 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index d75cf5c7c..f93eeef2a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,6 +48,44 @@ allprojects { } } +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + implementation("net.milkbowl.vault:VaultAPI:1.7") + implementation("io.papermc:paperlib:1.0.8") + implementation("org.bstats:bstats-bukkit:3.0.1") + implementation("com.google.inject:guice:7.0.0") + compileOnly("net.milkbowl.vault:VaultAPI:1.7") + compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") + compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") + compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") + compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + compileOnly("com.google.guava:guava:33.1.0-jre") + compileOnly("com.google.code.gson:gson:2.10.1") + compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.0.1-SNAPSHOT") { + exclude("*", "*") + } + compileOnly("net.kyori:adventure-api:4.16.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.2") + compileOnly("org.apache.commons:commons-lang3:3.14.0") + compileOnly("org.apache.commons:commons-text:1.12.0") + compileOnly("org.apache.httpcomponents:httpclient:4.5.14") + compileOnly("org.apache.maven:maven-artifact:3.8.6") + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") + testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") + testImplementation("org.hamcrest:hamcrest-core:1.3") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("com.google.code.gson:gson:2.8.9") +} + group = "ovh.uskyblock" version = "3.2.0-SNAPSHOT" diff --git a/bukkit-utils/build.gradle.kts b/bukkit-utils/build.gradle.kts index 09a35db74..5a8416745 100644 --- a/bukkit-utils/build.gradle.kts +++ b/bukkit-utils/build.gradle.kts @@ -4,13 +4,6 @@ dependencies { implementation(project(":po-utils")) - implementation("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") - implementation("net.milkbowl.vault:VaultAPI:1.7") - testImplementation("org.hamcrest:hamcrest-core:1.3") - testImplementation("org.hamcrest:hamcrest-library:1.3") - testImplementation("junit:junit:4.13.2") - testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("com.google.code.gson:gson:2.8.7") } description = "bukkit-utils" diff --git a/po-utils/build.gradle.kts b/po-utils/build.gradle.kts index e179685ee..bf20ba657 100644 --- a/po-utils/build.gradle.kts +++ b/po-utils/build.gradle.kts @@ -2,17 +2,4 @@ * This file was generated by the Gradle 'init' task. */ - -dependencies { - implementation("org.jetbrains:annotations:23.0.0") - testImplementation("junit:junit:4.13.2") - testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") - testImplementation("org.hamcrest:hamcrest:2.2") - testImplementation("org.hamcrest:hamcrest-library:2.2") -} - description = "po-utils" - -java { - withJavadocJar() -} diff --git a/uSkyBlock-API/build.gradle.kts b/uSkyBlock-API/build.gradle.kts index 5f60352d9..6b741e531 100644 --- a/uSkyBlock-API/build.gradle.kts +++ b/uSkyBlock-API/build.gradle.kts @@ -2,12 +2,6 @@ * This file was generated by the Gradle 'init' task. */ - -dependencies { - implementation("org.jetbrains:annotations:23.0.0") - compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") -} - group = "com.github.rlf" description = "uSkyBlock-API" diff --git a/uSkyBlock-APIv2/build.gradle.kts b/uSkyBlock-APIv2/build.gradle.kts index 6ca5ac442..c9bed0b91 100644 --- a/uSkyBlock-APIv2/build.gradle.kts +++ b/uSkyBlock-APIv2/build.gradle.kts @@ -2,11 +2,5 @@ * This file was generated by the Gradle 'init' task. */ - -dependencies { - implementation("org.jetbrains:annotations:23.0.0") - compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") -} - description = "uSkyBlock-APIv2" diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index 4cbcf8c4b..954006f1f 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -7,35 +7,7 @@ dependencies { implementation(project(":po-utils")) implementation(project(":uSkyBlock-API")) implementation(project(":uSkyBlock-APIv2")) - implementation("io.papermc:paperlib:1.0.8") - implementation("org.bstats:bstats-bukkit:3.0.1") - implementation("com.google.inject:guice:7.0.0") - implementation("org.jetbrains:annotations:23.0.0") testImplementation(project(":bukkit-utils", "testsJar")) - testImplementation("org.hamcrest:hamcrest:2.2") - testImplementation("org.hamcrest:hamcrest-library:2.2") - testImplementation("junit:junit:4.13.2") - testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") - testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") - testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - compileOnly("net.milkbowl.vault:VaultAPI:1.7") - compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") - compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") - compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") - compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") - compileOnly("com.google.guava:guava:33.1.0-jre") - compileOnly("com.google.code.gson:gson:2.10.1") - compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.0.1-SNAPSHOT") { - exclude("*", "*") - } - compileOnly("net.kyori:adventure-api:4.16.0") - compileOnly("net.kyori:adventure-platform-bukkit:4.3.2") - compileOnly("org.apache.commons:commons-lang3:3.14.0") - compileOnly("org.apache.commons:commons-text:1.12.0") - compileOnly("org.apache.httpcomponents:httpclient:4.5.14") - compileOnly("org.apache.maven:maven-artifact:3.8.6") } description = "uSkyBlock-Core" diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index c6fa5e3cd..e03d3c350 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -286,6 +286,8 @@ public static void setupGlobal(World world) { global = new GlobalProtectedRegion("__global__"); } global.setFlag(Flags.BUILD, StateFlag.State.DENY); + global.setFlag(Flags.OTHER_EXPLOSION, StateFlag.State.ALLOW); + global.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.ALLOW); if (Settings.island_allowPvP) { global.setFlag(Flags.PVP, StateFlag.State.ALLOW); } else { From 5aac3b5b96dccd2c763bb4c5f02d6ebc973ed1bf Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Sun, 27 Apr 2025 17:56:42 +0800 Subject: [PATCH 178/190] gradle failed --- build.gradle.kts | 38 -------------------- bukkit-utils/build.gradle.kts | 7 ++++ po-utils/build.gradle.kts | 13 +++++++ uSkyBlock-API/build.gradle.kts | 6 ++++ uSkyBlock-APIv2/build.gradle.kts | 6 ++++ uSkyBlock-Core/build.gradle.kts | 28 +++++++++++++++ uSkyBlock-Core/src/main/resources/plugin.yml | 2 +- 7 files changed, 61 insertions(+), 39 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f93eeef2a..d75cf5c7c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,44 +48,6 @@ allprojects { } } -dependencies { - implementation("org.jetbrains:annotations:23.0.0") - implementation("net.milkbowl.vault:VaultAPI:1.7") - implementation("io.papermc:paperlib:1.0.8") - implementation("org.bstats:bstats-bukkit:3.0.1") - implementation("com.google.inject:guice:7.0.0") - compileOnly("net.milkbowl.vault:VaultAPI:1.7") - compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") - compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") - compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") - compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") - compileOnly("com.google.guava:guava:33.1.0-jre") - compileOnly("com.google.code.gson:gson:2.10.1") - compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.0.1-SNAPSHOT") { - exclude("*", "*") - } - compileOnly("net.kyori:adventure-api:4.16.0") - compileOnly("net.kyori:adventure-platform-bukkit:4.3.2") - compileOnly("org.apache.commons:commons-lang3:3.14.0") - compileOnly("org.apache.commons:commons-text:1.12.0") - compileOnly("org.apache.httpcomponents:httpclient:4.5.14") - compileOnly("org.apache.maven:maven-artifact:3.8.6") - testImplementation("org.hamcrest:hamcrest:2.2") - testImplementation("org.hamcrest:hamcrest-library:2.2") - testImplementation("junit:junit:4.13.2") - testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") - testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") - testImplementation("org.hamcrest:hamcrest:2.2") - testImplementation("org.hamcrest:hamcrest-library:2.2") - testImplementation("org.hamcrest:hamcrest-core:1.3") - testImplementation("org.hamcrest:hamcrest-library:1.3") - testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("com.google.code.gson:gson:2.8.9") -} - group = "ovh.uskyblock" version = "3.2.0-SNAPSHOT" diff --git a/bukkit-utils/build.gradle.kts b/bukkit-utils/build.gradle.kts index 5a8416745..09a35db74 100644 --- a/bukkit-utils/build.gradle.kts +++ b/bukkit-utils/build.gradle.kts @@ -4,6 +4,13 @@ dependencies { implementation(project(":po-utils")) + implementation("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") + implementation("net.milkbowl.vault:VaultAPI:1.7") + testImplementation("org.hamcrest:hamcrest-core:1.3") + testImplementation("org.hamcrest:hamcrest-library:1.3") + testImplementation("junit:junit:4.13.2") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("com.google.code.gson:gson:2.8.7") } description = "bukkit-utils" diff --git a/po-utils/build.gradle.kts b/po-utils/build.gradle.kts index bf20ba657..e179685ee 100644 --- a/po-utils/build.gradle.kts +++ b/po-utils/build.gradle.kts @@ -2,4 +2,17 @@ * This file was generated by the Gradle 'init' task. */ + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") +} + description = "po-utils" + +java { + withJavadocJar() +} diff --git a/uSkyBlock-API/build.gradle.kts b/uSkyBlock-API/build.gradle.kts index 6b741e531..5f60352d9 100644 --- a/uSkyBlock-API/build.gradle.kts +++ b/uSkyBlock-API/build.gradle.kts @@ -2,6 +2,12 @@ * This file was generated by the Gradle 'init' task. */ + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") +} + group = "com.github.rlf" description = "uSkyBlock-API" diff --git a/uSkyBlock-APIv2/build.gradle.kts b/uSkyBlock-APIv2/build.gradle.kts index c9bed0b91..6ca5ac442 100644 --- a/uSkyBlock-APIv2/build.gradle.kts +++ b/uSkyBlock-APIv2/build.gradle.kts @@ -2,5 +2,11 @@ * This file was generated by the Gradle 'init' task. */ + +dependencies { + implementation("org.jetbrains:annotations:23.0.0") + compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") +} + description = "uSkyBlock-APIv2" diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index 954006f1f..4cbcf8c4b 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -7,7 +7,35 @@ dependencies { implementation(project(":po-utils")) implementation(project(":uSkyBlock-API")) implementation(project(":uSkyBlock-APIv2")) + implementation("io.papermc:paperlib:1.0.8") + implementation("org.bstats:bstats-bukkit:3.0.1") + implementation("com.google.inject:guice:7.0.0") + implementation("org.jetbrains:annotations:23.0.0") testImplementation(project(":bukkit-utils", "testsJar")) + testImplementation("org.hamcrest:hamcrest:2.2") + testImplementation("org.hamcrest:hamcrest-library:2.2") + testImplementation("junit:junit:4.13.2") + testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") + compileOnly("net.milkbowl.vault:VaultAPI:1.7") + compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") + compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") + compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") + compileOnly("com.sk89q.worldguard:worldguard-bukkit:7.0.9") + compileOnly("com.google.guava:guava:33.1.0-jre") + compileOnly("com.google.code.gson:gson:2.10.1") + compileOnly("be.maximvdw:MVdWPlaceholderAPI:3.0.1-SNAPSHOT") { + exclude("*", "*") + } + compileOnly("net.kyori:adventure-api:4.16.0") + compileOnly("net.kyori:adventure-platform-bukkit:4.3.2") + compileOnly("org.apache.commons:commons-lang3:3.14.0") + compileOnly("org.apache.commons:commons-text:1.12.0") + compileOnly("org.apache.httpcomponents:httpclient:4.5.14") + compileOnly("org.apache.maven:maven-artifact:3.8.6") } description = "uSkyBlock-Core" diff --git a/uSkyBlock-Core/src/main/resources/plugin.yml b/uSkyBlock-Core/src/main/resources/plugin.yml index 7f37b919e..58712da9c 100644 --- a/uSkyBlock-Core/src/main/resources/plugin.yml +++ b/uSkyBlock-Core/src/main/resources/plugin.yml @@ -17,7 +17,7 @@ softdepend: - FastAsyncWorldEdit # placeholders - MVdWPlaceholderAPI -api-version: 1.20.6 +api-version: 1.21.4 libraries: - com.google.code.gson:gson:2.10.1 - com.google.inject:guice:7.0.0 From 89c16504e5e04b3c6e5b851bd19b5271bc94762b Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Sun, 27 Apr 2025 18:07:47 +0800 Subject: [PATCH 179/190] migrate to paper api --- uSkyBlock-Core/build.gradle.kts | 4 ++-- .../talabrek/ultimateskyblock/Settings.java | 1 + .../ultimateskyblock/biome/BiomeConfig.java | 1 + .../challenge/ChallengeFactory.java | 1 + .../command/island/BiomeCommand.java | 1 + .../ultimateskyblock/island/IslandInfo.java | 1 + .../talabrek/ultimateskyblock/uSkyBlock.java | 1 + .../ultimateskyblock/uuid/NullPlayer.java | 24 +++++++++++++++++-- 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index 4cbcf8c4b..8e0052502 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -17,10 +17,10 @@ dependencies { testImplementation("junit:junit:4.13.2") testImplementation("org.junit.vintage:junit-vintage-engine:5.9.0") testImplementation("org.mockito:mockito-core:5.14.2") - testImplementation("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") compileOnly("net.milkbowl.vault:VaultAPI:1.7") - compileOnly("org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.19") diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java index e5d0edb59..0a94be517 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/Settings.java @@ -159,6 +159,7 @@ public static boolean loadPluginConfig(FileConfiguration config) { return changed; } + @SuppressWarnings("removal") private static Biome loadBiome(FileConfiguration config, String path, Biome defaultBiome) { try { String biomeKey = config.getString(path, defaultBiome.getKey().getKey()); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java index dfeba39ec..0b79774ea 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/biome/BiomeConfig.java @@ -67,6 +67,7 @@ public BiomeConfig(Logger logger) { return configuredBiomeKeys; } + @SuppressWarnings("removal") private @Nullable BiomeEntry readBiomeEntry(@NotNull String biomeKey, @NotNull ConfigurationSection section) { String itemSpecification = section.getString("displayItem"); String name = section.getString("name"); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java index 2435da82c..8d34a5bf3 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/challenge/ChallengeFactory.java @@ -83,6 +83,7 @@ public static Challenge createChallenge(Rank rank, ConfigurationSection section, radius, reward, repeatReward, repeatLimit); } + @SuppressWarnings("removal") private static List createEntities(List requiredEntities) { List entities = new ArrayList<>(); for (String entityString : requiredEntities) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java index 1d7078524..4519f2d9e 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BiomeCommand.java @@ -40,6 +40,7 @@ public BiomeCommand(@NotNull uSkyBlock plugin, @NotNull Biomes biomes, @NotNull } @Override + @SuppressWarnings("removal") protected boolean doExecute(String alias, final Player player, PlayerInfo pi, final IslandInfo island, Map data, final String... args) { if (args.length == 0) { if (!island.hasPerm(player, "canChangeBiome")) { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java index 65c0b672d..729c13b28 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/IslandInfo.java @@ -389,6 +389,7 @@ public boolean hasPerm(UUID uuid, String perm) { } @Override + @SuppressWarnings("removal") public Biome getIslandBiome() { String biomeKey = config.getString("general.biome", Settings.general_defaultBiome.getKey().getKey()); Biome biome = Registry.BIOME.match(biomeKey); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java index fcc26662b..fa32a3c11 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uSkyBlock.java @@ -499,6 +499,7 @@ public PlayerInfo getPlayerInfo(String playerName) { } // TODO: move these to Biome/World related classes + @SuppressWarnings("removal") public @Nullable Biome getBiome(String biomeName) { if (biomeName == null) return null; return Registry.BIOME.match(biomeName); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java index b83fc740d..85c24c490 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/uuid/NullPlayer.java @@ -1,5 +1,6 @@ package us.talabrek.ultimateskyblock.uuid; +import io.papermc.paper.persistence.PersistentDataContainerView; import org.bukkit.BanEntry; import org.bukkit.Location; import org.bukkit.Material; @@ -27,6 +28,11 @@ public boolean isOnline() { return false; } + @Override + public boolean isConnected() { + return false; + } + @Override public String getName() { return PlayerDB.UNKNOWN_PLAYER_NAME; @@ -37,9 +43,8 @@ public UUID getUniqueId() { return PlayerDB.UNKNOWN_PLAYER_UUID; } - @NotNull @Override - public PlayerProfile getPlayerProfile() { + public com.destroystokyo.paper.profile.PlayerProfile getPlayerProfile() { return null; } @@ -101,6 +106,16 @@ public Location getBedSpawnLocation() { return null; } + @Override + public long getLastLogin() { + return 0; + } + + @Override + public long getLastSeen() { + return 0; + } + @Nullable @Override public Location getRespawnLocation() { @@ -209,6 +224,11 @@ public Location getLocation() { return null; } + @Override + public PersistentDataContainerView getPersistentDataContainer() { + return null; + } + @Override public Map serialize() { return null; From f69cb15bc7f27b5288fe4962024c50b4170336f9 Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Mon, 28 Apr 2025 17:40:24 +0800 Subject: [PATCH 180/190] try to fix the VaultEconomy --- bukkit-utils/build.gradle.kts | 1 - uSkyBlock-Core/build.gradle.kts | 2 +- .../command/island/BuyHopperLimitCommand.java | 9 +++----- .../hook/economy/EconomyHook.java | 7 ++++-- .../hook/economy/VaultEconomy.java | 23 +++++++++++-------- .../hook/permissions/VaultPermissions.java | 2 +- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/bukkit-utils/build.gradle.kts b/bukkit-utils/build.gradle.kts index 09a35db74..f8a731090 100644 --- a/bukkit-utils/build.gradle.kts +++ b/bukkit-utils/build.gradle.kts @@ -5,7 +5,6 @@ dependencies { implementation(project(":po-utils")) implementation("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT") - implementation("net.milkbowl.vault:VaultAPI:1.7") testImplementation("org.hamcrest:hamcrest-core:1.3") testImplementation("org.hamcrest:hamcrest-library:1.3") testImplementation("junit:junit:4.13.2") diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index 8e0052502..f03442fe4 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { testImplementation("org.mockito:mockito-core:5.14.2") testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - compileOnly("net.milkbowl.vault:VaultAPI:1.7") + compileOnly("net.milkbowl.vault:VaultUnlockedAPI:2.9") compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java index 313783bf6..adc338987 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java @@ -1,16 +1,11 @@ package us.talabrek.ultimateskyblock.command.island; import com.google.inject.Inject; -import net.milkbowl.vault.economy.Economy; -import net.milkbowl.vault.economy.EconomyResponse; import org.bukkit.entity.Player; import us.talabrek.ultimateskyblock.island.IslandInfo; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.hook.economy.EconomyHook; -import us.talabrek.ultimateskyblock.hook.economy.VaultEconomy; - import java.util.Map; import static dk.lockfuglsang.minecraft.po.I18nUtil.marktr; @@ -43,10 +38,11 @@ protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandIn uSkyBlock.getInstance().getHookManager().getEconomyHook().ifPresent((hook) -> { if (hook.getBalance(player) >= price) { boolean success; + String result = hook.withdrawPlayer(player, price); if (price == 0) { success = true; } else { - success = hook.withdrawPlayer(player, price); + success = result == null; } if (success) { islandInfo.setHopperLimit(curlimit + 1); @@ -54,6 +50,7 @@ protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandIn player.sendMessage(tr("\u00a77======================")); } else { player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); + player.sendMessage(tr("\u00a7c {0}", result)); } } else { player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java index 8902f1293..9436d6472 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/EconomyHook.java @@ -2,6 +2,7 @@ import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.hook.PluginHook; import us.talabrek.ultimateskyblock.uSkyBlock; @@ -19,19 +20,21 @@ public EconomyHook(@NotNull uSkyBlock plugin, @NotNull String implementing) { /** * Deposit an amount to an {@link OfflinePlayer} - DO NOT USE NEGATIVE AMOUNTS + * * @param player to deposit to * @param amount Amount to deposit * @return Detailed response of transaction */ - public abstract boolean depositPlayer(@NotNull OfflinePlayer player, double amount); + public abstract @Nullable String depositPlayer(@NotNull OfflinePlayer player, double amount); /** * Withdraw an amount from an {@link OfflinePlayer} - DO NOT USE NEGATIVE AMOUNTS + * * @param player to withdraw from * @param amount Amount to withdraw * @return Detailed response of transaction */ - public abstract boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount); + public abstract @Nullable String withdrawPlayer(@NotNull OfflinePlayer player, double amount); /** * Returns the icon or name of the currency in plural form. Defaults to $. diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java index 3523848ee..c5740399c 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock.hook.economy; -import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault2.economy.Economy; +import net.milkbowl.vault2.economy.EconomyResponse; import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -8,8 +9,10 @@ import org.bukkit.event.server.ServiceUnregisterEvent; import org.bukkit.plugin.RegisteredServiceProvider; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.uSkyBlock; +import java.math.BigDecimal; import java.util.Optional; public class VaultEconomy extends EconomyHook implements Listener { @@ -36,7 +39,7 @@ private Optional setupEconomy() { @Override public @NotNull String getCurrenyName() { if (economy != null) { - return economy.currencyNamePlural(); + return economy.defaultCurrencyNamePlural(plugin.getName()); } return super.getCurrenyName(); } @@ -44,25 +47,27 @@ private Optional setupEconomy() { @Override public double getBalance(@NotNull OfflinePlayer player) { if (economy != null) { - return economy.getBalance(player); + return economy.balance(plugin.getName(), player.getUniqueId()).doubleValue(); } return 0; } @Override - public boolean depositPlayer(@NotNull OfflinePlayer player, double amount) { + public @Nullable String depositPlayer(@NotNull OfflinePlayer player, double amount) { if (economy != null) { - return economy.depositPlayer(player, amount).transactionSuccess(); + EconomyResponse response = economy.deposit(plugin.getName(), player.getUniqueId(), BigDecimal.valueOf(amount)); + if (response.transactionSuccess()) return null; else return response.errorMessage; } - return false; + return "Economy is null"; } @Override - public boolean withdrawPlayer(@NotNull OfflinePlayer player, double amount) { + public @Nullable String withdrawPlayer(@NotNull OfflinePlayer player, double amount) { if (economy != null) { - return economy.depositPlayer(player, amount).transactionSuccess(); + EconomyResponse response = economy.withdraw(plugin.getName(), player.getUniqueId(), BigDecimal.valueOf(amount)); + if (response.transactionSuccess()) return null; else return response.errorMessage; } - return false; + return "Economy is null"; } @EventHandler diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java index 59f711a10..f30774b97 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -1,6 +1,6 @@ package us.talabrek.ultimateskyblock.hook.permissions; -import net.milkbowl.vault.permission.Permission; +import net.milkbowl.vault2.permission.Permission; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; From e43d41219b17c7e470ed97d8a428fd8ca673ac12 Mon Sep 17 00:00:00 2001 From: seewo <3135055939@qq.com> Date: Tue, 29 Apr 2025 18:06:31 +0800 Subject: [PATCH 181/190] fix the VaultEconomy complete --- .../command/island/BuyHopperLimitCommand.java | 30 ++++++++----------- .../hook/economy/VaultEconomy.java | 18 +++++------ .../hook/permissions/VaultPermissions.java | 2 +- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java index adc338987..e840ebeb8 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/BuyHopperLimitCommand.java @@ -36,26 +36,20 @@ protected boolean doExecute(String alias, Player player, PlayerInfo pi, IslandIn if (args.length > 0 && args[0].equals("buy")) { int price = calcPrice(curlimit); uSkyBlock.getInstance().getHookManager().getEconomyHook().ifPresent((hook) -> { - if (hook.getBalance(player) >= price) { - boolean success; - String result = hook.withdrawPlayer(player, price); - if (price == 0) { - success = true; - } else { - success = result == null; - } - if (success) { - islandInfo.setHopperLimit(curlimit + 1); - player.sendMessage(tr("\u00a7a\u00a7lBuy Extra Hopper Success!")); - player.sendMessage(tr("\u00a77======================")); - } else { - player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); - player.sendMessage(tr("\u00a7c {0}", result)); - } + boolean success; + String result = hook.withdrawPlayer(player, price); + success = result == null; + if (success) { + islandInfo.setHopperLimit(curlimit + 1); + player.sendMessage(tr("\u00a7a\u00a7lBuy Extra Hopper Success!")); + player.sendMessage(tr("\u00a77======================")); } else { player.sendMessage(tr("\u00a7c\u00a7lBuy Extra Hopper Failed!")); - player.sendMessage(tr("\u00a7dYou do not have enough money!")); - player.sendMessage(tr("\u00a7dYou have {0}", hook.getBalance(player))); + if (hook.getBalance(player) < price) { + player.sendMessage(tr("\u00a7dYou do not have enough money!")); + player.sendMessage(tr("\u00a7dYou have {0}", hook.getBalance(player))); + } + player.sendMessage(tr("\u00a7c {0}", result)); } }); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java index c5740399c..73e9ba883 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/economy/VaultEconomy.java @@ -1,7 +1,7 @@ package us.talabrek.ultimateskyblock.hook.economy; -import net.milkbowl.vault2.economy.Economy; -import net.milkbowl.vault2.economy.EconomyResponse; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.economy.EconomyResponse; import org.bukkit.OfflinePlayer; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -12,7 +12,6 @@ import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.uSkyBlock; -import java.math.BigDecimal; import java.util.Optional; public class VaultEconomy extends EconomyHook implements Listener { @@ -29,17 +28,16 @@ private Optional setupEconomy() { plugin.getServer().getServicesManager().getRegistration(Economy.class); if (rsp != null) { economy = rsp.getProvider(); - plugin.getLogger().info("Using " + rsp.getProvider().getName() + " as economy provider."); + plugin.getLogger().info("Using " + economy.getName() + " as economy provider."); return Optional.of(economy); } - return Optional.empty(); } @Override public @NotNull String getCurrenyName() { if (economy != null) { - return economy.defaultCurrencyNamePlural(plugin.getName()); + return economy.currencyNamePlural(); } return super.getCurrenyName(); } @@ -47,7 +45,7 @@ private Optional setupEconomy() { @Override public double getBalance(@NotNull OfflinePlayer player) { if (economy != null) { - return economy.balance(plugin.getName(), player.getUniqueId()).doubleValue(); + return economy.getBalance(player); } return 0; } @@ -55,7 +53,7 @@ public double getBalance(@NotNull OfflinePlayer player) { @Override public @Nullable String depositPlayer(@NotNull OfflinePlayer player, double amount) { if (economy != null) { - EconomyResponse response = economy.deposit(plugin.getName(), player.getUniqueId(), BigDecimal.valueOf(amount)); + EconomyResponse response = economy.depositPlayer(player, amount); if (response.transactionSuccess()) return null; else return response.errorMessage; } return "Economy is null"; @@ -64,7 +62,7 @@ public double getBalance(@NotNull OfflinePlayer player) { @Override public @Nullable String withdrawPlayer(@NotNull OfflinePlayer player, double amount) { if (economy != null) { - EconomyResponse response = economy.withdraw(plugin.getName(), player.getUniqueId(), BigDecimal.valueOf(amount)); + EconomyResponse response = economy.withdrawPlayer(player, amount); if (response.transactionSuccess()) return null; else return response.errorMessage; } return "Economy is null"; @@ -74,6 +72,7 @@ public double getBalance(@NotNull OfflinePlayer player) { public void onEconomyRegister(ServiceRegisterEvent event) { if (event.getProvider().getProvider() instanceof Economy) { setupEconomy().ifPresent(vaultPlugin -> this.economy = vaultPlugin); + plugin.getLogger().info("Economy registered"); } } @@ -82,6 +81,7 @@ public void onEconomyUnregister(ServiceUnregisterEvent event) { if (event.getProvider().getProvider() instanceof Economy) { this.economy = null; setupEconomy().ifPresent(vaultPlugin -> this.economy = vaultPlugin); + plugin.getLogger().info("Economy unregistered"); } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java index f30774b97..156fcf1eb 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/permissions/VaultPermissions.java @@ -26,7 +26,7 @@ private Optional setupPermission() { plugin.getServer().getServicesManager().getRegistration(Permission.class); if (rsp != null) { permission = rsp.getProvider(); - plugin.getLogger().info("Using " + rsp.getProvider().getName() + " as permission provider."); + plugin.getLogger().info("Using " + permission.getName() + " as permission provider."); return Optional.of(permission); } From e084d6b606b818104499257dd10f0fae5f26de05 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Fri, 2 May 2025 15:00:36 +0800 Subject: [PATCH 182/190] fix tnt not break blocks --- uSkyBlock-Core/build.gradle.kts | 2 +- .../ultimateskyblock/handler/WorldGuardHandler.java | 4 ++-- .../java/us/talabrek/ultimateskyblock/hook/HookManager.java | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/uSkyBlock-Core/build.gradle.kts b/uSkyBlock-Core/build.gradle.kts index f03442fe4..9f0d1b15e 100644 --- a/uSkyBlock-Core/build.gradle.kts +++ b/uSkyBlock-Core/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { testImplementation("org.mockito:mockito-core:5.14.2") testImplementation("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") testImplementation("com.sk89q.worldedit:worldedit-bukkit:7.2.19") - compileOnly("net.milkbowl.vault:VaultUnlockedAPI:2.9") + compileOnly("net.milkbowl.vault:VaultUnlockedAPI:2.10") compileOnly("io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT") compileOnly("com.onarandombox.multiversecore:Multiverse-Core:4.3.1") compileOnly("com.onarandombox.multiverseinventories:Multiverse-Inventories:4.2.3") diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index e03d3c350..9d1b30ba1 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -286,8 +286,8 @@ public static void setupGlobal(World world) { global = new GlobalProtectedRegion("__global__"); } global.setFlag(Flags.BUILD, StateFlag.State.DENY); - global.setFlag(Flags.OTHER_EXPLOSION, StateFlag.State.ALLOW); - global.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.ALLOW); + global.setFlag(Flags.OTHER_EXPLOSION, StateFlag.State.DENY); + global.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.DENY); if (Settings.island_allowPvP) { global.setFlag(Flags.PVP, StateFlag.State.ALLOW); } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java index 170060b2d..7c5cbec2a 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/hook/HookManager.java @@ -91,7 +91,7 @@ public void setupHooks() { */ public boolean setupEconomyHook() { try { - if (Bukkit.getPluginManager().isPluginEnabled("Vault")) { + if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { VaultEconomy vault = new VaultEconomy(plugin); registerHook(vault); logger.info("Hooked into Vault economy"); @@ -112,7 +112,7 @@ public boolean setupEconomyHook() { */ public boolean setupMultiverse() { try { - if (Bukkit.getPluginManager().isPluginEnabled("Multiverse-Core")) { + if (plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Core")) { MultiverseHook mvHook = new MultiverseHook(plugin); registerHook(mvHook); logger.info("Hooked into Multiverse-Core"); @@ -133,7 +133,7 @@ public boolean setupMultiverse() { */ public boolean setupPermissionsHook() { try { - if (Bukkit.getPluginManager().isPluginEnabled("Vault")) { + if (plugin.getServer().getPluginManager().isPluginEnabled("Vault")) { VaultPermissions vault = new VaultPermissions(plugin); registerHook(vault); logger.info("Hooked into Vault permissions."); From b93839582c7cda8eb5d8b23a41a84b3eb2c96f4a Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Fri, 2 May 2025 16:41:28 +0800 Subject: [PATCH 183/190] =?UTF-8?q?=E8=80=81=E8=80=81=E5=AE=9E=E5=AE=9E?= =?UTF-8?q?=E5=81=9A=E5=AE=8C=E7=AC=AC=E4=B8=80=E9=A1=B5=E5=90=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../command/island/TrustCommand.java | 12 ++++++++++++ .../ultimateskyblock/event/PlayerEvents.java | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java index d5e025749..fd36e3a18 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/command/island/TrustCommand.java @@ -26,6 +26,12 @@ public TrustCommand(@NotNull uSkyBlock plugin) { @Override protected boolean doExecute(final String alias, final Player player, final PlayerInfo pi, final IslandInfo island, Map data, String... args) { + PlayerInfo playerInfo = plugin.getPlayerInfo(player); + boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; + if(isFirstCompletion){ + player.sendMessage(tr("\u00a7c你现在没有权限信任他,请先完成第一页任务")); + return true; + } if (args.length == 0) { player.sendMessage(tr("\u00a7eThe following players are trusted on your island:")); player.sendMessage(tr("\u00a74{0}", island.getTrustees())); @@ -46,6 +52,12 @@ protected boolean doExecute(final String alias, final Player player, final Playe return true; } if (alias.equals("trust")) { + PlayerInfo pinfo = plugin.getPlayerInfo(offlinePlayer.getUniqueId()); + boolean pii = pinfo.checkChallenge("page1finished") == 0; + if(pii){ + player.sendMessage(tr("\u00a7c你现在没有权限信任他,请先完成第一页任务")); + return true; + } island.trustPlayer(offlinePlayer, player); if (offlinePlayer.isOnline()) { offlinePlayer.getPlayer().sendMessage(tr("\u00a7eYou are now trusted on \u00a74{0}''s \u00a7eisland.", pi.getDisplayName())); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index 81a5315aa..99efaab9f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -349,6 +349,14 @@ public void onBlockPlaceEvent(BlockPlaceEvent event) { return; } Material type = event.getBlock().getType(); + if(type == Material.OBSIDIAN){ + PlayerInfo playerInfo = plugin.getPlayerInfo(player); + boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; + if(isFirstCompletion){ + event.setCancelled(true); + player.sendMessage(tr("完成第一页任务前你没有权限在这里放置 {0}",tr("Obsidian"))); + } + } BlockLimitLogic.CanPlace canPlace = plugin.getBlockLimitLogic().canPlace(type, islandInfo); if (canPlace == BlockLimitLogic.CanPlace.UNCERTAIN) { event.setCancelled(true); From ceac1eb2a0046a11a72d57dcd425f053cf4fd019 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 3 May 2025 21:47:40 +0800 Subject: [PATCH 184/190] fix java.lang.IllegalStateException: Not scheduled yet --- .../ultimateskyblock/island/task/CreateIslandTask.java | 5 +---- .../ultimateskyblock/island/task/LocateChestTask.java | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java index 9f2f3799b..711eba5f7 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java @@ -5,7 +5,6 @@ import org.bukkit.scheduler.BukkitRunnable; import us.talabrek.ultimateskyblock.player.PlayerPerk; import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.Scheduler; import java.time.Duration; @@ -20,11 +19,9 @@ public class CreateIslandTask extends BukkitRunnable { private final PlayerPerk playerPerk; private final Location next; private final String cSchem; - private final Scheduler scheduler; public CreateIslandTask(uSkyBlock plugin, Player player, PlayerPerk playerPerk, Location next, String cSchem) { this.plugin = plugin; - this.scheduler = plugin.getScheduler(); this.player = player; this.playerPerk = playerPerk; this.next = next; @@ -39,6 +36,6 @@ public void run() { GenerateTask generateTask = new GenerateTask(plugin, player, playerPerk.getPlayerInfo(), next, playerPerk, cSchem); Duration heartBeat = Duration.ofMillis(plugin.getConfig().getInt("asyncworldedit.watchDog.heartBeatMs", 2000)); final BukkitRunnable completionWatchDog = new LocateChestTask(plugin, player, next, generateTask); - scheduler.sync(completionWatchDog, Duration.ZERO, heartBeat); + completionWatchDog.runTask(plugin); } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java index bab2c1214..7b553fa70 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/LocateChestTask.java @@ -42,7 +42,7 @@ public void run() { // Just run again // TODO: this is hacky, waiting for async generation to complete. Should ideally be launched once the generation has finished. } else { - if (!this.isCancelled()) cancel(); + cancel(); if (chestLocation == null && player != null && player.isOnline()) { player.sendMessage(I18nUtil.tr("\u00a7cWatchdog!\u00a79 Unable to locate a chest within {0}, bailing out.", TimeUtil.durationAsString(Duration.between(start, timeout)))); } From 35adc50b4002a90f731a511de5f97c76604e6125 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 3 May 2025 22:18:38 +0800 Subject: [PATCH 185/190] fix java.lang.NullPointerException: Cannot invoke "java.time.Duration.plus(java.time.Duration)" because "this.timeActive" is null --- .../talabrek/ultimateskyblock/async/JobManager.java | 12 ++++++++++-- .../island/task/CreateIslandTask.java | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java index 0be42e7f6..04a3308ca 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/async/JobManager.java @@ -53,8 +53,16 @@ public synchronized void add(IncrementalRunnable runnable) { public synchronized void complete(IncrementalRunnable runnable) { jobsRunning--; ticks += runnable.getTicksConsumed(); - timeActive = timeActive.plus(runnable.getProcessingTimeUsed()); - timeElapsed = timeElapsed.plus(runnable.getTimeElapsed()); + if (timeActive == null) { + timeActive = runnable.getProcessingTimeUsed(); + } else { + timeActive = timeActive.plus(runnable.getProcessingTimeUsed()); + } + if (timeElapsed == null) { + timeElapsed = runnable.getProcessingTimeUsed(); + } else { + timeElapsed = timeElapsed.plus(runnable.getTimeElapsed()); + } } public int getJobs() { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java index 711eba5f7..d737b50c5 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/task/CreateIslandTask.java @@ -34,7 +34,6 @@ public void run() { player.sendMessage(tr("Unable to locate schematic {0}, contact a server-admin", cSchem)); } GenerateTask generateTask = new GenerateTask(plugin, player, playerPerk.getPlayerInfo(), next, playerPerk, cSchem); - Duration heartBeat = Duration.ofMillis(plugin.getConfig().getInt("asyncworldedit.watchDog.heartBeatMs", 2000)); final BukkitRunnable completionWatchDog = new LocateChestTask(plugin, player, next, generateTask); completionWatchDog.runTask(plugin); } From 9ab2eb44c12d620ae53bf8e31861af6c768cea5a Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sun, 4 May 2025 17:46:00 +0800 Subject: [PATCH 186/190] phantom protect --- .../ultimateskyblock/event/SpawnEvents.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index 177c98204..0c2d9ab48 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -22,12 +22,15 @@ import org.jetbrains.annotations.Nullable; import us.talabrek.ultimateskyblock.api.IslandInfo; import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; +import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; import java.util.*; +import java.util.logging.Level; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; +import static us.talabrek.ultimateskyblock.util.LogUtil.log; /** * Responsible for controlling spawns on uSkyBlock islands. @@ -36,6 +39,7 @@ public class SpawnEvents implements Listener { private static final Set RIGHT_CLICKS = Set.of(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK); + private HashMap newbieisland = new HashMap<>(); private final uSkyBlock plugin; private boolean phantomsInOverworld; @@ -90,6 +94,12 @@ public void onSpawnEggEvent(PlayerInteractEvent event) { } } + private int fastpos(int pos){ + pos+=64; + return (pos<0)?((pos+1)/128):(pos/128); + } + + @EventHandler(ignoreCancelled = true) public void onCreatureSpawn(CreatureSpawnEvent event) { if (event == null || !plugin.getWorldManager().isSkyAssociatedWorld(event.getLocation().getWorld())) { @@ -98,6 +108,32 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { if (event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.SPAWNER_EGG)) { return; // Allow it, the above method would have blocked it if it should be blocked. } + if (event.getEntity() instanceof Phantom) { + String island = fastpos(event.getLocation().getBlockX()) + "," + fastpos(event.getLocation().getBlockZ()); + + if(newbieisland.get(island) == null){ + IslandInfo is = plugin.getIslandInfo(event.getLocation()); + if(is != null){ + PlayerInfo pi = plugin.getPlayerInfo(is.getLeader()); + if (pi != null && pi.checkChallenge("page1finished")==0){ + // newbie protection + event.setCancelled(true); + pi = null; is = null; + newbieisland.put(island, true); + log(Level.INFO, "Add inf Phantom Protection: "+island+" : protect"); + return; + } + pi = null; is = null; + newbieisland.put(island, false); + log(Level.INFO, "Add inf Phantom Protection: "+island+" : Not-protect"); + } + }else{ + if (newbieisland.get(island) == true){ + event.setCancelled(true); + return; + } + } + } checkLimits(event, event.getEntity().getType(), event.getLocation()); if (event.getEntity() instanceof WaterMob) { Location loc = event.getLocation(); From 5cff530c91c54f96fec7ba52937d193c2e8f565d Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sun, 4 May 2025 17:50:27 +0800 Subject: [PATCH 187/190] rebuild the mob spawning --- .../ultimateskyblock/event/SpawnEvents.java | 72 +++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index 0c2d9ab48..b32c34b7f 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -24,7 +24,7 @@ import us.talabrek.ultimateskyblock.handler.WorldGuardHandler; import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; -import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.util.LogUtil; import java.util.*; import java.util.logging.Level; @@ -39,7 +39,7 @@ public class SpawnEvents implements Listener { private static final Set RIGHT_CLICKS = Set.of(Action.RIGHT_CLICK_AIR, Action.RIGHT_CLICK_BLOCK); - private HashMap newbieisland = new HashMap<>(); + private HashMap newIsland = new HashMap<>(); private final uSkyBlock plugin; private boolean phantomsInOverworld; @@ -111,7 +111,7 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { if (event.getEntity() instanceof Phantom) { String island = fastpos(event.getLocation().getBlockX()) + "," + fastpos(event.getLocation().getBlockZ()); - if(newbieisland.get(island) == null){ + if(newIsland.get(island) == null){ IslandInfo is = plugin.getIslandInfo(event.getLocation()); if(is != null){ PlayerInfo pi = plugin.getPlayerInfo(is.getLeader()); @@ -119,28 +119,36 @@ public void onCreatureSpawn(CreatureSpawnEvent event) { // newbie protection event.setCancelled(true); pi = null; is = null; - newbieisland.put(island, true); + newIsland.put(island, true); log(Level.INFO, "Add inf Phantom Protection: "+island+" : protect"); return; } pi = null; is = null; - newbieisland.put(island, false); + newIsland.put(island, false); log(Level.INFO, "Add inf Phantom Protection: "+island+" : Not-protect"); } }else{ - if (newbieisland.get(island) == true){ + if (newIsland.get(island) == true){ event.setCancelled(true); return; } } } + if (event.getEntity() instanceof WaterMob) { + Random r = new Random(); + if (r.nextInt(20) != 0){ + event.setCancelled(true); + return; + } + } + if (event.getEntity() instanceof ArmorStand){ + return; + } checkLimits(event, event.getEntity().getType(), event.getLocation()); if (event.getEntity() instanceof WaterMob) { Location loc = event.getLocation(); - if (isPrismarineRoof(loc)) { - loc.getWorld().spawnEntity(loc, EntityType.GUARDIAN); + if(doPrismarineRoof(loc)) event.setCancelled(true); - } } if (!event.isCancelled() && event.getEntity() instanceof Enderman) { Location loc = event.getLocation(); @@ -168,9 +176,49 @@ private boolean isPurpurFloor(Location loc){ return ret; } - private boolean isPrismarineRoof(Location loc) { - Collection prismarineBlocks = Set.of(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); - return prismarineBlocks.contains(LocationUtil.findRoofBlock(loc).getType()); + private boolean doPrismarineRoof(Location loc) { + List prismarineBlocks = Arrays.asList(Material.PRISMARINE, Material.PRISMARINE_BRICKS, Material.DARK_PRISMARINE); + Location tloc = loc.clone(); + if(tloc.getBlockY()<47 || tloc.getBlockY()>64) + return false; + while(tloc.getBlockY()<=70){ + if (tloc.getBlock().getType() == Material.WATER){ + tloc.add(0,1,0); + }else{ + if(prismarineBlocks.contains(tloc.getBlock().getType())){ + Random r = new Random(); + if (r.nextInt(5) == 0){ + if(r.nextInt(1000) == 0){ + if(r.nextInt(1000)==0){ + Drowned drowned= (Drowned) loc.getWorld().spawnEntity(loc, EntityType.DROWNED); + drowned.getEquipment().setItemInMainHand(new ItemStack(Material.TRIDENT)); + LogUtil.log(Level.INFO, java.time.Clock.systemUTC().instant()+" "+plugin.getIslandInfo(loc).getLeader()+" RANDOM TRIDENT"); + } + else{ + Drowned drowned= (Drowned) loc.getWorld().spawnEntity(loc, EntityType.DROWNED); + if(drowned.getEquipment().getItemInMainHand().equals(new ItemStack(Material.TRIDENT))){ + LogUtil.log(Level.INFO,java.time.Clock.systemUTC().instant()+" "+plugin.getIslandInfo(loc).getLeader()+" DROWNED TRIDENT"); + } + else{ + LogUtil.log(Level.INFO,java.time.Clock.systemUTC().instant()+" "+plugin.getIslandInfo(loc).getLeader()+" DROWNED NO TRIDENT"); + } + } + } + else{ + loc.getWorld().spawnEntity(loc, EntityType.GUARDIAN); + } + } + return true; + }else if(tloc.getBlock().getType() == Material.SEA_LANTERN){ + Random r = new Random(); + if (r.nextInt(50) == 0) + loc.getWorld().spawnEntity(loc, EntityType.ELDER_GUARDIAN); + return true; + } + return false; + } + } + return false; } private boolean isEndBiome(Location loc) { From faa8dd00ef0b5660fc56a5596ef54f47a5eda0b6 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 17 May 2025 19:06:22 +0800 Subject: [PATCH 188/190] avoid cross nether portal --- .../ultimateskyblock/event/PlayerEvents.java | 48 ++++++++++++------- .../ultimateskyblock/event/SpawnEvents.java | 5 -- .../ultimateskyblock/island/LimitLogic.java | 5 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index 99efaab9f..179371428 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -1,8 +1,10 @@ package us.talabrek.ultimateskyblock.event; +import com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent; import com.google.inject.Inject; import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; +import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -11,6 +13,7 @@ import org.bukkit.block.data.Levelled; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.EnderPearl; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; @@ -20,15 +23,9 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.FoodLevelChangeEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.entity.*; +import org.bukkit.event.player.*; +import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.projectiles.ProjectileSource; @@ -43,6 +40,7 @@ import us.talabrek.ultimateskyblock.player.PlayerInfo; import us.talabrek.ultimateskyblock.uSkyBlock; import us.talabrek.ultimateskyblock.util.LocationUtil; +import us.talabrek.ultimateskyblock.util.LogUtil; import us.talabrek.ultimateskyblock.world.WorldManager; import java.time.Duration; @@ -54,6 +52,7 @@ import java.util.Random; import java.util.Set; import java.util.UUID; +import java.util.logging.Level; import static dk.lockfuglsang.minecraft.po.I18nUtil.tr; @@ -319,6 +318,29 @@ public void onTeleport(PlayerTeleportEvent event) { } } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPlayerPortal(EntityPortalEnterEvent event) { + if (event.getEntityType() == EntityType.PLAYER) { + Player player = (Player) event.getEntity(); + PlayerInfo playerInfo = plugin.getPlayerInfo(player); + boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; + if (isFirstCompletion || player.isOp()){ + event.setCancelled(true); + player.sendMessage("地狱门已被禁用"); + } + } + else { + IslandInfo islandInfo = plugin.getIslandInfo(event.getLocation()); + if (islandInfo != null) { + PlayerInfo playerInfo = plugin.getPlayerInfo(islandInfo.getLeader()); + boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; + if (isFirstCompletion){ + event.setCancelled(true); + } + } + } + } + /** * This EventHandler handles {@link BlockBreakEvent} to detect if a player broke leaves in the skyworld, * and will drop a sapling if so. This will prevent cases where the default generated tree on a new @@ -349,14 +371,6 @@ public void onBlockPlaceEvent(BlockPlaceEvent event) { return; } Material type = event.getBlock().getType(); - if(type == Material.OBSIDIAN){ - PlayerInfo playerInfo = plugin.getPlayerInfo(player); - boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; - if(isFirstCompletion){ - event.setCancelled(true); - player.sendMessage(tr("完成第一页任务前你没有权限在这里放置 {0}",tr("Obsidian"))); - } - } BlockLimitLogic.CanPlace canPlace = plugin.getBlockLimitLogic().canPlace(type, islandInfo); if (canPlace == BlockLimitLogic.CanPlace.UNCERTAIN) { event.setCancelled(true); diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java index b32c34b7f..a4e1360c6 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/SpawnEvents.java @@ -234,11 +234,6 @@ private void checkLimits(Cancellable event, EntityType entityType, Location loca event.setCancelled(true); // Only allow spawning on active islands... return; } - if (entityType.equals(EntityType.GHAST) && location.getWorld().getEnvironment() != World.Environment.NETHER) { - // Disallow ghasts for now... - event.setCancelled(true); - return; - } IslandInfo islandInfo = plugin.getIslandInfo(islandName); if (islandInfo == null) { // Disallow spawns on inactive islands diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java index c33cbd38e..0a959eb33 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/island/LimitLogic.java @@ -115,10 +115,7 @@ public boolean canSpawn(EntityType entityType, us.talabrek.ultimateskyblock.api. Map creatureCount = getCreatureCount(islandInfo); CreatureType creatureType = getCreatureType(entityType); int max = getMax(islandInfo, creatureType); - if (creatureCount.containsKey(creatureType) && creatureCount.get(creatureType) >= max) { - return false; - } - return true; + return !creatureCount.containsKey(creatureType) || creatureCount.get(creatureType) < max; } private int getMax(us.talabrek.ultimateskyblock.api.IslandInfo islandInfo, CreatureType creatureType) { From 261b1489b30ef1f51f8a7fc80b4d4983d798823c Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 17 May 2025 20:01:52 +0800 Subject: [PATCH 189/190] fix nether portal --- .../talabrek/ultimateskyblock/event/PlayerEvents.java | 10 ++++++++-- .../ultimateskyblock/util/ProgressTracker.java | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java index 179371428..78576d4e9 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/PlayerEvents.java @@ -1,6 +1,7 @@ package us.talabrek.ultimateskyblock.event; import com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent; +import com.google.common.util.concurrent.RateLimiter; import com.google.inject.Inject; import com.google.inject.Singleton; import dk.lockfuglsang.minecraft.util.ItemStackUtil; @@ -318,15 +319,20 @@ public void onTeleport(PlayerTeleportEvent event) { } } + private RateLimiter rateLimiter = RateLimiter.create(1); + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerPortal(EntityPortalEnterEvent event) { if (event.getEntityType() == EntityType.PLAYER) { Player player = (Player) event.getEntity(); PlayerInfo playerInfo = plugin.getPlayerInfo(player); boolean isFirstCompletion = playerInfo.checkChallenge("page1finished") == 0; - if (isFirstCompletion || player.isOp()){ + if (player.isOp()) return; + if (isFirstCompletion){ event.setCancelled(true); - player.sendMessage("地狱门已被禁用"); + if (rateLimiter.tryAcquire()) { + player.sendMessage("\u00a7c地狱门已被禁用"); + } } } else { diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java index c7fda0e37..a4e827bfd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/util/ProgressTracker.java @@ -29,6 +29,7 @@ public ProgressTracker(CommandSender sender, String format, double progressEvery public void progressUpdate(long progress, long total, Object... args) { Instant now = Instant.now(); float pct = 100f * progress / (total > 0 ? total : 1f); + if (lastProgressTime == null) { lastProgressTime = now; } if (now.isAfter(lastProgressTime.plus(progressEvery)) || pct > (lastProgressPct + progressEveryPct)) { lastProgressPct = pct; lastProgressTime = now; From ff32f84618e00b562966d0f6d07d27279f141c46 Mon Sep 17 00:00:00 2001 From: Cong0707 <49234756+Cong0707@users.noreply.github.com> Date: Sat, 17 May 2025 20:53:32 +0800 Subject: [PATCH 190/190] fix tnt and drop item in spawn point --- .../java/us/talabrek/ultimateskyblock/event/GriefEvents.java | 5 ----- .../us/talabrek/ultimateskyblock/event/ItemDropEvents.java | 5 +++++ .../talabrek/ultimateskyblock/handler/WorldGuardHandler.java | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java index 769fd6cff..84b93d355 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/GriefEvents.java @@ -65,11 +65,6 @@ public void onCreeperExplode(ExplosionPrimeEvent event) { && !isValidTarget(((Creeper)event.getEntity()).getTarget())) { event.setCancelled(true); - } else if (event.getEntity() instanceof TNTPrimed) { - TNTPrimed tntPrimed = (TNTPrimed) event.getEntity(); - if (tntPrimed.getSource() instanceof Player && !isValidTarget(tntPrimed.getSource())) { - event.setCancelled(true); - } } } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java index d8639a1d5..47d4d1845 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/event/ItemDropEvents.java @@ -47,6 +47,11 @@ public void onDropEvent(PlayerDropItemEvent event) { plugin.notifyPlayer(player, tr("\u00a7eVisitors can't drop items!")); return; } + if (plugin.playerIsInSpawn(player)) { + event.setCancelled(true); + plugin.notifyPlayer(player, tr("\u00a7eSpawn point can't drop items!")); + return; + } addDropInfo(player, event.getItemDrop().getItemStack()); } diff --git a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java index 9d1b30ba1..c6fa5e3cd 100644 --- a/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java +++ b/uSkyBlock-Core/src/main/java/us/talabrek/ultimateskyblock/handler/WorldGuardHandler.java @@ -286,8 +286,6 @@ public static void setupGlobal(World world) { global = new GlobalProtectedRegion("__global__"); } global.setFlag(Flags.BUILD, StateFlag.State.DENY); - global.setFlag(Flags.OTHER_EXPLOSION, StateFlag.State.DENY); - global.setFlag(Flags.CREEPER_EXPLOSION, StateFlag.State.DENY); if (Settings.island_allowPvP) { global.setFlag(Flags.PVP, StateFlag.State.ALLOW); } else {