# Serveur de jeu dédié — R&D (branche `game-server`)

> ⚠️ **Expérimental.** Objectif : un serveur de jeu **autoritaire** pour que plusieurs
> joueurs soient dans la **même instance** (se voir, bouger). C'est un chantier de
> reverse-engineering du serveur Unreal du Cycle. **Un raid co-op complet reste hors de portée
> réaliste** ; on avance par jalons. **IA et loot volontairement hors périmètre pour l'instant.**

## Pièces en jeu
- **`Prospect.Unreal`** — réimplémentation en C# de la couche réseau d'Unreal Engine
  (NetDriver UDP, channels control/actor, bunches, packet handler, handshake, `UWorld`,
  `AGameModeBase`/`APlayerController`/`APawn`).
- **`Prospect.Server.Game`** — l'exécutable serveur (host loop, monde, game mode).

## État actuel (ce qui marche côté serveur)
Le **handshake de connexion Unreal est implémenté** et va jusqu'au spawn du PlayerController :

```
NMT_Hello  →  SendChallenge
NMT_Login  →  PreLogin → WelcomePlayer (envoie map + game mode)
NMT_Join   →  SpawnPlayActor → GameMode.Login → APlayerController
```

Corrections/avancées de cette branche :
- **Cible la map/gamemode du Cycle** (`/Game/Maps/MP/Station/Station_P` + `YGameMode_Station`)
  au lieu de la map template d'UE. Configurable via `PROSPECT_MAP` / `PROSPECT_GAMEMODE` / `PROSPECT_PORT`.
- **`WelcomePlayer`** envoie désormais la **vraie** map/gamemode du monde (plus le template).
- **`GameSession`** est initialisée → le login ne plante plus sur `"GameSession is null"`
  (c'était le point de blocage juste avant le spawn).

## Ce qui manque (roadmap, du plus atteignable au plus dur)
1. **Connexion client réelle** : valider le handshake complet avec le **vrai client** (pas le
   harnais `Client.cs`). Nécessite des **tests en live** (impossible à valider hors client).
2. **Spawn du Pawn du Cycle** : `GameMode.Login` spawn un `APlayerController` mais **pas** le
   personnage. Il faut spawner la **classe de Pawn spécifique du Cycle** (`YCharacter…`) avec le
   bon **NetGUID / class path** pour que le client l'instancie.
3. **Réplication du mouvement** : répliquer les propriétés du `CharacterMovementComponent`
   (position/rotation/état) chaque tick → **le premier vrai « se voir bouger »**.
4. *(plus tard)* IA, loot, dégâts, tempête, évac… — **hors périmètre pour l'instant**.

Les jalons 2–3 demandent de connaître les **classes répliquées du jeu** (côté client, non
présentes dans le code serveur) et **itèrent en live** avec le client. C'est le vrai mur.

## Build / run
```bash
# build
dotnet build src/Prospect.Server.Game/Prospect.Server.Game.csproj -c Release
# run (défauts : station, port 7777 UDP)
dotnet run --project src/Prospect.Server.Game
# ou conteneur
docker build -t the-cycle-game -f Dockerfile.gameserver .
docker run --rm -p 7777:7777/udp the-cycle-game
```

## CI/CD
`.gitea/workflows/game-server.yml` : à chaque push sur `game-server`, build de `Dockerfile.gameserver`
→ image **`git.nfteam.ovh/neckfire/the-cycle-game`** (tags `game-server` + sha) + notif ntfy.
Image **séparée** de l'API (`the-cycle`) — les deux ne se marchent pas dessus.

## Honnêteté
Ceci est une **base d'exploration**. Le handshake + le spawn du controller avancent ; le
« 2 joueurs se voient bouger » dépend du spawn du pawn du Cycle + réplication, qui exige du RE
spécifique au jeu **et** des tests dans le client réel. Aucune garantie d'aboutir.
