From ec9b24b3cb46125a5c55a20832ed01f364073a06 Mon Sep 17 00:00:00 2001 From: Fynn Bauer Date: Tue, 18 Nov 2025 18:55:40 +0100 Subject: [PATCH 1/3] feat: start migrating to platform api --- build.gradle.kts | 1 + command-shared/build.gradle.kts | 2 +- .../command/shared/CloudCommandHandler.kt | 578 +----------------- .../shared/commands/DeleteGroupCommand.kt | 59 ++ .../shared/commands/GroupInfoCommand.kt | 119 ++++ .../shared/commands/ServerInfoCommand.kt | 164 +++++ .../command/shared/commands/StartCommand.kt | 59 ++ .../command/shared/commands/StopCommand.kt | 77 +++ gradle/libs.versions.toml | 4 +- 9 files changed, 494 insertions(+), 569 deletions(-) create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt diff --git a/build.gradle.kts b/build.gradle.kts index 7865ec7..df9ea8a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ allprojects { maven("https://buf.build/gen/maven") maven("https://repo.simplecloud.app/snapshots") maven("https://repo.papermc.io/repository/maven-public/") + maven("https://repo.simplecloud.app/snapshots") } } diff --git a/command-shared/build.gradle.kts b/command-shared/build.gradle.kts index 1c2708d..616c5bb 100644 --- a/command-shared/build.gradle.kts +++ b/command-shared/build.gradle.kts @@ -1,5 +1,5 @@ dependencies { - compileOnly(libs.simplecloud.controller) + api(libs.simplecloud.api) api(libs.cloud.core) api(libs.adventure.api) api(libs.adventure.text.minimessage) diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt index 3f3f26a..1d28c69 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt @@ -1,27 +1,22 @@ package app.simplecloud.plugin.command.shared -import app.simplecloud.controller.api.ControllerApi -import app.simplecloud.controller.shared.group.Group -import build.buf.gen.simplecloud.controller.v1.ServerStopCause -import net.kyori.adventure.text.Component +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.commands.DeleteGroupCommand +import app.simplecloud.plugin.command.shared.commands.GroupInfoCommand +import app.simplecloud.plugin.command.shared.commands.ServerInfoCommand +import app.simplecloud.plugin.command.shared.commands.StartCommand +import app.simplecloud.plugin.command.shared.commands.StopCommand import net.kyori.adventure.text.minimessage.MiniMessage -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.incendo.cloud.CommandManager import org.incendo.cloud.context.CommandContext -import org.incendo.cloud.parser.standard.LongParser.longParser -import org.incendo.cloud.parser.standard.StringParser.stringParser import org.incendo.cloud.permission.Permission -import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider -import java.util.concurrent.CompletableFuture -// TODO: maybe move this into multiple classes? class CloudCommandHandler( private val commandManager: CommandManager, val commandPlugin: CommandPlugin ) { - private val controllerApi = ControllerApi.createFutureApi() + private val cloudApi = CloudApi.create() fun createCloudCommand() { commandManager.command( @@ -43,12 +38,6 @@ class CloudCommandHandler( context.sender().sendMessage( MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudGroupInfoCommand) ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudEditGroupCommand) - ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudEditServerCommand) - ) context.sender().sendMessage( MiniMessage.miniMessage() .deserialize(commandPlugin.messageConfiguration.cloudDeleteGroupCommand) @@ -58,553 +47,10 @@ class CloudCommandHandler( .build() ) - registerStartCommand() - registerStopCommand() - registerServerInfoCommand() - registerGroupInfoCommand() - registerDeleteGroupCommand() - registerEditGroupCommand() - registerEditServerCommand() - } - - private fun registerStartCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("start") - .required( - "group", - stringParser(), - SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - } - ) - .handler { context: CommandContext -> - val group = context.get("group") - - controllerApi.getServers().startServer(group).thenAccept { server -> - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverStarting, - Placeholder.component("group", Component.text(group)), - Placeholder.component("id", Component.text(server?.numericalId!!)) - ) - - context.sender().sendMessage(message) - } - } - .permission(Permission.permission("simplecloud.command.cloud.start")) - .build() - ) - } - - private fun registerStopCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("stop") - .required("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .optional("id", longParser(), SuggestionProvider { _, _ -> - controllerApi.getServers().getAllServers().thenApply { servers -> - servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } - } - }) - .handler { context: CommandContext -> - val group = context.get("group") - val id = context.getOrDefault("id", null as Long?) - - if (id == null) { - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerStopped, - Placeholder.component("group", Component.text(group)), - ) - - controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> - servers.forEach { server -> - controllerApi.getServers().stopServer( - server.group, - server.numericalId.toLong() - ) - } - } - - context.sender().sendMessage(message) - } else { - - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverStopped, - Placeholder.component("group", Component.text(group)), - Placeholder.component("id", Component.text(id.toString())) - ) - - controllerApi.getServers().stopServer(group, id) - context.sender().sendMessage(message) - } - } - .permission(Permission.permission("simplecloud.command.cloud.stop")) - .build() - ) - } - - private fun registerServerInfoCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("info", "get") - .literal("servers", "server") - .optional("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .optional("id", longParser(), SuggestionProvider { _, _ -> - controllerApi.getServers().getAllServers().thenApply { servers -> - servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } - } - }) - .handler { context: CommandContext -> - val groupName = context.getOrDefault("group", null as String?) - val id = context.getOrDefault("id", null as Long?) - - when { - groupName != null && id != null -> { - controllerApi.getServers().getServerByNumerical(groupName, id).thenAccept { server -> - controllerApi.getGroups().getGroupByName(groupName).thenAccept { group -> - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoTitle, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "serveramount", - Component.text( - controllerApi.getServers().getServersByGroup(groupName) - .get().size.toString() - ) - ), - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoType, - Placeholder.component("grouptype", Component.text(server.type.name)) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoSoftware, - Placeholder.component( - "groupsoftware", - Component.text(group.properties["server-software"].toString()) - ) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoMemory, - Placeholder.component("groupmemory", Component.text(server.maxMemory)) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoPlayers, - Placeholder.component( - "groupplayers", - Component.text(server.playerCount) - ) - ) - ) - } - } - } - - groupName != null -> { - controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerListTitle, - Placeholder.component("servergroup", Component.text(groupName)) - ) - ) - servers.forEach { server -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerListEntry, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "numericalid", - Component.text(server.numericalId.toString()) - ), - Placeholder.component( - "onlineplayers", - Component.text(server.playerCount) - ), - Placeholder.component("maxplayers", Component.text(server.maxPlayers)), - Placeholder.component("minmemory", Component.text(server.minMemory)), - Placeholder.component("maxmemory", Component.text(server.maxMemory)), - Placeholder.component("state", Component.text(server.state.name)), - ) - ) - } - } - } - - else -> { - controllerApi.getServers().getAllServers().thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverListTitle, - ) - ) - servers.forEach { server -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverListEntry, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "numericalid", - Component.text(server.numericalId.toString()) - ), - Placeholder.component( - "onlineplayers", - Component.text(server.playerCount) - ), - Placeholder.component("maxplayers", Component.text(server.maxPlayers)), - Placeholder.component("minmemory", Component.text(server.minMemory)), - Placeholder.component("maxmemory", Component.text(server.maxMemory)), - Placeholder.component("state", Component.text(server.state.name)), - ) - ) - } - } - } - } - } - .permission(Permission.permission("simplecloud.command.cloud.get.servers")) - .build() - ) - } - - private fun registerGroupInfoCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("info", "get") - .literal("groups", "group") - .optional("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .handler { context: CommandContext -> - val groupName = context.getOrDefault("group", null as String?) - if (groupName != null) { - controllerApi.getGroups().getGroupByName(groupName).thenAccept { group -> - controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoTitle, - Placeholder.component("servergroup", Component.text(groupName)), - Placeholder.component("serveramount", Component.text(servers.size)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoType, - Placeholder.component("grouptype", Component.text(group.type.name)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoTemplate, - Placeholder.component( - "grouptemplate", - Component.text(group.properties.get("template-id").toString()) - ) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoMemory, - Placeholder.component("minmemory", Component.text(group.minMemory)), - Placeholder.component("maxmemory", Component.text(group.maxMemory)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoPlayers, - Placeholder.component("maxplayers", Component.text(group.maxPlayers)) - ) - ) - } - } - } else { - controllerApi.getGroups().getAllGroups().thenAccept { groups -> - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize(commandPlugin.messageConfiguration.groupsListTitle) - ) - groups.forEach { group -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupsListEntry, - Placeholder.component("servergroup", Component.text(group.name)), - Placeholder.component( - "onlinecount", - Component.text( - controllerApi.getServers().getServersByGroup(group) - .get().size.toString() - ) - ), - Placeholder.component( - "template", - Component.text(group.properties["template-id"].toString()) - ), - Placeholder.component("type", Component.text(group.type.name)), - Placeholder.component("maxcount", Component.text(group.maxOnlineCount)), - Placeholder.component("minmemory", Component.text(group.minMemory)), - Placeholder.component("maxmemory", Component.text(group.maxMemory)), - ) - ) - - } - } - } - } - .permission(Permission.permission("simplecloud.command.cloud.get.groups")) - .build() - ) - } - - private fun registerDeleteGroupCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("delete") - .literal("group") - .required("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .handler { context: CommandContext -> - val group = context.get("group") - - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupDeleted, - Placeholder.component("group", Component.text(group)) - ) - - controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> - servers.forEach { server -> - controllerApi.getServers().stopServer( - server.group, - server.numericalId.toLong() - ) - } - } - - controllerApi.getGroups().deleteGroup(group) - context.sender().sendMessage(message) - } - .permission(Permission.permission("simplecloud.command.cloud.delete.group")) - .build() - ) - } - - private fun registerEditGroupCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("edit") - .literal("group") - .required("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .required("setting", stringParser(), SuggestionProvider { _, _ -> - CompletableFuture.completedFuture( - listOf( - "max-players", - "max-memory", - "max-online-count", - "min-memory", - "min-online-count", - "properties", - "server-url", - "start-port" - ).map { Suggestion.suggestion(it) } - ) - }) - .required("value", stringParser()) - .handler { context: CommandContext -> - val groupName = context.get("group") - val setting = context.get("setting") - val value = context.get("value") - - controllerApi.getGroups().getGroupByName(groupName).thenAccept { group -> - val updatedGroup = when (setting) { - "max-players" -> group.copy( - maxPlayers = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "max-memory" -> group.copy( - maxMemory = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "min-memory" -> group.copy( - minMemory = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "max-online-count" -> group.copy( - maxOnlineCount = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "min-online-count" -> group.copy( - minOnlineCount = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "start-port" -> group.copy( - startPort = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - "server-url" -> group.copy(properties = group.properties + mapOf("server-url" to value)) - "properties" -> group.copy(properties = group.properties + mapOf("custom-property" to value)) - else -> { - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidSetting, - Placeholder.component("key", Component.text(setting)) - ) - ) - return@thenAccept - } - } - - controllerApi.getGroups().updateGroup(updatedGroup).thenAccept { group -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupUpdated, - Placeholder.component("group", Component.text(group.name)) - ) - ) - } - } - - - } - .permission(Permission.permission("simplecloud.command.cloud.edit.group")) - .build() - ) - } - - private fun registerEditServerCommand() { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("edit") - .literal("server") - .required("group", stringParser(), SuggestionProvider { _, _ -> - controllerApi.getGroups().getAllGroups().thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .required("id", longParser(), SuggestionProvider { _, _ -> - controllerApi.getServers().getAllServers().thenApply { servers -> - servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } - } - }) - .required("setting", stringParser(), SuggestionProvider { _, _ -> - CompletableFuture.completedFuture( - listOf("max-players").map { Suggestion.suggestion(it) } - ) - }) - .required("value", stringParser()) - .handler { context: CommandContext -> - val groupName = context.get("group") - val serverId = context.get("id") - val setting = context.get("setting") - val value = context.get("value") - - controllerApi.getServers().getServerByNumerical(groupName, serverId).thenAccept { server -> - val updatedServer = when (setting) { - "max-players" -> server.copy( - maxPlayers = value.toLongOrNull() ?: return@thenAccept context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidValue, - Placeholder.component("value", Component.text(value)), - Placeholder.component("key", Component.text(setting)) - ) - ) - ) - - else -> { - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.invalidSetting, - Placeholder.component("key", Component.text(setting)) - ) - ) - return@thenAccept - } - } - - controllerApi.getServers().updateServer(updatedServer).thenAccept { server -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverUpdated, - Placeholder.component("group", Component.text(server.group)), - Placeholder.component("numericalid", Component.text(server.numericalId.toString())) - ) - ) - } - } - } - .permission(Permission.permission("simplecloud.command.cloud.edit.server")) - .build() - ) + StartCommand(cloudApi, commandPlugin).register(commandManager) + StopCommand(cloudApi, commandPlugin).register(commandManager) + ServerInfoCommand(cloudApi, commandPlugin).register(commandManager) + GroupInfoCommand(cloudApi, commandPlugin).register(commandManager) + DeleteGroupCommand(cloudApi, commandPlugin).register(commandManager) } } diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt new file mode 100644 index 0000000..bb7d254 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt @@ -0,0 +1,59 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.context.CommandContext +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import org.incendo.cloud.suggestion.SuggestionProvider + +class DeleteGroupCommand( + private val cloudApi: CloudApi, + private val commandPlugin: CommandPlugin +) { + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("delete") + .literal("group") + .required("group", stringParser(), SuggestionProvider { _, _ -> + cloudApi.group().allGroups.thenApply { groups -> + groups.map { group -> Suggestion.suggestion(group.name) } + } + }) + .handler { context: CommandContext -> + val group = context.get("group") + + val message = MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupDeleted, + Placeholder.component("group", Component.text(group)) + ) + + + + // TODO: getServersByGroup + /* controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> + servers.forEach { server -> + controllerApi.getServers().stopServer( + server.group, + server.numericalId.toLong() + ) + } + } + + controllerApi.getGroups().deleteGroup(group) */ + context.sender().sendMessage(message) + } + .permission(Permission.permission("simplecloud.command.cloud.delete.group")) + .build() + ) + } +} + diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt new file mode 100644 index 0000000..87e55eb --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt @@ -0,0 +1,119 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.context.CommandContext +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import org.incendo.cloud.suggestion.SuggestionProvider +import kotlin.text.get + +class GroupInfoCommand( + private val cloudApi: CloudApi, + private val commandPlugin: CommandPlugin +) { + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("info", "get") + .literal("groups", "group") + .optional("group", stringParser(), SuggestionProvider { _, _ -> + cloudApi.group().allGroups.thenApply { groups -> + groups.map { group -> Suggestion.suggestion(group.name) } + } + }) + .handler { context: CommandContext -> + val groupName = context.getOrDefault("group", null as String?) + if (groupName != null) { + cloudApi.group().getGroupByName(groupName).thenAccept { group -> + // TODO: get server by group + } + /* controllerApi.getGroups().getGroupByName(groupName).thenAccept { group -> + controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupInfoTitle, + Placeholder.component("servergroup", Component.text(groupName)), + Placeholder.component("serveramount", Component.text(servers.size)) + ) + ) + + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupInfoType, + Placeholder.component("grouptype", Component.text(group.type.name)) + ) + ) + + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupInfoTemplate, + Placeholder.component( + "grouptemplate", + Component.text(group.properties.get("template-id").toString()) + ) + ) + ) + + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupInfoMemory, + Placeholder.component("minmemory", Component.text(group.minMemory)), + Placeholder.component("maxmemory", Component.text(group.maxMemory)) + ) + ) + + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupInfoPlayers, + Placeholder.component("maxplayers", Component.text(group.maxPlayers)) + ) + ) + } + } */ + } else { + cloudApi.group().allGroups.thenAccept { groups -> + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize(commandPlugin.messageConfiguration.groupsListTitle) + ) + groups.forEach { group -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupsListEntry, + Placeholder.component("servergroup", Component.text(group.name)), + Placeholder.component( + "onlinecount", + Component.text( + /* TODO cloudApi.server().getServersByGroup(group) + .get().size.toString() */ + 0 + ) + ), + Placeholder.component( + "template", + Component.text(group.properties["template-id"].toString()) + ), + Placeholder.component("type", Component.text(group.type.name)), + Placeholder.component("maxcount", Component.text(group.maxPlayers)), + Placeholder.component("minmemory", Component.text(group.minMemory)), + Placeholder.component("maxmemory", Component.text(group.maxMemory)), + ) + ) + } + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.get.groups")) + .build() + ) + } +} + diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt new file mode 100644 index 0000000..95786c9 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt @@ -0,0 +1,164 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import org.incendo.cloud.CommandManager +import org.incendo.cloud.context.CommandContext +import org.incendo.cloud.parser.standard.LongParser.longParser +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import org.incendo.cloud.suggestion.SuggestionProvider +import kotlin.text.get + +class ServerInfoCommand( + private val cloudApi: CloudApi, + private val commandPlugin: CommandPlugin +) { + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("info", "get") + .literal("servers", "server") + .optional("group", stringParser(), SuggestionProvider { _, _ -> + cloudApi.group().allGroups.thenApply { groups -> + groups.map { group -> Suggestion.suggestion(group.name) } + } + }) + .optional("id", longParser(), SuggestionProvider { _, _ -> + cloudApi.server().allServers.thenApply { servers -> + servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } + } + }) + .handler { context: CommandContext -> + val groupName = context.getOrDefault("group", null as String?) + val id = context.getOrDefault("id", null as Long?) + + when { + groupName != null && id != null -> { + /* TODO: get server by numerical + controllerApi.getServers().getServerByNumerical(groupName, id).thenAccept { server -> + + cloudApi.group().getGroupByName(groupName).thenAccept { group -> + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize( + commandPlugin.messageConfiguration.serverInfoTitle, + Placeholder.component("servergroup", Component.text(server.group)), + Placeholder.component( + "serveramount", + Component.text( + controllerApi.getServers().getServersByGroup(groupName) + .get().size.toString() + ) + ), + ) + ) + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize( + commandPlugin.messageConfiguration.serverInfoType, + Placeholder.component("grouptype", Component.text(server.type.name)) + ) + ) + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize( + commandPlugin.messageConfiguration.serverInfoSoftware, + Placeholder.component( + "groupsoftware", + Component.text(group.properties["server-software"].toString()) + ) + ) + ) + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize( + commandPlugin.messageConfiguration.serverInfoMemory, + Placeholder.component("groupmemory", Component.text(server.maxMemory)) + ) + ) + context.sender().sendMessage( + MiniMessage.miniMessage() + .deserialize( + commandPlugin.messageConfiguration.serverInfoPlayers, + Placeholder.component( + "groupplayers", + Component.text(server.playerCount) + ) + ) + ) + } + } + } + + groupName != null -> { + controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupServerListTitle, + Placeholder.component("servergroup", Component.text(groupName)) + ) + ) + servers.forEach { server -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupServerListEntry, + Placeholder.component("servergroup", Component.text(server.group)), + Placeholder.component( + "numericalid", + Component.text(server.numericalId.toString()) + ), + Placeholder.component( + "onlineplayers", + Component.text(server.playerCount) + ), + Placeholder.component("maxplayers", Component.text(server.maxPlayers)), + Placeholder.component("minmemory", Component.text(server.minMemory)), + Placeholder.component("maxmemory", Component.text(server.maxMemory)), + Placeholder.component("state", Component.text(server.state.name)), + ) + ) + } + } + } + + else -> { + controllerApi.getServers().getAllServers().thenAccept { servers -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.serverListTitle, + ) + ) + servers.forEach { server -> + context.sender().sendMessage( + MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.serverListEntry, + Placeholder.component("servergroup", Component.text(server.group)), + Placeholder.component( + "numericalid", + Component.text(server.numericalId.toString()) + ), + Placeholder.component( + "onlineplayers", + Component.text(server.playerCount) + ), + Placeholder.component("maxplayers", Component.text(server.maxPlayers)), + Placeholder.component("minmemory", Component.text(server.minMemory)), + Placeholder.component("maxmemory", Component.text(server.maxMemory)), + Placeholder.component("state", Component.text(server.state.name)), + ) + ) + } + } + } + } */ + } + .permission(Permission.permission("simplecloud.command.cloud.get.servers")) + .build() + ) + } +} + diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt new file mode 100644 index 0000000..d0ea65d --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt @@ -0,0 +1,59 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.api.server.StartServerRequest +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.context.CommandContext +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import org.incendo.cloud.suggestion.SuggestionProvider + +class StartCommand( + private val cloudApi: CloudApi, + private val commandPlugin: CommandPlugin +) { + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("start") + .required( + "group", + stringParser(), + SuggestionProvider { _, _ -> + cloudApi.group().allGroups.thenApply { groups -> + groups.map { group -> Suggestion.suggestion(group.name) } + } + } + ) + .handler { context: CommandContext -> + val group = context.get("group") + + cloudApi.group().getGroupByName(group).thenAccept { group -> + val request = StartServerRequest(group.serverGroupId, group.name) + + cloudApi.server().startServer(request).thenAccept { server -> + val message = MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.serverStarting, + Placeholder.component("group", Component.text(group.name)), + // TODO: server returns a Void + Placeholder.component("id", Component.text(server)) + ) + + context.sender().sendMessage(message) + } + } + + } + .permission(Permission.permission("simplecloud.command.cloud.start")) + .build() + ) + } +} + diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt new file mode 100644 index 0000000..8dcc210 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt @@ -0,0 +1,77 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.context.CommandContext +import org.incendo.cloud.parser.standard.LongParser.longParser +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import org.incendo.cloud.suggestion.SuggestionProvider + +class StopCommand( + private val cloudApi: CloudApi, + private val commandPlugin: CommandPlugin +) { + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("stop") + .required("group", stringParser(), SuggestionProvider { _, _ -> + cloudApi.group().allGroups.thenApply { groups -> + groups.map { group -> Suggestion.suggestion(group.name) } + } + }) + .optional("id", longParser(), SuggestionProvider { _, _ -> + cloudApi.server().allServers.thenApply { servers -> + servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } + } + }) + .handler { context: CommandContext -> + val group = context.get("group") + val id = context.getOrDefault("id", null as Long?) + + if (id == null) { + val message = MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.groupServerStopped, + Placeholder.component("group", Component.text(group)), + ) + + // TODO: get server by group + + /* controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> + servers.forEach { server -> + controllerApi.getServers().stopServer( + server.group, + server.numericalId.toLong() + ) + } + } */ + + context.sender().sendMessage(message) + } else { + + val message = MiniMessage.miniMessage().deserialize( + commandPlugin.messageConfiguration.serverStopped, + Placeholder.component("group", Component.text(group)), + Placeholder.component("id", Component.text(id.toString())) + ) + + // TODO: stop server by numerical + + // controllerApi.getServers().stopServer(group, id) + context.sender().sendMessage(message) + } + } + .permission(Permission.permission("simplecloud.command.cloud.stop")) + .build() + ) + } +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2a4b503..1190cad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ kotlin = "2.0.20" shadow = "8.3.3" kapt = "2.0.20" -simplecloud-controller = "0.0.30-SNAPSHOT.2660ec8" +simplecloud-api = "0.1.0-platform.1-dev.1763294516035-de96444" cloud-core = "2.0.0" cloud-velocity = "2.0.0-beta.10" cloud-bungeecord = "2.0.0-beta.10" @@ -19,7 +19,7 @@ configurate-kotlin = "4.1.2" [libraries] kotlin-jvm = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } -simplecloud-controller = { module = "app.simplecloud.controller:controller-api", version.ref = "simplecloud-controller"} +simplecloud-api = { module = "app.simplecloud.api:api", version.ref = "simplecloud-api" } cloud-core = { module = "org.incendo:cloud-core", version.ref = "cloud-core" } cloud-velocity = { module = "org.incendo:cloud-velocity", version.ref = "cloud-velocity" } cloud-bungeecord = { module = "org.incendo:cloud-bungee", version.ref = "cloud-bungeecord" } From 4e36ad0cd749fc9f6d34883abe16ec4f76b4efd8 Mon Sep 17 00:00:00 2001 From: Fynn Bauer Date: Tue, 18 Nov 2025 19:31:12 +0100 Subject: [PATCH 2/3] feat: migrate DeleteGroupCommand, GroupInfoCommand & StopCommand.kt --- .../command/shared/commands/DeleteGroupCommand.kt | 13 ++++--------- .../command/shared/commands/GroupInfoCommand.kt | 13 +++++-------- .../plugin/command/shared/commands/StopCommand.kt | 14 ++++++-------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt index bb7d254..e51b437 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt @@ -1,6 +1,7 @@ package app.simplecloud.plugin.command.shared.commands import app.simplecloud.api.CloudApi +import app.simplecloud.api.server.ServerQuery import app.simplecloud.plugin.command.shared.CloudSender import app.simplecloud.plugin.command.shared.CommandPlugin import net.kyori.adventure.text.Component @@ -36,19 +37,13 @@ class DeleteGroupCommand( Placeholder.component("group", Component.text(group)) ) - - - // TODO: getServersByGroup - /* controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> + cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(group)).thenAccept { servers -> servers.forEach { server -> - controllerApi.getServers().stopServer( - server.group, - server.numericalId.toLong() - ) + cloudApi.server().stopServer(server.serverId) } } - controllerApi.getGroups().deleteGroup(group) */ + cloudApi.group().deleteGroup(group) context.sender().sendMessage(message) } .permission(Permission.permission("simplecloud.command.cloud.delete.group")) diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt index 87e55eb..1662f19 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt @@ -1,6 +1,7 @@ package app.simplecloud.plugin.command.shared.commands import app.simplecloud.api.CloudApi +import app.simplecloud.api.server.ServerQuery import app.simplecloud.plugin.command.shared.CloudSender import app.simplecloud.plugin.command.shared.CommandPlugin import net.kyori.adventure.text.Component @@ -12,7 +13,6 @@ import org.incendo.cloud.parser.standard.StringParser.stringParser import org.incendo.cloud.permission.Permission import org.incendo.cloud.suggestion.Suggestion import org.incendo.cloud.suggestion.SuggestionProvider -import kotlin.text.get class GroupInfoCommand( private val cloudApi: CloudApi, @@ -34,9 +34,8 @@ class GroupInfoCommand( if (groupName != null) { cloudApi.group().getGroupByName(groupName).thenAccept { group -> // TODO: get server by group - } - /* controllerApi.getGroups().getGroupByName(groupName).thenAccept { group -> - controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> + cloudApi.server().getAllServers(ServerQuery.create() + .filterByServerGroupName(groupName)).thenAccept { servers -> context.sender().sendMessage( MiniMessage.miniMessage().deserialize( commandPlugin.messageConfiguration.groupInfoTitle, @@ -77,7 +76,7 @@ class GroupInfoCommand( ) ) } - } */ + } } else { cloudApi.group().allGroups.thenAccept { groups -> context.sender().sendMessage( @@ -92,9 +91,7 @@ class GroupInfoCommand( Placeholder.component( "onlinecount", Component.text( - /* TODO cloudApi.server().getServersByGroup(group) - .get().size.toString() */ - 0 + cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(groupName)).get().size.toString() ) ), Placeholder.component( diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt index 8dcc210..ca1f331 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt @@ -1,6 +1,7 @@ package app.simplecloud.plugin.command.shared.commands import app.simplecloud.api.CloudApi +import app.simplecloud.api.server.ServerQuery import app.simplecloud.plugin.command.shared.CloudSender import app.simplecloud.plugin.command.shared.CommandPlugin import net.kyori.adventure.text.Component @@ -45,18 +46,15 @@ class StopCommand( // TODO: get server by group - /* controllerApi.getServers().getServersByGroup(group).thenAccept { servers -> - servers.forEach { server -> - controllerApi.getServers().stopServer( - server.group, - server.numericalId.toLong() - ) + cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(group)) + .thenApply { servers -> + servers.forEach { server -> + cloudApi.server().stopServer(server.serverId) + } } - } */ context.sender().sendMessage(message) } else { - val message = MiniMessage.miniMessage().deserialize( commandPlugin.messageConfiguration.serverStopped, Placeholder.component("group", Component.text(group)), From 4e909b9b96aa4ff41c864a46af613580cd145115 Mon Sep 17 00:00:00 2001 From: xXJanisXx Date: Wed, 11 Feb 2026 13:32:28 +0100 Subject: [PATCH 3/3] feat: improve YamlConfig and migrate to platform --- .gitignore | 4 + README.md | 6 +- build.gradle.kts | 27 +- command-bungeecord/build.gradle.kts | 13 +- .../command/bungeecord/BungeeCordPlugin.kt | 4 +- .../src/main/resources/plugin.yml | 2 +- command-shared/build.gradle.kts | 9 +- .../command/shared/CloudCommandHandler.kt | 46 +-- .../plugin/command/shared/CloudSender.kt | 1 + .../plugin/command/shared/CommandPlugin.kt | 8 +- .../plugin/command/shared/StringExtension.kt | 7 + .../command/shared/commands/DeleteCommand.kt | 90 ++++++ .../shared/commands/DeleteGroupCommand.kt | 54 ---- .../command/shared/commands/EditCommand.kt | 285 ++++++++++++++++++ .../shared/commands/GroupInfoCommand.kt | 116 ------- .../command/shared/commands/InfoCommand.kt | 197 ++++++++++++ .../shared/commands/ServerInfoCommand.kt | 164 ---------- .../command/shared/commands/StartCommand.kt | 97 ++++-- .../command/shared/commands/StopCommand.kt | 128 +++++--- .../command/shared/config/MessageConfig.kt | 95 +++--- .../command/shared/config/YamlConfig.kt | 219 ++++++++++++-- .../shared/resolver/GroupTagResolver.kt | 16 + .../resolver/PersistentServerTagResolver.kt | 18 ++ .../shared/resolver/ServerTagResolver.kt | 26 ++ command-velocity/build.gradle.kts | 11 +- .../plugin/command/velocity/VelocityPlugin.kt | 8 +- .../plugin/command/velocity/VelocitySender.kt | 1 - gradle/libs.versions.toml | 48 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 3 +- 30 files changed, 1123 insertions(+), 582 deletions(-) create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/StringExtension.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteCommand.kt delete mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/EditCommand.kt delete mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/InfoCommand.kt delete mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/resolver/GroupTagResolver.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/resolver/PersistentServerTagResolver.kt create mode 100644 command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/resolver/ServerTagResolver.kt diff --git a/.gitignore b/.gitignore index a5b1113..8d9649f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ gradle-app.setting .project # JDT-specific (Eclipse Java Development Tools) .classpath + +.idea/ + +.kotlin/ \ No newline at end of file diff --git a/README.md b/README.md index 60a1c45..c03492f 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ This repository is licensed under [Apache 2.0][license]. [banner]: https://github.com/simplecloudapp/branding/blob/main/readme/banner/plugin/cloud-command.png?raw=true -[issue-bug-report]: https://github.com/theSimpleCloud/command-plugin/issues/new?labels=bug&projects=template=01_BUG-REPORT.yml&title=%5BBUG%5D+%3Ctitle%3E -[issue-feature-request]: https://github.com/theSimpleCloud/command-plugin/discussions/new?category=ideas -[docs-thisproject]: https://docs.simplecloud.app/plugin/cloud-command +[issue-bug-report]: https://github.com/simplecloudapp/command-plugin/issues/new?labels=bug&projects=template=01_BUG-REPORT.yml&title=%5BBUG%5D+%3Ctitle%3E +[issue-feature-request]: https://github.com/simplecloudapp/command-plugin/discussions/new?category=ideas +[docs-thisproject]: https://docs.simplecloud.app/en/manual/plugin/cloud-command [docs-contribute]: https://docs.simplecloud.app/contribute [modrinth]: https://modrinth.com/plugin/command-plugin diff --git a/build.gradle.kts b/build.gradle.kts index df9ea8a..ce4b160 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,7 +32,8 @@ subprojects { dependencies { testImplementation(rootProject.libs.kotlin.test) - compileOnly(rootProject.libs.kotlin.jvm) + implementation(rootProject.libs.kotlin.jvm) + implementation(rootProject.libs.kotlinx.coroutines.core) } publishing { @@ -56,27 +57,11 @@ subprojects { } tasks.named("shadowJar", ShadowJar::class) { - dependencies { - exclude(dependency("com.velocitypowered:velocity-api")) - - relocate("org.incendo", "app.simplecloud.plugin.command.relocate.incendo") - relocate("org.spongepowered", "app.simplecloud.plugin.command.relocate.spongepowered") - relocate("app.simplecloud.plugin.api", "app.simplecloud.plugin.command.relocate.plugin.api") - } - /* dependsOn("processResources") - dependencies { - include(project(":command-shared")) - - /** - * TODO: Add dependencies ADDED BY YOU like this: - * include(dependency(libs.your.dependency.get())) - */ - include(dependency(libs.cloud.core.get())) - // TODO: only include the velocity dependency in the velocity plugin - include(dependency(libs.cloud.velocity.get())) - - } */ + mergeServiceFiles() + relocate("org.incendo", "app.simplecloud.plugin.command.relocate.incendo") + relocate("org.spongepowered", "app.simplecloud.plugin.command.relocate.spongepowered") archiveFileName.set("${project.name}.jar") + archiveClassifier.set("") } } diff --git a/command-bungeecord/build.gradle.kts b/command-bungeecord/build.gradle.kts index fab9f1d..f9611e6 100644 --- a/command-bungeecord/build.gradle.kts +++ b/command-bungeecord/build.gradle.kts @@ -3,10 +3,10 @@ plugins { } dependencies { - api(project(":command-shared")) - api(libs.bungeecord.api) - api(libs.adveture.platform.bungeecord) - api(libs.cloud.bungeecord) + implementation(project(":command-shared")) + implementation(libs.adveture.platform.bungeecord) + implementation(libs.cloud.bungeecord) + compileOnly(libs.bungeecord.api) } modrinth { @@ -16,8 +16,6 @@ modrinth { versionType.set("beta") uploadFile.set(tasks.shadowJar) gameVersions.addAll( - - "1.20", "1.20.1", "1.20.2", @@ -36,8 +34,7 @@ modrinth { "1.21.8", "1.21.9", "1.21.10", - - + "1.21.11" ) loaders.add("bungeecord") loaders.add("waterfall") diff --git a/command-bungeecord/src/main/kotlin/app/simplecloud/plugin/command/bungeecord/BungeeCordPlugin.kt b/command-bungeecord/src/main/kotlin/app/simplecloud/plugin/command/bungeecord/BungeeCordPlugin.kt index 4ff472d..64d81f1 100644 --- a/command-bungeecord/src/main/kotlin/app/simplecloud/plugin/command/bungeecord/BungeeCordPlugin.kt +++ b/command-bungeecord/src/main/kotlin/app/simplecloud/plugin/command/bungeecord/BungeeCordPlugin.kt @@ -10,11 +10,10 @@ import org.incendo.cloud.SenderMapper import org.incendo.cloud.bungee.BungeeCommandManager import org.incendo.cloud.execution.ExecutionCoordinator - /** * @author Fynn Bauer in 2024 */ -class BungeeCordPlugin(): Plugin() { +class BungeeCordPlugin : Plugin() { private lateinit var commandManager: BungeeCommandManager private lateinit var commandPlugin: CommandPlugin @@ -45,6 +44,7 @@ class BungeeCordPlugin(): Plugin() { override fun onDisable() { adventure.close() + commandPlugin.config.close() } fun adventure(): BungeeAudiences { diff --git a/command-bungeecord/src/main/resources/plugin.yml b/command-bungeecord/src/main/resources/plugin.yml index f46eaa9..3d63b0a 100644 --- a/command-bungeecord/src/main/resources/plugin.yml +++ b/command-bungeecord/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: CommandPlugin -version: 0.0.1-EXPERIMENTAL +version: 1.0.0 author: Kaseax main: app.simplecloud.plugin.command.bungeecord.BungeeCordPlugin depends: [simplecloud-api] \ No newline at end of file diff --git a/command-shared/build.gradle.kts b/command-shared/build.gradle.kts index 616c5bb..98d99f0 100644 --- a/command-shared/build.gradle.kts +++ b/command-shared/build.gradle.kts @@ -1,12 +1,9 @@ dependencies { - api(libs.simplecloud.api) + compileOnly(libs.simplecloud.api) api(libs.cloud.core) api(libs.adventure.api) api(libs.adventure.text.minimessage) - implementation(rootProject.libs.configurate.yaml) - implementation(rootProject.libs.configurate.kotlin) { - exclude(group = "org.jetbrains.kotlin") - exclude(group = "org.jetbrains.kotlinx") - } + implementation(libs.bundles.logging) + implementation(libs.bundles.configurate) } \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt index 1d28c69..e43dbd6 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudCommandHandler.kt @@ -1,56 +1,30 @@ package app.simplecloud.plugin.command.shared import app.simplecloud.api.CloudApi -import app.simplecloud.plugin.command.shared.commands.DeleteGroupCommand -import app.simplecloud.plugin.command.shared.commands.GroupInfoCommand -import app.simplecloud.plugin.command.shared.commands.ServerInfoCommand -import app.simplecloud.plugin.command.shared.commands.StartCommand -import app.simplecloud.plugin.command.shared.commands.StopCommand -import net.kyori.adventure.text.minimessage.MiniMessage +import app.simplecloud.plugin.command.shared.commands.* import org.incendo.cloud.CommandManager import org.incendo.cloud.context.CommandContext import org.incendo.cloud.permission.Permission class CloudCommandHandler( private val commandManager: CommandManager, - val commandPlugin: CommandPlugin + private val commandPlugin: CommandPlugin ) { - - private val cloudApi = CloudApi.create() + private val api = CloudApi.create() fun createCloudCommand() { commandManager.command( commandManager.commandBuilder("cloud") .handler { context: CommandContext -> - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudHelpTitle) - ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudStartCommand) - ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudStopCommand) - ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudServerInfoCommand) - ) - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize(commandPlugin.messageConfiguration.cloudGroupInfoCommand) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize(commandPlugin.messageConfiguration.cloudDeleteGroupCommand) - ) + context.sender().sendMessage(miniMessage(commandPlugin.messageConfiguration.cloudHelpMessage)) } .permission(Permission.permission("simplecloud.command.cloud")) .build() ) - - StartCommand(cloudApi, commandPlugin).register(commandManager) - StopCommand(cloudApi, commandPlugin).register(commandManager) - ServerInfoCommand(cloudApi, commandPlugin).register(commandManager) - GroupInfoCommand(cloudApi, commandPlugin).register(commandManager) - DeleteGroupCommand(cloudApi, commandPlugin).register(commandManager) + StopCommand(api, commandPlugin).register(commandManager) + StartCommand(api, commandPlugin).register(commandManager) + InfoCommand(api, commandPlugin).register(commandManager) + EditCommand(api, commandPlugin).register(commandManager) + DeleteCommand(api, commandPlugin).register(commandManager) } -} +} \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudSender.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudSender.kt index 5a323f1..a2484d0 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudSender.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CloudSender.kt @@ -8,4 +8,5 @@ import net.kyori.adventure.text.Component interface CloudSender { fun sendMessage(message: Component) + } \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CommandPlugin.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CommandPlugin.kt index f412ad9..d397988 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CommandPlugin.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/CommandPlugin.kt @@ -2,7 +2,6 @@ package app.simplecloud.plugin.command.shared import app.simplecloud.plugin.command.shared.config.MessageConfig import app.simplecloud.plugin.command.shared.config.YamlConfig -import net.kyori.adventure.text.minimessage.MiniMessage /** * @author Fynn Bauer in 2024 @@ -10,8 +9,7 @@ import net.kyori.adventure.text.minimessage.MiniMessage open class CommandPlugin( dirPath: String ) { - - val config = YamlConfig(dirPath); - val messageConfiguration = config.load("messages")!! - val prefix = MiniMessage.miniMessage().deserialize(" ") + val config = YamlConfig(dirPath) + val messageConfiguration: MessageConfig + get() = config.getCached("messages")!! } \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/StringExtension.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/StringExtension.kt new file mode 100644 index 0000000..b7e4962 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/StringExtension.kt @@ -0,0 +1,7 @@ +package app.simplecloud.plugin.command.shared + +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver + +fun miniMessage(message: String, vararg tagResolver: TagResolver) = + MiniMessage.miniMessage().deserialize(message, *tagResolver) \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteCommand.kt new file mode 100644 index 0000000..d238681 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteCommand.kt @@ -0,0 +1,90 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import app.simplecloud.plugin.command.shared.miniMessage +import app.simplecloud.plugin.command.shared.resolver.GroupTagResolver +import app.simplecloud.plugin.command.shared.resolver.PersistentServerTagResolver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion + +class DeleteCommand( + private val api: CloudApi, + private val plugin: CommandPlugin +) { + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + fun register(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("delete") + .literal("group") + .required("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .handler { context -> + val groupName = context.get("group") + scope.launch { + try { + val group = api.group().getGroupByName(groupName).await() + val servers = api.server().getServersByGroup(groupName).await() + servers.forEach { + try { + api.server().stopServer(it.serverId).await() + } catch (_: Exception) { + } + } + repeat(30) { + val remaining = api.server().getServersByGroup(groupName).await() + if (remaining.isEmpty()) return@repeat + delay(1000) + } + api.group().deleteGroup(group.serverGroupId).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.groupDeleted, GroupTagResolver.of(group))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.delete.group")) + .build() + ) + + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("delete") + .literal("persistent") + .required("server", stringParser()) { _, _ -> + api.persistentServer().allPersistentServers.thenApply { servers -> + servers.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .handler { context -> + val serverName = context.get("server") + scope.launch { + try { + val persistent = api.persistentServer().getPersistentServerByName(serverName).await() + api.persistentServer().deletePersistentServer(persistent.persistentServerId).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.persistentServerDeleted, PersistentServerTagResolver.of(persistent))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.delete.persistent")) + .build() + ) + } +} diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt deleted file mode 100644 index e51b437..0000000 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/DeleteGroupCommand.kt +++ /dev/null @@ -1,54 +0,0 @@ -package app.simplecloud.plugin.command.shared.commands - -import app.simplecloud.api.CloudApi -import app.simplecloud.api.server.ServerQuery -import app.simplecloud.plugin.command.shared.CloudSender -import app.simplecloud.plugin.command.shared.CommandPlugin -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.minimessage.MiniMessage -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder -import org.incendo.cloud.CommandManager -import org.incendo.cloud.context.CommandContext -import org.incendo.cloud.parser.standard.StringParser.stringParser -import org.incendo.cloud.permission.Permission -import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider - -class DeleteGroupCommand( - private val cloudApi: CloudApi, - private val commandPlugin: CommandPlugin -) { - - fun register(commandManager: CommandManager) { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("delete") - .literal("group") - .required("group", stringParser(), SuggestionProvider { _, _ -> - cloudApi.group().allGroups.thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .handler { context: CommandContext -> - val group = context.get("group") - - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupDeleted, - Placeholder.component("group", Component.text(group)) - ) - - cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(group)).thenAccept { servers -> - servers.forEach { server -> - cloudApi.server().stopServer(server.serverId) - } - } - - cloudApi.group().deleteGroup(group) - context.sender().sendMessage(message) - } - .permission(Permission.permission("simplecloud.command.cloud.delete.group")) - .build() - ) - } -} - diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/EditCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/EditCommand.kt new file mode 100644 index 0000000..52b5b2e --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/EditCommand.kt @@ -0,0 +1,285 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.api.group.DeploymentConfig +import app.simplecloud.api.group.DeploymentHost +import app.simplecloud.api.group.SourceConfig +import app.simplecloud.api.group.WorkflowsConfig +import app.simplecloud.api.group.WorkflowWhen +import app.simplecloud.api.group.UpdateGroupRequest +import app.simplecloud.api.group.ScalingConfig +import app.simplecloud.api.group.ScaleDownConfig +import app.simplecloud.api.persistentserver.PersistentServer +import app.simplecloud.api.persistentserver.UpdatePersistentServerRequest +import app.simplecloud.api.server.UpdateServerRequest +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import app.simplecloud.plugin.command.shared.miniMessage +import app.simplecloud.plugin.command.shared.resolver.GroupTagResolver +import app.simplecloud.plugin.command.shared.resolver.PersistentServerTagResolver +import app.simplecloud.plugin.command.shared.resolver.ServerTagResolver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.parser.standard.IntegerParser.integerParser +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import java.util.concurrent.CompletableFuture + +class EditCommand( + private val api: CloudApi, + private val plugin: CommandPlugin +) { + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + private val groupSettings = listOf("max-players", "min-memory", "max-memory") + private val serverSettings = listOf("max-players", "min-memory", "max-memory") + private val persistentSettings = listOf("max-players", "min-memory", "max-memory", "active") + + fun register(commandManager: CommandManager) { + registerEditGroup(commandManager) + registerEditServer(commandManager) + registerEditPersistent(commandManager) + } + + private fun registerEditGroup(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("edit") + .literal("group") + .required("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .required("setting", stringParser()) { _, _ -> + CompletableFuture.completedFuture(groupSettings.map { Suggestion.suggestion(it) }) + } + .required("value", stringParser()) + .handler { context -> + val groupName = context.get("group") + val setting = context.get("setting") + val value = context.get("value") + scope.launch { + try { + val group = api.group().getGroupByName(groupName).await() + val request = UpdateGroupRequest() + request.setName(group.name) + request.setType(group.type) + request.setMinMemory(group.minMemory) + request.setMaxMemory(group.maxMemory) + request.setMaxPlayers(group.maxPlayers) + group.deployment?.let { request.setDeployment(copyDeploymentConfig(it)) } + group.scaling?.let { request.setScaling(copyScalingConfig(it)) } + group.source?.let { request.setSource(copySourceConfig(it)) } + group.workflows?.let { request.setWorkflows(copyWorkflowsConfig(it)) } + request.setProperties(group.properties) + request.setTags(group.tags) + when (setting) { + "max-players" -> request.setMaxPlayers(parseIntOrError(value, setting, context.sender()) ?: return@launch) + "min-memory" -> request.setMinMemory(parseIntOrError(value, setting, context.sender()) ?: return@launch) + "max-memory" -> request.setMaxMemory(parseIntOrError(value, setting, context.sender()) ?: return@launch) + else -> { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.invalidSetting, Placeholder.unparsed("key", setting))) + return@launch + } + } + val updated = api.group().updateGroup(group.serverGroupId, request).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.groupUpdated, GroupTagResolver.of(updated))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.edit.group")) + .build() + ) + } + + private fun copyDeploymentConfig(original: DeploymentConfig): DeploymentConfig { + val copy = DeploymentConfig() + copy.strategy = original.strategy + original.hosts?.let { hosts -> + copy.hosts = hosts.map { host -> + DeploymentHost().apply { + name = host.name + priority = host.priority + } + }.toTypedArray() + } + return copy + } + + private fun copyScalingConfig(original: ScalingConfig): ScalingConfig { + val copy = ScalingConfig() + copy.availableSlots = original.availableSlots + copy.maxServers = original.maxServers + copy.minServers = original.minServers + copy.playerThreshold = original.playerThreshold + copy.scalingMode = original.scalingMode + original.scaleDown?.let { + val scaleDownCopy = ScaleDownConfig() + scaleDownCopy.idleTime = it.idleTime + scaleDownCopy.isIgnorePlayers = it.isIgnorePlayers + copy.scaleDown = scaleDownCopy + } + return copy + } + + private fun copySourceConfig(original: SourceConfig): SourceConfig { + val copy = SourceConfig() + copy.type = original.type + copy.blueprint = original.blueprint + copy.image = original.image + return copy + } + + private fun copyWorkflowsConfig(original: WorkflowsConfig): WorkflowsConfig { + val copy = WorkflowsConfig() + copy.manual = original.manual + original.`when`?.let { whenConfig -> + val whenCopy = WorkflowWhen() + whenCopy.start = whenConfig.start + whenCopy.stop = whenConfig.stop + copy.`when` = whenCopy + } + return copy + } + + private fun registerEditServer(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("edit") + .literal("server") + .required("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .required("id", integerParser()) { context, _ -> + try { + val group = context.get("group") + api.server().getServersByGroup(group).thenApply { servers -> + servers.map { Suggestion.suggestion(it.numericalId.toString()) } + }.exceptionally { emptyList() } + } catch (e: Exception) { + CompletableFuture.completedFuture(emptyList()) + } + } + .required("setting", stringParser()) { _, _ -> + CompletableFuture.completedFuture(serverSettings.map { Suggestion.suggestion(it) }) + } + .required("value", stringParser()) + .handler { context -> + val groupName = context.get("group") + val id = context.get("id") + val setting = context.get("setting") + val value = context.get("value") + scope.launch { + try { + val server = api.server().getServerByNumericalId(groupName, id).await() + val request = UpdateServerRequest().apply { + when (setting) { + "max-players" -> maxPlayers = parseIntOrError(value, setting, context.sender()) ?: return@launch + "min-memory" -> minMemory = parseIntOrError(value, setting, context.sender()) ?: return@launch + "max-memory" -> maxMemory = parseIntOrError(value, setting, context.sender()) ?: return@launch + else -> { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.invalidSetting, Placeholder.unparsed("key", setting))) + return@launch + } + } + } + val updated = api.server().updateServer(server.serverId, request).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.serverUpdated, ServerTagResolver.of(updated))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.edit.server")) + .build() + ) + } + + private fun registerEditPersistent(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("edit") + .literal("persistent") + .required("server", stringParser()) { _, _ -> + api.persistentServer().allPersistentServers.thenApply { servers -> + servers.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .required("setting", stringParser()) { _, _ -> + CompletableFuture.completedFuture(persistentSettings.map { Suggestion.suggestion(it) }) + } + .required("value", stringParser()) + .handler { context -> + val serverName = context.get("server") + val setting = context.get("setting") + val value = context.get("value") + scope.launch { + try { + val persistent = api.persistentServer().getPersistentServerByName(serverName).await() + val builder = persistentUpdateBuilder(persistent) + when (setting) { + "max-players" -> builder.maxPlayers(parseIntOrError(value, setting, context.sender()) ?: return@launch) + "min-memory" -> builder.minMemory(parseIntOrError(value, setting, context.sender()) ?: return@launch) + "max-memory" -> builder.maxMemory(parseIntOrError(value, setting, context.sender()) ?: return@launch) + "active" -> builder.active(parseBoolOrError(value, setting, context.sender()) ?: return@launch) + else -> { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.invalidSetting, Placeholder.unparsed("key", setting))) + return@launch + } + } + val updated = api.persistentServer().updatePersistentServer( + persistent.persistentServerId, builder.build() + ).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.persistentServerUpdated, PersistentServerTagResolver.of(updated))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.edit.persistent")) + .build() + ) + } + + private fun parseIntOrError(value: String, key: String, sender: CloudSender): Int? { + return value.toIntOrNull() ?: run { + sender.sendMessage(miniMessage(plugin.messageConfiguration.invalidValue, Placeholder.unparsed("value", value), Placeholder.unparsed("key", key))) + null + } + } + + private fun parseBoolOrError(value: String, key: String, sender: CloudSender): Boolean? { + return value.toBooleanStrictOrNull() ?: run { + sender.sendMessage(miniMessage(plugin.messageConfiguration.invalidValue, Placeholder.unparsed("value", value), Placeholder.unparsed("key", key))) + null + } + } + + companion object { + fun persistentUpdateBuilder(persistent: PersistentServer): UpdatePersistentServerRequest.Builder { + return UpdatePersistentServerRequest.builder() + .name(persistent.name) + .type(persistent.type) + .source(persistent.source) + .workflows(persistent.workflows) + .serverhostId(persistent.serverhostId) + .minMemory(persistent.minMemory) + .maxMemory(persistent.maxMemory) + .maxPlayers(persistent.maxPlayers) + .active(persistent.isActive) + .properties(persistent.properties) + .tags(persistent.tags) + } + } +} diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt deleted file mode 100644 index 1662f19..0000000 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/GroupInfoCommand.kt +++ /dev/null @@ -1,116 +0,0 @@ -package app.simplecloud.plugin.command.shared.commands - -import app.simplecloud.api.CloudApi -import app.simplecloud.api.server.ServerQuery -import app.simplecloud.plugin.command.shared.CloudSender -import app.simplecloud.plugin.command.shared.CommandPlugin -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.minimessage.MiniMessage -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder -import org.incendo.cloud.CommandManager -import org.incendo.cloud.context.CommandContext -import org.incendo.cloud.parser.standard.StringParser.stringParser -import org.incendo.cloud.permission.Permission -import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider - -class GroupInfoCommand( - private val cloudApi: CloudApi, - private val commandPlugin: CommandPlugin -) { - - fun register(commandManager: CommandManager) { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("info", "get") - .literal("groups", "group") - .optional("group", stringParser(), SuggestionProvider { _, _ -> - cloudApi.group().allGroups.thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .handler { context: CommandContext -> - val groupName = context.getOrDefault("group", null as String?) - if (groupName != null) { - cloudApi.group().getGroupByName(groupName).thenAccept { group -> - // TODO: get server by group - cloudApi.server().getAllServers(ServerQuery.create() - .filterByServerGroupName(groupName)).thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoTitle, - Placeholder.component("servergroup", Component.text(groupName)), - Placeholder.component("serveramount", Component.text(servers.size)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoType, - Placeholder.component("grouptype", Component.text(group.type.name)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoTemplate, - Placeholder.component( - "grouptemplate", - Component.text(group.properties.get("template-id").toString()) - ) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoMemory, - Placeholder.component("minmemory", Component.text(group.minMemory)), - Placeholder.component("maxmemory", Component.text(group.maxMemory)) - ) - ) - - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupInfoPlayers, - Placeholder.component("maxplayers", Component.text(group.maxPlayers)) - ) - ) - } - } - } else { - cloudApi.group().allGroups.thenAccept { groups -> - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize(commandPlugin.messageConfiguration.groupsListTitle) - ) - groups.forEach { group -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupsListEntry, - Placeholder.component("servergroup", Component.text(group.name)), - Placeholder.component( - "onlinecount", - Component.text( - cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(groupName)).get().size.toString() - ) - ), - Placeholder.component( - "template", - Component.text(group.properties["template-id"].toString()) - ), - Placeholder.component("type", Component.text(group.type.name)), - Placeholder.component("maxcount", Component.text(group.maxPlayers)), - Placeholder.component("minmemory", Component.text(group.minMemory)), - Placeholder.component("maxmemory", Component.text(group.maxMemory)), - ) - ) - } - } - } - } - .permission(Permission.permission("simplecloud.command.cloud.get.groups")) - .build() - ) - } -} - diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/InfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/InfoCommand.kt new file mode 100644 index 0000000..069ce55 --- /dev/null +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/InfoCommand.kt @@ -0,0 +1,197 @@ +package app.simplecloud.plugin.command.shared.commands + +import app.simplecloud.api.CloudApi +import app.simplecloud.plugin.command.shared.CloudSender +import app.simplecloud.plugin.command.shared.CommandPlugin +import app.simplecloud.plugin.command.shared.miniMessage +import app.simplecloud.plugin.command.shared.resolver.GroupTagResolver +import app.simplecloud.plugin.command.shared.resolver.PersistentServerTagResolver +import app.simplecloud.plugin.command.shared.resolver.ServerTagResolver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder +import org.incendo.cloud.CommandManager +import org.incendo.cloud.parser.standard.IntegerParser.integerParser +import org.incendo.cloud.parser.standard.StringParser.stringParser +import org.incendo.cloud.permission.Permission +import org.incendo.cloud.suggestion.Suggestion +import java.util.concurrent.CompletableFuture + +class InfoCommand( + private val api: CloudApi, + private val plugin: CommandPlugin +) { + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + fun register(commandManager: CommandManager) { + registerServerInfo(commandManager) + registerGroupInfo(commandManager) + registerPersistentServerInfo(commandManager) + } + + private fun registerServerInfo(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("info") + .literal("servers", "server") + .optional("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .optional("id", integerParser()) { context, _ -> + try { + val group = context.get("group") + api.server().getServersByGroup(group).thenApply { servers -> + servers.map { Suggestion.suggestion(it.numericalId.toString()) } + }.exceptionally { emptyList() } + } catch (e: Exception) { + CompletableFuture.completedFuture(emptyList()) + } + } + .handler { context -> + val groupName = context.getOrDefault("group", null as String?) + val id = context.getOrDefault("id", null as Int?) + scope.launch { + try { + when { + groupName != null && id != null -> showServerDetail(context.sender(), groupName, id) + groupName != null -> showGroupServers(context.sender(), groupName) + else -> showAllServers(context.sender()) + } + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.info.servers")) + .build() + ) + } + + private suspend fun showServerDetail(sender: CloudSender, groupName: String, id: Int) { + val server = api.server().getServerByNumericalId(groupName, id).await() + val resolver = ServerTagResolver.of(server) + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverInfoTitle, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverInfoState, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverInfoMemory, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverInfoPlayers, resolver)) + } + + private suspend fun showGroupServers(sender: CloudSender, groupName: String) { + val group = api.group().getGroupByName(groupName).await() + val servers = api.server().getServersByGroup(groupName).await() + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupServerListTitle, GroupTagResolver.of(group))) + servers.forEach { server -> + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupServerListEntry, ServerTagResolver.of(server))) + } + } + + private suspend fun showAllServers(sender: CloudSender) { + val servers = api.server().allServers.await() + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverListTitle)) + servers.forEach { server -> + sender.sendMessage(miniMessage(plugin.messageConfiguration.serverListEntry, ServerTagResolver.of(server))) + } + } + + private fun registerGroupInfo(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("info") + .literal("groups", "group") + .optional("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .handler { context -> + val groupName = context.getOrDefault("group", null as String?) + scope.launch { + try { + if (groupName != null) { + showGroupDetail(context.sender(), groupName) + } else { + showAllGroups(context.sender()) + } + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.info.groups")) + .build() + ) + } + + private suspend fun showGroupDetail(sender: CloudSender, groupName: String) { + val group = api.group().getGroupByName(groupName).await() + val servers = api.server().getServersByGroup(groupName).await() + val resolver = GroupTagResolver.of(group) + val countPlaceholder = Placeholder.unparsed("server_count", servers.size.toString()) + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupInfoTitle, resolver, countPlaceholder)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupInfoType, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupInfoMemory, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupInfoPlayers, resolver)) + } + + private suspend fun showAllGroups(sender: CloudSender) { + val groups = api.group().allGroups.await() + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupsListTitle)) + groups.forEach { group -> + val servers = api.server().getServersByGroup(group.name).await() + sender.sendMessage(miniMessage(plugin.messageConfiguration.groupsListEntry, GroupTagResolver.of(group), Placeholder.unparsed("server_count", servers.size.toString()))) + } + } + + private fun registerPersistentServerInfo(commandManager: CommandManager) { + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("info") + .literal("persistent") + .optional("server", stringParser()) { _, _ -> + api.persistentServer().allPersistentServers.thenApply { servers -> + servers.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .handler { context -> + val serverName = context.getOrDefault("server", null as String?) + scope.launch { + try { + if (serverName != null) { + showPersistentServerDetail(context.sender(), serverName) + } else { + showAllPersistentServers(context.sender()) + } + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.info.persistent")) + .build() + ) + } + + private suspend fun showPersistentServerDetail(sender: CloudSender, serverName: String) { + val persistent = api.persistentServer().getPersistentServerByName(serverName).await() + val resolver = PersistentServerTagResolver.of(persistent) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoTitle, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoType, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoMemory, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoPlayers, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoActive, resolver)) + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServerInfoServerhost, resolver)) + } + + private suspend fun showAllPersistentServers(sender: CloudSender) { + val servers = api.persistentServer().allPersistentServers.await() + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServersListTitle)) + servers.forEach { server -> + sender.sendMessage(miniMessage(plugin.messageConfiguration.persistentServersListEntry, PersistentServerTagResolver.of(server))) + } + } +} diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt deleted file mode 100644 index 95786c9..0000000 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/ServerInfoCommand.kt +++ /dev/null @@ -1,164 +0,0 @@ -package app.simplecloud.plugin.command.shared.commands - -import app.simplecloud.api.CloudApi -import app.simplecloud.plugin.command.shared.CloudSender -import app.simplecloud.plugin.command.shared.CommandPlugin -import org.incendo.cloud.CommandManager -import org.incendo.cloud.context.CommandContext -import org.incendo.cloud.parser.standard.LongParser.longParser -import org.incendo.cloud.parser.standard.StringParser.stringParser -import org.incendo.cloud.permission.Permission -import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider -import kotlin.text.get - -class ServerInfoCommand( - private val cloudApi: CloudApi, - private val commandPlugin: CommandPlugin -) { - - fun register(commandManager: CommandManager) { - commandManager.command( - commandManager.commandBuilder("cloud") - .literal("info", "get") - .literal("servers", "server") - .optional("group", stringParser(), SuggestionProvider { _, _ -> - cloudApi.group().allGroups.thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .optional("id", longParser(), SuggestionProvider { _, _ -> - cloudApi.server().allServers.thenApply { servers -> - servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } - } - }) - .handler { context: CommandContext -> - val groupName = context.getOrDefault("group", null as String?) - val id = context.getOrDefault("id", null as Long?) - - when { - groupName != null && id != null -> { - /* TODO: get server by numerical - controllerApi.getServers().getServerByNumerical(groupName, id).thenAccept { server -> - - cloudApi.group().getGroupByName(groupName).thenAccept { group -> - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoTitle, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "serveramount", - Component.text( - controllerApi.getServers().getServersByGroup(groupName) - .get().size.toString() - ) - ), - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoType, - Placeholder.component("grouptype", Component.text(server.type.name)) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoSoftware, - Placeholder.component( - "groupsoftware", - Component.text(group.properties["server-software"].toString()) - ) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoMemory, - Placeholder.component("groupmemory", Component.text(server.maxMemory)) - ) - ) - context.sender().sendMessage( - MiniMessage.miniMessage() - .deserialize( - commandPlugin.messageConfiguration.serverInfoPlayers, - Placeholder.component( - "groupplayers", - Component.text(server.playerCount) - ) - ) - ) - } - } - } - - groupName != null -> { - controllerApi.getServers().getServersByGroup(groupName).thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerListTitle, - Placeholder.component("servergroup", Component.text(groupName)) - ) - ) - servers.forEach { server -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerListEntry, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "numericalid", - Component.text(server.numericalId.toString()) - ), - Placeholder.component( - "onlineplayers", - Component.text(server.playerCount) - ), - Placeholder.component("maxplayers", Component.text(server.maxPlayers)), - Placeholder.component("minmemory", Component.text(server.minMemory)), - Placeholder.component("maxmemory", Component.text(server.maxMemory)), - Placeholder.component("state", Component.text(server.state.name)), - ) - ) - } - } - } - - else -> { - controllerApi.getServers().getAllServers().thenAccept { servers -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverListTitle, - ) - ) - servers.forEach { server -> - context.sender().sendMessage( - MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverListEntry, - Placeholder.component("servergroup", Component.text(server.group)), - Placeholder.component( - "numericalid", - Component.text(server.numericalId.toString()) - ), - Placeholder.component( - "onlineplayers", - Component.text(server.playerCount) - ), - Placeholder.component("maxplayers", Component.text(server.maxPlayers)), - Placeholder.component("minmemory", Component.text(server.minMemory)), - Placeholder.component("maxmemory", Component.text(server.maxMemory)), - Placeholder.component("state", Component.text(server.state.name)), - ) - ) - } - } - } - } */ - } - .permission(Permission.permission("simplecloud.command.cloud.get.servers")) - .build() - ) - } -} - diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt index d0ea65d..ea7b03b 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StartCommand.kt @@ -4,56 +4,89 @@ import app.simplecloud.api.CloudApi import app.simplecloud.api.server.StartServerRequest import app.simplecloud.plugin.command.shared.CloudSender import app.simplecloud.plugin.command.shared.CommandPlugin -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.minimessage.MiniMessage +import app.simplecloud.plugin.command.shared.miniMessage +import app.simplecloud.plugin.command.shared.resolver.GroupTagResolver +import app.simplecloud.plugin.command.shared.resolver.PersistentServerTagResolver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.incendo.cloud.CommandManager -import org.incendo.cloud.context.CommandContext import org.incendo.cloud.parser.standard.StringParser.stringParser import org.incendo.cloud.permission.Permission import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider -class StartCommand( - private val cloudApi: CloudApi, - private val commandPlugin: CommandPlugin +class StartCommand( + private val api: CloudApi, + private val plugin: CommandPlugin ) { + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - fun register(commandManager: CommandManager) { + fun register(commandManager: CommandManager) { commandManager.command( commandManager.commandBuilder("cloud") .literal("start") - .required( - "group", - stringParser(), - SuggestionProvider { _, _ -> - cloudApi.group().allGroups.thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } + .literal("group") + .required("group", stringParser()) { _, _ -> + api.group().allGroups + .thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + } + .exceptionally { emptyList() } + } + .handler { context -> + val groupName = context.get("group") + scope.launch { + try { + val group = api.group().getGroupByName(groupName).await() + api.server().startServer(StartServerRequest(group.serverGroupId, group.name)) + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.serverStarting, GroupTagResolver.of(group))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) } } - ) - .handler { context: CommandContext -> - val group = context.get("group") - - cloudApi.group().getGroupByName(group).thenAccept { group -> - val request = StartServerRequest(group.serverGroupId, group.name) + } + .permission(Permission.permission("simplecloud.command.cloud.start.group")) + .build() + ) - cloudApi.server().startServer(request).thenAccept { server -> - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverStarting, - Placeholder.component("group", Component.text(group.name)), - // TODO: server returns a Void - Placeholder.component("id", Component.text(server)) + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("start") + .literal("persistent") + .required("server", stringParser()) { _, _ -> + api.persistentServer().allPersistentServers + .thenApply { servers -> + servers.map { Suggestion.suggestion(it.name) } + } + .exceptionally { emptyList() } + } + .handler { context -> + val serverName = context.get("server") + scope.launch { + try { + val persistent = api.persistentServer().getPersistentServerByName(serverName).await() + api.persistentServer().updatePersistentServer( + persistent.persistentServerId, + EditCommand.persistentUpdateBuilder(persistent) + .active(true) + .build() + ).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.persistentServerActivated, PersistentServerTagResolver.of(persistent))) + } catch (e: Exception) { + context.sender().sendMessage( + miniMessage( + plugin.messageConfiguration.errorMessage, + Placeholder.unparsed("error", e.message ?: "Unknown error") + ) ) - - context.sender().sendMessage(message) } } - } - .permission(Permission.permission("simplecloud.command.cloud.start")) + .permission(Permission.permission("simplecloud.command.cloud.start.persistent")) .build() ) } -} - +} \ No newline at end of file diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt index ca1f331..4a6b089 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/commands/StopCommand.kt @@ -1,75 +1,103 @@ package app.simplecloud.plugin.command.shared.commands import app.simplecloud.api.CloudApi -import app.simplecloud.api.server.ServerQuery import app.simplecloud.plugin.command.shared.CloudSender import app.simplecloud.plugin.command.shared.CommandPlugin -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.minimessage.MiniMessage +import app.simplecloud.plugin.command.shared.miniMessage +import app.simplecloud.plugin.command.shared.resolver.GroupTagResolver +import app.simplecloud.plugin.command.shared.resolver.PersistentServerTagResolver +import app.simplecloud.plugin.command.shared.resolver.ServerTagResolver +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.future.await +import kotlinx.coroutines.launch import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder import org.incendo.cloud.CommandManager -import org.incendo.cloud.context.CommandContext -import org.incendo.cloud.parser.standard.LongParser.longParser +import org.incendo.cloud.parser.standard.IntegerParser.integerParser import org.incendo.cloud.parser.standard.StringParser.stringParser import org.incendo.cloud.permission.Permission import org.incendo.cloud.suggestion.Suggestion -import org.incendo.cloud.suggestion.SuggestionProvider +import java.util.concurrent.CompletableFuture -class StopCommand( - private val cloudApi: CloudApi, - private val commandPlugin: CommandPlugin +class StopCommand( + private val api: CloudApi, + private val plugin: CommandPlugin ) { + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - fun register(commandManager: CommandManager) { + fun register(commandManager: CommandManager) { commandManager.command( commandManager.commandBuilder("cloud") .literal("stop") - .required("group", stringParser(), SuggestionProvider { _, _ -> - cloudApi.group().allGroups.thenApply { groups -> - groups.map { group -> Suggestion.suggestion(group.name) } - } - }) - .optional("id", longParser(), SuggestionProvider { _, _ -> - cloudApi.server().allServers.thenApply { servers -> - servers.map { server -> Suggestion.suggestion(server.numericalId.toString()) } + .literal("group") + .required("group", stringParser()) { _, _ -> + api.group().allGroups.thenApply { groups -> + groups.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .optional("id", integerParser()) { context, _ -> + try { + val group = context.get("group") + api.server().getServersByGroup(group).thenApply { servers -> + servers.map { Suggestion.suggestion(it.numericalId.toString()) } + }.exceptionally { emptyList() } + } catch (e: Exception) { + CompletableFuture.completedFuture(emptyList()) } - }) - .handler { context: CommandContext -> - val group = context.get("group") - val id = context.getOrDefault("id", null as Long?) - - if (id == null) { - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.groupServerStopped, - Placeholder.component("group", Component.text(group)), - ) - - // TODO: get server by group - - cloudApi.server().getAllServers(ServerQuery.create().filterByServerGroupName(group)) - .thenApply { servers -> - servers.forEach { server -> - cloudApi.server().stopServer(server.serverId) - } + } + .handler { context -> + val groupName = context.get("group") + val id = context.getOrDefault("id", null as Int?) + scope.launch { + try { + if (id != null) { + val server = api.server().getServerByNumericalId(groupName, id).await() + api.server().stopServer(server.serverId).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.serverStopped, ServerTagResolver.of(server))) + } else { + val group = api.group().getGroupByName(groupName).await() + val servers = api.server().getServersByGroup(groupName).await() + servers.forEach { api.server().stopServer(it.serverId) } + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.groupServersStopped, GroupTagResolver.of(group))) } + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } + } + } + .permission(Permission.permission("simplecloud.command.cloud.stop.group")) + .build() + ) - context.sender().sendMessage(message) - } else { - val message = MiniMessage.miniMessage().deserialize( - commandPlugin.messageConfiguration.serverStopped, - Placeholder.component("group", Component.text(group)), - Placeholder.component("id", Component.text(id.toString())) - ) - - // TODO: stop server by numerical - - // controllerApi.getServers().stopServer(group, id) - context.sender().sendMessage(message) + commandManager.command( + commandManager.commandBuilder("cloud") + .literal("stop") + .literal("persistent") + .required("server", stringParser()) { _, _ -> + api.persistentServer().allPersistentServers.thenApply { servers -> + servers.map { Suggestion.suggestion(it.name) } + }.exceptionally { emptyList() } + } + .handler { context -> + val serverName = context.get("server") + scope.launch { + try { + val persistent = api.persistentServer().getPersistentServerByName(serverName).await() + api.persistentServer().updatePersistentServer( + persistent.persistentServerId, + EditCommand.persistentUpdateBuilder(persistent) + .active(false) + .build() + ).await() + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.persistentServerDeactivated, PersistentServerTagResolver.of(persistent))) + } catch (e: Exception) { + context.sender().sendMessage(miniMessage(plugin.messageConfiguration.errorMessage, Placeholder.unparsed("error", e.message ?: "Unknown error"))) + } } } - .permission(Permission.permission("simplecloud.command.cloud.stop")) + .permission(Permission.permission("simplecloud.command.cloud.stop.persistent")) .build() ) } } - diff --git a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/config/MessageConfig.kt b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/config/MessageConfig.kt index b5dc7bb..ee71180 100644 --- a/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/config/MessageConfig.kt +++ b/command-shared/src/main/kotlin/app/simplecloud/plugin/command/shared/config/MessageConfig.kt @@ -2,51 +2,68 @@ package app.simplecloud.plugin.command.shared.config import org.spongepowered.configurate.objectmapping.ConfigSerializable -/** - * @author Fynn Bauer in 2024 - */ - @ConfigSerializable data class MessageConfig( - val serverStarting: String = " A new server of group is starting ( )", - val serverStopped: String = " Server was stopped.", - val groupServerStopped: String = " Servers of group were stopped.", - val groupDeleted: String = " Server group was deleted.", - - val cloudHelpTitle: String = " Commands of Cloud Command Plugin", - val cloudStartCommand: String = " /cloud start ", - val cloudStopCommand: String = " /cloud stop ", - val cloudServerInfoCommand: String = " /cloud info servers [serverGroup] [Numerical ID]", - val cloudGroupInfoCommand: String = " /cloud info groups [groupName] [Numerical ID]", - val cloudDeleteGroupCommand: String = " /cloud delete group ", - val cloudEditGroupCommand: String = " /cloud edit group ", - val cloudEditServerCommand: String = " /cloud edit server ", - - val serverInfoTitle: String = " Information of server Online", - val serverInfoType: String = " Type: ", - val serverInfoSoftware: String = " Software: ", - val serverInfoMemory: String = " Memory: ", - val serverInfoPlayers: String = " Players: ", - - val groupInfoTitle: String = " Information of group Online", - val groupInfoType: String = " Type: ", - val groupInfoTemplate: String = " Template: ", - val groupInfoMemory: String = " Memory: -", - val groupInfoPlayers: String = " Players: ", + val cloudHelpMessage: String = """ + Commands of Cloud Command Plugin + /cloud start group + /cloud start persistent + /cloud stop group [id] + /cloud stop persistent + /cloud info servers [group] [id] + /cloud info groups [group] + /cloud info persistent [server] + /cloud delete group + /cloud delete persistent + /cloud edit group + /cloud edit server + /cloud edit persistent + """.trimIndent(), - val groupsListTitle: String = " List of every server group", - val groupsListEntry: String = " Online (