feat(game-server): scaffold dedicated server toward player join
Build Game Server / build (push) Successful in 17s

R&D branch for an authoritative Unreal game server (Prospect.Unreal).
The connection handshake already reaches PlayerController spawn; this
commit pushes it toward real players joining:

- Program.cs: target the Cycle station map + game mode (configurable via
  PROSPECT_MAP/GAMEMODE/PORT), proper host loop, and initialise a
  GameSession so NMT_Join -> Login no longer fails ("GameSession is null").
- UWorld.WelcomePlayer: send the world's real map/game mode to the client
  instead of the UE ThirdPerson template.
- Dockerfile.gameserver + .gitea/workflows/game-server.yml: build/push a
  separate image (the-cycle-game) on the game-server branch, ntfy notify.
- GAMESERVER.md: honest state + roadmap (player spawn + movement
  replication need live client testing; AI/loot intentionally deferred).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 18:30:09 +02:00
co-authored by Claude Opus 4.8
parent 57a45d91df
commit 9749828af8
5 changed files with 149 additions and 25 deletions
+7 -6
View File
@@ -434,13 +434,14 @@ public abstract partial class UWorld : FNetworkNotify, IAsyncDisposable
private void WelcomePlayer(UNetConnection connection)
{
// TODO: Properly fetch level name from CurrentLevel
var levelName = "/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap";
// TODO: Properly fetch from AuthorityGameMode
var gameName = "/Script/ThirdPersonMP.ThirdPersonMPGameMode";
// Tell the client which level + game mode to travel to. Previously hardcoded to the
// UE ThirdPerson template; now use the world's configured map and the "game=" option
// (set by the host), falling back to the template if unset.
var levelName = string.IsNullOrEmpty(Url.Map) ? "/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap" : Url.Map;
var gameName = Url.GetOption("game=", "/Script/ThirdPersonMP.ThirdPersonMPGameMode") ?? string.Empty;
var redirectUrl = string.Empty;
Logger.Information("Welcoming player -> level={Level} game={Game}", levelName, gameName);
NMT_Welcome.Send(connection, levelName, gameName, redirectUrl);
connection.FlushNet();