Uebliche.games Network
uebliche.games is the dedicated minigames network. It is intentionally separate from the MMO/story runtime: players join a hub, queue for a minigame, get moved to an on-demand game server, and return to a hub after the round.
Scope
uebliche.games includes:
- Velocity as the player-facing proxy.
- The Hub plugin's standalone lobby system as the lobby runtime.
- The Hub plugin as queue entry, navigation, and transfer surface.
- Connect Gateway as the external ingress path for
uebliche.games. - Regional matchmaking queues that can collect players from multiple hubs.
- On-demand minigame server containers managed by a regional fleet controller.
- Playable experience catalog entries with dedicated server and launcher profile metadata when they are not handled by the round queue runtime.
uebliche.games does not include:
- The full story or MMO progression runtime.
- Manual per-round server provisioning by operators.
- In-place updates that interrupt active rounds.
Topology
flowchart LR
player["Player"]
edge["Connect Gateway"]
velocity["Velocity proxy"]
hubA["Standalone Hub Lobby A"]
hubB["Standalone Hub Lobby B"]
queue["Regional matchmaking queue"]
fleet["Regional game fleet controller"]
server["Minigame server container"]
player --> edge
edge --> velocity
velocity --> hubA
velocity --> hubB
hubA --> queue
hubB --> queue
queue --> fleet
fleet --> server
server --> velocity
velocity --> serverDomain And Ingress
uebliche.games should be the public player entry point for the minigames network. Velocity should not be exposed directly. Instead, the Velocity runtime uses Connect to publish its Minecraft TCP route through Gateway.
The expected baseline is:
- DNS points
uebliche.gamesorplay.uebliche.gamesat the Connect Gateway route, preferably through an_minecraft._tcpSRV record. - Velocity runs behind Gateway and publishes a
minecraft-tcpConnect route. - Hub remains responsible for player routing after the player is inside the network.
Standalone Hub Lobby Runtime
uebliche.games should use the Hub system's existing standalone lobby runtime for all lobby instances. This keeps the minigames network on the Hub plugin's own lobby stack instead of reusing the story/MMO Gameserver as a lobby.
The standalone lobby runtime is responsible for:
- player spawn and safe fallback handling,
- lobby navigation, NPCs, signs, and Velocity-backed selectors,
- queue entry points for minigames,
- operator-spawned test bots and reconnect placeholder mannequins,
- cosmetic and lightweight lobby activities,
- returning players after rounds,
- advertising regional queue and match status.
Velocity should treat each standalone Hub lobby as a normal backend server. Multiple lobby instances can run per region, and the regional matchmaking queue can collect tickets from all of them.
Hub Test Bots
The standalone Hub lobby provides server-side test bots for local queue and routing tests. They are implemented as visible player mannequins with stable names and UUIDs, not as socket-connected Minecraft clients. This keeps them cheap to spawn while preserving the same identity model needed for future offline placeholders and reconnect recovery.
Initial operator commands:
/hubbot spawn <name>spawns one bot at the sender position./hubbot spawnmany <prefix> <count>spawns up to 64 bots in a small grid./hubbot tp <name>moves a bot to the sender position./hubbot remove <name>removes one bot./hubbot clearremoves all spawned bots./hubbot listshows spawned bot names, UUIDs, and positions.
Studio Stack
The first studio-local deployment lives in mod/hub/compose.uebliche-games.yml. It starts:
velocity: player-facing proxy on${UEBLICHE_GAMES_PORT:-25566}and optional Connect Gateway publisher,minigames-lobby: the standalone Hub lobby runtime,minigames-host-1andminigames-host-2: shared Minestom games backends for FFA, SkyBlock, SurvivalGames, and TTT assignments,abyss: the Velocity holding backend used while no Hub fallback is reachable.
Legacy mode-specific backends such as minigame-ffa and minigame-survivalgames remain buildable through the legacy-games Compose profile, but the default studio stack routes game joins through games-local-1.
Resource Packs
uebliche.games uses one stable optional server resource-pack stack for Hub and GamesHost sessions. The default stack is base,games; players receive it when they enter the lobby or a games context, and the server avoids resending it while the resolved pack hashes stay unchanged.
Definitions, variants, and maps can adjust the stack through metadata. The priority is map metadata, then variant metadata, then definition metadata, then environment defaults.
resourcepacks.names: replaces the full pack list, for examplebase,games.resourcepacks.extra: appends additional packs such asbimorevent-easter.resourcepacks.required: makes the prompt required for that scope.resourcepacks.disabled: disables resource-pack delivery for that scope.
Local development can serve packs directly from resourcepack/<name> through the built-in dev HTTP server at /dev/resourcepacks/<name>.zip. Production should resolve pack records from Mongo/CDN metadata with public_url and sha1_hash. Gameplay must stay readable without accepting the pack: every item keeps a vanilla material and display name fallback.
Performance Sidebar
GamesHost servers enable lightweight performance monitoring by default. Players can toggle their personal sidebar with /performance, /perf, or /mspt. The sidebar reuses the shared libs/minestom-monitoring tick window and shows current and average MSPT, p95 windows, the latest peak, tick overruns, heap, process CPU, and online players.
Local and production hosts can control it with:
PERFORMANCE_MONITORING_ENABLED: enable the tick probe and command.PERFORMANCE_SIDEBAR_AUTO_SHOW: show the sidebar automatically on first spawn.PERFORMANCE_SIDEBAR_HISTORY_SECONDS: rolling tick history size.
Match Teams
uebliche.games keeps party/queue groups and in-match teams separate. Parties come from the Public API party endpoints; match teams are read from minigame variant definitions through the existing teams list and each role's team field.
Shared team behavior now goes through libs/teams. The loader-free core owns role-to-team resolution, entrant keys, same-team audience filtering, and team score-limit aggregation. The Minestom adapter exposes the audience helper used by GamesHost team chat. This keeps BIM, TDM, TTT, tournament, and future arena modes on one match-team model while preserving the current JSON seed format.
The local stack builds the Minestom lobby and games host against net.minestom:minestom:26_1-SNAPSHOT. Velocity is launched via the latest official 3.5.0-SNAPSHOT runtime build exposed by PaperMC downloads.
Voice
uebliche.games uses the shared Uebliche social voice stack: the client-side mod/social channel manager, common/social server API, and services/uebliche-voice-node routing backend. The current GamesHost does not install or configure the old mod-specific voice bridge.
GamesHost syncs server-side proximity groups to the canonical proximity channel for the public server address. By default, every active match receives one voice group so players in different matches cannot hear each other on the same GamesHost. Arena variants can opt into team-only proximity isolation with voice.grouping=team, or disable server grouping with voice.disabled=true.
Local and production hosts can control it with:
GAMES_HOST_VOICE_ENABLED: enable GamesHost voice control sync.GAMES_HOST_VOICE_SERVER_ADDRESS: public address used to resolve the proximity channel, defaulting touebliche.games.GAMES_HOST_VOICE_SYNC_INTERVAL_MILLIS: minimum sync interval.CONNECT_API_BASE,CONNECT_SERVER_ID, andCONNECT_SERVER_SECRET: server authentication for the voice control API.UEBLICHE_SOCIAL_API_TOKENorUEBLICHE_API_TOKEN: token fallback for local or non-Connect environments.
The stack is guarded so it does not accidentally start on a workstation. Run it on studio with:
cd mod/hub
UEBLICHE_GAMES_STUDIO_RUN=true docker compose -f compose.uebliche-games.yml up -dJoin on the studio host at localhost:25566. Velocity runs in online mode for this stack, so a real authenticated Minecraft account is required. The stack also bundles the Connect Velocity plugin. When the studio stack is published through Connect Gateway, it must stay on a DEV route. By default it reports itself as uebliche.games DEV, publishes dev.uebliche.games, and refuses to start Gateway publishing for non-DEV route hosts such as uebliche.games or play.uebliche.games.
The HUB repository also contains the Deploy Studio Minigames GitHub Action. It runs on the Studio self-hosted Windows runner for every push, checks out the parent workspace layout, overlays the pushed HUB revision into mod/hub, and recreates the local compose.uebliche-games.yml stack. Optional Studio-specific repository variables and secrets use the STUDIO_ prefix, for example STUDIO_CONNECT_SERVER_ID, STUDIO_CONNECT_SERVER_SECRET, and STUDIO_CONNECT_GATEWAY_ROUTE_HOST.
Community Test Stack
mod/hub/compose.community-test.yml runs a fully separate local community network for third-party Connect testing. It has its own Velocity proxy, MongoDB volume, Hub lobby, GamesHost, Abyss backend, Velocity server names, run directories, and default port. It is not a backend inside the uebliche.games Velocity process. Its DockBridge config also uses a separate community-test label value so it does not auto-register backends from the normal uebliche.games stack.
Use it to test public systems such as friends and future party delegation exactly as a non-official community server would see them.
First provision a Connect server identity and Ed25519 signing key:
mod/hub/scripts/provision-community-connect-server.shThe script stores credentials under secrets/community-test-connect/, prints a short-lived claim key, and writes a connect-server-patch.json file containing the public key plus the allowed delegated scope. Claim the server in Dash, then apply that patch to the claimed Connect server. If CONNECT_USER_TOKEN is set, the script claims and patches the server automatically.
Then start the local community backend:
cd mod/hub
docker compose --env-file ../../secrets/community-test-connect/community-test.env \
-f compose.community-test.yml up -dJoin it through its own Velocity proxy at community.127.0.0.1.nip.io:25567. Because the seeded server identity is not official, the Connect client should show the consent overlay before the Hub can read the friends list.
Set CONNECT_COMMUNITY_GATEWAY_ENABLED=true and CONNECT_COMMUNITY_GATEWAY_ROUTE_HOST=community.uebliche.games when this stack should publish itself through Connect Gateway instead of only running locally.
The Minestom Hub navigator adds SurvivalGames Classic, SurvivalGames Blitz, TTT Classic, FFA Arena, and SkyBlock entries when UEBLICHE_GAMES_STACK=true. Joining a queued round writes a match assignment, waits up to the configured fill timeout (30 seconds by default), then fills the remaining target slots with bot placeholders before transferring real players to games-local-1. Server-only entries such as FFA and SkyBlock create a persistent assignment immediately and then transfer the player to the same shared games backend.
Players can also join queues with the unified Hub command:
/queue survival-games classic/queue survival-games blitz/queue sg classic/queue ttt/queue ffa/ffa/queue leave/queue status
When UEBLICHE_GAMES_REPORT_TOKEN is present, the Minestom lobby reports its enabled queue entries to the Public API endpoint /v1/games/minigames/report. The Launcher reads the public catalog from /v1/public/games/minigames, so newly reported Uebliche.games queues appear in the Play > Minigames page without a Launcher release.
The SurvivalGames backend shows round counters in chat at key moments and keeps a live sidebar for connected players. The sidebar includes the selected mode, map, phase, phase timer, alive real players, bots, and current match id.
PvP uses the reusable libs/pvp stack. The loader-free core owns melee weapon damage, armor reduction, and hit cooldowns, while the Minestom adapter applies damage and knockback from entity attack events. SurvivalGames enables these hits only in PvP-capable phases and keeps spectators/disconnected players out of combat.
The SurvivalGames backend also installs the shared vanilla crafting adapter with SURVIVAL_GAMES_CRAFTING_POLICY=survival-games-classic. This policy enables crafting-grid recipes from the pinned 1.21.11 vanilla data. Crafting tables are not generated by the runtime; players can use crafting-table blocks that already exist in the selected map. Set the policy to vanilla to register all supported vanilla stations, or disabled to turn recipe registration off for a runtime.
Maps are loaded from SURVIVAL_GAMES_MAPS_DIR and configured through SURVIVAL_GAMES_MAP_CONFIG. The local stack points these values at mod/hub/run-uebliche-games-maps. On first boot, the server imports The Original Survival Games Map.zip from mod/hub/run-uebliche-games-map-sources, writes a maps.json entry for original-survival-games, migrates the map into MongoDB, and loads match instances from the uebliche world format instead of using raw Anvil files as the runtime source.
The Hub and GamesHost map catalogs now go through the shared libs/maps runtime. MINIGAME_MAPS_PATH remains the local JSON fallback, and MongoDB active map records remain the production source. GamesHost still resolves world instances through the world library, but JSON/Mongo map catalog parsing is owned by libs/maps.
The uebliche world format stores a world manifest, palette-section chunk documents, metadata slots for overlays and regions, world-stored round triggers, SurvivalGames round spawnpoints, and SurvivalGames loot container metadata discovered from the imported world. The stored spawnpoint count defines the map's max player count. The SurvivalGames runtime does not place chest blocks; it fills loot only when a player interacts with a chest, trapped chest, or barrel that came from the map. Legacy Anvil worlds with numeric block sections are converted during import so older maps can be used without pre-conversion. Local collections use the uebliche_world_* prefix in SURVIVAL_GAMES_MONGODB_DATABASE.
The preferred local map editing flow is the UeblicheEngine Fabric editor. Join the SurvivalGames backend with the engine client, press Right Shift, and the backend opens the active map in a separate editor instance. Existing round spawnpoints appear as visible markers. Press N in the editor to add a new spawnpoint at the builder's current position, select markers from the outliner or viewport, and move them with the transform controls. Spawnpoint changes are saved back into the MongoDB world manifest.
Opening a world editor session now also switches the builder into Creative mode. The shared /edit command opens the current world in a separate editor instance, while /edit <world> opens a named target when the backend supports it. Use /edit save, /edit close, and /edit status to manage the session. Hub edits are saved into the local Hub world storage, SurvivalGames map edits save changed chunks through the uebliche world format, and the generic GamesHost exposes the active SkyBlock island as its editable world. The older /worldcreative on|off|save|status and SurvivalGames /sgcreative commands remain available as live-instance Creative toggles.
Fallback map editor commands remain available on the SurvivalGames backend:
/sgeditor spawn addstores the sender's current position as a round spawn in the world manifest./sgeditor spawn listlists round spawns and the resulting max player count./sgeditor spawn clearresets round spawns to the primary world spawn./sgeditor trigger piston <id> [radius]scans nearby map pistons and stores a round-start extension trigger in the world manifest./sgeditor trigger test <id>runs a stored trigger immediately./sgeditor trigger listlists stored round-start triggers./sgeditor trigger clear <id>removes a stored trigger.
Players can bias map selection with /sgmap favorite, which opens a map GUI: left click marks a map as favorite and right click marks it as hated. The text commands /sgmap favorite <map>, /sgmap hate <map>, and /sgmap clear <map> remain available for direct edits. The selector scores all eligible maps from current player preferences, then randomly picks one of the best-scoring maps so favorites matter without making the order deterministic.
Hub Responsibilities
Hub becomes the minigames control surface, not just a lobby router:
- Show available game modes and queue state.
- Let players and parties join or leave queues.
- Submit queue tickets to the regional matchmaking queue.
- Receive match assignments and transfer players through Velocity.
- Keep fallback hub routing available when a match server fails or a round ends.
- Expose operator/debug views for queues, active matches, and fleet state.
Hub should not talk to the Docker socket directly in production. It should call a small regional controller API that owns container lifecycle and can enforce quotas, versions, health checks, and cleanup. A direct Docker adapter is acceptable for local development only.
Regional Matchmaking
Each region owns its own matchmaking queue. The queue can accept tickets from multiple Hub instances in the same region, so players are pooled across hubs without requiring all players to stand in the same lobby.
Queue tickets should carry:
- player ids and party ids,
- target game mode,
- acceptable region or latency hints,
- party size and team constraints,
- client/server compatibility constraints,
- enqueue time and priority metadata.
The regional matchmaker creates a match when enough compatible tickets are available. It then asks the fleet controller for the best ready or bootable game server in that region and returns a transfer assignment to every affected hub.
Cross-region matching should be a fallback policy, not the default. The default decision should keep players in their nearest healthy region.
First Game: SurvivalGames
SurvivalGames is the first planned uebliche.games minigame. The shared core defines two initial variants:
Classic: normal SurvivalGames pacing.Blitz: faster rounds with smaller starting thresholds.
Both variants use S, L, XL, and XXL queue sizes. Each size has a minimum player count, a target fill count, a maximum capacity, and a wait budget. The matchmaker should:
- start a target-filled size immediately,
- prefer one larger fitting round over multiple smaller rounds,
- start under-target larger rounds only after players waited long enough,
- leave small overflow remainders queued instead of launching too many small extra servers,
- keep parties together and never split one ticket across two matches.
This policy keeps wait times bounded while still trying to keep rounds full and server count low.
Second Game: TTT
TTT is the second local uebliche.games minigame. The shared core defines the Classic variant, role model, phases, role assignment, and win condition:
InnocentandDetectivewin when no traitors remain alive.Traitorwins when no innocent-side players remain alive.- A single real-player local queue-fill round assigns the real player as traitor so bot-filled testing can immediately validate combat and win checks.
The first local Minestom backend uses a generated test arena, Velocity forwarding, the shared PvP adapter, a /ttt role/status command, and the same match-file queue handoff pattern as SurvivalGames. The Hub navigator exposes TTT Classic beside the SurvivalGames entries.
Shared Minigame Libraries
Minigame code must be reusable across uebliche.games, Hub, Gameserver, and the future MMO RPG world. Portable logic belongs under libs/minigame/*, following the shared module pattern:
libs/minigame/corecontains loader-free contracts such as game modes, matchmaking tickets, assignments, server fleet snapshots, SurvivalGames phases, player states, loot tables, and map selection.- Future
adapter-*modules translate platform objects intocorecontracts. - Future
storage-*modules persist queues, templates, rounds, and stats behindcoreinterfaces.
Game rules, queue contracts, match assignments, and fleet state should not live inside a Velocity plugin, Docker controller, or MMO-specific runtime. Those layers should consume the shared contracts so the same minigames can later be rebuilt inside the MMO RPG world.
Vanilla crafting follows the same rule through libs/crafting/*:
libs/crafting/corecontains loader-free recipe access policies.libs/crafting/adapter-minestomloads pinned vanilla recipe data, registers Minestom recipe displays, matches crafting grids, and provides a small crafting-table interaction module.
On-Demand Game Server Fleet
Minigame servers are short-lived or semi-warm containers. A server can host multiple rounds when its game mode, map pool, and version still match the current fleet policy, but it must be drainable for seamless updates.
Recommended instance states:
requested: a match or warm-pool policy needs capacity.provisioning: the controller is creating the container.booting: the process is starting and registering health.ready: the server can accept a match.assigned: the server is reserved for a specific match.running: a round is active.draining: no new rounds are assigned; current players may finish.stopped: the container was removed.failed: startup, health, or runtime checks failed.
The fleet controller should track game mode, map, image tag, build version, region, capacity, current round id, assigned players, health, and expiry time for each instance.
Seamless Updates
Updates should be versioned instead of mutating active servers:
- New game server images receive immutable build tags.
- New matches are assigned only to the newest eligible version after rollout starts.
- Existing match servers keep running until the current round ends.
- Servers with old versions enter
drainingand are removed after their final round or after a hard timeout. - Hub and Velocity stay online throughout the rollout.
This allows multiple rounds to continue on already-started containers while still moving new rounds to the updated version as soon as capacity is ready.
MVP
The first usable slice should be:
- Publish Velocity for
uebliche.gamesthrough Connect Gateway. - Run the existing standalone Hub lobby runtime as the
uebliche.gameslobby. - Keep minigame contracts in
libs/minigame/corebefore adding runtime-specific adapters. - Add a Hub queue UI and commands for one minigame mode.
- Add one regional matchmaking queue that can receive tickets from multiple hubs.
- Add a regional fleet controller with a Docker adapter for starting one minigame server image.
- Register started game servers as Velocity backends and transfer matched players automatically.
- Add drain-on-update semantics so new rounds use the new image while old rounds finish cleanly.