mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-28 23:38:32 +01:00
Reintroduce GeyserDefineCommandsEvent and cleanup a few things
This commit is contained in:
parent
c07c7b9337
commit
e5337b6298
22 changed files with 355 additions and 107 deletions
|
@ -1,4 +1,7 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
api("org.geysermc.cumulus", "cumulus", Versions.cumulusVersion)
|
api("org.geysermc.cumulus", "cumulus", Versions.cumulusVersion)
|
||||||
api("org.geysermc.event", "events", Versions.eventsVersion)
|
api("org.geysermc.event", "events", Versions.eventsVersion) {
|
||||||
|
exclude(group = "com.google.guava", module = "guava")
|
||||||
|
exclude(group = "org.lanternpowered", module = "lmbda")
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -69,7 +69,7 @@ public class Geyser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the given api type. The api cannot be
|
* Registers the given api type. The api cannot be
|
||||||
* registered if {@link #registered()} is true as
|
* registered if {@link #isRegistered()} is true as
|
||||||
* an api has already been specified.
|
* an api has already been specified.
|
||||||
*
|
*
|
||||||
* @param api the api
|
* @param api the api
|
||||||
|
@ -88,7 +88,7 @@ public class Geyser {
|
||||||
*
|
*
|
||||||
* @return if the api has been registered
|
* @return if the api has been registered
|
||||||
*/
|
*/
|
||||||
public static boolean registered() {
|
public static boolean isRegistered() {
|
||||||
return api != null;
|
return api != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.api.Geyser;
|
import org.geysermc.api.Geyser;
|
||||||
import org.geysermc.api.GeyserApiBase;
|
import org.geysermc.api.GeyserApiBase;
|
||||||
import org.geysermc.geyser.api.command.CommandManager;
|
|
||||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||||
import org.geysermc.geyser.api.event.EventBus;
|
import org.geysermc.geyser.api.event.EventBus;
|
||||||
import org.geysermc.geyser.api.extension.ExtensionManager;
|
import org.geysermc.geyser.api.extension.ExtensionManager;
|
||||||
|
@ -66,15 +65,9 @@ public interface GeyserApi extends GeyserApiBase {
|
||||||
*
|
*
|
||||||
* @return the extension manager
|
* @return the extension manager
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
ExtensionManager extensionManager();
|
ExtensionManager extensionManager();
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the {@link CommandManager}.
|
|
||||||
*
|
|
||||||
* @return the command manager
|
|
||||||
*/
|
|
||||||
CommandManager commandManager();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an implementation for the specified API type.
|
* Provides an implementation for the specified API type.
|
||||||
*
|
*
|
||||||
|
@ -92,6 +85,7 @@ public interface GeyserApi extends GeyserApiBase {
|
||||||
*
|
*
|
||||||
* @return the event bus
|
* @return the event bus
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
EventBus eventBus();
|
EventBus eventBus();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,6 +94,7 @@ public interface GeyserApi extends GeyserApiBase {
|
||||||
*
|
*
|
||||||
* @return the default remote server used within Geyser
|
* @return the default remote server used within Geyser
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
RemoteServer defaultRemoteServer();
|
RemoteServer defaultRemoteServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,6 +103,7 @@ public interface GeyserApi extends GeyserApiBase {
|
||||||
*
|
*
|
||||||
* @return the listener used for Bedrock client connectins
|
* @return the listener used for Bedrock client connectins
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
BedrockListener bedrockListener();
|
BedrockListener bedrockListener();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,6 +111,7 @@ public interface GeyserApi extends GeyserApiBase {
|
||||||
*
|
*
|
||||||
* @return the current geyser api instance
|
* @return the current geyser api instance
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
static GeyserApi api() {
|
static GeyserApi api() {
|
||||||
return Geyser.api(GeyserApi.class);
|
return Geyser.api(GeyserApi.class);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ package org.geysermc.geyser.api.command;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.api.GeyserApi;
|
import org.geysermc.geyser.api.GeyserApi;
|
||||||
|
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -104,19 +106,39 @@ public interface Command {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T extends CommandSource> Command.Builder<T> builder(Class<T> sourceType) {
|
/**
|
||||||
return GeyserApi.api().provider(Builder.class, sourceType);
|
* Creates a new {@link Command.Builder} used to construct commands.
|
||||||
|
*
|
||||||
|
* @param extension the extension
|
||||||
|
* @param <T> the source type
|
||||||
|
* @return a new command builder used to construct commands
|
||||||
|
*/
|
||||||
|
static <T extends CommandSource> Command.Builder<T> builder(@NonNull Extension extension) {
|
||||||
|
return GeyserApi.api().provider(Builder.class, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Builder<T extends CommandSource> {
|
interface Builder<T extends CommandSource> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the source type to use for this command.
|
||||||
|
* <p>
|
||||||
|
* Command source types can be anything that extend
|
||||||
|
* {@link CommandSource}, such as {@link GeyserConnection}.
|
||||||
|
* This will guarantee that the source used in the executor
|
||||||
|
* is an instance of this source.
|
||||||
|
*
|
||||||
|
* @param sourceType the source type
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
Builder<T> source(@NonNull Class<? extends T> sourceType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the command name.
|
* Sets the command name.
|
||||||
*
|
*
|
||||||
* @param name the command name
|
* @param name the command name
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> name(String name);
|
Builder<T> name(@NonNull String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the command description.
|
* Sets the command description.
|
||||||
|
@ -124,7 +146,7 @@ public interface Command {
|
||||||
* @param description the command description
|
* @param description the command description
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> description(String description);
|
Builder<T> description(@NonNull String description);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the permission node.
|
* Sets the permission node.
|
||||||
|
@ -132,7 +154,7 @@ public interface Command {
|
||||||
* @param permission the permission node
|
* @param permission the permission node
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> permission(String permission);
|
Builder<T> permission(@NonNull String permission);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the aliases.
|
* Sets the aliases.
|
||||||
|
@ -140,7 +162,7 @@ public interface Command {
|
||||||
* @param aliases the aliases
|
* @param aliases the aliases
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> aliases(List<String> aliases);
|
Builder<T> aliases(@NonNull List<String> aliases);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if this command is designed to be used only by server operators.
|
* Sets if this command is designed to be used only by server operators.
|
||||||
|
@ -164,7 +186,7 @@ public interface Command {
|
||||||
* @param subCommands the subcommands
|
* @param subCommands the subcommands
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> subCommands(List<String> subCommands);
|
Builder<T> subCommands(@NonNull List<String> subCommands);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if this command is bedrock only.
|
* Sets if this command is bedrock only.
|
||||||
|
@ -180,13 +202,14 @@ public interface Command {
|
||||||
* @param executor the command executor
|
* @param executor the command executor
|
||||||
* @return the builder
|
* @return the builder
|
||||||
*/
|
*/
|
||||||
Builder<T> executor(CommandExecutor<T> executor);
|
Builder<T> executor(@NonNull CommandExecutor<T> executor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the command.
|
* Builds the command.
|
||||||
*
|
*
|
||||||
* @return the command
|
* @return the command
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
Command build();
|
Command build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,36 +23,35 @@
|
||||||
* @link https://github.com/GeyserMC/Geyser
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.geysermc.geyser.api.command;
|
package org.geysermc.geyser.api.event.lifecycle;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.event.Event;
|
||||||
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages Bedrock commands within Geyser.
|
* Called when commands are defined within Geyser.
|
||||||
|
*
|
||||||
|
* This event allows you to register new commands using the {@link #register(Command)}
|
||||||
|
* method and retrieve the default commands defined.
|
||||||
*/
|
*/
|
||||||
public abstract class CommandManager {
|
public interface GeyserDefineCommandsEvent extends Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the given {@link Command}.
|
* Registers the given {@link Command} into the Geyser
|
||||||
|
* command manager.
|
||||||
*
|
*
|
||||||
* @param command the command to register
|
* @param command the command to register
|
||||||
*/
|
*/
|
||||||
public abstract void register(@NonNull Command command);
|
void register(@NonNull Command command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters the given {@link Command}.
|
* Gets all the registered built-in {@link Command}s.
|
||||||
*
|
*
|
||||||
* @param command the command to unregister
|
* @return all the registered built-in commands
|
||||||
*/
|
|
||||||
public abstract void unregister(@NonNull Command command);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all the registered {@link Command}s.
|
|
||||||
*
|
|
||||||
* @return all the registered commands
|
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract Map<String, Command> commands();
|
Map<String, Command> commands();
|
||||||
}
|
}
|
|
@ -27,12 +27,11 @@ package org.geysermc.geyser.api.event.lifecycle;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.event.Event;
|
import org.geysermc.event.Event;
|
||||||
import org.geysermc.geyser.api.command.CommandManager;
|
|
||||||
import org.geysermc.geyser.api.event.EventBus;
|
import org.geysermc.geyser.api.event.EventBus;
|
||||||
import org.geysermc.geyser.api.extension.ExtensionManager;
|
import org.geysermc.geyser.api.extension.ExtensionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when Geyser is shutting down.
|
* Called when Geyser is shutting down.
|
||||||
*/
|
*/
|
||||||
public record GeyserShutdownEvent(@NonNull ExtensionManager extensionManager, @NonNull CommandManager commandManager, @NonNull EventBus eventBus) implements Event {
|
public record GeyserShutdownEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus eventBus) implements Event {
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,20 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the Geyser extension description
|
* Represents the description of an {@link Extension}.
|
||||||
*/
|
*/
|
||||||
public interface ExtensionDescription {
|
public interface ExtensionDescription {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the extension's name
|
* Gets the extension's id.
|
||||||
|
*
|
||||||
|
* @return the extension's id
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
String id();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the extension's name.
|
||||||
*
|
*
|
||||||
* @return the extension's name
|
* @return the extension's name
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +51,7 @@ public interface ExtensionDescription {
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the extension's main class
|
* Gets the extension's main class.
|
||||||
*
|
*
|
||||||
* @return the extension's main class
|
* @return the extension's main class
|
||||||
*/
|
*/
|
||||||
|
@ -51,7 +59,7 @@ public interface ExtensionDescription {
|
||||||
String main();
|
String main();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the extension's api version
|
* Gets the extension's api version.
|
||||||
*
|
*
|
||||||
* @return the extension's api version
|
* @return the extension's api version
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +67,7 @@ public interface ExtensionDescription {
|
||||||
String apiVersion();
|
String apiVersion();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the extension's description
|
* Gets the extension's description.
|
||||||
*
|
*
|
||||||
* @return the extension's description
|
* @return the extension's description
|
||||||
*/
|
*/
|
||||||
|
@ -67,7 +75,7 @@ public interface ExtensionDescription {
|
||||||
String version();
|
String version();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the extension's authors
|
* Gets the extension's authors.
|
||||||
*
|
*
|
||||||
* @return the extension's authors
|
* @return the extension's authors
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,6 +32,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserBootstrap;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
import org.geysermc.geyser.api.network.AuthType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
|
@ -49,6 +51,7 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@ -149,8 +152,15 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
||||||
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
|
this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", geyser, geyserCommandManager.getCommands()));
|
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", this.geyser, this.geyserCommandManager.getCommands()));
|
||||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyserext", geyser, geyserCommandManager.commands()));
|
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||||
|
Map<String, Command> commands = entry.getValue();
|
||||||
|
if (commands.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(entry.getKey().description().id(), this.geyser, commands));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,9 +32,11 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import me.lucko.commodore.CommodoreProvider;
|
import me.lucko.commodore.CommodoreProvider;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.command.PluginCommand;
|
import org.bukkit.command.PluginCommand;
|
||||||
import org.bukkit.permissions.Permission;
|
import org.bukkit.permissions.Permission;
|
||||||
import org.bukkit.permissions.PermissionDefault;
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.Constants;
|
import org.geysermc.geyser.Constants;
|
||||||
|
@ -42,6 +44,7 @@ import org.geysermc.geyser.GeyserBootstrap;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
||||||
import org.geysermc.geyser.api.command.Command;
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
import org.geysermc.geyser.api.network.AuthType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
|
@ -62,6 +65,8 @@ import org.geysermc.geyser.util.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -269,13 +274,32 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
||||||
|
|
||||||
PluginCommand geyserCommand = this.getCommand("geyser");
|
PluginCommand geyserCommand = this.getCommand("geyser");
|
||||||
geyserCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
geyserCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
||||||
PluginCommand geyserExtCommand = this.getCommand("geyserext");
|
|
||||||
geyserExtCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
CommandMap commandMap = GeyserSpigotCommandManager.getCommandMap();
|
||||||
|
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||||
|
Map<String, Command> commands = entry.getValue();
|
||||||
|
if (commands.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thanks again, Bukkit
|
||||||
|
try {
|
||||||
|
Constructor<PluginCommand> constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
|
||||||
|
PluginCommand pluginCommand = constructor.newInstance(entry.getKey().description().id(), this);
|
||||||
|
pluginCommand.setExecutor(new GeyserSpigotCommandExecutor(this.geyser, commands));
|
||||||
|
pluginCommand.setDescription("The main command for the " + entry.getKey().name() + " Geyser extension!");
|
||||||
|
commandMap.register(entry.getKey().description().id(), "geyserext", pluginCommand);
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
|
||||||
|
this.geyserLogger.error("Failed to construct PluginCommand for extension " + entry.getKey().description().name(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!INITIALIZED) {
|
if (!INITIALIZED) {
|
||||||
// Register permissions so they appear in, for example, LuckPerms' UI
|
// Register permissions so they appear in, for example, LuckPerms' UI
|
||||||
// Re-registering permissions throws an error
|
// Re-registering permissions throws an error
|
||||||
for (Map.Entry<String, Command> entry : geyserCommandManager.getCommands().entrySet()) {
|
for (Map.Entry<String, Command> entry : geyserCommandManager.commands().entrySet()) {
|
||||||
Command command = entry.getValue();
|
Command command = entry.getValue();
|
||||||
if (command.aliases().contains(entry.getKey())) {
|
if (command.aliases().contains(entry.getKey())) {
|
||||||
// Don't register aliases
|
// Don't register aliases
|
||||||
|
@ -286,6 +310,26 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
||||||
GeyserLocale.getLocaleStringLog(command.description()),
|
GeyserLocale.getLocaleStringLog(command.description()),
|
||||||
command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE));
|
command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register permissions for extension commands
|
||||||
|
for (Map.Entry<Extension, Map<String, Command>> commandEntry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||||
|
for (Map.Entry<String, Command> entry : commandEntry.getValue().entrySet()) {
|
||||||
|
Command command = entry.getValue();
|
||||||
|
if (command.aliases().contains(entry.getKey())) {
|
||||||
|
// Don't register aliases
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.permission().isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().addPermission(new Permission(command.permission(),
|
||||||
|
GeyserLocale.getLocaleStringLog(command.description()),
|
||||||
|
command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION,
|
Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION,
|
||||||
"Whether update notifications can be seen", PermissionDefault.OP));
|
"Whether update notifications can be seen", PermissionDefault.OP));
|
||||||
|
|
||||||
|
|
|
@ -65,4 +65,8 @@ public class GeyserSpigotCommandManager extends GeyserCommandManager {
|
||||||
Command cmd = COMMAND_MAP.getCommand(command.replace("/", ""));
|
Command cmd = COMMAND_MAP.getCommand(command.replace("/", ""));
|
||||||
return cmd != null ? cmd.getDescription() : "";
|
return cmd != null ? cmd.getDescription() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CommandMap getCommandMap() {
|
||||||
|
return COMMAND_MAP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,3 @@ commands:
|
||||||
geyser:
|
geyser:
|
||||||
description: The main command for Geyser.
|
description: The main command for Geyser.
|
||||||
usage: /geyser <subcommand>
|
usage: /geyser <subcommand>
|
||||||
geyserext:
|
|
||||||
description: The command any extensions can register to.
|
|
||||||
usage: /geyserext <subcommand>
|
|
|
@ -29,6 +29,8 @@ import com.google.inject.Inject;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserBootstrap;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||||
|
@ -50,6 +52,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Sponge", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Sponge", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||||
|
@ -122,7 +125,15 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
||||||
this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), geyser);
|
this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), geyser);
|
||||||
this.geyserCommandManager.init();
|
this.geyserCommandManager.init();
|
||||||
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
|
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
|
||||||
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.commands()), "geyserext");
|
|
||||||
|
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||||
|
Map<String, Command> commands = entry.getValue();
|
||||||
|
if (commands.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,6 +39,8 @@ import net.kyori.adventure.util.Codec;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserBootstrap;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
import org.geysermc.geyser.api.network.AuthType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
|
@ -58,6 +60,7 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||||
|
@ -159,7 +162,15 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
||||||
this.geyserCommandManager.init();
|
this.geyserCommandManager.init();
|
||||||
|
|
||||||
this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
||||||
this.commandManager.register("geyserext", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.commands()));
|
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||||
|
Map<String, Command> commands = entry.getValue();
|
||||||
|
if (commands.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commandManager.register(entry.getKey().description().id(), new GeyserVelocityCommandExecutor(this.geyser, commands));
|
||||||
|
}
|
||||||
|
|
||||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -547,7 +547,7 @@ public class GeyserImpl implements GeyserApi {
|
||||||
|
|
||||||
ResourcePack.PACKS.clear();
|
ResourcePack.PACKS.clear();
|
||||||
|
|
||||||
this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.commandManager(), this.eventBus));
|
this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus));
|
||||||
this.extensionManager.disableExtensions();
|
this.extensionManager.disableExtensions();
|
||||||
|
|
||||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
|
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
|
||||||
|
@ -572,11 +572,12 @@ public class GeyserImpl implements GeyserApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public GeyserExtensionManager extensionManager() {
|
public GeyserExtensionManager extensionManager() {
|
||||||
return this.extensionManager;
|
return this.extensionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NonNull
|
||||||
public GeyserCommandManager commandManager() {
|
public GeyserCommandManager commandManager() {
|
||||||
return this.bootstrap.getGeyserCommandManager();
|
return this.bootstrap.getGeyserCommandManager();
|
||||||
}
|
}
|
||||||
|
@ -587,15 +588,18 @@ public class GeyserImpl implements GeyserApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public EventBus eventBus() {
|
public EventBus eventBus() {
|
||||||
return this.eventBus;
|
return this.eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public RemoteServer defaultRemoteServer() {
|
public RemoteServer defaultRemoteServer() {
|
||||||
return getConfig().getRemote();
|
return getConfig().getRemote();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@NonNull
|
||||||
public BedrockListener bedrockListener() {
|
public BedrockListener bedrockListener() {
|
||||||
return getConfig().getBedrock();
|
return getConfig().getBedrock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,30 +33,46 @@ import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.command.Command;
|
import org.geysermc.geyser.api.command.Command;
|
||||||
import org.geysermc.geyser.api.command.CommandExecutor;
|
import org.geysermc.geyser.api.command.CommandExecutor;
|
||||||
import org.geysermc.geyser.api.command.CommandManager;
|
|
||||||
import org.geysermc.geyser.api.command.CommandSource;
|
import org.geysermc.geyser.api.command.CommandSource;
|
||||||
import org.geysermc.geyser.command.defaults.*;
|
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent;
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
|
import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.AdvancementsCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.ConnectionTestCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.DumpCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.ExtensionsCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.HelpCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.ListCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.OffhandCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.ReloadCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.SettingsCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.StatisticsCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.StopCommand;
|
||||||
|
import org.geysermc.geyser.command.defaults.VersionCommand;
|
||||||
|
import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl;
|
||||||
|
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public abstract class GeyserCommandManager extends CommandManager {
|
public abstract class GeyserCommandManager {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Map<String, Command> commands = new Object2ObjectOpenHashMap<>(12);
|
private final Map<String, Command> commands = new Object2ObjectOpenHashMap<>(12);
|
||||||
private final Map<String, Command> extensionCommands = new Object2ObjectOpenHashMap<>(0);
|
private final Map<Extension, Map<String, Command>> extensionCommands = new Object2ObjectOpenHashMap<>(0);
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
private final GeyserImpl geyser;
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", commands));
|
registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", this.commands));
|
||||||
registerBuiltInCommand(new ListCommand(geyser, "list", "geyser.commands.list.desc", "geyser.command.list"));
|
registerBuiltInCommand(new ListCommand(geyser, "list", "geyser.commands.list.desc", "geyser.command.list"));
|
||||||
registerBuiltInCommand(new ReloadCommand(geyser, "reload", "geyser.commands.reload.desc", "geyser.command.reload"));
|
registerBuiltInCommand(new ReloadCommand(geyser, "reload", "geyser.commands.reload.desc", "geyser.command.reload"));
|
||||||
registerBuiltInCommand(new OffhandCommand(geyser, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand"));
|
registerBuiltInCommand(new OffhandCommand(geyser, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand"));
|
||||||
|
@ -67,11 +83,32 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements"));
|
registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements"));
|
||||||
registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips"));
|
registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips"));
|
||||||
registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest"));
|
registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest"));
|
||||||
if (GeyserImpl.getInstance().getPlatformType() == PlatformType.STANDALONE) {
|
if (this.geyser.getPlatformType() == PlatformType.STANDALONE) {
|
||||||
registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop"));
|
registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop"));
|
||||||
}
|
}
|
||||||
|
|
||||||
register(new HelpCommand(geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp", "geyserext", extensionCommands));
|
if (this.geyser.extensionManager().extensions().size() > 0) {
|
||||||
|
registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions"));
|
||||||
|
}
|
||||||
|
|
||||||
|
GeyserDefineCommandsEvent defineCommandsEvent = new GeyserDefineCommandsEventImpl(this.commands) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(@NonNull Command command) {
|
||||||
|
if (!(command instanceof GeyserExtensionCommand extensionCommand)) {
|
||||||
|
throw new IllegalArgumentException("Expected GeyserExtensionCommand as part of command registration but got " + command + "! Did you use the Command builder properly?");
|
||||||
|
}
|
||||||
|
|
||||||
|
registerExtensionCommand(extensionCommand.extension(), extensionCommand);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.geyser.eventBus().fire(defineCommandsEvent);
|
||||||
|
|
||||||
|
// Register help commands for all extensions with commands
|
||||||
|
for (Map.Entry<Extension, Map<String, Command>> entry : this.extensionCommands.entrySet()) {
|
||||||
|
registerExtensionCommand(entry.getKey(), new HelpCommand(this.geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp", entry.getKey().description().id(), entry.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,9 +118,8 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
register(command, this.commands);
|
register(command, this.commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void registerExtensionCommand(@NonNull Extension extension, @NonNull Command command) {
|
||||||
public void register(@NonNull Command command) {
|
register(command, this.extensionCommands.computeIfAbsent(extension, e -> new HashMap<>()));
|
||||||
register(command, this.extensionCommands);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void register(Command command, Map<String, Command> commands) {
|
private void register(Command command, Map<String, Command> commands) {
|
||||||
|
@ -99,32 +135,30 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NotNull
|
||||||
public void unregister(@NonNull Command command) {
|
public Map<String, Command> commands() {
|
||||||
this.extensionCommands.remove(command.name(), command);
|
return Collections.unmodifiableMap(this.commands);
|
||||||
|
|
||||||
if (command.aliases().isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String alias : command.aliases()) {
|
|
||||||
this.extensionCommands.remove(alias, command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
public Map<Extension, Map<String, Command>> extensionCommands() {
|
||||||
public Map<String, Command> commands() {
|
|
||||||
return Collections.unmodifiableMap(this.extensionCommands);
|
return Collections.unmodifiableMap(this.extensionCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean runCommand(GeyserCommandSource sender, String command) {
|
public boolean runCommand(GeyserCommandSource sender, String command) {
|
||||||
boolean extensionCommand = command.startsWith("geyserext ");
|
Extension extension = null;
|
||||||
if (!command.startsWith("geyser ") && !extensionCommand) {
|
for (Extension loopedExtension : this.extensionCommands.keySet()) {
|
||||||
|
if (command.startsWith(loopedExtension.description().id() + " ")) {
|
||||||
|
extension = loopedExtension;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!command.startsWith("geyser ") && extension == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
command = command.trim().replace(extensionCommand ? "geyserext " : "geyser ", "");
|
command = command.trim().replace(extension != null ? extension.description().id() + " " : "geyser ", "");
|
||||||
String label;
|
String label;
|
||||||
String[] args;
|
String[] args;
|
||||||
|
|
||||||
|
@ -137,9 +171,9 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine };
|
args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine };
|
||||||
}
|
}
|
||||||
|
|
||||||
Command cmd = (extensionCommand ? this.extensionCommands : this.commands).get(label);
|
Command cmd = (extension != null ? this.extensionCommands.getOrDefault(extension, Collections.emptyMap()) : this.commands).get(label);
|
||||||
if (cmd == null) {
|
if (cmd == null) {
|
||||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.invalid"));
|
sender.sendMessage(GeyserLocale.getLocaleStringLog("geyser.commands.invalid"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +202,8 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public static class CommandBuilder<T extends CommandSource> implements Command.Builder<T> {
|
public static class CommandBuilder<T extends CommandSource> implements Command.Builder<T> {
|
||||||
private final Class<T> sourceType;
|
private final Extension extension;
|
||||||
|
private Class<? extends T> sourceType;
|
||||||
private String name;
|
private String name;
|
||||||
private String description = "";
|
private String description = "";
|
||||||
private String permission = "";
|
private String permission = "";
|
||||||
|
@ -179,22 +214,28 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
private boolean bedrockOnly;
|
private boolean bedrockOnly;
|
||||||
private CommandExecutor<T> executor;
|
private CommandExecutor<T> executor;
|
||||||
|
|
||||||
public CommandBuilder<T> name(String name) {
|
@Override
|
||||||
|
public Command.Builder<T> source(@NonNull Class<? extends T> sourceType) {
|
||||||
|
this.sourceType = sourceType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandBuilder<T> name(@NonNull String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder<T> description(String description) {
|
public CommandBuilder<T> description(@NonNull String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder<T> permission(String permission) {
|
public CommandBuilder<T> permission(@NonNull String permission) {
|
||||||
this.permission = permission;
|
this.permission = permission;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder<T> aliases(List<String> aliases) {
|
public CommandBuilder<T> aliases(@NonNull List<String> aliases) {
|
||||||
this.aliases = aliases;
|
this.aliases = aliases;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -210,7 +251,7 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder<T> subCommands(List<String> subCommands) {
|
public CommandBuilder<T> subCommands(@NonNull List<String> subCommands) {
|
||||||
this.subCommands = subCommands;
|
this.subCommands = subCommands;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -220,22 +261,27 @@ public abstract class GeyserCommandManager extends CommandManager {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder<T> executor(CommandExecutor<T> executor) {
|
public CommandBuilder<T> executor(@NonNull CommandExecutor<T> executor) {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeyserCommand build() {
|
@NonNull
|
||||||
|
public GeyserExtensionCommand build() {
|
||||||
if (this.name == null || this.name.isBlank()) {
|
if (this.name == null || this.name.isBlank()) {
|
||||||
throw new IllegalArgumentException("Command cannot be null or blank!");
|
throw new IllegalArgumentException("Command cannot be null or blank!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GeyserCommand(this.name, this.description, this.permission) {
|
if (this.sourceType == null) {
|
||||||
|
throw new IllegalArgumentException("Source type was not defined for command " + this.name + " in extension " + this.extension.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GeyserExtensionCommand(this.extension, this.name, this.description, this.permission) {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) {
|
public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) {
|
||||||
Class<T> sourceType = CommandBuilder.this.sourceType;
|
Class<? extends T> sourceType = CommandBuilder.this.sourceType;
|
||||||
CommandExecutor<T> executor = CommandBuilder.this.executor;
|
CommandExecutor<T> executor = CommandBuilder.this.executor;
|
||||||
if (sourceType.isInstance(session)) {
|
if (sourceType.isInstance(session)) {
|
||||||
executor.execute((T) session, this, args);
|
executor.execute((T) session, this, args);
|
||||||
|
|
|
@ -66,19 +66,19 @@ public class HelpCommand extends GeyserCommand {
|
||||||
String header = GeyserLocale.getPlayerLocaleString("geyser.commands.help.header", sender.locale(), page, maxPage);
|
String header = GeyserLocale.getPlayerLocaleString("geyser.commands.help.header", sender.locale(), page, maxPage);
|
||||||
sender.sendMessage(header);
|
sender.sendMessage(header);
|
||||||
|
|
||||||
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
this.commands.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
|
||||||
Command cmd = entry.getValue();
|
Command cmd = entry.getValue();
|
||||||
|
|
||||||
// Standalone hack-in since it doesn't have a concept of permissions
|
// Standalone hack-in since it doesn't have a concept of permissions
|
||||||
if (geyser.getPlatformType() == PlatformType.STANDALONE || sender.hasPermission(cmd.permission())) {
|
if (geyser.getPlatformType() == PlatformType.STANDALONE || sender.hasPermission(cmd.permission())) {
|
||||||
// Only list commands the player can actually run
|
// Only list commands the player can actually run
|
||||||
if (cmd.isBedrockOnly() && session == null) {
|
if (cmd.isBedrockOnly() && session == null) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sender.sendMessage(ChatColor.YELLOW + "/" + baseCommand + " " + entry.getKey() + ChatColor.WHITE + ": " +
|
sender.sendMessage(ChatColor.YELLOW + "/" + baseCommand + " " + entry.getKey() + ChatColor.WHITE + ": " +
|
||||||
GeyserLocale.getPlayerLocaleString(cmd.description(), sender.locale()));
|
GeyserLocale.getPlayerLocaleString(cmd.description(), sender.locale()));
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.event.type;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.geyser.api.command.Command;
|
||||||
|
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class GeyserDefineCommandsEventImpl implements GeyserDefineCommandsEvent {
|
||||||
|
private final Map<String, Command> commands;
|
||||||
|
|
||||||
|
public GeyserDefineCommandsEventImpl(Map<String, Command> commands) {
|
||||||
|
this.commands = commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Map<String, Command> commands() {
|
||||||
|
return Collections.unmodifiableMap(this.commands);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,11 +36,11 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class DefineCustomItemsEvent implements GeyserDefineCustomItemsEvent {
|
public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCustomItemsEvent {
|
||||||
private final Multimap<String, CustomItemData> customItems;
|
private final Multimap<String, CustomItemData> customItems;
|
||||||
private final List<NonVanillaCustomItemData> nonVanillaCustomItems;
|
private final List<NonVanillaCustomItemData> nonVanillaCustomItems;
|
||||||
|
|
||||||
public DefineCustomItemsEvent(Multimap<String, CustomItemData> customItems, List<NonVanillaCustomItemData> nonVanillaCustomItems) {
|
public GeyserDefineCustomItemsEventImpl(Multimap<String, CustomItemData> customItems, List<NonVanillaCustomItemData> nonVanillaCustomItems) {
|
||||||
this.customItems = customItems;
|
this.customItems = customItems;
|
||||||
this.nonVanillaCustomItems = nonVanillaCustomItems;
|
this.nonVanillaCustomItems = nonVanillaCustomItems;
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ import org.yaml.snakeyaml.Yaml;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public record GeyserExtensionDescription(String name, String main, String apiVersion, String version, List<String> authors) implements ExtensionDescription {
|
public record GeyserExtensionDescription(String id, String name, String main, String apiVersion, String version, List<String> authors) implements ExtensionDescription {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static GeyserExtensionDescription fromYaml(Reader reader) throws InvalidDescriptionException {
|
public static GeyserExtensionDescription fromYaml(Reader reader) throws InvalidDescriptionException {
|
||||||
DumperOptions dumperOptions = new DumperOptions();
|
DumperOptions dumperOptions = new DumperOptions();
|
||||||
|
@ -42,6 +42,11 @@ public record GeyserExtensionDescription(String name, String main, String apiVer
|
||||||
Yaml yaml = new Yaml(dumperOptions);
|
Yaml yaml = new Yaml(dumperOptions);
|
||||||
Map<String, Object> yamlMap = yaml.loadAs(reader, LinkedHashMap.class);
|
Map<String, Object> yamlMap = yaml.loadAs(reader, LinkedHashMap.class);
|
||||||
|
|
||||||
|
String id = ((String) yamlMap.get("id")).replaceAll("[^A-Za-z0-9 _.-]", "");
|
||||||
|
if (id.isBlank()) {
|
||||||
|
throw new InvalidDescriptionException("Invalid extension id, cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
String name = ((String) yamlMap.get("name")).replaceAll("[^A-Za-z0-9 _.-]", "");
|
String name = ((String) yamlMap.get("name")).replaceAll("[^A-Za-z0-9 _.-]", "");
|
||||||
if (name.isBlank()) {
|
if (name.isBlank()) {
|
||||||
throw new InvalidDescriptionException("Invalid extension name, cannot be empty");
|
throw new InvalidDescriptionException("Invalid extension name, cannot be empty");
|
||||||
|
@ -72,6 +77,6 @@ public record GeyserExtensionDescription(String name, String main, String apiVer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GeyserExtensionDescription(name, main, apiVersion, version, authors);
|
return new GeyserExtensionDescription(id, name, main, apiVersion, version, Collections.unmodifiableList(authors));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.extension.command;
|
||||||
|
|
||||||
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
|
import org.geysermc.geyser.command.GeyserCommand;
|
||||||
|
|
||||||
|
public abstract class GeyserExtensionCommand extends GeyserCommand {
|
||||||
|
private final Extension extension;
|
||||||
|
|
||||||
|
public GeyserExtensionCommand(Extension extension, String name, String description, String permission) {
|
||||||
|
super(name, description, permission);
|
||||||
|
|
||||||
|
this.extension = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Extension extension() {
|
||||||
|
return this.extension;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@
|
||||||
package org.geysermc.geyser.registry.loader;
|
package org.geysermc.geyser.registry.loader;
|
||||||
|
|
||||||
import org.geysermc.geyser.api.command.Command;
|
import org.geysermc.geyser.api.command.Command;
|
||||||
import org.geysermc.geyser.api.command.CommandSource;
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||||
|
@ -43,10 +43,9 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class ProviderRegistryLoader implements RegistryLoader<Map<Class<?>, ProviderSupplier>, Map<Class<?>, ProviderSupplier>> {
|
public class ProviderRegistryLoader implements RegistryLoader<Map<Class<?>, ProviderSupplier>, Map<Class<?>, ProviderSupplier>> {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Class<?>, ProviderSupplier> load(Map<Class<?>, ProviderSupplier> providers) {
|
public Map<Class<?>, ProviderSupplier> load(Map<Class<?>, ProviderSupplier> providers) {
|
||||||
providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Class<? extends CommandSource>) args[0]));
|
providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Extension) args[0]));
|
||||||
providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.CustomItemDataBuilder());
|
providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.CustomItemDataBuilder());
|
||||||
providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.CustomItemOptionsBuilder());
|
providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.CustomItemOptionsBuilder());
|
||||||
providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.NonVanillaCustomItemDataBuilder());
|
providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.NonVanillaCustomItemDataBuilder());
|
||||||
|
|
|
@ -48,11 +48,10 @@ import it.unimi.dsi.fastutil.objects.*;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserBootstrap;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomItemsEvent;
|
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||||
import org.geysermc.geyser.event.type.DefineCustomItemsEvent;
|
import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl;
|
||||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||||
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
||||||
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
|
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
|
||||||
|
@ -109,7 +108,7 @@ public class ItemRegistryPopulator {
|
||||||
});
|
});
|
||||||
|
|
||||||
nonVanillaCustomItems = new ObjectArrayList<>();
|
nonVanillaCustomItems = new ObjectArrayList<>();
|
||||||
GeyserImpl.getInstance().eventBus().fire(new DefineCustomItemsEvent(customItems, nonVanillaCustomItems) {
|
GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) {
|
||||||
@Override
|
@Override
|
||||||
public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) {
|
public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) {
|
||||||
if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) {
|
if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) {
|
||||||
|
|
Loading…
Reference in a new issue