mirror of https://github.com/GeyserMC/Geyser.git
Initial start on cloud
This commit is contained in:
parent
246ebddc78
commit
db5ccff9e5
|
@ -26,6 +26,10 @@
|
|||
package org.geysermc.geyser.api.command;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents an instance capable of sending commands.
|
||||
|
@ -64,6 +68,13 @@ public interface CommandSource {
|
|||
*/
|
||||
boolean isConsole();
|
||||
|
||||
/**
|
||||
* todo: commands
|
||||
*/
|
||||
Optional<UUID> playerUuid();
|
||||
|
||||
Optional<? extends Connection> connection();
|
||||
|
||||
/**
|
||||
* Returns the locale of the command source.
|
||||
*
|
||||
|
|
|
@ -107,6 +107,14 @@ public interface Extension extends EventRegistrar {
|
|||
return this.extensionLoader().description(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: commands
|
||||
*/
|
||||
@NonNull
|
||||
default String rootCommand() {
|
||||
return this.description().id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extension's logger
|
||||
*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
dependencies {
|
||||
api(projects.core)
|
||||
|
||||
implementation(libs.cloud.bungee)
|
||||
implementation(libs.adventure.text.serializer.bungeecord)
|
||||
}
|
||||
|
||||
|
@ -8,6 +9,7 @@ platformRelocate("net.md_5.bungee.jni")
|
|||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("io.netty.channel.kqueue") // This is not used because relocating breaks natives, but we must include it or else we get ClassDefNotFound
|
||||
platformRelocate("net.kyori")
|
||||
platformRelocate("cloud.commandframework")
|
||||
|
||||
// These dependencies are already present on the platform
|
||||
provided(libs.bungeecord.proxy)
|
||||
|
|
|
@ -25,8 +25,12 @@
|
|||
|
||||
package org.geysermc.geyser.platform.bungeecord;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.bungee.BungeeCommandManager;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import io.netty.channel.Channel;
|
||||
import net.md_5.bungee.BungeeCord;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
|
@ -34,14 +38,13 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
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.GeyserCommandSource;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor;
|
||||
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -54,7 +57,6 @@ import java.net.SocketAddress;
|
|||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -174,19 +176,16 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
|
|||
this.geyserInjector = new GeyserBungeeInjector(this);
|
||||
this.geyserInjector.initializeLocalChannel(this);
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
|
||||
CommandManager<GeyserCommandSource> cloud = new BungeeCommandManager<>(
|
||||
this,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
BungeeCommandSource::new,
|
||||
origin -> (CommandSender) origin.handle()
|
||||
);
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser, cloud);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", this.geyser, this.geyserCommandManager.getCommands()));
|
||||
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));
|
||||
}
|
||||
|
||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||
this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
|||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeCommandSource implements GeyserCommandSource {
|
||||
|
||||
|
@ -71,6 +73,14 @@ public class BungeeCommandSource implements GeyserCommandSource {
|
|||
return !(handle instanceof ProxiedPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
if (handle instanceof ProxiedPlayer player) {
|
||||
return Optional.of(player.getUniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String locale() {
|
||||
if (handle instanceof ProxiedPlayer player) {
|
||||
|
@ -87,4 +97,9 @@ public class BungeeCommandSource implements GeyserCommandSource {
|
|||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* 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.platform.bungeecord.command;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeyserBungeeCommandExecutor extends Command implements TabExecutor {
|
||||
private final GeyserCommandExecutor commandExecutor;
|
||||
|
||||
public GeyserBungeeCommandExecutor(String name, GeyserImpl geyser, Map<String, org.geysermc.geyser.api.command.Command> commands) {
|
||||
super(name);
|
||||
|
||||
this.commandExecutor = new GeyserCommandExecutor(geyser, commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender, String[] args) {
|
||||
BungeeCommandSource commandSender = new BungeeCommandSource(sender);
|
||||
GeyserSession session = this.commandExecutor.getGeyserSession(commandSender);
|
||||
|
||||
if (args.length > 0) {
|
||||
GeyserCommand command = this.commandExecutor.getCommand(args[0]);
|
||||
if (command != null) {
|
||||
if (!sender.hasPermission(command.permission())) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.locale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return;
|
||||
}
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.locale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return;
|
||||
}
|
||||
command.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
} else {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale());
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
}
|
||||
} else {
|
||||
this.commandExecutor.getCommand("help").execute(session, commandSender, new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return commandExecutor.tabComplete(new BungeeCommandSource(sender));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,9 @@ dependencies {
|
|||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
modImplementation(libs.fabric.api)
|
||||
|
||||
modImplementation(libs.cloud.fabric)
|
||||
include(libs.cloud.fabric)
|
||||
|
||||
// This should be in the libs TOML, but something about modImplementation AND include just doesn't work
|
||||
include(modImplementation("me.lucko", "fabric-permissions-api", "0.2-SNAPSHOT"))
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
|
||||
package org.geysermc.geyser.platform.fabric;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.fabric.FabricClientCommandManager;
|
||||
import cloud.commandframework.fabric.FabricCommandManager;
|
||||
import cloud.commandframework.fabric.FabricServerCommandManager;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
|
@ -33,22 +37,21 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
|||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor;
|
||||
import org.geysermc.geyser.platform.fabric.command.FabricCommandSource;
|
||||
import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
|
@ -59,7 +62,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -144,26 +146,16 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
|
|||
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
|
||||
CommandManager<GeyserCommandSource> cloud = new FabricServerCommandManager<>(
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
FabricCommandSource::new,
|
||||
source -> (CommandSourceStack) source.handle()
|
||||
);
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser, cloud);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
this.geyserWorldManager = new GeyserFabricWorldManager(server);
|
||||
|
||||
// Start command building
|
||||
// Set just "geyser" as the help command
|
||||
GeyserFabricCommandExecutor helpExecutor = new GeyserFabricCommandExecutor(geyser,
|
||||
(GeyserCommand) geyser.commandManager().getCommands().get("help"));
|
||||
LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("geyser").executes(helpExecutor);
|
||||
|
||||
// Register all subcommands as valid
|
||||
for (Map.Entry<String, Command> command : geyser.commandManager().getCommands().entrySet()) {
|
||||
GeyserFabricCommandExecutor executor = new GeyserFabricCommandExecutor(geyser, (GeyserCommand) command.getValue());
|
||||
builder.then(Commands.literal(command.getKey())
|
||||
.executes(executor)
|
||||
// Could also test for Bedrock but depending on when this is called it may backfire
|
||||
.requires(executor::testPermission));
|
||||
}
|
||||
server.getCommands().getDispatcher().register(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -257,7 +249,7 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
|
|||
}
|
||||
|
||||
public void setReloading(boolean reloading) {
|
||||
this.reloading = reloading;
|
||||
this.reloading = reloading; // todo: commands
|
||||
}
|
||||
|
||||
public static GeyserFabricMod getInstance() {
|
||||
|
|
|
@ -28,13 +28,13 @@ package org.geysermc.geyser.platform.fabric;
|
|||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.platform.fabric.command.FabricCommandSender;
|
||||
import org.geysermc.geyser.platform.fabric.command.FabricCommandSource;
|
||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||
|
||||
public final class GeyserFabricUpdateListener {
|
||||
public static void onPlayReady(ServerGamePacketListenerImpl handler) {
|
||||
if (Permissions.check(handler.player, Constants.UPDATE_PERMISSION, 2)) {
|
||||
VersionCheckUtils.checkForGeyserUpdate(() -> new FabricCommandSender(handler.player.createCommandSourceStack()));
|
||||
VersionCheckUtils.checkForGeyserUpdate(() -> new FabricCommandSource(handler.player.createCommandSourceStack()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,12 +35,14 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
|||
import org.geysermc.geyser.text.ChatColor;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FabricCommandSender implements GeyserCommandSource {
|
||||
public class FabricCommandSource implements GeyserCommandSource {
|
||||
|
||||
private final CommandSourceStack source;
|
||||
|
||||
public FabricCommandSender(CommandSourceStack source) {
|
||||
public FabricCommandSource(CommandSourceStack source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
|
@ -73,8 +75,21 @@ public class FabricCommandSender implements GeyserCommandSource {
|
|||
return !(source.getEntity() instanceof ServerPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
if (source.getEntity() instanceof ServerPlayer player) {
|
||||
return Optional.of(player.getUUID());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return Permissions.check(source, permission);
|
||||
return Permissions.check(source, permission, source.getServer().getOperatorUserPermissionLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return source;
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* 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.platform.fabric.command;
|
||||
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.platform.fabric.GeyserFabricMod;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class GeyserFabricCommandExecutor extends GeyserCommandExecutor implements Command<CommandSourceStack> {
|
||||
private final GeyserCommand command;
|
||||
|
||||
public GeyserFabricCommandExecutor(GeyserImpl connector, GeyserCommand command) {
|
||||
super(connector, Collections.singletonMap(command.name(), command));
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public boolean testPermission(CommandSourceStack source) {
|
||||
return Permissions.check(source, command.permission(), command.isSuggestedOpOnly() ? 2 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int run(CommandContext context) {
|
||||
CommandSourceStack source = (CommandSourceStack) context.getSource();
|
||||
FabricCommandSender sender = new FabricCommandSender(source);
|
||||
GeyserSession session = getGeyserSession(sender);
|
||||
if (!testPermission(source)) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale()));
|
||||
return 0;
|
||||
}
|
||||
if (this.command.name().equals("reload")) {
|
||||
GeyserFabricMod.getInstance().setReloading(true);
|
||||
}
|
||||
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale()));
|
||||
return 0;
|
||||
}
|
||||
command.execute(session, sender, new String[0]);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ dependencies {
|
|||
|
||||
implementation(libs.adapters.spigot)
|
||||
|
||||
implementation(libs.cloud.paper)
|
||||
implementation(libs.commodore)
|
||||
|
||||
implementation(libs.adventure.text.serializer.bungeecord)
|
||||
|
@ -29,6 +30,7 @@ platformRelocate("com.fasterxml.jackson")
|
|||
platformRelocate("net.kyori", "net.kyori.adventure.text.logger.slf4j.ComponentLogger")
|
||||
platformRelocate("org.objectweb.asm")
|
||||
platformRelocate("me.lucko.commodore")
|
||||
platformRelocate("cloud.commandframework")
|
||||
|
||||
// These dependencies are already present on the platform
|
||||
provided(libs.viaversion)
|
||||
|
|
|
@ -25,22 +25,22 @@
|
|||
|
||||
package org.geysermc.geyser.platform.spigot;
|
||||
|
||||
import cloud.commandframework.bukkit.BukkitCommandManager;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.paper.PaperCommandManager;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.lucko.commodore.CommodoreProvider;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerLoadEvent;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.permissions.PermissionDefault;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.Constants;
|
||||
|
@ -50,15 +50,14 @@ import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
|
|||
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.GeyserCommandSource;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.spigot.command.GeyserBrigadierSupport;
|
||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandExecutor;
|
||||
import org.geysermc.geyser.platform.spigot.command.GeyserSpigotCommandManager;
|
||||
import org.geysermc.geyser.platform.spigot.command.SpigotCommandSource;
|
||||
import org.geysermc.geyser.platform.spigot.world.GeyserPistonListener;
|
||||
import org.geysermc.geyser.platform.spigot.world.GeyserSpigotBlockPlaceListener;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotLegacyNativeWorldManager;
|
||||
|
@ -70,8 +69,6 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
@ -85,7 +82,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
*/
|
||||
private static boolean INITIALIZED = false;
|
||||
|
||||
private GeyserSpigotCommandManager geyserCommandManager;
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
private GeyserSpigotConfiguration geyserConfig;
|
||||
private GeyserSpigotInjector geyserInjector;
|
||||
private GeyserSpigotLogger geyserLogger;
|
||||
|
@ -172,7 +169,30 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
return;
|
||||
}
|
||||
|
||||
this.geyserCommandManager = new GeyserSpigotCommandManager(geyser);
|
||||
PaperCommandManager<GeyserCommandSource> cloud;
|
||||
try {
|
||||
cloud = new PaperCommandManager<>(
|
||||
this,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
SpigotCommandSource::new,
|
||||
source -> (CommandSender) source.handle()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
// Should always be available on 1.13 and up
|
||||
cloud.registerBrigadier();
|
||||
} catch (BukkitCommandManager.BrigadierFailureException e) {
|
||||
geyserLogger.error("Failed to initialize Brigadier support: " + e.getMessage());
|
||||
if (e.getReason() == BukkitCommandManager.BrigadierFailureReason.VERSION_TOO_HIGH) {
|
||||
// Commodore brig only supports Spigot 1.13 - 1.18.2
|
||||
geyserLogger.error("Using Paper instead of Spigot will likely fix this.");
|
||||
}
|
||||
}
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser, cloud);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
if (!INITIALIZED) {
|
||||
|
@ -185,25 +205,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
postStartup();
|
||||
}
|
||||
}, this);
|
||||
|
||||
// Because Bukkit locks its command map upon startup, we need to
|
||||
// add our plugin commands in onEnable, but populating the executor
|
||||
// can happen at any time
|
||||
CommandMap commandMap = GeyserSpigotCommandManager.getCommandMap();
|
||||
for (Extension extension : this.geyserCommandManager.extensionCommands().keySet()) {
|
||||
// Thanks again, Bukkit
|
||||
try {
|
||||
Constructor<PluginCommand> constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class);
|
||||
constructor.setAccessible(true);
|
||||
|
||||
PluginCommand pluginCommand = constructor.newInstance(extension.description().id(), this);
|
||||
pluginCommand.setDescription("The main command for the " + extension.name() + " Geyser extension!");
|
||||
|
||||
commandMap.register(extension.description().id(), "geyserext", pluginCommand);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
|
||||
this.geyserLogger.error("Failed to construct PluginCommand for extension " + extension.description().name(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (INITIALIZED) {
|
||||
|
@ -278,22 +279,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
geyserLogger.debug("Using default world manager.");
|
||||
}
|
||||
|
||||
PluginCommand geyserCommand = this.getCommand("geyser");
|
||||
geyserCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
||||
|
||||
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||
Map<String, Command> commands = entry.getValue();
|
||||
if (commands.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PluginCommand command = this.getCommand(entry.getKey().description().id());
|
||||
if (command == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
command.setExecutor(new GeyserSpigotCommandExecutor(this.geyser, commands));
|
||||
}
|
||||
|
||||
if (!INITIALIZED) {
|
||||
// Register permissions so they appear in, for example, LuckPerms' UI
|
||||
|
@ -341,12 +326,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserSpigotUpdateListener(), this);
|
||||
}
|
||||
|
||||
boolean brigadierSupported = CommodoreProvider.isSupported();
|
||||
geyserLogger.debug("Brigadier supported? " + brigadierSupported);
|
||||
if (brigadierSupported) {
|
||||
GeyserBrigadierSupport.loadBrigadier(this, geyserCommand);
|
||||
}
|
||||
|
||||
// Check to ensure the current setup can support the protocol version Geyser uses
|
||||
GeyserSpigotVersionChecker.checkForSupportedProtocol(geyserLogger, isViaVersion);
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* 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.platform.spigot.command;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.lucko.commodore.Commodore;
|
||||
import me.lucko.commodore.CommodoreProvider;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.geysermc.geyser.platform.spigot.GeyserSpigotPlugin;
|
||||
|
||||
/**
|
||||
* Needs to be a separate class so pre-1.13 loads correctly.
|
||||
*/
|
||||
public final class GeyserBrigadierSupport {
|
||||
|
||||
public static void loadBrigadier(GeyserSpigotPlugin plugin, PluginCommand pluginCommand) {
|
||||
// Enable command completions if supported
|
||||
// This is beneficial because this is sent over the network and Bedrock can see it
|
||||
Commodore commodore = CommodoreProvider.getCommodore(plugin);
|
||||
LiteralArgumentBuilder<?> builder = LiteralArgumentBuilder.literal("geyser");
|
||||
for (String command : plugin.getGeyserCommandManager().getCommands().keySet()) {
|
||||
builder.then(LiteralArgumentBuilder.literal(command));
|
||||
}
|
||||
commodore.register(pluginCommand, builder);
|
||||
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent");
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new GeyserPaperCommandListener(), plugin);
|
||||
plugin.getGeyserLogger().debug("Successfully registered AsyncPlayerSendCommandsEvent listener.");
|
||||
} catch (ClassNotFoundException e) {
|
||||
plugin.getGeyserLogger().debug("Not registering AsyncPlayerSendCommandsEvent listener.");
|
||||
}
|
||||
}
|
||||
|
||||
private GeyserBrigadierSupport() {
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* 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.platform.spigot.command;
|
||||
|
||||
import com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public final class GeyserPaperCommandListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
@SuppressWarnings("deprecation") // Used to indicate an unstable event
|
||||
public void onCommandSend(AsyncPlayerSendCommandsEvent<?> event) {
|
||||
// Documentation says to check (event.isAsynchronous() || !event.hasFiredAsync()), but as of Paper 1.18.2
|
||||
// event.hasFiredAsync is never true
|
||||
if (event.isAsynchronous()) {
|
||||
CommandNode<?> geyserBrigadier = event.getCommandNode().getChild("geyser");
|
||||
if (geyserBrigadier != null) {
|
||||
Player player = event.getPlayer();
|
||||
boolean isJavaPlayer = isProbablyJavaPlayer(player);
|
||||
Map<String, Command> commands = GeyserImpl.getInstance().commandManager().getCommands();
|
||||
Iterator<? extends CommandNode<?>> it = geyserBrigadier.getChildren().iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
CommandNode<?> subnode = it.next();
|
||||
Command command = commands.get(subnode.getName());
|
||||
if (command != null) {
|
||||
if ((command.isBedrockOnly() && isJavaPlayer) || !player.hasPermission(command.permission())) {
|
||||
// Remove this from the node as we don't have permission to use it
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This early on, there is a rare chance that Geyser has yet to process the connection. We'll try to minimize that
|
||||
* chance, though.
|
||||
*/
|
||||
private boolean isProbablyJavaPlayer(Player player) {
|
||||
if (GeyserImpl.getInstance().connectionByUuid(player.getUniqueId()) != null) {
|
||||
// For sure this is a Bedrock player
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GeyserImpl.getInstance().getConfig().isUseDirectConnection()) {
|
||||
InetSocketAddress address = player.getAddress();
|
||||
if (address != null) {
|
||||
return address.getPort() != 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* 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.platform.spigot.command;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeyserSpigotCommandExecutor extends GeyserCommandExecutor implements TabExecutor {
|
||||
|
||||
public GeyserSpigotCommandExecutor(GeyserImpl geyser, Map<String, org.geysermc.geyser.api.command.Command> commands) {
|
||||
super(geyser, commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
SpigotCommandSource commandSender = new SpigotCommandSource(sender);
|
||||
GeyserSession session = getGeyserSession(commandSender);
|
||||
|
||||
if (args.length > 0) {
|
||||
GeyserCommand geyserCommand = getCommand(args[0]);
|
||||
if (geyserCommand != null) {
|
||||
if (!sender.hasPermission(geyserCommand.permission())) {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", commandSender.locale());
|
||||
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
return true;
|
||||
}
|
||||
if (geyserCommand.isBedrockOnly() && session == null) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", commandSender.locale()));
|
||||
return true;
|
||||
}
|
||||
geyserCommand.execute(session, commandSender, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
return true;
|
||||
} else {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", commandSender.locale());
|
||||
commandSender.sendMessage(ChatColor.RED + message);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(session, commandSender, new String[0]);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return tabComplete(new SpigotCommandSource(sender));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* 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.platform.spigot.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class GeyserSpigotCommandManager extends GeyserCommandManager {
|
||||
|
||||
private static final CommandMap COMMAND_MAP;
|
||||
|
||||
static {
|
||||
CommandMap commandMap = null;
|
||||
try {
|
||||
// Paper-only
|
||||
Server.class.getMethod("getCommandMap");
|
||||
commandMap = Bukkit.getServer().getCommandMap();
|
||||
} catch (NoSuchMethodException e) {
|
||||
try {
|
||||
Field cmdMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap");
|
||||
cmdMapField.setAccessible(true);
|
||||
commandMap = (CommandMap) cmdMapField.get(Bukkit.getServer());
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
COMMAND_MAP = commandMap;
|
||||
}
|
||||
|
||||
public GeyserSpigotCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(String command) {
|
||||
Command cmd = COMMAND_MAP.getCommand(command.replace("/", ""));
|
||||
return cmd != null ? cmd.getDescription() : "";
|
||||
}
|
||||
|
||||
public static CommandMap getCommandMap() {
|
||||
return COMMAND_MAP;
|
||||
}
|
||||
}
|
|
@ -33,6 +33,9 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
|||
import org.geysermc.geyser.platform.spigot.PaperAdventure;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpigotCommandSource implements GeyserCommandSource {
|
||||
private final org.bukkit.command.CommandSender handle;
|
||||
|
||||
|
@ -63,11 +66,24 @@ public class SpigotCommandSource implements GeyserCommandSource {
|
|||
handle.spigot().sendMessage(BungeeComponentSerializer.get().serialize(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsole() {
|
||||
return handle instanceof ConsoleCommandSender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
if (handle instanceof Player player) {
|
||||
return Optional.of(player.getUniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String locale() {
|
||||
if (this.handle instanceof Player player) {
|
||||
|
|
|
@ -30,17 +30,13 @@ import org.apache.logging.log4j.Logger;
|
|||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
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.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.Sponge;
|
||||
|
@ -59,7 +55,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Plugin(value = "geyser")
|
||||
|
@ -85,7 +80,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
private GeyserSpongeConfiguration geyserConfig;
|
||||
private GeyserSpongeLogger geyserLogger;
|
||||
private GeyserImpl geyser;
|
||||
private GeyserSpongeCommandManager geyserCommandManager; // Commands are only registered after command registration lifecycle
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
|
||||
// Available after StartedEngine lifecycle
|
||||
private IGeyserPingPassthrough geyserSpongePingPassthrough;
|
||||
|
@ -144,29 +139,18 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
|
|||
|
||||
this.geyser = GeyserImpl.load(PlatformType.SPONGE, this);
|
||||
|
||||
this.geyserCommandManager = new GeyserSpongeCommandManager(geyser);
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser); // todo: commands
|
||||
this.geyserCommandManager.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the {@link GeyserSpongeCommandManager} and register the commands
|
||||
* Construct the {@link GeyserCommandManager} and register the commands
|
||||
*
|
||||
* @param event required to register the commands
|
||||
*/
|
||||
@Listener
|
||||
public void onRegisterCommands(@Nonnull RegisterCommandEvent<org.spongepowered.api.command.Command.Raw> event) {
|
||||
if (enabled) {
|
||||
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser");
|
||||
|
||||
for (Map.Entry<Extension, Map<String, Command>> entry : this.geyserCommandManager.extensionCommands().entrySet()) {
|
||||
Map<String, Command> commands = entry.getValue();
|
||||
if (commands.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
event.register(this.pluginContainer, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id());
|
||||
}
|
||||
}
|
||||
// todo: commands. sponge-cloud probably hooks into this without us needing to
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* 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.platform.sponge.command;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.command.CommandCompletion;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.parameter.ArgumentReader;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GeyserSpongeCommandExecutor extends GeyserCommandExecutor implements org.spongepowered.api.command.Command.Raw {
|
||||
|
||||
public GeyserSpongeCommandExecutor(GeyserImpl geyser, Map<String, Command> commands) {
|
||||
super(geyser, commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
GeyserCommandSource commandSource = new SpongeCommandSource(cause);
|
||||
GeyserSession session = getGeyserSession(commandSource);
|
||||
|
||||
String[] args = arguments.input().split(" ");
|
||||
// This split operation results in an array of length 1, containing a zero length string, if the input string is empty
|
||||
if (args.length > 0 && !args[0].isEmpty()) {
|
||||
GeyserCommand command = getCommand(args[0]);
|
||||
if (command != null) {
|
||||
if (!cause.hasPermission(command.permission())) {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.permission_fail")).color(NamedTextColor.RED));
|
||||
return CommandResult.success();
|
||||
}
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only")).color(NamedTextColor.RED));
|
||||
return CommandResult.success();
|
||||
}
|
||||
command.execute(session, commandSource, args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0]);
|
||||
} else {
|
||||
cause.audience().sendMessage(Component.text(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.not_found")).color(NamedTextColor.RED));
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(session, commandSource, new String[0]);
|
||||
}
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandCompletion> complete(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
if (arguments.input().split(" ").length == 1) {
|
||||
return tabComplete(new SpongeCommandSource(cause)).stream().map(CommandCompletion::of).collect(Collectors.toList());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(CommandCause cause) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> shortDescription(CommandCause cause) {
|
||||
return Optional.of(Component.text("The main command for Geyser."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> extendedDescription(CommandCause cause) {
|
||||
return shortDescription(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Component> help(@NotNull CommandCause cause) {
|
||||
return Optional.of(Component.text("/geyser help"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component usage(CommandCause cause) {
|
||||
return Component.text("/geyser help");
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* 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.platform.sponge.command;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.command.manager.CommandMapping;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class GeyserSpongeCommandManager extends GeyserCommandManager {
|
||||
|
||||
public GeyserSpongeCommandManager(GeyserImpl geyser) {
|
||||
super(geyser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description(String command) {
|
||||
if (!Sponge.isServerAvailable()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Note: The command manager may be replaced at any point during the game lifecycle
|
||||
return Sponge.server().commandManager().commandMapping(command)
|
||||
.map(this::description)
|
||||
.map(Optional::get)
|
||||
.map(MessageTranslator::convertMessage)
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
public Optional<Component> description(CommandMapping mapping) {
|
||||
return mapping.registrar().shortDescription(CommandCause.create(), mapping);
|
||||
}
|
||||
}
|
|
@ -32,6 +32,9 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
|||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class SpongeCommandSource implements GeyserCommandSource {
|
||||
|
||||
|
@ -52,8 +55,21 @@ public class SpongeCommandSource implements GeyserCommandSource {
|
|||
return !(handle.cause().root() instanceof ServerPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
if (handle.cause().root() instanceof ServerPlayer player) {
|
||||
return Optional.of(player.uniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||
geyser = GeyserImpl.load(PlatformType.STANDALONE, this);
|
||||
GeyserImpl.start();
|
||||
|
||||
geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
geyserCommandManager = new GeyserCommandManager(geyser, new GeyserStandaloneCommandManager());
|
||||
geyserCommandManager.init();
|
||||
|
||||
if (gui != null) {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2023 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.platform.standalone;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.internal.CommandRegistrationHandler;
|
||||
import cloud.commandframework.meta.CommandMeta;
|
||||
import cloud.commandframework.meta.SimpleCommandMeta;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
|
||||
public class GeyserStandaloneCommandManager extends CommandManager<GeyserCommandSource> {
|
||||
|
||||
protected GeyserStandaloneCommandManager() {
|
||||
super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NonNull GeyserCommandSource sender, @NonNull String permission) {
|
||||
return false; // todo: commands
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CommandMeta createDefaultCommandMeta() {
|
||||
return SimpleCommandMeta.empty();
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
|
|||
|
||||
@Override
|
||||
protected void runCommand(String line) {
|
||||
GeyserImpl.getInstance().commandManager().runCommand(this, line);
|
||||
GeyserImpl.getInstance().commandManager().cloud().executeCommand(this, line);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -260,7 +260,7 @@ public class GeyserStandaloneGUI {
|
|||
commandsMenu.removeAll();
|
||||
optionsMenu.removeAll();
|
||||
|
||||
for (Map.Entry<String, Command> entry : geyserCommandManager.getCommands().entrySet()) {
|
||||
for (Map.Entry<String, Command> entry : geyserCommandManager.commands().entrySet()) {
|
||||
// Remove the offhand command and any alias commands to prevent duplicates in the list
|
||||
if (!entry.getValue().isExecutableOnConsole() || entry.getValue().aliases().contains(entry.getKey())) {
|
||||
continue;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
dependencies {
|
||||
annotationProcessor(libs.velocity.api)
|
||||
api(projects.core)
|
||||
api(libs.cloud.velocity)
|
||||
}
|
||||
|
||||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("it.unimi.dsi.fastutil")
|
||||
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
|
||||
platformRelocate("cloud.commandframework")
|
||||
|
||||
exclude("com.google.*:*")
|
||||
|
||||
|
|
|
@ -25,28 +25,31 @@
|
|||
|
||||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||
import cloud.commandframework.velocity.VelocityCommandManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.command.CommandManager;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ListenerBoundEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.network.ListenerType;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.util.Codec;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
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.GeyserCommandSource;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||
import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor;
|
||||
import org.geysermc.geyser.platform.velocity.command.VelocityCommandSource;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -58,7 +61,6 @@ import java.io.IOException;
|
|||
import java.net.SocketAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC")
|
||||
|
@ -71,7 +73,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
private ProxyServer proxyServer;
|
||||
|
||||
@Inject
|
||||
private CommandManager commandManager;
|
||||
private PluginContainer container;
|
||||
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
private GeyserVelocityConfiguration geyserConfig;
|
||||
|
@ -132,19 +134,16 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
this.geyserInjector = new GeyserVelocityInjector(proxyServer);
|
||||
// Will be initialized after the proxy has been bound
|
||||
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
CommandManager<GeyserCommandSource> cloud = new VelocityCommandManager<>(
|
||||
container,
|
||||
proxyServer,
|
||||
CommandExecutionCoordinator.simpleCoordinator(),
|
||||
VelocityCommandSource::new,
|
||||
origin -> (CommandSource) origin.handle()
|
||||
);
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser, cloud);
|
||||
this.geyserCommandManager.init();
|
||||
|
||||
this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands()));
|
||||
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()) {
|
||||
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||
} else {
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* 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.platform.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.SimpleCommand;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.command.GeyserCommandExecutor;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeyserVelocityCommandExecutor extends GeyserCommandExecutor implements SimpleCommand {
|
||||
|
||||
public GeyserVelocityCommandExecutor(GeyserImpl geyser, Map<String, Command> commands) {
|
||||
super(geyser, commands);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Invocation invocation) {
|
||||
GeyserCommandSource sender = new VelocityCommandSource(invocation.source());
|
||||
GeyserSession session = getGeyserSession(sender);
|
||||
|
||||
if (invocation.arguments().length > 0) {
|
||||
GeyserCommand command = getCommand(invocation.arguments()[0]);
|
||||
if (command != null) {
|
||||
if (!invocation.source().hasPermission(getCommand(invocation.arguments()[0]).permission())) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", sender.locale()));
|
||||
return;
|
||||
}
|
||||
if (command.isBedrockOnly() && session == null) {
|
||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.bedrock_only", sender.locale()));
|
||||
return;
|
||||
}
|
||||
command.execute(session, sender, invocation.arguments().length > 1 ? Arrays.copyOfRange(invocation.arguments(), 1, invocation.arguments().length) : new String[0]);
|
||||
} else {
|
||||
String message = GeyserLocale.getPlayerLocaleString("geyser.bootstrap.command.not_found", sender.locale());
|
||||
sender.sendMessage(ChatColor.RED + message);
|
||||
}
|
||||
} else {
|
||||
getCommand("help").execute(session, sender, new String[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(Invocation invocation) {
|
||||
// Velocity seems to do the splitting a bit differently. This results in the same behaviour in bungeecord/spigot.
|
||||
if (invocation.arguments().length == 0 || invocation.arguments().length == 1) {
|
||||
return tabComplete(new VelocityCommandSource(invocation.source()));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
|||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VelocityCommandSource implements GeyserCommandSource {
|
||||
|
||||
|
@ -71,6 +73,14 @@ public class VelocityCommandSource implements GeyserCommandSource {
|
|||
return handle instanceof ConsoleCommandSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
if (handle instanceof Player player) {
|
||||
return Optional.of(player.getUniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String locale() {
|
||||
if (handle instanceof Player) {
|
||||
|
@ -84,4 +94,9 @@ public class VelocityCommandSource implements GeyserCommandSource {
|
|||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ dependencies {
|
|||
// Adventure text serialization
|
||||
api(libs.bundles.adventure)
|
||||
|
||||
// command library
|
||||
api(libs.cloud.core)
|
||||
|
||||
api(libs.erosion.common) {
|
||||
isTransitive = false
|
||||
}
|
||||
|
|
|
@ -616,7 +616,7 @@ public class GeyserImpl implements GeyserApi {
|
|||
skinUploader.close();
|
||||
}
|
||||
newsHandler.shutdown();
|
||||
this.commandManager().getCommands().clear();
|
||||
this.commandManager().clear();
|
||||
|
||||
if (this.erosionUnixListener != null) {
|
||||
this.erosionUnixListener.close();
|
||||
|
|
|
@ -29,6 +29,8 @@ import net.kyori.adventure.text.Component;
|
|||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface GeyserLogger extends GeyserCommandSource {
|
||||
|
||||
|
@ -128,6 +130,11 @@ public interface GeyserLogger extends GeyserCommandSource {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
default Optional<UUID> playerUuid() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean hasPermission(String permission) {
|
||||
return true;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser.command;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.arguments.standard.StringArgument;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
@ -95,4 +97,31 @@ public abstract class GeyserCommand implements Command {
|
|||
public boolean isSuggestedOpOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String rootCommand() {
|
||||
return "geyser";
|
||||
}
|
||||
|
||||
public void register(CommandManager<GeyserCommandSource> manager) {
|
||||
// todo: commands all builtin commands should directly use cloud
|
||||
// also, there needs to be customized messages for isExecutableOnConsole and isBedrockOnly, etc. Review the old CommandExecutors.
|
||||
manager.command(manager.commandBuilder(rootCommand())
|
||||
.literal(name, aliases.toArray(new String[0]))
|
||||
.permission(source -> {
|
||||
if (source.isConsole()) {
|
||||
return isExecutableOnConsole();
|
||||
}
|
||||
if (isBedrockOnly() && source.connection().isEmpty()) {
|
||||
return false; // bedrock only but not a bedrock player
|
||||
}
|
||||
|
||||
return source.hasPermission(permission);
|
||||
})
|
||||
.argument(StringArgument.optional("args", StringArgument.StringMode.GREEDY))
|
||||
.handler(context -> {
|
||||
GeyserCommandSource source = context.getSender();
|
||||
execute(source.connection().orElse(null), source, context.getOrDefault("args", "").split(" "));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* 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.command;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents helper functions for listening to {@code /geyser} or {@code /geyserext} commands.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class GeyserCommandExecutor {
|
||||
|
||||
protected final GeyserImpl geyser;
|
||||
private final Map<String, Command> commands;
|
||||
|
||||
public GeyserCommand getCommand(String label) {
|
||||
return (GeyserCommand) commands.get(label);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GeyserSession getGeyserSession(GeyserCommandSource sender) {
|
||||
if (sender.isConsole()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (GeyserSession session : geyser.getSessionManager().getSessions().values()) {
|
||||
if (sender.name().equals(session.getPlayerEntity().getUsername())) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which subcommands to suggest in the tab complete for the main /geyser command by a given command sender.
|
||||
*
|
||||
* @param sender The command sender to receive the tab complete suggestions.
|
||||
* If the command sender is a bedrock player, an empty list will be returned as bedrock players do not get command argument suggestions.
|
||||
* If the command sender is not a bedrock player, bedrock commands will not be shown.
|
||||
* If the command sender does not have the permission for a given command, the command will not be shown.
|
||||
* @return A list of command names to include in the tab complete
|
||||
*/
|
||||
public List<String> tabComplete(GeyserCommandSource sender) {
|
||||
if (getGeyserSession(sender) != null) {
|
||||
// Bedrock doesn't get tab completions or argument suggestions
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> availableCommands = new ArrayList<>();
|
||||
|
||||
// Only show commands they have permission to use
|
||||
for (Map.Entry<String, Command> entry : commands.entrySet()) {
|
||||
Command geyserCommand = entry.getValue();
|
||||
if (sender.hasPermission(geyserCommand.permission())) {
|
||||
if (geyserCommand.isBedrockOnly()) {
|
||||
// Don't show commands the JE player can't run
|
||||
continue;
|
||||
}
|
||||
|
||||
availableCommands.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return availableCommands;
|
||||
}
|
||||
}
|
|
@ -25,10 +25,11 @@
|
|||
|
||||
package org.geysermc.geyser.command;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.Command;
|
||||
|
@ -54,22 +55,24 @@ import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class GeyserCommandManager {
|
||||
|
||||
@Getter
|
||||
private final Map<String, Command> commands = new Object2ObjectOpenHashMap<>(12);
|
||||
private final Map<String, Command> commands = new Object2ObjectOpenHashMap<>(13);
|
||||
private final Map<Extension, Map<String, Command>> extensionCommands = new Object2ObjectOpenHashMap<>(0);
|
||||
|
||||
private final GeyserImpl geyser;
|
||||
private final CommandManager<GeyserCommandSource> cloud;
|
||||
|
||||
public GeyserCommandManager(GeyserImpl geyser, CommandManager<GeyserCommandSource> cloud) {
|
||||
this.geyser = geyser;
|
||||
this.cloud = cloud;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", this.commands));
|
||||
|
@ -118,11 +121,13 @@ public class GeyserCommandManager {
|
|||
register(command, this.commands);
|
||||
}
|
||||
|
||||
public void registerExtensionCommand(@NonNull Extension extension, @NonNull Command command) {
|
||||
public void registerExtensionCommand(@NonNull Extension extension, @NonNull GeyserCommand command) {
|
||||
register(command, this.extensionCommands.computeIfAbsent(extension, e -> new HashMap<>()));
|
||||
}
|
||||
|
||||
private void register(Command command, Map<String, Command> commands) {
|
||||
private void register(GeyserCommand command, Map<String, Command> commands) {
|
||||
command.register(cloud);
|
||||
|
||||
commands.put(command.name(), command);
|
||||
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.commands.registered", command.name()));
|
||||
|
||||
|
@ -135,6 +140,11 @@ public class GeyserCommandManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.commands.clear();
|
||||
this.extensionCommands.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<String, Command> commands() {
|
||||
return Collections.unmodifiableMap(this.commands);
|
||||
|
@ -145,51 +155,9 @@ public class GeyserCommandManager {
|
|||
return Collections.unmodifiableMap(this.extensionCommands);
|
||||
}
|
||||
|
||||
public boolean runCommand(GeyserCommandSource sender, String command) {
|
||||
Extension extension = null;
|
||||
for (Extension loopedExtension : this.extensionCommands.keySet()) {
|
||||
if (command.startsWith(loopedExtension.description().id() + " ")) {
|
||||
extension = loopedExtension;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!command.startsWith("geyser ") && extension == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
command = command.trim().replace(extension != null ? extension.description().id() + " " : "geyser ", "");
|
||||
String label;
|
||||
String[] args;
|
||||
|
||||
if (!command.contains(" ")) {
|
||||
label = command.toLowerCase(Locale.ROOT);
|
||||
args = new String[0];
|
||||
} else {
|
||||
label = command.substring(0, command.indexOf(" ")).toLowerCase(Locale.ROOT);
|
||||
String argLine = command.substring(command.indexOf(" ") + 1);
|
||||
args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine };
|
||||
}
|
||||
|
||||
Command cmd = (extension != null ? this.extensionCommands.getOrDefault(extension, Collections.emptyMap()) : this.commands).get(label);
|
||||
if (cmd == null) {
|
||||
sender.sendMessage(GeyserLocale.getLocaleStringLog("geyser.commands.invalid"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmd instanceof GeyserCommand) {
|
||||
if (sender instanceof GeyserSession) {
|
||||
((GeyserCommand) cmd).execute((GeyserSession) sender, sender, args);
|
||||
} else {
|
||||
if (!cmd.isBedrockOnly()) {
|
||||
((GeyserCommand) cmd).execute(null, sender, args);
|
||||
} else {
|
||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.command.bedrock_only"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@NotNull
|
||||
public CommandManager<GeyserCommandSource> cloud() {
|
||||
return cloud;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,6 +292,11 @@ public class GeyserCommandManager {
|
|||
public boolean isExecutableOnConsole() {
|
||||
return CommandBuilder.this.executableOnConsole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rootCommand() {
|
||||
return extension().rootCommand();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,15 @@
|
|||
|
||||
package org.geysermc.geyser.command;
|
||||
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.command.CommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Implemented on top of any class that can send a command.
|
||||
* For example, it wraps around Spigot's CommandSender class.
|
||||
|
@ -46,4 +50,20 @@ public interface GeyserCommandSource extends CommandSource {
|
|||
default void sendMessage(Component message) {
|
||||
sendMessage(LegacyComponentSerializer.legacySection().serialize(message));
|
||||
}
|
||||
|
||||
default void sendLocaleString(String key, Object... values) {
|
||||
sendMessage(GeyserLocale.getPlayerLocaleString(key, locale(), values));
|
||||
}
|
||||
|
||||
@Override
|
||||
default Optional<GeyserSession> connection() {
|
||||
return playerUuid().map(id -> GeyserImpl.getInstance().connectionByUuid(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: commands
|
||||
*/
|
||||
default Object handle() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ public class HelpCommand extends GeyserCommand {
|
|||
String header = GeyserLocale.getPlayerLocaleString("geyser.commands.help.header", sender.locale(), page, maxPage);
|
||||
sender.sendMessage(header);
|
||||
|
||||
// todo: commands looks like this doesn't guard against alias keys
|
||||
this.commands.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
|
||||
Command cmd = entry.getValue();
|
||||
|
||||
|
|
|
@ -1407,6 +1407,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> playerUuid() {
|
||||
return Optional.of(playerEntity.getUuid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String locale() {
|
||||
return clientData.getLanguageCode();
|
||||
|
|
|
@ -25,9 +25,11 @@
|
|||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import cloud.commandframework.CommandManager;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
|
@ -40,13 +42,27 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
|
|||
@Override
|
||||
public void translate(GeyserSession session, CommandRequestPacket packet) {
|
||||
String command = MessageTranslator.convertToPlainText(packet.getCommand());
|
||||
if (!(session.getGeyser().getPlatformType() == PlatformType.STANDALONE
|
||||
&& GeyserImpl.getInstance().commandManager().runCommand(session, command.substring(1)))) {
|
||||
if (MessageTranslator.isTooLong(command, session)) {
|
||||
return;
|
||||
}
|
||||
String strippedCommand = command.substring(1);
|
||||
|
||||
session.sendCommand(command.substring(1));
|
||||
if (session.getGeyser().getPlatformType() == PlatformType.STANDALONE) {
|
||||
// try to handle the command within the standalone command manager
|
||||
|
||||
String[] args = strippedCommand.split(" ");
|
||||
if (args.length > 0) {
|
||||
String root = args[0];
|
||||
|
||||
CommandManager<GeyserCommandSource> manager = GeyserImpl.getInstance().commandManager().cloud();
|
||||
if (manager.rootCommands().contains(root)) {
|
||||
manager.executeCommand(session, strippedCommand);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MessageTranslator.isTooLong(command, session)) {
|
||||
return;
|
||||
}
|
||||
|
||||
session.sendCommand(strippedCommand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ terminalconsoleappender = "1.2.0"
|
|||
folia = "1.19.4-R0.1-SNAPSHOT"
|
||||
viaversion = "4.0.0"
|
||||
adapters = "1.8-SNAPSHOT"
|
||||
cloud = "1.8.3"
|
||||
commodore = "2.2"
|
||||
bungeecord = "a7c6ede"
|
||||
velocity = "3.0.0"
|
||||
|
@ -71,6 +72,12 @@ jline-terminal = { group = "org.jline", name = "jline-terminal", version.ref = "
|
|||
jline-terminal-jna = { group = "org.jline", name = "jline-terminal-jna", version.ref = "jline" }
|
||||
jline-reader = { group = "org.jline", name = "jline-reader", version.ref = "jline" }
|
||||
|
||||
cloud-core = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" }
|
||||
cloud-paper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" }
|
||||
cloud-velocity = { group = "cloud.commandframework", name = "cloud-velocity", version.ref = "cloud" }
|
||||
cloud-bungee = { group = "cloud.commandframework", name = "cloud-bungee", version.ref = "cloud" }
|
||||
cloud-fabric = { group = "cloud.commandframework", name = "cloud-fabric", version.ref = "cloud" }
|
||||
|
||||
folia-api = { group = "dev.folia", name = "folia-api", version.ref = "folia" }
|
||||
paper-mojangapi = { group = "io.papermc.paper", name = "paper-mojangapi", version.ref = "folia" }
|
||||
|
||||
|
|
Loading…
Reference in New Issue