Cloud for commands (#3808)

Co-authored-by: onebeastchris <github@onechris.mozmail.com>
This commit is contained in:
Konicai 2024-07-11 23:56:42 -05:00
parent 6002c9c7a1
commit 87ab51cb28
95 changed files with 2556 additions and 1879 deletions

View file

@ -1,5 +1,9 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
plugins {
application
}
val terminalConsoleVersion = "1.2.0"
val jlineVersion = "3.21.0"

View file

@ -42,7 +42,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.command.standalone.StandaloneCloudCommandManager;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo;
@ -69,7 +70,8 @@ import java.util.stream.Collectors;
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserCommandManager geyserCommandManager;
private StandaloneCloudCommandManager cloud;
private CommandRegistry commandRegistry;
private GeyserStandaloneConfiguration geyserConfig;
private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
private IGeyserPingPassthrough geyserPingPassthrough;
@ -222,13 +224,24 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
geyser = GeyserImpl.load(PlatformType.STANDALONE, this);
geyserCommandManager = new GeyserCommandManager(geyser);
geyserCommandManager.init();
boolean reloading = geyser.isReloading();
if (!reloading) {
// Currently there would be no significant benefit of re-initializing commands. Also, we would have to unsubscribe CommandRegistry.
// Fire GeyserDefineCommandsEvent after PreInitEvent, before PostInitEvent, for consistency with other bootstraps.
cloud = new StandaloneCloudCommandManager(geyser);
commandRegistry = new CommandRegistry(geyser, cloud);
}
GeyserImpl.start();
if (!reloading) {
// Event must be fired after CommandRegistry has subscribed its listener.
// Also, the subscription for the Permissions class is created when Geyser is initialized.
cloud.fireRegisterPermissionsEvent();
}
if (gui != null) {
gui.enableCommands(geyser.getScheduledThread(), geyserCommandManager);
gui.enableCommands(geyser.getScheduledThread(), commandRegistry);
}
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
@ -255,8 +268,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
@Override
public void onGeyserDisable() {
// We can re-register commands on standalone, so why not
GeyserImpl.getInstance().commandManager().getCommands().clear();
geyser.disable();
}
@ -277,8 +288,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
}
@Override
public GeyserCommandManager getGeyserCommandManager() {
return geyserCommandManager;
public CommandRegistry getCommandRegistry() {
return commandRegistry;
}
@Override

View file

@ -44,7 +44,9 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
@Override
protected void runCommand(String line) {
GeyserImpl.getInstance().commandManager().runCommand(this, line);
// don't block the terminal!
GeyserImpl geyser = GeyserImpl.getInstance();
geyser.getScheduledThread().execute(() -> geyser.commandRegistry().runCommand(this, line));
}
@Override

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.platform.standalone.gui;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
@ -271,15 +271,14 @@ public class GeyserStandaloneGUI {
}
/**
* Enable the command input box.
* Enables the command input box.
*
* @param executor the executor for running commands off the GUI thread
* @param commandManager the command manager to delegate commands to
* @param executor the executor that commands will be run on
* @param registry the command registry containing all current commands
*/
public void enableCommands(ScheduledExecutorService executor, GeyserCommandManager commandManager) {
public void enableCommands(ScheduledExecutorService executor, CommandRegistry registry) {
// we don't want to block the GUI thread with the command execution
// todo: once cloud is used, an AsynchronousCommandExecutionCoordinator can be used to avoid this scheduler
commandListener.handler = cmd -> executor.schedule(() -> commandManager.runCommand(logger, cmd), 0, TimeUnit.SECONDS);
commandListener.dispatcher = cmd -> executor.execute(() -> registry.runCommand(logger, cmd));
commandInput.setEnabled(true);
commandInput.requestFocusInWindow();
}
@ -344,13 +343,14 @@ public class GeyserStandaloneGUI {
private class CommandListener implements ActionListener {
private Consumer<String> handler;
private Consumer<String> dispatcher;
@Override
public void actionPerformed(ActionEvent e) {
String command = commandInput.getText();
// the headless variant of Standalone strips trailing whitespace for us - we need to manually
String command = commandInput.getText().stripTrailing();
appendConsole(command + "\n"); // show what was run in the console
handler.accept(command); // run the command
dispatcher.accept(command); // run the command
commandInput.setText(""); // clear the input
}
}