From a0ae828fbd4cf0a6bb6e8663eda227c2d1785fa4 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Tue, 14 Jun 2022 16:18:45 +0200 Subject: [PATCH] Add SWCommand and corresponding api --- src/de/steamwar/bungeecore/BungeeCore.java | 16 ++ .../steamwar/command/CommandRegistering.java | 37 +++++ src/de/steamwar/command/GuardChecker.java | 30 ++++ src/de/steamwar/command/SWCommand.java | 147 ++++++++++++++++++ src/de/steamwar/command/TypeMapper.java | 29 ++++ src/de/steamwar/command/TypeUtils.java | 36 +++++ .../steamwar/messages/BungeeCore.properties | 3 + .../messages/BungeeCore_de.properties | 2 + 8 files changed, 300 insertions(+) create mode 100644 src/de/steamwar/command/CommandRegistering.java create mode 100644 src/de/steamwar/command/GuardChecker.java create mode 100644 src/de/steamwar/command/SWCommand.java create mode 100644 src/de/steamwar/command/TypeMapper.java create mode 100644 src/de/steamwar/command/TypeUtils.java diff --git a/src/de/steamwar/bungeecore/BungeeCore.java b/src/de/steamwar/bungeecore/BungeeCore.java index 5cd415e..216722b 100644 --- a/src/de/steamwar/bungeecore/BungeeCore.java +++ b/src/de/steamwar/bungeecore/BungeeCore.java @@ -27,6 +27,9 @@ import de.steamwar.bungeecore.listeners.mods.*; import de.steamwar.bungeecore.network.BungeeNetworkHandler; import de.steamwar.bungeecore.network.NetworkReceiver; import de.steamwar.bungeecore.sql.*; +import de.steamwar.command.SWCommandUtils; +import de.steamwar.command.SWTypeMapperCreator; +import de.steamwar.command.TypeMapper; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; @@ -42,6 +45,7 @@ import net.md_5.bungee.config.YamlConfiguration; import java.io.File; import java.io.IOException; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -67,6 +71,18 @@ public class BungeeCore extends Plugin { @Override public void onEnable(){ + SWCommandUtils.init((SWTypeMapperCreator, CommandSender, Object>) (mapper, tabCompleter) -> new TypeMapper() { + @Override + public Object map(CommandSender commandSender, String[] previousArguments, String s) { + return mapper.apply(s); + } + + @Override + public Collection tabCompletes(CommandSender sender, String[] previousArguments, String s) { + return tabCompleter.apply(sender, s); + } + }); + getProxy().registerChannel("sw:bridge"); getProxy().registerChannel("fabricmodsender:mods"); diff --git a/src/de/steamwar/command/CommandRegistering.java b/src/de/steamwar/command/CommandRegistering.java new file mode 100644 index 0000000..b6a4994 --- /dev/null +++ b/src/de/steamwar/command/CommandRegistering.java @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * 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 de.steamwar.command; + +import de.steamwar.bungeecore.BungeeCore; +import lombok.experimental.UtilityClass; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.plugin.Command; + +@UtilityClass +class CommandRegistering { + + static void unregister(Command command) { + ProxyServer.getInstance().getPluginManager().unregisterCommand(command); + } + + static void register(Command command) { + ProxyServer.getInstance().getPluginManager().registerCommand(BungeeCore.get(), command); + } +} diff --git a/src/de/steamwar/command/GuardChecker.java b/src/de/steamwar/command/GuardChecker.java new file mode 100644 index 0000000..06c9110 --- /dev/null +++ b/src/de/steamwar/command/GuardChecker.java @@ -0,0 +1,30 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * 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 de.steamwar.command; + +import net.md_5.bungee.api.CommandSender; + +@FunctionalInterface +public interface GuardChecker extends AbstractGuardChecker { + /** + * While guarding the first parameter of the command the parameter s of this method is {@code null} + */ + GuardResult guard(CommandSender commandSender, GuardCheckType guardCheckType, String[] previousArguments, String s); +} diff --git a/src/de/steamwar/command/SWCommand.java b/src/de/steamwar/command/SWCommand.java new file mode 100644 index 0000000..026c74c --- /dev/null +++ b/src/de/steamwar/command/SWCommand.java @@ -0,0 +1,147 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * 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 de.steamwar.command; + +import de.steamwar.bungeecore.BungeeCore; +import de.steamwar.messages.ChatSender; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.TabExecutor; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; +import java.util.logging.Level; + +public class SWCommand extends AbstractSWCommand { + + static { + TypeUtils.init(); + } + + private Command command; + + private List defaultHelpMessages = new ArrayList<>(); + + protected SWCommand(String command) { + super(CommandSender.class, command); + } + + protected SWCommand(String command, String... aliases) { + super(CommandSender.class, command, aliases); + } + + @Override + protected void createAndSafeCommand(String command, String[] aliases) { + this.command = new TabCompletableCommand(command, aliases) { + @Override + public void execute(CommandSender commandSender, String[] strings) { + SWCommand.this.execute(commandSender, null, strings); + } + + @Override + public Iterable onTabComplete(CommandSender commandSender, String[] strings) { + return SWCommand.this.tabComplete(commandSender, null, strings); + } + }; + } + + private abstract static class TabCompletableCommand extends Command implements TabExecutor { + public TabCompletableCommand(String name, String... aliases) { + super(name, null, aliases); + } + } + + @Override + public void unregister() { + CommandRegistering.unregister(this.command); + } + + @Override + public void register() { + CommandRegistering.register(this.command); + } + + @Override + protected void commandSystemError(CommandSender sender, CommandFrameworkException e) { + BungeeCore.get().getLogger().log(Level.SEVERE, e.getMessage(), e); + ChatSender.of(sender).prefixless("COMMAND_SYSTEM_ERROR"); + } + + @Override + protected void commandSystemWarning(Supplier message) { + BungeeCore.get().getLogger().log(Level.WARNING, message); + } + + public void addDefaultHelpMessage(String message) { + defaultHelpMessages.add(message); + } + + @Register(help = true) + private void internalHelp(ProxiedPlayer p, String... args) { + ChatSender chatSender = ChatSender.of(p); + try { + chatSender.prefixless("COMMAND_HELP_HEAD", command.getName()); + defaultHelpMessages.forEach(chatSender::prefixless); + } catch (Exception e) { + BungeeCore.get().getLogger().log(Level.WARNING, "Failed to send help message", e); + return; + } + AtomicInteger atomicInteger = new AtomicInteger(); + if (args.length != 0) { + commandList.forEach(subCommand -> { + List tabCompletes = subCommand.tabComplete(p, args); + if (tabCompletes == null || tabCompletes.isEmpty()) { + atomicInteger.incrementAndGet(); + return; + } + boolean hasTabCompletes = tabCompletes.stream() + .anyMatch(s -> s.toLowerCase().startsWith(args[args.length - 1].toLowerCase())); + if (hasTabCompletes) { + send(chatSender, subCommand); + } else { + atomicInteger.incrementAndGet(); + } + }); + } + if (args.length == 0 || atomicInteger.get() == commandList.size()) { + commandList.forEach(subCommand -> { + if (subCommand.guardChecker == null || subCommand.guardChecker.guard(p, GuardCheckType.TAB_COMPLETE, new String[0], null) == GuardResult.ALLOWED) { + send(chatSender, subCommand); + } + }); + } + } + + private void send(ChatSender chatSender, SubCommand subCommand) { + try { + for (String s : subCommand.description) { + String hover = "§8/§e" + command.getName() + " " + String.join(" ", subCommand.subCommand); + String suggest = "/" + command.getName() + " " + String.join(" ", subCommand.subCommand); + chatSender.prefixless(s, hover, new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, suggest)); + } + } catch (Exception e) { + BungeeCore.get().getLogger().log(Level.WARNING, "Failed to send description of registered method '" + subCommand.method + "' with description '" + subCommand.description + "'", e); + } + } +} diff --git a/src/de/steamwar/command/TypeMapper.java b/src/de/steamwar/command/TypeMapper.java new file mode 100644 index 0000000..1d9cb72 --- /dev/null +++ b/src/de/steamwar/command/TypeMapper.java @@ -0,0 +1,29 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * 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 de.steamwar.command; + +import net.md_5.bungee.api.CommandSender; + +public interface TypeMapper extends AbstractTypeMapper { + /** + * The CommandSender can be null! + */ + T map(CommandSender commandSender, String[] previousArguments, String s); +} diff --git a/src/de/steamwar/command/TypeUtils.java b/src/de/steamwar/command/TypeUtils.java new file mode 100644 index 0000000..df779d9 --- /dev/null +++ b/src/de/steamwar/command/TypeUtils.java @@ -0,0 +1,36 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * 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 de.steamwar.command; + +import de.steamwar.bungeecore.sql.SteamwarUser; +import lombok.experimental.UtilityClass; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.stream.Collectors; + +@UtilityClass +public class TypeUtils { + + static void init() { + SWCommandUtils.addMapper(ProxiedPlayer.class, SWCommandUtils.createMapper(BungeeCord.getInstance()::getPlayer, (s) -> BungeeCord.getInstance().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList()))); + SWCommandUtils.addMapper(SteamwarUser.class, SWCommandUtils.createMapper(SteamwarUser::get, s -> BungeeCord.getInstance().getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList()))); + } +} diff --git a/src/de/steamwar/messages/BungeeCore.properties b/src/de/steamwar/messages/BungeeCore.properties index 2fd155e..45a4f05 100644 --- a/src/de/steamwar/messages/BungeeCore.properties +++ b/src/de/steamwar/messages/BungeeCore.properties @@ -1,3 +1,6 @@ +COMMAND_SYSTEM_ERROR = §cError executing the command! +COMMAND_HELP_HEAD=§7---=== (§e{0}§7) ===--- + PREFIX=§eSteam§8War» SPACER= TIMEFORMAT=dd.MM.yyyy HH:mm diff --git a/src/de/steamwar/messages/BungeeCore_de.properties b/src/de/steamwar/messages/BungeeCore_de.properties index f118020..21a7a55 100644 --- a/src/de/steamwar/messages/BungeeCore_de.properties +++ b/src/de/steamwar/messages/BungeeCore_de.properties @@ -1,3 +1,5 @@ +COMMAND_SYSTEM_ERROR = §cFehler beim Ausführen des Befehls! + PREFIX=§eSteam§8War» SPACER= TIMEFORMAT=dd.MM.yyyy HH:mm