diff --git a/gradle.properties b/gradle.properties index 87c6bd7..94db2d5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ kotlin.code.style=official kotlin.stdlib.default.dependency=false org.gradle.parallel=true -version=2.2.1-SNAPSHOT +version=2.3.0-SNAPSHOT \ No newline at end of file diff --git a/surf-core-api/surf-core-api-paper/src/main/kotlin/dev/slne/surf/core/api/paper/CorePlayerInfoProvider.kt b/surf-core-api/surf-core-api-paper/src/main/kotlin/dev/slne/surf/core/api/paper/CorePlayerInfoProvider.kt new file mode 100644 index 0000000..05de044 --- /dev/null +++ b/surf-core-api/surf-core-api-paper/src/main/kotlin/dev/slne/surf/core/api/paper/CorePlayerInfoProvider.kt @@ -0,0 +1,38 @@ +package dev.slne.surf.core.api.paper + +import dev.slne.surf.core.api.paper.CorePlayerInfoProvider.Companion.getServerInfo +import java.util.* + +interface CorePlayerInfoProvider { + fun createServerInfo(playerUuid: UUID): ServerInfo? + + /** + * Server Info data class containing the server name, nice name and region. This is used to provide information about the server a player is currently on. + * + * @param serverName The name of the server the player is currently on. + * @param serverDisplayName The nice name of the server the player is currently on. + * @param serverRegion The region of the server the player is currently on. + * + * NOTE: This method should not be used to gain access to players current server. Use [dev.slne.surf.core.api.common.player.SurfPlayer.currentServer] instead. + * + * @see [getServerInfo] + */ + data class ServerInfo( + val serverName: String, + val serverDisplayName: String, + val serverRegion: String + ) + + companion object { + private lateinit var instance: CorePlayerInfoProvider + + fun setInstance(provider: CorePlayerInfoProvider) { + instance = provider + } + + /** + * Available after plugin bootstrapper + */ + fun getServerInfo(playerUuid: UUID) = instance.createServerInfo(playerUuid) + } +} \ No newline at end of file diff --git a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfCommonServerArgument.kt b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfCommonServerArgument.kt index 4711a2d..372f9f8 100644 --- a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfCommonServerArgument.kt +++ b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfCommonServerArgument.kt @@ -7,6 +7,7 @@ import com.velocitypowered.api.command.VelocityBrigadierMessage import dev.jorel.commandapi.CommandAPICommand import dev.jorel.commandapi.CommandTree import dev.jorel.commandapi.arguments.Argument +import dev.jorel.commandapi.arguments.ArgumentSuggestions import dev.jorel.commandapi.arguments.CommandAPIArgumentType import dev.jorel.commandapi.executors.CommandArguments import dev.slne.surf.api.core.messages.adventure.buildText @@ -19,6 +20,14 @@ open class SurfServerArgument(nodeName: String) : return CommonSurfServer::class.java } + init { + replaceSuggestions( + ArgumentSuggestions.stringCollection { _ -> + SurfCoreApi.getCommonServers().map { it.name } + } + ) + } + override fun getArgumentType(): CommandAPIArgumentType? { return CommandAPIArgumentType.PRIMITIVE_STRING } diff --git a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfOfflinePlayerArgument.kt b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfOfflinePlayerArgument.kt index dc247bb..d66684b 100644 --- a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfOfflinePlayerArgument.kt +++ b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfOfflinePlayerArgument.kt @@ -5,6 +5,7 @@ import com.mojang.brigadier.context.CommandContext import dev.jorel.commandapi.CommandAPICommand import dev.jorel.commandapi.CommandTree import dev.jorel.commandapi.arguments.Argument +import dev.jorel.commandapi.arguments.ArgumentSuggestions import dev.jorel.commandapi.arguments.CommandAPIArgumentType import dev.jorel.commandapi.executors.CommandArguments import dev.slne.surf.api.core.util.logger @@ -33,6 +34,15 @@ open class SurfOfflinePlayerArgument(nodeName: String) : SurfCoreApi.getOfflinePlayer(StringArgumentType.getString(cmdCtx, key)) }.asDeferred() + init { + replaceSuggestions( + ArgumentSuggestions.stringCollection { _ -> + SurfCoreApi.getOnlinePlayers() + .mapNotNull { it.lastKnownName } + } + ) + } + companion object { private val log = logger() private val scope = diff --git a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfPlayerArgument.kt b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfPlayerArgument.kt index 0f8bac3..297e3d3 100644 --- a/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfPlayerArgument.kt +++ b/surf-core-api/surf-core-api-velocity/src/main/kotlin/dev/slne/surf/core/api/velocity/command/argument/SurfPlayerArgument.kt @@ -7,6 +7,7 @@ import com.velocitypowered.api.command.VelocityBrigadierMessage import dev.jorel.commandapi.CommandAPICommand import dev.jorel.commandapi.CommandTree import dev.jorel.commandapi.arguments.Argument +import dev.jorel.commandapi.arguments.ArgumentSuggestions import dev.jorel.commandapi.arguments.CommandAPIArgumentType import dev.jorel.commandapi.executors.CommandArguments import dev.slne.surf.api.core.messages.adventure.buildText @@ -36,6 +37,16 @@ open class SurfPlayerArgument(nodeName: String) : } ) ).create() + + + init { + replaceSuggestions( + ArgumentSuggestions.stringCollection { _ -> + SurfCoreApi.getOnlinePlayers() + .mapNotNull { it.lastKnownName } + } + ) + } } inline fun CommandTree.surfPlayerArgument( diff --git a/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/ClientLoader.kt b/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/ClientLoader.kt index 0319c8b..98f934c 100644 --- a/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/ClientLoader.kt +++ b/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/ClientLoader.kt @@ -4,8 +4,10 @@ package dev.slne.surf.core.client import dev.slne.surf.core.core.common.event.LocalSurfEventBusListener import dev.slne.surf.core.core.common.player.SurfPlayerService +import dev.slne.surf.core.core.common.redis.listener.ExecuteCommandRedisListener import dev.slne.surf.core.core.common.redis.listener.SendPlayerToProxyListener import dev.slne.surf.core.core.common.redis.listener.SendPlayerToServerListener +import dev.slne.surf.core.core.common.redis.listener.ShutdownServerRedisListener import dev.slne.surf.core.core.common.server.SurfServerService import dev.slne.surf.rabbitmq.api.ClientRabbitMQApi import dev.slne.surf.redis.RedisApi @@ -31,6 +33,9 @@ class ClientLoader( withListener(SendPlayerToServerListener) withListener(SendPlayerToProxyListener) + withRequestResponseHandler(ShutdownServerRedisListener) + withRequestResponseHandler(ExecuteCommandRedisListener) + // Initialize Redis Maps SurfPlayerService SurfServerService diff --git a/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/server/SurfServerServiceImpl.kt b/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/server/SurfServerServiceImpl.kt index 8caba8d..9aba35b 100644 --- a/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/server/SurfServerServiceImpl.kt +++ b/surf-core-core/surf-core-core-client/src/main/kotlin/dev/slne/surf/core/client/server/SurfServerServiceImpl.kt @@ -7,8 +7,11 @@ import dev.slne.surf.core.api.common.server.SurfProxyServer import dev.slne.surf.core.api.common.server.SurfServer import dev.slne.surf.core.api.common.server.state.SurfServerState import dev.slne.surf.core.client.ClientCoreInstance +import dev.slne.surf.core.core.common.redis.request.ExecuteCommandServerRequest +import dev.slne.surf.core.core.common.redis.request.ShutdownServerRequest import dev.slne.surf.core.core.common.server.SurfServerService import it.unimi.dsi.fastutil.objects.ObjectSet +import net.kyori.adventure.text.Component import java.util.* @AutoService(SurfServerService::class) @@ -55,6 +58,14 @@ class SurfServerServiceImpl : SurfServerService { } } + override suspend fun shutdown(commonSurfServer: CommonSurfServer, reason: Component?) = + ShutdownServerRequest.createRequest(commonSurfServer, reason).status + + override suspend fun executeCommand( + commonSurfServer: CommonSurfServer, + command: String + ) = ExecuteCommandServerRequest.createRequest(commonSurfServer, command).status + override fun getServerByName(name: String) = servers.find { it.name == name } override fun getServerByCategory(category: String) = servers.filter { it.category == category }.toObjectSet() diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ExecuteCommandRedisListener.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ExecuteCommandRedisListener.kt new file mode 100644 index 0000000..b6956a2 --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ExecuteCommandRedisListener.kt @@ -0,0 +1,21 @@ +package dev.slne.surf.core.core.common.redis.listener + +import dev.slne.surf.core.core.common.redis.request.ExecuteCommandServerRequest +import dev.slne.surf.redis.request.HandleRedisRequest +import dev.slne.surf.redis.request.RequestContext + +object ExecuteCommandRedisListener { + @HandleRedisRequest + suspend fun handleExecuteCommandRequest(context: RequestContext) { + RemoteCommandExecutor.executeCommand( + context.request.commonSurfServer, + context.request.command + )?.let { + context.respond( + ExecuteCommandServerRequest.Response( + it + ) + ) + } + } +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/RemoteCommandExecutor.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/RemoteCommandExecutor.kt new file mode 100644 index 0000000..18239bd --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/RemoteCommandExecutor.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.core.core.common.redis.listener + +import dev.slne.surf.api.core.util.requiredService +import dev.slne.surf.core.api.common.server.CommonSurfServer + +private val listener = requiredService() + +interface RemoteCommandExecutor { + suspend fun executeCommand(commonSurfServer: CommonSurfServer, command: String): Boolean? + + companion object : + RemoteCommandExecutor by listener +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ServerShutdownHandler.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ServerShutdownHandler.kt new file mode 100644 index 0000000..a5335b2 --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ServerShutdownHandler.kt @@ -0,0 +1,13 @@ +package dev.slne.surf.core.core.common.redis.listener + +import dev.slne.surf.api.core.util.requiredService +import dev.slne.surf.core.api.common.server.CommonSurfServer +import net.kyori.adventure.text.Component + +private val listener = requiredService() + +interface ServerShutdownHandler { + fun shutdown(commonSurfServer: CommonSurfServer, reason: Component?): Boolean? + + companion object : ServerShutdownHandler by listener +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ShutdownServerRedisListener.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ShutdownServerRedisListener.kt new file mode 100644 index 0000000..4658d4f --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/listener/ShutdownServerRedisListener.kt @@ -0,0 +1,22 @@ +package dev.slne.surf.core.core.common.redis.listener + +import dev.slne.surf.core.core.common.redis.request.ShutdownServerRequest +import dev.slne.surf.redis.request.HandleRedisRequest +import dev.slne.surf.redis.request.RequestContext + +object ShutdownServerRedisListener { + @HandleRedisRequest + fun handleShutdownRequest(context: RequestContext) { + ServerShutdownHandler.shutdown( + context.request.commonSurfServer, + context.request.reason + )?.let { + context.respond( + ShutdownServerRequest.Response( + it + ) + ) + } + + } +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ExecuteCommandServerRequest.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ExecuteCommandServerRequest.kt new file mode 100644 index 0000000..5083cd1 --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ExecuteCommandServerRequest.kt @@ -0,0 +1,29 @@ +package dev.slne.surf.core.core.common.redis.request + +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.core.CoreInstance +import dev.slne.surf.redis.request.RedisRequest +import dev.slne.surf.redis.request.RedisResponse +import kotlinx.serialization.Serializable +import kotlin.time.Duration.Companion.seconds + +object ExecuteCommandServerRequest { + @Serializable + data class Request( + val commonSurfServer: CommonSurfServer, + val command: String + ) : RedisRequest() + + @Serializable + data class Response( + val status: Boolean + ) : RedisResponse() + + suspend fun createRequest(commonSurfServer: CommonSurfServer, command: String) = + runCatching { + CoreInstance.redisApi.sendRequest( + Request(commonSurfServer, command), + 10.seconds.inWholeMilliseconds + ) + }.getOrNull() ?: Response(false) +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ShutdownServerRequest.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ShutdownServerRequest.kt new file mode 100644 index 0000000..0998fdf --- /dev/null +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/redis/request/ShutdownServerRequest.kt @@ -0,0 +1,31 @@ +package dev.slne.surf.core.core.common.redis.request + +import dev.slne.surf.api.core.serializer.adventure.component.SerializableComponent +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.core.CoreInstance +import dev.slne.surf.redis.request.RedisRequest +import dev.slne.surf.redis.request.RedisResponse +import kotlinx.serialization.Serializable +import net.kyori.adventure.text.Component +import kotlin.time.Duration.Companion.seconds + +object ShutdownServerRequest { + @Serializable + data class Request( + val commonSurfServer: CommonSurfServer, + val reason: SerializableComponent? + ) : RedisRequest() + + @Serializable + data class Response( + val status: Boolean + ) : RedisResponse() + + suspend fun createRequest(commonSurfServer: CommonSurfServer, reason: Component?) = + runCatching { + CoreInstance.redisApi.sendRequest( + Request(commonSurfServer, reason), + 10.seconds.inWholeMilliseconds + ) + }.getOrNull() ?: Response(false) +} \ No newline at end of file diff --git a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/server/SurfServerService.kt b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/server/SurfServerService.kt index ad3871a..22f8426 100644 --- a/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/server/SurfServerService.kt +++ b/surf-core-core/surf-core-core-common/src/main/kotlin/dev/slne/surf/core/core/common/server/SurfServerService.kt @@ -6,6 +6,7 @@ import dev.slne.surf.core.api.common.server.SurfProxyServer import dev.slne.surf.core.api.common.server.SurfServer import dev.slne.surf.core.api.common.server.state.SurfServerState import it.unimi.dsi.fastutil.objects.ObjectSet +import net.kyori.adventure.text.Component import org.jetbrains.annotations.UnmodifiableView import java.util.* @@ -19,6 +20,9 @@ interface SurfServerService { fun removeServer(server: CommonSurfServer) fun changeState(commonSurfServer: CommonSurfServer, state: SurfServerState) + suspend fun shutdown(commonSurfServer: CommonSurfServer, reason: Component?): Boolean + suspend fun executeCommand(commonSurfServer: CommonSurfServer, command: String): Boolean + fun getServerByName(name: String): SurfServer? fun getServerByUuid(uuid: UUID): CommonSurfServer? fun getServerByCategory(category: String): ObjectSet diff --git a/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/CoreMicroservice.kt b/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/CoreMicroservice.kt index 787478e..130a764 100644 --- a/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/CoreMicroservice.kt +++ b/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/CoreMicroservice.kt @@ -1,10 +1,7 @@ package dev.slne.surf.core.microservice import com.google.auto.service.AutoService -import dev.slne.surf.core.microservice.database.tables.SurfPlayerIpAddressHistoriesTable -import dev.slne.surf.core.microservice.database.tables.SurfPlayerNameHistoriesTable -import dev.slne.surf.core.microservice.database.tables.SurfPlayerTexturesHistoriesTable -import dev.slne.surf.core.microservice.database.tables.SurfPlayersTable +import dev.slne.surf.core.microservice.database.tables.* import dev.slne.surf.core.microservice.rabbit.* import dev.slne.surf.database.DatabaseApi import dev.slne.surf.database.libs.org.jetbrains.exposed.v1.r2dbc.SchemaUtils @@ -25,7 +22,8 @@ class CoreMicroservice : Microservice() { SurfPlayerIpAddressHistoriesTable, SurfPlayerNameHistoriesTable, SurfPlayersTable, - SurfPlayerTexturesHistoriesTable + SurfPlayerTexturesHistoriesTable, + SurfPlayerErrorsTable ) } diff --git a/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/rabbit/SurfPlayerErrorHandler.kt b/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/rabbit/SurfPlayerErrorHandler.kt index 7cc937b..8cd8ec6 100644 --- a/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/rabbit/SurfPlayerErrorHandler.kt +++ b/surf-core-microservice/src/main/kotlin/dev/slne/surf/core/microservice/rabbit/SurfPlayerErrorHandler.kt @@ -1,6 +1,7 @@ package dev.slne.surf.core.microservice.rabbit import dev.slne.surf.core.core.common.rabbit.packet.player.error.SaveSurfPlayerErrorRequestPacket +import dev.slne.surf.core.core.common.rabbit.packet.player.error.SingleSurfPlayerErrorResponsePacket import dev.slne.surf.core.microservice.database.repository.SurfPlayerErrorRepository import dev.slne.surf.rabbitmq.api.handler.RabbitHandler import kotlinx.coroutines.launch @@ -8,12 +9,16 @@ import kotlinx.coroutines.launch object SurfPlayerErrorHandler { @RabbitHandler fun handleSavePlayerError(packet: SaveSurfPlayerErrorRequestPacket) = packet.launch { - SurfPlayerErrorRepository.saveError( - playerUuid = packet.playerUuid, - occurredOn = packet.occurredOn, - occurredAt = packet.occurredAt, - staffMessage = packet.staffMessage, - errorCode = packet.errorCode + packet.respond( + SingleSurfPlayerErrorResponsePacket( + SurfPlayerErrorRepository.saveError( + playerUuid = packet.playerUuid, + occurredOn = packet.occurredOn, + occurredAt = packet.occurredAt, + staffMessage = packet.staffMessage, + errorCode = packet.errorCode + ) + ) ) } } \ No newline at end of file diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperBootstrap.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperBootstrap.kt index f70a85b..3dbca9c 100644 --- a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperBootstrap.kt +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperBootstrap.kt @@ -3,11 +3,13 @@ package dev.slne.surf.core.paper import dev.slne.surf.core.api.common.event.SurfServerStartEvent import dev.slne.surf.core.api.common.server.SurfServer import dev.slne.surf.core.api.common.server.state.SurfServerState +import dev.slne.surf.core.api.paper.CorePlayerInfoProvider import dev.slne.surf.core.client.ClientCoreInstance import dev.slne.surf.core.core.CoreInstance import dev.slne.surf.core.core.common.config.SurfServerConfiguration import dev.slne.surf.core.core.common.event.SurfEventBus import dev.slne.surf.core.core.common.server.SurfServerService +import dev.slne.surf.core.paper.api.DefaultCorePlayerInfoProvider import dev.slne.surf.core.paper.redis.listener.PaperRedisListener import dev.slne.surf.core.paper.teleport.TeleportRedisListener import io.papermc.paper.plugin.bootstrap.BootstrapContext @@ -46,6 +48,8 @@ class PaperBootstrap : PluginBootstrap { SurfEventBus.fire(SurfServerStartEvent(surfServerConfig.serverName)) SurfServerService.addServer(server) + + CorePlayerInfoProvider.setInstance(DefaultCorePlayerInfoProvider) } companion object { diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperMain.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperMain.kt index 892b11a..bf56c91 100644 --- a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperMain.kt +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/PaperMain.kt @@ -1,7 +1,9 @@ package dev.slne.surf.core.paper import com.github.shynixn.mccoroutine.folia.SuspendingJavaPlugin +import dev.slne.surf.api.core.luckperms.LuckPermsAccess import dev.slne.surf.api.paper.event.register +import dev.slne.surf.api.paper.util.getPrefixedName import dev.slne.surf.core.api.common.event.SurfServerOnlineEvent import dev.slne.surf.core.api.common.event.SurfServerStoppingEvent import dev.slne.surf.core.api.common.server.SurfServer @@ -13,6 +15,7 @@ import dev.slne.surf.core.paper.command.* import dev.slne.surf.core.paper.event.SurfServerEventListener import dev.slne.surf.core.paper.listener.PlayerConnectListener import dev.slne.surf.core.paper.task.surfServerInformationSyncTask +import net.luckperms.api.event.user.UserDataRecalculateEvent import org.bukkit.Bukkit import org.bukkit.plugin.java.JavaPlugin @@ -47,6 +50,9 @@ class PaperMain : SuspendingJavaPlugin() { SurfServer.current().copy(maxPlayers = Bukkit.getMaxPlayers()) ) + + luckPerms() + surfServerInformationSyncTask.start() } @@ -58,4 +64,16 @@ class PaperMain : SuspendingJavaPlugin() { ClientCoreInstance.clientLoader.onDisable() } + + + private fun luckPerms() { + LuckPermsAccess.luckperms.eventBus.subscribe( + plugin, + UserDataRecalculateEvent::class.java + ) { event -> + Bukkit.getPlayer(event.user.uniqueId)?.let { + it.displayName(it.getPrefixedName()) + } + } + } } \ No newline at end of file diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/api/DefaultCorePlayerInfoProvider.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/api/DefaultCorePlayerInfoProvider.kt new file mode 100644 index 0000000..a313ebf --- /dev/null +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/api/DefaultCorePlayerInfoProvider.kt @@ -0,0 +1,23 @@ +package dev.slne.surf.core.paper.api + +import dev.slne.surf.core.api.common.server.SurfServer +import dev.slne.surf.core.api.paper.CorePlayerInfoProvider +import org.bukkit.Bukkit +import org.bukkit.World +import java.util.* + +object DefaultCorePlayerInfoProvider : CorePlayerInfoProvider { + override fun createServerInfo(playerUuid: UUID): CorePlayerInfoProvider.ServerInfo? { + val player = Bukkit.getPlayer(playerUuid) ?: return null + + return CorePlayerInfoProvider.ServerInfo( + serverName = SurfServer.current().name, + serverDisplayName = SurfServer.current().displayName, + serverRegion = when (player.world.environment) { + World.Environment.NETHER -> "Nether" + World.Environment.THE_END -> "End" + else -> "Overworld" + } + ) + } +} \ No newline at end of file diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/NetworkBroadcastCommand.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/NetworkBroadcastCommand.kt index fe16b5a..91c1387 100644 --- a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/NetworkBroadcastCommand.kt +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/NetworkBroadcastCommand.kt @@ -8,7 +8,9 @@ import dev.slne.surf.api.core.messages.adventure.sendText import dev.slne.surf.core.api.common.SurfCoreApi import dev.slne.surf.core.api.common.util.sendText import dev.slne.surf.core.core.common.util.appendCorePrefix +import dev.slne.surf.core.core.common.util.niceRed import dev.slne.surf.core.paper.permission.PermissionRegistry +import net.kyori.adventure.text.format.TextDecoration import net.kyori.adventure.text.minimessage.MiniMessage fun networkBroadcastCommand() = commandTree("nbroadcast") { @@ -20,7 +22,14 @@ fun networkBroadcastCommand() = commandTree("nbroadcast") { SurfCoreApi.getOnlinePlayers().forEach { it.sendText { appendCorePrefix() + + appendNewline() + appendCorePrefix() + niceRed("INFO: ", TextDecoration.BOLD) append(MiniMessage.miniMessage().deserialize(message)) + + appendNewline() + appendCorePrefix() } } diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/SurfCoreCommand.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/SurfCoreCommand.kt index 81eafcf..76a757e 100644 --- a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/SurfCoreCommand.kt +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/command/SurfCoreCommand.kt @@ -17,7 +17,7 @@ import dev.slne.surf.core.paper.PaperBootstrap import dev.slne.surf.core.paper.permission.PermissionRegistry import dev.slne.surf.core.paper.plugin -fun surfCoreCommand() = commandTree("core") { +fun surfCoreCommand() = commandTree("surfcore") { withPermission(PermissionRegistry.COMMAND_CORE) literalArgument("reload") { anyExecutor { executor, _ -> diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperRemoteCommandListener.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperRemoteCommandListener.kt new file mode 100644 index 0000000..8792beb --- /dev/null +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperRemoteCommandListener.kt @@ -0,0 +1,26 @@ +package dev.slne.surf.core.paper.listener + +import com.github.shynixn.mccoroutine.folia.globalRegionDispatcher +import com.google.auto.service.AutoService +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.api.common.server.SurfServer +import dev.slne.surf.core.core.common.redis.listener.RemoteCommandExecutor +import dev.slne.surf.core.paper.plugin +import kotlinx.coroutines.withContext +import org.bukkit.Bukkit + +@AutoService(RemoteCommandExecutor::class) +class PaperRemoteCommandListener : RemoteCommandExecutor { + override suspend fun executeCommand( + commonSurfServer: CommonSurfServer, + command: String + ): Boolean? { + if (commonSurfServer.uuid != SurfServer.current().uuid) { + return null + } + + return withContext(plugin.globalRegionDispatcher) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command) + } + } +} \ No newline at end of file diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperShutdownHandler.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperShutdownHandler.kt new file mode 100644 index 0000000..3e1f9b2 --- /dev/null +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PaperShutdownHandler.kt @@ -0,0 +1,48 @@ +package dev.slne.surf.core.paper.listener + +import com.google.auto.service.AutoService +import dev.slne.surf.api.core.messages.adventure.appendNewline +import dev.slne.surf.api.core.messages.adventure.buildText +import dev.slne.surf.api.paper.util.forEachPlayer +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.api.common.server.SurfServer +import dev.slne.surf.core.core.common.redis.listener.ServerShutdownHandler +import net.kyori.adventure.text.Component +import org.bukkit.Bukkit + +@AutoService(ServerShutdownHandler::class) +class PaperShutdownHandler : ServerShutdownHandler { + override fun shutdown(commonSurfServer: CommonSurfServer, reason: Component?): Boolean? { + if (commonSurfServer.uuid != SurfServer.current().uuid) { + return null + } + + val msg = buildDisconnectComponent(reason) + + forEachPlayer { player -> + player.kick(msg) + } + + Bukkit.shutdown() + return true + } + + + private fun buildDisconnectComponent(reason: Component?) = buildText { + appendNewline(2) + primary("CASTCRAFTER") + appendNewline() + primary("COMMUNITY SERVER") + appendNewline(2) + error("DER SERVER WIRD HERUNTERGEFAHREN.") + appendNewline(3) + spacer("Der Server wurde gestoppt. Bitte versuche es später erneut.") + reason?.let { + appendNewline() + spacer("Grund: ") + append(reason) + } + appendNewline(2) + primary("discord.gg/castcrafter") + } +} \ No newline at end of file diff --git a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PlayerConnectListener.kt b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PlayerConnectListener.kt index e0b9be5..5d8fb3a 100644 --- a/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PlayerConnectListener.kt +++ b/surf-core-paper/src/main/kotlin/dev/slne/surf/core/paper/listener/PlayerConnectListener.kt @@ -4,6 +4,7 @@ import com.github.shynixn.mccoroutine.folia.launch import com.github.shynixn.mccoroutine.folia.scope import dev.slne.surf.api.core.messages.adventure.* import dev.slne.surf.api.paper.command.util.idOrThrow +import dev.slne.surf.api.paper.util.getPrefixedName import dev.slne.surf.core.api.common.server.connection.SurfProxyServerConnectionResult import dev.slne.surf.core.api.paper.util.surfPlayer import dev.slne.surf.core.core.CoreInstance @@ -128,6 +129,11 @@ object PlayerConnectListener : Listener { } } + @EventHandler + fun onJoin(event: PlayerJoinEvent) { + event.player.displayName(event.player.getPrefixedName()) + } + private fun buildDisconnectComponent(errorCode: String) = buildText { appendNewline(2) primary("CASTCRAFTER") diff --git a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/VelocityMain.kt b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/VelocityMain.kt index a46e33f..db21f71 100644 --- a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/VelocityMain.kt +++ b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/VelocityMain.kt @@ -27,6 +27,7 @@ import dev.slne.surf.core.core.common.util.appendCorePrefix import dev.slne.surf.core.core.common.util.niceRed import dev.slne.surf.core.velocity.auth.AuthenticationListener import dev.slne.surf.core.velocity.auth.AuthenticationService +import dev.slne.surf.core.velocity.command.coreCommand import dev.slne.surf.core.velocity.config.VelocityCoreConfigManager import dev.slne.surf.core.velocity.listener.ConnectionListener import dev.slne.surf.core.velocity.listener.VelocityServerListener @@ -99,6 +100,8 @@ class VelocityMain @Inject constructor( SurfServerService.changeState(SurfProxyServer.current(), SurfServerState.RUNNING) + coreCommand() + surfPlayerSyncTask.start() } diff --git a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/command/CoreCommand.kt b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/command/CoreCommand.kt new file mode 100644 index 0000000..f6c1fa6 --- /dev/null +++ b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/command/CoreCommand.kt @@ -0,0 +1,493 @@ +package dev.slne.surf.core.velocity.command + +import com.github.shynixn.mccoroutine.velocity.launch +import com.velocitypowered.api.proxy.ConsoleCommandSource +import dev.jorel.commandapi.kotlindsl.* +import dev.slne.surf.api.core.messages.CommonComponents +import dev.slne.surf.api.core.messages.adventure.buildText +import dev.slne.surf.api.core.messages.adventure.clickRunsCommand +import dev.slne.surf.api.core.messages.adventure.sendText +import dev.slne.surf.api.core.minimessage.miniMessage +import dev.slne.surf.api.core.util.dateTimeFormatter +import dev.slne.surf.api.velocity.command.executors.anyExecutorSuspend +import dev.slne.surf.api.velocity.command.executors.playerExecutorSuspend +import dev.slne.surf.core.api.common.player.SurfPlayer +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.api.common.util.sendText +import dev.slne.surf.core.api.velocity.command.argument.surfPlayerArgument +import dev.slne.surf.core.api.velocity.command.argument.surfServerArgument +import dev.slne.surf.core.core.common.player.SurfPlayerService +import dev.slne.surf.core.core.common.server.SurfServerService +import dev.slne.surf.core.core.common.util.appendCorePrefix +import dev.slne.surf.core.core.common.util.niceRed +import dev.slne.surf.core.velocity.permission.PermissionList +import dev.slne.surf.core.velocity.plugin +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.event.ClickEvent +import net.kyori.adventure.text.format.TextDecoration +import java.time.Duration +import java.time.OffsetDateTime +import kotlin.jvm.optionals.getOrElse +import kotlin.time.toKotlinDuration + +fun coreCommand() = commandTree("core") { + withPermission(PermissionList.CORE_COMMAND) + + anyExecutor { source, _ -> + val coreVersion = plugin.pluginContainer.description.version.getOrElse { "#Unknown" } + val platform = plugin.proxy.version.name + val platformVersion = plugin.proxy.version.version + val vendor = plugin.proxy.version.vendor + + source.sendText { + appendCorePrefix() + info("This proxy is running ") + variableValue("surf-core-velocity") + info(" version ") + variableValue(coreVersion) + info(" on ") + variableValue(platform) + appendSpace() + variableValue(platformVersion) + info(" by ") + variableValue(vendor) + info(".") + } + } + + literalArgument("player") { + withPermission(PermissionList.CORE_COMMAND_PLAYER) + + literalArgument("#list") { + anyExecutor { source, _ -> + if (SurfPlayerService.players.isEmpty()) { + source.sendText { + appendCorePrefix() + error("Derzeit sind keine Spieler auf dem Netzwerk online.") + } + return@anyExecutor + } + + source.sendText { + appendCorePrefix() + info("Derzeit sind ") + variableValue(SurfPlayerService.players.size) + info(" Spieler auf dem Netzwerk online: ") + appendCollection(SurfPlayerService.players) { player -> + buildText { + variableValue(player.username) + clickRunsCommand("/core player ${player.username} info") + hoverEvent(buildText { + info("Online auf ") + variableValue("${player.currentServer?.name ?: "Unbekannt"} (${player.currentProxy?.name ?: "Unbekannt"})") + }) + } + } + } + } + } + + surfPlayerArgument("target") { + literalArgument("find") { + anyExecutor { source, arguments -> + val target: SurfPlayer by arguments + + source.sendText { + appendCorePrefix() + info("Der Spieler ") + variableValue(target.username) + info(" ist derzeit online auf ") + variableValue("${target.currentServer?.name ?: "Unbekannt"} (${target.currentProxy?.name ?: "Unbekannt"})") + info(". ") + + append { + spacer("[TP]") + clickRunsCommand("/ntp ${target.username}") + hoverEvent(buildText { + info("Teleportiere dich zu ${target.username}") + }) + } + } + } + } + + literalArgument("info") { + anyExecutor { source, arguments -> + val target: SurfPlayer by arguments + + source.sendText { + appendCorePrefix() + spacer("*") + spacer("-".repeat((30 - target.username.length) / 2)) + variableValue(target.username) + spacer("-".repeat((30 - target.username.length) / 2)) + spacer("*") + + appendNewline() + appendCorePrefix() + + appendNewline() + appendCorePrefix() + info("UUID: ") + variableValue(target.uuid.toString()) + + appendNewline() + appendCorePrefix() + info("Letzter Name: ") + variableValue(target.lastKnownName ?: "Unbekannt") + + appendNewline() + appendCorePrefix() + info("Aktueller Server: ") + variableValue(target.currentServer?.name ?: "Unbekannt") + + appendNewline() + appendCorePrefix() + info("Aktueller Proxy: ") + variableValue(target.currentProxy?.name ?: "Unbekannt") + + appendNewline() + appendCorePrefix() + info("Erstmals gesehen: ") + variableValue(target.firstSeen?.let { + dateTimeFormatter.format(it).toString() + } ?: "Unbekannt") + + appendNewline() + appendCorePrefix() + info("Verbindung transferiert: ") + variableValue(target.transferred) + + appendNewline() + appendCorePrefix() + info("Ip Adresse: ") + variableValue(target.lastKnownIpAddress?.toString() ?: "Unbekannt") + + appendNewline() + appendCorePrefix() + + appendNewline() + appendCorePrefix() + spacer("*") + spacer("-".repeat(30)) + spacer("*") + } + } + } + + literalArgument("notify") { + textArgument("message") { + multiLiteralArgument( + "prefix", + "--moderation", + "--system", + "--warn", + optional = true + ) { + anyExecutor { source, arguments -> + val target: SurfPlayer by arguments + val message: String by arguments + val prefix: String? by arguments + + target.sendText { + appendCorePrefix() + append(findPrefix(prefix)) + append(miniMessage.deserialize(message)) + } + + source.sendText { + appendCorePrefix() + info("Die Nachricht wurde gesendet.") + } + } + } + } + } + } + } + + literalArgument("service") { + withPermission(PermissionList.CORE_COMMAND_SERVICE) + + literalArgument("#list") { + anyExecutor { source, _ -> + val services = SurfServerService.servers + + if (services.isEmpty()) { + source.sendText { + appendCorePrefix() + error("Derzeit sind keine Server auf dem Netzwerk online.") + } + return@anyExecutor + } + + source.sendText { + appendCorePrefix() + info("Derzeit sind ") + variableValue(services.size) + info(" Server aktiv: ") + appendCollection(services) { service -> + buildText { + variableValue(service.displayName) + clickRunsCommand("/core service ${service.name} info") + hoverEvent(buildText { + info("ID: ") + variableValue(service.uuid.toString()) + appendNewline() + info("Spieler: ") + variableValue("${service.getPlayerCount()}/${service.maxPlayers}") + }) + } + } + } + } + } + + + surfServerArgument("service") { + literalArgument("shutdown") { + textArgument("reason", optional = true) { + anyExecutorSuspend { source, arguments -> + val service: CommonSurfServer by arguments + val reason: String? by arguments + + if (source is ConsoleCommandSource || service.getPlayerCount() <= 5) { + source.sendText { + appendInfoPrefix() + info("Der Server ") + variableValue(service.name) + info(" wird heruntergefahren...") + } + + val result = + SurfServerService.shutdown( + service, + reason?.let { miniMessage.deserialize(it) }) + + if (result) { + source.sendText { + appendCorePrefix() + success("Der Server ") + variableValue(service.name) + success(" wurde erfolgreich heruntergefahren.") + } + } else { + source.sendText { + appendCorePrefix() + error("Der Server ") + variableValue(service.name) + error(" konnte nicht heruntergefahren werden.") + } + } + + return@anyExecutorSuspend + } + + source.sendText { + appendInfoPrefix() + info("Möchtest du wirklich den Server ") + variableValue(service.name) + info(" herunterfahren? Es sind derzeit ") + variableValue(service.getPlayerCount()) + info(" Spieler online! ") + append { + spacer("[") + success("Bestätigen") + spacer("]") + clickEvent(ClickEvent.callback { + plugin.pluginContainer.launch { + source.sendText { + appendInfoPrefix() + info("Der Server ") + variableValue(service.name) + info(" wird heruntergefahren...") + } + + val result = + SurfServerService.shutdown( + service, + reason?.let { miniMessage.deserialize(it) }) + + if (result) { + source.sendText { + appendCorePrefix() + success("Der Server ") + variableValue(service.name) + success(" wurde erfolgreich heruntergefahren.") + } + } else { + source.sendText { + appendCorePrefix() + error("Der Server ") + variableValue(service.name) + error(" konnte nicht heruntergefahren werden.") + } + } + } + }) + } + } + } + } + } + + literalArgument("info") { + anyExecutor { source, arguments -> + val service: CommonSurfServer by arguments + + source.sendText { + appendCorePrefix() + spacer("*") + spacer("-".repeat((30 - service.name.length) / 2)) + variableValue(service.name) + spacer("-".repeat((30 - service.name.length) / 2)) + spacer("*") + + appendNewline() + appendCorePrefix() + + appendNewline() + appendCorePrefix() + info("ID: ") + variableValue(service.uuid.toString()) + + appendNewline() + appendCorePrefix() + info("Interner Name: ") + variableValue(service.name) + + appendNewline() + appendCorePrefix() + info("Anzeigename: ") + variableValue(service.displayName) + + appendNewline() + appendCorePrefix() + info("Serverkategorie: ") + variableValue(service.category) + + appendNewline() + appendCorePrefix() + info("Servertyp: ") + variableValue(if (service.isProxy()) "Proxy" else "Backend") + + appendNewline() + appendCorePrefix() + info("Status: ") + variableValue(service.state.toString()) + + appendNewline() + appendCorePrefix() + info("Spieler: ") + variableValue("${service.getPlayerCount()}/${service.maxPlayers}") + + appendNewline() + appendCorePrefix() + info("Uptime: ") + append( + CommonComponents.formatTime( + Duration.between( + service.startedAt, + OffsetDateTime.now() + ).toKotlinDuration(), + showSeconds = true, + shortForms = false + ) + ) + + appendNewline() + appendCorePrefix() + + appendNewline() + appendCorePrefix() + spacer("*") + spacer("-".repeat(30)) + spacer("*") + } + } + } + + + literalArgument("sudo") { + textArgument("command") { + playerExecutorSuspend { player, arguments -> + val service: CommonSurfServer by arguments + val command: String by arguments + + if (blockedCommands.any { command.startsWith(it, ignoreCase = true) }) { + player.sendText { + appendCorePrefix() + error("Du darfst diesen Befehl nicht auf dem Server ") + variableValue(service.name) + error(" ausführen.") + } + return@playerExecutorSuspend + } + + val result = SurfServerService.executeCommand(service, command) + + if (result) { + player.sendText { + appendCorePrefix() + success("Der Befehl wurde erfolgreich auf dem Server ") + variableValue(service.name) + success(" ausgeführt.") + } + } else { + player.sendText { + appendCorePrefix() + error("Der Befehl konnte nicht auf dem Server ") + variableValue(service.name) + error(" ausgeführt werden.") + } + } + } + } + } + } + } +} + +private val blockedCommands = + listOf("lp", "lpv", "luckperms", "perm", "permission", "permissions", "luckpermsvelocity") + +private fun findPrefix(prefix: String?) = buildText { + when (prefix) { + "--moderation" -> { + spacer("[") + error("MODERATION") + spacer("]") + appendSpace() + } + + "--system" -> { + spacer("[") + variableValue("SYSTEM") + spacer("]") + appendSpace() + } + + "--warn" -> { + spacer("[") + niceRed("WARNUNG", TextDecoration.BOLD) + spacer("]") + appendSpace() + } + + else -> Component.empty() + } +} + +private fun formatDuration(duration: Duration): String { + val seconds = duration.seconds % 60 + val minutes = (duration.toMinutes() % 60) + val hours = (duration.toHours() % 24) + val days = duration.toDays() + + return buildString { + if (days > 0) append("${days}d ") + if (hours > 0) append("${hours}h ") + if (minutes > 0) append("${minutes}m ") + append("${seconds}s") + }.trim() +} \ No newline at end of file diff --git a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityRemoteCommandListener.kt b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityRemoteCommandListener.kt new file mode 100644 index 0000000..3292bd2 --- /dev/null +++ b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityRemoteCommandListener.kt @@ -0,0 +1,23 @@ +package dev.slne.surf.core.velocity.listener + +import com.google.auto.service.AutoService +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.api.common.server.SurfProxyServer +import dev.slne.surf.core.core.common.redis.listener.RemoteCommandExecutor +import dev.slne.surf.core.velocity.plugin +import dev.slne.surf.core.velocity.proxy +import kotlinx.coroutines.future.await + +@AutoService(RemoteCommandExecutor::class) +class VelocityRemoteCommandListener : RemoteCommandExecutor { + override suspend fun executeCommand( + commonSurfServer: CommonSurfServer, + command: String + ): Boolean? { + if (commonSurfServer.uuid != SurfProxyServer.current().uuid) { + return null + } + + return plugin.proxy.commandManager.executeAsync(proxy.consoleCommandSource, command).await() + } +} \ No newline at end of file diff --git a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityShutdownHandler.kt b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityShutdownHandler.kt new file mode 100644 index 0000000..042ef8a --- /dev/null +++ b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/listener/VelocityShutdownHandler.kt @@ -0,0 +1,30 @@ +package dev.slne.surf.core.velocity.listener + +import com.google.auto.service.AutoService +import dev.slne.surf.core.api.common.server.CommonSurfServer +import dev.slne.surf.core.api.common.server.SurfProxyServer +import dev.slne.surf.core.core.common.redis.listener.ServerShutdownHandler +import dev.slne.surf.core.velocity.plugin +import net.kyori.adventure.text.Component + +@AutoService(ServerShutdownHandler::class) +class VelocityShutdownHandler : ServerShutdownHandler { + override fun shutdown(commonSurfServer: CommonSurfServer, reason: Component?): Boolean? { + if (commonSurfServer.uuid != SurfProxyServer.current().uuid) { + return null + } + + val shutdownThread = Thread { + try { + Thread.sleep(100) + } catch (_: InterruptedException) { + Thread.currentThread().interrupt() + } + + plugin.proxy.shutdown(reason) + } + shutdownThread.isDaemon = false + shutdownThread.start() + return true + } +} \ No newline at end of file diff --git a/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/permission/PermissionList.kt b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/permission/PermissionList.kt new file mode 100644 index 0000000..591e73f --- /dev/null +++ b/surf-core-velocity/src/main/kotlin/dev/slne/surf/core/velocity/permission/PermissionList.kt @@ -0,0 +1,11 @@ +package dev.slne.surf.core.velocity.permission + +object PermissionList { + private const val BASE = "surf.core" + + const val CORE_COMMAND = "$BASE.command" + + const val CORE_COMMAND_PLAYER = "$CORE_COMMAND.player" + + const val CORE_COMMAND_SERVICE = "$CORE_COMMAND.service" +} \ No newline at end of file