From 0cd2e6f54cab74c6331a729ebd0e5dbd816f6ca3 Mon Sep 17 00:00:00 2001 From: ANameSpace <125720576+ANameSpace@users.noreply.github.com> Date: Sun, 29 Sep 2024 19:56:36 +0300 Subject: [PATCH 1/4] New redesigned command system --- README.md | 18 +- .../java/net/elytrium/fastmotd/FastMOTD.java | 46 +++- .../java/net/elytrium/fastmotd/Settings.java | 29 ++- .../fastmotd/command/FastmotdCommand.java | 76 ++++++ .../fastmotd/command/MaintenanceCommand.java | 234 ++++++++++++++---- .../fastmotd/command/ReloadCommand.java | 42 ---- 6 files changed, 337 insertions(+), 108 deletions(-) create mode 100644 src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java delete mode 100644 src/main/java/net/elytrium/fastmotd/command/ReloadCommand.java diff --git a/README.md b/README.md index 14f622f..62948b7 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ Test server: [``ely.su``](https://hotmc.ru/minecraft-server-203216) Intel Core i9-9700K, DDR4 (a server that is not running any programs): -| Plugin | Pings per second count | -| - | - | -| FastMOTD | 1 700 000 - 2 000 000 pings per second | -| Without MOTD plugins | 900 000 - 1 100 000 pings per second | -| MiniMOTD | 480 000 - 580 000 pings per second | +| Plugin | Pings per second count | +|----------------------|----------------------------------------| +| FastMOTD | 1 700 000 - 2 000 000 pings per second | +| Without MOTD plugins | 900 000 - 1 100 000 pings per second | +| MiniMOTD | 480 000 - 580 000 pings per second | Intel Xeon E3-1270, DDR3 (a PC with several applications running): | Plugin | Pings per second count | @@ -34,3 +34,11 @@ Intel Xeon E3-1270, DDR3 (a PC with several applications running): | FastMOTD | 840 000 - 1 000 000 pings per second | | Without MOTD plugins | 330 000 - 430 000 pings per second | | MiniMOTD | 150 000 - 200 000 pings per second | + +## Commands and permissions + +### Admin + +- ***fastmotd.info* | /fastmotd info** - The command to get general information about the current state of the plugin +- ***fastmotd.reload* | /fastmotd reload** - Reload Plugin Command +- ***fastmotd.maintenance* | /maintenance** - Maintenance Mode Setting Command \ No newline at end of file diff --git a/src/main/java/net/elytrium/fastmotd/FastMOTD.java b/src/main/java/net/elytrium/fastmotd/FastMOTD.java index 47f7154..2b5b0f5 100644 --- a/src/main/java/net/elytrium/fastmotd/FastMOTD.java +++ b/src/main/java/net/elytrium/fastmotd/FastMOTD.java @@ -19,12 +19,14 @@ import com.google.inject.Inject; import com.velocitypowered.api.command.CommandManager; +import com.velocitypowered.api.command.CommandMeta; import com.velocitypowered.api.event.EventManager; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.plugin.annotation.DataDirectory; +import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.ServerPing; import com.velocitypowered.api.scheduler.ScheduledTask; @@ -59,8 +61,8 @@ import java.util.stream.IntStream; import net.elytrium.commons.utils.reflection.ReflectionException; import net.elytrium.commons.utils.updates.UpdatesChecker; +import net.elytrium.fastmotd.command.FastmotdCommand; import net.elytrium.fastmotd.command.MaintenanceCommand; -import net.elytrium.fastmotd.command.ReloadCommand; import net.elytrium.fastmotd.injection.ServerChannelInitializerHook; import net.elytrium.fastmotd.listener.CompatPingListener; import net.elytrium.fastmotd.listener.DisconnectOnZeroPlayersListener; @@ -99,6 +101,9 @@ public class FastMOTD { private final Map domainMaintenanceMOTD = new HashMap<>(); private PreparedPacketFactory preparedPacketFactory; private ScheduledTask updater; + private CommandMeta fastmotdCommandMeta; + private CommandMeta maintenanceCommandMeta; + private Component kickReasonComponent; private PreparedPacket kickReason; private Set kickWhitelist; @@ -137,6 +142,10 @@ public void onProxyInitialization(ProxyInitializeEvent event) { this.preparedPacketFactory = new PreparedPacketFactory(PreparedPacket::new, StateRegistry.LOGIN, false, 1, 1, false, true); + final CommandManager commandManager = this.server.getCommandManager(); + this.fastmotdCommandMeta = commandManager.metaBuilder("fastmotd").plugin(this).build(); + this.maintenanceCommandMeta = commandManager.metaBuilder("maintenance").plugin(this).build(); + this.reload(); } @@ -174,13 +183,11 @@ public void reload() { this.maintenanceMOTDGenerators.clear(); this.domainMaintenanceMOTD.clear(); - CommandManager commandManager = this.server.getCommandManager(); - commandManager.unregister("fastmotdreload"); - commandManager.unregister("maintenance"); - - commandManager.register("fastmotdreload", new ReloadCommand(this)); - commandManager.register("maintenance", - new MaintenanceCommand(this, serializer.deserialize(Settings.IMP.MAINTENANCE.COMMAND.USAGE))); + final CommandManager commandManager = this.server.getCommandManager(); + commandManager.unregister(this.fastmotdCommandMeta); + commandManager.unregister(this.maintenanceCommandMeta); + commandManager.register(this.fastmotdCommandMeta, FastmotdCommand.createBrigadierCommand(this, serializer)); + commandManager.register(this.maintenanceCommandMeta, MaintenanceCommand.createBrigadierCommand(this, serializer)); EventManager eventManager = this.server.getEventManager(); eventManager.unregisterListeners(this); @@ -198,10 +205,10 @@ public void reload() { this.kickReason.release(); } - Component kickReasonComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.KICK_MESSAGE.replace("{NL}", "\n")); + this.kickReasonComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.KICK_MESSAGE.replace("{NL}", "\n")); this.kickReason = this.preparedPacketFactory .createPreparedPacket(ProtocolVersion.MINIMUM_VERSION, ProtocolVersion.MAXIMUM_VERSION) - .prepare(version -> DisconnectPacket.create(kickReasonComponent, version, StateRegistry.LOGIN)) + .prepare(version -> DisconnectPacket.create(this.kickReasonComponent, version, StateRegistry.LOGIN)) .build(); this.kickWhitelist = Settings.IMP.MAINTENANCE.KICK_WHITELIST.stream().map((String host) -> { @@ -212,6 +219,10 @@ public void reload() { } }).collect(Collectors.toSet()); + if (Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED) { + this.kickNotWhitelist(); + } + this.generateMOTDGenerators(serializer, Settings.IMP.MAIN.VERSION_NAME, Settings.IMP.MAIN.DESCRIPTIONS, Settings.IMP.MAIN.FAVICONS, Settings.IMP.MAIN.INFORMATION, this.motdGenerators, this.protocolPointers, Settings.IMP.MAIN.VERSIONS.DESCRIPTIONS, Settings.IMP.MAIN.VERSIONS.FAVICONS, Settings.IMP.MAIN.VERSIONS.INFORMATION, @@ -377,10 +388,25 @@ public void inject(MinecraftConnection connection, ChannelPipeline pipeline) { this.preparedPacketFactory.inject(false, connection, pipeline); } + public void kickNotWhitelist() { + if (!Settings.IMP.MAINTENANCE.SHOULD_KICK_ONLINE) { + return; + } + for (Player player : this.server.getAllPlayers()) { + if (!this.kickWhitelist.contains(player.getRemoteAddress().getAddress())) { + player.disconnect(this.kickReasonComponent); + } + } + } + public boolean checkKickWhitelist(InetAddress inetAddress) { return this.kickWhitelist.contains(inetAddress); } + public Set getKickWhitelist() { + return this.kickWhitelist; + } + public VelocityServer getServer() { return this.server; } diff --git a/src/main/java/net/elytrium/fastmotd/Settings.java b/src/main/java/net/elytrium/fastmotd/Settings.java index e21167e..cf1db68 100644 --- a/src/main/java/net/elytrium/fastmotd/Settings.java +++ b/src/main/java/net/elytrium/fastmotd/Settings.java @@ -41,6 +41,7 @@ public class Settings extends YamlSerializable { @CommentValue("GSON_COLOR_DOWNSAMPLING - Same as GSON, but uses downsampling."), }) public Serializers SERIALIZER = Serializers.MINIMESSAGE; + public String PREFIX = "FastMOTD >>"; public MAIN MAIN = new MAIN(); @@ -92,6 +93,16 @@ public static class VERSIONS { } public Map DOMAINS = Map.of("example.com:25565", new DOMAIN_MOTD_NODE()); + + public MESSAGES MESSAGES = new MESSAGES(); + + public static class MESSAGES { + public List USAGE = List.of("FastMOTD command usage:", " /fastmotd info", " /fastmotd reload"); + public List INFO = List.of("FastMOTD Info:", " Maintenance status: {MAINTENANCE_ENABLED}"); + public String YES = ""; + public String NO = ""; + public String RELOAD = "Reloaded successfully!"; + } } public MAINTENANCE MAINTENANCE = new MAINTENANCE(); @@ -100,6 +111,8 @@ public static class MAINTENANCE { public boolean MAINTENANCE_ENABLED = false; public boolean SHOW_VERSION = true; public boolean SHOULD_KICK_ON_JOIN = true; + @Comment(@CommentValue("This parameter determines whether to remove non-whitelisted players from the game when maintenance mode is activated.")) + public boolean SHOULD_KICK_ONLINE = false; public List KICK_WHITELIST = List.of("127.0.0.1"); public String KICK_MESSAGE = "Try to join the server later"; public String VERSION_NAME = "MAINTENANCE MODE ENABLED!!"; @@ -128,10 +141,18 @@ public static class VERSIONS { public Map DOMAINS = Map.of("example.com:25565", new DOMAIN_MOTD_NODE()); - public COMMAND COMMAND = new COMMAND(); - - public static class COMMAND { - public String USAGE = "FastMOTD >> Usage: /maintenance "; + public MESSAGES MESSAGES = new MESSAGES(); + + public static class MESSAGES { + public List USAGE = List.of("FastMOTD maintenance command usage:", " /maintenance ", " /maintenance list [-p]", " /maintenance "); + public String OFF = "You have disabled the maintenance mode!"; + public String ON = "You have enabled maintenance mode!"; + public String LIST = "Whitelist: {KICK_WHITELIST}"; + public String SUCCESSFULLY_ADDED = "You have successfully added the IP address to the whitelist!"; + public String SUCCESSFULLY_REMOVED = "You have successfully removed the IP address to the whitelist!"; + public String INVALID_INPUT = "This is not an online player or IP address."; + public String ALREADY_IN = "This IP address has already been added!"; + public String NOT_IN_WHITELIST = "This IP address has not yet been added!"; } } diff --git a/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java new file mode 100644 index 0000000..30ddb2b --- /dev/null +++ b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 - 2023 Elytrium + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.elytrium.fastmotd.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.tree.LiteralCommandNode; +import com.velocitypowered.api.command.BrigadierCommand; +import com.velocitypowered.api.command.CommandSource; +import net.elytrium.fastmotd.FastMOTD; +import net.elytrium.fastmotd.Settings; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.serializer.ComponentSerializer; + +public class FastmotdCommand { + /** + * This method creates a {@link com.velocitypowered.api.command.BrigadierCommand} for the fastmotd command. + * + * @param plugin The FastMOTD plugin instance. + * @param serializer The component serializer. + * @return The maintenance command. + */ + public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, final ComponentSerializer serializer) { + final String PREFIX = Settings.IMP.PREFIX + " "; + final Component usageComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAIN.MESSAGES.USAGE)); + final Component infoComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAIN.MESSAGES.INFO)); + final Component reloadComponent = serializer.deserialize(PREFIX + Settings.IMP.MAIN.MESSAGES.RELOAD); + final Component yesComponent = serializer.deserialize(Settings.IMP.MAIN.MESSAGES.YES); + final Component noComponent = serializer.deserialize(Settings.IMP.MAIN.MESSAGES.NO); + + LiteralCommandNode fastmotdNode = BrigadierCommand.literalArgumentBuilder("fastmotd") + .requires(source -> source.hasPermission("fastmotd.reload") || source.hasPermission("fastmotd.info")) + .executes(context -> { + context.getSource().sendMessage(usageComponent); + return Command.SINGLE_SUCCESS; + }) + // info subcommand + .then(BrigadierCommand.literalArgumentBuilder("info") + .requires(source -> source.hasPermission("fastmotd.info")) + .executes(context -> { + final TextReplacementConfig maintenanceReplacement = TextReplacementConfig.builder() + .matchLiteral("{MAINTENANCE_ENABLED}") + .replacement(Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ? yesComponent : noComponent) + .build(); + context.getSource().sendMessage(infoComponent.replaceText(maintenanceReplacement)); + return Command.SINGLE_SUCCESS; + }) + ) + // reload subcommand + .then(BrigadierCommand.literalArgumentBuilder("reload") + .requires(source -> source.hasPermission("fastmotd.reload")) + .executes(context -> { + plugin.reload(); + context.getSource().sendMessage(reloadComponent); + return Command.SINGLE_SUCCESS; + }) + ) + .build(); + return new BrigadierCommand(fastmotdNode); + } +} diff --git a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java index 18684d3..39cade6 100644 --- a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java +++ b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java @@ -17,63 +17,203 @@ package net.elytrium.fastmotd.command; -import com.google.common.collect.ImmutableList; +import com.google.common.base.Joiner; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.tree.LiteralCommandNode; +import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.command.SimpleCommand; -import com.velocitypowered.api.permission.Tristate; -import java.util.List; +import com.velocitypowered.api.proxy.Player; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; import net.elytrium.fastmotd.FastMOTD; import net.elytrium.fastmotd.Settings; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextReplacementConfig; +import net.kyori.adventure.text.serializer.ComponentSerializer; -public class MaintenanceCommand implements SimpleCommand { +public class MaintenanceCommand { + /** + * This method creates a {@link com.velocitypowered.api.command.BrigadierCommand} for the maintenance command. + * + * @param plugin The FastMOTD plugin instance. + * @param serializer The component serializer. + * @return The maintenance command. + */ + public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, final ComponentSerializer serializer) { + final String PREFIX = Settings.IMP.PREFIX + " "; + final Component usageComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAINTENANCE.MESSAGES.USAGE)); + final Component maintenanceOnComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.ON); + final Component maintenanceOffComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.OFF); + final Component listComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.LIST); + final Component successfullyAddComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_ADDED); + final Component successfullyRemoveComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_REMOVED); + final Component invalidInputComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.INVALID_INPUT); + final Component alreadyInComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.ALREADY_IN); + final Component notInWhitelistComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.NOT_IN_WHITELIST); - private final FastMOTD plugin; - private final Component usage; - - public MaintenanceCommand(FastMOTD plugin, Component usage) { - this.plugin = plugin; - this.usage = usage; - } - - @Override - public List suggest(Invocation invocation) { - return ImmutableList.of("off", "on", "toggle"); + LiteralCommandNode maintenanceNode = BrigadierCommand.literalArgumentBuilder("maintenance") + .requires(source -> source.hasPermission("fastmotd.maintenance")) + .executes(context -> { + context.getSource().sendMessage(usageComponent); + return Command.SINGLE_SUCCESS; + }) + // off subcommand + .then(BrigadierCommand.literalArgumentBuilder("off") + .executes(context -> { + Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED = false; + Settings.IMP.save(plugin.getConfigPath()); + context.getSource().sendMessage(maintenanceOffComponent); + return Command.SINGLE_SUCCESS; + }) + ) + // on subcommand + .then(BrigadierCommand.literalArgumentBuilder("on") + .executes(context -> { + Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED = true; + Settings.IMP.save(plugin.getConfigPath()); + plugin.kickNotWhitelist(); + context.getSource().sendMessage(maintenanceOnComponent); + return Command.SINGLE_SUCCESS; + }) + ) + // toggle subcommand + .then(BrigadierCommand.literalArgumentBuilder("toggle") + .executes(context -> { + Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ^= true; + Settings.IMP.save(plugin.getConfigPath()); + if (Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED) { + plugin.kickNotWhitelist(); + context.getSource().sendMessage(maintenanceOnComponent); + } else { + context.getSource().sendMessage(maintenanceOffComponent); + } + return Command.SINGLE_SUCCESS; + }) + ) + // list subcommand + .then(BrigadierCommand.literalArgumentBuilder("list") + .then(BrigadierCommand.literalArgumentBuilder("-p") + .executes(context -> { + final TextReplacementConfig playerReplacement = TextReplacementConfig.builder() + .matchLiteral("{KICK_WHITELIST}") + .replacement(Joiner.on(",").join(getOnlinePlayersFromWhitelist(plugin))) + .build(); + context.getSource().sendMessage(listComponent.replaceText(playerReplacement)); + return Command.SINGLE_SUCCESS; + }) + ) + .executes(context -> { + final TextReplacementConfig addressReplacement = TextReplacementConfig.builder() + .matchLiteral("{KICK_WHITELIST}") + .replacement(Joiner.on(",").join(plugin.getKickWhitelist().stream() + .map(InetAddress::getHostAddress) + .collect(Collectors.toList()))) + .build(); + context.getSource().sendMessage(listComponent.replaceText(addressReplacement)); + return Command.SINGLE_SUCCESS; + }) + ) + // add subcommand + .then(BrigadierCommand.literalArgumentBuilder("add") + .then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.string()) + .suggests((ctx, builder) -> { + plugin.getServer().getAllPlayers().forEach(player -> builder.suggest(player.getUsername())); + builder.suggest("127.0.0.1"); + return builder.buildFuture(); + }) + .executes(context -> { + final CommandSource source = context.getSource(); + final InetAddress address = getInetAddressFromString(plugin, context.getArgument("player", String.class)); + if (address == null) { + source.sendMessage(invalidInputComponent); + return Command.SINGLE_SUCCESS; + } + if (plugin.checkKickWhitelist(address)) { + source.sendMessage(alreadyInComponent); + return Command.SINGLE_SUCCESS; + } + plugin.getKickWhitelist().add(address); + Settings.IMP.MAINTENANCE.KICK_WHITELIST.add(address.getHostAddress()); + Settings.IMP.save(plugin.getConfigPath()); + source.sendMessage(successfullyAddComponent); + return Command.SINGLE_SUCCESS; + }) + ) + .executes(context -> { + context.getSource().sendMessage(usageComponent); + return Command.SINGLE_SUCCESS; + }) + ) + // remove subcommand + .then(BrigadierCommand.literalArgumentBuilder("remove") + .then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.string()) + .suggests((ctx, builder) -> { + plugin.getServer().getAllPlayers().forEach(player -> builder.suggest(player.getUsername())); + plugin.getKickWhitelist().forEach(inetAddress -> builder.suggest(inetAddress.getHostAddress())); + return builder.buildFuture(); + }) + .executes(context -> { + final CommandSource source = context.getSource(); + final InetAddress address = getInetAddressFromString(plugin, context.getArgument("player", String.class)); + if (address == null) { + source.sendMessage(invalidInputComponent); + return Command.SINGLE_SUCCESS; + } + if (!plugin.checkKickWhitelist(address)) { + source.sendMessage(notInWhitelistComponent); + return Command.SINGLE_SUCCESS; + } + plugin.getKickWhitelist().remove(address); + Settings.IMP.MAINTENANCE.KICK_WHITELIST.remove(address.getHostAddress()); + Settings.IMP.save(plugin.getConfigPath()); + source.sendMessage(successfullyRemoveComponent); + return Command.SINGLE_SUCCESS; + }) + ) + .executes(context -> { + context.getSource().sendMessage(usageComponent); + return Command.SINGLE_SUCCESS; + }) + ) + .build(); + return new BrigadierCommand(maintenanceNode); } - @Override - public void execute(Invocation invocation) { - String[] args = invocation.arguments(); - CommandSource source = invocation.source(); - - if (args.length < 1) { - source.sendMessage(this.usage); - return; - } - - switch (args[0]) { - case "off": - Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED = false; - break; - - case "on": - Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED = true; - break; - - case "toggle": - Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ^= true; - break; - - default: - source.sendMessage(this.usage); - return; + /** + * Retrieves the InetAddress from a given string. + * + * @param plugin The FastMOTD plugin instance. + * @param str The string with the player's name or IP address. + * @return The InetAddress object corresponding to the given string, or null if the string cannot be resolved. + */ + private static InetAddress getInetAddressFromString(final FastMOTD plugin, final String str) { + Optional playerOptional = plugin.getServer().getPlayer(str); + if (playerOptional.isPresent()) { + return playerOptional.get().getRemoteAddress().getAddress(); + } else { + try { + return InetAddress.getByName(str); + } catch (UnknownHostException e) { + return null; + } } - - Settings.IMP.save(this.plugin.getConfigPath()); } - @Override - public boolean hasPermission(Invocation invocation) { - return invocation.source().getPermissionValue("fastmotd.maintenance") == Tristate.TRUE; + /** + * Retrieves a set of online players whose addresses are present in the kick whitelist. + * + * @param plugin The FastMOTD plugin instance. + * @return A set of online players whose addresses are present in the kick whitelist. + */ + private static Set getOnlinePlayersFromWhitelist(final FastMOTD plugin) { + final Set addresses = plugin.getKickWhitelist(); + return plugin.getServer().getAllPlayers().stream() + .filter(player -> addresses.contains(player.getRemoteAddress().getAddress())) + .map(player -> player.getUsername() + "(" + player.getRemoteAddress().getAddress().getHostName() + ")") + .collect(Collectors.toSet()); } } diff --git a/src/main/java/net/elytrium/fastmotd/command/ReloadCommand.java b/src/main/java/net/elytrium/fastmotd/command/ReloadCommand.java deleted file mode 100644 index 76ea028..0000000 --- a/src/main/java/net/elytrium/fastmotd/command/ReloadCommand.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2022 - 2023 Elytrium - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package net.elytrium.fastmotd.command; - -import com.velocitypowered.api.command.SimpleCommand; -import com.velocitypowered.api.permission.Tristate; -import net.elytrium.fastmotd.FastMOTD; - -public class ReloadCommand implements SimpleCommand { - - private final FastMOTD plugin; - - public ReloadCommand(FastMOTD plugin) { - this.plugin = plugin; - } - - - @Override - public void execute(Invocation invocation) { - this.plugin.reload(); - } - - @Override - public boolean hasPermission(Invocation invocation) { - return invocation.source().getPermissionValue("fastmotd.reload") == Tristate.TRUE; - } -} From 2b211147289ffd557b2416c7c524871457d745db Mon Sep 17 00:00:00 2001 From: ANameSpace <125720576+ANameSpace@users.noreply.github.com> Date: Mon, 30 Sep 2024 07:45:06 +0300 Subject: [PATCH 2/4] New redesigned command system (part 2) --- README.md | 15 ++-- .../java/net/elytrium/fastmotd/FastMOTD.java | 4 +- .../java/net/elytrium/fastmotd/Settings.java | 25 +++--- .../fastmotd/command/FastmotdCommand.java | 18 ++-- .../fastmotd/command/MaintenanceCommand.java | 82 +++++++++---------- 5 files changed, 70 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 62948b7..9df3033 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,17 @@ Intel Core i9-9700K, DDR4 (a server that is not running any programs): | MiniMOTD | 480 000 - 580 000 pings per second | Intel Xeon E3-1270, DDR3 (a PC with several applications running): -| Plugin | Pings per second count | -| - | - | -| FastMOTD | 840 000 - 1 000 000 pings per second | -| Without MOTD plugins | 330 000 - 430 000 pings per second | -| MiniMOTD | 150 000 - 200 000 pings per second | + +| Plugin | Pings per second count | +|----------------------|--------------------------------------| +| FastMOTD | 840 000 - 1 000 000 pings per second | +| Without MOTD plugins | 330 000 - 430 000 pings per second | +| MiniMOTD | 150 000 - 200 000 pings per second | ## Commands and permissions ### Admin - ***fastmotd.info* | /fastmotd info** - The command to get general information about the current state of the plugin -- ***fastmotd.reload* | /fastmotd reload** - Reload Plugin Command -- ***fastmotd.maintenance* | /maintenance** - Maintenance Mode Setting Command \ No newline at end of file +- ***fastmotd.reload* | /fastmotd reload** - Reload plugin command +- ***fastmotd.maintenance* | /maintenance** - Maintenance mode setting command \ No newline at end of file diff --git a/src/main/java/net/elytrium/fastmotd/FastMOTD.java b/src/main/java/net/elytrium/fastmotd/FastMOTD.java index 2b5b0f5..4e6ce67 100644 --- a/src/main/java/net/elytrium/fastmotd/FastMOTD.java +++ b/src/main/java/net/elytrium/fastmotd/FastMOTD.java @@ -220,7 +220,7 @@ public void reload() { }).collect(Collectors.toSet()); if (Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED) { - this.kickNotWhitelist(); + this.kickNotWhitelisted(); } this.generateMOTDGenerators(serializer, Settings.IMP.MAIN.VERSION_NAME, Settings.IMP.MAIN.DESCRIPTIONS, @@ -388,7 +388,7 @@ public void inject(MinecraftConnection connection, ChannelPipeline pipeline) { this.preparedPacketFactory.inject(false, connection, pipeline); } - public void kickNotWhitelist() { + public void kickNotWhitelisted() { if (!Settings.IMP.MAINTENANCE.SHOULD_KICK_ONLINE) { return; } diff --git a/src/main/java/net/elytrium/fastmotd/Settings.java b/src/main/java/net/elytrium/fastmotd/Settings.java index cf1db68..cec14fd 100644 --- a/src/main/java/net/elytrium/fastmotd/Settings.java +++ b/src/main/java/net/elytrium/fastmotd/Settings.java @@ -23,6 +23,7 @@ import net.elytrium.serializer.annotations.Comment; import net.elytrium.serializer.annotations.CommentValue; import net.elytrium.serializer.annotations.Final; +import net.elytrium.serializer.annotations.RegisterPlaceholders; import net.elytrium.serializer.language.object.YamlSerializable; public class Settings extends YamlSerializable { @@ -41,7 +42,6 @@ public class Settings extends YamlSerializable { @CommentValue("GSON_COLOR_DOWNSAMPLING - Same as GSON, but uses downsampling."), }) public Serializers SERIALIZER = Serializers.MINIMESSAGE; - public String PREFIX = "FastMOTD >>"; public MAIN MAIN = new MAIN(); @@ -98,10 +98,11 @@ public static class VERSIONS { public static class MESSAGES { public List USAGE = List.of("FastMOTD command usage:", " /fastmotd info", " /fastmotd reload"); + @RegisterPlaceholders("{MAINTENANCE_ENABLED}") public List INFO = List.of("FastMOTD Info:", " Maintenance status: {MAINTENANCE_ENABLED}"); public String YES = ""; public String NO = ""; - public String RELOAD = "Reloaded successfully!"; + public String RELOAD = "FastMOTD >> Reloaded successfully!"; } } @@ -144,15 +145,17 @@ public static class VERSIONS { public MESSAGES MESSAGES = new MESSAGES(); public static class MESSAGES { - public List USAGE = List.of("FastMOTD maintenance command usage:", " /maintenance ", " /maintenance list [-p]", " /maintenance "); - public String OFF = "You have disabled the maintenance mode!"; - public String ON = "You have enabled maintenance mode!"; - public String LIST = "Whitelist: {KICK_WHITELIST}"; - public String SUCCESSFULLY_ADDED = "You have successfully added the IP address to the whitelist!"; - public String SUCCESSFULLY_REMOVED = "You have successfully removed the IP address to the whitelist!"; - public String INVALID_INPUT = "This is not an online player or IP address."; - public String ALREADY_IN = "This IP address has already been added!"; - public String NOT_IN_WHITELIST = "This IP address has not yet been added!"; + public List USAGE = List.of("FastMOTD maintenance command usage:", " /maintenance - change maintenance mode", " /maintenance list [-p] - get all ip addresses in whitelist ([-p] - get all online players in whitelist)", " /maintenance - add/remove ip (or current player ip) from whitelist"); + public String OFF = "FastMOTD >> You have disabled the maintenance mode!"; + public String ON = "FastMOTD >> You have enabled maintenance mode!"; + @RegisterPlaceholders("{KICK_WHITELIST}") + public String LIST = "FastMOTD >> Whitelist: {KICK_WHITELIST}"; + public String LIST_PLAYER_FORMAT = "{PLAYER} ({IP})"; + public String SUCCESSFULLY_ADDED = "FastMOTD >> You have successfully added the IP address to the whitelist!"; + public String SUCCESSFULLY_REMOVED = "FastMOTD >> You have successfully removed the IP address to the whitelist!"; + public String INVALID_INPUT = "FastMOTD >> This is not an online player or IP address."; + public String ALREADY_IN = "FastMOTD >> This IP address has already been added!"; + public String NOT_IN_WHITELIST = "FastMOTD >> This IP address has not yet been added!"; } } diff --git a/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java index 30ddb2b..3541391 100644 --- a/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java +++ b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java @@ -23,8 +23,8 @@ import com.velocitypowered.api.command.CommandSource; import net.elytrium.fastmotd.FastMOTD; import net.elytrium.fastmotd.Settings; +import net.elytrium.serializer.placeholders.Placeholders; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.serializer.ComponentSerializer; public class FastmotdCommand { @@ -36,12 +36,9 @@ public class FastmotdCommand { * @return The maintenance command. */ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, final ComponentSerializer serializer) { - final String PREFIX = Settings.IMP.PREFIX + " "; final Component usageComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAIN.MESSAGES.USAGE)); - final Component infoComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAIN.MESSAGES.INFO)); - final Component reloadComponent = serializer.deserialize(PREFIX + Settings.IMP.MAIN.MESSAGES.RELOAD); - final Component yesComponent = serializer.deserialize(Settings.IMP.MAIN.MESSAGES.YES); - final Component noComponent = serializer.deserialize(Settings.IMP.MAIN.MESSAGES.NO); + final Component reloadComponent = serializer.deserialize(Settings.IMP.MAIN.MESSAGES.RELOAD); + final String infoString = String.join("\n", Settings.IMP.MAIN.MESSAGES.INFO); LiteralCommandNode fastmotdNode = BrigadierCommand.literalArgumentBuilder("fastmotd") .requires(source -> source.hasPermission("fastmotd.reload") || source.hasPermission("fastmotd.info")) @@ -53,11 +50,10 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .then(BrigadierCommand.literalArgumentBuilder("info") .requires(source -> source.hasPermission("fastmotd.info")) .executes(context -> { - final TextReplacementConfig maintenanceReplacement = TextReplacementConfig.builder() - .matchLiteral("{MAINTENANCE_ENABLED}") - .replacement(Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ? yesComponent : noComponent) - .build(); - context.getSource().sendMessage(infoComponent.replaceText(maintenanceReplacement)); + context.getSource().sendMessage(serializer.deserialize(Placeholders.replace( + infoString, + Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ? Settings.IMP.MAIN.MESSAGES.YES : Settings.IMP.MAIN.MESSAGES.NO + ))); return Command.SINGLE_SUCCESS; }) ) diff --git a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java index 39cade6..23096ca 100644 --- a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java +++ b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java @@ -27,12 +27,11 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import net.elytrium.fastmotd.FastMOTD; import net.elytrium.fastmotd.Settings; +import net.elytrium.serializer.placeholders.Placeholders; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.serializer.ComponentSerializer; public class MaintenanceCommand { @@ -44,16 +43,16 @@ public class MaintenanceCommand { * @return The maintenance command. */ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, final ComponentSerializer serializer) { - final String PREFIX = Settings.IMP.PREFIX + " "; final Component usageComponent = serializer.deserialize(String.join("\n", Settings.IMP.MAINTENANCE.MESSAGES.USAGE)); - final Component maintenanceOnComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.ON); - final Component maintenanceOffComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.OFF); - final Component listComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.LIST); - final Component successfullyAddComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_ADDED); - final Component successfullyRemoveComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_REMOVED); - final Component invalidInputComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.INVALID_INPUT); - final Component alreadyInComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.ALREADY_IN); - final Component notInWhitelistComponent = serializer.deserialize(PREFIX + Settings.IMP.MAINTENANCE.MESSAGES.NOT_IN_WHITELIST); + final Component maintenanceOnComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.ON); + final Component maintenanceOffComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.OFF); + final String listString = Settings.IMP.MAINTENANCE.MESSAGES.LIST; + final String listPlayerFormat = Settings.IMP.MAINTENANCE.MESSAGES.LIST_PLAYER_FORMAT; + final Component successfullyAddComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_ADDED); + final Component successfullyRemoveComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.SUCCESSFULLY_REMOVED); + final Component invalidInputComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.INVALID_INPUT); + final Component alreadyInComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.ALREADY_IN); + final Component notInWhitelistComponent = serializer.deserialize(Settings.IMP.MAINTENANCE.MESSAGES.NOT_IN_WHITELIST); LiteralCommandNode maintenanceNode = BrigadierCommand.literalArgumentBuilder("maintenance") .requires(source -> source.hasPermission("fastmotd.maintenance")) @@ -75,7 +74,7 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .executes(context -> { Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED = true; Settings.IMP.save(plugin.getConfigPath()); - plugin.kickNotWhitelist(); + plugin.kickNotWhitelisted(); context.getSource().sendMessage(maintenanceOnComponent); return Command.SINGLE_SUCCESS; }) @@ -86,7 +85,7 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ^= true; Settings.IMP.save(plugin.getConfigPath()); if (Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED) { - plugin.kickNotWhitelist(); + plugin.kickNotWhitelisted(); context.getSource().sendMessage(maintenanceOnComponent); } else { context.getSource().sendMessage(maintenanceOffComponent); @@ -98,22 +97,25 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .then(BrigadierCommand.literalArgumentBuilder("list") .then(BrigadierCommand.literalArgumentBuilder("-p") .executes(context -> { - final TextReplacementConfig playerReplacement = TextReplacementConfig.builder() - .matchLiteral("{KICK_WHITELIST}") - .replacement(Joiner.on(",").join(getOnlinePlayersFromWhitelist(plugin))) - .build(); - context.getSource().sendMessage(listComponent.replaceText(playerReplacement)); + context.getSource().sendMessage(serializer.deserialize(Placeholders.replace( + listString, + Joiner.on(", ").join(plugin.getServer().getAllPlayers().stream() + .filter(player -> plugin.checkKickWhitelist(player.getRemoteAddress().getAddress())) + .map(player -> listPlayerFormat + .replace("{PLAYER}", player.getUsername()) + .replace("{IP}", player.getRemoteAddress().getAddress().getHostAddress())) + .collect(Collectors.toSet())) + ))); return Command.SINGLE_SUCCESS; }) ) .executes(context -> { - final TextReplacementConfig addressReplacement = TextReplacementConfig.builder() - .matchLiteral("{KICK_WHITELIST}") - .replacement(Joiner.on(",").join(plugin.getKickWhitelist().stream() - .map(InetAddress::getHostAddress) - .collect(Collectors.toList()))) - .build(); - context.getSource().sendMessage(listComponent.replaceText(addressReplacement)); + context.getSource().sendMessage(serializer.deserialize(Placeholders.replace( + listString, + Joiner.on(", ").join(plugin.getKickWhitelist().stream() + .map(InetAddress::getHostAddress) + .collect(Collectors.toList())) + ))); return Command.SINGLE_SUCCESS; }) ) @@ -121,8 +123,12 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .then(BrigadierCommand.literalArgumentBuilder("add") .then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.string()) .suggests((ctx, builder) -> { - plugin.getServer().getAllPlayers().forEach(player -> builder.suggest(player.getUsername())); - builder.suggest("127.0.0.1"); + plugin.getServer().getAllPlayers().stream() + .filter(player -> !plugin.checkKickWhitelist(player.getRemoteAddress().getAddress())) + .forEach(player -> { + builder.suggest(player.getUsername()); + builder.suggest(player.getRemoteAddress().getAddress().getHostAddress()); + }); return builder.buildFuture(); }) .executes(context -> { @@ -152,8 +158,12 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .then(BrigadierCommand.literalArgumentBuilder("remove") .then(BrigadierCommand.requiredArgumentBuilder("player", StringArgumentType.string()) .suggests((ctx, builder) -> { - plugin.getServer().getAllPlayers().forEach(player -> builder.suggest(player.getUsername())); - plugin.getKickWhitelist().forEach(inetAddress -> builder.suggest(inetAddress.getHostAddress())); + plugin.getServer().getAllPlayers().stream() + .filter(player -> plugin.checkKickWhitelist(player.getRemoteAddress().getAddress())) + .forEach(player -> { + builder.suggest(player.getUsername()); + builder.suggest(player.getRemoteAddress().getAddress().getHostAddress()); + }); return builder.buildFuture(); }) .executes(context -> { @@ -202,18 +212,4 @@ private static InetAddress getInetAddressFromString(final FastMOTD plugin, final } } } - - /** - * Retrieves a set of online players whose addresses are present in the kick whitelist. - * - * @param plugin The FastMOTD plugin instance. - * @return A set of online players whose addresses are present in the kick whitelist. - */ - private static Set getOnlinePlayersFromWhitelist(final FastMOTD plugin) { - final Set addresses = plugin.getKickWhitelist(); - return plugin.getServer().getAllPlayers().stream() - .filter(player -> addresses.contains(player.getRemoteAddress().getAddress())) - .map(player -> player.getUsername() + "(" + player.getRemoteAddress().getAddress().getHostName() + ")") - .collect(Collectors.toSet()); - } } From 892c6ba1cbcd593d7fab89fa7f5cd37be1718498 Mon Sep 17 00:00:00 2001 From: ANameSpace <125720576+ANameSpace@users.noreply.github.com> Date: Mon, 30 Sep 2024 08:02:43 +0300 Subject: [PATCH 3/4] New redesigned command system (fix) --- src/main/java/net/elytrium/fastmotd/Settings.java | 1 - .../elytrium/fastmotd/command/FastmotdCommand.java | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/elytrium/fastmotd/Settings.java b/src/main/java/net/elytrium/fastmotd/Settings.java index cec14fd..bb2c236 100644 --- a/src/main/java/net/elytrium/fastmotd/Settings.java +++ b/src/main/java/net/elytrium/fastmotd/Settings.java @@ -98,7 +98,6 @@ public static class VERSIONS { public static class MESSAGES { public List USAGE = List.of("FastMOTD command usage:", " /fastmotd info", " /fastmotd reload"); - @RegisterPlaceholders("{MAINTENANCE_ENABLED}") public List INFO = List.of("FastMOTD Info:", " Maintenance status: {MAINTENANCE_ENABLED}"); public String YES = ""; public String NO = ""; diff --git a/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java index 3541391..cd366ef 100644 --- a/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java +++ b/src/main/java/net/elytrium/fastmotd/command/FastmotdCommand.java @@ -23,7 +23,6 @@ import com.velocitypowered.api.command.CommandSource; import net.elytrium.fastmotd.FastMOTD; import net.elytrium.fastmotd.Settings; -import net.elytrium.serializer.placeholders.Placeholders; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.ComponentSerializer; @@ -50,10 +49,12 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .then(BrigadierCommand.literalArgumentBuilder("info") .requires(source -> source.hasPermission("fastmotd.info")) .executes(context -> { - context.getSource().sendMessage(serializer.deserialize(Placeholders.replace( - infoString, - Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ? Settings.IMP.MAIN.MESSAGES.YES : Settings.IMP.MAIN.MESSAGES.NO - ))); + context.getSource().sendMessage(serializer.deserialize(infoString + .replace( + "{MAINTENANCE_ENABLED}", + Settings.IMP.MAINTENANCE.MAINTENANCE_ENABLED ? Settings.IMP.MAIN.MESSAGES.YES : Settings.IMP.MAIN.MESSAGES.NO + ) + )); return Command.SINGLE_SUCCESS; }) ) From a0bd0c1200eb54284e47a5b39fab9bb93ef0967a Mon Sep 17 00:00:00 2001 From: ANameSpace <125720576+ANameSpace@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:45:54 +0300 Subject: [PATCH 4/4] New redesigned command system (fix-2) --- .../java/net/elytrium/fastmotd/command/MaintenanceCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java index 23096ca..98d5ad1 100644 --- a/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java +++ b/src/main/java/net/elytrium/fastmotd/command/MaintenanceCommand.java @@ -162,8 +162,8 @@ public static BrigadierCommand createBrigadierCommand(final FastMOTD plugin, fin .filter(player -> plugin.checkKickWhitelist(player.getRemoteAddress().getAddress())) .forEach(player -> { builder.suggest(player.getUsername()); - builder.suggest(player.getRemoteAddress().getAddress().getHostAddress()); }); + plugin.getKickWhitelist().forEach(address -> builder.suggest(address.getHostAddress())); return builder.buildFuture(); }) .executes(context -> {