Lobby mode: Paper servers can now connect directly to Redis for real-time global sync (lobby.enabled: true).
Global Player List: real-time player visibility across all lobbies via Redis pub/sub (replaces periodic proxy dumps).
Global Challenges: lobby-to-lobby challenge routing via Redis. 2-hop flow replaces the old 4-hop proxy-mediated routing.
Global Presence: real-time online/offline/in-battle/in-queue status across all regions via PRESENCE_UPDATE messages.
Global Invites: invite any player from any server with INVITE_SEND/INVITE_ACCEPT/INVITE_DECLINE messages.
Global Parties: create, join, and manage parties across all servers with Redis-synced state. Party-aware matchmaking. Commands: /party create, /party invite, /party join, /party leave, /party kick, /party disband.
Global Routing: smart region selection for cross-region battles (ROUTE_REQUEST/ROUTE_RESPONSE). Strategies: nearest, lowest latency, least loaded, shared server.
Optional Database Layer: persistent storage for stats, match history, ELO ratings, and player profiles.
MySQL/MariaDB support with HikariCP connection pooling.
SQLite support for single-server or development setups.
MongoDB support for complex data (stub; requires driver on classpath).
Configurable via database.* section in config.yml.
New Maven module: pvpindex-database with DatabaseProvider interface, repository abstractions, and implementations.
NetworkNode class with NodeType enum (PROXY, LOBBY, BACKEND) generalising the network module.
LobbyNetworkService orchestrates all Redis-based services on lobby Paper servers.
LobbySettings and DatabaseSettings config records.
New config sections: lobby.* (Redis connectivity for lobby servers) and database.* (optional persistence).
New docs: SETUP-LOBBY.md, SETUP-DATABASE.md, GLOBAL-FEATURES.md, SCALING.md.
Changed
Architecture: lobbies now handle all global features via Redis instead of routing through proxies. Proxies are simplified to authentication, routing, and player transfers.
Network module generalised: ProxyNode → NetworkNode with NodeType enum. ProxyNode kept as deprecated subclass.
DefaultNetworkRouter: refactored to use NetworkNode internally; backward-compatible with ProxyNode usage.
ChallengeManager: added setLobbyServices() for Redis-direct challenge routing. Supports three modes: lobby (Redis), proxy (plugin messaging), standalone (local).
Velocity ProxyMessageHandler: stripped all challenge routing logic. Now handles battle lifecycle, heartbeats, and TRANSFER_REQUEST only. Legacy challenge forwarding kept for backward compat.
BungeeCord BungeeProxyMessageHandler: same simplification as Velocity.
PvPIndexBattlesPlugin: added initialisation for LobbyNetworkService and DataService.
Plugin messaging reliability: lobbies no longer depend on proxy for challenge delivery (no dropped messages when no players online).
Challenge flow reduced from 4 hops (Paper→Proxy→Redis→Proxy→Paper) to 2 hops (Lobby→Redis→Lobby).
Fixed
Challenge "Player not found" after restart: lobby servers ignored proxy player list updates after restarting, leaving the network player cache empty for remote players. NetworkPlayerCache now merges incoming updates so remote players are visible within seconds of a restart.
Cross-proxy challenge lookup: challenges between players on different proxies (e.g. US to EU) failed with "Player not found" because the proxy only checked its own player list. Velocity and BungeeCord proxies now fall back to the Redis player registry for cross-proxy lookups.
Dead player teleport failure: after a battle, defeated players who were still dead could not be teleported, silently stranding them in deleted arena worlds. PlayerStateSnapshot now force-respawns dead players before attempting the teleport.
Cross-server return after battle: players transferred to another server for a battle were not returned to their original server afterwards. Proxies now track each player's origin server before transfer and automatically return them when the battle ends.
SMP loot phase cleanup on winner disconnect: if the winner disconnected during the SMP loot phase, the loser was left stranded with no boss bar and no timer. The plugin now ends the loot phase cleanly, restoring the loser and cancelling all timers.
Challenge accepted notification not delivered: accepting or declining a challenge from a backend server through a lobby produced no response on the challenger's side. Fixed routing of CHALLENGE_ACCEPT and CHALLENGE_DECLINE messages between Redis and plugin messaging on both Velocity and BungeeCord proxies.
TeleHop arena conflict: TeleHop's random respawn feature interfered with PvPIndex arena death handling by teleporting dead players before the plugin could process them. Added excluded-worlds support to TeleHop to skip arena worlds.
Deprecated
ProxyNode class. Use NetworkNode with NodeType.PROXY instead.
NetworkRouter.registerLocalProxy(). Use registerLocalNode().
NetworkRouter.getProxy(), allProxies(), onlineProxies(). Use node-generic equivalents.
Proxy-based challenge routing (kept as fallback for standalone/SMP servers without Redis).
Periodic NETWORK_PLAYER_LIST broadcast from proxy (kept as fallback for non-lobby backends).
Removed
PendingChallenge from platform-velocity (challenge state no longer lives on proxy).
BungeePendingChallenge from platform-bungeecord.
Cross-proxy challenge routing logic from both proxy message handlers.