Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Refactor built-in commands to use Brigadier (#1208)
* Refactor /velocity command to use Brigadier * Added default usage message and code cleanup * Reimplemented callback subcommand * Fixed execution of the callback subcommand when all permissions of the main command subcommands are denied * Migrated callback subcommand to its own command * Migrated server command * GList, Send and Server command cleanup --------- Co-authored-by: Adrian <adriangonzalesval@gmail.com>
Dieser Commit ist enthalten in:
Ursprung
c3583e182c
Commit
b9b11665b9
@ -37,6 +37,7 @@ import com.velocitypowered.api.util.Favicon;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.api.util.ProxyVersion;
|
||||
import com.velocitypowered.proxy.command.VelocityCommandManager;
|
||||
import com.velocitypowered.proxy.command.builtin.CallbackCommand;
|
||||
import com.velocitypowered.proxy.command.builtin.GlistCommand;
|
||||
import com.velocitypowered.proxy.command.builtin.SendCommand;
|
||||
import com.velocitypowered.proxy.command.builtin.ServerCommand;
|
||||
@ -223,8 +224,9 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||
cm.logChannelInformation();
|
||||
|
||||
// Initialize commands first
|
||||
commandManager.register("velocity", new VelocityCommand(this));
|
||||
commandManager.register("server", new ServerCommand(this));
|
||||
commandManager.register(VelocityCommand.create(this));
|
||||
commandManager.register(CallbackCommand.create());
|
||||
commandManager.register(ServerCommand.create(this));
|
||||
commandManager.register("shutdown", ShutdownCommand.command(this),
|
||||
"end", "stop");
|
||||
new GlistCommand(this).register();
|
||||
|
@ -33,7 +33,7 @@ import org.checkerframework.checker.index.qual.NonNegative;
|
||||
public class ClickCallbackManager {
|
||||
public static final ClickCallbackManager INSTANCE = new ClickCallbackManager();
|
||||
|
||||
static final String COMMAND = "/velocity callback ";
|
||||
static final String COMMAND = "/velocity:callback ";
|
||||
|
||||
private final Cache<UUID, RegisteredCallback> registrations = Caffeine.newBuilder()
|
||||
.expireAfter(new Expiry<UUID, RegisteredCallback>() {
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Velocity Contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.velocitypowered.proxy.command.builtin;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.velocitypowered.api.command.BrigadierCommand;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.proxy.adventure.ClickCallbackManager;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Callback Command.
|
||||
*/
|
||||
public final class CallbackCommand implements Command<CommandSource> {
|
||||
|
||||
@SuppressWarnings("checkstyle:MissingJavadocMethod")
|
||||
public static BrigadierCommand create() {
|
||||
final LiteralCommandNode<CommandSource> node = BrigadierCommand
|
||||
.literalArgumentBuilder("velocity:callback")
|
||||
.then(BrigadierCommand.requiredArgumentBuilder("id", StringArgumentType.word())
|
||||
.executes(new CallbackCommand()))
|
||||
.build();
|
||||
|
||||
return new BrigadierCommand(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int run(final CommandContext<CommandSource> context) {
|
||||
final String providedId = StringArgumentType.getString(context, "id");
|
||||
final UUID id;
|
||||
try {
|
||||
id = UUID.fromString(providedId);
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
ClickCallbackManager.INSTANCE.runCallback(context.getSource(), id);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
@ -20,12 +20,11 @@ package com.velocitypowered.proxy.command.builtin;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.velocitypowered.api.command.BrigadierCommand;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.permission.Tristate;
|
||||
@ -34,7 +33,6 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
@ -57,20 +55,19 @@ public class GlistCommand {
|
||||
* Registers this command.
|
||||
*/
|
||||
public void register() {
|
||||
LiteralCommandNode<CommandSource> totalNode = LiteralArgumentBuilder
|
||||
.<CommandSource>literal("glist")
|
||||
final LiteralArgumentBuilder<CommandSource> rootNode = BrigadierCommand
|
||||
.literalArgumentBuilder("glist")
|
||||
.requires(source ->
|
||||
source.getPermissionValue("velocity.command.glist") == Tristate.TRUE)
|
||||
.executes(this::totalCount)
|
||||
.build();
|
||||
ArgumentCommandNode<CommandSource, String> serverNode = RequiredArgumentBuilder
|
||||
.<CommandSource, String>argument(SERVER_ARG, StringArgumentType.string())
|
||||
.executes(this::totalCount);
|
||||
final ArgumentCommandNode<CommandSource, String> serverNode = BrigadierCommand
|
||||
.requiredArgumentBuilder(SERVER_ARG, StringArgumentType.string())
|
||||
.suggests((context, builder) -> {
|
||||
String argument = context.getArguments().containsKey(SERVER_ARG)
|
||||
final String argument = context.getArguments().containsKey(SERVER_ARG)
|
||||
? context.getArgument(SERVER_ARG, String.class)
|
||||
: "";
|
||||
for (RegisteredServer server : server.getAllServers()) {
|
||||
String serverName = server.getServerInfo().getName();
|
||||
final String serverName = server.getServerInfo().getName();
|
||||
if (serverName.regionMatches(true, 0, argument, 0, argument.length())) {
|
||||
builder.suggest(serverName);
|
||||
}
|
||||
@ -82,14 +79,14 @@ public class GlistCommand {
|
||||
})
|
||||
.executes(this::serverCount)
|
||||
.build();
|
||||
totalNode.addChild(serverNode);
|
||||
server.getCommandManager().register(new BrigadierCommand(totalNode));
|
||||
rootNode.then(serverNode);
|
||||
server.getCommandManager().register(new BrigadierCommand(rootNode));
|
||||
}
|
||||
|
||||
private int totalCount(final CommandContext<CommandSource> context) {
|
||||
final CommandSource source = context.getSource();
|
||||
sendTotalProxyCount(source);
|
||||
source.sendMessage(Identity.nil(),
|
||||
source.sendMessage(
|
||||
Component.translatable("velocity.command.glist-view-all", NamedTextColor.YELLOW));
|
||||
return 1;
|
||||
}
|
||||
@ -98,38 +95,42 @@ public class GlistCommand {
|
||||
final CommandSource source = context.getSource();
|
||||
final String serverName = getString(context, SERVER_ARG);
|
||||
if (serverName.equalsIgnoreCase("all")) {
|
||||
for (RegisteredServer server : BuiltinCommandUtil.sortedServerList(server)) {
|
||||
for (final RegisteredServer server : BuiltinCommandUtil.sortedServerList(server)) {
|
||||
sendServerPlayers(source, server, true);
|
||||
}
|
||||
sendTotalProxyCount(source);
|
||||
} else {
|
||||
Optional<RegisteredServer> registeredServer = server.getServer(serverName);
|
||||
if (!registeredServer.isPresent()) {
|
||||
source.sendMessage(Identity.nil(),
|
||||
CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
|
||||
final Optional<RegisteredServer> registeredServer = server.getServer(serverName);
|
||||
if (registeredServer.isEmpty()) {
|
||||
source.sendMessage(
|
||||
CommandMessages.SERVER_DOES_NOT_EXIST
|
||||
.arguments(Component.text(serverName)));
|
||||
return -1;
|
||||
}
|
||||
sendServerPlayers(source, registeredServer.get(), false);
|
||||
}
|
||||
return 1;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private void sendTotalProxyCount(CommandSource target) {
|
||||
int online = server.getPlayerCount();
|
||||
TranslatableComponent msg = online == 1
|
||||
? Component.translatable("velocity.command.glist-player-singular")
|
||||
: Component.translatable("velocity.command.glist-player-plural");
|
||||
target.sendMessage(msg.color(NamedTextColor.YELLOW)
|
||||
.args(Component.text(Integer.toString(online), NamedTextColor.GREEN)));
|
||||
final int online = server.getPlayerCount();
|
||||
final TranslatableComponent.Builder msg = Component.translatable()
|
||||
.key(online == 1
|
||||
? "velocity.command.glist-player-singular"
|
||||
: "velocity.command.glist-player-plural"
|
||||
).color(NamedTextColor.YELLOW)
|
||||
.arguments(Component.text(Integer.toString(online), NamedTextColor.GREEN));
|
||||
target.sendMessage(msg.build());
|
||||
}
|
||||
|
||||
private void sendServerPlayers(CommandSource target, RegisteredServer server, boolean fromAll) {
|
||||
List<Player> onServer = ImmutableList.copyOf(server.getPlayersConnected());
|
||||
private void sendServerPlayers(final CommandSource target,
|
||||
final RegisteredServer server, final boolean fromAll) {
|
||||
final List<Player> onServer = ImmutableList.copyOf(server.getPlayersConnected());
|
||||
if (onServer.isEmpty() && fromAll) {
|
||||
return;
|
||||
}
|
||||
|
||||
TextComponent.Builder builder = Component.text()
|
||||
final TextComponent.Builder builder = Component.text()
|
||||
.append(Component.text("[" + server.getServerInfo().getName() + "] ",
|
||||
NamedTextColor.DARK_AQUA))
|
||||
.append(Component.text("(" + onServer.size() + ")", NamedTextColor.GRAY))
|
||||
@ -137,7 +138,7 @@ public class GlistCommand {
|
||||
.resetStyle();
|
||||
|
||||
for (int i = 0; i < onServer.size(); i++) {
|
||||
Player player = onServer.get(i);
|
||||
final Player player = onServer.get(i);
|
||||
builder.append(Component.text(player.getUsername()));
|
||||
|
||||
if (i + 1 < onServer.size()) {
|
||||
@ -145,6 +146,6 @@ public class GlistCommand {
|
||||
}
|
||||
}
|
||||
|
||||
target.sendMessage(Identity.nil(), builder.build());
|
||||
target.sendMessage(builder.build());
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,12 @@
|
||||
|
||||
package com.velocitypowered.proxy.command.builtin;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import com.velocitypowered.api.command.BrigadierCommand;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.permission.Tristate;
|
||||
@ -51,20 +51,19 @@ public class SendCommand {
|
||||
* Registers this command.
|
||||
*/
|
||||
public void register() {
|
||||
LiteralCommandNode<CommandSource> totalNode = LiteralArgumentBuilder
|
||||
.<CommandSource>literal("send")
|
||||
final LiteralArgumentBuilder<CommandSource> rootNode = BrigadierCommand
|
||||
.literalArgumentBuilder("send")
|
||||
.requires(source ->
|
||||
source.getPermissionValue("velocity.command.send") == Tristate.TRUE)
|
||||
.executes(this::usage)
|
||||
.build();
|
||||
ArgumentCommandNode<CommandSource, String> playerNode = RequiredArgumentBuilder
|
||||
.<CommandSource, String>argument("player", StringArgumentType.word())
|
||||
.executes(this::usage);
|
||||
final RequiredArgumentBuilder<CommandSource, String> playerNode = BrigadierCommand
|
||||
.requiredArgumentBuilder(PLAYER_ARG, StringArgumentType.word())
|
||||
.suggests((context, builder) -> {
|
||||
String argument = context.getArguments().containsKey(PLAYER_ARG)
|
||||
final String argument = context.getArguments().containsKey(PLAYER_ARG)
|
||||
? context.getArgument(PLAYER_ARG, String.class)
|
||||
: "";
|
||||
for (Player player : server.getAllPlayers()) {
|
||||
String playerName = player.getUsername();
|
||||
for (final Player player : server.getAllPlayers()) {
|
||||
final String playerName = player.getUsername();
|
||||
if (playerName.regionMatches(true, 0, argument, 0, argument.length())) {
|
||||
builder.suggest(playerName);
|
||||
}
|
||||
@ -78,16 +77,15 @@ public class SendCommand {
|
||||
}
|
||||
return builder.buildFuture();
|
||||
})
|
||||
.executes(this::usage)
|
||||
.build();
|
||||
ArgumentCommandNode<CommandSource, String> serverNode = RequiredArgumentBuilder
|
||||
.<CommandSource, String>argument("server", StringArgumentType.word())
|
||||
.executes(this::usage);
|
||||
final ArgumentCommandNode<CommandSource, String> serverNode = BrigadierCommand
|
||||
.requiredArgumentBuilder(SERVER_ARG, StringArgumentType.word())
|
||||
.suggests((context, builder) -> {
|
||||
String argument = context.getArguments().containsKey(SERVER_ARG)
|
||||
final String argument = context.getArguments().containsKey(SERVER_ARG)
|
||||
? context.getArgument(SERVER_ARG, String.class)
|
||||
: "";
|
||||
for (RegisteredServer server : server.getAllServers()) {
|
||||
String serverName = server.getServerInfo().getName();
|
||||
for (final RegisteredServer server : server.getAllServers()) {
|
||||
final String serverName = server.getServerInfo().getName();
|
||||
if (serverName.regionMatches(true, 0, argument, 0, argument.length())) {
|
||||
builder.suggest(server.getServerInfo().getName());
|
||||
}
|
||||
@ -96,66 +94,68 @@ public class SendCommand {
|
||||
})
|
||||
.executes(this::send)
|
||||
.build();
|
||||
totalNode.addChild(playerNode);
|
||||
playerNode.addChild(serverNode);
|
||||
server.getCommandManager().register(new BrigadierCommand(totalNode));
|
||||
playerNode.then(serverNode);
|
||||
rootNode.then(playerNode.build());
|
||||
server.getCommandManager().register(new BrigadierCommand(rootNode.build()));
|
||||
}
|
||||
|
||||
private int usage(CommandContext<CommandSource> context) {
|
||||
private int usage(final CommandContext<CommandSource> context) {
|
||||
context.getSource().sendMessage(
|
||||
Component.translatable("velocity.command.send-usage", NamedTextColor.YELLOW)
|
||||
);
|
||||
return 1;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private int send(CommandContext<CommandSource> context) {
|
||||
String serverName = context.getArgument(SERVER_ARG, String.class);
|
||||
String player = context.getArgument(PLAYER_ARG, String.class);
|
||||
private int send(final CommandContext<CommandSource> context) {
|
||||
final String serverName = context.getArgument(SERVER_ARG, String.class);
|
||||
final String player = context.getArgument(PLAYER_ARG, String.class);
|
||||
|
||||
Optional<RegisteredServer> maybeServer = server.getServer(serverName);
|
||||
final Optional<RegisteredServer> maybeServer = server.getServer(serverName);
|
||||
|
||||
if (maybeServer.isEmpty()) {
|
||||
context.getSource().sendMessage(
|
||||
CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName))
|
||||
CommandMessages.SERVER_DOES_NOT_EXIST.arguments(Component.text(serverName))
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (server.getPlayer(player).isEmpty()
|
||||
final RegisteredServer targetServer = maybeServer.get();
|
||||
|
||||
final Optional<Player> maybePlayer = server.getPlayer(player);
|
||||
if (maybePlayer.isEmpty()
|
||||
&& !Objects.equals(player, "all")
|
||||
&& !Objects.equals(player, "current")) {
|
||||
context.getSource().sendMessage(
|
||||
CommandMessages.PLAYER_NOT_FOUND.args(Component.text(player))
|
||||
CommandMessages.PLAYER_NOT_FOUND.arguments(Component.text(player))
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Objects.equals(player, "all")) {
|
||||
for (Player p : server.getAllPlayers()) {
|
||||
p.createConnectionRequest(server.getServer(serverName).get()).fireAndForget();
|
||||
for (final Player p : server.getAllPlayers()) {
|
||||
p.createConnectionRequest(targetServer).fireAndForget();
|
||||
}
|
||||
return 1;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
if (Objects.equals(player, "current")) {
|
||||
if (!(context.getSource() instanceof Player)) {
|
||||
if (!(context.getSource() instanceof Player source)) {
|
||||
context.getSource().sendMessage(CommandMessages.PLAYERS_ONLY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Player source = (Player) context.getSource();
|
||||
Optional<ServerConnection> connectedServer = source.getCurrentServer();
|
||||
final Optional<ServerConnection> connectedServer = source.getCurrentServer();
|
||||
if (connectedServer.isPresent()) {
|
||||
for (Player p : connectedServer.get().getServer().getPlayersConnected()) {
|
||||
for (final Player p : connectedServer.get().getServer().getPlayersConnected()) {
|
||||
p.createConnectionRequest(maybeServer.get()).fireAndForget();
|
||||
}
|
||||
return 1;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
server.getPlayer(player).get().createConnectionRequest(
|
||||
maybeServer.get()).fireAndForget();
|
||||
return 1;
|
||||
// The player at this point must be present
|
||||
maybePlayer.orElseThrow().createConnectionRequest(targetServer).fireAndForget();
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,11 @@ package com.velocitypowered.proxy.command.builtin;
|
||||
|
||||
import static net.kyori.adventure.text.event.HoverEvent.showText;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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 com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
@ -30,8 +32,6 @@ import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
@ -41,50 +41,65 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||
/**
|
||||
* Implements Velocity's {@code /server} command.
|
||||
*/
|
||||
public class ServerCommand implements SimpleCommand {
|
||||
|
||||
public final class ServerCommand {
|
||||
private static final String SERVER_ARG = "server";
|
||||
public static final int MAX_SERVERS_TO_LIST = 50;
|
||||
private final ProxyServer server;
|
||||
|
||||
public ServerCommand(ProxyServer server) {
|
||||
this.server = server;
|
||||
@SuppressWarnings("checkstyle:MissingJavadocMethod")
|
||||
public static BrigadierCommand create(final ProxyServer server) {
|
||||
final LiteralCommandNode<CommandSource> node = BrigadierCommand
|
||||
.literalArgumentBuilder("server")
|
||||
.requires(src -> src instanceof Player
|
||||
&& src.getPermissionValue("velocity.command.server") != Tristate.FALSE)
|
||||
.executes(ctx -> {
|
||||
final Player player = (Player) ctx.getSource();
|
||||
outputServerInformation(player, server);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
.then(BrigadierCommand.requiredArgumentBuilder(SERVER_ARG, StringArgumentType.word())
|
||||
.suggests((ctx, builder) -> {
|
||||
final String argument = ctx.getArguments().containsKey(SERVER_ARG)
|
||||
? StringArgumentType.getString(ctx, SERVER_ARG)
|
||||
: "";
|
||||
for (final RegisteredServer sv : server.getAllServers()) {
|
||||
final String serverName = sv.getServerInfo().getName();
|
||||
if (serverName.regionMatches(true, 0, argument, 0, argument.length())) {
|
||||
builder.suggest(serverName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SimpleCommand.Invocation invocation) {
|
||||
final CommandSource source = invocation.source();
|
||||
final String[] args = invocation.arguments();
|
||||
|
||||
if (!(source instanceof Player)) {
|
||||
source.sendMessage(CommandMessages.PLAYERS_ONLY);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) source;
|
||||
if (args.length == 1) {
|
||||
return builder.buildFuture();
|
||||
})
|
||||
.executes(ctx -> {
|
||||
final Player player = (Player) ctx.getSource();
|
||||
// Trying to connect to a server.
|
||||
String serverName = args[0];
|
||||
Optional<RegisteredServer> toConnect = server.getServer(serverName);
|
||||
final String serverName = StringArgumentType.getString(ctx, SERVER_ARG);
|
||||
final Optional<RegisteredServer> toConnect = server.getServer(serverName);
|
||||
if (toConnect.isEmpty()) {
|
||||
player.sendMessage(CommandMessages.SERVER_DOES_NOT_EXIST.args(Component.text(serverName)));
|
||||
return;
|
||||
player.sendMessage(CommandMessages.SERVER_DOES_NOT_EXIST
|
||||
.arguments(Component.text(serverName)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
player.createConnectionRequest(toConnect.get()).fireAndForget();
|
||||
} else {
|
||||
outputServerInformation(player);
|
||||
}
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
).build();
|
||||
|
||||
return new BrigadierCommand(node);
|
||||
}
|
||||
|
||||
private void outputServerInformation(Player executor) {
|
||||
String currentServer = executor.getCurrentServer().map(ServerConnection::getServerInfo)
|
||||
.map(ServerInfo::getName).orElse("<unknown>");
|
||||
private static void outputServerInformation(final Player executor,
|
||||
final ProxyServer server) {
|
||||
final String currentServer = executor.getCurrentServer()
|
||||
.map(ServerConnection::getServerInfo)
|
||||
.map(ServerInfo::getName)
|
||||
.orElse("<unknown>");
|
||||
executor.sendMessage(Component.translatable(
|
||||
"velocity.command.server-current-server",
|
||||
NamedTextColor.YELLOW,
|
||||
Component.text(currentServer)));
|
||||
|
||||
List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
|
||||
final List<RegisteredServer> servers = BuiltinCommandUtil.sortedServerList(server);
|
||||
if (servers.size() > MAX_SERVERS_TO_LIST) {
|
||||
executor.sendMessage(Component.translatable(
|
||||
"velocity.command.server-too-many", NamedTextColor.RED));
|
||||
@ -92,12 +107,12 @@ public class ServerCommand implements SimpleCommand {
|
||||
}
|
||||
|
||||
// Assemble the list of servers as components
|
||||
TextComponent.Builder serverListBuilder = Component.text()
|
||||
final TextComponent.Builder serverListBuilder = Component.text()
|
||||
.append(Component.translatable("velocity.command.server-available",
|
||||
NamedTextColor.YELLOW))
|
||||
.append(Component.space());
|
||||
.appendSpace();
|
||||
for (int i = 0; i < servers.size(); i++) {
|
||||
RegisteredServer rs = servers.get(i);
|
||||
final RegisteredServer rs = servers.get(i);
|
||||
serverListBuilder.append(formatServerComponent(currentServer, rs));
|
||||
if (i != servers.size() - 1) {
|
||||
serverListBuilder.append(Component.text(", ", NamedTextColor.GRAY));
|
||||
@ -107,22 +122,22 @@ public class ServerCommand implements SimpleCommand {
|
||||
executor.sendMessage(serverListBuilder.build());
|
||||
}
|
||||
|
||||
private TextComponent formatServerComponent(String currentPlayerServer, RegisteredServer server) {
|
||||
ServerInfo serverInfo = server.getServerInfo();
|
||||
TextComponent serverTextComponent = Component.text(serverInfo.getName());
|
||||
private static TextComponent formatServerComponent(final String currentPlayerServer,
|
||||
final RegisteredServer server) {
|
||||
final ServerInfo serverInfo = server.getServerInfo();
|
||||
final TextComponent.Builder serverTextComponent = Component.text()
|
||||
.content(serverInfo.getName());
|
||||
|
||||
int connectedPlayers = server.getPlayersConnected().size();
|
||||
TranslatableComponent playersTextComponent;
|
||||
final int connectedPlayers = server.getPlayersConnected().size();
|
||||
final TranslatableComponent.Builder playersTextComponent = Component.translatable();
|
||||
if (connectedPlayers == 1) {
|
||||
playersTextComponent = Component.translatable(
|
||||
"velocity.command.server-tooltip-player-online");
|
||||
playersTextComponent.key("velocity.command.server-tooltip-player-online");
|
||||
} else {
|
||||
playersTextComponent = Component.translatable(
|
||||
"velocity.command.server-tooltip-players-online");
|
||||
playersTextComponent.key("velocity.command.server-tooltip-players-online");
|
||||
}
|
||||
playersTextComponent = playersTextComponent.args(Component.text(connectedPlayers));
|
||||
playersTextComponent.arguments(Component.text(connectedPlayers));
|
||||
if (serverInfo.getName().equals(currentPlayerServer)) {
|
||||
serverTextComponent = serverTextComponent.color(NamedTextColor.GREEN)
|
||||
serverTextComponent.color(NamedTextColor.GREEN)
|
||||
.hoverEvent(
|
||||
showText(
|
||||
Component.translatable("velocity.command.server-tooltip-current-server")
|
||||
@ -130,7 +145,7 @@ public class ServerCommand implements SimpleCommand {
|
||||
.append(playersTextComponent))
|
||||
);
|
||||
} else {
|
||||
serverTextComponent = serverTextComponent.color(NamedTextColor.GRAY)
|
||||
serverTextComponent.color(NamedTextColor.GRAY)
|
||||
.clickEvent(ClickEvent.runCommand("/server " + serverInfo.getName()))
|
||||
.hoverEvent(
|
||||
showText(
|
||||
@ -139,28 +154,6 @@ public class ServerCommand implements SimpleCommand {
|
||||
.append(playersTextComponent))
|
||||
);
|
||||
}
|
||||
return serverTextComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(final SimpleCommand.Invocation invocation) {
|
||||
final String[] currentArgs = invocation.arguments();
|
||||
Stream<String> possibilities = server.getAllServers().stream()
|
||||
.map(rs -> rs.getServerInfo().getName());
|
||||
|
||||
if (currentArgs.length == 0) {
|
||||
return possibilities.collect(Collectors.toList());
|
||||
} else if (currentArgs.length == 1) {
|
||||
return possibilities
|
||||
.filter(name -> name.regionMatches(true, 0, currentArgs[0], 0, currentArgs[0].length()))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final SimpleCommand.Invocation invocation) {
|
||||
return invocation.source().getPermissionValue("velocity.command.server") != Tristate.FALSE;
|
||||
return serverTextComponent.build();
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,16 @@
|
||||
|
||||
package com.velocitypowered.proxy.command.builtin;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
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 com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.plugin.PluginDescription;
|
||||
@ -31,7 +34,6 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.util.ProxyVersion;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import com.velocitypowered.proxy.adventure.ClickCallbackManager;
|
||||
import com.velocitypowered.proxy.util.InformationUtils;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
@ -44,14 +46,12 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
@ -63,129 +63,71 @@ import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
/**
|
||||
* Implements the {@code /velocity} command and friends.
|
||||
*/
|
||||
public class VelocityCommand implements SimpleCommand {
|
||||
public final class VelocityCommand {
|
||||
private static final String USAGE = "/velocity <%s>";
|
||||
|
||||
private interface SubCommand {
|
||||
|
||||
void execute(final CommandSource source, final String @NonNull [] args);
|
||||
|
||||
default List<String> suggest(final CommandSource source, final String @NonNull [] currentArgs) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
boolean hasPermission(final CommandSource source, final String @NonNull [] args);
|
||||
}
|
||||
|
||||
private final Map<String, SubCommand> commands;
|
||||
|
||||
/**
|
||||
* Initializes the command object for /velocity.
|
||||
*
|
||||
* @param server the Velocity server
|
||||
*/
|
||||
public VelocityCommand(VelocityServer server) {
|
||||
this.commands = ImmutableMap.<String, SubCommand>builder()
|
||||
.put("version", new Info(server))
|
||||
.put("plugins", new Plugins(server))
|
||||
.put("reload", new Reload(server))
|
||||
.put("dump", new Dump(server))
|
||||
.put("heap", new Heap())
|
||||
.put("callback", new Callback())
|
||||
@SuppressWarnings("checkstyle:MissingJavadocMethod")
|
||||
public static BrigadierCommand create(final VelocityServer server) {
|
||||
final LiteralCommandNode<CommandSource> dump = BrigadierCommand.literalArgumentBuilder("dump")
|
||||
.requires(source -> source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE)
|
||||
.executes(new Dump(server))
|
||||
.build();
|
||||
final LiteralCommandNode<CommandSource> heap = BrigadierCommand.literalArgumentBuilder("heap")
|
||||
.requires(source -> source.getPermissionValue("velocity.command.heap") == Tristate.TRUE)
|
||||
.executes(new Heap())
|
||||
.build();
|
||||
final LiteralCommandNode<CommandSource> info = BrigadierCommand.literalArgumentBuilder("info")
|
||||
.requires(source -> source.getPermissionValue("velocity.command.info") != Tristate.FALSE)
|
||||
.executes(new Info(server))
|
||||
.build();
|
||||
final LiteralCommandNode<CommandSource> plugins = BrigadierCommand
|
||||
.literalArgumentBuilder("plugins")
|
||||
.requires(source -> source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE)
|
||||
.executes(new Plugins(server))
|
||||
.build();
|
||||
final LiteralCommandNode<CommandSource> reload = BrigadierCommand
|
||||
.literalArgumentBuilder("reload")
|
||||
.requires(source -> source.getPermissionValue("velocity.command.reload") == Tristate.TRUE)
|
||||
.executes(new Reload(server))
|
||||
.build();
|
||||
}
|
||||
|
||||
private void usage(CommandSource source) {
|
||||
String availableCommands = commands.entrySet().stream()
|
||||
.filter(e -> e.getValue().hasPermission(source, new String[0]))
|
||||
.map(Map.Entry::getKey)
|
||||
final List<LiteralCommandNode<CommandSource>> commands = List
|
||||
.of(dump, heap, info, plugins, reload);
|
||||
return new BrigadierCommand(
|
||||
commands.stream()
|
||||
.reduce(
|
||||
BrigadierCommand.literalArgumentBuilder("velocity")
|
||||
.executes(ctx -> {
|
||||
final CommandSource source = ctx.getSource();
|
||||
final String availableCommands = commands.stream()
|
||||
.filter(e -> e.getRequirement().test(source))
|
||||
.map(LiteralCommandNode::getName)
|
||||
.collect(Collectors.joining("|"));
|
||||
String commandText = "/velocity <" + availableCommands + ">";
|
||||
final String commandText = USAGE.formatted(availableCommands);
|
||||
source.sendMessage(Component.text(commandText, NamedTextColor.RED));
|
||||
return Command.SINGLE_SUCCESS;
|
||||
})
|
||||
.requires(commands.stream()
|
||||
.map(CommandNode::getRequirement)
|
||||
.reduce(Predicate::or)
|
||||
.orElseThrow()),
|
||||
ArgumentBuilder::then,
|
||||
ArgumentBuilder::then
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SimpleCommand.Invocation invocation) {
|
||||
final CommandSource source = invocation.source();
|
||||
final String[] args = invocation.arguments();
|
||||
|
||||
if (args.length == 0) {
|
||||
usage(source);
|
||||
return;
|
||||
}
|
||||
|
||||
SubCommand command = commands.get(args[0].toLowerCase(Locale.US));
|
||||
if (command == null) {
|
||||
usage(source);
|
||||
return;
|
||||
}
|
||||
@SuppressWarnings("nullness")
|
||||
String[] actualArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
command.execute(source, actualArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(final SimpleCommand.Invocation invocation) {
|
||||
final CommandSource source = invocation.source();
|
||||
final String[] currentArgs = invocation.arguments();
|
||||
|
||||
if (currentArgs.length == 0) {
|
||||
return commands.entrySet().stream()
|
||||
.filter(e -> e.getValue().hasPermission(source, new String[0]))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
|
||||
if (currentArgs.length == 1) {
|
||||
return commands.entrySet().stream()
|
||||
.filter(e -> e.getKey().regionMatches(true, 0, currentArgs[0], 0,
|
||||
currentArgs[0].length()))
|
||||
.filter(e -> e.getValue().hasPermission(source, new String[0]))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
|
||||
SubCommand command = commands.get(currentArgs[0].toLowerCase(Locale.US));
|
||||
if (command == null) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
@SuppressWarnings("nullness")
|
||||
String[] actualArgs = Arrays.copyOfRange(currentArgs, 1, currentArgs.length);
|
||||
return command.suggest(source, actualArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final SimpleCommand.Invocation invocation) {
|
||||
final CommandSource source = invocation.source();
|
||||
final String[] args = invocation.arguments();
|
||||
|
||||
if (args.length == 0) {
|
||||
return commands.values().stream().anyMatch(e -> e.hasPermission(source, args));
|
||||
}
|
||||
SubCommand command = commands.get(args[0].toLowerCase(Locale.US));
|
||||
if (command == null) {
|
||||
return true;
|
||||
}
|
||||
@SuppressWarnings("nullness")
|
||||
String[] actualArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
return command.hasPermission(source, actualArgs);
|
||||
}
|
||||
|
||||
private static class Reload implements SubCommand {
|
||||
private record Reload(VelocityServer server) implements Command<CommandSource> {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(Reload.class);
|
||||
private final VelocityServer server;
|
||||
|
||||
private Reload(VelocityServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource source, String @NonNull [] args) {
|
||||
public int run(final CommandContext<CommandSource> context) {
|
||||
final CommandSource source = context.getSource();
|
||||
try {
|
||||
if (server.reloadConfiguration()) {
|
||||
source.sendMessage(Component.translatable("velocity.command.reload-success",
|
||||
@ -199,38 +141,28 @@ public class VelocityCommand implements SimpleCommand {
|
||||
source.sendMessage(Component.translatable("velocity.command.reload-failure",
|
||||
NamedTextColor.RED));
|
||||
}
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
private record Info(ProxyServer server) implements Command<CommandSource> {
|
||||
|
||||
private static final TextColor VELOCITY_COLOR = TextColor.color(0x09add3);
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||
return source.getPermissionValue("velocity.command.reload") == Tristate.TRUE;
|
||||
}
|
||||
}
|
||||
public int run(final CommandContext<CommandSource> context) {
|
||||
final CommandSource source = context.getSource();
|
||||
final ProxyVersion version = server.getVersion();
|
||||
|
||||
private static class Info implements SubCommand {
|
||||
|
||||
private static final TextColor VELOCITY_COLOR = TextColor.fromHexString("#09add3");
|
||||
private final ProxyServer server;
|
||||
|
||||
private Info(ProxyServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource source, String @NonNull [] args) {
|
||||
if (args.length != 0) {
|
||||
source.sendMessage(Component.text("/velocity version", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
ProxyVersion version = server.getVersion();
|
||||
|
||||
Component velocity = Component.text().content(version.getName() + " ")
|
||||
final Component velocity = Component.text()
|
||||
.content(version.getName() + " ")
|
||||
.decoration(TextDecoration.BOLD, true)
|
||||
.color(VELOCITY_COLOR)
|
||||
.append(Component.text(version.getVersion()).decoration(TextDecoration.BOLD, false))
|
||||
.append(Component.text()
|
||||
.content(version.getVersion())
|
||||
.decoration(TextDecoration.BOLD, false))
|
||||
.build();
|
||||
Component copyright = Component
|
||||
final Component copyright = Component
|
||||
.translatable("velocity.command.version-copyright",
|
||||
Component.text(version.getVendor()),
|
||||
Component.text(version.getName()));
|
||||
@ -238,14 +170,16 @@ public class VelocityCommand implements SimpleCommand {
|
||||
source.sendMessage(copyright);
|
||||
|
||||
if (version.getName().equals("Velocity")) {
|
||||
TextComponent embellishment = Component.text()
|
||||
.append(Component.text().content("velocitypowered.com")
|
||||
final TextComponent embellishment = Component.text()
|
||||
.append(Component.text()
|
||||
.content("velocitypowered.com")
|
||||
.color(NamedTextColor.GREEN)
|
||||
.clickEvent(
|
||||
ClickEvent.openUrl("https://velocitypowered.com"))
|
||||
.build())
|
||||
.append(Component.text(" - "))
|
||||
.append(Component.text().content("GitHub")
|
||||
.append(Component.text()
|
||||
.content("GitHub")
|
||||
.color(NamedTextColor.GREEN)
|
||||
.decoration(TextDecoration.UNDERLINED, true)
|
||||
.clickEvent(ClickEvent.openUrl(
|
||||
@ -254,59 +188,48 @@ public class VelocityCommand implements SimpleCommand {
|
||||
.build();
|
||||
source.sendMessage(embellishment);
|
||||
}
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
private record Plugins(ProxyServer server) implements Command<CommandSource> {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||
return source.getPermissionValue("velocity.command.info") != Tristate.FALSE;
|
||||
}
|
||||
}
|
||||
public int run(final CommandContext<CommandSource> context) {
|
||||
final CommandSource source = context.getSource();
|
||||
|
||||
private static class Plugins implements SubCommand {
|
||||
|
||||
private final ProxyServer server;
|
||||
|
||||
private Plugins(ProxyServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource source, String @NonNull [] args) {
|
||||
if (args.length != 0) {
|
||||
source.sendMessage(Component.text("/velocity plugins", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
List<PluginContainer> plugins = ImmutableList.copyOf(server.getPluginManager().getPlugins());
|
||||
int pluginCount = plugins.size();
|
||||
final List<PluginContainer> plugins = List.copyOf(server.getPluginManager().getPlugins());
|
||||
final int pluginCount = plugins.size();
|
||||
|
||||
if (pluginCount == 0) {
|
||||
source.sendMessage(Component.translatable("velocity.command.no-plugins",
|
||||
NamedTextColor.YELLOW));
|
||||
return;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
TextComponent.Builder listBuilder = Component.text();
|
||||
final TextComponent.Builder listBuilder = Component.text();
|
||||
for (int i = 0; i < pluginCount; i++) {
|
||||
PluginContainer plugin = plugins.get(i);
|
||||
final PluginContainer plugin = plugins.get(i);
|
||||
listBuilder.append(componentForPlugin(plugin.getDescription()));
|
||||
if (i + 1 < pluginCount) {
|
||||
listBuilder.append(Component.text(", "));
|
||||
}
|
||||
}
|
||||
|
||||
TranslatableComponent.Builder output = Component.translatable()
|
||||
final TranslatableComponent output = Component.translatable()
|
||||
.key("velocity.command.plugins-list")
|
||||
.color(NamedTextColor.YELLOW)
|
||||
.args(listBuilder.build());
|
||||
.arguments(listBuilder.build())
|
||||
.build();
|
||||
source.sendMessage(output);
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
|
||||
private TextComponent componentForPlugin(PluginDescription description) {
|
||||
String pluginInfo = description.getName().orElse(description.getId())
|
||||
final String pluginInfo = description.getName().orElse(description.getId())
|
||||
+ description.getVersion().map(v -> " " + v).orElse("");
|
||||
|
||||
TextComponent.Builder hoverText = Component.text().content(pluginInfo);
|
||||
final TextComponent.Builder hoverText = Component.text().content(pluginInfo);
|
||||
|
||||
description.getUrl().ifPresent(url -> {
|
||||
hoverText.append(Component.newline());
|
||||
@ -333,61 +256,51 @@ public class VelocityCommand implements SimpleCommand {
|
||||
hoverText.append(Component.text(pdesc));
|
||||
});
|
||||
|
||||
return Component.text(description.getId(), NamedTextColor.GRAY)
|
||||
.hoverEvent(HoverEvent.showText(hoverText.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||
return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE;
|
||||
return Component.text()
|
||||
.content(description.getId())
|
||||
.color(NamedTextColor.GRAY)
|
||||
.hoverEvent(HoverEvent.showText(hoverText.build()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Dump implements SubCommand {
|
||||
|
||||
private record Dump(ProxyServer server) implements Command<CommandSource> {
|
||||
private static final Logger logger = LogManager.getLogger(Dump.class);
|
||||
private final ProxyServer server;
|
||||
|
||||
private Dump(ProxyServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource source, String @NonNull [] args) {
|
||||
if (args.length != 0) {
|
||||
source.sendMessage(Component.text("/velocity dump", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
public int run(final CommandContext<CommandSource> context) {
|
||||
final CommandSource source = context.getSource();
|
||||
|
||||
Collection<RegisteredServer> allServers = ImmutableSet.copyOf(server.getAllServers());
|
||||
JsonObject servers = new JsonObject();
|
||||
for (RegisteredServer iter : allServers) {
|
||||
final Collection<RegisteredServer> allServers = Set.copyOf(server.getAllServers());
|
||||
final JsonObject servers = new JsonObject();
|
||||
for (final RegisteredServer iter : allServers) {
|
||||
servers.add(iter.getServerInfo().getName(),
|
||||
InformationUtils.collectServerInfo(iter));
|
||||
}
|
||||
JsonArray connectOrder = new JsonArray();
|
||||
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
|
||||
final JsonArray connectOrder = new JsonArray();
|
||||
final List<String> attemptedConnectionOrder = List.copyOf(
|
||||
server.getConfiguration().getAttemptConnectionOrder());
|
||||
for (String s : attemptedConnectionOrder) {
|
||||
for (final String s : attemptedConnectionOrder) {
|
||||
connectOrder.add(s);
|
||||
}
|
||||
|
||||
JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.getConfiguration());
|
||||
final JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.getConfiguration());
|
||||
proxyConfig.add("servers", servers);
|
||||
proxyConfig.add("connectOrder", connectOrder);
|
||||
proxyConfig.add("forcedHosts",
|
||||
InformationUtils.collectForcedHosts(server.getConfiguration()));
|
||||
|
||||
JsonObject dump = new JsonObject();
|
||||
final JsonObject dump = new JsonObject();
|
||||
dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion()));
|
||||
dump.add("platform", InformationUtils.collectEnvironmentInfo());
|
||||
dump.add("config", proxyConfig);
|
||||
dump.add("plugins", InformationUtils.collectPluginInfo(server));
|
||||
|
||||
Path dumpPath = Path.of("velocity-dump-"
|
||||
final Path dumpPath = Path.of("velocity-dump-"
|
||||
+ new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date())
|
||||
+ ".json");
|
||||
try (BufferedWriter bw = Files.newBufferedWriter(
|
||||
try (final BufferedWriter bw = Files.newBufferedWriter(
|
||||
dumpPath, StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW)) {
|
||||
bw.write(InformationUtils.toHumanReadableString(dump));
|
||||
|
||||
@ -397,32 +310,29 @@ public class VelocityCommand implements SimpleCommand {
|
||||
NamedTextColor.GREEN));
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to complete dump command, "
|
||||
+ "the executor was interrupted: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
+ "the executor was interrupted: " + e.getMessage(), e);
|
||||
source.sendMessage(Component.text(
|
||||
"We could not save the anonymized dump. Check the console for more details.",
|
||||
NamedTextColor.RED)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||
return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Heap SubCommand.
|
||||
*/
|
||||
public static class Heap implements SubCommand {
|
||||
public static final class Heap implements Command<CommandSource> {
|
||||
private static final Logger logger = LogManager.getLogger(Heap.class);
|
||||
private MethodHandle heapGenerator;
|
||||
private Consumer<CommandSource> heapConsumer;
|
||||
private final Path dir = Path.of("./dumps");
|
||||
|
||||
@Override
|
||||
public void execute(CommandSource source, String @NonNull [] args) {
|
||||
public int run(final CommandContext<CommandSource> context) throws CommandSyntaxException {
|
||||
final CommandSource source = context.getSource();
|
||||
|
||||
try {
|
||||
if (Files.notExists(dir)) {
|
||||
Files.createDirectories(dir);
|
||||
@ -480,39 +390,7 @@ public class VelocityCommand implements SimpleCommand {
|
||||
NamedTextColor.RED));
|
||||
logger.error("Could not write heap", t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(CommandSource source, String @NonNull [] args) {
|
||||
return source.getPermissionValue("velocity.command.heap") == Tristate.TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback SubCommand.
|
||||
*/
|
||||
public static class Callback implements SubCommand {
|
||||
|
||||
@Override
|
||||
public void execute(final CommandSource source, final String @NonNull [] args) {
|
||||
if (args.length != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID id;
|
||||
try {
|
||||
id = UUID.fromString(args[0]);
|
||||
} catch (final IllegalArgumentException ignored) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClickCallbackManager.INSTANCE.runCallback(source, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||
return true;
|
||||
return Command.SINGLE_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,6 +297,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
||||
// Inject commands from the proxy.
|
||||
final CommandGraphInjector<CommandSource> injector = server.getCommandManager().getInjector();
|
||||
injector.inject(rootNode, serverConn.getPlayer());
|
||||
rootNode.removeChildByName("velocity:callback");
|
||||
}
|
||||
|
||||
server.getEventManager().fire(
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren