dcsim-gameserver/Patchs/pack_multi/README_PACK_v7.1.md
2026-04-18 11:31:50 +00:00

180 lines
7.8 KiB
Markdown

# DatacenterSim v7.1 — Pack multi complet
Pack de 3 patches qui corrigent les 3 bugs identifiés en multijoueur après reco :
1. **Portage d'équipements** invisible pour les autres joueurs
2. **Câbles alim + RJ45** pendants après reco
3. **Serveurs éteints** après reco
---
## Ce qu'il y a dans le ZIP
### Scripts_Modifies/ (remplacer dans Assets/Scripts/)
- **`PlayerInteraction.cs`** — 3 changements
- Revert de mon patch authority (plus de AssignClientAuthority/RemoveClientAuthority sur équipements)
- `CmdUpdateTransportPosition` bouge maintenant l'objet côté serveur
- Helper `SetNetworkTransformActif()` + désactivation NT local pendant portage + réactivation à la pose
- `CmdAppuyerBoutonPower` appelle `EtatEquipementNetworkSync.ServerSyncEtat` pour le rejoin
- **`CablageReseau.cs`** — 4 ajouts
- `CmdCreerCableRJ45` / `CmdCreerCableAlim` enregistrent dans le gestionnaire
- `CmdSupprimerCableRJ45` / `CmdSupprimerCableAlim` désenregistrent
- **`BaieNetworkSetup.cs`** — 1 ajout
- `OnStartClient` notifie le gestionnaire que la baie est prête
- **`EtatEquipement.cs`** — 1 ajout
- `VerifierAlimentation` appelle `EtatEquipementNetworkSync.ServerSyncEtat` quand l'état change
### Scripts_Nouveaux/ (AJOUTER dans Assets/Scripts/)
- **`GestionnaireCablesReseau.cs`** — NetworkBehaviour singleton qui tient 2 SyncLists (câbles alim + RJ45) et rejoue les câbles au rejoin des clients
- **`EtatEquipementNetworkSync.cs`** — Composant à ajouter sur les prefabs d'équipements rackmount pour synchroniser l'état bouton/sous-tension au rejoin
---
## Configuration Unity requise
### 1. Prefabs d'équipements : NetworkTransform en `Server To Client`
**IMPORTANT** : tu avais configuré `Client To Server` pour mon dernier patch raté. **Remets-les en `Server To Client`** :
Pour chaque prefab dans `NetworkManager.spawnPrefabs` (sauf Chariot et prefab joueur) :
- Ouvrir le prefab
- Le `NetworkTransformReliable` / `NetworkTransformUnreliable` :
- **Sync Direction : `Server To Client`** ⚠️
- Sync Position : ✅
- Sync Rotation : ✅
- Sync Scale : ❌
- Compress Rotation : ✅
- Only Sync On Change : ✅
- Interpolate Position : ✅
- Interpolate Rotation : ✅
- Send Interval Multiplier : 3 ou 5
Prefabs concernés : `Serveur_1U`, `Switch_24P`, `Parefeu`, `PDU_APC_*`, `Baie_Procedurale`, `Toron_Base`.
**Ne PAS toucher** : le chariot (Client To Server) et le prefab joueur (Client To Server).
### 2. Ajouter `GestionnaireCablesReseau` à la scène `Datacenter_01`
1. Dans la scène, `Hierarchy` → clic droit → `Create Empty`
2. Renommer : `GestionnaireCables_Holder`
3. `Add Component``NetworkIdentity` (laisser toutes les checkboxes décochées)
4. `Add Component``GestionnaireCablesReseau`
5. **Sauver la scène** (Ctrl+S)
### 3. Ajouter `EtatEquipementNetworkSync` sur les prefabs d'équipements rackmount
Pour chaque prefab qui a un `BoutonPower` + `EtatEquipement` :
- Ouvrir le prefab
- `Add Component``EtatEquipementNetworkSync`
- Sauver
Prefabs concernés : `Serveur_1U`, `Switch_24P`, `Parefeu`.
(Pas besoin sur PDU, Toron, Baie — ces prefabs n'ont pas de bouton power.)
---
## Tests à faire
### Test 1 — Non-régression solo
Lancer en éditeur Play. Tout doit fonctionner comme avant (pas de multi).
### Test 2 — Portage visible en multi
1. Host + 1 client connecté
2. Client prend un serveur 1U depuis un carton → **tu dois voir le serveur suivre le client**
3. Client le pose dans une baie → **tu dois voir le snap**
4. Tu prends le même serveur pour le déracker → **le client doit te voir le porter**
### Test 3 — Câbles alim au rejoin
1. Client pose baie + 2 serveurs + 2 PDUs + 2 câbles alim
2. Client allume les serveurs (bouton Power)
3. Client déco + reco
4. **Attendu** : câbles alim toujours connectés (non pendants), serveurs toujours allumés (ventilos tournent, LED verte)
### Test 4 — Câbles RJ45 au rejoin
1. Client pose baie + 2 serveurs + 1 switch + torons + câbles RJ45
2. Client déco + reco
3. **Attendu** : câbles RJ45 toujours branchés correctement
### Test 5 — 2e joueur qui rejoint en cours
1. Client 1 a tout câblé et allumé
2. Client 2 se connecte
3. **Attendu** : client 2 voit TOUT l'état (câbles + serveurs allumés)
---
## Logs à surveiller
### Côté serveur, quand un câble est créé :
```
[Serveur] Câble alim créé : PDU 10 prise 11 → equip 7 port 0
[GestionnaireCablesReseau] Cable alim enregistre (total : 1)
```
### Côté client qui rejoint :
```
[GestionnaireCablesReseau] Client rejoint : 2 cables alim, 3 cables RJ45 a recreer
[BaieNetworkSetup] Baie regeneree cote client : Baie_Procedurale(Clone)
[GestionnaireCablesReseau] Baie prete : Baie_Procedurale(Clone), retry cables en attente
[GestionnaireCablesReseau] Cable alim recree : PDU 10 prise #11 -> PSU0
[GestionnaireCablesReseau] Tous les cables ont ete recrees
```
### Si timeout (normalement jamais) :
```
[GestionnaireCablesReseau] Timeout : 1 cables alim + 0 cables RJ45 jamais recrees
```
→ ça veut dire qu'une baie ou un équipement ne s'est pas spawné correctement côté client.
---
## Architecture du mécanisme "baie prête"
Le problème classique au rejoin : on tente de recréer un câble entre PDU X et serveur Y, mais X ou Y n'existent pas encore localement parce que leur parent (la baie) n'a pas fini de se régénérer.
**Solution** :
1. Au `OnStartClient` du gestionnaire, on met tous les câbles à recréer en "liste d'attente"
2. On tente une première passe après 0.5s (laisse le temps aux premiers spawn)
3. Chaque `BaieNetworkSetup.OnStartClient` se termine par `NotifierBaiePrete()` qui déclenche un **retry** sur tous les câbles en attente
4. En fallback, un retry périodique toutes les 0.5s pendant 15s max
5. Timeout à 15s avec un warning dans les logs
C'est robuste aux ordres de spawn aléatoires et évite tout callback hell.
---
## Remarques techniques
### Pourquoi retirer l'authority pour le portage ?
`NetworkTransform Client-to-Server` exige l'authority. Le patch précédent transférait l'authority au ramassage, mais ça créait plein de race conditions (logs `EntityStateMessage without authority`, objets figés/dédoublés...).
La nouvelle approche : le **serveur est TOUJOURS autoritaire**. Le client porteur envoie des `CmdUpdateTransportPosition` qui bougent l'objet côté serveur, puis `NetworkTransform Server-to-Client` propage aux autres clients. Beaucoup plus simple, plus robuste.
### Pourquoi désactiver NT local pour le porteur ?
Sans ça, le client porteur reçoit sa propre position serveur avec ~50ms de latence → son objet tremble. En désactivant le NT localement, son objet suit parfaitement ses mouvements (il est pilote par le Rigidbody local).
Quand il pose, on réactive NT → il reçoit alors la position "figée" du serveur (qui a fait `rb.isKinematic=true` + position snap).
### Pourquoi un gestionnaire séparé pour les câbles ?
`CablageReseau` est sur le prefab joueur : chaque joueur a sa propre instance. Impossible d'y mettre une SyncList globale. On crée donc un singleton à part qui porte l'état global.
### Pourquoi un composant séparé pour l'état power ?
Pour éviter de transformer `EtatEquipement` en `NetworkBehaviour` (ce qui casserait les équipements instanciés localement, par ex. pour les tests en éditeur). Composant séparé = découplage propre.
---
## Si ça ne marche pas
1. **Serveur crash au lancement** → probablement `GestionnaireCablesReseau` sans `NetworkIdentity` dans la scène. Vérifier.
2. **Câbles toujours pendants au reco** → regarder les logs `[GestionnaireCablesReseau]`. Si "Timeout", c'est que les refs PDU/port sont toujours null. Ouvrir un ticket.
3. **Portage local trembant**`SetNetworkTransformActif` pas appelé au ramassage. Vérifier logs console.
4. **Erreur `EntityStateMessage without authority`** → il reste un NT en Client-to-Server quelque part. Vérifier tous les prefabs.