diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 21f130da..3c7ae839 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -29,6 +29,7 @@ import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; import java.util.UUID; @@ -37,25 +38,27 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { private GeyserBukkitConfiguration geyserConfig; private GeyserBukkitLogger geyserLogger; + private GeyserConnector connector; + @Override public void onEnable() { saveDefaultConfig(); - geyserConfig = new GeyserBukkitConfiguration(getDataFolder(), getConfig()); - + this.geyserConfig = new GeyserBukkitConfiguration(getDataFolder(), getConfig()); if (geyserConfig.getMetrics().getUniqueId().equals("generateduuid")) { getConfig().set("metrics.uuid", UUID.randomUUID().toString()); saveConfig(); } - geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); + this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); + this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); - GeyserConnector.start(PlatformType.BUKKIT, this); + this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); } @Override public void onDisable() { - GeyserConnector.stop(); + connector.shutdown(); } @Override diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java new file mode 100644 index 00000000..05e371e5 --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020 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.platform.bukkit.command; + +import lombok.AllArgsConstructor; + +import org.bukkit.command.ConsoleCommandSender; +import org.geysermc.connector.command.CommandSender; + +@AllArgsConstructor +public class BukkitCommandSender implements CommandSender { + + private org.bukkit.command.CommandSender handle; + + @Override + public String getName() { + return handle.getName(); + } + + @Override + public void sendMessage(String message) { + handle.sendMessage(message); + } + + @Override + public boolean isConsole() { + return handle instanceof ConsoleCommandSender; + } +} diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java new file mode 100644 index 00000000..84920db7 --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019-2020 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.platform.bukkit.command; + +import lombok.AllArgsConstructor; + +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.GeyserCommand; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@AllArgsConstructor +public class GeyserBukkitCommandExecutor implements TabExecutor { + + private GeyserConnector connector; + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length > 0) { + if (getCommand(args[0]) != null) { + if (!sender.hasPermission(getCommand(args[0]).getPermission())) { + sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!"); + return true; + } + getCommand(args[0]).execute(new BukkitCommandSender(sender), args); + return true; + } + } else { + getCommand("help").execute(new BukkitCommandSender(sender), args); + return true; + } + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 1) { + return Arrays.asList("?", "help", "reload", "shutdown", "stop"); + } + return new ArrayList<>(); + } + + private GeyserCommand getCommand(String label) { + return connector.getCommandMap().getCommands().get(label); + } +} diff --git a/bootstrap/bukkit/src/main/resources/plugin.yml b/bootstrap/bukkit/src/main/resources/plugin.yml index b67547f2..8e002eb2 100644 --- a/bootstrap/bukkit/src/main/resources/plugin.yml +++ b/bootstrap/bukkit/src/main/resources/plugin.yml @@ -2,4 +2,8 @@ main: org.geysermc.platform.bukkit.GeyserBukkitPlugin name: ${outputName}-Bukkit author: ${project.organization.name} website: ${project.organization.url} -version: ${project.version} \ No newline at end of file +version: ${project.version} +commands: + geyser: + description: The main command for Geyser. + usage: /geyser help \ No newline at end of file diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index b396ede5..d6974daf 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -33,6 +33,7 @@ import net.md_5.bungee.config.YamlConfiguration; import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor; import java.io.File; import java.io.IOException; @@ -46,6 +47,8 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { private GeyserBungeeConfiguration geyserConfig; private GeyserBungeeLogger geyserLogger; + private GeyserConnector connector; + @Override public void onEnable() { if (!getDataFolder().exists()) @@ -73,7 +76,7 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { return; } - geyserConfig = new GeyserBungeeConfiguration(getDataFolder(), configuration); + this.geyserConfig = new GeyserBungeeConfiguration(getDataFolder(), configuration); if (geyserConfig.getMetrics().getUniqueId().equals("generateduuid")) { configuration.set("metrics.uuid", UUID.randomUUID().toString()); @@ -85,14 +88,15 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { } } - geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); + this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); + this.connector = GeyserConnector.start(PlatformType.BUNGEECORD, this); - GeyserConnector.start(PlatformType.BUNGEECORD, this); + this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(connector)); } @Override public void onDisable() { - GeyserConnector.stop(); + connector.shutdown(); } @Override diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/BungeeCommandSender.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/BungeeCommandSender.java new file mode 100644 index 00000000..d40dc902 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/BungeeCommandSender.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020 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.platform.bungeecord.command; + +import lombok.AllArgsConstructor; + +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import org.geysermc.connector.command.CommandSender; + +@AllArgsConstructor +public class BungeeCommandSender implements CommandSender { + + private net.md_5.bungee.api.CommandSender handle; + + @Override + public String getName() { + return handle.getName(); + } + + @Override + public void sendMessage(String message) { + handle.sendMessage(TextComponent.fromLegacyText(message)); + } + + @Override + public boolean isConsole() { + return !(handle instanceof ProxiedPlayer); + } +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java new file mode 100644 index 00000000..8149d291 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019-2020 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.platform.bungeecord.command; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.TabExecutor; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.GeyserCommand; + +import java.util.ArrayList; +import java.util.Arrays; + +public class GeyserBungeeCommandExecutor extends Command implements TabExecutor { + + private GeyserConnector connector; + + public GeyserBungeeCommandExecutor(GeyserConnector connector) { + super("geyser"); + + this.connector = connector; + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (args.length > 0) { + if (getCommand(args[0]) != null) { + if (!sender.hasPermission(getCommand(args[0]).getPermission())) { + sender.sendMessage(TextComponent.fromLegacyText(ChatColor.RED + "You do not have permission to execute this command!")); + return; + } + getCommand(args[0]).execute(new BungeeCommandSender(sender), args); + } + } else { + getCommand("help").execute(new BungeeCommandSender(sender), args); + } + } + + @Override + public Iterable onTabComplete(CommandSender sender, String[] args) { + if (args.length == 1) { + return Arrays.asList("?", "help", "reload", "shutdown", "stop"); + } + return new ArrayList<>(); + } + + private GeyserCommand getCommand(String label) { + return connector.getCommandMap().getCommands().get(label); + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 15ab0d1f..a2074b15 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -34,7 +34,9 @@ import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor; import org.slf4j.Logger; +import org.spongepowered.api.Sponge; import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.game.state.GameStartedServerEvent; @@ -58,6 +60,8 @@ public class GeyserSpongePlugin implements IGeyserBootstrap { private GeyserSpongeConfiguration geyserConfig; private GeyserSpongeLogger geyserLogger; + private GeyserConnector connector; + @Override public void onEnable() { if (!configDir.exists()) @@ -81,13 +85,14 @@ public class GeyserSpongePlugin implements IGeyserBootstrap { } this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); + this.connector = GeyserConnector.start(PlatformType.SPONGE, this); - GeyserConnector.start(PlatformType.SPONGE, this); + Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(connector), "geyser"); } @Override public void onDisable() { - GeyserConnector.stop(); + connector.shutdown(); } @Override diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java new file mode 100644 index 00000000..c68ff4e4 --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2019-2020 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.platform.sponge.command; + +import lombok.AllArgsConstructor; + +import org.geysermc.common.ChatColor; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.GeyserCommand; +import org.spongepowered.api.command.CommandCallable; +import org.spongepowered.api.command.CommandException; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.text.Text; +import org.spongepowered.api.world.Location; +import org.spongepowered.api.world.World; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +@AllArgsConstructor +public class GeyserSpongeCommandExecutor implements CommandCallable { + + private GeyserConnector connector; + + @Override + public CommandResult process(CommandSource source, String arguments) throws CommandException { + String[] args = arguments.split(" "); + if (args.length > 0) { + if (getCommand(args[0]) != null) { + if (!source.hasPermission(getCommand(args[0]).getPermission())) { + source.sendMessage(Text.of(ChatColor.RED + "You do not have permission to execute this command!")); + return CommandResult.success(); + } + getCommand(args[0]).execute(new SpongeCommandSender(source), args); + } + } else { + getCommand("help").execute(new SpongeCommandSender(source), args); + } + return CommandResult.success(); + } + + @Override + public List getSuggestions(CommandSource source, String arguments, @Nullable Location targetPosition) throws CommandException { + if (arguments.split(" ").length == 1) { + return Arrays.asList("?", "help", "reload", "shutdown", "stop"); + } + return new ArrayList<>(); + } + + @Override + public boolean testPermission(CommandSource source) { + return true; + } + + @Override + public Optional getShortDescription(CommandSource source) { + return Optional.of(Text.of("The main command for Geyser.")); + } + + @Override + public Optional getHelp(CommandSource source) { + return Optional.of(Text.of("/geyser help")); + } + + @Override + public Text getUsage(CommandSource source) { + return Text.of("/geyser help"); + } + + private GeyserCommand getCommand(String label) { + return connector.getCommandMap().getCommands().get(label); + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/SpongeCommandSender.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/SpongeCommandSender.java new file mode 100644 index 00000000..a309a26f --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/SpongeCommandSender.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020 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.platform.sponge.command; + +import lombok.AllArgsConstructor; + +import org.geysermc.connector.command.CommandSender; +import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.command.source.ConsoleSource; +import org.spongepowered.api.text.Text; + +@AllArgsConstructor +public class SpongeCommandSender implements CommandSender { + + private CommandSource handle; + + @Override + public String getName() { + return handle.getName(); + } + + @Override + public void sendMessage(String message) { + handle.sendMessage(Text.of(message)); + } + + @Override + public boolean isConsole() { + return handle instanceof ConsoleSource; + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java index 19974538..1ba111e7 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java @@ -40,6 +40,8 @@ public class GeyserBootstrap implements IGeyserBootstrap { private GeyserConfiguration geyserConfig; private GeyserLogger geyserLogger; + private GeyserConnector connector; + public static void main(String[] args) { new GeyserBootstrap().onEnable(); } @@ -56,13 +58,13 @@ public class GeyserBootstrap implements IGeyserBootstrap { System.exit(0); } - GeyserConnector.start(PlatformType.STANDALONE, this); + connector = GeyserConnector.start(PlatformType.STANDALONE, this); geyserLogger.start(); } @Override public void onDisable() { - GeyserConnector.stop(); + connector.shutdown(); System.exit(0); } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 4020b81e..5ab411f3 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -27,6 +27,7 @@ package org.geysermc.platform.velocity; import com.google.inject.Inject; +import com.velocitypowered.api.command.CommandManager; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; @@ -36,6 +37,7 @@ import org.geysermc.common.PlatformType; import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor; import org.slf4j.Logger; import java.io.File; @@ -48,9 +50,13 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { @Inject private Logger logger; + @Inject + private CommandManager commandManager; + private GeyserVelocityConfiguration geyserConfig; private GeyserVelocityLogger geyserLogger; + private GeyserConnector connector; @Override public void onEnable() { @@ -59,19 +65,21 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { if (!configDir.exists()) configDir.mkdir(); File configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); - geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); } catch (IOException ex) { logger.warn("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); ex.printStackTrace(); } this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); - GeyserConnector.start(PlatformType.VELOCITY, this); + this.connector = GeyserConnector.start(PlatformType.VELOCITY, this); + + this.commandManager.register(new GeyserVelocityCommandExecutor(connector), "geyser"); } @Override public void onDisable() { - GeyserConnector.stop(); + connector.shutdown(); } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java new file mode 100644 index 00000000..39a0af97 --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019-2020 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.platform.velocity.command; + +import com.velocitypowered.api.command.Command; +import com.velocitypowered.api.command.CommandSource; + +import lombok.AllArgsConstructor; + +import net.kyori.text.TextComponent; + +import org.geysermc.common.ChatColor; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.GeyserCommand; + +@AllArgsConstructor +public class GeyserVelocityCommandExecutor implements Command { + + private GeyserConnector connector; + + @Override + public void execute(CommandSource source, String[] args) { + if (args.length > 0) { + if (getCommand(args[0]) != null) { + if (!source.hasPermission(getCommand(args[0]).getPermission())) { + source.sendMessage(TextComponent.of(ChatColor.RED + "You do not have permission to execute this command!")); + return; + } + getCommand(args[0]).execute(new VelocityCommandSender(source), args); + } + } else { + getCommand("help").execute(new VelocityCommandSender(source), args); + } + } + + private GeyserCommand getCommand(String label) { + return connector.getCommandMap().getCommands().get(label); + } +} diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/VelocityCommandSender.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/VelocityCommandSender.java new file mode 100644 index 00000000..1b0d6f3e --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/VelocityCommandSender.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019-2020 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.platform.velocity.command; + +import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.proxy.ConsoleCommandSource; +import com.velocitypowered.api.proxy.Player; + +import lombok.AllArgsConstructor; + +import net.kyori.text.TextComponent; + +import org.geysermc.connector.command.CommandSender; + +@AllArgsConstructor +public class VelocityCommandSender implements CommandSender { + + private CommandSource handle; + + @Override + public String getName() { + if (handle instanceof Player) { + return ((Player) handle).getUsername(); + } else if (handle instanceof ConsoleCommandSource) { + return "CONSOLE"; + } + return ""; + } + + @Override + public void sendMessage(String message) { + handle.sendMessage(TextComponent.of(message)); + } + + @Override + public boolean isConsole() { + return handle instanceof ConsoleCommandSource; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 12c09e16..401e3eb9 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -68,9 +68,6 @@ public class GeyserConnector { private RemoteServer remoteServer; private AuthType authType; - private IGeyserLogger logger; - private IGeyserConfiguration config; - private GeyserCommandMap commandMap; private boolean shuttingDown = false; @@ -80,15 +77,20 @@ public class GeyserConnector { private BedrockServer bedrockServer; private PlatformType platformType; + private IGeyserBootstrap bootstrap; private Metrics metrics; - private GeyserConnector(PlatformType platformType, IGeyserConfiguration config, IGeyserLogger logger) { + private GeyserConnector(PlatformType platformType, IGeyserBootstrap bootstrap) { long startupTime = System.currentTimeMillis(); instance = this; - this.logger = logger; + this.bootstrap = bootstrap; + + IGeyserLogger logger = bootstrap.getGeyserLogger(); + IGeyserConfiguration config = bootstrap.getGeyserConfig(); + this.platformType = platformType; logger.info("******************************************"); @@ -97,7 +99,6 @@ public class GeyserConnector { logger.info(""); logger.info("******************************************"); - this.config = config; this.generalThreadPool = Executors.newScheduledThreadPool(config.getGeneralThreadPool()); logger.setDebug(config.isDebugMode()); @@ -137,11 +138,16 @@ public class GeyserConnector { } public void shutdown() { - logger.info("Shutting down Geyser."); + bootstrap.getGeyserLogger().info("Shutting down Geyser."); shuttingDown = true; generalThreadPool.shutdown(); bedrockServer.close(); + players.clear(); + remoteServer = null; + authType = null; + commandMap.getCommands().clear(); + commandMap = null; } public void addPlayer(GeyserSession player) { @@ -157,11 +163,20 @@ public class GeyserConnector { } public static GeyserConnector start(PlatformType platformType, IGeyserBootstrap bootstrap) { - return new GeyserConnector(platformType, bootstrap.getGeyserConfig(), bootstrap.getGeyserLogger()); + return new GeyserConnector(platformType, bootstrap); } - public static void stop() { - instance.shutdown(); + public void reload() { + shutdown(); + bootstrap.onEnable(); + } + + public IGeyserLogger getLogger() { + return bootstrap.getGeyserLogger(); + } + + public IGeyserConfiguration getConfig() { + return bootstrap.getGeyserConfig(); } public static GeyserConnector getInstance() { diff --git a/connector/src/main/java/org/geysermc/connector/command/GeyserCommand.java b/connector/src/main/java/org/geysermc/connector/command/GeyserCommand.java index ea8ed874..62bc6c73 100644 --- a/connector/src/main/java/org/geysermc/connector/command/GeyserCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/GeyserCommand.java @@ -25,33 +25,23 @@ package org.geysermc.connector.command; -import lombok.AccessLevel; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Setter; import java.util.ArrayList; import java.util.List; @Getter -@Setter +@RequiredArgsConstructor public abstract class GeyserCommand { - private String name; - private String description; - - @Setter(AccessLevel.NONE) - private GeyserCommandMap commandMap; + protected final String name; + protected final String description; + protected final String permission; + @Setter private List aliases = new ArrayList<>(); - public GeyserCommand(String name) { - this(name, "A geyser command."); - } - - public GeyserCommand(String name, String description) { - this.name = name; - this.description = description; - } - public abstract void execute(CommandSender sender, String[] args); -} +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java b/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java index 7172622c..c4bf488e 100644 --- a/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java +++ b/connector/src/main/java/org/geysermc/connector/command/GeyserCommandMap.java @@ -25,8 +25,10 @@ package org.geysermc.connector.command; +import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.defaults.HelpCommand; +import org.geysermc.connector.command.defaults.ReloadCommand; import org.geysermc.connector.command.defaults.StopCommand; import java.util.Collections; @@ -35,37 +37,35 @@ import java.util.Map; public class GeyserCommandMap { - private final Map commandMap = Collections.synchronizedMap(new HashMap<>()); + @Getter + private final Map commands = Collections.synchronizedMap(new HashMap<>()); + private GeyserConnector connector; public GeyserCommandMap(GeyserConnector connector) { this.connector = connector; - registerDefaults(); - } - - public void registerDefaults() { - registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.")); - registerCommand(new StopCommand(connector, "stop", "Shut down Geyser.")); + registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.", "geyser.command.help")); + registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload")); + registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop")); } public void registerCommand(GeyserCommand command) { - commandMap.put(command.getName(), command); + commands.put(command.getName(), command); connector.getLogger().debug("Registered command " + command.getName()); if (command.getAliases().isEmpty()) return; for (String alias : command.getAliases()) - commandMap.put(alias, command); + commands.put(alias, command); } public void runCommand(CommandSender sender, String command) { if (!command.startsWith("geyser ")) return; - command = command.trim(); - command = command.replace("geyser ", ""); + command = command.trim().replace("geyser ", ""); String label; String[] args; @@ -78,7 +78,7 @@ public class GeyserCommandMap { args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine }; } - GeyserCommand cmd = commandMap.get(label); + GeyserCommand cmd = commands.get(label); if (cmd == null) { connector.getLogger().error("Invalid Command! Try /geyser help for a list of commands."); return; @@ -86,8 +86,4 @@ public class GeyserCommandMap { cmd.execute(sender, args); } - - public Map getCommands() { - return commandMap; - } } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java index 4fa0068a..cdfb612a 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java @@ -30,14 +30,17 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class HelpCommand extends GeyserCommand { public GeyserConnector connector; - public HelpCommand(GeyserConnector connector, String name, String description) { - super(name, description); + public HelpCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); this.connector = connector; this.setAliases(Collections.singletonList("?")); @@ -47,12 +50,7 @@ public class HelpCommand extends GeyserCommand { public void execute(CommandSender sender, String[] args) { sender.sendMessage("---- Showing Help For: Geyser (Page 1/1) ----"); Map cmds = connector.getCommandMap().getCommands(); - - List commands = new ArrayList<>(cmds.keySet()); - Collections.sort(commands); - - for (String cmd : commands) { - sender.sendMessage(ChatColor.YELLOW + "/geyser " + cmd + ChatColor.WHITE + ": " + cmds.get(cmd).getDescription()); - } + List commands = connector.getCommandMap().getCommands().keySet().stream().sorted().collect(Collectors.toList()); + commands.forEach(cmd -> sender.sendMessage(ChatColor.YELLOW + "/geyser " + cmd + ChatColor.WHITE + ": " + cmds.get(cmd).getDescription())); } } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java new file mode 100644 index 00000000..bd8444c7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019-2020 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.connector.command.defaults; + +import org.geysermc.common.ChatColor; +import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; + +public class ReloadCommand extends GeyserCommand { + + private GeyserConnector connector; + + public ReloadCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); + this.connector = connector; + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) { + return; + } + sender.sendMessage(ChatColor.YELLOW + "Reloading Geyser configurations... all connected bedrock clients will be kicked."); + for (GeyserSession session : connector.getPlayers().values()) { + session.getUpstream().disconnect("Geyser has been reloaded... sorry for the inconvenience!"); + } + connector.reload(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java index 25034f1a..4694d0fd 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java @@ -25,6 +25,7 @@ package org.geysermc.connector.command.defaults; +import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; @@ -33,10 +34,10 @@ import java.util.Collections; public class StopCommand extends GeyserCommand { - public GeyserConnector connector; + private GeyserConnector connector; - public StopCommand(GeyserConnector connector, String name, String description) { - super(name, description); + public StopCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); this.connector = connector; this.setAliases(Collections.singletonList("shutdown")); @@ -44,9 +45,9 @@ public class StopCommand extends GeyserCommand { @Override public void execute(CommandSender sender, String[] args) { - if (!sender.isConsole()) + if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) { return; - + } connector.shutdown(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java index 8091781a..93b6b3ec 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockCommandRequestTranslator.java @@ -28,6 +28,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket; import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket; +import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.GeyserCommandMap; import org.geysermc.connector.network.session.GeyserSession; @@ -39,7 +40,7 @@ public class BedrockCommandRequestTranslator extends PacketTranslator