/* * This file is a part of the SteamWar software. * * Copyright (C) 2025 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 com.velocitypowered.api.command.SimpleCommand; import de.steamwar.messages.Chatter; import de.steamwar.messages.Message; import de.steamwar.sql.UserPerm; import de.steamwar.velocitycore.VelocityCore; import de.steamwar.velocitycore.discord.DiscordBot; import lombok.Getter; import net.kyori.adventure.text.event.ClickEvent; import java.util.ArrayList; import java.util.Arrays; 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 final String name; @Getter private final UserPerm permission; private final String[] aliases; private SimpleCommand command; private final List defaultHelpMessages = new ArrayList<>(); protected SWCommand(String command, String... aliases) { this(command, null, aliases); } protected SWCommand(String command, UserPerm permission, String... aliases) { super(Chatter.class, command, aliases); this.name = command; this.permission = permission; this.aliases = aliases; create = true; createAndSafeCommand(command, aliases); unregister(); register(); } public void execute(Chatter sender, String[] args) { execute(sender, null, args); } private boolean create = false; @Override protected void createAndSafeCommand(String command, String[] aliases) { if (!create) return; this.command = new SimpleCommand() { @Override public void execute(Invocation invocation) { SWCommand.this.execute(Chatter.of(invocation.source()), invocation.alias(), invocation.arguments()); } @Override public List suggest(Invocation invocation) { String[] args = invocation.arguments(); if (args.length == 0) args = new String[]{""}; return SWCommand.this.tabComplete(Chatter.of(invocation.source()), invocation.alias(), args); } @Override public boolean hasPermission(Invocation invocation) { return permission == null || Chatter.of(invocation.source()).user().perms().contains(permission); } }; } @Override public void unregister() { if (command == null) return; VelocityCore.getProxy().getCommandManager().unregister(name); DiscordBot.getCommands().remove(name); } @Override public void register() { if (command == null) return; VelocityCore.getProxy().getCommandManager().register(VelocityCore.getProxy().getCommandManager().metaBuilder(name).aliases(aliases).plugin(VelocityCore.get()).build(), command); DiscordBot.getCommands().put(name, this); } @Override protected void commandSystemError(Chatter sender, CommandFrameworkException e) { VelocityCore.getLogger().log(Level.SEVERE, e.getMessage(), e); sender.prefixless("COMMAND_SYSTEM_ERROR"); } @Override protected void commandSystemWarning(Supplier message) { VelocityCore.getLogger().log(Level.WARNING, message); } public void addDefaultHelpMessage(String message) { defaultHelpMessages.add(message); } @Override protected void sendMessage(Chatter sender, String message, Object[] args) { sender.system(message, args); } @Register(noTabComplete = true) public void internalHelp(Chatter sender, String... args) { try { sender.prefixless("COMMAND_HELP_HEAD", name); defaultHelpMessages.forEach(sender::prefixless); } catch (Exception e) { VelocityCore.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(sender, 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(sender, subCommand); } else { atomicInteger.incrementAndGet(); } }); } if (args.length == 0 || atomicInteger.get() == commandList.size()) { commandList.forEach(subCommand -> { if (subCommand.validator == null || subCommand.validator.validate(sender, sender, (s, args1) -> { })) { send(sender, subCommand); } }); } } private void send(Chatter chatter, SubCommand subCommand) { try { for (String s : subCommand.description) { String hover = "§8/§e" + name + " " + String.join(" ", subCommand.subCommand); chatter.prefixless(s, new Message("PLAIN_STRING", hover), ClickEvent.suggestCommand("/" + name + " " + String.join(" ", subCommand.subCommand))); } } catch (Exception e) { VelocityCore.getLogger().log(Level.WARNING, "Failed to send description of registered method '%s' with description '%s'".formatted(subCommand.method, Arrays.toString(subCommand.description)), e); } } }