mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-21 15:59:21 +00:00
Update Cloud to 2.0 beta
This commit is contained in:
@@ -8,7 +8,7 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
relocate("net.kyori")
|
relocate("net.kyori")
|
||||||
relocate("cloud.commandframework")
|
relocate("org.incendo.cloud")
|
||||||
relocate("io.leangen.geantyref") // used in cloud
|
relocate("io.leangen.geantyref") // used in cloud
|
||||||
|
|
||||||
// these dependencies are already present on the platform
|
// these dependencies are already present on the platform
|
||||||
|
|||||||
@@ -25,29 +25,28 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.bungee.module;
|
package org.geysermc.floodgate.bungee.module;
|
||||||
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.bungee.BungeeCommandManager;
|
|
||||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
|
||||||
import io.micronaut.context.annotation.Bean;
|
import io.micronaut.context.annotation.Bean;
|
||||||
import io.micronaut.context.annotation.Factory;
|
import io.micronaut.context.annotation.Factory;
|
||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||||
|
import org.geysermc.floodgate.core.connection.audience.FloodgateSenderMapper;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.bungee.BungeeCommandManager;
|
||||||
|
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||||
|
|
||||||
@Factory
|
@Factory
|
||||||
public final class BungeePlatformModule {
|
public final class BungeePlatformModule {
|
||||||
@Bean
|
@Bean
|
||||||
@Singleton
|
@Singleton
|
||||||
public CommandManager<UserAudience> commandManager(CommandUtil commandUtil, Plugin plugin) {
|
public CommandManager<UserAudience> commandManager(CommandUtil commandUtil, Plugin plugin) {
|
||||||
CommandManager<UserAudience> commandManager = new BungeeCommandManager<>(
|
var commandManager = new BungeeCommandManager<>(
|
||||||
plugin,
|
plugin,
|
||||||
CommandExecutionCoordinator.simpleCoordinator(),
|
ExecutionCoordinator.simpleCoordinator(),
|
||||||
commandUtil::getUserAudience,
|
new FloodgateSenderMapper<>(commandUtil)
|
||||||
audience -> (CommandSender) audience.source()
|
|
||||||
);
|
);
|
||||||
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
||||||
return commandManager;
|
return commandManager;
|
||||||
|
|||||||
@@ -25,11 +25,8 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.command;
|
package org.geysermc.floodgate.core.command;
|
||||||
|
|
||||||
import cloud.commandframework.ArgumentDescription;
|
import static org.incendo.cloud.parser.standard.StringParser.stringParser;
|
||||||
import cloud.commandframework.Command;
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.arguments.standard.StringArgument;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import io.micronaut.context.annotation.Secondary;
|
import io.micronaut.context.annotation.Secondary;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
@@ -40,7 +37,6 @@ import org.geysermc.floodgate.core.api.SimpleFloodgateApi;
|
|||||||
import org.geysermc.floodgate.core.command.util.Permission;
|
import org.geysermc.floodgate.core.command.util.Permission;
|
||||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
||||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudienceArgument;
|
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience.PlayerAudience;
|
||||||
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
||||||
@@ -50,6 +46,10 @@ import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
|||||||
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.core.util.Constants;
|
import org.geysermc.floodgate.core.util.Constants;
|
||||||
import org.geysermc.floodgate.core.util.Utils;
|
import org.geysermc.floodgate.core.util.Utils;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
import org.incendo.cloud.description.Description;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Secondary
|
@Secondary
|
||||||
@@ -59,20 +59,19 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
|||||||
@Inject FloodgateLogger logger;
|
@Inject FloodgateLogger logger;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<PlayerAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
return commandManager.commandBuilder("linkaccount",
|
return commandManager.commandBuilder("linkaccount",
|
||||||
ArgumentDescription.of("Link your Java account with your Bedrock account"))
|
Description.of("Link your Java account with your Bedrock account"))
|
||||||
.senderType(PlayerAudience.class)
|
.senderType(PlayerAudience.class)
|
||||||
.permission(Permission.COMMAND_LINK.get())
|
.permission(Permission.COMMAND_LINK.get())
|
||||||
.argument(ProfileAudienceArgument.of("player", true))
|
.argument(ProfileAudience.ofAnyUsernameBoth("player"))
|
||||||
.argument(StringArgument.optional("code"))
|
.optional("code", stringParser())
|
||||||
.handler(this::execute)
|
.handler(this::execute)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void execute(CommandContext<PlayerAudience> context) {
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
UserAudience sender = context.sender();
|
||||||
UserAudience sender = context.getSender();
|
|
||||||
|
|
||||||
//todo make this less hacky
|
//todo make this less hacky
|
||||||
if (link instanceof GlobalPlayerLinking) {
|
if (link instanceof GlobalPlayerLinking) {
|
||||||
|
|||||||
@@ -25,38 +25,39 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.command;
|
package org.geysermc.floodgate.core.command;
|
||||||
|
|
||||||
import cloud.commandframework.Command;
|
import static org.incendo.cloud.parser.standard.StringParser.stringParser;
|
||||||
import cloud.commandframework.CommandManager;
|
import static org.incendo.cloud.parser.standard.UUIDParser.uuidParser;
|
||||||
import cloud.commandframework.arguments.standard.StringArgument;
|
|
||||||
import cloud.commandframework.arguments.standard.UUIDArgument;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
|
import org.geysermc.floodgate.core.connection.audience.UserAudience.ConsoleAudience;
|
||||||
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
import org.geysermc.floodgate.core.link.CommonPlayerLink;
|
||||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||||
import org.geysermc.floodgate.core.util.Constants;
|
import org.geysermc.floodgate.core.util.Constants;
|
||||||
import org.geysermc.floodgate.core.util.Utils;
|
import org.geysermc.floodgate.core.util.Utils;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class TestCommand implements FloodgateCommand {
|
public class TestCommand implements FloodgateCommand {
|
||||||
@Inject CommonPlayerLink link;
|
@Inject CommonPlayerLink link;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<ConsoleAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
return commandManager.commandBuilder("floodgate-test")
|
return commandManager.commandBuilder("floodgate-test")
|
||||||
.senderType(UserAudience.ConsoleAudience.class)
|
.senderType(ConsoleAudience.class)
|
||||||
|
.required("xuid", stringParser())
|
||||||
|
.required("uuid", uuidParser())
|
||||||
|
.required("name", stringParser())
|
||||||
.handler(this::execute)
|
.handler(this::execute)
|
||||||
.argument(StringArgument.of("xuid"))
|
|
||||||
.argument(UUIDArgument.of("uuid"))
|
|
||||||
.argument(StringArgument.of("name"))
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void execute(CommandContext<ConsoleAudience> context) {
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
|
||||||
try {
|
try {
|
||||||
link.addLink(context.get("uuid"), context.get("name"), Utils.getJavaUuid(context.get("xuid"))).get();
|
link.addLink(context.get("uuid"), context.get("name"), Utils.getJavaUuid(context.get("xuid"))).get();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.command;
|
package org.geysermc.floodgate.core.command;
|
||||||
|
|
||||||
import cloud.commandframework.ArgumentDescription;
|
|
||||||
import cloud.commandframework.Command;
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -41,24 +37,27 @@ import org.geysermc.floodgate.core.link.GlobalPlayerLinking;
|
|||||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||||
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.core.util.Constants;
|
import org.geysermc.floodgate.core.util.Constants;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
import org.incendo.cloud.description.Description;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public final class UnlinkAccountCommand implements FloodgateCommand {
|
public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||||
@Inject CommonPlayerLink link;
|
@Inject CommonPlayerLink link;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<PlayerAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
return commandManager.commandBuilder("unlinkaccount",
|
return commandManager.commandBuilder("unlinkaccount",
|
||||||
ArgumentDescription.of("Unlink your Java account from your Bedrock account"))
|
Description.of("Unlink your Java account from your Bedrock account"))
|
||||||
.senderType(PlayerAudience.class)
|
.senderType(PlayerAudience.class)
|
||||||
.permission(Permission.COMMAND_UNLINK.get())
|
.permission(Permission.COMMAND_UNLINK.get())
|
||||||
.handler(this::execute)
|
.handler(this::execute)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void execute(CommandContext<PlayerAudience> context) {
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
UserAudience sender = context.sender();
|
||||||
UserAudience sender = context.getSender();
|
|
||||||
|
|
||||||
//todo make this less hacky
|
//todo make this less hacky
|
||||||
if (link instanceof GlobalPlayerLinking) {
|
if (link instanceof GlobalPlayerLinking) {
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.command;
|
package org.geysermc.floodgate.core.command;
|
||||||
|
|
||||||
import cloud.commandframework.ArgumentDescription;
|
|
||||||
import cloud.commandframework.Command;
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import io.micronaut.http.client.exceptions.HttpClientResponseException;
|
import io.micronaut.http.client.exceptions.HttpClientResponseException;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
@@ -39,13 +35,15 @@ import org.geysermc.floodgate.core.command.util.Permission;
|
|||||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.config.ProxyFloodgateConfig;
|
import org.geysermc.floodgate.core.config.ProxyFloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
import org.geysermc.floodgate.core.connection.audience.ProfileAudience;
|
||||||
import org.geysermc.floodgate.core.connection.audience.ProfileAudienceArgument;
|
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.http.xbox.XboxClient;
|
import org.geysermc.floodgate.core.http.xbox.XboxClient;
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||||
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
import org.geysermc.floodgate.core.platform.command.TranslatableMessage;
|
||||||
import org.geysermc.floodgate.core.platform.util.PlayerType;
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
import org.incendo.cloud.description.Description;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class WhitelistCommand implements FloodgateCommand {
|
public class WhitelistCommand implements FloodgateCommand {
|
||||||
@@ -56,23 +54,23 @@ public class WhitelistCommand implements FloodgateCommand {
|
|||||||
@Override
|
@Override
|
||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
|
Command.Builder<UserAudience> builder = commandManager.commandBuilder("fwhitelist",
|
||||||
ArgumentDescription.of("Easy way to whitelist Bedrock players"))
|
Description.of("Easy way to whitelist Bedrock players"))
|
||||||
.permission(Permission.COMMAND_WHITELIST.get());
|
.permission(Permission.COMMAND_WHITELIST.get());
|
||||||
|
|
||||||
commandManager.command(builder
|
commandManager.command(builder
|
||||||
.literal("add", "a")
|
.literal("add", "a")
|
||||||
.argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
|
.argument(ProfileAudience.ofAnyIdentifierBedrock("player"))
|
||||||
.handler(context -> performCommand(context, true)));
|
.handler(context -> performCommand(context, true)));
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
.literal("remove", "r")
|
.literal("remove", "r")
|
||||||
.argument(ProfileAudienceArgument.of("player", true, true, PlayerType.ONLY_BEDROCK))
|
.argument(ProfileAudience.ofAnyIdentifierBedrock("player"))
|
||||||
.handler(context -> performCommand(context, false))
|
.handler(context -> performCommand(context, false))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performCommand(CommandContext<UserAudience> context, boolean add) {
|
public void performCommand(CommandContext<UserAudience> context, boolean add) {
|
||||||
UserAudience sender = context.getSender();
|
UserAudience sender = context.sender();
|
||||||
ProfileAudience profile = context.get("player");
|
ProfileAudience profile = context.get("player");
|
||||||
UUID uuid = profile.uuid();
|
UUID uuid = profile.uuid();
|
||||||
String name = profile.username();
|
String name = profile.username();
|
||||||
@@ -181,11 +179,6 @@ public class WhitelistCommand implements FloodgateCommand {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
|
||||||
// ignored, all the logic is in the other method
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldRegister(FloodgateConfig config) {
|
public boolean shouldRegister(FloodgateConfig config) {
|
||||||
// currently only Spigot (our only non-Proxy platform) has a whitelist build-in.
|
// currently only Spigot (our only non-Proxy platform) has a whitelist build-in.
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ package org.geysermc.floodgate.core.command.main;
|
|||||||
|
|
||||||
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
||||||
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
@@ -41,6 +40,7 @@ import org.geysermc.floodgate.core.util.Constants;
|
|||||||
import org.geysermc.floodgate.core.util.HttpClient;
|
import org.geysermc.floodgate.core.util.HttpClient;
|
||||||
import org.geysermc.floodgate.core.util.HttpClient.HttpResponse;
|
import org.geysermc.floodgate.core.util.HttpClient.HttpResponse;
|
||||||
import org.geysermc.floodgate.core.util.Utils;
|
import org.geysermc.floodgate.core.util.Utils;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
|
||||||
final class FirewallCheckSubcommand extends FloodgateSubCommand {
|
final class FirewallCheckSubcommand extends FloodgateSubCommand {
|
||||||
@Inject HttpClient httpProvider;
|
@Inject HttpClient httpProvider;
|
||||||
@@ -67,7 +67,7 @@ final class FirewallCheckSubcommand extends FloodgateSubCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
public void execute(CommandContext<UserAudience> context) {
|
||||||
UserAudience sender = context.getSender();
|
UserAudience sender = context.sender();
|
||||||
executeChecks(
|
executeChecks(
|
||||||
globalApiCheck(sender)
|
globalApiCheck(sender)
|
||||||
).whenComplete((response, $) ->
|
).whenComplete((response, $) ->
|
||||||
|
|||||||
@@ -26,12 +26,8 @@
|
|||||||
package org.geysermc.floodgate.core.command.main;
|
package org.geysermc.floodgate.core.command.main;
|
||||||
|
|
||||||
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
||||||
|
import static org.incendo.cloud.description.Description.description;
|
||||||
|
|
||||||
import cloud.commandframework.ArgumentDescription;
|
|
||||||
import cloud.commandframework.Command;
|
|
||||||
import cloud.commandframework.Command.Builder;
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import org.geysermc.floodgate.core.command.util.Permission;
|
import org.geysermc.floodgate.core.command.util.Permission;
|
||||||
@@ -39,6 +35,11 @@ import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
|||||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||||
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
||||||
import org.geysermc.floodgate.core.platform.command.SubCommands;
|
import org.geysermc.floodgate.core.platform.command.SubCommands;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.Command.Builder;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
import org.incendo.cloud.description.Description;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public final class MainCommand extends SubCommands implements FloodgateCommand {
|
public final class MainCommand extends SubCommands implements FloodgateCommand {
|
||||||
@@ -46,14 +47,14 @@ public final class MainCommand extends SubCommands implements FloodgateCommand {
|
|||||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||||
Builder<UserAudience> builder = commandManager.commandBuilder(
|
Builder<UserAudience> builder = commandManager.commandBuilder(
|
||||||
"floodgate",
|
"floodgate",
|
||||||
ArgumentDescription.of("A set of Floodgate related actions in one command"))
|
Description.of("A set of Floodgate related actions in one command"))
|
||||||
.senderType(UserAudience.class)
|
.senderType(UserAudience.class)
|
||||||
.permission(Permission.COMMAND_MAIN.get())
|
.permission(Permission.COMMAND_MAIN.get())
|
||||||
.handler(this::execute);
|
.handler(this::execute);
|
||||||
|
|
||||||
for (FloodgateSubCommand subCommand : subCommands()) {
|
for (FloodgateSubCommand subCommand : subCommands()) {
|
||||||
commandManager.command(builder
|
commandManager.command(builder
|
||||||
.literal(subCommand.name().toLowerCase(Locale.ROOT), subCommand.description())
|
.literal(subCommand.name().toLowerCase(Locale.ROOT), description(subCommand.description()))
|
||||||
.permission(subCommand.permission().get())
|
.permission(subCommand.permission().get())
|
||||||
.handler(subCommand::execute)
|
.handler(subCommand::execute)
|
||||||
);
|
);
|
||||||
@@ -63,12 +64,11 @@ public final class MainCommand extends SubCommands implements FloodgateCommand {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
public void execute(CommandContext<UserAudience> context) {
|
||||||
StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n");
|
StringBuilder helpMessage = new StringBuilder("Available subcommands are:\n");
|
||||||
|
|
||||||
for (FloodgateSubCommand subCommand : subCommands()) {
|
for (FloodgateSubCommand subCommand : subCommands()) {
|
||||||
if (context.getSender().hasPermission(subCommand.permission().get())) {
|
if (context.sender().hasPermission(subCommand.permission().get())) {
|
||||||
helpMessage.append('\n').append(COLOR_CHAR).append('b')
|
helpMessage.append('\n').append(COLOR_CHAR).append('b')
|
||||||
.append(subCommand.name().toLowerCase(Locale.ROOT))
|
.append(subCommand.name().toLowerCase(Locale.ROOT))
|
||||||
.append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7')
|
.append(COLOR_CHAR).append("f - ").append(COLOR_CHAR).append('7')
|
||||||
@@ -76,6 +76,6 @@ public final class MainCommand extends SubCommands implements FloodgateCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.getSender().sendMessage(helpMessage.toString());
|
context.sender().sendMessage(helpMessage.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ package org.geysermc.floodgate.core.command.main;
|
|||||||
|
|
||||||
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
import static org.geysermc.floodgate.core.util.Constants.COLOR_CHAR;
|
||||||
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||||
@@ -37,6 +36,7 @@ import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
|||||||
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateSubCommand;
|
||||||
import org.geysermc.floodgate.core.util.Constants;
|
import org.geysermc.floodgate.core.util.Constants;
|
||||||
import org.geysermc.floodgate.core.util.HttpClient;
|
import org.geysermc.floodgate.core.util.HttpClient;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
|
||||||
public class VersionSubcommand extends FloodgateSubCommand {
|
public class VersionSubcommand extends FloodgateSubCommand {
|
||||||
@Inject HttpClient httpClient;
|
@Inject HttpClient httpClient;
|
||||||
@@ -64,7 +64,7 @@ public class VersionSubcommand extends FloodgateSubCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(CommandContext<UserAudience> context) {
|
public void execute(CommandContext<UserAudience> context) {
|
||||||
UserAudience sender = context.getSender();
|
UserAudience sender = context.sender();
|
||||||
sender.sendMessage(String.format(
|
sender.sendMessage(String.format(
|
||||||
COLOR_CHAR + "7You're currently on " + COLOR_CHAR + "b%s" +
|
COLOR_CHAR + "7You're currently on " + COLOR_CHAR + "b%s" +
|
||||||
COLOR_CHAR + "7 (branch: " + COLOR_CHAR + "b%s" + COLOR_CHAR + "7)\n" +
|
COLOR_CHAR + "7 (branch: " + COLOR_CHAR + "b%s" + COLOR_CHAR + "7)\n" +
|
||||||
|
|||||||
@@ -25,14 +25,14 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.connection.audience;
|
package org.geysermc.floodgate.core.connection.audience;
|
||||||
|
|
||||||
import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext;
|
|
||||||
import cloud.commandframework.execution.preprocessor.CommandPreprocessor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.incendo.cloud.execution.preprocessor.CommandPreprocessingContext;
|
||||||
|
import org.incendo.cloud.execution.preprocessor.CommandPreprocessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command preprocessor which decorated incoming {@link cloud.commandframework.context.CommandContext}
|
* Command preprocessor which decorated incoming {@link org.incendo.cloud.context.CommandContext}
|
||||||
* with Floodgate specific objects
|
* with Floodgate specific objects
|
||||||
*
|
*
|
||||||
* @param <C> Command sender type
|
* @param <C> Command sender type
|
||||||
@@ -44,6 +44,6 @@ public final class FloodgateCommandPreprocessor<C> implements CommandPreprocesso
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(@NonNull CommandPreprocessingContext<C> context) {
|
public void accept(@NonNull CommandPreprocessingContext<C> context) {
|
||||||
context.getCommandContext().store("CommandUtil", commandUtil);
|
context.commandContext().store("CommandUtil", commandUtil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.geysermc.floodgate.core.connection.audience;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.incendo.cloud.SenderMapper;
|
||||||
|
|
||||||
|
public record FloodgateSenderMapper<T>(CommandUtil commandUtil) implements SenderMapper<T, UserAudience> {
|
||||||
|
@Override
|
||||||
|
public @NonNull UserAudience map(@NonNull T base) {
|
||||||
|
return commandUtil.getUserAudience(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public @NonNull T reverse(@NonNull UserAudience mapped) {
|
||||||
|
return (T) mapped.source();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.geysermc.floodgate.core.connection.audience;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
public final class InvalidPlayerIdentifierException extends IllegalArgumentException {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = -6500019324607183855L;
|
||||||
|
|
||||||
|
public InvalidPlayerIdentifierException(@NonNull String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Throwable fillInStackTrace() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,18 +25,80 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.connection.audience;
|
package org.geysermc.floodgate.core.connection.audience;
|
||||||
|
|
||||||
|
import static org.incendo.cloud.parser.standard.StringParser.quotedStringParser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import lombok.Getter;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.geysermc.floodgate.core.platform.util.PlayerType;
|
||||||
|
import org.geysermc.floodgate.core.util.BrigadierUtils;
|
||||||
|
import org.incendo.cloud.component.CommandComponent;
|
||||||
|
import org.incendo.cloud.parser.ArgumentParseResult;
|
||||||
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
|
|
||||||
@Getter @Accessors(fluent = true)
|
public record ProfileAudience(@Nullable UUID uuid, @Nullable String username) {
|
||||||
public final class ProfileAudience {
|
public static CommandComponent.Builder<UserAudience, ProfileAudience> ofAnyIdentifierBedrock(String name) {
|
||||||
private final @Nullable UUID uuid;
|
return of(name, true, true, PlayerType.ONLY_BEDROCK);
|
||||||
private final @Nullable String username;
|
}
|
||||||
|
|
||||||
public ProfileAudience(@Nullable UUID uuid, @Nullable String username) {
|
public static CommandComponent.Builder<UserAudience, ProfileAudience> ofAnyUsernameBoth(String name) {
|
||||||
this.uuid = uuid;
|
return of(name, false, true, PlayerType.ALL_PLAYERS);
|
||||||
this.username = username;
|
}
|
||||||
|
|
||||||
|
private static CommandComponent.Builder<UserAudience, ProfileAudience> of(String name, boolean allowUuid, boolean allowOffline, PlayerType limitTo) {
|
||||||
|
return CommandComponent.<UserAudience, ProfileAudience>builder()
|
||||||
|
.name(name)
|
||||||
|
.parser(quotedStringParser().flatMapSuccess(ProfileAudience.class, (context, input) -> {
|
||||||
|
CommandUtil commandUtil = context.get("CommandUtil");
|
||||||
|
|
||||||
|
ProfileAudience profileAudience;
|
||||||
|
if (input.length() > 16) {
|
||||||
|
// This must be a UUID.
|
||||||
|
if (!allowUuid) {
|
||||||
|
return ArgumentParseResult.failureFuture(
|
||||||
|
new InvalidPlayerIdentifierException("UUID is not allowed here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.length() != 32 && input.length() != 36) {
|
||||||
|
// Neither UUID without dashes nor with dashes.
|
||||||
|
return ArgumentParseResult.failureFuture(
|
||||||
|
new InvalidPlayerIdentifierException("Expected player name/UUID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We only want to make sure the UUID is valid here.
|
||||||
|
Object player = commandUtil.getPlayerByUuid(UUID.fromString(input), limitTo);
|
||||||
|
profileAudience = commandUtil.getProfileAudience(player, allowOffline);
|
||||||
|
} catch (final IllegalArgumentException ignored) {
|
||||||
|
return ArgumentParseResult.failureFuture(
|
||||||
|
new InvalidPlayerIdentifierException("Invalid UUID '" + input + "'"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is a username.
|
||||||
|
Object player = commandUtil.getPlayerByUsername(input, limitTo);
|
||||||
|
profileAudience = commandUtil.getProfileAudience(player, allowOffline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profileAudience == null) {
|
||||||
|
return ArgumentParseResult.failureFuture(
|
||||||
|
new InvalidPlayerIdentifierException("Invalid player '" + input + "'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArgumentParseResult.successFuture(profileAudience);
|
||||||
|
}))
|
||||||
|
.suggestionProvider((context, input) -> {
|
||||||
|
CommandUtil commandUtil = context.get("CommandUtil");
|
||||||
|
|
||||||
|
var quoted = input.remainingInput().startsWith("\"");
|
||||||
|
|
||||||
|
var suggestions = new ArrayList<Suggestion>();
|
||||||
|
for (final String player : commandUtil.getOnlineUsernames(limitTo)) {
|
||||||
|
suggestions.add(Suggestion.simple(BrigadierUtils.escapeIfRequired(player, quoted)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompletableFuture.completedFuture(suggestions);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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/Floodgate
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.geysermc.floodgate.core.connection.audience;
|
|
||||||
|
|
||||||
import cloud.commandframework.arguments.CommandArgument;
|
|
||||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
|
||||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.UUID;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
|
||||||
import org.geysermc.floodgate.core.platform.util.PlayerType;
|
|
||||||
|
|
||||||
public class ProfileAudienceArgument extends CommandArgument<UserAudience, ProfileAudience> {
|
|
||||||
private ProfileAudienceArgument(@NonNull String name, ProfileAudienceParser parser) {
|
|
||||||
super(true, name, parser, ProfileAudience.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProfileAudienceArgument of(
|
|
||||||
String name,
|
|
||||||
boolean allowUuid,
|
|
||||||
boolean allowOffline,
|
|
||||||
PlayerType limitTo) {
|
|
||||||
return new ProfileAudienceArgument(name,
|
|
||||||
new ProfileAudienceParser(allowUuid, allowOffline, limitTo));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProfileAudienceArgument of(
|
|
||||||
String name,
|
|
||||||
boolean allowOffline,
|
|
||||||
PlayerType limitTo) {
|
|
||||||
return of(name, false, allowOffline, limitTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProfileAudienceArgument ofOnline(String name, PlayerType limitTo) {
|
|
||||||
return of(name, false, false, limitTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProfileAudienceArgument ofOnline(String name, boolean allowUuid) {
|
|
||||||
return of(name, allowUuid, false, PlayerType.ALL_PLAYERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CommandArgument<UserAudience, ProfileAudience> ofOnline(String name) {
|
|
||||||
return of(name, false, false, PlayerType.ALL_PLAYERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProfileAudienceArgument of(String name, boolean allowOffline) {
|
|
||||||
return of(name, false, allowOffline, PlayerType.ALL_PLAYERS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public static final class ProfileAudienceParser
|
|
||||||
implements ArgumentParser<UserAudience, ProfileAudience> {
|
|
||||||
|
|
||||||
private final boolean allowUuid;
|
|
||||||
private final boolean allowOffline;
|
|
||||||
private final PlayerType limitTo;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull ArgumentParseResult<ProfileAudience> parse(
|
|
||||||
@NonNull CommandContext<@NonNull UserAudience> commandContext,
|
|
||||||
@NonNull Queue<@NonNull String> inputQueue) {
|
|
||||||
CommandUtil commandUtil = commandContext.get("CommandUtil");
|
|
||||||
|
|
||||||
String input = inputQueue.poll();
|
|
||||||
if (input == null || input.length() < 3) {
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new NullPointerException("Expected player name/UUID"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.startsWith("\"")) {
|
|
||||||
if (input.endsWith("\"")) {
|
|
||||||
// Remove quotes from both sides of this string
|
|
||||||
input = input.substring(1);
|
|
||||||
input = input.substring(0, input.length() - 1);
|
|
||||||
} else {
|
|
||||||
// Multi-line
|
|
||||||
StringBuilder builder = new StringBuilder(input);
|
|
||||||
while (!inputQueue.isEmpty()) {
|
|
||||||
String string = inputQueue.remove();
|
|
||||||
builder.append(' ').append(string);
|
|
||||||
if (string.endsWith("\"")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder.lastIndexOf("\"") != builder.length() - 1) {
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new InvalidPlayerIdentifierException("Malformed string provided; " +
|
|
||||||
"no end quotes found!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.deleteCharAt(0);
|
|
||||||
builder.deleteCharAt(builder.length() - 1);
|
|
||||||
input = builder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfileAudience profileAudience;
|
|
||||||
|
|
||||||
if (input.length() > 16) {
|
|
||||||
// This must be a UUID.
|
|
||||||
if (!allowUuid) {
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new InvalidPlayerIdentifierException("UUID is not allowed here"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.length() != 32 && input.length() != 36) {
|
|
||||||
// Neither UUID without dashes nor with dashes.
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new InvalidPlayerIdentifierException("Expected player name/UUID"));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// We only want to make sure the UUID is valid here.
|
|
||||||
Object player = commandUtil.getPlayerByUuid(UUID.fromString(input), limitTo);
|
|
||||||
profileAudience = commandUtil.getProfileAudience(player, allowOffline);
|
|
||||||
} catch (final IllegalArgumentException ignored) {
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new InvalidPlayerIdentifierException("Invalid UUID '" + input + "'"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// This is a username.
|
|
||||||
Object player = commandUtil.getPlayerByUsername(input, limitTo);
|
|
||||||
profileAudience = commandUtil.getProfileAudience(player, allowOffline);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profileAudience == null) {
|
|
||||||
return ArgumentParseResult.failure(
|
|
||||||
new InvalidPlayerIdentifierException("Invalid player '" + input + "'"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ArgumentParseResult.success(profileAudience);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull List<String> suggestions(
|
|
||||||
@NonNull CommandContext<UserAudience> commandContext,
|
|
||||||
@NonNull String input) {
|
|
||||||
CommandUtil commandUtil = commandContext.get("CommandUtil");
|
|
||||||
String trimmedInput = input.trim();
|
|
||||||
|
|
||||||
if (trimmedInput.isEmpty()) {
|
|
||||||
return Collections.unmodifiableList(commandUtil.getOnlineUsernames(limitTo));
|
|
||||||
}
|
|
||||||
|
|
||||||
String lowercaseInput = input.toLowerCase(Locale.ROOT);
|
|
||||||
List<String> profileSuggestions = new ArrayList<>();
|
|
||||||
|
|
||||||
for (final String player : commandUtil.getOnlineUsernames(limitTo)) {
|
|
||||||
if (player.toLowerCase(Locale.ROOT).startsWith(lowercaseInput)) {
|
|
||||||
profileSuggestions.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(profileSuggestions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isContextFree() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class InvalidPlayerIdentifierException extends IllegalArgumentException {
|
|
||||||
private static final long serialVersionUID = -6500019324607183855L;
|
|
||||||
|
|
||||||
public InvalidPlayerIdentifierException(@NonNull String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull Throwable fillInStackTrace() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,11 +25,10 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.platform.command;
|
package org.geysermc.floodgate.core.platform.command;
|
||||||
|
|
||||||
import cloud.commandframework.Command;
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
|
import org.incendo.cloud.Command;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
|
||||||
/** The base class for every Floodgate command. */
|
/** The base class for every Floodgate command. */
|
||||||
public interface FloodgateCommand {
|
public interface FloodgateCommand {
|
||||||
@@ -39,14 +38,7 @@ public interface FloodgateCommand {
|
|||||||
* @param commandManager the manager to create a command
|
* @param commandManager the manager to create a command
|
||||||
* @return the command to register
|
* @return the command to register
|
||||||
*/
|
*/
|
||||||
Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager);
|
Command<? extends UserAudience> buildCommand(CommandManager<UserAudience> commandManager);
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the command created in {@link #buildCommand(CommandManager)} is executed.
|
|
||||||
*
|
|
||||||
* @param context the context of the executed command
|
|
||||||
*/
|
|
||||||
void execute(CommandContext<UserAudience> context);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the CommandRegister to check if the command should be added given the config.
|
* Called by the CommandRegister to check if the command should be added given the config.
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.platform.command;
|
package org.geysermc.floodgate.core.platform.command;
|
||||||
|
|
||||||
import cloud.commandframework.context.CommandContext;
|
|
||||||
import org.geysermc.floodgate.core.command.util.Permission;
|
import org.geysermc.floodgate.core.command.util.Permission;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
|
||||||
public abstract class FloodgateSubCommand {
|
public abstract class FloodgateSubCommand {
|
||||||
public abstract Class<?> parent();
|
public abstract Class<?> parent();
|
||||||
|
|||||||
@@ -25,13 +25,13 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.core.register;
|
package org.geysermc.floodgate.core.register;
|
||||||
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
import org.geysermc.floodgate.core.platform.command.FloodgateCommand;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for registering commands to the command register of the platform that
|
* This class is responsible for registering commands to the command register of the platform that
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.geysermc.floodgate.core.util;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Code taken from Brigadier's StringArgumentType and StringReader
|
||||||
|
*/
|
||||||
|
public final class BrigadierUtils {
|
||||||
|
public static boolean isAllowedInUnquotedString(char c) {
|
||||||
|
return c >= '0' && c <= '9' ||
|
||||||
|
c >= 'A' && c <= 'Z' ||
|
||||||
|
c >= 'a' && c <= 'z' ||
|
||||||
|
c == '_' || c == '-' ||
|
||||||
|
c == '.' || c == '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapeIfRequired(String input) {
|
||||||
|
for (final char c : input.toCharArray()) {
|
||||||
|
if (!isAllowedInUnquotedString(c)) {
|
||||||
|
return "\"" + input + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapeIfRequired(String input, boolean quoted) {
|
||||||
|
if (quoted) {
|
||||||
|
return escape(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final char c : input.toCharArray()) {
|
||||||
|
if (!isAllowedInUnquotedString(c)) {
|
||||||
|
return "\"" + input + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String escape(final String input) {
|
||||||
|
final StringBuilder result = new StringBuilder("\"");
|
||||||
|
|
||||||
|
for (int i = 0; i < input.length(); i++) {
|
||||||
|
final char c = input.charAt(i);
|
||||||
|
if (c == '\\' || c == '"') {
|
||||||
|
result.append('\\');
|
||||||
|
}
|
||||||
|
result.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append("\"");
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[versions]
|
[versions]
|
||||||
# parent
|
# parent
|
||||||
micronaut-gradle = "4.3.2"
|
micronaut-gradle = "4.3.2"
|
||||||
lombok = "8.0.1"
|
lombok = "8.4"
|
||||||
|
|
||||||
# api
|
# api
|
||||||
cumulus = "2.0.0-SNAPSHOT"
|
cumulus = "2.0.0-SNAPSHOT"
|
||||||
@@ -14,8 +14,7 @@ base-api = "feature-floodgate-merge-1.1.0-SNAPSHOT"
|
|||||||
configurate = "4.2.0-GeyserMC-SNAPSHOT"
|
configurate = "4.2.0-GeyserMC-SNAPSHOT"
|
||||||
database-utils = "1.0-SNAPSHOT"
|
database-utils = "1.0-SNAPSHOT"
|
||||||
fastutil = "8.5.3"
|
fastutil = "8.5.3"
|
||||||
java-websocket = "1.5.2"
|
cloud = "2.0.0-beta.2"
|
||||||
cloud = "1.5.0"
|
|
||||||
snakeyaml = "2.0"
|
snakeyaml = "2.0"
|
||||||
bstats = "3.0.2"
|
bstats = "3.0.2"
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@ velocity = "3.2.0-SNAPSHOT"
|
|||||||
indra = "3.1.3"
|
indra = "3.1.3"
|
||||||
shadow = "8.1.1"
|
shadow = "8.1.1"
|
||||||
gradle-idea-ext = "1.1.7"
|
gradle-idea-ext = "1.1.7"
|
||||||
checkerframework = "3.19.0"
|
checkerframework = "3.42.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# indirectly included
|
# indirectly included
|
||||||
@@ -56,7 +55,7 @@ database-utils-mongo = { module = "org.geysermc.databaseutils:database-mongo", v
|
|||||||
database-utils-ap = { module = "org.geysermc.databaseutils:ap", version.ref = "database-utils" }
|
database-utils-ap = { module = "org.geysermc.databaseutils:ap", version.ref = "database-utils" }
|
||||||
fastutil-short-object-maps = { module = "com.nukkitx.fastutil:fastutil-short-object-maps", version.ref = "fastutil" }
|
fastutil-short-object-maps = { module = "com.nukkitx.fastutil:fastutil-short-object-maps", version.ref = "fastutil" }
|
||||||
fastutil-int-object-maps = { module = "com.nukkitx.fastutil:fastutil-int-object-maps", version.ref = "fastutil" }
|
fastutil-int-object-maps = { module = "com.nukkitx.fastutil:fastutil-int-object-maps", version.ref = "fastutil" }
|
||||||
cloud-core = { module = "cloud.commandframework:cloud-core", version.ref = "cloud" }
|
cloud-core = { module = "org.incendo:cloud-core", version.ref = "cloud" }
|
||||||
snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" }
|
snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" }
|
||||||
bstats = { module = "org.bstats:bstats-base", version.ref = "bstats" }
|
bstats = { module = "org.bstats:bstats-base", version.ref = "bstats" }
|
||||||
|
|
||||||
@@ -78,15 +77,15 @@ junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher
|
|||||||
|
|
||||||
# bungee
|
# bungee
|
||||||
bungee = { module = "com.github.SpigotMC.BungeeCord:bungeecord-proxy", version.ref = "bungee" }
|
bungee = { module = "com.github.SpigotMC.BungeeCord:bungeecord-proxy", version.ref = "bungee" }
|
||||||
cloud-bungee = { module = "cloud.commandframework:cloud-bungee", version.ref = "cloud" }
|
cloud-bungee = { module = "org.incendo:cloud-bungee", version.ref = "cloud" }
|
||||||
|
|
||||||
# spigot
|
# spigot
|
||||||
paper-api = { module = "io.papermc.paper:paper-api", version.ref = "paper" }
|
paper-api = { module = "io.papermc.paper:paper-api", version.ref = "paper" }
|
||||||
cloud-bukkit = { module = "cloud.commandframework:cloud-bukkit", version.ref = "cloud" }
|
cloud-paper = { module = "org.incendo:cloud-paper", version.ref = "cloud" }
|
||||||
authlib = { module = "com.mojang:authlib", version.ref = "authlib" }
|
authlib = { module = "com.mojang:authlib", version.ref = "authlib" }
|
||||||
|
|
||||||
# velocity
|
# velocity
|
||||||
cloud-velocity = { module = "cloud.commandframework:cloud-velocity", version.ref = "cloud" }
|
cloud-velocity = { module = "org.incendo:cloud-velocity", version.ref = "cloud" }
|
||||||
velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
|
velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
|
||||||
|
|
||||||
# buildSrc
|
# buildSrc
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ dependencies {
|
|||||||
annotationProcessor(libs.micronaut.inject.java)
|
annotationProcessor(libs.micronaut.inject.java)
|
||||||
compileOnlyApi(projects.isolation)
|
compileOnlyApi(projects.isolation)
|
||||||
|
|
||||||
implementation(libs.cloud.bukkit)
|
implementation(libs.cloud.paper)
|
||||||
|
|
||||||
compileOnlyApi(libs.paper.api)
|
compileOnlyApi(libs.paper.api)
|
||||||
}
|
}
|
||||||
|
|
||||||
relocate("net.kyori")
|
relocate("net.kyori")
|
||||||
relocate("cloud.commandframework")
|
relocate("org.incendo.cloud")
|
||||||
relocate("io.leangen.geantyref") // used in cloud
|
relocate("io.leangen.geantyref") // used in cloud
|
||||||
// hack to make (old versions? of) Paper work
|
// hack to make (old versions? of) Paper work
|
||||||
relocate("it.unimi")
|
relocate("it.unimi")
|
||||||
|
|||||||
@@ -25,23 +25,23 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.spigot.command;
|
package org.geysermc.floodgate.spigot.command;
|
||||||
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.bukkit.BukkitCommandManager;
|
|
||||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
|
||||||
import io.micronaut.context.annotation.Bean;
|
import io.micronaut.context.annotation.Bean;
|
||||||
import io.micronaut.context.annotation.Factory;
|
import io.micronaut.context.annotation.Factory;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.permissions.PermissionDefault;
|
import org.bukkit.permissions.PermissionDefault;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.geysermc.floodgate.core.command.util.Permission;
|
import org.geysermc.floodgate.core.command.util.Permission;
|
||||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||||
|
import org.geysermc.floodgate.core.connection.audience.FloodgateSenderMapper;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||||
|
import org.incendo.cloud.paper.PaperCommandManager;
|
||||||
|
|
||||||
@Factory
|
@Factory
|
||||||
public class SpigotCommandManager {
|
public class SpigotCommandManager {
|
||||||
@@ -49,11 +49,10 @@ public class SpigotCommandManager {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Singleton
|
@Singleton
|
||||||
public CommandManager<UserAudience> commandManager(CommandUtil commandUtil, JavaPlugin plugin) {
|
public CommandManager<UserAudience> commandManager(CommandUtil commandUtil, JavaPlugin plugin) {
|
||||||
CommandManager<UserAudience> commandManager = new BukkitCommandManager<>(
|
var commandManager = new PaperCommandManager<>(
|
||||||
plugin,
|
plugin,
|
||||||
CommandExecutionCoordinator.simpleCoordinator(),
|
ExecutionCoordinator.simpleCoordinator(),
|
||||||
commandUtil::getUserAudience,
|
new FloodgateSenderMapper<>(commandUtil)
|
||||||
audience -> (CommandSender) audience.source()
|
|
||||||
);
|
);
|
||||||
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
||||||
return commandManager;
|
return commandManager;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ dependencies {
|
|||||||
implementation(libs.cloud.velocity)
|
implementation(libs.cloud.velocity)
|
||||||
}
|
}
|
||||||
|
|
||||||
relocate("cloud.commandframework")
|
relocate("org.incendo.cloud")
|
||||||
relocate("io.leangen.geantyref") // used in cloud
|
relocate("io.leangen.geantyref") // used in cloud
|
||||||
|
|
||||||
relocate("org.yaml.snakeyaml")
|
relocate("org.yaml.snakeyaml")
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.floodgate.velocity.module;
|
package org.geysermc.floodgate.velocity.module;
|
||||||
|
|
||||||
import cloud.commandframework.CommandManager;
|
|
||||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
|
||||||
import cloud.commandframework.velocity.VelocityCommandManager;
|
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
|
||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import io.micronaut.context.annotation.Bean;
|
import io.micronaut.context.annotation.Bean;
|
||||||
@@ -36,8 +32,12 @@ import io.micronaut.context.annotation.Factory;
|
|||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
import org.geysermc.floodgate.core.connection.audience.FloodgateCommandPreprocessor;
|
||||||
|
import org.geysermc.floodgate.core.connection.audience.FloodgateSenderMapper;
|
||||||
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
import org.geysermc.floodgate.core.connection.audience.UserAudience;
|
||||||
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
import org.geysermc.floodgate.core.platform.command.CommandUtil;
|
||||||
|
import org.incendo.cloud.CommandManager;
|
||||||
|
import org.incendo.cloud.execution.ExecutionCoordinator;
|
||||||
|
import org.incendo.cloud.velocity.VelocityCommandManager;
|
||||||
|
|
||||||
@Factory
|
@Factory
|
||||||
public class VelocityPlatformModule {
|
public class VelocityPlatformModule {
|
||||||
@@ -48,12 +48,11 @@ public class VelocityPlatformModule {
|
|||||||
ProxyServer proxy,
|
ProxyServer proxy,
|
||||||
PluginContainer container
|
PluginContainer container
|
||||||
) {
|
) {
|
||||||
CommandManager<UserAudience> commandManager = new VelocityCommandManager<>(
|
var commandManager = new VelocityCommandManager<>(
|
||||||
container,
|
container,
|
||||||
proxy,
|
proxy,
|
||||||
CommandExecutionCoordinator.simpleCoordinator(),
|
ExecutionCoordinator.simpleCoordinator(),
|
||||||
commandUtil::getUserAudience,
|
new FloodgateSenderMapper<>(commandUtil)
|
||||||
audience -> (CommandSource) audience.source()
|
|
||||||
);
|
);
|
||||||
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));
|
||||||
return commandManager;
|
return commandManager;
|
||||||
|
|||||||
Reference in New Issue
Block a user