Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ import app.simplecloud.plugin.proxy.shared.handler.command.CommandSender
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer
import net.md_5.bungee.api.chat.BaseComponent
import net.md_5.bungee.api.connection.ProxiedPlayer

class BungeeCordCommandSender(private val commandSender: net.md_5.bungee.api.CommandSender
class BungeeCordCommandSender(
private val commandSender: net.md_5.bungee.api.CommandSender,
private val plugin: ProxyBungeeCordPlugin
) : CommandSender {

fun getCommandSender(): net.md_5.bungee.api.CommandSender {
return commandSender
}

override fun sendMessage(message: String) {
commandSender.sendMessage(message)
val player = commandSender as? ProxiedPlayer
val component = plugin.deserializeToComponent(message, player)
plugin.adventure().sender(commandSender).sendMessage(component)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class ProxyBungeeCordPlugin: Plugin() {
val executionCoordinator = ExecutionCoordinator.simpleCoordinator<CommandSender>()

val senderMapper = SenderMapper.create<net.md_5.bungee.api.CommandSender, CommandSender>(
{ commandSender -> BungeeCordCommandSender(commandSender) },
{ commandSender -> BungeeCordCommandSender(commandSender, this) },
{ cloudSender -> (cloudSender as BungeeCordCommandSender).getCommandSender() }
)

Expand Down
2 changes: 1 addition & 1 deletion proxy-shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ dependencies {
implementation(rootProject.libs.configurate.yaml)
implementation(rootProject.libs.configurate.kotlin)

compileOnly(rootProject.libs.simplecloud.controller)
implementation(rootProject.libs.simplecloud.controller)

compileOnly(rootProject.libs.command.cloud.core)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,24 @@ open class ProxyPlugin(
) {

val config = YamlConfig(dirPath)
val tabListConfiguration = config.load<TabListConfiguration>("tablist")!!
val placeHolderConfiguration = config.load<PlaceHolderConfiguration>("placeholder")!!
val messagesConfiguration = config.load<MessageConfig>("messages")!!
val joinStateConfiguration = config.load<JoinStateConfiguration>("joinstate")!!

val tabListConfiguration = loadOrCreate("tablist", TabListConfiguration())
val placeHolderConfiguration = loadOrCreate("placeholder", PlaceHolderConfiguration())
val messagesConfiguration = loadOrCreate("messages", MessageConfig())
val joinStateConfiguration = loadOrCreate("joinstate", JoinStateConfiguration())

val motdLayoutHandler = MotdLayoutHandler(config, this)
val joinStateHandler = JoinStateHandler(this)
val cloudControllerHandler = CloudControllerHandler(joinStateHandler)

private inline fun <reified T : Any> loadOrCreate(path: String, defaultValue: T): T {
val loaded = config.load<T>(path)
if (loaded != null) {
return loaded
}

config.save(path, defaultValue)
return defaultValue
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,36 @@ class CloudControllerHandler(
private val joinStateHandler: JoinStateHandler
) {

private val controllerApi = ControllerApi.createCoroutineApi()
private val logger = Logger.getLogger(CloudControllerHandler::class.java.name)
private val controllerApi = createControllerApiOrNull()

var groupName: String? = null
var numericalId: Int? = null

fun isControllerAvailable(): Boolean {
return controllerApi != null
}

init {
initializeGroupName()
}

private fun createControllerApiOrNull(): ControllerApi.Coroutine? {
return try {
ControllerApi.createCoroutineApi()
} catch (e: Throwable) {
logger.warning("ControllerApi is not available: ${e.message}")
null
}
}

private fun initializeGroupName() {
val api = controllerApi
if (api == null) {
logger.warning("Skipping controller initialization because ControllerApi is unavailable.")
return
}

val serviceID = System.getenv("SIMPLECLOUD_UNIQUE_ID")

if (serviceID == null) {
Expand All @@ -28,7 +47,7 @@ class CloudControllerHandler(

CoroutineScope(Dispatchers.IO).launch {
try {
val service = controllerApi.getServers().getServerById(serviceID)
val service = api.getServers().getServerById(serviceID)
groupName = service.group
numericalId = service.numericalId
logger.info("Group name initialized to: $groupName")
Expand All @@ -53,25 +72,28 @@ class CloudControllerHandler(
}*/

suspend fun getGroupProperties(groupName: String, key: String): String {
val api = controllerApi ?: return ""
return groupName.let {
retrievePropertyOrEmpty {
controllerApi.getGroups().getGroupByName(it).properties[key]
api.getGroups().getGroupByName(it).properties[key]
}
}
}

suspend fun getServiceProperties(groupName: String, numericalId: Long, key: String): String {
return controllerApi.getServers().getServerByNumerical(groupName, numericalId).let { server ->
val api = controllerApi ?: return ""
return api.getServers().getServerByNumerical(groupName, numericalId).let { server ->
retrievePropertyOrEmpty {
server.properties[key]
}
}
}

suspend fun setServiceProperties(groupName: String, numericalId: Long, key: String, value: String): Boolean {
controllerApi.getServers().getServerByNumerical(groupName, numericalId).let { server ->
val api = controllerApi ?: return false
api.getServers().getServerByNumerical(groupName, numericalId).let { server ->
try {
controllerApi.getServers().updateServerProperty(server.uniqueId, key, value)
api.getServers().updateServerProperty(server.uniqueId, key, value)
logger.info("Service property '$key' updated to '$value'")
return true
} catch (e: Exception) {
Expand All @@ -82,11 +104,12 @@ class CloudControllerHandler(
}

suspend fun setServicePropertiesOnAllGroupServices(groupName: String, key: String, value: String): Boolean {
val api = controllerApi ?: return false
groupName.let { name ->
try {
controllerApi.getServers().getServersByGroup(name).forEach { server ->
api.getServers().getServersByGroup(name).forEach { server ->
logger.info("Updating service property '$key' to '$value' on service ${server.group} ${server.numericalId} ${server.uniqueId}")
controllerApi.getServers().updateServerProperty(server.uniqueId, key, value)
api.getServers().updateServerProperty(server.uniqueId, key, value)
}
logger.info("Service property '$key' updated to '$value' on all services in group '$name'")
return true
Expand All @@ -98,11 +121,12 @@ class CloudControllerHandler(
}

suspend fun setGroupProperties(groupName: String, key: String, value: String): Boolean {
val api = controllerApi ?: return false
groupName.let { name ->
try {
val group = controllerApi.getGroups().getGroupByName(name)
val group = api.getGroups().getGroupByName(name)
val updatedGroup = group.copy(properties = group.properties + (key to value))
controllerApi.getGroups().updateGroup(updatedGroup)
api.getGroups().updateGroup(updatedGroup)
logger.info("Group property '$key' updated to '$value'")
return true
} catch (e: Exception) {
Expand All @@ -113,9 +137,10 @@ class CloudControllerHandler(
}

suspend fun getOnlinePlayersInGroup(groupName: String): Int {
val api = controllerApi ?: return 0
return groupName.let { name ->
try {
controllerApi.getServers().getServersByGroup(name).sumOf { it.playerCount.toInt() }
api.getServers().getServersByGroup(name).sumOf { it.playerCount.toInt() }
} catch (e: Exception) {
logger.severe("Error retrieving online players in group: ${e.message}")
0
Expand All @@ -125,9 +150,10 @@ class CloudControllerHandler(
}

suspend fun getMaxPlayersInGroup(groupName: String): Int {
val api = controllerApi ?: return 0
return groupName.let {
try {
controllerApi.getGroups().getGroupByName(it).maxPlayers.toInt()
api.getGroups().getGroupByName(it).maxPlayers.toInt()
} catch (e: Exception) {
logger.severe("Error retrieving max players in group: ${e.message}")
0
Expand All @@ -136,11 +162,13 @@ class CloudControllerHandler(
}

suspend fun getAllGroups(): List<String> {
return controllerApi.getGroups().getAllGroups().map { it.name }
val api = controllerApi ?: return emptyList()
return api.getGroups().getAllGroups().map { it.name }
}

suspend fun getAllNumericalIdsFromGroup(groupName: String): List<Int> {
return controllerApi.getServers().getServersByGroup(groupName).map { it.numericalId }
val api = controllerApi ?: return emptyList()
return api.getServers().getServersByGroup(groupName).map { it.numericalId }
}

private suspend fun retrievePropertyOrEmpty(retrieve: suspend () -> String?): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class JoinStateHandler(
* @param joinStateName The name of the join state.
*/
suspend fun setJoinStateAtGroup(groupName: String, joinStateName: String) {
if (!this.proxyPlugin.cloudControllerHandler.isControllerAvailable()) {
this.localState = joinStateName
return
}

this.proxyPlugin.cloudControllerHandler.setGroupProperties(groupName, JOINSTATE_KEY, joinStateName)
}

Expand All @@ -33,13 +38,16 @@ class JoinStateHandler(
* @return The name of the join state.
*/
suspend fun getJoinStateAtGroup(groupName: String): String {
if (!this.proxyPlugin.cloudControllerHandler.isControllerAvailable()) {
return this.localState
}

val groupProperties = this.proxyPlugin.cloudControllerHandler.getGroupProperties(groupName, JOINSTATE_KEY)

if (groupProperties.isEmpty()) {
logger.warning("No join state found for group $groupName. Using default join state.")
setJoinStateAtGroup(groupName, this.proxyPlugin.joinStateConfiguration.defaultState)

return getJoinStateAtGroup(groupName)
return this.proxyPlugin.joinStateConfiguration.defaultState
}

return groupProperties
Expand All @@ -55,6 +63,11 @@ class JoinStateHandler(
* @return True if the join state was set successfully, false otherwise.
*/
suspend fun setJoinStateAtService(groupName: String, numericalId: Long, joinStateName: String): Boolean {
if (!this.proxyPlugin.cloudControllerHandler.isControllerAvailable()) {
this.localState = joinStateName
return true
}

return this.proxyPlugin.cloudControllerHandler.setServiceProperties(groupName, numericalId, JOINSTATE_KEY, joinStateName)
}

Expand All @@ -67,6 +80,12 @@ class JoinStateHandler(
* @return True if the join state was set successfully, false otherwise.
*/
suspend fun setJoinStateAtGroupAndAllServicesInGroup(groupName: String, joinStateName: String): Boolean {
if (!this.proxyPlugin.cloudControllerHandler.isControllerAvailable()) {
this.localState = joinStateName
logger.warning("Controller API unavailable. Updated local join state only.")
return true
}

val groupProperties =
this.proxyPlugin.cloudControllerHandler.setGroupProperties(groupName, JOINSTATE_KEY, joinStateName)
val servicePropertiesOnAllGroupServices =
Expand All @@ -92,13 +111,16 @@ class JoinStateHandler(
* @return The name of the join state.
*/
suspend fun getJoinStateAtService(groupName: String, numericalId: Long): String {
if (!this.proxyPlugin.cloudControllerHandler.isControllerAvailable()) {
return this.localState
}

val serviceProperties = this.proxyPlugin.cloudControllerHandler.getServiceProperties(groupName, numericalId, JOINSTATE_KEY)

if (serviceProperties.isEmpty()) {
logger.warning("No join state found for service $numericalId in group $groupName. Using default join state.")
setJoinStateAtService(groupName, numericalId, this.proxyPlugin.joinStateConfiguration.defaultState)

return getJoinStateAtService(groupName, numericalId)
return this.proxyPlugin.joinStateConfiguration.defaultState
}

return serviceProperties
Expand Down
5 changes: 4 additions & 1 deletion proxy-velocity/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ dependencies {
compileOnly(rootProject.libs.velocity)
annotationProcessor(rootProject.libs.velocity)

compileOnly(rootProject.libs.simplecloud.event.wrapper.velocity)
implementation(rootProject.libs.simplecloud.event.wrapper.velocity)
compileOnly(rootProject.libs.simplecloud.controller)

implementation(rootProject.libs.simplecloud.plugin.api)
Expand All @@ -22,6 +22,9 @@ dependencies {
}

tasks.shadowJar {
from(sourceSets.main.get().resources)
configurations = listOf(project.configurations.runtimeClasspath.get())

relocate("org.incendo", "app.simplecloud.relocate.incendo")
relocate("org.spongepowered", "app.simplecloud.relocate.spongepowered")
relocate("app.simplecloud.plugin.api", "app.simplecloud.relocate.plugin.api")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ class ServerPreConnectListener(
) {
private val logger = Logger.getLogger(ServerPreConnectListener::class.java.name)

private val identifier = ServerPatternIdentifier(
this.proxyPlugin.joinStateConfiguration.serverNamePattern
)
private val identifier = createServerPatternIdentifier()

private fun createServerPatternIdentifier(): ServerPatternIdentifier? {
return try {
ServerPatternIdentifier(this.proxyPlugin.joinStateConfiguration.serverNamePattern)
} catch (e: Throwable) {
logger.warning("ServerPatternIdentifier is unavailable. Server switch checks are disabled: ${e.message}")
null
}
}

@Subscribe(order = PostOrder.EARLY)
fun handle(event: ServerPreConnectEvent) {
Expand Down Expand Up @@ -68,8 +75,13 @@ class ServerPreConnectListener(

private fun checkAllowServerSwitch(player: Player, event: ServerPreConnectEvent, server: RegisteredServer) {
val serverName = server.serverInfo.name
val parser = identifier

if (parser == null) {
return
}

val (groupName, numericalId) = identifier.parse(serverName)
val (groupName, numericalId) = parser.parse(serverName)

runBlocking {
val joinStateName =
Expand Down Expand Up @@ -99,8 +111,8 @@ class ServerPreConnectListener(
val groupName = this.proxyPlugin.cloudControllerHandler.groupName

if (groupName == null) {
logger.warning("No group name found for server.")
return true
logger.warning("No group name found for server. Skipping network-full check.")
return false
}

val maxPlayers = proxyPlugin.cloudControllerHandler.getMaxPlayersInGroup(groupName)
Expand Down