Skip to content
Merged
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
20 changes: 20 additions & 0 deletions api/src/main/kotlin/gg/grounds/proxy/api/PlayerSessionQuery.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ interface PlayerSessionQuery {
* 10k players online. Implementations clamp [limit] themselves.
*/
fun suggestNames(prefix: String, limit: Int): List<String>

/**
* How many players are on each backend server, across every proxy.
*
* Null when the network cannot be asked (no presence backend reachable). Callers must not
* quietly substitute their own proxy's numbers for this — a proxy-local count *looks* like a
* network count and is the very thing this exists to replace.
*/
fun countPlayersByServer(): NetworkPlayerCounts?
}

/**
* A snapshot of who is online network-wide.
*
* [byServer] holds one entry per *occupied* backend server; a server nobody is on is absent rather
* than zero. [total] counts everyone online, including players who have not reached a backend
* server yet, so it can exceed the sum of [byServer].
*/
data class NetworkPlayerCounts(val byServer: Map<String, Int>, val total: Int) {
fun on(serverName: String): Int = byServer[serverName] ?: 0
}

data class PlayerSessionInfo(
Expand Down
14 changes: 14 additions & 0 deletions api/src/main/kotlin/gg/grounds/proxy/api/ProxyService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ interface ProxyService {

fun getPresence(playerId: UUID): PlayerPresence?

/**
* Players per backend server across the whole network, or null when the network cannot be
* asked.
*
* Velocity's own `playersConnected` only ever counts the players on *this* proxy, so with two
* proxies in front of one lobby each sees half of it. Anything that shows a player a number
* about the network has to come from here.
*
* Null rather than a proxy-local fallback on purpose: a local count is indistinguishable from a
* network count once it is rendered, and silently showing the wrong one is the bug this
* replaces. Callers should say the number is proxy-local instead.
*/
fun getNetworkPlayerCounts(): NetworkPlayerCounts?

/**
* Delivers to the player wherever they are — locally, or over NATS to the proxy holding them.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gg.grounds.proxy.velocity

import com.velocitypowered.api.proxy.ProxyServer
import gg.grounds.proxy.api.NetworkPlayerCounts
import gg.grounds.proxy.api.PlayerPresence
import gg.grounds.proxy.api.PlayerSessionQuery
import gg.grounds.proxy.api.ProxyService
Expand Down Expand Up @@ -75,6 +76,9 @@ class ProxyServiceImpl(
)
}

override fun getNetworkPlayerCounts(): NetworkPlayerCounts? =
sessionQuery()?.countPlayersByServer()

override fun sendToPlayer(targetId: UUID, message: Component) {
val local = proxy.getPlayer(targetId).orElse(null)
if (local != null) {
Expand Down