Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Add console tab complete, shutdown command, gracefully kick players.
Dieser Commit ist enthalten in:
Ursprung
beb947cc3e
Commit
bb601dca4b
@ -10,6 +10,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.natives.util.Natives;
|
||||
import com.velocitypowered.network.ConnectionManager;
|
||||
import com.velocitypowered.proxy.command.ServerCommand;
|
||||
import com.velocitypowered.proxy.command.ShutdownCommand;
|
||||
import com.velocitypowered.proxy.command.VelocityCommand;
|
||||
import com.velocitypowered.proxy.config.VelocityConfiguration;
|
||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
||||
@ -21,6 +22,7 @@ import com.velocitypowered.proxy.util.EncryptionUtils;
|
||||
import com.velocitypowered.proxy.util.ServerMap;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import net.kyori.text.Component;
|
||||
import net.kyori.text.TextComponent;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import net.kyori.text.serializer.GsonComponentSerializer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -50,7 +52,8 @@ public class VelocityServer implements ProxyServer {
|
||||
private KeyPair serverKeyPair;
|
||||
private final ServerMap servers = new ServerMap();
|
||||
private final CommandManager commandManager = new CommandManager();
|
||||
private final AtomicBoolean shutdown = new AtomicBoolean(false);
|
||||
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
||||
private boolean shutdown = false;
|
||||
|
||||
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
||||
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
||||
@ -69,6 +72,7 @@ public class VelocityServer implements ProxyServer {
|
||||
private VelocityServer() {
|
||||
commandManager.registerCommand("velocity", new VelocityCommand());
|
||||
commandManager.registerCommand("server", new ServerCommand());
|
||||
commandManager.registerCommand("shutdown", new ShutdownCommand());
|
||||
}
|
||||
|
||||
public static VelocityServer getServer() {
|
||||
@ -136,13 +140,19 @@ public class VelocityServer implements ProxyServer {
|
||||
}
|
||||
|
||||
public boolean isShutdown() {
|
||||
return shutdown.get();
|
||||
return shutdown;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (!shutdown.compareAndSet(false, true)) return;
|
||||
if (!shutdownInProgress.compareAndSet(false, true)) return;
|
||||
logger.info("Shutting down the proxy...");
|
||||
|
||||
for (ConnectedPlayer player : ImmutableList.copyOf(connectionsByUuid.values())) {
|
||||
player.close(TextComponent.of("Proxy shutting down."));
|
||||
}
|
||||
|
||||
this.cm.shutdown();
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
public NettyHttpClient getHttpClient() {
|
||||
|
@ -1,12 +1,15 @@
|
||||
package com.velocitypowered.proxy.command;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.command.CommandExecutor;
|
||||
import com.velocitypowered.api.command.CommandInvoker;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommandManager {
|
||||
private final Map<String, CommandExecutor> executors = new HashMap<>();
|
||||
@ -45,4 +48,33 @@ public class CommandManager {
|
||||
throw new RuntimeException("Unable to invoke command " + cmdLine + " for " + invoker, e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> offerSuggestions(CommandInvoker invoker, String cmdLine) {
|
||||
Preconditions.checkNotNull(invoker, "invoker");
|
||||
Preconditions.checkNotNull(cmdLine, "cmdLine");
|
||||
|
||||
String[] split = cmdLine.split(" ", -1);
|
||||
if (split.length == 0) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
String command = split[0];
|
||||
if (split.length == 1) {
|
||||
return executors.keySet().stream()
|
||||
.filter(cmd -> cmd.regionMatches(true, 0, command, 0, command.length()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
String[] actualArgs = Arrays.copyOfRange(split, 1, split.length);
|
||||
CommandExecutor executor = executors.get(command);
|
||||
if (executor == null) {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
try {
|
||||
return executor.suggest(invoker, actualArgs);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to invoke suggestions for command " + command + " for " + invoker, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.velocitypowered.proxy.command;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.velocitypowered.api.command.CommandExecutor;
|
||||
import com.velocitypowered.api.command.CommandInvoker;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
@ -9,6 +10,7 @@ import net.kyori.text.TextComponent;
|
||||
import net.kyori.text.format.TextColor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -38,4 +40,20 @@ public class ServerCommand implements CommandExecutor {
|
||||
player.sendMessage(TextComponent.of("Available servers: " + serverList, TextColor.YELLOW));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(@Nonnull CommandInvoker invoker, @Nonnull String[] currentArgs) {
|
||||
if (currentArgs.length == 0) {
|
||||
return VelocityServer.getServer().getAllServers().stream()
|
||||
.map(ServerInfo::getName)
|
||||
.collect(Collectors.toList());
|
||||
} else if (currentArgs.length == 1) {
|
||||
return VelocityServer.getServer().getAllServers().stream()
|
||||
.map(ServerInfo::getName)
|
||||
.filter(name -> name.regionMatches(true, 0, currentArgs[0], 0, currentArgs[0].length()))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.velocitypowered.proxy.command;
|
||||
|
||||
import com.velocitypowered.api.command.CommandExecutor;
|
||||
import com.velocitypowered.api.command.CommandInvoker;
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import net.kyori.text.TextComponent;
|
||||
import net.kyori.text.format.TextColor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ShutdownCommand implements CommandExecutor {
|
||||
@Override
|
||||
public void execute(@Nonnull CommandInvoker invoker, @Nonnull String[] args) {
|
||||
if (invoker != VelocityServer.getServer().getConsoleCommandInvoker()) {
|
||||
invoker.sendMessage(TextComponent.of("You are not allowed to use this command.", TextColor.RED));
|
||||
return;
|
||||
}
|
||||
VelocityServer.getServer().shutdown();
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ public class VelocityCommand implements CommandExecutor {
|
||||
TextComponent thisIsVelocity = TextComponent.builder()
|
||||
.content("This is ")
|
||||
.append(TextComponent.of("Velocity " + implVersion, TextColor.DARK_AQUA))
|
||||
.append(TextComponent.of(", the next generation Minecraft: Java Edition proxy.", TextColor.WHITE))
|
||||
.append(TextComponent.of(", the next generation Minecraft: Java Edition proxy.").resetStyle())
|
||||
.build();
|
||||
TextComponent velocityInfo = TextComponent.builder()
|
||||
.content("Copyright 2018 Velocity Contributors. Velocity is freely licensed under the terms of the " +
|
||||
@ -28,7 +28,7 @@ public class VelocityCommand implements CommandExecutor {
|
||||
.color(TextColor.GREEN)
|
||||
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.velocitypowered.com"))
|
||||
.build())
|
||||
.append(TextComponent.of(" or the ", TextColor.WHITE))
|
||||
.append(TextComponent.of(" or the ").resetStyle())
|
||||
.append(TextComponent.builder("Velocity GitHub")
|
||||
.color(TextColor.GREEN)
|
||||
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://github.com/astei/velocity"))
|
||||
|
@ -1,9 +1,12 @@
|
||||
package com.velocitypowered.proxy.console;
|
||||
|
||||
import com.velocitypowered.proxy.VelocityServer;
|
||||
import net.kyori.text.TextComponent;
|
||||
import net.kyori.text.format.TextColor;
|
||||
import net.minecrell.terminalconsole.SimpleTerminalConsole;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
import org.jline.reader.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class VelocityConsole extends SimpleTerminalConsole {
|
||||
|
||||
@ -16,8 +19,14 @@ public final class VelocityConsole extends SimpleTerminalConsole {
|
||||
@Override
|
||||
protected LineReader buildReader(LineReaderBuilder builder) {
|
||||
return super.buildReader(builder
|
||||
.appName("Velocity")
|
||||
// TODO: Command completion
|
||||
.appName("Velocity")
|
||||
.completer((reader, parsedLine, list) -> {
|
||||
List<String> offers = server.getCommandManager().offerSuggestions(server.getConsoleCommandInvoker(), parsedLine.line());
|
||||
for (String offer : offers) {
|
||||
if (offer.isEmpty()) continue;
|
||||
list.add(new Candidate(offer));
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -28,7 +37,9 @@ public final class VelocityConsole extends SimpleTerminalConsole {
|
||||
|
||||
@Override
|
||||
protected void runCommand(String command) {
|
||||
this.server.getCommandManager().execute(this.server.getConsoleCommandInvoker(), command);
|
||||
if (!this.server.getCommandManager().execute(this.server.getConsoleCommandInvoker(), command)) {
|
||||
server.getConsoleCommandInvoker().sendMessage(TextComponent.of("Command not found.", TextColor.RED));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren