From 0663eb90e339da78c848910151c65af1e1c2d53a Mon Sep 17 00:00:00 2001 From: Bananaa Date: Fri, 5 Aug 2022 19:37:54 +0200 Subject: [PATCH 01/30] Fix https://github.com/kangarko/ChatControl-Red/issues/2041 --- src/main/java/org/mineacademy/fo/model/SimpleComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java index a35dc0978..bd71fc13e 100644 --- a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java +++ b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java @@ -40,7 +40,7 @@ public final class SimpleComponent implements ConfigSerializable { /** * The pattern to match URL addresses when parsing text */ - private static final Pattern URL_PATTERN = Pattern.compile("^(http(s|):\\/\\/|)(www\\.|)[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[a-zA-Z:,.\\?\\!]*)$"); + private static final Pattern URL_PATTERN = Pattern.compile("^(https?:\\/\\/|)(www\\.|)[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[a-zA-Z:,.\\?\\!\\/0-9]*)$"); /** * The past components From 0cb3c40cae69e888ac99785b99db631a1d45b910 Mon Sep 17 00:00:00 2001 From: Bananaa Date: Sat, 6 Aug 2022 17:18:27 +0200 Subject: [PATCH 02/30] 1.19.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0ec07a97..1a1ccfe83 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ org.spigotmc spigot-api - 1.19.1-R0.1-SNAPSHOT + 1.19.2-R0.1-SNAPSHOT From f2917c8684f20d0f3f65dbf6c186e336ad9af9ad Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 8 Aug 2022 19:32:59 +0200 Subject: [PATCH 03/30] Fix Remain#injectServerName() corrupting unicode when saving server.properties --- .../org/mineacademy/fo/remain/Remain.java | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/remain/Remain.java b/src/main/java/org/mineacademy/fo/remain/Remain.java index 71dbdf1b8..ee7e2a9e3 100644 --- a/src/main/java/org/mineacademy/fo/remain/Remain.java +++ b/src/main/java/org/mineacademy/fo/remain/Remain.java @@ -4,18 +4,17 @@ import static org.mineacademy.fo.ReflectionUtil.getOBCClass; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; @@ -44,6 +43,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.command.SimpleCommandMap; +import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; @@ -68,6 +68,7 @@ import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Score; import org.mineacademy.fo.Common; +import org.mineacademy.fo.EntityUtil; import org.mineacademy.fo.FileUtil; import org.mineacademy.fo.ItemUtil; import org.mineacademy.fo.MathUtil; @@ -344,7 +345,7 @@ private Remain() { "&cYour server version (&f" + Bukkit.getBukkitVersion().replace("-SNAPSHOT", "") + "&c) doesn't\n" + " &cinclude &elibraries required&c for this plugin to\n" + " &crun. Install the following plugin for compatibility:\n" + - " &fhttps://mineacademy.org/plugins/#misc"); + " &fhttps://mineacademy.org/plugins/#misc"); } try { @@ -2555,40 +2556,51 @@ public static void setGameRule(final World world, final String gameRule, final b * restore it back */ public static void injectServerName() { - final Properties properties = new Properties(); - final File props = new File(SimplePlugin.getData().getParentFile().getParentFile(), "server.properties"); - - // If user has Bungee_Server_Name in their settings, move it automatically - final File settingsFile = FileUtil.getFile("settings.yml"); - String previousName = null; + try { + // If user has Bungee_Server_Name in their settings, move it automatically + final File settingsFile = FileUtil.getFile("settings.yml"); + String previousName = null; - if (settingsFile.exists()) { - final YamlConfiguration settings = YamlConfiguration.loadConfiguration(settingsFile); - final String previousNameRaw = settings.getString("Bungee_Server_Name"); + if (settingsFile.exists()) { + final YamlConfiguration settings = YamlConfiguration.loadConfiguration(settingsFile); + final String previousNameRaw = settings.getString("Bungee_Server_Name"); - if (previousNameRaw != null && !previousNameRaw.isEmpty() && !"none".equals(previousNameRaw) && !"undefined".equals(previousNameRaw)) { - Common.warning("Detected Bungee_Server_Name being used in your settings.yml that is now located in server.properties." + - " It has been moved there and you can now delete this key from settings.yml if it was not deleted already."); + if (previousNameRaw != null && !previousNameRaw.isEmpty() && !"none".equals(previousNameRaw) && !"undefined".equals(previousNameRaw)) { + Common.warning("Detected Bungee_Server_Name being used in your settings.yml that is now located in server.properties." + + " It has been moved there and you can now delete this key from settings.yml if it was not deleted already."); - previousName = previousNameRaw; + previousName = previousNameRaw; + } } - } - try (final FileReader fileReader = new FileReader(props)) { - properties.load(fileReader); + // Check server.properties for a valid server-name key, if it lacks, add it with instructions on configuring properly + final File serverProperties = new File(SimplePlugin.getData().getParentFile().getParentFile(), "server.properties"); + final List lines = FileUtil.readLines(serverProperties); + + lines.removeIf(line -> line.equals("server-name=undefined") || line.equals("server-name=Unknown Server")); - if (!properties.containsKey("server-name") || previousName != null) { - properties.setProperty("server-name", previousName != null ? previousName : "Undefined - see mineacademy.org/server-properties to configure"); + boolean hasServerName = false; + String oldName = null; - try (FileWriter fileWriter = new FileWriter(props)) { - properties.store(fileWriter, "Minecraft server properties\nModified by " + SimplePlugin.getNamed() + ", see mineacademy.org/server-properties for more information"); + for (String line : lines) + if (line.startsWith("server-name=")) { + hasServerName = true; + + oldName = line.replace("server-name=", ""); + break; } + + if (!hasServerName) { + serverName = previousName == null ? "Undefined - see mineacademy.org/server-properties to configure" : previousName; + lines.add("server-name=" + serverName); + + Files.write(serverProperties.toPath(), lines, StandardOpenOption.TRUNCATE_EXISTING); } - serverName = properties.getProperty("server-name"); + serverName = oldName; - } catch (final Throwable e) { - e.printStackTrace(); + } catch (Throwable t) { + t.printStackTrace(); } } From bfe1b54dca3fba62723ff97f3f8b67f4c049ab8e Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 9 Aug 2022 11:03:01 +0200 Subject: [PATCH 04/30] Improve performance and remove unused debugger messages --- .../fo/bungee/message/IncomingMessage.java | 4 +- .../fo/bungee/message/OutgoingMessage.java | 3 - .../mineacademy/fo/command/SimpleCommand.java | 4 - .../org/mineacademy/fo/debug/Debugger.java | 10 +- .../mineacademy/fo/model/DiscordListener.java | 2 - .../org/mineacademy/fo/model/HookManager.java | 20 ++-- .../mineacademy/fo/model/PacketListener.java | 7 +- .../fo/plugin/AutoRegisterScanner.java | 3 - .../mineacademy/fo/plugin/SimplePlugin.java | 92 +++++++++---------- 9 files changed, 55 insertions(+), 90 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java b/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java index 4a175d7d9..7717945b3 100644 --- a/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java +++ b/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java @@ -7,8 +7,8 @@ import org.bukkit.entity.Player; import org.mineacademy.fo.ReflectionUtil; import org.mineacademy.fo.bungee.BungeeListener; +import org.mineacademy.fo.bungee.BungeeMessageType; import org.mineacademy.fo.collection.SerializedMap; -import org.mineacademy.fo.debug.Debugger; import org.mineacademy.fo.plugin.SimplePlugin; import com.google.common.io.ByteArrayDataInput; @@ -236,7 +236,5 @@ public short readShort() { */ public void forward(Player player) { player.sendPluginMessage(SimplePlugin.getInstance(), this.getChannel(), this.data); - - Debugger.debug("bungee", "Forwarding data on " + this.getChannel() + " channel from " + this.getAction() + " as " + player.getName() + " player to BungeeCord."); } } \ No newline at end of file diff --git a/src/main/java/org/mineacademy/fo/bungee/message/OutgoingMessage.java b/src/main/java/org/mineacademy/fo/bungee/message/OutgoingMessage.java index 18481d2ce..95507ff80 100644 --- a/src/main/java/org/mineacademy/fo/bungee/message/OutgoingMessage.java +++ b/src/main/java/org/mineacademy/fo/bungee/message/OutgoingMessage.java @@ -9,7 +9,6 @@ import org.mineacademy.fo.bungee.BungeeListener; import org.mineacademy.fo.bungee.BungeeMessageType; import org.mineacademy.fo.collection.SerializedMap; -import org.mineacademy.fo.debug.Debugger; import org.mineacademy.fo.exception.FoException; import org.mineacademy.fo.plugin.SimplePlugin; import org.mineacademy.fo.remain.Remain; @@ -178,8 +177,6 @@ private void write(Object object, Class typeOf) { */ public void send(Player player) { player.sendPluginMessage(SimplePlugin.getInstance(), this.getChannel(), this.compileData()); - - Debugger.debug("bungee", "Sending data on " + this.getChannel() + " channel from " + this.getAction() + " as " + player.getName() + " player to BungeeCord."); } /** diff --git a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java index 8fbe86e02..c73d83171 100644 --- a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java +++ b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java @@ -31,7 +31,6 @@ import org.mineacademy.fo.collection.StrictList; import org.mineacademy.fo.collection.expiringmap.ExpiringMap; import org.mineacademy.fo.command.SimpleCommandGroup.MainCommand; -import org.mineacademy.fo.debug.Debugger; import org.mineacademy.fo.debug.LagCatcher; import org.mineacademy.fo.exception.CommandException; import org.mineacademy.fo.exception.EventHandledException; @@ -273,9 +272,6 @@ public final void register(final boolean unregisterOldCommand, final boolean unr if (oldCommand != null && unregisterOldCommand) { final String owningPlugin = oldCommand.getPlugin().getName(); - if (!owningPlugin.equals(SimplePlugin.getNamed())) - Debugger.debug("command", "Command /" + this.getLabel() + " already (" + owningPlugin + "), overriding and unregistering /" + oldCommand.getLabel() + ", /" + String.join(", /", oldCommand.getAliases())); - Remain.unregisterCommand(oldCommand.getLabel(), unregisterOldAliases); } diff --git a/src/main/java/org/mineacademy/fo/debug/Debugger.java b/src/main/java/org/mineacademy/fo/debug/Debugger.java index 5769fe826..1c8a5769a 100644 --- a/src/main/java/org/mineacademy/fo/debug/Debugger.java +++ b/src/main/java/org/mineacademy/fo/debug/Debugger.java @@ -66,10 +66,7 @@ public static void detectDebugMode() { public static void debug(String section, String... messages) { if (isDebugged(section)) for (final String message : messages) - if (SimplePlugin.hasInstance()) - Common.log("[" + section + "] " + message); - else - System.out.println("[" + section + "] " + message); + print("[" + section + "] " + message); } /** @@ -358,9 +355,6 @@ private static boolean canPrint(String message) { // Print a simple console message private static void print(String message) { - if (SimplePlugin.hasInstance()) - Common.logNoPrefix(message); - else - System.out.println(message); + System.out.println(message); // our instance may or may not be available yet to log } } diff --git a/src/main/java/org/mineacademy/fo/model/DiscordListener.java b/src/main/java/org/mineacademy/fo/model/DiscordListener.java index ccf39fb16..9cd75ea18 100644 --- a/src/main/java/org/mineacademy/fo/model/DiscordListener.java +++ b/src/main/java/org/mineacademy/fo/model/DiscordListener.java @@ -315,8 +315,6 @@ protected final void sendWebhookMessage(@Nullable CommandSender sender, String c // Send the message Common.runAsync(() -> { try { - Debugger.debug("discord", "[Minecraft > Discord] Send MC message from '" + channelName + "' to Discord's '" + channel.getName() + "' channel: " + message); - // You can remove this if you don't want to use webhooks if (sender instanceof Player) WebhookUtil.deliverMessage(channel, (Player) sender, message); diff --git a/src/main/java/org/mineacademy/fo/model/HookManager.java b/src/main/java/org/mineacademy/fo/model/HookManager.java index 80487074f..480273e37 100644 --- a/src/main/java/org/mineacademy/fo/model/HookManager.java +++ b/src/main/java/org/mineacademy/fo/model/HookManager.java @@ -50,6 +50,7 @@ import com.bekvon.bukkit.residence.protection.ClaimedResidence; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketListener; import com.earth2me.essentials.CommandSource; @@ -1231,11 +1232,6 @@ public static String replacePlaceholders(final @Nullable OfflinePlayer player, S message = isPlaceholderAPILoaded() ? placeholderAPIHook.replacePlaceholders(player, message) : message; message = isMVdWPlaceholderAPILoaded() ? MVdWPlaceholderHook.replacePlaceholders(player, message) : message; - if (!isPlaceholderAPILoaded()) - Debugger.debug("placeholder-api", "Not replacing PAPI placeholders in '" + message + "' as the plugin is not yet loaded"); - else - Debugger.debug("placeholder-api", "Replacing PAPI placeholders in: " + message); - return message; } @@ -2675,15 +2671,15 @@ public List getAllRegions() { } else ((com.sk89q.worldguard.protection.managers.RegionManager) rm) - .getRegions().values().forEach(reg -> { - if (reg == null || reg.getId() == null) - return; + .getRegions().values().forEach(reg -> { + if (reg == null || reg.getId() == null) + return; - final String name = Common.stripColors(reg.getId()); + final String name = Common.stripColors(reg.getId()); - if (!name.startsWith("__")) - list.add(name); - }); + if (!name.startsWith("__")) + list.add(name); + }); } return list; diff --git a/src/main/java/org/mineacademy/fo/model/PacketListener.java b/src/main/java/org/mineacademy/fo/model/PacketListener.java index e7b792e8e..77d61797d 100644 --- a/src/main/java/org/mineacademy/fo/model/PacketListener.java +++ b/src/main/java/org/mineacademy/fo/model/PacketListener.java @@ -26,6 +26,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers.ChatType; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.protocol.wrappers.WrappedServerPing; import lombok.AccessLevel; import lombok.Getter; @@ -250,8 +251,8 @@ public void onPacketSending(final PacketEvent event) { // Such errors mean the parsed message took too long to process. // Only show such errors every 30 minutes to prevent console spam Common.logTimed(1800, "&cWarning: &fPacket message '" + Common.limit(this.jsonMessage, 500) - + "' (possibly longer) took too long time to edit received message and was ignored." - + " This message only shows once per 30 minutes when that happens. For most cases, this can be ignored."); + + "' (possibly longer) took too long time to edit received message and was ignored." + + " This message only shows once per 30 minutes when that happens. For most cases, this can be ignored."); return; @@ -360,8 +361,6 @@ private void writeEditedMessage(String message, PacketEvent event) { if (this.systemChat) { event.getPacket().getStrings().writeSafely(0, this.jsonMessage); - System.out.println("Fixing: " + message); - } else if (this.isBaseComponent) packet.writeSafely(this.adventure ? 2 : 1, Remain.toComponent(this.jsonMessage)); diff --git a/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java b/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java index 73845debf..751b8e802 100644 --- a/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java +++ b/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java @@ -24,7 +24,6 @@ import org.mineacademy.fo.bungee.BungeeListener; import org.mineacademy.fo.command.SimpleCommand; import org.mineacademy.fo.command.SimpleCommandGroup; -import org.mineacademy.fo.debug.Debugger; import org.mineacademy.fo.event.SimpleListener; import org.mineacademy.fo.exception.FoException; import org.mineacademy.fo.menu.tool.Tool; @@ -374,8 +373,6 @@ else if (instance instanceof Listener) { // Register events if needed if (!eventsRegistered && instance instanceof Listener) plugin.registerEvents((Listener) instance); - - Debugger.debug("auto-register", "Automatically registered " + clazz); } /* diff --git a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java index b8bbd6d76..a094c7305 100644 --- a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java +++ b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java @@ -32,6 +32,7 @@ import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.Messenger; +import org.mineacademy.fo.BungeeUtil; import org.mineacademy.fo.Common; import org.mineacademy.fo.FileUtil; import org.mineacademy.fo.MinecraftVersion; @@ -439,19 +440,19 @@ private void loadLibraries() { else methodLibraryLoader: - for (final Library library : manualLibraries) { + for (final Library library : manualLibraries) { - // Detect conflicts - for (final Library otherLibrary : libraries) - if (library.getArtifactId().equals(otherLibrary.getArtifactId()) && library.getGroupId().equals(otherLibrary.getGroupId())) { - Common.warning("Detected library conflict: '" + library.getGroupId() + "." + library.getArtifactId() + "' is defined both in getLibraries() and plugin.yml! " - + "We'll prefer the version from plugin.yml, if you want to use the one from getLibraries() then remove it from your plugin.yml file."); + // Detect conflicts + for (final Library otherLibrary : libraries) + if (library.getArtifactId().equals(otherLibrary.getArtifactId()) && library.getGroupId().equals(otherLibrary.getGroupId())) { + Common.warning("Detected library conflict: '" + library.getGroupId() + "." + library.getArtifactId() + "' is defined both in getLibraries() and plugin.yml! " + + "We'll prefer the version from plugin.yml, if you want to use the one from getLibraries() then remove it from your plugin.yml file."); - continue methodLibraryLoader; - } + continue methodLibraryLoader; + } - library.load(); - } + library.load(); + } } /** @@ -505,7 +506,6 @@ protected final void registerBungeeCord(@NonNull BungeeListener bungee) { messenger.registerOutgoingPluginChannel(this, bungee.getChannel()); this.reloadables.registerEvents(bungee); - Debugger.debug("bungee", "Registered BungeeCord listener on channel " + bungee.getChannel()); } /** @@ -893,24 +893,21 @@ protected final void registerAllEvents(final Class exten Valid.checkBoolean(!extendingClass.equals(SimpleListener.class), "registerAllEvents does not support SimpleListener.class due to conflicts, create your own middle class instead"); classLookup: - for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { + for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { - // AutoRegister means the class is already being registered - if (pluginClass.isAnnotationPresent(AutoRegister.class)) - continue; - - for (final Constructor con : pluginClass.getConstructors()) - if (con.getParameterCount() == 0) { - final T instance = (T) ReflectionUtil.instantiate(con); + // AutoRegister means the class is already being registered + if (pluginClass.isAnnotationPresent(AutoRegister.class)) + continue; - Debugger.debug("auto-register", "Auto-registering events in " + pluginClass); - this.registerEvents(instance); + for (final Constructor con : pluginClass.getConstructors()) + if (con.getParameterCount() == 0) { + final T instance = (T) ReflectionUtil.instantiate(con); - continue classLookup; - } + this.registerEvents(instance); - Debugger.debug("auto-register", "Skipping auto-registering events in " + pluginClass + " because it lacks at least one no arguments constructor"); - } + continue classLookup; + } + } } /** @@ -957,40 +954,33 @@ protected final void registerAllCommands(final Class exte Valid.checkBoolean(!extendingClass.equals(SimpleSubCommand.class), "registerAllCommands does not support SubCommand.class"); classLookup: - for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { + for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { - // AutoRegister means the class is already being registered - if (pluginClass.isAnnotationPresent(AutoRegister.class)) - continue; - - if (SimpleSubCommand.class.isAssignableFrom(pluginClass)) { - Debugger.debug("auto-register", "Skipping auto-registering command " + pluginClass + " because sub-commands cannot be registered"); - - continue; - } + // AutoRegister means the class is already being registered + if (pluginClass.isAnnotationPresent(AutoRegister.class)) + continue; - try { - for (final Constructor con : pluginClass.getConstructors()) - if (con.getParameterCount() == 0) { - final T instance = (T) ReflectionUtil.instantiate(con); + if (SimpleSubCommand.class.isAssignableFrom(pluginClass)) + continue; - Debugger.debug("auto-register", "Auto-registering command " + pluginClass); + try { + for (final Constructor con : pluginClass.getConstructors()) + if (con.getParameterCount() == 0) { + final T instance = (T) ReflectionUtil.instantiate(con); - if (instance instanceof SimpleCommand) - this.registerCommand(instance); + if (instance instanceof SimpleCommand) + this.registerCommand(instance); - else - this.registerCommand(instance); + else + this.registerCommand(instance); - continue classLookup; - } + continue classLookup; + } - } catch (final LinkageError ex) { - Common.log("Unable to register commands in '" + pluginClass.getSimpleName() + "' due to error: " + ex); + } catch (final LinkageError ex) { + Common.log("Unable to register commands in '" + pluginClass.getSimpleName() + "' due to error: " + ex); + } } - - Debugger.debug("auto-register", "Skipping auto-registering command " + pluginClass + " because it lacks at least one no arguments constructor"); - } } /** From 09e7d94ee4fae2c47d54cf414a79d8086ed94c80 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 9 Aug 2022 11:03:11 +0200 Subject: [PATCH 05/30] Beta: Add support for replacing variables in variables --- src/main/java/org/mineacademy/fo/model/Variables.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/model/Variables.java b/src/main/java/org/mineacademy/fo/model/Variables.java index 1a7d83bf4..e3aca8c42 100644 --- a/src/main/java/org/mineacademy/fo/model/Variables.java +++ b/src/main/java/org/mineacademy/fo/model/Variables.java @@ -272,10 +272,14 @@ else if (sender instanceof DiscordSender) // Default message = replaceHardVariables0(sender, message); - // Support the & color system - if (!message.startsWith("[JSON]")) + // Support the & color system and replacing variables in variables + if (!message.startsWith("[JSON]")) { message = Common.colorize(message); + if (!original.equals(message) && (message.contains("{") && message.contains("}"))) + return replace(message, sender, replacements, colorize); + } + if (senderIsPlayer) { final Map map = cache.get(sender.getName()); From 2546e4792969c664fbabea08586d6c9aa543096e Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Wed, 10 Aug 2022 08:59:16 +0200 Subject: [PATCH 06/30] Reformat --- .../org/mineacademy/fo/conversation/SimpleConversation.java | 1 - src/main/java/org/mineacademy/fo/settings/FileConfig.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java b/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java index 371efe649..7f4535116 100644 --- a/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java +++ b/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java @@ -309,7 +309,6 @@ private CustomConversation(final Conversable forWhom) { if (SimpleConversation.this.insertPrefix() && SimpleConversation.this.getPrefix() != null) this.prefix = SimpleConversation.this.getPrefix(); - } @Override diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index a2a1a5ef6..853452ec6 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -35,6 +35,8 @@ import org.mineacademy.fo.Valid; import org.mineacademy.fo.collection.SerializedMap; import org.mineacademy.fo.collection.StrictList; +import org.mineacademy.fo.command.SimpleCommand; +import org.mineacademy.fo.command.SimpleCommandGroup; import org.mineacademy.fo.exception.FoException; import org.mineacademy.fo.model.BoxedMessage; import org.mineacademy.fo.model.ConfigSerializable; From e03a435961bd56e010c2171c07d87da933f55e19 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Wed, 10 Aug 2022 08:59:29 +0200 Subject: [PATCH 07/30] Add support for toast styles to Remain#sendToast with multiple recipients --- .../mineacademy/fo/remain/CompToastStyle.java | 21 +++++++++++++++++++ .../org/mineacademy/fo/remain/Remain.java | 17 ++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/remain/CompToastStyle.java b/src/main/java/org/mineacademy/fo/remain/CompToastStyle.java index 5b510e076..3ed6b8305 100644 --- a/src/main/java/org/mineacademy/fo/remain/CompToastStyle.java +++ b/src/main/java/org/mineacademy/fo/remain/CompToastStyle.java @@ -1,5 +1,7 @@ package org.mineacademy.fo.remain; +import org.mineacademy.fo.Common; + import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -16,4 +18,23 @@ public enum CompToastStyle { @Getter private final String key; + + /** + * Attempt to load CompToastStyle from the given key + * + * @param key + * @return + */ + public static CompToastStyle fromKey(String key) { + for (final CompToastStyle style : values()) + if (style.key.equalsIgnoreCase(key)) + return style; + + throw new IllegalArgumentException("No such CompToastStyle '" + key + "'. Available: " + Common.join(values())); + } + + @Override + public String toString() { + return this.key; + } } diff --git a/src/main/java/org/mineacademy/fo/remain/Remain.java b/src/main/java/org/mineacademy/fo/remain/Remain.java index ee7e2a9e3..9effd0e88 100644 --- a/src/main/java/org/mineacademy/fo/remain/Remain.java +++ b/src/main/java/org/mineacademy/fo/remain/Remain.java @@ -2183,8 +2183,23 @@ public static void sendToast(final Player receiver, final String message, final * @param receivers * @param message you can replace player-specific variables in the message here * @param icon + * @param goal */ public static void sendToast(final List receivers, final Function message, final CompMaterial icon) { + sendToast(receivers, message, icon, CompToastStyle.GOAL); + } + + /** + * Send a "toast" notification to the given receivers. This is an advancement notification that cannot + * be modified that much. It imposes a slight performance penalty the more players to send to. + * + * Each player sending is delayed by 0.1s + * + * @param receivers + * @param message you can replace player-specific variables in the message here + * @param icon + */ + public static void sendToast(final List receivers, final Function message, final CompMaterial icon, final CompToastStyle style) { if (hasAdvancements) Common.runLaterAsync(() -> { @@ -2197,7 +2212,7 @@ public static void sendToast(final List receivers, final Function Date: Sat, 13 Aug 2022 16:36:14 +0200 Subject: [PATCH 08/30] Add ability to change a conversation's modality --- .../fo/conversation/SimpleConversation.java | 13 +++++++++++++ .../mineacademy/fo/conversation/SimplePrompt.java | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java b/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java index 7f4535116..c0088106e 100644 --- a/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java +++ b/src/main/java/org/mineacademy/fo/conversation/SimpleConversation.java @@ -206,6 +206,18 @@ protected int getTimeout() { return 60; } + /** + * Modal true = Bukkit will hide all chat and plugin messages OTHER THAN + * conversational messages from your prompts + * + * Defaults to true + * + * @return + */ + protected boolean isModal() { + return true; + } + /** * Sets the menu to return to after the end of this conversation * @@ -306,6 +318,7 @@ private CustomConversation(final Conversable forWhom) { super(SimplePlugin.getInstance(), forWhom, SimpleConversation.this.getFirstPrompt()); this.localEchoEnabled = false; + this.modal = SimpleConversation.this.isModal(); if (SimpleConversation.this.insertPrefix() && SimpleConversation.this.getPrefix() != null) this.prefix = SimpleConversation.this.getPrefix(); diff --git a/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java b/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java index babc740b6..9f0716d9c 100644 --- a/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java +++ b/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java @@ -15,6 +15,9 @@ import org.mineacademy.fo.model.Variables; import org.mineacademy.fo.settings.SimpleLocalization; +import lombok.Getter; +import lombok.Setter; + /** * Represents one question for the player during a server conversation */ @@ -25,6 +28,13 @@ public abstract class SimplePrompt extends ValidatingPrompt { */ private boolean openMenu = true; + /** + * See {@link SimpleConversation#isModal()} + */ + @Setter + @Getter + private boolean modal = true; + /** * The player who sees the input */ @@ -221,6 +231,11 @@ protected Prompt getFirstPrompt() { return SimplePrompt.this; } + @Override + protected boolean isModal() { + return SimplePrompt.this.modal; + } + @Override protected ConversationPrefix getPrefix() { final String prefix = SimplePrompt.this.getCustomPrefix(); From 28099343bdd9eafde0ec4cc3fc11ec6652827f5e Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Sat, 13 Aug 2022 16:36:36 +0200 Subject: [PATCH 09/30] 6.0.9 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1a1ccfe83..b804d483e 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.mineacademy Foundation - 6.0.8 + 6.0.9 jar Foundation From 2c3fc22b4f631c8a3d64bba5fb4401bc00788d3d Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Sat, 13 Aug 2022 19:00:08 +0200 Subject: [PATCH 10/30] Beta: Save config files async --- .../org/mineacademy/fo/settings/FileConfig.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index 853452ec6..d4e1d4d5c 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -1275,16 +1275,16 @@ public final void save(@NonNull File file) { final String data = this.saveToString(); - if (data != null) { - final Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8); + if (data != null) + Common.runAsync(() -> { + try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { + writer.write(data); - try { - writer.write(data); + } catch (Exception ex) { + Remain.sneaky(ex); + } + }); - } finally { - writer.close(); - } - } // Update file this.file = file; From 6a4e28c1eabe9e242a9d680bc3c5db38b2dcf992 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Sat, 13 Aug 2022 19:00:14 +0200 Subject: [PATCH 11/30] Fix itemcreator breaking books --- .../fo/menu/model/ItemCreator.java | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java index 321d02959..4df67a113 100644 --- a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java +++ b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java @@ -151,7 +151,8 @@ public final class ItemCreator { /** * If this is a book, you can set its new pages here. */ - private final List bookPages = new ArrayList<>(); + @Nullable + private List bookPages = null; /** * If this a book, you can set its author here. @@ -438,6 +439,10 @@ public ItemCreator bookPages(String... pages) { * @return */ public ItemCreator bookPages(List pages) { + + if (this.bookPages == null) + this.bookPages = new ArrayList<>(); + this.bookPages.addAll(pages); return this; @@ -523,48 +528,48 @@ public ItemStack make() { // Apply specific material color if possible color: - if (this.color != null) { + if (this.color != null) { - if (compiledItem.getType().toString().contains("LEATHER")) { - if (MinecraftVersion.atLeast(V.v1_4)) { - Valid.checkBoolean(compiledMeta instanceof LeatherArmorMeta, "Expected a leather item, cannot apply color to " + compiledItem); + if (compiledItem.getType().toString().contains("LEATHER")) { + if (MinecraftVersion.atLeast(V.v1_4)) { + Valid.checkBoolean(compiledMeta instanceof LeatherArmorMeta, "Expected a leather item, cannot apply color to " + compiledItem); - ((LeatherArmorMeta) compiledMeta).setColor(this.color.getColor()); + ((LeatherArmorMeta) compiledMeta).setColor(this.color.getColor()); + } } - } - else { + else { - // Hack: If you put WHITE_WOOL and a color, we automatically will change the material to the colorized version - if (MinecraftVersion.atLeast(V.v1_13)) { - final String dye = this.color.getDye().toString(); - final List colorableMaterials = Arrays.asList("BANNER", "BED", "CARPET", "CONCRETE", "GLAZED_TERRACOTTA", "SHULKER_BOX", "STAINED_GLASS", - "STAINED_GLASS_PANE", "TERRACOTTA", "WALL_BANNER", "WOOL"); + // Hack: If you put WHITE_WOOL and a color, we automatically will change the material to the colorized version + if (MinecraftVersion.atLeast(V.v1_13)) { + final String dye = this.color.getDye().toString(); + final List colorableMaterials = Arrays.asList("BANNER", "BED", "CARPET", "CONCRETE", "GLAZED_TERRACOTTA", "SHULKER_BOX", "STAINED_GLASS", + "STAINED_GLASS_PANE", "TERRACOTTA", "WALL_BANNER", "WOOL"); - for (final String material : colorableMaterials) { - final String suffix = "_" + material; + for (final String material : colorableMaterials) { + final String suffix = "_" + material; - if (compiledItem.getType().toString().endsWith(suffix)) { - compiledItem.setType(Material.valueOf(dye + suffix)); + if (compiledItem.getType().toString().endsWith(suffix)) { + compiledItem.setType(Material.valueOf(dye + suffix)); - break color; + break color; + } } } - } - else { - try { - final byte dataValue = this.color.getDye().getWoolData(); + else { + try { + final byte dataValue = this.color.getDye().getWoolData(); - compiledItem.setData(new MaterialData(compiledItem.getType(), dataValue)); - compiledItem.setDurability(dataValue); + compiledItem.setData(new MaterialData(compiledItem.getType(), dataValue)); + compiledItem.setDurability(dataValue); - } catch (final NoSuchMethodError err) { - // Ancient MC, ignore + } catch (final NoSuchMethodError err) { + // Ancient MC, ignore + } } } } - } // Fix monster eggs if (compiledItem.getType().toString().endsWith("SPAWN_EGG") || compiledItem.getType().toString().equals("MONSTER_EGG")) { @@ -636,15 +641,15 @@ else if ("ZOMBIE_PIGMAN".equals(entityRaw)) if (this.bookPages != null) bookMeta.setPages(Common.colorize(this.bookPages)); - if (this.bookAuthor == null) + if (this.bookAuthor != null) bookMeta.setAuthor(Common.getOrEmpty(this.bookAuthor)); - if (this.bookTitle == null) + if (this.bookTitle != null) bookMeta.setTitle(Common.getOrEmpty(this.bookTitle)); // Fix "Corrupted NBT tag" error when any of these fields are not set if (bookMeta.getPages() == null) - bookMeta.setPages(""); + bookMeta.setPages(Arrays.asList("")); if (bookMeta.getAuthor() == null) bookMeta.setAuthor("Anonymous"); From 147ee376c5106a338db57245e8c80844143d6bdb Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 16:00:41 +0200 Subject: [PATCH 12/30] Fix isModal in SimplePrompt --- .../fo/conversation/SimplePrompt.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java b/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java index 9f0716d9c..e6a1247be 100644 --- a/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java +++ b/src/main/java/org/mineacademy/fo/conversation/SimplePrompt.java @@ -15,9 +15,6 @@ import org.mineacademy.fo.model.Variables; import org.mineacademy.fo.settings.SimpleLocalization; -import lombok.Getter; -import lombok.Setter; - /** * Represents one question for the player during a server conversation */ @@ -31,9 +28,6 @@ public abstract class SimplePrompt extends ValidatingPrompt { /** * See {@link SimpleConversation#isModal()} */ - @Setter - @Getter - private boolean modal = true; /** * The player who sees the input @@ -62,6 +56,15 @@ protected String getCustomPrefix() { return null; } + /** + * @see {@link SimpleConversation#isModal()} + * + * @return + */ + protected boolean isModal() { + return true; + } + /** * @see SimpleConversation#setMenuAnimatedTitle(String) * @@ -233,7 +236,7 @@ protected Prompt getFirstPrompt() { @Override protected boolean isModal() { - return SimplePrompt.this.modal; + return SimplePrompt.this.isModal(); } @Override From bc0e23c4fc4d5782ab0894ca81ae5aa954c3cc67 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 16:02:40 +0200 Subject: [PATCH 13/30] 6.0.10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b804d483e..94901fde1 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.mineacademy Foundation - 6.0.9 + 6.0.10 jar Foundation From 2038729d48a4f3e7cd1df8fcfd1dd1380c2b5013 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 17:57:30 +0200 Subject: [PATCH 14/30] Remove async config save to prevent concurrency issues --- .../org/mineacademy/fo/settings/FileConfig.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index d4e1d4d5c..906e0d9cc 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -1276,14 +1276,12 @@ public final void save(@NonNull File file) { final String data = this.saveToString(); if (data != null) - Common.runAsync(() -> { - try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { - writer.write(data); - - } catch (Exception ex) { - Remain.sneaky(ex); - } - }); + try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { + writer.write(data); + + } catch (Exception ex) { + Remain.sneaky(ex); + } // Update file From ddb8c198d15555bdbe53c3b8b347ea72f9bbe2ff Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 17:57:41 +0200 Subject: [PATCH 15/30] Increase domain filter domain length from 6 to 8 chars --- src/main/java/org/mineacademy/fo/model/SimpleComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java index bd71fc13e..19457f611 100644 --- a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java +++ b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java @@ -40,7 +40,7 @@ public final class SimpleComponent implements ConfigSerializable { /** * The pattern to match URL addresses when parsing text */ - private static final Pattern URL_PATTERN = Pattern.compile("^(https?:\\/\\/|)(www\\.|)[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[a-zA-Z:,.\\?\\!\\/0-9]*)$"); + private static final Pattern URL_PATTERN = Pattern.compile("^(https?:\\/\\/|)(www\\.|)[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,8}\\b(?:[a-zA-Z:,.\\?\\!\\/0-9]*)$"); /** * The past components From a6eeae6632576b4160d598a07410837385455b8f Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 17:57:46 +0200 Subject: [PATCH 16/30] Remove unused field --- src/main/java/org/mineacademy/fo/command/SimpleCommand.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java index c73d83171..8245e7d23 100644 --- a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java +++ b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java @@ -269,11 +269,8 @@ public final void register(final boolean unregisterOldCommand, final boolean unr final PluginCommand oldCommand = Bukkit.getPluginCommand(this.getLabel()); - if (oldCommand != null && unregisterOldCommand) { - final String owningPlugin = oldCommand.getPlugin().getName(); - + if (oldCommand != null && unregisterOldCommand) Remain.unregisterCommand(oldCommand.getLabel(), unregisterOldAliases); - } Remain.registerCommand(this); this.registered = true; From 019c2d2c9bad8b4034a2c996d9f2e7d4a65859d7 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 15 Aug 2022 20:32:56 +0200 Subject: [PATCH 17/30] Add support for %% variables as well as {} ones, split and rename placeholder fields in Variables class --- .../org/mineacademy/fo/model/HookManager.java | 28 ++++++++---- .../fo/model/JavaScriptExecutor.java | 19 +++++--- .../org/mineacademy/fo/model/Replacer.java | 7 ++- .../org/mineacademy/fo/model/Variables.java | 44 ++++++++++++++----- 4 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/model/HookManager.java b/src/main/java/org/mineacademy/fo/model/HookManager.java index 480273e37..2f914ae5e 100644 --- a/src/main/java/org/mineacademy/fo/model/HookManager.java +++ b/src/main/java/org/mineacademy/fo/model/HookManager.java @@ -2181,8 +2181,13 @@ private String setPlaceholders(final OfflinePlayer player, String text) { if (hooks.isEmpty()) return text; - final Matcher matcher = Variables.BRACKET_PLACEHOLDER_PATTERN.matcher(text); + text = setPlaceholders(player, oldText, text, hooks, Variables.VARIABLE_PATTERN.matcher(text)); + text = setPlaceholders(player, oldText, text, hooks, Variables.BRACKET_VARIABLE_PATTERN.matcher(text)); + return text; + } + + private String setPlaceholders(OfflinePlayer player, String oldText, String text, Map hooks, Matcher matcher) { while (matcher.find()) { String format = matcher.group(1); boolean frontSpace = false; @@ -2273,8 +2278,13 @@ private String setRelationalPlaceholders(final Player one, final Player two, Str if (hooks.isEmpty()) return text; - final Matcher matcher = Variables.BRACKET_REL_PLACEHOLDER_PATTERN.matcher(text); + text = setRelationalPlaceholders(one, two, text, hooks, Variables.REL_VARIABLE_PATTERN.matcher(text)); + text = setRelationalPlaceholders(one, two, text, hooks, Variables.BRACKET_REL_VARIABLE_PATTERN.matcher(text)); + return text; + } + + private String setRelationalPlaceholders(final Player one, final Player two, String text, Map hooks, Matcher matcher) { while (matcher.find()) { final String format = matcher.group(2); final int index = format.indexOf("_"); @@ -2671,15 +2681,15 @@ public List getAllRegions() { } else ((com.sk89q.worldguard.protection.managers.RegionManager) rm) - .getRegions().values().forEach(reg -> { - if (reg == null || reg.getId() == null) - return; + .getRegions().values().forEach(reg -> { + if (reg == null || reg.getId() == null) + return; - final String name = Common.stripColors(reg.getId()); + final String name = Common.stripColors(reg.getId()); - if (!name.startsWith("__")) - list.add(name); - }); + if (!name.startsWith("__")) + list.add(name); + }); } return list; diff --git a/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java b/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java index 90b08c02e..414d55025 100644 --- a/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java +++ b/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java @@ -156,12 +156,8 @@ public static Object run(@NonNull String javascript, final CommandSender sender, engine.put("event", event); if (sender instanceof DiscordSender) { - final Matcher matcher = Variables.BRACKET_PLACEHOLDER_PATTERN.matcher(javascript); - - while (matcher.find()) - // We do not support variables when the message sender is Discord, - // so just replace those that were not translated earlier with false value. - javascript = javascript.replace(matcher.group(), "false"); + javascript = replaceVariables(javascript, Variables.VARIABLE_PATTERN.matcher(javascript)); + javascript = replaceVariables(javascript, Variables.BRACKET_VARIABLE_PATTERN.matcher(javascript)); } Object result = engine.eval(javascript); @@ -210,6 +206,17 @@ else if (resultString.equals("false") || resultString.equals("no")) } } + /* + * We do not support variables when the message sender is Discord, + * so just replace those that were not translated earlier with false value. + */ + private static String replaceVariables(String javascript, Matcher matcher) { + while (matcher.find()) + javascript = javascript.replace(matcher.group(), "false"); + + return javascript; + } + /** * Executes the Javascript code with the given variables - you have to handle the error yourself * diff --git a/src/main/java/org/mineacademy/fo/model/Replacer.java b/src/main/java/org/mineacademy/fo/model/Replacer.java index 84f2c4aeb..ff7bb9466 100644 --- a/src/main/java/org/mineacademy/fo/model/Replacer.java +++ b/src/main/java/org/mineacademy/fo/model/Replacer.java @@ -73,8 +73,13 @@ public static String replaceVariables(String message, SerializedMap variables) { if ("".equals(message)) return ""; - final Matcher matcher = Variables.BRACKET_PLACEHOLDER_PATTERN.matcher(message); + message = replaceVariables(message, variables, Variables.VARIABLE_PATTERN.matcher(message)); + message = replaceVariables(message, variables, Variables.BRACKET_VARIABLE_PATTERN.matcher(message)); + return message; + } + + private static String replaceVariables(String message, SerializedMap variables, Matcher matcher) { while (matcher.find()) { String variable = matcher.group(1); diff --git a/src/main/java/org/mineacademy/fo/model/Variables.java b/src/main/java/org/mineacademy/fo/model/Variables.java index e3aca8c42..30f1c76d7 100644 --- a/src/main/java/org/mineacademy/fo/model/Variables.java +++ b/src/main/java/org/mineacademy/fo/model/Variables.java @@ -34,19 +34,29 @@ public final class Variables { /** - * The pattern to find singular [syntax_name] variables + * The pattern to find singular [syntax_name] variables. */ - public static final Pattern MESSAGE_PLACEHOLDER_PATTERN = Pattern.compile("[\\[]([^\\[\\]]+)[\\]]"); + public static final Pattern MESSAGE_VARIABLE_PATTERN = Pattern.compile("[\\[]([^\\[\\]]+)[\\]]"); /** - * The pattern to find simple {} placeholders + * The pattern to find simple %syntax% placeholders. */ - public static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[({|%)]([^{}]+)[(}|%)]"); + public static final Pattern VARIABLE_PATTERN = Pattern.compile("[%]([^%]+)[%]"); /** - * The patter to find simple {} placeholders starting with {rel_ (used for PlaceholderAPI) + * The pattern to find simple {syntax} placeholders. */ - public static final Pattern BRACKET_REL_PLACEHOLDER_PATTERN = Pattern.compile("[({|%)](rel_)([^}]+)[(}|%)]"); + public static final Pattern BRACKET_VARIABLE_PATTERN = Pattern.compile("[{]([^{}]+)[}]"); + + /** + * The patter to find simple %syntax% placeholders starting with %rel_% (used for PlaceholderAPI) + */ + public static final Pattern REL_VARIABLE_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]"); + + /** + * The patter to find simple {syntax} placeholders starting with {rel_} (used for PlaceholderAPI) + */ + public static final Pattern BRACKET_REL_VARIABLE_PATTERN = Pattern.compile("[({)](rel_)([^}]+)[(})]"); /** * Player - [Original Message - Translated Message] @@ -276,8 +286,9 @@ else if (sender instanceof DiscordSender) if (!message.startsWith("[JSON]")) { message = Common.colorize(message); - if (!original.equals(message) && (message.contains("{") && message.contains("}"))) + if (!original.equals(message) && ((message.contains("{") && message.contains("}")) || message.contains("%"))) return replace(message, sender, replacements, colorize); + } if (senderIsPlayer) { @@ -297,8 +308,13 @@ else if (sender instanceof DiscordSender) */ private static String replaceJavascriptVariables0(String message, CommandSender sender, Map replacements) { - final Matcher matcher = BRACKET_PLACEHOLDER_PATTERN.matcher(message); + message = replaceJavascriptVariables0(message, sender, replacements, VARIABLE_PATTERN.matcher(message)); + message = replaceJavascriptVariables0(message, sender, replacements, BRACKET_VARIABLE_PATTERN.matcher(message)); + + return message; + } + private static String replaceJavascriptVariables0(String message, CommandSender sender, Map replacements, Matcher matcher) { while (matcher.find()) { final String variableKey = matcher.group(); @@ -327,7 +343,15 @@ private static String replaceJavascriptVariables0(String message, CommandSender * Replaces our hardcoded variables in the message, using a cache for better performance */ private static String replaceHardVariables0(CommandSender sender, String message) { - final Matcher matcher = Variables.BRACKET_PLACEHOLDER_PATTERN.matcher(message); + + message = replaceHardVariables0(sender, message, Variables.VARIABLE_PATTERN.matcher(message)); + message = replaceHardVariables0(sender, message, Variables.BRACKET_VARIABLE_PATTERN.matcher(message)); + message = Messenger.replacePrefixes(message); + + return message; + } + + private static String replaceHardVariables0(CommandSender sender, String message, Matcher matcher) { final Player player = sender instanceof Player ? (Player) sender : null; while (matcher.find()) { @@ -357,8 +381,6 @@ private static String replaceHardVariables0(CommandSender sender, String message } } - message = Messenger.replacePrefixes(message); - return message; } From d78ffc7d2bfa24b4c9423d97bec2e9fc8fbe35e4 Mon Sep 17 00:00:00 2001 From: kangarko Date: Tue, 16 Aug 2022 16:57:08 +0200 Subject: [PATCH 18/30] Reformat --- .../java/org/mineacademy/fo/BlockUtil.java | 6 +- .../org/mineacademy/fo/ReflectionUtil.java | 10 +- .../fo/bungee/message/IncomingMessage.java | 1 - .../mineacademy/fo/collection/StrictMap.java | 3 +- .../collection/expiringmap/ExpiringMap.java | 5 +- .../mineacademy/fo/command/SimpleCommand.java | 4 +- .../fo/command/SimpleCommandGroup.java | 137 +- .../fo/menu/model/ItemCreator.java | 60 +- .../org/mineacademy/fo/metrics/Metrics.java | 372 +++-- .../org/mineacademy/fo/model/HookManager.java | 17 +- .../fo/model/JavaScriptExecutor.java | 2 +- .../mineacademy/fo/model/PacketListener.java | 10 +- .../org/mineacademy/fo/model/RangedValue.java | 8 +- .../fo/model/SimpleScoreboard.java | 1196 ++++++++--------- .../fo/plugin/AutoRegisterScanner.java | 23 +- .../mineacademy/fo/plugin/SimplePlugin.java | 83 +- .../org/mineacademy/fo/remain/CompSound.java | 20 +- .../org/mineacademy/fo/remain/Remain.java | 8 +- .../mineacademy/fo/remain/nbt/NBTItem.java | 2 +- .../mineacademy/fo/remain/nbt/NBTList.java | 6 +- .../fo/remain/nbt/NBTListCompound.java | 2 +- .../mineacademy/fo/settings/FileConfig.java | 5 +- 22 files changed, 946 insertions(+), 1034 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/BlockUtil.java b/src/main/java/org/mineacademy/fo/BlockUtil.java index 8b3312832..40de10443 100644 --- a/src/main/java/org/mineacademy/fo/BlockUtil.java +++ b/src/main/java/org/mineacademy/fo/BlockUtil.java @@ -410,7 +410,7 @@ public static List getChunks(final Location location, final int radius) { final World world = location.getWorld(); final int chunkX = location.getBlockX() >> 4; - final int chunkZ = location.getBlockZ() >> 4; + final int chunkZ = location.getBlockZ() >> 4; for (int x = chunkX - radius; x <= chunkX + radius; ++x) for (int z = chunkZ - radius; z <= chunkZ + radius; ++z) @@ -652,7 +652,7 @@ public static int findHighestBlock(final Location location, final Predicate predicate) { - int minHeight = MinecraftVersion.atLeast(V.v1_18) ? world.getMinHeight() : 0; + final int minHeight = MinecraftVersion.atLeast(V.v1_18) ? world.getMinHeight() : 0; for (int y = world.getMaxHeight() - 1; y > minHeight; y--) { final Block block = world.getBlockAt(x, y, z); @@ -688,7 +688,7 @@ public static int findAirBlock(final Location location, final boolean topDown, f * @return */ public static int findAirBlock(final World world, final int x, final int z, final boolean topDown, final Predicate predicate) { - int minHeight = (MinecraftVersion.atLeast(V.v1_18) ? world.getMinHeight() : 0) + 1; + final int minHeight = (MinecraftVersion.atLeast(V.v1_18) ? world.getMinHeight() : 0) + 1; if (topDown) for (int y = world.getMaxHeight() - 1; y > minHeight; y--) { diff --git a/src/main/java/org/mineacademy/fo/ReflectionUtil.java b/src/main/java/org/mineacademy/fo/ReflectionUtil.java index 50d01716f..36597405e 100644 --- a/src/main/java/org/mineacademy/fo/ReflectionUtil.java +++ b/src/main/java/org/mineacademy/fo/ReflectionUtil.java @@ -1061,7 +1061,7 @@ public static Class wrapperToPrimitive(Class cls) { primitiveWrapperMap.put(Float.TYPE, Float.class); primitiveWrapperMap.put(Void.TYPE, Void.TYPE); - for (Class primitiveClass : primitiveWrapperMap.keySet()) { + for (final Class primitiveClass : primitiveWrapperMap.keySet()) { final Class wrapperClass = primitiveWrapperMap.get(primitiveClass); if (!primitiveClass.equals(wrapperClass)) @@ -1160,16 +1160,16 @@ public Constructor getConstructor(final Class... paramTypes) throws NoSuch /*public Method getDeclaredMethod(final String name, final Class... paramTypes) throws NoSuchMethodException { if (methodCache.containsKey(name)) { final Collection methods = methodCache.get(name); - + for (final Method method : methods) if (Arrays.equals(paramTypes, method.getParameterTypes())) return method; } - + final Method method = clazz.getDeclaredMethod(name, paramTypes); - + cacheMethod(method); - + return method; }*/ diff --git a/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java b/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java index 7717945b3..a26b9d720 100644 --- a/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java +++ b/src/main/java/org/mineacademy/fo/bungee/message/IncomingMessage.java @@ -7,7 +7,6 @@ import org.bukkit.entity.Player; import org.mineacademy.fo.ReflectionUtil; import org.mineacademy.fo.bungee.BungeeListener; -import org.mineacademy.fo.bungee.BungeeMessageType; import org.mineacademy.fo.collection.SerializedMap; import org.mineacademy.fo.plugin.SimplePlugin; diff --git a/src/main/java/org/mineacademy/fo/collection/StrictMap.java b/src/main/java/org/mineacademy/fo/collection/StrictMap.java index 5a8f43edb..1b81bd231 100644 --- a/src/main/java/org/mineacademy/fo/collection/StrictMap.java +++ b/src/main/java/org/mineacademy/fo/collection/StrictMap.java @@ -256,9 +256,8 @@ public boolean containsValue(V value) { * @param consumer */ public void forEachIterate(BiConsumer consumer) { - for (final Entry entry : this.entrySet()) { + for (final Entry entry : this.entrySet()) consumer.accept(entry.getKey(), entry.getValue()); - } } /** diff --git a/src/main/java/org/mineacademy/fo/collection/expiringmap/ExpiringMap.java b/src/main/java/org/mineacademy/fo/collection/expiringmap/ExpiringMap.java index 2fdea44d4..d8d257dd3 100644 --- a/src/main/java/org/mineacademy/fo/collection/expiringmap/ExpiringMap.java +++ b/src/main/java/org/mineacademy/fo/collection/expiringmap/ExpiringMap.java @@ -788,7 +788,7 @@ public int compareTo(ExpiringEntry other) { @Override public int hashCode() { - return Objects.hash(key, value); + return Objects.hash(this.key, this.value); } @Override @@ -802,9 +802,8 @@ public boolean equals(Object obj) { final ExpiringEntry other = (ExpiringEntry) obj; if (!this.key.equals(other.key)) return false; - if (!Objects.equals(this.value, other.value)) { + if (!Objects.equals(this.value, other.value)) return false; - } return true; } diff --git a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java index 8245e7d23..24d2b6ec3 100644 --- a/src/main/java/org/mineacademy/fo/command/SimpleCommand.java +++ b/src/main/java/org/mineacademy/fo/command/SimpleCommand.java @@ -375,8 +375,8 @@ public final boolean execute(final CommandSender sender, final String label, fin } paginator - .setFoundationHeader(SimpleLocalization.Commands.LABEL_HELP_FOR.replace("{label}", this.getLabel() + sublabel)) - .setPages(Common.toArray(pages)); + .setFoundationHeader(SimpleLocalization.Commands.LABEL_HELP_FOR.replace("{label}", this.getLabel() + sublabel)) + .setPages(Common.toArray(pages)); // Force sending on the main thread Common.runLater(() -> paginator.send(sender)); diff --git a/src/main/java/org/mineacademy/fo/command/SimpleCommandGroup.java b/src/main/java/org/mineacademy/fo/command/SimpleCommandGroup.java index 0f61dd518..150478488 100644 --- a/src/main/java/org/mineacademy/fo/command/SimpleCommandGroup.java +++ b/src/main/java/org/mineacademy/fo/command/SimpleCommandGroup.java @@ -123,21 +123,21 @@ protected SimpleCommandGroup(String labelAndAliases) { * Register this command group into Bukkit and start using it */ public final void register() { - Valid.checkBoolean(!isRegistered(), "Main command already registered as: " + mainCommand); + Valid.checkBoolean(!this.isRegistered(), "Main command already registered as: " + this.mainCommand); - mainCommand = new MainCommand(label); + this.mainCommand = new MainCommand(this.label); - if (aliases != null) - mainCommand.setAliases(aliases); + if (this.aliases != null) + this.mainCommand.setAliases(this.aliases); - mainCommand.register(); - registerSubcommands(); + this.mainCommand.register(); + this.registerSubcommands(); // Sort A-Z - Collections.sort(subcommands.getSource(), Comparator.comparing(SimpleSubCommand::getSublabel)); + Collections.sort(this.subcommands.getSource(), Comparator.comparing(SimpleSubCommand::getSublabel)); // Check for collision - checkSubCommandAliasesCollision(); + this.checkSubCommandAliasesCollision(); } /* @@ -146,9 +146,9 @@ public final void register() { private void checkSubCommandAliasesCollision() { final List aliases = new ArrayList<>(); - for (final SimpleSubCommand subCommand : subcommands) + for (final SimpleSubCommand subCommand : this.subcommands) for (final String alias : subCommand.getSublabels()) { - Valid.checkBoolean(!aliases.contains(alias), "Subcommand '/" + getLabel() + " " + subCommand.getSublabel() + "' has alias '" + alias + "' that is already in use by another subcommand!"); + Valid.checkBoolean(!aliases.contains(alias), "Subcommand '/" + this.getLabel() + " " + subCommand.getSublabel() + "' has alias '" + alias + "' that is already in use by another subcommand!"); aliases.add(alias); } @@ -158,12 +158,12 @@ private void checkSubCommandAliasesCollision() { * Remove this command group from Bukkit. Takes immediate changes in the game. */ public final void unregister() { - Valid.checkBoolean(isRegistered(), "Main command not registered!"); + Valid.checkBoolean(this.isRegistered(), "Main command not registered!"); - mainCommand.unregister(); - mainCommand = null; + this.mainCommand.unregister(); + this.mainCommand = null; - subcommands.clear(); + this.subcommands.clear(); } /** @@ -172,7 +172,7 @@ public final void unregister() { * @return */ public final boolean isRegistered() { - return mainCommand != null; + return this.mainCommand != null; } /** @@ -188,10 +188,10 @@ public final boolean isRegistered() { * @param command */ protected final void registerSubcommand(final SimpleSubCommand command) { - Valid.checkNotNull(mainCommand, "Cannot add subcommands when main command is missing! Call register()"); - Valid.checkBoolean(!subcommands.contains(command), "Subcommand /" + mainCommand.getLabel() + " " + command.getSublabel() + " already registered when trying to add " + command.getClass()); + Valid.checkNotNull(this.mainCommand, "Cannot add subcommands when main command is missing! Call register()"); + Valid.checkBoolean(!this.subcommands.contains(command), "Subcommand /" + this.mainCommand.getLabel() + " " + command.getSublabel() + " already registered when trying to add " + command.getClass()); - subcommands.add(command); + this.subcommands.add(command); } /** @@ -206,7 +206,7 @@ protected final void registerSubcommand(Class parent continue; Valid.checkBoolean(Modifier.isFinal(clazz.getModifiers()), "Make child of " + parentClass.getSimpleName() + " class " + clazz.getSimpleName() + " final to auto register it!"); - registerSubcommand(ReflectionUtil.instantiate(clazz)); + this.registerSubcommand(ReflectionUtil.instantiate(clazz)); } } @@ -217,9 +217,9 @@ protected final void registerSubcommand(Class parent * @param menuHelp */ protected final void registerHelpLine(final String... menuHelp) { - Valid.checkNotNull(mainCommand, "Cannot add subcommands when main command is missing! Call register()"); + Valid.checkNotNull(this.mainCommand, "Cannot add subcommands when main command is missing! Call register()"); - subcommands.add(new FillerSubCommand(this, menuHelp)); + this.subcommands.add(new FillerSubCommand(this, menuHelp)); } // ---------------------------------------------------------------------- @@ -270,7 +270,7 @@ protected List getNoParamsHeader() { final List messages = new ArrayList<>(); messages.add("&8" + Common.chatLineSmooth()); - messages.add(getHeaderPrefix() + " " + SimplePlugin.getNamed() + getTrademark() + " &7" + SimplePlugin.getVersion()); + messages.add(this.getHeaderPrefix() + " " + SimplePlugin.getNamed() + this.getTrademark() + " &7" + SimplePlugin.getVersion()); messages.add(" "); { @@ -281,7 +281,7 @@ protected List getNoParamsHeader() { } { - final String credits = getCredits(); + final String credits = this.getCredits(); if (credits != null && !credits.isEmpty()) messages.add(" " + credits); @@ -304,7 +304,7 @@ protected boolean sendHelpIfNoArgs() { // Return the TM symbol in case we have it for kangarko's plugins private String getTrademark() { - return SimplePlugin.getInstance().getDescription().getAuthors().contains("kangarko") ? getHeaderPrefix() + "&8\u2122" : ""; + return SimplePlugin.getInstance().getDescription().getAuthors().contains("kangarko") ? this.getHeaderPrefix() + "&8\u2122" : ""; } /** @@ -342,7 +342,7 @@ protected String[] getHelpHeader() { return new String[] { "&8", "&8" + Common.chatLineSmooth(), - getHeaderPrefix() + " " + SimplePlugin.getNamed() + getTrademark() + " &7" + SimplePlugin.getVersion(), + this.getHeaderPrefix() + " " + SimplePlugin.getNamed() + this.getTrademark() + " &7" + SimplePlugin.getVersion(), " ", "&2 [] &f= " + SimpleLocalization.Commands.LABEL_OPTIONAL_ARGS, this.getTheme() + " <> &f= " + SimpleLocalization.Commands.LABEL_REQUIRED_ARGS, @@ -404,10 +404,10 @@ private MainCommand(final String label) { super(label); // Let everyone view credits of this command when they run it without any sublabels - setPermission(null); + this.setPermission(null); // We handle help ourselves - setAutoHandleHelp(false); + this.setAutoHandleHelp(false); } /** @@ -421,17 +421,17 @@ protected void onCommand() { SimpleCommandGroup.this.sender = this.sender; // Print a special message on no arguments - if (args.length == 0) { - if (sendHelpIfNoArgs()) - tellSubcommandsHelp(); + if (this.args.length == 0) { + if (SimpleCommandGroup.this.sendHelpIfNoArgs()) + this.tellSubcommandsHelp(); else - tell(getNoParamsHeader()); + this.tell(SimpleCommandGroup.this.getNoParamsHeader()); return; } - final String argument = args[0]; - final SimpleSubCommand command = findSubcommand(argument); + final String argument = this.args[0]; + final SimpleSubCommand command = this.findSubcommand(argument); // Handle subcommands if (command != null) { @@ -439,10 +439,10 @@ protected void onCommand() { try { // Simulate our main label - command.setSublabel(args[0]); + command.setSublabel(this.args[0]); // Run the command - command.execute(sender, getLabel(), args.length == 1 ? new String[] {} : Arrays.copyOfRange(args, 1, args.length)); + command.execute(this.sender, this.getLabel(), this.args.length == 1 ? new String[] {} : Arrays.copyOfRange(this.args, 1, this.args.length)); } finally { // Restore old sublabel after the command has been run @@ -451,13 +451,10 @@ protected void onCommand() { } // Handle help argument - else if (!getHelpLabel().isEmpty() && Valid.isInList(argument, getHelpLabel())) { - tellSubcommandsHelp(); - } - - // Handle unknown argument + else if (!SimpleCommandGroup.this.getHelpLabel().isEmpty() && Valid.isInList(argument, SimpleCommandGroup.this.getHelpLabel())) + this.tellSubcommandsHelp(); else - returnInvalidArgs(); + this.returnInvalidArgs(); } /** @@ -467,9 +464,9 @@ protected void tellSubcommandsHelp() { // Building help can be heavy so do it off of the main thread Common.runAsync(() -> { - if (subcommands.isEmpty()) { + if (SimpleCommandGroup.this.subcommands.isEmpty()) { if (Messenger.ENABLED) - tellError(SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS); + this.tellError(SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS); else Common.tell(this.sender, SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS); @@ -479,22 +476,22 @@ protected void tellSubcommandsHelp() { final List lines = new ArrayList<>(); final boolean atLeast17 = MinecraftVersion.atLeast(V.v1_7); - for (final SimpleSubCommand subcommand : subcommands) - if (subcommand.showInHelp() && hasPerm(subcommand.getPermission())) { + for (final SimpleSubCommand subcommand : SimpleCommandGroup.this.subcommands) + if (subcommand.showInHelp() && this.hasPerm(subcommand.getPermission())) { // Simulate the sender to enable permission checks in getMultilineHelp for ex. - subcommand.sender = sender; + subcommand.sender = this.sender; if (subcommand instanceof FillerSubCommand) { - tellNoPrefix(((FillerSubCommand) subcommand).getHelpMessages()); + this.tellNoPrefix(((FillerSubCommand) subcommand).getHelpMessages()); continue; } - final String usage = colorizeUsage(subcommand.getUsage()); + final String usage = this.colorizeUsage(subcommand.getUsage()); final String desc = Common.getOrEmpty(subcommand.getDescription()); - final String plainMessage = Replacer.replaceArray(getSubcommandDescription(), - "label", getLabel(), + final String plainMessage = Replacer.replaceArray(SimpleCommandGroup.this.getSubcommandDescription(), + "label", this.getLabel(), "sublabel", (atLeast17 ? "&n" : "") + subcommand.getSublabel() + (atLeast17 ? "&r" : ""), "usage", usage, "description", !desc.isEmpty() && !atLeast17 ? desc : "", @@ -515,7 +512,7 @@ protected void tellSubcommandsHelp() { hover.add(SimpleLocalization.Commands.HELP_TOOLTIP_USAGE); for (final String usageLine : subcommand.getMultilineUsageMessage()) - hover.add("&f" + replacePlaceholders(colorizeUsage(usageLine.replace("{sublabel}", subcommand.getSublabel())))); + hover.add("&f" + this.replacePlaceholders(this.colorizeUsage(usageLine.replace("{sublabel}", subcommand.getSublabel())))); } else hover.add(SimpleLocalization.Commands.HELP_TOOLTIP_USAGE + (usage.isEmpty() ? command : usage)); @@ -527,32 +524,30 @@ protected void tellSubcommandsHelp() { } line.onHover(hover); - line.onClickSuggestCmd("/" + getLabel() + " " + subcommand.getSublabel()); + line.onClickSuggestCmd("/" + this.getLabel() + " " + subcommand.getSublabel()); } lines.add(line); } if (!lines.isEmpty()) { - final ChatPaginator pages = new ChatPaginator(MathUtil.range(0, lines.size(), getCommandsPerPage()), ChatColor.DARK_GRAY); + final ChatPaginator pages = new ChatPaginator(MathUtil.range(0, lines.size(), SimpleCommandGroup.this.getCommandsPerPage()), ChatColor.DARK_GRAY); - if (getHelpHeader() != null) - pages.setHeader(getHelpHeader()); + if (SimpleCommandGroup.this.getHelpHeader() != null) + pages.setHeader(SimpleCommandGroup.this.getHelpHeader()); pages.setPages(lines); // Allow "? " page parameter - final int page = (args.length > 1 && Valid.isInteger(args[1]) ? Integer.parseInt(args[1]) : 1); + final int page = (this.args.length > 1 && Valid.isInteger(this.args[1]) ? Integer.parseInt(this.args[1]) : 1); // Send the component on the main thread - Common.runLater(() -> pages.send(sender, page)); + Common.runLater(() -> pages.send(this.sender, page)); - } else { - if (Messenger.ENABLED) - tellError(SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS_PERMISSION); - else - Common.tell(this.sender, SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS_PERMISSION); - } + } else if (Messenger.ENABLED) + this.tellError(SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS_PERMISSION); + else + Common.tell(this.sender, SimpleLocalization.Commands.HEADER_NO_SUBCOMMANDS_PERMISSION); }); } @@ -573,7 +568,7 @@ private String colorizeUsage(final String message) { * @return */ private SimpleSubCommand findSubcommand(final String label) { - for (final SimpleSubCommand command : subcommands) { + for (final SimpleSubCommand command : SimpleCommandGroup.this.subcommands) { if (command instanceof FillerSubCommand) continue; @@ -590,14 +585,14 @@ private SimpleSubCommand findSubcommand(final String label) { */ @Override public List tabComplete() { - if (args.length == 1) - return tabCompleteSubcommands(sender, args[0]); + if (this.args.length == 1) + return this.tabCompleteSubcommands(this.sender, this.args[0]); - if (args.length > 1) { - final SimpleSubCommand cmd = findSubcommand(args[0]); + if (this.args.length > 1) { + final SimpleSubCommand cmd = this.findSubcommand(this.args[0]); if (cmd != null) - return cmd.tabComplete(sender, getLabel(), Arrays.copyOfRange(args, 1, args.length)); + return cmd.tabComplete(this.sender, this.getLabel(), Arrays.copyOfRange(this.args, 1, this.args.length)); } return null; @@ -615,8 +610,8 @@ private List tabCompleteSubcommands(final CommandSender sender, String p final List tab = new ArrayList<>(); - for (final SimpleSubCommand subcommand : subcommands) - if (subcommand.showInHelp() && !(subcommand instanceof FillerSubCommand) && hasPerm(subcommand.getPermission())) + for (final SimpleSubCommand subcommand : SimpleCommandGroup.this.subcommands) + if (subcommand.showInHelp() && !(subcommand instanceof FillerSubCommand) && this.hasPerm(subcommand.getPermission())) for (final String label : subcommand.getSublabels()) if (!label.trim().isEmpty() && label.startsWith(param)) tab.add(label); diff --git a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java index 4df67a113..c84e77741 100644 --- a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java +++ b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java @@ -528,48 +528,38 @@ public ItemStack make() { // Apply specific material color if possible color: - if (this.color != null) { + if (this.color != null) + if (compiledItem.getType().toString().contains("LEATHER")) { + if (MinecraftVersion.atLeast(V.v1_4)) { + Valid.checkBoolean(compiledMeta instanceof LeatherArmorMeta, "Expected a leather item, cannot apply color to " + compiledItem); - if (compiledItem.getType().toString().contains("LEATHER")) { - if (MinecraftVersion.atLeast(V.v1_4)) { - Valid.checkBoolean(compiledMeta instanceof LeatherArmorMeta, "Expected a leather item, cannot apply color to " + compiledItem); - - ((LeatherArmorMeta) compiledMeta).setColor(this.color.getColor()); - } + ((LeatherArmorMeta) compiledMeta).setColor(this.color.getColor()); } + } else // Hack: If you put WHITE_WOOL and a color, we automatically will change the material to the colorized version + if (MinecraftVersion.atLeast(V.v1_13)) { + final String dye = this.color.getDye().toString(); + final List colorableMaterials = Arrays.asList("BANNER", "BED", "CARPET", "CONCRETE", "GLAZED_TERRACOTTA", "SHULKER_BOX", "STAINED_GLASS", + "STAINED_GLASS_PANE", "TERRACOTTA", "WALL_BANNER", "WOOL"); - else { - - // Hack: If you put WHITE_WOOL and a color, we automatically will change the material to the colorized version - if (MinecraftVersion.atLeast(V.v1_13)) { - final String dye = this.color.getDye().toString(); - final List colorableMaterials = Arrays.asList("BANNER", "BED", "CARPET", "CONCRETE", "GLAZED_TERRACOTTA", "SHULKER_BOX", "STAINED_GLASS", - "STAINED_GLASS_PANE", "TERRACOTTA", "WALL_BANNER", "WOOL"); + for (final String material : colorableMaterials) { + final String suffix = "_" + material; - for (final String material : colorableMaterials) { - final String suffix = "_" + material; + if (compiledItem.getType().toString().endsWith(suffix)) { + compiledItem.setType(Material.valueOf(dye + suffix)); - if (compiledItem.getType().toString().endsWith(suffix)) { - compiledItem.setType(Material.valueOf(dye + suffix)); - - break color; - } - } + break color; } + } + } else + try { + final byte dataValue = this.color.getDye().getWoolData(); - else { - try { - final byte dataValue = this.color.getDye().getWoolData(); - - compiledItem.setData(new MaterialData(compiledItem.getType(), dataValue)); - compiledItem.setDurability(dataValue); + compiledItem.setData(new MaterialData(compiledItem.getType(), dataValue)); + compiledItem.setDurability(dataValue); - } catch (final NoSuchMethodError err) { - // Ancient MC, ignore - } - } + } catch (final NoSuchMethodError err) { + // Ancient MC, ignore } - } // Fix monster eggs if (compiledItem.getType().toString().endsWith("SPAWN_EGG") || compiledItem.getType().toString().equals("MONSTER_EGG")) { @@ -677,7 +667,7 @@ else if ("ZOMBIE_PIGMAN".equals(entityRaw)) } if (this.name != null && !"".equals(this.name)) - ((ItemMeta) compiledMeta).setDisplayName(Common.colorize("&r&f" + name)); + ((ItemMeta) compiledMeta).setDisplayName(Common.colorize("&r&f" + this.name)); if (!this.lores.isEmpty()) { final List coloredLores = new ArrayList<>(); @@ -747,7 +737,7 @@ else if ("ZOMBIE_PIGMAN".equals(entityRaw)) compiledItem = CompMetadata.setMetadata(compiledItem, entry.getKey(), entry.getValue()); else if (!this.tags.isEmpty() && this.item != null) - Common.log("Item had unsupported tags " + tags + " that are not supported on MC " + MinecraftVersion.getServerVersion() + " Item: " + compiledItem); + Common.log("Item had unsupported tags " + this.tags + " that are not supported on MC " + MinecraftVersion.getServerVersion() + " Item: " + compiledItem); return compiledItem; } diff --git a/src/main/java/org/mineacademy/fo/metrics/Metrics.java b/src/main/java/org/mineacademy/fo/metrics/Metrics.java index 9d47bed21..b9dd55d50 100644 --- a/src/main/java/org/mineacademy/fo/metrics/Metrics.java +++ b/src/main/java/org/mineacademy/fo/metrics/Metrics.java @@ -64,9 +64,9 @@ public class Metrics { public Metrics(int serviceId) { // Get the config file - File bStatsFolder = new File(SimplePlugin.getData().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + final File bStatsFolder = new File(SimplePlugin.getData().getParentFile(), "bStats"); + final File configFile = new File(bStatsFolder, "config.yml"); + final YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); if (!config.isSet("serverUuid")) { config.addDefault("enabled", true); config.addDefault("serverUuid", UUID.randomUUID().toString()); @@ -75,40 +75,39 @@ public Metrics(int serviceId) { config.addDefault("logResponseStatusText", false); // Inform the server owners about bStats config - .options() - .header( - "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" - + "many people use their plugin and their total player count. It's recommended to keep bStats\n" - + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" - + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" - + "anonymous.") - .copyDefaults(true); + .options() + .header( + "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" + + "many people use their plugin and their total player count. It's recommended to keep bStats\n" + + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" + + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" + + "anonymous.") + .copyDefaults(true); try { config.save(configFile); - } catch (IOException ignored) { + } catch (final IOException ignored) { } } // Load the data - boolean enabled = config.getBoolean("enabled", true); - String serverUUID = config.getString("serverUuid"); - boolean logErrors = config.getBoolean("logFailedRequests", false); - boolean logSentData = config.getBoolean("logSentData", false); - boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); - metricsBase = - new MetricsBase( - "bukkit", - serverUUID, - serviceId, - enabled, - this::appendPlatformData, - this::appendServiceData, - submitDataTask -> Bukkit.getScheduler().runTask(SimplePlugin.getInstance(), submitDataTask), - () -> true, - (message, error) -> Common.error(error, message), - Common::log, - logErrors, - logSentData, - logResponseStatusText); + final boolean enabled = config.getBoolean("enabled", true); + final String serverUUID = config.getString("serverUuid"); + final boolean logErrors = config.getBoolean("logFailedRequests", false); + final boolean logSentData = config.getBoolean("logSentData", false); + final boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); + this.metricsBase = new MetricsBase( + "bukkit", + serverUUID, + serviceId, + enabled, + this::appendPlatformData, + this::appendServiceData, + submitDataTask -> Bukkit.getScheduler().runTask(SimplePlugin.getInstance(), submitDataTask), + () -> true, + (message, error) -> Common.error(error, message), + Common::log, + logErrors, + logSentData, + logResponseStatusText); } /** @@ -117,11 +116,11 @@ public Metrics(int serviceId) { * @param chart The chart to add. */ public void addCustomChart(CustomChart chart) { - metricsBase.addCustomChart(chart); + this.metricsBase.addCustomChart(chart); } private void appendPlatformData(JsonObjectBuilder builder) { - builder.appendField("playerAmount", getPlayerAmount()); + builder.appendField("playerAmount", this.getPlayerAmount()); builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); builder.appendField("bukkitVersion", Bukkit.getVersion()); builder.appendField("bukkitName", Bukkit.getName()); @@ -141,11 +140,11 @@ private int getPlayerAmount() { // Around MC 1.8 the return type was changed from an array to a collection, // This fixes java.lang.NoSuchMethodError: // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + final Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); return onlinePlayersMethod.getReturnType().equals(Collection.class) ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (final Exception e) { // Just use the new method if the reflection failed return Bukkit.getOnlinePlayers().size(); } @@ -156,8 +155,7 @@ public static class MetricsBase { /** The version of the Metrics class. */ public static final String METRICS_VERSION = "3.0.0"; - private static final ScheduledExecutorService scheduler = - Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); + private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; @@ -237,11 +235,10 @@ public MetricsBase( this.logErrors = logErrors; this.logSentData = logSentData; this.logResponseStatusText = logResponseStatusText; - checkRelocation(); - if (enabled) { + this.checkRelocation(); + if (enabled) // WARNING: Removing the option to opt-out will get your plugin banned from bStats - startSubmitting(); - } + this.startSubmitting(); } public void addCustomChart(CustomChart chart) { @@ -249,71 +246,66 @@ public void addCustomChart(CustomChart chart) { } private void startSubmitting() { - final Runnable submitTask = - () -> { - if (!enabled || !checkServiceEnabledSupplier.get()) { - // Submitting data or service is disabled - scheduler.shutdown(); - return; - } - if (submitTaskConsumer != null) { - submitTaskConsumer.accept(this::submitData); - } else { - this.submitData(); - } - }; - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution - // of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial - // and second delay. - // WARNING: You must not modify and part of this Metrics class, including the submit delay or - // frequency! - // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! - long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); - long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); - scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); - scheduler.scheduleAtFixedRate( - submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); + final Runnable submitTask = () -> { + if (!this.enabled || !this.checkServiceEnabledSupplier.get()) { + // Submitting data or service is disabled + scheduler.shutdown(); + return; + } + if (this.submitTaskConsumer != null) + this.submitTaskConsumer.accept(this::submitData); + else + this.submitData(); + }; + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution + // of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial + // and second delay. + // WARNING: You must not modify and part of this Metrics class, including the submit delay or + // frequency! + // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! + final long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); + final long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); + scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate( + submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); } private void submitData() { final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); - appendPlatformDataConsumer.accept(baseJsonBuilder); + this.appendPlatformDataConsumer.accept(baseJsonBuilder); final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); - appendServiceDataConsumer.accept(serviceJsonBuilder); - JsonObjectBuilder.JsonObject[] chartData = - customCharts.stream() - .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) + this.appendServiceDataConsumer.accept(serviceJsonBuilder); + final JsonObjectBuilder.JsonObject[] chartData = this.customCharts.stream() + .map(customChart -> customChart.getRequestJsonObject(this.errorLogger, this.logErrors)) .filter(Objects::nonNull) .toArray(JsonObjectBuilder.JsonObject[]::new); - serviceJsonBuilder.appendField("id", serviceId); + serviceJsonBuilder.appendField("id", this.serviceId); serviceJsonBuilder.appendField("customCharts", chartData); baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); - baseJsonBuilder.appendField("serverUUID", serverUuid); + baseJsonBuilder.appendField("serverUUID", this.serverUuid); baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); - JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); + final JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); scheduler.execute( () -> { try { // Send the data - sendData(data); - } catch (Exception e) { + this.sendData(data); + } catch (final Exception e) { // Something went wrong! :( - if (logErrors) { - errorLogger.accept("Could not submit bStats metrics data", e); - } + if (this.logErrors) + this.errorLogger.accept("Could not submit bStats metrics data", e); } }); } private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { - if (logSentData) { - infoLogger.accept("Sent bStats metrics data: " + data.toString()); - } - String url = String.format(REPORT_URL, platform); - HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + if (this.logSentData) + this.infoLogger.accept("Sent bStats metrics data: " + data.toString()); + final String url = String.format(REPORT_URL, this.platform); + final HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); + final byte[] compressedData = compress(data.toString()); connection.setRequestMethod("POST"); connection.addRequestProperty("Accept", "application/json"); connection.addRequestProperty("Connection", "close"); @@ -325,17 +317,14 @@ private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { outputStream.write(compressedData); } - StringBuilder builder = new StringBuilder(); - try (BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + final StringBuilder builder = new StringBuilder(); + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { String line; - while ((line = bufferedReader.readLine()) != null) { + while ((line = bufferedReader.readLine()) != null) builder.append(line); - } - } - if (logResponseStatusText) { - infoLogger.accept("Sent data to bStats and received response: " + builder); } + if (this.logResponseStatusText) + this.infoLogger.accept("Sent data to bStats and received response: " + builder); } /** Checks that the class was properly relocated. */ @@ -345,16 +334,13 @@ private void checkRelocation() { || !System.getProperty("bstats.relocatecheck").equals("false")) { // Maven's Relocate is clever and changes strings, too. So we have to use this little // "trick" ... :D - final String defaultPackage = - new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); - final String examplePackage = - new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); + final String defaultPackage = new String(new byte[] { 'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's' }); + final String examplePackage = new String(new byte[] { 'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e' }); // We want to make sure no one just copy & pastes the example and uses the wrong package // names if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) - || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { + || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } } } @@ -365,10 +351,9 @@ private void checkRelocation() { * @return The gzipped string. */ private static byte[] compress(final String str) throws IOException { - if (str == null) { + if (str == null) return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { gzip.write(str.getBytes(StandardCharsets.UTF_8)); } @@ -393,17 +378,16 @@ public DrilldownPie(String chartId, Callable>> @Override public JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map> map = callable.call(); - if (map == null || map.isEmpty()) { + final JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + final Map> map = this.callable.call(); + if (map == null || map.isEmpty()) // Null = skip the chart return null; - } boolean reallyAllSkipped = true; - for (Map.Entry> entryValues : map.entrySet()) { - JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); + for (final Map.Entry> entryValues : map.entrySet()) { + final JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); boolean allSkipped = true; - for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { + for (final Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); allSkipped = false; } @@ -412,10 +396,9 @@ public JsonObjectBuilder.JsonObject getChartData() throws Exception { valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); } } - if (reallyAllSkipped) { + if (reallyAllSkipped) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); } } @@ -437,25 +420,22 @@ public AdvancedPie(String chartId, Callable> callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { + final JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + final Map map = this.callable.call(); + if (map == null || map.isEmpty()) // Null = skip the chart return null; - } boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { + for (final Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) // Skip this invalid continue; - } allSkipped = false; valuesBuilder.appendField(entry.getKey(), entry.getValue()); } - if (allSkipped) { + if (allSkipped) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); } } @@ -477,25 +457,22 @@ public MultiLineChart(String chartId, Callable> callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { + final JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + final Map map = this.callable.call(); + if (map == null || map.isEmpty()) // Null = skip the chart return null; - } boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { + for (final Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) // Skip this invalid continue; - } allSkipped = false; valuesBuilder.appendField(entry.getKey(), entry.getValue()); } - if (allSkipped) { + if (allSkipped) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); } } @@ -517,15 +494,13 @@ public SimpleBarChart(String chartId, Callable> callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { + final JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + final Map map = this.callable.call(); + if (map == null || map.isEmpty()) // Null = skip the chart return null; - } - for (Map.Entry entry : map.entrySet()) { - valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()}); - } + for (final Map.Entry entry : map.entrySet()) + valuesBuilder.appendField(entry.getKey(), new int[] { entry.getValue() }); return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); } } @@ -535,27 +510,24 @@ public abstract static class CustomChart { private final String chartId; protected CustomChart(String chartId) { - if (chartId == null) { + if (chartId == null) throw new IllegalArgumentException("chartId must not be null"); - } this.chartId = chartId; } public JsonObjectBuilder.JsonObject getRequestJsonObject( BiConsumer errorLogger, boolean logErrors) { - JsonObjectBuilder builder = new JsonObjectBuilder(); - builder.appendField("chartId", chartId); + final JsonObjectBuilder builder = new JsonObjectBuilder(); + builder.appendField("chartId", this.chartId); try { - JsonObjectBuilder.JsonObject data = getChartData(); - if (data == null) { + final JsonObjectBuilder.JsonObject data = this.getChartData(); + if (data == null) // If the data is null we don't send the chart. return null; - } builder.appendField("data", data); - } catch (Throwable t) { - if (logErrors) { - errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); - } + } catch (final Throwable t) { + if (logErrors) + errorLogger.accept("Failed to get data for custom chart with id " + this.chartId, t); return null; } return builder.build(); @@ -581,11 +553,10 @@ public SimplePie(String chartId, Callable callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - String value = callable.call(); - if (value == null || value.isEmpty()) { + final String value = this.callable.call(); + if (value == null || value.isEmpty()) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("value", value).build(); } } @@ -607,25 +578,22 @@ public AdvancedBarChart(String chartId, Callable> callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { + final JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + final Map map = this.callable.call(); + if (map == null || map.isEmpty()) // Null = skip the chart return null; - } boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue().length == 0) { + for (final Map.Entry entry : map.entrySet()) { + if (entry.getValue().length == 0) // Skip this invalid continue; - } allSkipped = false; valuesBuilder.appendField(entry.getKey(), entry.getValue()); } - if (allSkipped) { + if (allSkipped) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); } } @@ -647,11 +615,10 @@ public SingleLineChart(String chartId, Callable callable) { @Override protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - int value = callable.call(); - if (value == 0) { + final int value = this.callable.call(); + if (value == 0) // Null = skip the chart return null; - } return new JsonObjectBuilder().appendField("value", value).build(); } } @@ -669,7 +636,7 @@ public static class JsonObjectBuilder { private boolean hasAtLeastOneField = false; public JsonObjectBuilder() { - builder.append("{"); + this.builder.append("{"); } /** @@ -679,7 +646,7 @@ public JsonObjectBuilder() { * @return A reference to this object. */ public JsonObjectBuilder appendNull(String key) { - appendFieldUnescaped(key, "null"); + this.appendFieldUnescaped(key, "null"); return this; } @@ -691,10 +658,9 @@ public JsonObjectBuilder appendNull(String key) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, String value) { - if (value == null) { + if (value == null) throw new IllegalArgumentException("JSON value must not be null"); - } - appendFieldUnescaped(key, "\"" + escape(value) + "\""); + this.appendFieldUnescaped(key, "\"" + escape(value) + "\""); return this; } @@ -706,7 +672,7 @@ public JsonObjectBuilder appendField(String key, String value) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, int value) { - appendFieldUnescaped(key, String.valueOf(value)); + this.appendFieldUnescaped(key, String.valueOf(value)); return this; } @@ -718,10 +684,9 @@ public JsonObjectBuilder appendField(String key, int value) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, JsonObject object) { - if (object == null) { + if (object == null) throw new IllegalArgumentException("JSON object must not be null"); - } - appendFieldUnescaped(key, object.toString()); + this.appendFieldUnescaped(key, object.toString()); return this; } @@ -733,14 +698,12 @@ public JsonObjectBuilder appendField(String key, JsonObject object) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, String[] values) { - if (values == null) { + if (values == null) throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values) + final String escapedValues = Arrays.stream(values) .map(value -> "\"" + escape(value) + "\"") .collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); + this.appendFieldUnescaped(key, "[" + escapedValues + "]"); return this; } @@ -752,12 +715,10 @@ public JsonObjectBuilder appendField(String key, String[] values) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, int[] values) { - if (values == null) { + if (values == null) throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); + final String escapedValues = Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); + this.appendFieldUnescaped(key, "[" + escapedValues + "]"); return this; } @@ -769,12 +730,10 @@ public JsonObjectBuilder appendField(String key, int[] values) { * @return A reference to this object. */ public JsonObjectBuilder appendField(String key, JsonObject[] values) { - if (values == null) { + if (values == null) throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); + final String escapedValues = Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); + this.appendFieldUnescaped(key, "[" + escapedValues + "]"); return this; } @@ -785,17 +744,14 @@ public JsonObjectBuilder appendField(String key, JsonObject[] values) { * @param escapedValue The escaped value of the field. */ private void appendFieldUnescaped(String key, String escapedValue) { - if (builder == null) { + if (this.builder == null) throw new IllegalStateException("JSON has already been built"); - } - if (key == null) { + if (key == null) throw new IllegalArgumentException("JSON key must not be null"); - } - if (hasAtLeastOneField) { - builder.append(","); - } - builder.append("\"").append(escape(key)).append("\":").append(escapedValue); - hasAtLeastOneField = true; + if (this.hasAtLeastOneField) + this.builder.append(","); + this.builder.append("\"").append(escape(key)).append("\":").append(escapedValue); + this.hasAtLeastOneField = true; } /** @@ -804,11 +760,10 @@ private void appendFieldUnescaped(String key, String escapedValue) { * @return The built JSON string. */ public JsonObject build() { - if (builder == null) { + if (this.builder == null) throw new IllegalStateException("JSON has already been built"); - } - JsonObject object = new JsonObject(builder.append("}").toString()); - builder = null; + final JsonObject object = new JsonObject(this.builder.append("}").toString()); + this.builder = null; return object; } @@ -824,18 +779,17 @@ public JsonObject build() { private static String escape(String value) { final StringBuilder builder = new StringBuilder(); for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (c == '"') { + final char c = value.charAt(i); + if (c == '"') builder.append("\\\""); - } else if (c == '\\') { + else if (c == '\\') builder.append("\\\\"); - } else if (c <= '\u000F') { + else if (c <= '\u000F') builder.append("\\u000").append(Integer.toHexString(c)); - } else if (c <= '\u001F') { + else if (c <= '\u001F') builder.append("\\u00").append(Integer.toHexString(c)); - } else { + else builder.append(c); - } } return builder.toString(); } @@ -857,7 +811,7 @@ private JsonObject(String value) { @Override public String toString() { - return value; + return this.value; } } } diff --git a/src/main/java/org/mineacademy/fo/model/HookManager.java b/src/main/java/org/mineacademy/fo/model/HookManager.java index 2f914ae5e..d1a151043 100644 --- a/src/main/java/org/mineacademy/fo/model/HookManager.java +++ b/src/main/java/org/mineacademy/fo/model/HookManager.java @@ -50,7 +50,6 @@ import com.bekvon.bukkit.residence.protection.ClaimedResidence; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketListener; import com.earth2me.essentials.CommandSource; @@ -2181,8 +2180,8 @@ private String setPlaceholders(final OfflinePlayer player, String text) { if (hooks.isEmpty()) return text; - text = setPlaceholders(player, oldText, text, hooks, Variables.VARIABLE_PATTERN.matcher(text)); - text = setPlaceholders(player, oldText, text, hooks, Variables.BRACKET_VARIABLE_PATTERN.matcher(text)); + text = this.setPlaceholders(player, oldText, text, hooks, Variables.VARIABLE_PATTERN.matcher(text)); + text = this.setPlaceholders(player, oldText, text, hooks, Variables.BRACKET_VARIABLE_PATTERN.matcher(text)); return text; } @@ -2278,8 +2277,8 @@ private String setRelationalPlaceholders(final Player one, final Player two, Str if (hooks.isEmpty()) return text; - text = setRelationalPlaceholders(one, two, text, hooks, Variables.REL_VARIABLE_PATTERN.matcher(text)); - text = setRelationalPlaceholders(one, two, text, hooks, Variables.BRACKET_REL_VARIABLE_PATTERN.matcher(text)); + text = this.setRelationalPlaceholders(one, two, text, hooks, Variables.REL_VARIABLE_PATTERN.matcher(text)); + text = this.setRelationalPlaceholders(one, two, text, hooks, Variables.BRACKET_REL_VARIABLE_PATTERN.matcher(text)); return text; } @@ -3376,16 +3375,16 @@ boolean isMuted(final Player player) { /*try { final Class api = ReflectionUtil.lookupClass("litebans.api.Database"); final Object instance = ReflectionUtil.invokeStatic(api, "get"); - + return ReflectionUtil.invoke("isPlayerMuted", instance, player.getUniqueId()); - + } catch (final Throwable t) { if (!t.toString().contains("Could not find class")) { Common.log("Unable to check if " + player.getName() + " is muted at LiteBans. Is the API hook outdated? See console error:"); - + t.printStackTrace(); } - + return false; }*/ } diff --git a/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java b/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java index 414d55025..841a961e8 100644 --- a/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java +++ b/src/main/java/org/mineacademy/fo/model/JavaScriptExecutor.java @@ -163,7 +163,7 @@ public static Object run(@NonNull String javascript, final CommandSender sender, Object result = engine.eval(javascript); if (result instanceof String) { - String resultString = Common.stripColors((String) result).toLowerCase(); + final String resultString = Common.stripColors((String) result).toLowerCase(); if (resultString.equals("true") || resultString.equals("yes")) result = true; diff --git a/src/main/java/org/mineacademy/fo/model/PacketListener.java b/src/main/java/org/mineacademy/fo/model/PacketListener.java index 77d61797d..f9dc0cb13 100644 --- a/src/main/java/org/mineacademy/fo/model/PacketListener.java +++ b/src/main/java/org/mineacademy/fo/model/PacketListener.java @@ -26,7 +26,6 @@ import com.comphenix.protocol.wrappers.EnumWrappers.ChatType; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.comphenix.protocol.wrappers.WrappedServerPing; import lombok.AccessLevel; import lombok.Getter; @@ -251,8 +250,8 @@ public void onPacketSending(final PacketEvent event) { // Such errors mean the parsed message took too long to process. // Only show such errors every 30 minutes to prevent console spam Common.logTimed(1800, "&cWarning: &fPacket message '" + Common.limit(this.jsonMessage, 500) - + "' (possibly longer) took too long time to edit received message and was ignored." - + " This message only shows once per 30 minutes when that happens. For most cases, this can be ignored."); + + "' (possibly longer) took too long time to edit received message and was ignored." + + " This message only shows once per 30 minutes when that happens. For most cases, this can be ignored."); return; @@ -358,10 +357,9 @@ private void writeEditedMessage(String message, PacketEvent event) { this.jsonMessage = Remain.toJson(message); - if (this.systemChat) { + if (this.systemChat) event.getPacket().getStrings().writeSafely(0, this.jsonMessage); - - } else if (this.isBaseComponent) + else if (this.isBaseComponent) packet.writeSafely(this.adventure ? 2 : 1, Remain.toComponent(this.jsonMessage)); else if (MinecraftVersion.atLeast(V.v1_7)) diff --git a/src/main/java/org/mineacademy/fo/model/RangedValue.java b/src/main/java/org/mineacademy/fo/model/RangedValue.java index bb685a390..05d2dabe7 100644 --- a/src/main/java/org/mineacademy/fo/model/RangedValue.java +++ b/src/main/java/org/mineacademy/fo/model/RangedValue.java @@ -145,9 +145,9 @@ public static RangedValue parse(String line) { } String[] parts; - String[] split = line.split("\\-"); + final String[] split = line.split("\\-"); - boolean secondNegative = split.length == 3; + final boolean secondNegative = split.length == 3; if (split.length == 1) parts = new String[] { (firstNegative ? "-" : "") + line }; @@ -172,11 +172,11 @@ public static RangedValue parse(String line) { // Check if 1<2 if (first.contains(".")) Valid.checkBoolean(firstNumber.longValue() <= secondNumber.longValue(), - "First number cannot be greater than second: " + firstNumber.longValue() + " vs " + secondNumber.longValue() + " in " + line); + "First number cannot be greater than second: " + firstNumber.longValue() + " vs " + secondNumber.longValue() + " in " + line); else Valid.checkBoolean(firstNumber.doubleValue() <= secondNumber.doubleValue(), - "First number cannot be greater than second: " + firstNumber.doubleValue() + " vs " + secondNumber.doubleValue() + " in " + line); + "First number cannot be greater than second: " + firstNumber.doubleValue() + " vs " + secondNumber.doubleValue() + " in " + line); return new RangedValue(firstNumber, secondNumber); } diff --git a/src/main/java/org/mineacademy/fo/model/SimpleScoreboard.java b/src/main/java/org/mineacademy/fo/model/SimpleScoreboard.java index 89ccfc616..ab4704de1 100644 --- a/src/main/java/org/mineacademy/fo/model/SimpleScoreboard.java +++ b/src/main/java/org/mineacademy/fo/model/SimpleScoreboard.java @@ -38,609 +38,603 @@ */ public class SimpleScoreboard { - // ------------------------------------------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------------------------------------------ - - private static final String COLOR_CHAR = "\u00A7"; - - /** - * List of all active scoreboard (added upon creating a new instance) - */ - @Getter - private static final List registeredBoards = new ArrayList<>(); - - /** - * Unique chat color identifiers for specific team entries - */ - private static final String[] colors = - new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; - - /** - * Stored scoreboard lines - */ - private final List rows = new ArrayList<>(); - - /** - * Stored players viewing THIS scoreboard - */ - - private final List viewers = new ArrayList<>(); - - /** - * The color theme for key: value pairs such as - *

- * Players: 12 - * Mode: playing - */ - private final String[] theme = new String[2]; - - /** - * The title of this scoreboard - */ - private String title; - - /** - * The update tick delay - */ - @Getter - private int updateDelayTicks = 20; - - /** - * The running update task - */ - private BukkitTask updateTask; - - /** - * Create a new scoreboard updating every second - */ - - public SimpleScoreboard() { - registeredBoards.add(this); - } - - public SimpleScoreboard(String title) { - this(title, 20); - } - - /** - * Create a new scoreboard with customizable updateDelayTicks - */ - public SimpleScoreboard(String title, int updateDelayTicks) { - //Scoreboards were introduced in 1.5, objectives were added in 1.7.2 - Valid.checkBoolean( - MinecraftVersion.atLeast(MinecraftVersion.V.v1_7), - "Scoreboards (with objectives) are not supported below Minecraft version 1.7!"); - - this.setTitle(title); - this.setUpdateDelayTicks(updateDelayTicks); - - registeredBoards.add(this); - } - - // ------------------------------------------------------------------------------------------------------------ - // Static - // ------------------------------------------------------------------------------------------------------------ - - /** - * Clears registered boards, usually called on reload - */ - public static void clearBoards() { - registeredBoards.clear(); - } - - /** - * Removes all scoreboard for a player - * - * @param player - */ - public static void clearBoardsFor(final Player player) { - for (final SimpleScoreboard scoreboard : registeredBoards) - if (scoreboard.isViewing(player)) - scoreboard.hide(player); - } - - // ------------------------------------------------------------------------------------------------------------ - // Public entries - // ------------------------------------------------------------------------------------------------------------ - - /** - * Replaces variables in the message for the given player - * - * @param player - * @param message - * @return - */ - protected String replaceVariables(final @NonNull Player player, final @NonNull String message) { - return message; - } - - /** - * Called when this scoreboard is ticked - */ - protected void onUpdate() { - } - - public final String getTitle() { - return this.title; - } - - /** - * @param title the title to set - */ - public final void setTitle(String title) { - final int maxTitleLength = MinecraftVersion.atLeast(MinecraftVersion.V.v1_13) ? 128 : 32; - final String colorizedTitle = Common.colorize(title); - this.title = - colorizedTitle.length() > maxTitleLength ? colorizedTitle.substring(0, maxTitleLength) : colorizedTitle; - this.title = this.title.endsWith(COLOR_CHAR) ? this.title.substring(0, this.title.length() - 1) : this.title; - } - - public List getRows() { - return Common.convert(rows, ScoreboardLine::getText); - } - - /** - * Return true if the scoreboard is running and rendering? - * - * @return - */ - public final boolean isRunning() { - return this.updateTask != null; - } - - /** - * @param updateDelayTicks the updateDelayTicks to set - */ - public final void setUpdateDelayTicks(int updateDelayTicks) { - this.updateDelayTicks = updateDelayTicks; - } - - /** - * Show this scoreboard to the player - * - * @param player - */ - public final void show(final Player player) { - Valid.checkBoolean( - this.title != null && !this.title.isEmpty(), - "Before calling show(Player) you need to use setTitle() for " + this); - Valid.checkBoolean( - !this.isViewing(player), "Player " + player.getName() + " is already viewing scoreboard: " + this); - - if (this.updateTask == null) - this.start(); - - final Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); - this.viewers.add(player.getUniqueId()); - player.setScoreboard(scoreboard); - } - - /** - * Hide this scoreboard from the player - * - * @param player - */ - public final void hide(final Player player) { - Valid.checkBoolean( - this.isViewing(player), - "Player " + player.getName() + " is not viewing scoreboard: " + this.getTitle()); - - player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); - this.viewers.remove(player.getUniqueId()); - - if (this.viewers.isEmpty()) - this.cancelUpdateTask(); - } - - /** - * Returns true if the given player is viewing THIS scoreboard - * - * @param player - * @return - */ - public final boolean isViewing(final Player player) { - return this.viewers.contains(player.getUniqueId()); - } - - /** - * Set the coloring theme for rows having : such as - *

- * Players: 12 - * Mode: playing - *

- * To use simply put color codes - * - * @param primary - * @param secondary - */ - public final void setTheme(@NonNull final ChatColor primary, final ChatColor secondary) { - if (secondary != null) { - this.theme[0] = "&" + primary.getChar(); - this.theme[1] = "&" + secondary.getChar(); - } else - this.theme[0] = "&" + primary.getChar(); - } - - // ------------------------------------------------------------------------------------------------------------ - // Add new rows - // ------------------------------------------------------------------------------------------------------------ - - /** - * Add rows onto the scoreboard - * - * @param entries - */ - public final void addRows(final Object... entries) { - this.addRows(Arrays.asList(entries)); - } - - /** - * Add rows onto the scoreboard - * - * @param entries - */ - public final void addRows(final List entries) { - Valid.checkBoolean( - (this.rows.size() + entries.size()) < 17, "You are trying to add too many rows (the limit is 16)"); - this.rows.addAll( - Common.convert(Common.colorize(Common.convert(entries, Object::toString)), ScoreboardLine::new)); - } - - public final void changeRow(final int index, Object value) { - Valid.checkBoolean( - index < this.rows.size(), - "The row for index " + index + " is currently not existing. Please use addRows()!"); - this.rows.get(index).setText(Common.colorize(value.toString())); - } - - /** - * Remove all rows - */ - public final void clearRows() { - this.rows.clear(); - } - - /** - * Remove row at the given index - * - * @param index - */ - public final void removeRow(final int index) { - this.rows.remove(index); - } - - /** - * Remove row that contains the given text - * - * @param thatContains - */ - public final void removeRow(final String thatContains) { - this.rows.removeIf(row -> row.getText().contains(thatContains)); - } - - // ------------------------------------------------------------------------------------------------------------ - // Start / stop - // ------------------------------------------------------------------------------------------------------------ - - /** - * Starts visualizing this scoreboard - */ - private void start() { - Valid.checkBoolean(this.updateTask == null, "Scoreboard " + this + " already running"); - - this.updateTask = Bukkit.getScheduler().runTaskTimer(SimplePlugin.getInstance(), () -> - { - try { - this.onUpdate(); - - for (final UUID viewerId : new StrictList<>(this.viewers)) { - Player viewer = Bukkit.getPlayer(viewerId); - - if (viewer == null || !viewer.isOnline()) { - this.viewers.remove(viewerId); - continue; - } - - this.reloadEntries(viewer); - } - - } catch (final Throwable t) { - final String lines = String.join(" ", getRows()); - - Common.error(t, "Error displaying " + this, "Entries: " + lines, "Title: " + title, "%error", - "Stopping rendering for safety."); - - this.stop(); - } - }, 0, this.updateDelayTicks); - } - - /** - * Stops this scoreboard and removes it from all viewers - */ - public final void stop() { - this.viewers.forEach(viewerId -> - { - Player viewer = Bukkit.getPlayer(viewerId); - - if (viewer != null && viewer.isOnline()) { - viewer.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); - } - }); - - this.viewers.clear(); - - if (this.updateTask != null) - this.cancelUpdateTask(); - } - - @Override - public final String toString() { - return "Scoreboard{title=" + this.getTitle() + "}"; - } - - // ------------------------------------------------------------------------------------------------------------ - // Private - // ------------------------------------------------------------------------------------------------------------ - - /** - * Adds theme colors to the row if applicable - * - * @param row - * @return - */ - private String replaceTheme(final String row) { - if (row.contains(":")) - if (this.theme.length == 1) - return this.theme[0] + row; - - else if (this.theme[0] != null) { - final String[] split = row.split("\\:"); - - if (split.length > 1) - return this.theme[0] + split[0] + ":" + this.theme[1] + split[1]; - } - - return row; - } - - /** - * Cancels the update task - */ - private void cancelUpdateTask() { - Valid.checkNotNull(this.updateTask, "Scoreboard " + this + " not running"); - - this.updateTask.cancel(); - this.updateTask = null; - } - - // ------------------------------------------------------------------------------------------------------------ - // Rendering - // ------------------------------------------------------------------------------------------------------------ - - /** - * Reload entries for the given player - * - * @param player - */ - private void reloadEntries(Player player) throws IllegalArgumentException { - final int size = this.rows.size(); - final Scoreboard scoreboard = player.getScoreboard(); - Objective mainboard = scoreboard.getObjective("mainboard"); - - if (mainboard == null) { - mainboard = scoreboard.registerNewObjective("mainboard", "dummy"); - mainboard.setDisplayName(title); - mainboard.setDisplaySlot(DisplaySlot.SIDEBAR); - } - - if (!mainboard.getDisplayName().equals(title)) - mainboard.setDisplayName(title); - - for (int lineNumber = 0; lineNumber < 16; lineNumber++) { - final int scoreboardLineNumber = size - lineNumber; - Team line = scoreboard.getTeam("line" + scoreboardLineNumber); - - if (lineNumber < this.rows.size()) { - if (line == null) - line = scoreboard.registerNewTeam("line" + scoreboardLineNumber); - - final ScoreboardLine scoreboardLine = this.rows.get(lineNumber); - final Function replaceFunction = (lineText) -> this.replaceTheme( - this.replaceVariables(player, lineText.replace("{player}", player.getName()))); - final String[] createdLine = - scoreboardLine.createLine(COLOR_CHAR + colors[lineNumber] + COLOR_CHAR + "r", replaceFunction); - - final String prefix = createdLine[0]; - final String entry = createdLine[1]; - final String suffix = createdLine[2]; - String oldEntry = null; - - if (!line.getPrefix().equals(prefix)) - line.setPrefix(prefix); - - if (line.getEntries().size() > 1) - throw new IllegalArgumentException("There are more than allowed entries in the teams entry list!"); - - if (!line.getEntries().contains(entry)) { - if (!line.getEntries().isEmpty()) { - oldEntry = new ArrayList<>(line.getEntries()).get(0); - line.removeEntry(oldEntry); - } - - line.addEntry(entry); - } - - if (!line.getSuffix().equals(suffix)) - line.setSuffix(suffix); - - if (oldEntry != null) - scoreboard.resetScores(oldEntry); - - mainboard.getScore(entry).setScore(scoreboardLineNumber); - } else if (line != null) { - for (final String oldEntry : line.getEntries()) - scoreboard.resetScores(oldEntry); - - line.unregister(); - } - } - } - - // ------------------------------------------------------------------------------------------------------------ - // Classes - // ------------------------------------------------------------------------------------------------------------ - - private static class ScoreboardLine { - private String text; - - private ScoreboardLine(String text) { - this.text = text; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String[] createLine(String lineIdentifier, Function textReplaceFunction) { - String[] line = new String[3]; - - final String text = textReplaceFunction.apply(this.text); - final boolean mc1_13 = MinecraftVersion.atLeast(MinecraftVersion.V.v1_13); - final boolean mc1_18 = MinecraftVersion.atLeast(MinecraftVersion.V.v1_18); - final int[] splitPoints = mc1_13 ? new int[]{64, mc1_18 ? 32831 : 104} : new int[]{16, 56}; - final int length = mc1_18 ? 32895 : (mc1_13 ? 168 : 70); - final List copy = copyColors(text, length, splitPoints); - - line[0] = Common.colorize(copy.isEmpty() ? "" : copy.get(0)); //Team Prefix - line[1] = Common.colorize(copy.size() < 2 ? lineIdentifier : copy.get(1)); //Score entry - line[2] = Common.colorize(copy.size() < 3 ? "" : copy.get(2)); //Team Suffix - - return line; - } - - /** - * @param text The text containing the color codes - * @param maxLength The maximum length the text can have all added - * @param splitPoints The points to split the text - * @return The method will split the text at the given splitPoints and will copy the colors over - */ - private List copyColors(String text, int maxLength, int... splitPoints) { - if (maxLength < 1) - return new ArrayList<>(); - - List splitText = new ArrayList<>(); - int lastSplitPoint = 0; - - for (final int splitPoint : splitPoints) { - - if (splitPoint < 0) - throw new IllegalArgumentException("SplitPoints cannot be negative!"); - else if (splitPoint <= lastSplitPoint) - throw new IllegalArgumentException("Please put your splitPoints in order from small to large!"); - else if (splitPoint >= text.length() || splitPoint >= maxLength) - break; - - splitText.add(text.substring(lastSplitPoint, splitPoint)); - lastSplitPoint = splitPoint; - } - - if (text.length() > lastSplitPoint) - splitText.add(text.substring(lastSplitPoint, Math.min(text.length(), maxLength))); - - for (int index = 1; index < splitText.size(); index++) { - final int currentSplitPoint = splitPoints.length > index ? splitPoints[index] : maxLength; - final int previousSplitPoint = splitPoints.length > index - 1 ? splitPoints[index - 1] : 0; - final int maxSubStringLength = currentSplitPoint - previousSplitPoint; - final boolean lastLoop = index == splitText.size() - 1; - String previousText = splitText.get(index - 1); - final String currentText = splitText.get(index); - String fixedText = currentText; - String marge = null; - - if (previousText.endsWith(SimpleScoreboard.COLOR_CHAR)) { - previousText = previousText.substring(0, previousText.length() - 1); - fixedText = SimpleScoreboard.COLOR_CHAR + currentText; - - if (!lastLoop) { - marge = fixedText.substring(fixedText.length() - 1); - fixedText = fixedText.substring(0, fixedText.length() - 1); - } - } else if (!currentText.startsWith(SimpleScoreboard.COLOR_CHAR)) { - final String lastColor = ChatColor.getLastColors(previousText); - fixedText = lastColor + currentText; - - if (!lastLoop) { - marge = fixedText.substring(fixedText.length() - 2); - fixedText = fixedText.substring(0, fixedText.length() - 2); - } - } - - if (fixedText.length() > maxSubStringLength) { - marge = fixedText.substring(maxSubStringLength); - fixedText = fixedText.substring(0, maxSubStringLength); - } - - splitText.set(index - 1, previousText); - splitText.set(index, fixedText); - - List linesWithMarge = new ArrayList<>(); - - for (int j = index + 1; j < splitText.size(); j++) - linesWithMarge.add(splitText.get(j)); - - linesWithMarge = passMergeThrough(marge, linesWithMarge, maxLength); - - for (int j = 0; j < linesWithMarge.size(); j++) - splitText.set(index + 1 + j, linesWithMarge.get(j)); - } - - int stringLength = 0; - - for (final String line : splitText) - stringLength += line.length(); - - if (stringLength > maxLength) - splitText = passMergeThrough(null, splitText, maxLength); - - return splitText; - } - - private List passMergeThrough(String marge, List text, int maxLength) { - final StringBuilder textBuilder = new StringBuilder(marge == null ? "" : marge); - final List stringLengths = new ArrayList<>(); - final List newSplitText = new ArrayList<>(); - - for (final String line : text) { - stringLengths.add(line.length()); - textBuilder.append(line); - } + // ------------------------------------------------------------------------------------------------------------ + // Fields + // ------------------------------------------------------------------------------------------------------------ + + private static final String COLOR_CHAR = "\u00A7"; + + /** + * List of all active scoreboard (added upon creating a new instance) + */ + @Getter + private static final List registeredBoards = new ArrayList<>(); + + /** + * Unique chat color identifiers for specific team entries + */ + private static final String[] colors = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; + + /** + * Stored scoreboard lines + */ + private final List rows = new ArrayList<>(); + + /** + * Stored players viewing THIS scoreboard + */ + + private final List viewers = new ArrayList<>(); + + /** + * The color theme for key: value pairs such as + *

+ * Players: 12 + * Mode: playing + */ + private final String[] theme = new String[2]; + + /** + * The title of this scoreboard + */ + private String title; + + /** + * The update tick delay + */ + @Getter + private int updateDelayTicks = 20; + + /** + * The running update task + */ + private BukkitTask updateTask; + + /** + * Create a new scoreboard updating every second + */ + + public SimpleScoreboard() { + registeredBoards.add(this); + } + + public SimpleScoreboard(String title) { + this(title, 20); + } + + /** + * Create a new scoreboard with customizable updateDelayTicks + */ + public SimpleScoreboard(String title, int updateDelayTicks) { + //Scoreboards were introduced in 1.5, objectives were added in 1.7.2 + Valid.checkBoolean( + MinecraftVersion.atLeast(MinecraftVersion.V.v1_7), + "Scoreboards (with objectives) are not supported below Minecraft version 1.7!"); + + this.setTitle(title); + this.setUpdateDelayTicks(updateDelayTicks); + + registeredBoards.add(this); + } + + // ------------------------------------------------------------------------------------------------------------ + // Static + // ------------------------------------------------------------------------------------------------------------ + + /** + * Clears registered boards, usually called on reload + */ + public static void clearBoards() { + registeredBoards.clear(); + } + + /** + * Removes all scoreboard for a player + * + * @param player + */ + public static void clearBoardsFor(final Player player) { + for (final SimpleScoreboard scoreboard : registeredBoards) + if (scoreboard.isViewing(player)) + scoreboard.hide(player); + } + + // ------------------------------------------------------------------------------------------------------------ + // Public entries + // ------------------------------------------------------------------------------------------------------------ + + /** + * Replaces variables in the message for the given player + * + * @param player + * @param message + * @return + */ + protected String replaceVariables(final @NonNull Player player, final @NonNull String message) { + return message; + } + + /** + * Called when this scoreboard is ticked + */ + protected void onUpdate() { + } + + public final String getTitle() { + return this.title; + } + + /** + * @param title the title to set + */ + public final void setTitle(String title) { + final int maxTitleLength = MinecraftVersion.atLeast(MinecraftVersion.V.v1_13) ? 128 : 32; + final String colorizedTitle = Common.colorize(title); + this.title = colorizedTitle.length() > maxTitleLength ? colorizedTitle.substring(0, maxTitleLength) : colorizedTitle; + this.title = this.title.endsWith(COLOR_CHAR) ? this.title.substring(0, this.title.length() - 1) : this.title; + } + + public List getRows() { + return Common.convert(this.rows, ScoreboardLine::getText); + } + + /** + * Return true if the scoreboard is running and rendering? + * + * @return + */ + public final boolean isRunning() { + return this.updateTask != null; + } + + /** + * @param updateDelayTicks the updateDelayTicks to set + */ + public final void setUpdateDelayTicks(int updateDelayTicks) { + this.updateDelayTicks = updateDelayTicks; + } + + /** + * Show this scoreboard to the player + * + * @param player + */ + public final void show(final Player player) { + Valid.checkBoolean( + this.title != null && !this.title.isEmpty(), + "Before calling show(Player) you need to use setTitle() for " + this); + Valid.checkBoolean( + !this.isViewing(player), "Player " + player.getName() + " is already viewing scoreboard: " + this); + + if (this.updateTask == null) + this.start(); + + final Scoreboard scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + this.viewers.add(player.getUniqueId()); + player.setScoreboard(scoreboard); + } + + /** + * Hide this scoreboard from the player + * + * @param player + */ + public final void hide(final Player player) { + Valid.checkBoolean( + this.isViewing(player), + "Player " + player.getName() + " is not viewing scoreboard: " + this.getTitle()); + + player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); + this.viewers.remove(player.getUniqueId()); + + if (this.viewers.isEmpty()) + this.cancelUpdateTask(); + } + + /** + * Returns true if the given player is viewing THIS scoreboard + * + * @param player + * @return + */ + public final boolean isViewing(final Player player) { + return this.viewers.contains(player.getUniqueId()); + } + + /** + * Set the coloring theme for rows having : such as + *

+ * Players: 12 + * Mode: playing + *

+ * To use simply put color codes + * + * @param primary + * @param secondary + */ + public final void setTheme(@NonNull final ChatColor primary, final ChatColor secondary) { + if (secondary != null) { + this.theme[0] = "&" + primary.getChar(); + this.theme[1] = "&" + secondary.getChar(); + } else + this.theme[0] = "&" + primary.getChar(); + } + + // ------------------------------------------------------------------------------------------------------------ + // Add new rows + // ------------------------------------------------------------------------------------------------------------ + + /** + * Add rows onto the scoreboard + * + * @param entries + */ + public final void addRows(final Object... entries) { + this.addRows(Arrays.asList(entries)); + } + + /** + * Add rows onto the scoreboard + * + * @param entries + */ + public final void addRows(final List entries) { + Valid.checkBoolean( + (this.rows.size() + entries.size()) < 17, "You are trying to add too many rows (the limit is 16)"); + this.rows.addAll( + Common.convert(Common.colorize(Common.convert(entries, Object::toString)), ScoreboardLine::new)); + } + + public final void changeRow(final int index, Object value) { + Valid.checkBoolean( + index < this.rows.size(), + "The row for index " + index + " is currently not existing. Please use addRows()!"); + this.rows.get(index).setText(Common.colorize(value.toString())); + } + + /** + * Remove all rows + */ + public final void clearRows() { + this.rows.clear(); + } + + /** + * Remove row at the given index + * + * @param index + */ + public final void removeRow(final int index) { + this.rows.remove(index); + } + + /** + * Remove row that contains the given text + * + * @param thatContains + */ + public final void removeRow(final String thatContains) { + this.rows.removeIf(row -> row.getText().contains(thatContains)); + } + + // ------------------------------------------------------------------------------------------------------------ + // Start / stop + // ------------------------------------------------------------------------------------------------------------ + + /** + * Starts visualizing this scoreboard + */ + private void start() { + Valid.checkBoolean(this.updateTask == null, "Scoreboard " + this + " already running"); + + this.updateTask = Bukkit.getScheduler().runTaskTimer(SimplePlugin.getInstance(), () -> { + try { + this.onUpdate(); + + for (final UUID viewerId : new StrictList<>(this.viewers)) { + final Player viewer = Bukkit.getPlayer(viewerId); + + if (viewer == null || !viewer.isOnline()) { + this.viewers.remove(viewerId); + continue; + } + + this.reloadEntries(viewer); + } + + } catch (final Throwable t) { + final String lines = String.join(" ", this.getRows()); + + Common.error(t, "Error displaying " + this, "Entries: " + lines, "Title: " + this.title, "%error", + "Stopping rendering for safety."); + + this.stop(); + } + }, 0, this.updateDelayTicks); + } + + /** + * Stops this scoreboard and removes it from all viewers + */ + public final void stop() { + this.viewers.forEach(viewerId -> { + final Player viewer = Bukkit.getPlayer(viewerId); + + if (viewer != null && viewer.isOnline()) + viewer.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); + }); + + this.viewers.clear(); + + if (this.updateTask != null) + this.cancelUpdateTask(); + } + + @Override + public final String toString() { + return "Scoreboard{title=" + this.getTitle() + "}"; + } + + // ------------------------------------------------------------------------------------------------------------ + // Private + // ------------------------------------------------------------------------------------------------------------ + + /** + * Adds theme colors to the row if applicable + * + * @param row + * @return + */ + private String replaceTheme(final String row) { + if (row.contains(":")) + if (this.theme.length == 1) + return this.theme[0] + row; + + else if (this.theme[0] != null) { + final String[] split = row.split("\\:"); + + if (split.length > 1) + return this.theme[0] + split[0] + ":" + this.theme[1] + split[1]; + } + + return row; + } + + /** + * Cancels the update task + */ + private void cancelUpdateTask() { + Valid.checkNotNull(this.updateTask, "Scoreboard " + this + " not running"); + + this.updateTask.cancel(); + this.updateTask = null; + } + + // ------------------------------------------------------------------------------------------------------------ + // Rendering + // ------------------------------------------------------------------------------------------------------------ + + /** + * Reload entries for the given player + * + * @param player + */ + private void reloadEntries(Player player) throws IllegalArgumentException { + final int size = this.rows.size(); + final Scoreboard scoreboard = player.getScoreboard(); + Objective mainboard = scoreboard.getObjective("mainboard"); + + if (mainboard == null) { + mainboard = scoreboard.registerNewObjective("mainboard", "dummy"); + mainboard.setDisplayName(this.title); + mainboard.setDisplaySlot(DisplaySlot.SIDEBAR); + } + + if (!mainboard.getDisplayName().equals(this.title)) + mainboard.setDisplayName(this.title); + + for (int lineNumber = 0; lineNumber < 16; lineNumber++) { + final int scoreboardLineNumber = size - lineNumber; + Team line = scoreboard.getTeam("line" + scoreboardLineNumber); + + if (lineNumber < this.rows.size()) { + if (line == null) + line = scoreboard.registerNewTeam("line" + scoreboardLineNumber); + + final ScoreboardLine scoreboardLine = this.rows.get(lineNumber); + final Function replaceFunction = lineText -> this.replaceTheme( + this.replaceVariables(player, lineText.replace("{player}", player.getName()))); + final String[] createdLine = scoreboardLine.createLine(COLOR_CHAR + colors[lineNumber] + COLOR_CHAR + "r", replaceFunction); + + final String prefix = createdLine[0]; + final String entry = createdLine[1]; + final String suffix = createdLine[2]; + String oldEntry = null; + + if (!line.getPrefix().equals(prefix)) + line.setPrefix(prefix); + + if (line.getEntries().size() > 1) + throw new IllegalArgumentException("There are more than allowed entries in the teams entry list!"); + + if (!line.getEntries().contains(entry)) { + if (!line.getEntries().isEmpty()) { + oldEntry = new ArrayList<>(line.getEntries()).get(0); + line.removeEntry(oldEntry); + } + + line.addEntry(entry); + } + + if (!line.getSuffix().equals(suffix)) + line.setSuffix(suffix); + + if (oldEntry != null) + scoreboard.resetScores(oldEntry); + + mainboard.getScore(entry).setScore(scoreboardLineNumber); + } else if (line != null) { + for (final String oldEntry : line.getEntries()) + scoreboard.resetScores(oldEntry); + + line.unregister(); + } + } + } + + // ------------------------------------------------------------------------------------------------------------ + // Classes + // ------------------------------------------------------------------------------------------------------------ + + private static class ScoreboardLine { + private String text; + + private ScoreboardLine(String text) { + this.text = text; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + + public String[] createLine(String lineIdentifier, Function textReplaceFunction) { + final String[] line = new String[3]; + + final String text = textReplaceFunction.apply(this.text); + final boolean mc1_13 = MinecraftVersion.atLeast(MinecraftVersion.V.v1_13); + final boolean mc1_18 = MinecraftVersion.atLeast(MinecraftVersion.V.v1_18); + final int[] splitPoints = mc1_13 ? new int[] { 64, mc1_18 ? 32831 : 104 } : new int[] { 16, 56 }; + final int length = mc1_18 ? 32895 : (mc1_13 ? 168 : 70); + final List copy = this.copyColors(text, length, splitPoints); + + line[0] = Common.colorize(copy.isEmpty() ? "" : copy.get(0)); //Team Prefix + line[1] = Common.colorize(copy.size() < 2 ? lineIdentifier : copy.get(1)); //Score entry + line[2] = Common.colorize(copy.size() < 3 ? "" : copy.get(2)); //Team Suffix + + return line; + } + + /** + * @param text The text containing the color codes + * @param maxLength The maximum length the text can have all added + * @param splitPoints The points to split the text + * @return The method will split the text at the given splitPoints and will copy the colors over + */ + private List copyColors(String text, int maxLength, int... splitPoints) { + if (maxLength < 1) + return new ArrayList<>(); + + List splitText = new ArrayList<>(); + int lastSplitPoint = 0; + + for (final int splitPoint : splitPoints) { + + if (splitPoint < 0) + throw new IllegalArgumentException("SplitPoints cannot be negative!"); + else if (splitPoint <= lastSplitPoint) + throw new IllegalArgumentException("Please put your splitPoints in order from small to large!"); + else if (splitPoint >= text.length() || splitPoint >= maxLength) + break; + + splitText.add(text.substring(lastSplitPoint, splitPoint)); + lastSplitPoint = splitPoint; + } + + if (text.length() > lastSplitPoint) + splitText.add(text.substring(lastSplitPoint, Math.min(text.length(), maxLength))); + + for (int index = 1; index < splitText.size(); index++) { + final int currentSplitPoint = splitPoints.length > index ? splitPoints[index] : maxLength; + final int previousSplitPoint = splitPoints.length > index - 1 ? splitPoints[index - 1] : 0; + final int maxSubStringLength = currentSplitPoint - previousSplitPoint; + final boolean lastLoop = index == splitText.size() - 1; + String previousText = splitText.get(index - 1); + final String currentText = splitText.get(index); + String fixedText = currentText; + String marge = null; + + if (previousText.endsWith(SimpleScoreboard.COLOR_CHAR)) { + previousText = previousText.substring(0, previousText.length() - 1); + fixedText = SimpleScoreboard.COLOR_CHAR + currentText; + + if (!lastLoop) { + marge = fixedText.substring(fixedText.length() - 1); + fixedText = fixedText.substring(0, fixedText.length() - 1); + } + } else if (!currentText.startsWith(SimpleScoreboard.COLOR_CHAR)) { + final String lastColor = ChatColor.getLastColors(previousText); + fixedText = lastColor + currentText; + + if (!lastLoop) { + marge = fixedText.substring(fixedText.length() - 2); + fixedText = fixedText.substring(0, fixedText.length() - 2); + } + } + + if (fixedText.length() > maxSubStringLength) { + marge = fixedText.substring(maxSubStringLength); + fixedText = fixedText.substring(0, maxSubStringLength); + } + + splitText.set(index - 1, previousText); + splitText.set(index, fixedText); + + List linesWithMarge = new ArrayList<>(); + + for (int j = index + 1; j < splitText.size(); j++) + linesWithMarge.add(splitText.get(j)); + + linesWithMarge = this.passMergeThrough(marge, linesWithMarge, maxLength); + + for (int j = 0; j < linesWithMarge.size(); j++) + splitText.set(index + 1 + j, linesWithMarge.get(j)); + } + + int stringLength = 0; + + for (final String line : splitText) + stringLength += line.length(); + + if (stringLength > maxLength) + splitText = this.passMergeThrough(null, splitText, maxLength); + + return splitText; + } + + private List passMergeThrough(String marge, List text, int maxLength) { + final StringBuilder textBuilder = new StringBuilder(marge == null ? "" : marge); + final List stringLengths = new ArrayList<>(); + final List newSplitText = new ArrayList<>(); + + for (final String line : text) { + stringLengths.add(line.length()); + textBuilder.append(line); + } - String textWithMarge = textBuilder.toString(); - textWithMarge = textWithMarge.substring(0, Math.min(maxLength, textWithMarge.length())); - int previousLength = 0; - - for (int index = 0; index < stringLengths.size(); index++) { - int length = stringLengths.get(index); - - if (index == stringLengths.size() - 1) - length = Math.max(length, maxLength); + String textWithMarge = textBuilder.toString(); + textWithMarge = textWithMarge.substring(0, Math.min(maxLength, textWithMarge.length())); + int previousLength = 0; + + for (int index = 0; index < stringLengths.size(); index++) { + int length = stringLengths.get(index); + + if (index == stringLengths.size() - 1) + length = Math.max(length, maxLength); - final String subString = textWithMarge.substring(previousLength, - Math.min(textWithMarge.length(), previousLength + length)); + final String subString = textWithMarge.substring(previousLength, + Math.min(textWithMarge.length(), previousLength + length)); - if (!subString.isEmpty()) - newSplitText.add(subString); + if (!subString.isEmpty()) + newSplitText.add(subString); - previousLength += length; - } - - return newSplitText; - } - } + previousLength += length; + } + + return newSplitText; + } + } } \ No newline at end of file diff --git a/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java b/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java index 751b8e802..097aa2b91 100644 --- a/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java +++ b/src/main/java/org/mineacademy/fo/plugin/AutoRegisterScanner.java @@ -204,12 +204,11 @@ else if (name.matches("localization\\/messages\\_(.*)\\.yml")) // A dirty solution to prioritize loading settings and then localization final List> delayedLoading = new ArrayList<>(); - for (final Class customSettings : staticCustom) { + for (final Class customSettings : staticCustom) if (SimpleSettings.class.isAssignableFrom(customSettings)) YamlStaticConfig.load((Class) customSettings); else delayedLoading.add(customSettings); - } for (final Class delayedSettings : delayedLoading) YamlStaticConfig.load((Class) delayedSettings); @@ -247,7 +246,7 @@ private static void autoRegister(Class clazz, boolean printWarnings) { if (printWarnings) { Bukkit.getLogger().warning("**** WARNING ****"); Bukkit.getLogger().warning("SimpleEnchantment requires Minecraft 1.13.2 or greater. The following class will not be registered: " + clazz.getName() - + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); + + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); } return; @@ -257,7 +256,7 @@ private static void autoRegister(Class clazz, boolean printWarnings) { if (printWarnings) { Bukkit.getLogger().warning("**** WARNING ****"); Bukkit.getLogger().warning("The following class requires DiscordSRV and won't be registered: " + clazz.getName() - + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); + + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); } return; @@ -267,7 +266,7 @@ private static void autoRegister(Class clazz, boolean printWarnings) { if (printWarnings && !clazz.equals(EnchantmentPacketListener.class)) { Bukkit.getLogger().warning("**** WARNING ****"); Bukkit.getLogger().warning("The following class requires ProtocolLib and won't be registered: " + clazz.getName() - + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); + + ". To hide this message, put @AutoRegister(hideIncompatibilityWarnings=true) over the class."); } return; @@ -301,10 +300,8 @@ else if (BungeeListener.class.isAssignableFrom(clazz)) { eventsRegistered = true; } - else if (SimpleCommand.class.isAssignableFrom(clazz)) { + else if (SimpleCommand.class.isAssignableFrom(clazz)) plugin.registerCommand((SimpleCommand) instance); - } - else if (SimpleCommandGroup.class.isAssignableFrom(clazz)) { final SimpleCommandGroup group = (SimpleCommandGroup) instance; @@ -337,12 +334,9 @@ else if (PacketListener.class.isAssignableFrom(clazz)) { ((PacketListener) instance).onRegister(); } - else if (DiscordListener.class.isAssignableFrom(clazz)) { - + else if (DiscordListener.class.isAssignableFrom(clazz)) // Automatically registered in its constructor enforceModeFor(clazz, mode, FindInstance.SINGLETON); - } - else if (SimpleEnchantment.class.isAssignableFrom(clazz)) { // Automatically registered in its constructor @@ -357,12 +351,9 @@ else if (SimpleEnchantment.class.isAssignableFrom(clazz)) { enchantListenersRegistered = true; } - else if (Tool.class.isAssignableFrom(clazz)) { - + else if (Tool.class.isAssignableFrom(clazz)) // Automatically registered in its constructor enforceModeFor(clazz, mode, FindInstance.SINGLETON); - } - else if (instance instanceof Listener) { // Pass-through to register events later } diff --git a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java index a094c7305..24e376853 100644 --- a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java +++ b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java @@ -32,7 +32,6 @@ import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.Messenger; -import org.mineacademy.fo.BungeeUtil; import org.mineacademy.fo.Common; import org.mineacademy.fo.FileUtil; import org.mineacademy.fo.MinecraftVersion; @@ -223,7 +222,7 @@ public final void onLoad() { final String version = Bukkit.getVersion(); - if (suggestPaper() && !version.contains("Paper") + if (this.suggestPaper() && !version.contains("Paper") && !version.contains("Purpur") && !version.contains("NachoSpigot") && !version.contains("-Spigot") @@ -440,19 +439,19 @@ private void loadLibraries() { else methodLibraryLoader: - for (final Library library : manualLibraries) { + for (final Library library : manualLibraries) { - // Detect conflicts - for (final Library otherLibrary : libraries) - if (library.getArtifactId().equals(otherLibrary.getArtifactId()) && library.getGroupId().equals(otherLibrary.getGroupId())) { - Common.warning("Detected library conflict: '" + library.getGroupId() + "." + library.getArtifactId() + "' is defined both in getLibraries() and plugin.yml! " - + "We'll prefer the version from plugin.yml, if you want to use the one from getLibraries() then remove it from your plugin.yml file."); + // Detect conflicts + for (final Library otherLibrary : libraries) + if (library.getArtifactId().equals(otherLibrary.getArtifactId()) && library.getGroupId().equals(otherLibrary.getGroupId())) { + Common.warning("Detected library conflict: '" + library.getGroupId() + "." + library.getArtifactId() + "' is defined both in getLibraries() and plugin.yml! " + + "We'll prefer the version from plugin.yml, if you want to use the one from getLibraries() then remove it from your plugin.yml file."); - continue methodLibraryLoader; - } + continue methodLibraryLoader; + } - library.load(); - } + library.load(); + } } /** @@ -893,21 +892,21 @@ protected final void registerAllEvents(final Class exten Valid.checkBoolean(!extendingClass.equals(SimpleListener.class), "registerAllEvents does not support SimpleListener.class due to conflicts, create your own middle class instead"); classLookup: - for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { + for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { - // AutoRegister means the class is already being registered - if (pluginClass.isAnnotationPresent(AutoRegister.class)) - continue; + // AutoRegister means the class is already being registered + if (pluginClass.isAnnotationPresent(AutoRegister.class)) + continue; - for (final Constructor con : pluginClass.getConstructors()) - if (con.getParameterCount() == 0) { - final T instance = (T) ReflectionUtil.instantiate(con); + for (final Constructor con : pluginClass.getConstructors()) + if (con.getParameterCount() == 0) { + final T instance = (T) ReflectionUtil.instantiate(con); - this.registerEvents(instance); + this.registerEvents(instance); - continue classLookup; - } - } + continue classLookup; + } + } } /** @@ -954,33 +953,33 @@ protected final void registerAllCommands(final Class exte Valid.checkBoolean(!extendingClass.equals(SimpleSubCommand.class), "registerAllCommands does not support SubCommand.class"); classLookup: - for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { + for (final Class pluginClass : ReflectionUtil.getClasses(instance, extendingClass)) { - // AutoRegister means the class is already being registered - if (pluginClass.isAnnotationPresent(AutoRegister.class)) - continue; + // AutoRegister means the class is already being registered + if (pluginClass.isAnnotationPresent(AutoRegister.class)) + continue; - if (SimpleSubCommand.class.isAssignableFrom(pluginClass)) - continue; + if (SimpleSubCommand.class.isAssignableFrom(pluginClass)) + continue; - try { - for (final Constructor con : pluginClass.getConstructors()) - if (con.getParameterCount() == 0) { - final T instance = (T) ReflectionUtil.instantiate(con); + try { + for (final Constructor con : pluginClass.getConstructors()) + if (con.getParameterCount() == 0) { + final T instance = (T) ReflectionUtil.instantiate(con); - if (instance instanceof SimpleCommand) - this.registerCommand(instance); + if (instance instanceof SimpleCommand) + this.registerCommand(instance); - else - this.registerCommand(instance); + else + this.registerCommand(instance); - continue classLookup; - } + continue classLookup; + } - } catch (final LinkageError ex) { - Common.log("Unable to register commands in '" + pluginClass.getSimpleName() + "' due to error: " + ex); - } + } catch (final LinkageError ex) { + Common.log("Unable to register commands in '" + pluginClass.getSimpleName() + "' due to error: " + ex); } + } } /** diff --git a/src/main/java/org/mineacademy/fo/remain/CompSound.java b/src/main/java/org/mineacademy/fo/remain/CompSound.java index 1faacd925..b63cb81c4 100644 --- a/src/main/java/org/mineacademy/fo/remain/CompSound.java +++ b/src/main/java/org/mineacademy/fo/remain/CompSound.java @@ -1621,7 +1621,7 @@ public enum CompSound { * @param location the location to play the sound in. */ public void play(Location location) { - play(location, DEFAULT_VOLUME, DEFAULT_PITCH); + this.play(location, DEFAULT_VOLUME, DEFAULT_PITCH); } /** @@ -1632,7 +1632,7 @@ public void play(Location location) { * @since 1.0.0 */ public void play(Entity entity) { - play(entity, DEFAULT_VOLUME, DEFAULT_PITCH); + this.play(entity, DEFAULT_VOLUME, DEFAULT_PITCH); } /** @@ -1664,7 +1664,7 @@ public void play(@NonNull Entity entity, float volume, float pitch) { ((Player) entity).playSound(entity.getLocation(), sound, volume, pitch); } else - play(entity.getLocation(), volume, pitch); + this.play(entity.getLocation(), volume, pitch); } @@ -1692,9 +1692,9 @@ public BukkitTask playRepeatedly(@NonNull Entity entity, float volume, float pit @Override public void run() { - play(entity.getLocation(), volume, pitch); - if (repeating-- == 0) - cancel(); + CompSound.this.play(entity.getLocation(), volume, pitch); + if (this.repeating-- == 0) + this.cancel(); } }.runTaskTimer(SimplePlugin.getInstance(), 0, delay); } @@ -1734,7 +1734,7 @@ public Sound getSound() { */ @Override public String toString() { - return Arrays.stream(name().split("_")) + return Arrays.stream(this.name().split("_")) .map(t -> t.charAt(0) + t.substring(1).toLowerCase()) .collect(Collectors.joining(" ")); } @@ -1856,10 +1856,10 @@ public static BukkitTask playAscendingNote(@NonNull Player player, @NonNull Enti @Override public void run() { - player.playNote(playTo.getLocation(), instrument, Note.natural(1, Note.Tone.values()[ascendLevel - repeating])); + player.playNote(playTo.getLocation(), instrument, Note.natural(1, Note.Tone.values()[ascendLevel - this.repeating])); - if (repeating-- == 0) - cancel(); + if (this.repeating-- == 0) + this.cancel(); } }.runTaskTimerAsynchronously(SimplePlugin.getInstance(), 0, delay); } diff --git a/src/main/java/org/mineacademy/fo/remain/Remain.java b/src/main/java/org/mineacademy/fo/remain/Remain.java index 9effd0e88..b29807e01 100644 --- a/src/main/java/org/mineacademy/fo/remain/Remain.java +++ b/src/main/java/org/mineacademy/fo/remain/Remain.java @@ -43,7 +43,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.command.SimpleCommandMap; -import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; @@ -68,7 +67,6 @@ import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Score; import org.mineacademy.fo.Common; -import org.mineacademy.fo.EntityUtil; import org.mineacademy.fo.FileUtil; import org.mineacademy.fo.ItemUtil; import org.mineacademy.fo.MathUtil; @@ -345,7 +343,7 @@ private Remain() { "&cYour server version (&f" + Bukkit.getBukkitVersion().replace("-SNAPSHOT", "") + "&c) doesn't\n" + " &cinclude &elibraries required&c for this plugin to\n" + " &crun. Install the following plugin for compatibility:\n" + - " &fhttps://mineacademy.org/plugins/#misc"); + " &fhttps://mineacademy.org/plugins/#misc"); } try { @@ -2597,7 +2595,7 @@ public static void injectServerName() { boolean hasServerName = false; String oldName = null; - for (String line : lines) + for (final String line : lines) if (line.startsWith("server-name=")) { hasServerName = true; @@ -2614,7 +2612,7 @@ public static void injectServerName() { serverName = oldName; - } catch (Throwable t) { + } catch (final Throwable t) { t.printStackTrace(); } } diff --git a/src/main/java/org/mineacademy/fo/remain/nbt/NBTItem.java b/src/main/java/org/mineacademy/fo/remain/nbt/NBTItem.java index b021b85b7..29c21565c 100644 --- a/src/main/java/org/mineacademy/fo/remain/nbt/NBTItem.java +++ b/src/main/java/org/mineacademy/fo/remain/nbt/NBTItem.java @@ -14,7 +14,7 @@ public class NBTItem extends NBTCompound { private ItemStack bukkitItem; - private boolean directApply; + private final boolean directApply; private ItemStack originalSrcStack = null; /** diff --git a/src/main/java/org/mineacademy/fo/remain/nbt/NBTList.java b/src/main/java/org/mineacademy/fo/remain/nbt/NBTList.java index a8aa4eee9..49920a9d7 100644 --- a/src/main/java/org/mineacademy/fo/remain/nbt/NBTList.java +++ b/src/main/java/org/mineacademy/fo/remain/nbt/NBTList.java @@ -19,9 +19,9 @@ */ public abstract class NBTList implements List { - private String listName; - private NBTCompound parent; - private NBTType type; + private final String listName; + private final NBTCompound parent; + private final NBTType type; protected Object listObject; protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { diff --git a/src/main/java/org/mineacademy/fo/remain/nbt/NBTListCompound.java b/src/main/java/org/mineacademy/fo/remain/nbt/NBTListCompound.java index c4ae2617a..40385b5b6 100644 --- a/src/main/java/org/mineacademy/fo/remain/nbt/NBTListCompound.java +++ b/src/main/java/org/mineacademy/fo/remain/nbt/NBTListCompound.java @@ -11,7 +11,7 @@ */ public class NBTListCompound extends NBTCompound { - private NBTList owner; + private final NBTList owner; private Object compound; protected NBTListCompound(NBTList parent, Object obj) { diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index 906e0d9cc..62f22b032 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -35,8 +35,6 @@ import org.mineacademy.fo.Valid; import org.mineacademy.fo.collection.SerializedMap; import org.mineacademy.fo.collection.StrictList; -import org.mineacademy.fo.command.SimpleCommand; -import org.mineacademy.fo.command.SimpleCommandGroup; import org.mineacademy.fo.exception.FoException; import org.mineacademy.fo.model.BoxedMessage; import org.mineacademy.fo.model.ConfigSerializable; @@ -1279,11 +1277,10 @@ public final void save(@NonNull File file) { try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) { writer.write(data); - } catch (Exception ex) { + } catch (final Exception ex) { Remain.sneaky(ex); } - // Update file this.file = file; } From fcbfd8f53f551c76d03efaf6acabfb6a6916b521 Mon Sep 17 00:00:00 2001 From: kangarko Date: Wed, 17 Aug 2022 16:48:26 +0200 Subject: [PATCH 19/30] Improve domain filter by ElBananaa See https://github.com/ElBananaa/Foundation/commit/ddb8c198d15555bdbe53c3b8b347ea72f9bbe2ff for discussion --- src/main/java/org/mineacademy/fo/model/SimpleComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java index 19457f611..64dcae5a1 100644 --- a/src/main/java/org/mineacademy/fo/model/SimpleComponent.java +++ b/src/main/java/org/mineacademy/fo/model/SimpleComponent.java @@ -40,7 +40,7 @@ public final class SimpleComponent implements ConfigSerializable { /** * The pattern to match URL addresses when parsing text */ - private static final Pattern URL_PATTERN = Pattern.compile("^(https?:\\/\\/|)(www\\.|)[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,8}\\b(?:[a-zA-Z:,.\\?\\!\\/0-9]*)$"); + private static final Pattern URL_PATTERN = Pattern.compile("^(https?:\\/\\/|)(www\\.|)[\\w-:.\\d]{1,256}\\.[\\w()]{1,12}\\b([\\w-@:%.,+~#=?!&$/\\d]*)$"); /** * The past components From 1cfb1eeff4500e0b093881a3dc1664f46521da7d Mon Sep 17 00:00:00 2001 From: kangarko Date: Thu, 18 Aug 2022 16:09:44 +0200 Subject: [PATCH 20/30] Fix armor stand visible when creating animation by @CoobMC --- .../fo/model/SimpleHologramStand.java | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/model/SimpleHologramStand.java b/src/main/java/org/mineacademy/fo/model/SimpleHologramStand.java index c941d6ac6..34e72bfe5 100644 --- a/src/main/java/org/mineacademy/fo/model/SimpleHologramStand.java +++ b/src/main/java/org/mineacademy/fo/model/SimpleHologramStand.java @@ -3,6 +3,8 @@ import org.bukkit.Location; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Consumer; import org.mineacademy.fo.menu.model.ItemCreator; import org.mineacademy.fo.remain.CompMaterial; @@ -15,9 +17,9 @@ public class SimpleHologramStand extends SimpleHologram { /** - * The material this hologram will have + * The item or material this hologram will have */ - private final CompMaterial material; + private final Object itemOrMaterial; /** * Is this item stand small? @@ -29,16 +31,28 @@ public class SimpleHologramStand extends SimpleHologram { */ private boolean glowing; + /** + * Create a new simple hologram using armor stand showing the given itemstack + * + * @param spawnLocation + * @param item + */ + public SimpleHologramStand(final Location spawnLocation, final ItemStack item) { + super(spawnLocation); + + this.itemOrMaterial = item; + } + /** * Create a new simple hologram using armor stand showing the given material * * @param spawnLocation * @param material */ - public SimpleHologramStand(Location spawnLocation, CompMaterial material) { + public SimpleHologramStand(final Location spawnLocation, final CompMaterial material) { super(spawnLocation); - this.material = material; + this.itemOrMaterial = material; } /** @@ -46,22 +60,29 @@ public SimpleHologramStand(Location spawnLocation, CompMaterial material) { */ @Override protected final Entity createEntity() { - final ArmorStand armorStand = this.getLastTeleportLocation().getWorld().spawn(this.getLastTeleportLocation(), ArmorStand.class); - armorStand.setGravity(false); - armorStand.setHelmet(ItemCreator.of(this.material).glow(this.glowing).make()); - armorStand.setVisible(false); - armorStand.setSmall(this.small); + final ItemCreator item; + + if (this.itemOrMaterial instanceof ItemStack) + item = ItemCreator.of((ItemStack) this.itemOrMaterial); + else + item = ItemCreator.of((CompMaterial) this.itemOrMaterial); - return armorStand; + final Consumer consumer = armorStand -> { + armorStand.setGravity(false); + armorStand.setHelmet(item.glow(this.glowing).make()); + armorStand.setVisible(false); + armorStand.setSmall(this.small); + }; + + return getLastTeleportLocation().getWorld().spawn(getLastTeleportLocation(), ArmorStand.class, consumer); } /** - * * @param glowing * @return */ - public final SimpleHologram setGlowing(boolean glowing) { + public final SimpleHologram setGlowing(final boolean glowing) { this.glowing = glowing; return this; @@ -71,9 +92,9 @@ public final SimpleHologram setGlowing(boolean glowing) { * @param small the small to set * @return */ - public final SimpleHologram setSmall(boolean small) { + public final SimpleHologram setSmall(final boolean small) { this.small = small; return this; } -} +} \ No newline at end of file From 9bfda01ef6b30685ff1ddfe67c99da984367a6de Mon Sep 17 00:00:00 2001 From: Bananaa Date: Fri, 19 Aug 2022 03:26:35 +0200 Subject: [PATCH 21/30] Get the full server version (with build number) --- src/main/java/org/mineacademy/fo/command/DebugCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/command/DebugCommand.java b/src/main/java/org/mineacademy/fo/command/DebugCommand.java index fda76e5b1..ad8512a0c 100644 --- a/src/main/java/org/mineacademy/fo/command/DebugCommand.java +++ b/src/main/java/org/mineacademy/fo/command/DebugCommand.java @@ -81,7 +81,7 @@ private void writeDebugInformation() { " Debug log generated " + TimeUtil.getFormattedDate(), Common.consoleLine(), "Plugin: " + SimplePlugin.getInstance().getDescription().getFullName(), - "Server Version: " + Bukkit.getName() + " " + MinecraftVersion.getServerVersion(), + "Server Version: " + Bukkit.getVersion(), "Java: " + System.getProperty("java.version") + " (" + System.getProperty("java.specification.vendor") + "/" + System.getProperty("java.vm.vendor") + ")", "OS: " + System.getProperty("os.name") + " " + System.getProperty("os.version"), "Online mode: " + Bukkit.getOnlineMode(), From 0e5295be6527591f191a49093d9f7fc68b2ab86e Mon Sep 17 00:00:00 2001 From: kangarko Date: Sat, 20 Aug 2022 18:58:11 +0200 Subject: [PATCH 22/30] Test --- src/main/java/org/mineacademy/fo/BlockUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/mineacademy/fo/BlockUtil.java b/src/main/java/org/mineacademy/fo/BlockUtil.java index 40de10443..2f21ffff3 100644 --- a/src/main/java/org/mineacademy/fo/BlockUtil.java +++ b/src/main/java/org/mineacademy/fo/BlockUtil.java @@ -35,6 +35,7 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class BlockUtil { + // TEst /** * Matches all DOUBLE or STEP block names */ From b0c6511d70918c762f9cc029a35b1e4882f82e86 Mon Sep 17 00:00:00 2001 From: kangarko Date: Sat, 20 Aug 2022 18:58:43 +0200 Subject: [PATCH 23/30] Remove test comment --- src/main/java/org/mineacademy/fo/BlockUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/mineacademy/fo/BlockUtil.java b/src/main/java/org/mineacademy/fo/BlockUtil.java index 2f21ffff3..40de10443 100644 --- a/src/main/java/org/mineacademy/fo/BlockUtil.java +++ b/src/main/java/org/mineacademy/fo/BlockUtil.java @@ -35,7 +35,6 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class BlockUtil { - // TEst /** * Matches all DOUBLE or STEP block names */ From 2b1c3b9b0fca12b02bdbc42ba8274f24dcc12cf8 Mon Sep 17 00:00:00 2001 From: kangarko Date: Sun, 21 Aug 2022 14:53:14 +0200 Subject: [PATCH 24/30] More compatible for Foundation 5 upgrading --- .../java/org/mineacademy/fo/PacketUtil.java | 13 ++++++ .../mineacademy/fo/bungee/BungeeAction.java | 10 +++++ .../mineacademy/fo/bungee/SimpleBungee.java | 13 ++++++ .../mineacademy/fo/command/DebugCommand.java | 1 - .../fo/constants/FoPermissions.java | 9 ++++ .../java/org/mineacademy/fo/menu/Menu.java | 16 ++++++++ .../mineacademy/fo/menu/MenuQuantitable.java | 24 +++++++++++ .../fo/menu/model/ItemCreator.java | 41 +++++++++++++++++++ .../fo/menu/model/MenuQuantity.java | 11 +++++ .../org/mineacademy/fo/model/ChunkedTask.java | 9 ++++ .../mineacademy/fo/plugin/SimplePlugin.java | 2 +- .../mineacademy/fo/settings/FileConfig.java | 35 +++++++++++----- .../fo/settings/YamlSectionConfig.java | 8 ++++ .../fo/settings/YamlStaticConfig.java | 9 ++++ .../fo/visual/VisualizedRegion.java | 10 +++++ 15 files changed, 199 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/mineacademy/fo/PacketUtil.java create mode 100644 src/main/java/org/mineacademy/fo/bungee/BungeeAction.java create mode 100644 src/main/java/org/mineacademy/fo/bungee/SimpleBungee.java create mode 100644 src/main/java/org/mineacademy/fo/constants/FoPermissions.java create mode 100644 src/main/java/org/mineacademy/fo/settings/YamlSectionConfig.java diff --git a/src/main/java/org/mineacademy/fo/PacketUtil.java b/src/main/java/org/mineacademy/fo/PacketUtil.java new file mode 100644 index 000000000..9031cd764 --- /dev/null +++ b/src/main/java/org/mineacademy/fo/PacketUtil.java @@ -0,0 +1,13 @@ +package org.mineacademy.fo; + +/** + * @deprecated make your class final and extend {@link PacketAdapter} instead, + * and place \@AutoRegister annotation over your class + * @author kangarko + * + */ +@Deprecated +public final class PacketUtil { + + // Empty +} diff --git a/src/main/java/org/mineacademy/fo/bungee/BungeeAction.java b/src/main/java/org/mineacademy/fo/bungee/BungeeAction.java new file mode 100644 index 000000000..914ab7d2a --- /dev/null +++ b/src/main/java/org/mineacademy/fo/bungee/BungeeAction.java @@ -0,0 +1,10 @@ +package org.mineacademy.fo.bungee; + +/** + * @deprecated renamed, use {@link BungeeMessageType} instead + * + */ +@Deprecated +public interface BungeeAction { + // Renamed +} diff --git a/src/main/java/org/mineacademy/fo/bungee/SimpleBungee.java b/src/main/java/org/mineacademy/fo/bungee/SimpleBungee.java new file mode 100644 index 000000000..f2477a31f --- /dev/null +++ b/src/main/java/org/mineacademy/fo/bungee/SimpleBungee.java @@ -0,0 +1,13 @@ +package org.mineacademy.fo.bungee; + +/** + * @deprecated no longer used. Simply remove your line: + * "private final SimpleBungee bungeeCord = new SimpleBungee" + * from your main plugin's class, and place \@AutoRegister over your + * class extending {@link BungeeListener} and put channel name and + * packet/messages types into its constructor instead. + */ +@Deprecated +public final class SimpleBungee { + // Moved +} diff --git a/src/main/java/org/mineacademy/fo/command/DebugCommand.java b/src/main/java/org/mineacademy/fo/command/DebugCommand.java index ad8512a0c..7611cf41b 100644 --- a/src/main/java/org/mineacademy/fo/command/DebugCommand.java +++ b/src/main/java/org/mineacademy/fo/command/DebugCommand.java @@ -11,7 +11,6 @@ import org.bukkit.Bukkit; import org.mineacademy.fo.Common; import org.mineacademy.fo.FileUtil; -import org.mineacademy.fo.MinecraftVersion; import org.mineacademy.fo.TimeUtil; import org.mineacademy.fo.plugin.SimplePlugin; import org.mineacademy.fo.remain.Remain; diff --git a/src/main/java/org/mineacademy/fo/constants/FoPermissions.java b/src/main/java/org/mineacademy/fo/constants/FoPermissions.java new file mode 100644 index 000000000..7a9832592 --- /dev/null +++ b/src/main/java/org/mineacademy/fo/constants/FoPermissions.java @@ -0,0 +1,9 @@ +package org.mineacademy.fo.constants; + +/** + * @deprecated unused now, you simply do not need to extend your class by this class + */ +@Deprecated +public class FoPermissions { + +} diff --git a/src/main/java/org/mineacademy/fo/menu/Menu.java b/src/main/java/org/mineacademy/fo/menu/Menu.java index 97e7f2ccd..6e6aa653d 100644 --- a/src/main/java/org/mineacademy/fo/menu/Menu.java +++ b/src/main/java/org/mineacademy/fo/menu/Menu.java @@ -838,6 +838,22 @@ protected final int getBottomCenterSlot() { * by default */ protected boolean isActionAllowed(final MenuClickLocation location, final int slot, @Nullable final ItemStack clicked, @Nullable final ItemStack cursor, InventoryAction action) { + return this.isActionAllowed(location, slot, clicked, cursor); + } + + /** + * Should we prevent the click or drag? + * + * @param location the click location + * @param slot the slot + * @param clicked the clicked item + * @param cursor the cursor + * @param action the inventory action + * + * @return if the action is cancelled in the {@link InventoryClickEvent}, false + * by default + */ + protected boolean isActionAllowed(final MenuClickLocation location, final int slot, @Nullable final ItemStack clicked, @Nullable final ItemStack cursor) { return false; } diff --git a/src/main/java/org/mineacademy/fo/menu/MenuQuantitable.java b/src/main/java/org/mineacademy/fo/menu/MenuQuantitable.java index eb4331acc..b5bfd4d64 100644 --- a/src/main/java/org/mineacademy/fo/menu/MenuQuantitable.java +++ b/src/main/java/org/mineacademy/fo/menu/MenuQuantitable.java @@ -59,6 +59,18 @@ default String getCurrentQuantityPercent() { return (this.allowDecimalQuantities() ? MathUtil.formatTwoDigits(percent) : String.valueOf((int) percent)) + (this.quantitiesArePercents() ? "%" : ""); } + /** + * @deprecated rounds the amount number, you need to decide if you will support + * decimal quantities and use either {@link #getAmountDouble()} or if not, use {@link #getAmountPercent()} + * + * @param clickType + * @return + */ + @Deprecated + default int getNextQuantity(ClickType clickType) { + return (int) Math.round(this.getNextQuantityPercent(clickType)); + } + /** * Get the next edit quantity from click from 0.0 to 1.0 * @@ -79,6 +91,18 @@ default double getNextQuantityPercent(ClickType clickType) { return clickType == ClickType.LEFT ? -this.getQuantity().getAmountPercent() : this.getQuantity().getAmountPercent(); } + /** + * @see #getQuantityButton(Menu) + * @deprecated renamed to {@link #getQuantityButton(Menu)} + * + * @param menu + * @return + */ + @Deprecated + default Button getEditQuantityButton(Menu menu) { + return this.getQuantityButton(menu); + } + /** * Get the button that is responsible for setting the quantity edit * Implemented by default. diff --git a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java index c84e77741..3a6f485fa 100644 --- a/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java +++ b/src/main/java/org/mineacademy/fo/menu/model/ItemCreator.java @@ -29,6 +29,7 @@ import org.mineacademy.fo.MinecraftVersion.V; import org.mineacademy.fo.ReflectionUtil; import org.mineacademy.fo.Valid; +import org.mineacademy.fo.model.SimpleEnchant; import org.mineacademy.fo.model.SimpleEnchantment; import org.mineacademy.fo.remain.CompColor; import org.mineacademy.fo.remain.CompItemFlag; @@ -282,6 +283,16 @@ public ItemCreator lore(List lore) { return this; } + /** + * Add the given enchant to the item. + * + * @param enchant + * @return + */ + public ItemCreator enchant(SimpleEnchant enchant) { + return this.enchant(enchant.getEnchant(), enchant.getLevel()); + } + /** * Add the given enchant to the item. * @@ -305,6 +316,17 @@ public ItemCreator enchant(Enchantment enchantment, int level) { return this; } + /** + * @see #flags(CompItemFlag...) + * @deprecated call {@link #flags(CompItemFlag...)} instead + * @param flags + * @return + */ + @Deprecated + public ItemCreator flag(CompItemFlag... flags) { + return this.flags(flags); + } + /** * Add the given flags to the item. * @@ -489,6 +511,25 @@ public void give(final Player player) { // Constructing items // ---------------------------------------------------------------------------------------- + /** + * @deprecated no longer needed, will simply return itself. Instead of calling "built().make()", now simple call "make()" + * @return + */ + @Deprecated + public ItemCreator build() { + return this; + } + + /** + * + * @deprecated simply returns {@link #make()} now, call that instead + * @return + */ + @Deprecated + public ItemStack makeSurvival() { + return this.make(); + } + /** * Make an unbreakable item with all attributes hidden, suitable for menu use. * diff --git a/src/main/java/org/mineacademy/fo/menu/model/MenuQuantity.java b/src/main/java/org/mineacademy/fo/menu/model/MenuQuantity.java index eee78b94b..9c118737d 100644 --- a/src/main/java/org/mineacademy/fo/menu/model/MenuQuantity.java +++ b/src/main/java/org/mineacademy/fo/menu/model/MenuQuantity.java @@ -56,6 +56,17 @@ public enum MenuQuantity { */ private final double amountPercent; + /** + * @deprecated rounds the amount number, you need to decide if you will support + * decimal quantities and use either {@link #getAmountDouble()} or if not, use {@link #getAmountPercent()} + * + * @return + */ + @Deprecated + public int getAmount() { + return (int) Math.round(this.getAmountPercent()); + } + /** * Get the amount from 0.00 to 1.00 * diff --git a/src/main/java/org/mineacademy/fo/model/ChunkedTask.java b/src/main/java/org/mineacademy/fo/model/ChunkedTask.java index a09d80815..233a2c951 100644 --- a/src/main/java/org/mineacademy/fo/model/ChunkedTask.java +++ b/src/main/java/org/mineacademy/fo/model/ChunkedTask.java @@ -133,6 +133,15 @@ protected String getProcessMessage(long initialTime, int processed) { * @param gracefully true if natural end, false if {@link #cancel()} used */ protected void onFinish(boolean gracefully) { + this.onFinish(); + } + + /** + * @see #onFinish(boolean) + * @deprecated it is prefered to call {@link #onFinish(boolean)} instead + */ + @Deprecated + protected void onFinish() { } /** diff --git a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java index 24e376853..f243e0405 100644 --- a/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java +++ b/src/main/java/org/mineacademy/fo/plugin/SimplePlugin.java @@ -1054,7 +1054,7 @@ public MinecraftVersion.V getMaximumVersion() { * @return */ @Nullable - public final SimpleCommandGroup getMainCommand() { + public SimpleCommandGroup getMainCommand() { return this.mainCommand; } diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index 62f22b032..190a812a1 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -1180,6 +1180,7 @@ final void load(@NonNull File file) { this.load(new InputStreamReader(stream, StandardCharsets.UTF_8)); this.onLoad(); + this.onLoadFinish(); if (this.shouldSave) { this.loading = false; @@ -1238,6 +1239,15 @@ private final void load(@NonNull Reader reader) { protected void onLoad() { } + /** + * @see #onLoad() + * + * @deprecated Renamed to {@link #onLoad()}, use that instead. + */ + @Deprecated + protected void onLoadFinish() { + } + /** * Save the configuration to the file immediately (you need to call loadConfiguration(File) first) */ @@ -1305,6 +1315,10 @@ protected void onPreSave() { */ protected void onSave() { final SerializedMap map = this.saveToMap(); + final SerializedMap legacy = this.serialize(); + + if (legacy != null) + map.put(legacy); if (map != null) for (final Map.Entry entry : map.entrySet()) @@ -1340,6 +1354,17 @@ public SerializedMap saveToMap() { return null; } + /** + * @see #saveToMap() + * @deprecated renamed, override {@link #saveToMap()} instead + * + * @return + */ + @Deprecated + protected SerializedMap serialize() { + return null; + } + /** * Removes the loaded file configuration from the disk. */ @@ -1468,16 +1493,6 @@ public final boolean isEmpty() { return this.section.isEmpty(); } - /** - * @deprecated unused, see {@link #saveToMap()} - * - * @return - */ - @Deprecated - public final SerializedMap serialize() { - throw new RuntimeException("serialize() is no longer used, override saveToMap() and use it manually instead. If you absolutely must use serialize, call getMap(\"\").serialize()"); - } - // ------------------------------------------------------------------------------------ // Static // ------------------------------------------------------------------------------------ diff --git a/src/main/java/org/mineacademy/fo/settings/YamlSectionConfig.java b/src/main/java/org/mineacademy/fo/settings/YamlSectionConfig.java new file mode 100644 index 000000000..394f3dc8c --- /dev/null +++ b/src/main/java/org/mineacademy/fo/settings/YamlSectionConfig.java @@ -0,0 +1,8 @@ +package org.mineacademy.fo.settings; + +public class YamlSectionConfig extends YamlConfig { + + public YamlSectionConfig(String pathPrefix) { + this.setPathPrefix(pathPrefix); + } +} diff --git a/src/main/java/org/mineacademy/fo/settings/YamlStaticConfig.java b/src/main/java/org/mineacademy/fo/settings/YamlStaticConfig.java index 90abd3d9b..647512808 100644 --- a/src/main/java/org/mineacademy/fo/settings/YamlStaticConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/YamlStaticConfig.java @@ -259,6 +259,15 @@ protected static final void move(final String fromRelative, final String toAbsol TEMPORARY_INSTANCE.move(fromRelative, toAbsolute); } + /** + * @deprecated renamed, use {@link #setPathPrefix(String)} instead + * @param pathPrefix + */ + @Deprecated + protected static final void pathPrefix(final String pathPrefix) { + setPathPrefix(pathPrefix); + } + protected static final void setPathPrefix(final String pathPrefix) { TEMPORARY_INSTANCE.setPathPrefix(pathPrefix); } diff --git a/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java b/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java index b673e0510..6c52a16f0 100644 --- a/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java +++ b/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java @@ -26,6 +26,16 @@ */ public final class VisualizedRegion extends Region { + /** + * @deprecated Instead of calling VisualizedRegion.EMPTY, call new VisualizedRegion() instead + */ + @Deprecated + public final static VisualizedRegion EMPTY = dummyThrow(); + + private static VisualizedRegion dummyThrow() { + throw new RuntimeException("Instead of calling VisualizedRegion.EMPTY, call new VisualizedRegion() instead"); + } + /** * A list of players who can see the particles, along with the particle color (requires {@link #particle} to be REDSTONE) */ From b4afdfa7fc12553267fd075fd4b14a3fdeacae00 Mon Sep 17 00:00:00 2001 From: kangarko Date: Sun, 21 Aug 2022 14:53:29 +0200 Subject: [PATCH 25/30] 6.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 94901fde1..d465d6760 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.mineacademy Foundation - 6.0.10 + 6.1.0 jar Foundation From 8512c160c74e01d10f54c11dd9cbe4c4191714dc Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 23 Aug 2022 06:58:54 +0200 Subject: [PATCH 26/30] Compile with the help of Java 18 (still works on Java 8) --- jitpack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jitpack.yml b/jitpack.yml index 8baa3589f..85f61dbd1 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,5 +1,5 @@ before_install: - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh - - source ./install-jdk.sh --feature 17 --license GPL + - source ./install-jdk.sh --feature 18 jdk: - openjdk17 \ No newline at end of file From 7b23082294fd2e438d29a9dc6e9abdaee203b12b Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 23 Aug 2022 07:08:17 +0200 Subject: [PATCH 27/30] Actually use openjdk18 --- jitpack.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jitpack.yml b/jitpack.yml index 85f61dbd1..160a92e81 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -2,4 +2,4 @@ before_install: - wget https://github.com/sormuras/bach/raw/master/install-jdk.sh - source ./install-jdk.sh --feature 18 jdk: - - openjdk17 \ No newline at end of file + - openjdk18 \ No newline at end of file From eafa56b3696ccf40dbf519a767c3b28a5a94d822 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 23 Aug 2022 13:52:28 +0200 Subject: [PATCH 28/30] Add BentoBox support --- pom.xml | 5 + .../org/mineacademy/fo/model/HookManager.java | 147 ++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/pom.xml b/pom.xml index d465d6760..721a2f506 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,11 @@ AuthMe 5.6.0-SNAPSHOT-2530 + + org.mineacademy.plugin + BentoBox + 1.20.1 + org.mineacademy.plugin CitizensAPI diff --git a/src/main/java/org/mineacademy/fo/model/HookManager.java b/src/main/java/org/mineacademy/fo/model/HookManager.java index d1a151043..929860dc0 100644 --- a/src/main/java/org/mineacademy/fo/model/HookManager.java +++ b/src/main/java/org/mineacademy/fo/model/HookManager.java @@ -93,6 +93,9 @@ import net.milkbowl.vault.chat.Chat; import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.permission.Permission; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; /** * Our main class hooking into different plugins, providing you @@ -107,6 +110,7 @@ public final class HookManager { private static AuthMeHook authMeHook; private static BanManagerHook banManagerHook; + private static BentoBoxHook bentoBoxHook; private static BossHook bossHook; private static CitizensHook citizensHook; private static CMIHook CMIHook; @@ -151,6 +155,9 @@ public static void loadDependencies() { if (Common.doesPluginExist("BanManager")) banManagerHook = new BanManagerHook(); + if (Common.doesPluginExist("BentoBox")) + bentoBoxHook = new BentoBoxHook(); + if (Common.doesPluginExist("Boss")) bossHook = new BossHook(); @@ -328,6 +335,15 @@ public static boolean isBanManagerLoaded() { return banManagerHook != null; } + /** + * Return if BentoBox is detected + * + * @return + */ + public static boolean isBentoBoxLoaded() { + return bentoBoxHook != null; + } + /** * Return if Boss plugin is detected * @@ -645,6 +661,90 @@ public static String getMythicMobName(Entity entity) { return isMythicMobsLoaded() ? mythicMobsHook.getBossName(entity) : null; } + // ------------------------------------------------------------------------------------------------------------ + // BentoBox-related plugins + // ------------------------------------------------------------------------------------------------------------ + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxVisitors(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandVisitors(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxCoops(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandCoops(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxTrustees(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandTrustees(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxMembers(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandMembers(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxSubOwners(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandSubOwners(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxOwners(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandOwners(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxMods(Location islandLocation) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandMods(islandLocation) : new HashSet<>(); + } + + /** + * Return BentoBox island members if the given location is an island, or empty set if null + * + * @param islandLocation + * @return + */ + public static Set getBentoBoxAdmins(Location islandLocation, int rank) { + return isBentoBoxLoaded() ? bentoBoxHook.getIslandAdmins(islandLocation) : new HashSet<>(); + } + // ------------------------------------------------------------------------------------------------------------ // Lands // ------------------------------------------------------------------------------------------------------------ @@ -3245,6 +3345,53 @@ boolean isMuted(final Player player) { } } +class BentoBoxHook { + + Set getIslandVisitors(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.VISITOR_RANK); + } + + Set getIslandCoops(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.COOP_RANK); + } + + Set getIslandTrustees(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.TRUSTED_RANK); + } + + Set getIslandMembers(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.MEMBER_RANK); + } + + Set getIslandSubOwners(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.SUB_OWNER_RANK); + } + + Set getIslandOwners(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.OWNER_RANK); + } + + Set getIslandMods(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.MOD_RANK); + } + + Set getIslandAdmins(Location islandLocation) { + return this.getIslandUsers(islandLocation, RanksManager.ADMIN_RANK); + } + + private Set getIslandUsers(Location islandLocation, int rank) { + final Optional maybeIsland = BentoBox.getInstance().getIslands().getIslandAt(islandLocation); + + if (maybeIsland.isPresent()) { + final Island island = maybeIsland.get(); + + return island.getMemberSet(rank); + } + + return new HashSet<>(); + } +} + class BossHook { /* From 4e1ee8c6576b9d4ce04a811d2034817b28fd35d8 Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Tue, 23 Aug 2022 13:52:41 +0200 Subject: [PATCH 29/30] Fix always throw, had to remove the deprecated EMPTY field all together --- .../java/org/mineacademy/fo/visual/VisualizedRegion.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java b/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java index 6c52a16f0..afb98a728 100644 --- a/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java +++ b/src/main/java/org/mineacademy/fo/visual/VisualizedRegion.java @@ -27,14 +27,10 @@ public final class VisualizedRegion extends Region { /** - * @deprecated Instead of calling VisualizedRegion.EMPTY, call new VisualizedRegion() instead + * @deprecated DOES NOT WORK, call new VisualizedRegion() instead */ @Deprecated - public final static VisualizedRegion EMPTY = dummyThrow(); - - private static VisualizedRegion dummyThrow() { - throw new RuntimeException("Instead of calling VisualizedRegion.EMPTY, call new VisualizedRegion() instead"); - } + public final static VisualizedRegion EMPTY = null; /** * A list of players who can see the particles, along with the particle color (requires {@link #particle} to be REDSTONE) From cd16b0d4c5085ba10be1d5e78c9074f4c15d95eb Mon Sep 17 00:00:00 2001 From: Matej Pacan Date: Mon, 29 Aug 2022 08:16:57 +0200 Subject: [PATCH 30/30] Update imports --- src/main/java/org/mineacademy/fo/settings/FileConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/mineacademy/fo/settings/FileConfig.java b/src/main/java/org/mineacademy/fo/settings/FileConfig.java index 190a812a1..64ed67a75 100644 --- a/src/main/java/org/mineacademy/fo/settings/FileConfig.java +++ b/src/main/java/org/mineacademy/fo/settings/FileConfig.java @@ -35,6 +35,8 @@ import org.mineacademy.fo.Valid; import org.mineacademy.fo.collection.SerializedMap; import org.mineacademy.fo.collection.StrictList; +import org.mineacademy.fo.command.SimpleCommand; +import org.mineacademy.fo.command.SimpleCommandGroup; import org.mineacademy.fo.exception.FoException; import org.mineacademy.fo.model.BoxedMessage; import org.mineacademy.fo.model.ConfigSerializable;