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 @@ -17,8 +17,9 @@ class ConfigureTagResolversListener(
val serverName = player?.server?.info?.name ?: "unknown"
val ping = player?.ping ?: -1
val pingColors = plugin.proxyPlugin.placeHolderConfiguration.get().pingColors
val onlinePlayers = plugin.proxy.players.size
val realMaxPlayers = plugin.proxy.config.playerLimit
val playerCountHandler = plugin.proxyPlugin.playerCountHandler
val onlinePlayers = playerCountHandler.onlinePlayersOr(plugin.proxy.players.size)
val realMaxPlayers = playerCountHandler.maxPlayersOr(plugin.proxy.config.playerLimit)

event.withTagResolvers(
TagResolverHelper.getDefaultTagResolvers(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,17 @@ class ProxyPingListener(
}

// slots
val onlinePlayers = response.players.online
val playerCountHandler = plugin.proxyPlugin.playerCountHandler
val onlinePlayers = playerCountHandler.onlinePlayersOr(response.players.online)
val realMax = playerCountHandler.maxPlayersOr(response.players.max)
val maxPlayers = if (layout.versionSettings.slots.enabled) {
when (layout.versionSettings.slots.type) {
MaxPlayerDisplayType.REAL -> response.players.max
MaxPlayerDisplayType.REAL -> realMax
MaxPlayerDisplayType.FAKE -> layout.versionSettings.slots.fakeSlots
MaxPlayerDisplayType.DYNAMIC -> onlinePlayers + layout.versionSettings.slots.dynamicPlayerRange
}
} else {
response.players.max
realMax
}

response.players = Players(maxPlayers, onlinePlayers, samplePlayers)
Expand Down
17 changes: 17 additions & 0 deletions proxy-bungeecord/src/main/resources/config/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ whitelist:
players:
- Notch

# ───────────────────────────────────────────────────────────────────────────────
# Player Count
# Displays the summed player count for this proxy group and optional extra targets.
#
# Read more @ https://docs.simplecloud.app/manual/plugins/proxy-essentials
# ───────────────────────────────────────────────────────────────────────────────

player-count:
# Enables summed player counts for the server list and placeholders.
enabled: true
# Additional SimpleCloud groups included in the displayed player count.
additional-groups: []
# Persistent servers included in the displayed player count.
additional-persistent-servers: []
# Player count update interval in ticks. Set to 0 to disable automatic updates.
update-time: 20

# ───────────────────────────────────────────────────────────────────────────────
# Tablist
# Configures tablist layouts and update intervals for connected players.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import app.simplecloud.plugin.proxy.shared.handler.CloudControllerHandler
import app.simplecloud.plugin.proxy.shared.handler.JoinStateHandler
import app.simplecloud.plugin.proxy.shared.handler.JoinStateResolver
import app.simplecloud.plugin.proxy.shared.handler.MotdLayoutHandler
import app.simplecloud.plugin.proxy.shared.handler.PlayerCountHandler
import app.simplecloud.plugin.proxy.shared.handler.TabListResolver
import java.io.File
import java.nio.file.Path
Expand All @@ -36,10 +37,12 @@ class ProxyPlugin(
val motdLayoutHandler = MotdLayoutHandler(File("$dirPath/layout").toPath(), this)
val joinStateHandler = JoinStateHandler(this)
val cloudControllerHandler = CloudControllerHandler(this, joinStateHandler)
val playerCountHandler = PlayerCountHandler(this).also { it.start() }
val joinStateResolver = JoinStateResolver(this)
val tabListResolver = TabListResolver { proxyEssentialsConfig.get().tablist }

fun shutdown() {
playerCountHandler.stop()
joinStateHandler.stop()
cloudControllerHandler.close()
motdLayoutHandler.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object OldConfigMigrator {
Files.createDirectories(dataDirectory)

migrateMainConfig(dataDirectory)
ensureMainConfigDefaults(dataDirectory.resolve("config.yml"))
migrateMessages(dataDirectory.resolve("messages.yml"))
migratePlaceholder(dataDirectory.resolve("placeholder.yml"))
migrateLayouts(dataDirectory.resolve("layout"))
Expand All @@ -47,6 +48,7 @@ object OldConfigMigrator {

node.node("version").set(CURRENT_CONFIG_VERSION)
migrateJoinStates(joinStateNode, node)
node.node("player-count").set(defaultPlayerCount())
migrateTabList(tabListNode, node)
node.applyMainConfigComments()

Expand All @@ -56,6 +58,29 @@ object OldConfigMigrator {
deleteIfExists(tabListFile)
}

private fun ensureMainConfigDefaults(target: Path) {
if (!Files.exists(target)) return

val loader = createLoader(target)
val node = loader.load()
val playerCountNode = node.node("player-count")
var changed = false

if (playerCountNode.virtual()) {
playerCountNode.set(defaultPlayerCount())
changed = true
} else if (playerCountNode.node("enabled").virtual()) {
playerCountNode.node("enabled").set(ProxyEssentialsConfig().playerCount.enabled)
changed = true
}

if (!changed) return

node.applyMainConfigComments()
loader.save(node)
target.writeCommentedYaml(::decorateMainConfigYaml)
}

private fun CommentedConfigurationNode.containsMigratedMainConfig(
joinStateNode: CommentedConfigurationNode?,
tabListNode: CommentedConfigurationNode?
Expand Down Expand Up @@ -436,6 +461,11 @@ object OldConfigMigrator {
node("initial-state").comment(JOIN_STATES_COMMENT)
node("whitelist").comment(WHITELIST_COMMENT)
node("whitelist", "players").comment("Supports player names and UUIDs.")
node("player-count").comment(PLAYER_COUNT_COMMENT)
node("player-count", "enabled").comment("Enables summed player counts for the server list and placeholders.")
node("player-count", "additional-groups").comment("Additional SimpleCloud groups included in the displayed player count.")
node("player-count", "additional-persistent-servers").comment("Persistent servers included in the displayed player count.")
node("player-count", "update-time").comment("Player count update interval in ticks. Set to 0 to disable automatic updates.")
node("tablist").comment(TABLIST_COMMENT)
node("tablist").childrenList().forEach { group ->
group.node("update-time").comment("Update interval in ticks.")
Expand Down Expand Up @@ -489,6 +519,16 @@ object OldConfigMigrator {
}
}

private fun defaultPlayerCount(): Map<String, Any> {
val playerCount = ProxyEssentialsConfig().playerCount
return mapOf(
"enabled" to playerCount.enabled,
"additional-groups" to playerCount.additionalGroups,
"additional-persistent-servers" to playerCount.additionalPersistentServers,
"update-time" to playerCount.updateTime
)
}

private fun Path.loadYaml(): CommentedConfigurationNode {
return createLoader(this).load()
}
Expand All @@ -506,8 +546,13 @@ object OldConfigMigrator {
.insertBefore("initial-state:", JOIN_STATES_YAML_COMMENT)
.insertBefore("whitelist:", WHITELIST_YAML_COMMENT)
.insertBefore(" players:", " # Supports player names and UUIDs.\n")
.insertBefore("player-count:", PLAYER_COUNT_YAML_COMMENT)
.insertBeforeInSection("player-count:", " enabled:", " # Enables summed player counts for the server list and placeholders.\n")
.insertBeforeInSection("player-count:", " additional-groups:", " # Additional SimpleCloud groups included in the displayed player count.\n")
.insertBeforeInSection("player-count:", " additional-persistent-servers:", " # Persistent servers included in the displayed player count.\n")
.insertBeforeInSection("player-count:", " update-time:", " # Player count update interval in ticks. Set to 0 to disable automatic updates.\n")
.insertBefore("tablist:", TABLIST_YAML_COMMENT)
.insertBefore(" update-time:", " # Update interval in ticks.\n")
.insertBeforeInSection("tablist:", " update-time:", " # Update interval in ticks.\n")
}

private fun decorateLayoutYaml(content: String): String {
Expand Down Expand Up @@ -538,6 +583,22 @@ object OldConfigMigrator {
return lines.joinToString("\n").trimEnd() + "\n"
}

private fun String.insertBeforeInSection(sectionPrefix: String, linePrefix: String, comment: String): String {
if (comment.isEmpty() || contains(comment.trimEnd())) return this
val lines = lines().toMutableList()
val sectionIndex = lines.indexOfFirst { it.startsWith(sectionPrefix) }
if (sectionIndex == -1) return this

val relativeIndex = lines
.drop(sectionIndex + 1)
.indexOfFirst { it.startsWith(linePrefix) }
if (relativeIndex == -1) return this

val commentLines = comment.trimEnd().lines()
lines.addAll(sectionIndex + 1 + relativeIndex, commentLines)
return lines.joinToString("\n").trimEnd() + "\n"
}

private fun createLoader(path: Path): YamlConfigurationLoader {
return YamlConfigurationLoader.builder()
.path(path)
Expand All @@ -563,6 +624,13 @@ object OldConfigMigrator {
"Prefer permission-based access for regular users.\n" +
"Use this list only for administrators or emergency access."

private const val PLAYER_COUNT_COMMENT =
"───────────────────────────────────────────────────────────────────────────────\n" +
"Player Count\n" +
"Displays the summed player count for this proxy group and optional extra targets.\n\n" +
"Read more @ https://docs.simplecloud.app/manual/plugins/proxy-essentials\n" +
"───────────────────────────────────────────────────────────────────────────────"

private const val TABLIST_COMMENT =
"───────────────────────────────────────────────────────────────────────────────\n" +
"Tablist\n" +
Expand Down Expand Up @@ -610,6 +678,14 @@ object OldConfigMigrator {
"# Prefer permission-based access for regular users.\n" +
"# Use this list only for administrators or emergency access.\n"

private const val PLAYER_COUNT_YAML_COMMENT =
"\n# ───────────────────────────────────────────────────────────────────────────────\n" +
"# Player Count\n" +
"# Displays the summed player count for this proxy group and optional extra targets.\n" +
"#\n" +
"# Read more @ https://docs.simplecloud.app/manual/plugins/proxy-essentials\n" +
"# ───────────────────────────────────────────────────────────────────────────────\n"

private const val TABLIST_YAML_COMMENT =
"\n# ───────────────────────────────────────────────────────────────────────────────\n" +
"# Tablist\n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package app.simplecloud.plugin.proxy.shared.config

import org.spongepowered.configurate.objectmapping.ConfigSerializable
import org.spongepowered.configurate.objectmapping.meta.Setting

@ConfigSerializable
data class PlayerCountConfig(
val enabled: Boolean = true,
@Setting("additional-groups") val additionalGroups: List<String> = emptyList(),
@Setting("additional-persistent-servers") val additionalPersistentServers: List<String> = emptyList(),
@Setting("update-time") val updateTime: Long = 20L
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ data class ProxyEssentialsConfig(
)
),
val whitelist: WhitelistConfig = WhitelistConfig(),
@Setting("player-count") val playerCount: PlayerCountConfig = PlayerCountConfig(),
val tablist: List<TabListGroup> = listOf(
TabListGroup(
name = "global",
Expand All @@ -37,4 +38,12 @@ data class ProxyEssentialsConfig(
val ticks = tablist.minOfOrNull { it.updateTime } ?: 20L
return ticks * 50L
}

fun playerCountUpdateTimeMillis(): Long? {
if (!playerCount.enabled || playerCount.updateTime <= 0L) {
return null
}

return playerCount.updateTime * 50L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ class CloudControllerHandler(
null
}

suspend fun getServerById(serverId: String): Server? = try {
plugin.api.server().getServerById(serverId).await()
} catch (e: Exception) {
logger.severe("Error retrieving server by ID '$serverId': ${e.message}")
null
}

suspend fun getServersByGroup(groupName: String): List<Server> = try {
plugin.api.server().getAllServers(
ServerQuery.create()
Expand Down Expand Up @@ -198,4 +205,18 @@ class CloudControllerHandler(
null
}
}

suspend fun getPersistentServersByNames(names: Set<String>): List<Server> {
if (names.isEmpty()) {
return emptyList()
}

return try {
val servers = plugin.api.server().getAllServers(ServerQuery.create()).await() ?: return emptyList()
servers.filter { server -> server.persistentServer?.name?.let { it in names } == true }
} catch (e: Exception) {
logger.severe("Error retrieving persistent servers by name: ${e.message}")
emptyList()
}
}
}
Loading