dcsim-gameserver/Patchs/sync_salles/README_SYNC_SALLES.md
2026-04-18 09:24:59 +00:00

148 lines
6.7 KiB
Markdown

# Sync multi des nouvelles salles (GestionnaireMultiSalles v2.0)
## Contexte
Ton dernier test a révélé que j'avais synchronisé le mauvais système :
- Tu utilises **`GestionnaireMultiSalles`** (achat "Nouvelle salle Ouest/Est/Nord/Sud" au Terminal)
- J'avais synchronisé **`AgrandissementSalle`** (panneau mural, qui n'est plus utilisé)
Ce pack corrige ça.
## Ce qui change
Un seul fichier patché : **`GestionnaireMultiSalles.cs` v2.0**
Changements :
1. La classe passe de `MonoBehaviour` à **`NetworkBehaviour`**
2. Ajout d'une **`SyncList<string>`** qui contient les créations de salles (ex: `"1_Ouest"`, `"2_Nord"`)
3. Ajout d'un **`[ClientRpc] RpcLancerConstructionSalle`** qui broadcast l'ordre aux clients
4. `CreerNouvelleSalle` côté serveur :
- Enregistre dans la SyncList (pour rejoin)
- Broadcast le Rpc aux clients
5. Chaque instance (serveur + clients) exécute l'animation **localement** via `AnimationCreationSalleLocal`
6. Nouvelle méthode `OnStartClient` : les clients qui rejoignent en cours de partie relisent la SyncList et rejouent toutes les salles en mode **instantané** (pas d'animation)
7. Le code de génération est refactorisé : la partie "construire la géométrie de la salle + couloir" est extraite dans `CreerSalleGeometrie` pour être réutilisée par le flux normal ET le rejoin
8. Gardes `DedicatedServerMode.IsDedicatedServer` ajoutées partout où du Material/Light est créé (pas de shaders côté serveur)
## Setup Inspector
**Important** : `GestionnaireMultiSalles` est maintenant un `NetworkBehaviour`, donc il a besoin d'un `NetworkIdentity` sur son GameObject.
### Étapes
1. Dans la scène `Datacenter_01`, trouver le GameObject qui porte le composant `GestionnaireMultiSalles`
2. Si ce GameObject n'a **pas** de `NetworkIdentity` :
- `Add Component``NetworkIdentity`
- Dans l'Inspector du `NetworkIdentity`, **ne coche rien** (ni "Server Only" ni "Local Player Authority" — c'est un objet serveur autoritaire qui synchronise via la SyncList)
3. Sauver la scène (`Ctrl+S`)
### Note sur les autres composants
Tu peux **retirer** maintenant :
- `SynchronisationAgrandissement` (de la scène)
- `PlayerAgrandissementBridge` (du prefab joueur)
- Les 2 fichiers `.cs` correspondants (si tu veux nettoyer)
Puisque `AgrandissementSalle` n'est plus utilisé dans ta version actuelle, les 2 scripts que j'avais livrés hier ne servent plus à rien. Tu peux les garder dans le code mort s'il te semble possible d'y revenir plus tard.
## Actions à faire
1. **Remplacer** `Assets/Scripts/GestionnaireMultiSalles.cs` par la nouvelle version
2. **Vérifier / ajouter** `NetworkIdentity` sur le GameObject qui porte ce composant
3. **Sauver la scène**
4. **Build client Windows** (pour pouvoir tester)
5. **Build Dedicated Server Linux** et déployer sur la Debian
## Test à faire
### Test 1 — Solo (éditeur Play)
1. Lancer l'éditeur en Play (pas host)
2. Aller au Terminal, acheter "Nouvelle salle Ouest"
3. **Attendu** : le mur explose, couloir apparaît, salle Ouest se construit comme avant
### Test 2 — Host + Client
1. Éditeur en Host, un build Windows connecté en client
2. Le **host** achète "Nouvelle salle Est"
3. **Attendu** : les DEUX voient la même animation + couloir + salle créée
### Test 3 — Client déclencheur
1. Host + Client
2. Le **client** achète "Nouvelle salle Nord"
3. **Attendu** : les DEUX voient la même animation
### Test 4 — Dedicated + 2 clients
1. Dedicated sur Debian + 2 clients Windows
2. Un client achète "Nouvelle salle Sud"
3. **Attendu** : les 2 clients voient l'animation synchrone, le serveur logue la création
### Test 5 — Rejoin
1. Dedicated + 1 client
2. Le client achète "Nouvelle salle Ouest"
3. Un **2e client** se connecte APRÈS
4. **Attendu** : le 2e client voit la nouvelle salle + le couloir déjà construits (rejeu instantané, pas d'anim)
## Diagnostic
Dans les logs, tu devrais voir :
**Côté serveur** :
```
[MultiSalles] Salle enregistree dans SyncList : 1_Ouest (total : 1)
[MultiSalles] Debut construction locale salle Ouest depuis Salle 1 (instantane=False)
[MultiSalles] Mur DC_MurEst percé avec morceaux latéraux
[MultiSalles] Nouvelle salle creee localement : Salle 2 (15x10m) direction Ouest
```
**Côté client** :
```
[MultiSalles] Rpc recu : construction salle Ouest depuis parent id=1
[MultiSalles] Debut construction locale salle Ouest depuis Salle 1 (instantane=False)
[MultiSalles] Mur DC_MurEst percé avec morceaux latéraux
[MultiSalles] Nouvelle salle creee localement : Salle 2 (15x10m) direction Ouest
```
**Si rien ne se passe côté client** malgré le Rpc envoyé :
- Vérifier que le GameObject qui porte `GestionnaireMultiSalles` a bien un `NetworkIdentity`
- Vérifier dans Mirror Inspector que le NetworkBehaviour est bien enregistré
**Si "Salle parente id=X introuvable localement, skip"** :
- Problème de timing : le client n'a pas encore sa salle 1 enregistrée
- Pas grave dans 99% des cas (la salle 1 s'enregistre au démarrage via `SalleDatacenter.Start()`), mais si ça arrive à un client qui rejoint tardivement, le rejeu va skipper proprement
## Ce qui n'est PAS encore synchronisé
- **Les équipements placés dans les nouvelles salles** : quand un joueur pose une baie dans la salle 2, ça passe par `BoutiqueReseau.TraiterPlacementBaieServeur` qui utilise bien `NetworkServer.Spawn`, donc **c'est déjà synchronisé**. Pas de travail.
- **L'état "mur percé" dans la SyncList** : je ne track pas séparément les percements de mur, je track la création de salle. Le percement est fait automatiquement quand la salle est créée (dans `AnimationCreationSalleLocal`). Donc pas de divergence possible.
- **L'ordre des salles créées** : la SyncList conserve l'ordre d'insertion. Si un client rejoint, il rejoue dans l'ordre → pas de conflit.
## Architecture en un schéma
```
Client achete "Nouvelle salle Ouest" au Terminal
BoutiqueReseau.DemanderCommandeSalle
PlayerBoutiqueCommande.CmdCommanderSalle (deja en place, aucun changement)
[SERVEUR] BoutiqueReseau.TraiterCommandeSalleServeur
[SERVEUR] GestionnaireMultiSalles.CreerNouvelleSalle
├── Ajoute "1_Ouest" a _sallesSyncList (→ sync auto aux clients)
└── RpcLancerConstructionSalle(1, "Ouest")
├── [CLIENT 1] StartCoroutine(AnimationCreationSalleLocal(1, "Ouest", false))
├── [CLIENT 2] StartCoroutine(AnimationCreationSalleLocal(1, "Ouest", false))
└── [HOST si applicable] skip (deja joue cote serveur)
[NOUVEAU CLIENT qui rejoint plus tard]
OnStartClient : lit _sallesSyncList → rejoue chaque entree en mode instantane=true
```