Skip to content

Commit bac1f10

Browse files
committed
Added proper command system
1 parent e0b5abe commit bac1f10

14 files changed

+432
-90
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ dependencies {
8282
exclude group: "com.google.code.gson", module: "gson"
8383
}
8484
includeInJar "net.lenni0451.commons:swing:1.7.1"
85+
includeInJar "net.lenni0451.commons:brigadier:1.7.1"
8586
includeInJar("net.raphimc.netminecraft:all:3.1.0") {
8687
exclude group: "com.google.code.gson", module: "gson"
8788
}

src/main/java/net/raphimc/viaproxy/ViaProxy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.netty.channel.group.DefaultChannelGroup;
2323
import io.netty.util.ResourceLeakDetector;
2424
import io.netty.util.concurrent.GlobalEventExecutor;
25+
import io.netty.util.internal.PlatformDependent;
2526
import net.lenni0451.classtransform.TransformerManager;
2627
import net.lenni0451.classtransform.additionalclassprovider.GuavaClassPathProvider;
2728
import net.lenni0451.classtransform.mixinstranslator.MixinsTranslator;
@@ -305,8 +306,8 @@ public static void stopProxy() {
305306

306307
private static void loadNetty() {
307308
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
308-
if (System.getProperty("io.netty.allocator.maxOrder") == null) {
309-
System.setProperty("io.netty.allocator.maxOrder", "9");
309+
if (System.getProperty("io.netty.allocator.type") == null) {
310+
System.setProperty("io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
310311
}
311312
MCPipeline.useOptimizedPipeline();
312313
CLIENT_CHANNELS = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

src/main/java/net/raphimc/viaproxy/cli/ConsoleHandler.java

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,10 @@
1717
*/
1818
package net.raphimc.viaproxy.cli;
1919

20-
import com.viaversion.viaversion.api.Via;
21-
import net.raphimc.viaproxy.ViaProxy;
22-
import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent;
23-
import net.raphimc.viaproxy.protocoltranslator.viaproxy.ConsoleCommandSender;
24-
import net.raphimc.viaproxy.util.ArrayHelper;
20+
import net.raphimc.viaproxy.cli.command.CommandManager;
2521
import net.raphimc.viaproxy.util.logging.Logger;
2622

2723
import java.io.IOException;
28-
import java.util.Arrays;
2924
import java.util.Scanner;
3025

3126
public class ConsoleHandler {
@@ -42,37 +37,13 @@ public static void hookConsole() {
4237
}
4338

4439
private static void listen() {
40+
final CommandManager commandManager = new CommandManager();
4541
final Scanner scanner = new Scanner(System.in);
4642
try {
4743
while (scanner.hasNextLine()) {
4844
final String line = scanner.nextLine();
4945
try {
50-
final String[] parts = line.split(" ");
51-
if (parts.length == 0) continue;
52-
final String command = parts[0];
53-
final ArrayHelper args = new ArrayHelper(Arrays.copyOfRange(parts, 1, parts.length));
54-
55-
if (command.equalsIgnoreCase("gc")) {
56-
System.gc();
57-
System.out.println("GC Done");
58-
} else if (command.equalsIgnoreCase("via") || command.equalsIgnoreCase("viaversion")) {
59-
Via.getManager().getCommandHandler().onCommand(new ConsoleCommandSender(), args.getAsArray());
60-
} else if (command.equalsIgnoreCase("exit")) {
61-
System.exit(0);
62-
} else if (command.equalsIgnoreCase("threaddump")) {
63-
System.out.println("Thread Dump:");
64-
for (Thread thread : Thread.getAllStackTraces().keySet()) {
65-
System.out.println("Thread: " + thread.getName() + " | State: " + thread.getState());
66-
for (StackTraceElement element : thread.getStackTrace()) System.out.println(" " + element.toString());
67-
}
68-
} else {
69-
if (ViaProxy.EVENT_MANAGER.call(new ConsoleCommandEvent(command, args.getAsArray())).isCancelled()) continue;
70-
System.out.println("Invalid Command!");
71-
System.out.println(" gc | Run the garbage collector");
72-
System.out.println(" exit | Shutdown ViaProxy");
73-
System.out.println(" via | Run a viaversion command");
74-
System.out.println(" threaddump | Print the stacktrace of all running threads");
75-
}
46+
commandManager.execute(line);
7647
} catch (Throwable e) {
7748
Logger.LOGGER.error("Error while handling console input", e);
7849
}

src/main/java/net/raphimc/viaproxy/cli/ProtocolVersionConverter.java

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.cli.command;
19+
20+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
21+
import net.lenni0451.commons.brigadier.CommandBuilder;
22+
import net.raphimc.viaproxy.cli.command.executor.CommandExecutor;
23+
24+
public abstract class Command implements CommandBuilder<CommandExecutor> {
25+
26+
private final String[] names;
27+
private final String description;
28+
private final String help;
29+
30+
public Command(final String name, final String description, final String help, final String... aliases) {
31+
this.names = new String[aliases.length + 1];
32+
this.names[0] = name;
33+
System.arraycopy(aliases, 0, this.names, 1, aliases.length);
34+
this.description = description;
35+
this.help = help;
36+
}
37+
38+
public abstract void register(final LiteralArgumentBuilder<CommandExecutor> builder);
39+
40+
public String getName() {
41+
return this.names[0];
42+
}
43+
44+
public String[] getNames() {
45+
return this.names;
46+
}
47+
48+
public String getDescription() {
49+
return this.description;
50+
}
51+
52+
public String getHelp() {
53+
return this.help;
54+
}
55+
56+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.cli.command;
19+
20+
import com.mojang.brigadier.CommandDispatcher;
21+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
22+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
23+
import net.lenni0451.commons.brigadier.CommandBuilder;
24+
import net.lenni0451.reflect.stream.RStream;
25+
import net.raphimc.viaproxy.ViaProxy;
26+
import net.raphimc.viaproxy.cli.command.executor.CommandExecutor;
27+
import net.raphimc.viaproxy.cli.command.executor.ConsoleCommandExecutor;
28+
import net.raphimc.viaproxy.cli.command.impl.*;
29+
import net.raphimc.viaproxy.plugins.events.ConsoleCommandEvent;
30+
import net.raphimc.viaproxy.util.logging.Logger;
31+
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.List;
35+
36+
public class CommandManager implements CommandBuilder<CommandExecutor> {
37+
38+
private final CommandDispatcher<CommandExecutor> dispatcher = new CommandDispatcher<>();
39+
private final List<Command> commands = new ArrayList<>();
40+
41+
// Core commands
42+
private final HelpCommand HelpCommand = new HelpCommand(this);
43+
private final StopCommand StopCommand = new StopCommand();
44+
private final ViaVersionCommand ViaVersionCommand = new ViaVersionCommand();
45+
46+
// Debugging commands
47+
private final GcCommand GcCommand = new GcCommand();
48+
private final ThreadDumpCommand ThreadDumpCommand = new ThreadDumpCommand();
49+
50+
public CommandManager() {
51+
RStream
52+
.of(this)
53+
.fields()
54+
.filter(field -> Command.class.isAssignableFrom(field.type()))
55+
.forEach(field -> {
56+
final Command command = field.get();
57+
try {
58+
for (String name : command.getNames()) {
59+
final LiteralArgumentBuilder<CommandExecutor> builder = literal(name);
60+
command.register(builder);
61+
this.dispatcher.register(builder);
62+
}
63+
this.commands.add(command);
64+
} catch (Throwable e) {
65+
Logger.LOGGER.error("Failed to register command " + command.getNames()[0], e);
66+
}
67+
});
68+
69+
this.dispatcher.findAmbiguities((parent, child, sibling, inputs) -> Logger.LOGGER.warn("Ambiguity between arguments {} and {} with inputs: {}", this.dispatcher.getPath(child), this.dispatcher.getPath(sibling), inputs));
70+
}
71+
72+
public void execute(final String message) {
73+
try {
74+
this.dispatcher.execute(message, ConsoleCommandExecutor.INSTANCE);
75+
} catch (CommandSyntaxException e) {
76+
if (e.getMessage().startsWith("Unknown command at position 0")) { // Compat for the old command API
77+
final String[] parts = message.split(" ");
78+
if (parts.length != 0) {
79+
final String command = parts[0];
80+
final String[] args = Arrays.copyOfRange(parts, 1, parts.length);
81+
if (ViaProxy.EVENT_MANAGER.call(new ConsoleCommandEvent(command, args)).isCancelled()) {
82+
return;
83+
}
84+
}
85+
Logger.LOGGER.error(e.getMessage().replace("Unknown command", "Unknown or incomplete command"));
86+
Logger.LOGGER.error("Type 'help' for help and a list of available commands.");
87+
} else if (e.getMessage().startsWith("Unknown command at position")) {
88+
Logger.LOGGER.error(e.getMessage().replace("Unknown command", "Unknown or incomplete command"));
89+
Logger.LOGGER.error("Type 'help' for help and a list of available commands.");
90+
} else {
91+
Logger.LOGGER.error(e.getMessage());
92+
}
93+
}
94+
}
95+
96+
public List<Command> getCommands() {
97+
return this.commands;
98+
}
99+
100+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.cli.command.executor;
19+
20+
public interface CommandExecutor {
21+
22+
void sendMessage(final String message);
23+
24+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.cli.command.executor;
19+
20+
import net.raphimc.viaproxy.util.logging.Logger;
21+
22+
public class ConsoleCommandExecutor implements CommandExecutor {
23+
24+
public static final ConsoleCommandExecutor INSTANCE = new ConsoleCommandExecutor();
25+
26+
private ConsoleCommandExecutor() {
27+
}
28+
29+
@Override
30+
public void sendMessage(final String message) {
31+
Logger.LOGGER.info(message);
32+
}
33+
34+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy
3+
* Copyright (C) 2021-2025 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.viaproxy.cli.command.impl;
19+
20+
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
21+
import net.raphimc.viaproxy.cli.command.Command;
22+
import net.raphimc.viaproxy.cli.command.executor.CommandExecutor;
23+
24+
public class GcCommand extends Command {
25+
26+
public GcCommand() {
27+
super("gc", "Perform JVM garbage collection", "gc");
28+
}
29+
30+
@Override
31+
public void register(final LiteralArgumentBuilder<CommandExecutor> builder) {
32+
builder.executes(context -> {
33+
System.gc();
34+
context.getSource().sendMessage("Performed garbage collection.");
35+
return 1;
36+
});
37+
}
38+
39+
}

0 commit comments

Comments
 (0)