mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Cloud for commands (#3808)
Co-authored-by: onebeastchris <github@onechris.mozmail.com>
This commit is contained in:
parent
6002c9c7a1
commit
87ab51cb28
95 changed files with 2556 additions and 1879 deletions
|
@ -3,12 +3,15 @@ dependencies {
|
|||
api(projects.core)
|
||||
|
||||
compileOnlyApi(libs.velocity.api)
|
||||
api(libs.cloud.velocity)
|
||||
}
|
||||
|
||||
platformRelocate("com.fasterxml.jackson")
|
||||
platformRelocate("it.unimi.dsi.fastutil")
|
||||
platformRelocate("net.kyori.adventure.text.serializer.gson.legacyimpl")
|
||||
platformRelocate("org.yaml")
|
||||
platformRelocate("org.incendo")
|
||||
platformRelocate("io.leangen.geantyref") // provided by cloud, should also be relocated
|
||||
|
||||
exclude("com.google.*:*")
|
||||
|
||||
|
@ -38,8 +41,8 @@ exclude("net.kyori:adventure-nbt:*")
|
|||
// These dependencies are already present on the platform
|
||||
provided(libs.velocity.api)
|
||||
|
||||
application {
|
||||
mainClass.set("org.geysermc.geyser.platform.velocity.GeyserVelocityMain")
|
||||
tasks.withType<Jar> {
|
||||
manifest.attributes["Main-Class"] = "org.geysermc.geyser.platform.velocity.GeyserVelocityMain"
|
||||
}
|
||||
|
||||
tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
||||
|
@ -74,4 +77,4 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
|||
modrinth {
|
||||
uploadFile.set(tasks.getByPath("shadowJar"))
|
||||
loaders.addAll("velocity")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
package org.geysermc.geyser.platform.velocity;
|
||||
|
||||
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;
|
||||
|
@ -34,24 +34,28 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
|||
import com.velocitypowered.api.network.ListenerType;
|
||||
import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
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.api.util.PlatformType;
|
||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||
import org.geysermc.geyser.command.CommandRegistry;
|
||||
import org.geysermc.geyser.command.CommandSourceConverter;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
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.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||
import org.incendo.cloud.velocity.VelocityCommandManager;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -59,29 +63,28 @@ 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")
|
||||
public class GeyserVelocityPlugin implements GeyserBootstrap {
|
||||
|
||||
private final ProxyServer proxyServer;
|
||||
private final CommandManager commandManager;
|
||||
private final PluginContainer container;
|
||||
private final GeyserVelocityLogger geyserLogger;
|
||||
private GeyserCommandManager geyserCommandManager;
|
||||
private GeyserVelocityConfiguration geyserConfig;
|
||||
private GeyserVelocityInjector geyserInjector;
|
||||
private IGeyserPingPassthrough geyserPingPassthrough;
|
||||
private CommandRegistry commandRegistry;
|
||||
private GeyserImpl geyser;
|
||||
|
||||
@Getter
|
||||
private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/");
|
||||
|
||||
@Inject
|
||||
public GeyserVelocityPlugin(ProxyServer server, Logger logger, CommandManager manager) {
|
||||
this.geyserLogger = new GeyserVelocityLogger(logger);
|
||||
public GeyserVelocityPlugin(ProxyServer server, PluginContainer container, Logger logger) {
|
||||
this.proxyServer = server;
|
||||
this.commandManager = manager;
|
||||
this.container = container;
|
||||
this.geyserLogger = new GeyserVelocityLogger(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -117,8 +120,19 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
this.geyserLogger.setDebug(geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
} else {
|
||||
this.geyserCommandManager = new GeyserCommandManager(geyser);
|
||||
this.geyserCommandManager.init();
|
||||
var sourceConverter = new CommandSourceConverter<>(
|
||||
CommandSource.class,
|
||||
id -> proxyServer.getPlayer(id).orElse(null),
|
||||
proxyServer::getConsoleCommandSource,
|
||||
VelocityCommandSource::new
|
||||
);
|
||||
CommandManager<GeyserCommandSource> cloud = new VelocityCommandManager<>(
|
||||
container,
|
||||
proxyServer,
|
||||
ExecutionCoordinator.simpleCoordinator(),
|
||||
sourceConverter
|
||||
);
|
||||
this.commandRegistry = new CommandRegistry(geyser, cloud, false); // applying root permission would be a breaking change because we can't register permission defaults
|
||||
}
|
||||
|
||||
GeyserImpl.start();
|
||||
|
@ -129,22 +143,10 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer);
|
||||
}
|
||||
|
||||
// No need to re-register commands when reloading
|
||||
if (GeyserImpl.getInstance().isReloading()) {
|
||||
return;
|
||||
// No need to re-register events
|
||||
if (!GeyserImpl.getInstance().isReloading()) {
|
||||
proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener());
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
proxyServer.getEventManager().register(this, new GeyserVelocityUpdateListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -175,8 +177,8 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
|
|||
}
|
||||
|
||||
@Override
|
||||
public GeyserCommandManager getGeyserCommandManager() {
|
||||
return this.geyserCommandManager;
|
||||
public CommandRegistry getCommandRegistry() {
|
||||
return this.commandRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,8 +28,8 @@ package org.geysermc.geyser.platform.velocity;
|
|||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import org.geysermc.geyser.Constants;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.Permissions;
|
||||
import org.geysermc.geyser.platform.velocity.command.VelocityCommandSource;
|
||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||
|
||||
|
@ -39,7 +39,7 @@ public final class GeyserVelocityUpdateListener {
|
|||
public void onPlayerJoin(PostLoginEvent event) {
|
||||
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
||||
if (player.hasPermission(Permissions.CHECK_UPDATE)) {
|
||||
VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -31,10 +31,12 @@ import com.velocitypowered.api.proxy.Player;
|
|||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VelocityCommandSource implements GeyserCommandSource {
|
||||
|
||||
|
@ -72,6 +74,14 @@ public class VelocityCommandSource implements GeyserCommandSource {
|
|||
return handle instanceof ConsoleCommandSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UUID playerUuid() {
|
||||
if (handle instanceof Player player) {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String locale() {
|
||||
if (handle instanceof Player) {
|
||||
|
@ -83,6 +93,12 @@ public class VelocityCommandSource implements GeyserCommandSource {
|
|||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return handle.hasPermission(permission);
|
||||
// Handle blank permissions ourselves, as velocity only handles empty ones
|
||||
return permission.isBlank() || handle.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue