extraction patch v4

This commit is contained in:
Stephane MAURO 2026-04-18 08:12:27 +00:00
parent d6829d7402
commit de1783815c
22 changed files with 530 additions and 0 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1 @@
{"root":[{"assemblyName":"Assembly-CSharp","nameSpace":"Mirror","className":"GeneratedNetworkCode","methodName":"InitReadWriters","loadTypes":1,"isUnityClass":false},{"assemblyName":"Cinemachine","nameSpace":"Cinemachine","className":"CinemachineStoryboard","methodName":"InitializeModule","loadTypes":0,"isUnityClass":false},{"assemblyName":"Cinemachine","nameSpace":"Cinemachine","className":"CinemachineCore","methodName":"InitializeModule","loadTypes":0,"isUnityClass":false},{"assemblyName":"Cinemachine","nameSpace":"Cinemachine","className":"UpdateTracker","methodName":"InitializeModule","loadTypes":0,"isUnityClass":false},{"assemblyName":"Cinemachine","nameSpace":"Cinemachine","className":"CinemachineImpulseManager","methodName":"InitializeModule","loadTypes":0,"isUnityClass":false},{"assemblyName":"Cinemachine","nameSpace":"Cinemachine.PostFX","className":"CinemachineVolumeSettings","methodName":"InitializeModule","loadTypes":0,"isUnityClass":false},{"assemblyName":"glTFast","nameSpace":"","className":"$BurstDirectCallInitializer","methodName":"Initialize","loadTypes":2,"isUnityClass":false},{"assemblyName":"Mirror.Authenticators","nameSpace":"Mirror.Authenticators","className":"UniqueNameAuthenticator","methodName":"ResetStatics","loadTypes":0,"isUnityClass":false},{"assemblyName":"Mirror.Authenticators","nameSpace":"Mirror","className":"GeneratedNetworkCode","methodName":"InitReadWriters","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror.Components","nameSpace":"Mirror","className":"GeneratedNetworkCode","methodName":"InitReadWriters","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkClient","methodName":"Shutdown","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkDiagnostics","methodName":"ResetStatics","loadTypes":0,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkIdentity","methodName":"ResetStatics","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkLoop","methodName":"ResetStatics","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkLoop","methodName":"RuntimeInitializeOnLoad","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkManager","methodName":"ResetStatics","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkServer","methodName":"Shutdown","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"NetworkTime","methodName":"ResetStatics","loadTypes":0,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"ThreadLog","methodName":"Initialize","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror","nameSpace":"Mirror","className":"GeneratedNetworkCode","methodName":"InitReadWriters","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror.Examples","nameSpace":"Mirror.Examples.MultipleMatch","className":"CanvasController","methodName":"ResetStatics","loadTypes":1,"isUnityClass":false},{"assemblyName":"Mirror.Examples","nameSpace":"Mirror","className":"GeneratedNetworkCode","methodName":"InitReadWriters","loadTypes":1,"isUnityClass":false},{"assemblyName":"Unity.Burst","nameSpace":"","className":"$BurstDirectCallInitializer","methodName":"Initialize","loadTypes":2,"isUnityClass":true},{"assemblyName":"Unity.Collections","nameSpace":"","className":"$BurstDirectCallInitializer","methodName":"Initialize","loadTypes":2,"isUnityClass":true},{"assemblyName":"Unity.InputSystem","nameSpace":"UnityEngine.InputSystem","className":"InputSystem","methodName":"RunInitializeInPlayer","loadTypes":4,"isUnityClass":true},{"assemblyName":"Unity.InputSystem","nameSpace":"UnityEngine.InputSystem","className":"InputSystem","methodName":"RunInitialUpdate","loadTypes":1,"isUnityClass":true},{"assemblyName":"Unity.InputSystem","nameSpace":"UnityEngine.InputSystem.UI","className":"InputSystemUIInputModule","methodName":"ResetDefaultActions","loadTypes":4,"isUnityClass":true},{"assemblyName":"Unity.RenderPipelines.Core.Runtime","nameSpace":"UnityEngine.Experimental.Rendering","className":"XRSystem","methodName":"XRSystemInit","loadTypes":3,"isUnityClass":true},{"assemblyName":"Unity.RenderPipelines.Core.Runtime","nameSpace":"UnityEngine.Rendering","className":"DebugUpdater","methodName":"RuntimeInit","loadTypes":0,"isUnityClass":true},{"assemblyName":"Unity.VisualScripting.Core","nameSpace":"Unity.VisualScripting","className":"RuntimeVSUsageUtility","methodName":"RuntimeInitializeOnLoadBeforeSceneLoad","loadTypes":1,"isUnityClass":true}]}

View File

@ -0,0 +1 @@
{"names":["UnityEngine.dll","UnityEngine.AIModule.dll","UnityEngine.AccessibilityModule.dll","UnityEngine.AndroidJNIModule.dll","UnityEngine.AnimationModule.dll","UnityEngine.AssetBundleModule.dll","UnityEngine.AudioModule.dll","UnityEngine.ClothModule.dll","UnityEngine.ClusterInputModule.dll","UnityEngine.ClusterRendererModule.dll","UnityEngine.ContentLoadModule.dll","UnityEngine.CoreModule.dll","UnityEngine.CrashReportingModule.dll","UnityEngine.DSPGraphModule.dll","UnityEngine.DirectorModule.dll","UnityEngine.GIModule.dll","UnityEngine.GameCenterModule.dll","UnityEngine.GridModule.dll","UnityEngine.HotReloadModule.dll","UnityEngine.IMGUIModule.dll","UnityEngine.ImageConversionModule.dll","UnityEngine.InputModule.dll","UnityEngine.InputLegacyModule.dll","UnityEngine.JSONSerializeModule.dll","UnityEngine.LocalizationModule.dll","UnityEngine.ParticleSystemModule.dll","UnityEngine.PerformanceReportingModule.dll","UnityEngine.PhysicsModule.dll","UnityEngine.Physics2DModule.dll","UnityEngine.ProfilerModule.dll","UnityEngine.PropertiesModule.dll","UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll","UnityEngine.ScreenCaptureModule.dll","UnityEngine.SharedInternalsModule.dll","UnityEngine.SpriteMaskModule.dll","UnityEngine.SpriteShapeModule.dll","UnityEngine.StreamingModule.dll","UnityEngine.SubstanceModule.dll","UnityEngine.SubsystemsModule.dll","UnityEngine.TLSModule.dll","UnityEngine.TerrainModule.dll","UnityEngine.TerrainPhysicsModule.dll","UnityEngine.TextCoreFontEngineModule.dll","UnityEngine.TextCoreTextEngineModule.dll","UnityEngine.TextRenderingModule.dll","UnityEngine.TilemapModule.dll","UnityEngine.UIModule.dll","UnityEngine.UIElementsModule.dll","UnityEngine.UmbraModule.dll","UnityEngine.UnityAnalyticsModule.dll","UnityEngine.UnityAnalyticsCommonModule.dll","UnityEngine.UnityConnectModule.dll","UnityEngine.UnityCurlModule.dll","UnityEngine.UnityTestProtocolModule.dll","UnityEngine.UnityWebRequestModule.dll","UnityEngine.UnityWebRequestAssetBundleModule.dll","UnityEngine.UnityWebRequestAudioModule.dll","UnityEngine.UnityWebRequestTextureModule.dll","UnityEngine.UnityWebRequestWWWModule.dll","UnityEngine.VFXModule.dll","UnityEngine.VRModule.dll","UnityEngine.VehiclesModule.dll","UnityEngine.VideoModule.dll","UnityEngine.VirtualTexturingModule.dll","UnityEngine.WindModule.dll","UnityEngine.XRModule.dll","Assembly-CSharp.dll","glTFast.dots.dll","Unity.RenderPipelines.Core.Runtime.dll","Unity.ProBuilder.Stl.dll","Unity.ProBuilder.Csg.dll","Unity.RenderPipelines.Universal.Config.Runtime.dll","Unity.VisualScripting.Flow.dll","Telepathy.dll","glTFast.Newtonsoft.dll","Unity.RenderPipelines.Core.ShaderLibrary.dll","Mirror.Examples.dll","Unity.Collections.dll","Unity.ProBuilder.Poly2Tri.dll","glTFast.Documentation.Examples.dll","Unity.TextMeshPro.dll","kcp2k.dll","Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll","Unity.RenderPipelines.Universal.Runtime.dll","Unity.Burst.dll","Unity.ProBuilder.dll","Mirror.dll","Unity.VisualScripting.Core.dll","Mirror.Transports.dll","UnityEngine.UI.dll","Mirror.Components.dll","glTFast.Export.dll","Unity.RenderPipelines.Universal.2D.Internal.dll","Unity.RenderPipeline.Universal.ShaderLibrary.dll","Unity.Timeline.dll","Unity.InputSystem.dll","SimpleWebTransport.dll","Unity.InputSystem.ForUI.dll","Mirror.Authenticators.dll","glTFast.dll","Unity.ProBuilder.KdTree.dll","Unity.Mathematics.dll","Unity.RenderPipelines.Universal.Shaders.dll","Unity.VisualScripting.State.dll","Cinemachine.dll","Unity.Collections.LowLevel.ILSupport.dll","Mirror.BouncyCastle.Cryptography.dll","Unity.VisualScripting.Antlr3.Runtime.dll","Unity.Burst.Unsafe.dll","Newtonsoft.Json.dll"],"types":[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16]}

View File

@ -0,0 +1,2 @@
MAURO Stéphane
DatacenterSim_Alpha

View File

@ -0,0 +1,6 @@
gfx-enable-gfx-jobs=1
gfx-enable-native-gfx-jobs=1
wait-for-native-debugger=0
hdr-display-enabled=0
gc-max-time-slice=3
build-guid=dda67375c968463c8faf660d4f2e44c6

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,100 @@
# Patches v4 - VRAI fix du BoutonPower sur dedicated server
## ⚠️ Remplace les patches v3 qui étaient partiellement corrects
La v3 (patch de CableAlimentation + CableRJ45) n'était PAS la cause racine.
Le patch de v3 reste valide (évite des WARNINGS visuels), mais le vrai bug
était ailleurs.
## 🎯 La vraie cause racine
`CablageReseau.TrouverPortAlimentation()` cherchait les équipements dans
**`NetworkClient.spawned`** au lieu de `NetworkServer.spawned`.
Sur un dedicated server (serveur pur, pas host), `NetworkClient` n'est pas
actif, donc `NetworkClient.spawned` est **vide**. Résultat :
- `TrouverPortAlimentation()` retournait toujours `null`
- La condition `if (prise != null && port != null && ...)` était fausse
- `port.Connecter()` n'était JAMAIS appelé
- `port.estConnecte` restait à `false`
- `BoutonPower` refusait d'allumer l'équipement
Le message `[Serveur] Câble alim créé` était trompeur parce qu'il apparaît
AVANT la vérification, juste au moment de l'entrée dans la méthode.
## ✅ Le fix
Ajout d'un helper universel `TrouverGameObjectNetId(netId)` dans `CablageReseau.cs`
qui cherche dans le bon dictionnaire selon le contexte :
- `NetworkServer.spawned` si on est serveur (dedicated OU host)
- `NetworkClient.spawned` si on est purement client
- `null` sinon
Les 3 helpers `TrouverPortRJ45`, `TrouverPriseC13`, `TrouverPortAlimentation`
utilisent maintenant ce helper universel.
## 📄 Script patché (1)
- **`CablageReseau.cs`** — helper universel + refacto des 3 méthodes Trouver*
## 🚀 Actions à faire
### 1. Remplacer le script dans Unity
Copie `Scripts_Modifies/CablageReseau.cs` dans `Assets/Scripts/`, écrase
l'existant.
### 2. Rebuild Dedicated Server
File → Build Settings → Dedicated Server Linux → Build.
⚠️ **Astuce** : si tu veux t'assurer que le build prend bien les derniers
scripts, supprime le contenu du dossier de build avant de rebuilder. Unity
fait parfois du cache agressif.
### 3. Redéploie sur la Debian
```bash
# Arrêter le service
sudo systemctl stop datacentersim-server
# Remplacer le dossier
# (ou scp -r depuis ton Windows)
# Relancer
sudo systemctl start datacentersim-server
sudo journalctl -u datacentersim-server -f
```
### 4. Test
1. Commande PDU + serveur 1U
2. Branche l'alim PDU → serveur (même procédure qu'avant)
3. Appuie sur Power → **DOIT S'ALLUMER**
Attendu dans les logs serveur : plus de `BoutonPower: aucun câble
d'alimentation branché !`.
## 🐛 Bug annexe détecté (pour plus tard)
Les câbles RJ45 ne font RIEN côté serveur actuellement (la méthode
`CmdCreerCableRJ45` broadcast juste aux clients sans créer d'état serveur).
Conséquence : les logiques type "flux de paquets", "consommation bande
passante", etc. ne tourneront pas si elles dépendent de l'existence des
câbles RJ45 côté serveur. À réfléchir dans une future refonte quand tu
implémenteras ce genre de features.
Pour l'instant c'est OK, le multi fonctionne et les câbles s'affichent
bien chez tous les clients via le Rpc.
## 🖥️ Rappel Ctrl+C qui ne marche pas
Ajoute `-batchmode -nographics` aux arguments quand tu lances manuellement :
```bash
./DatacenterSim.x86_64 -server -port 7777 -batchmode -nographics
```
Ces flags forcent Unity à gérer proprement SIGINT. Ton service systemd les
utilise déjà (ils sont dans `datacentersim-server.service`).

View File

@ -0,0 +1,420 @@
using UnityEngine;
using System.Collections.Generic;
using Mirror;
/// <summary>
/// CablageReseau.cs - v6.7 Multijoueur
///
/// v6.7 : sync longueur toron
/// - CmdSyncLongueurToron : met à jour la SyncVar longueur sur le serveur
/// après consommation ou restitution de câble. Propage automatiquement
/// à tous les clients via le hook de ToronNetworkSync.
///
/// v6.4 : sync câbles RJ45 + alimentation + interrupteur prise
///
/// SETUP : Ajouter sur le prefab PlayerCapsule.
/// </summary>
public class CablageReseau : NetworkBehaviour
{
// ════════════════════════════════════════════════════════════
// CÂBLES RJ45
// ════════════════════════════════════════════════════════════
[Command]
public void CmdCreerCableRJ45(uint equipSourceNetId, int portSourceIndex,
uint equipDestNetId, int portDestIndex,
Color couleur, float longueur)
{
Debug.Log($"[Serveur] Câble RJ45 créé : equip {equipSourceNetId} port {portSourceIndex} → equip {equipDestNetId} port {portDestIndex}");
RpcCreerCableRJ45(equipSourceNetId, portSourceIndex, equipDestNetId, portDestIndex, couleur, longueur);
}
[ClientRpc]
void RpcCreerCableRJ45(uint equipSourceNetId, int portSourceIndex,
uint equipDestNetId, int portDestIndex,
Color couleur, float longueur)
{
if (isLocalPlayer) return;
PortRJ45 portSource = TrouverPortRJ45(equipSourceNetId, portSourceIndex);
PortRJ45 portDest = TrouverPortRJ45(equipDestNetId, portDestIndex);
if (portSource == null || portDest == null)
{
Debug.LogWarning($"[CablageReseau] Ports introuvables pour câble RJ45 distant");
return;
}
List<PointAccroche> chemin = ConstruireCheminAutoLocal(
portSource.GetPointConnexion(), portDest.GetPointConnexion());
string nom = "Cable_" + portSource.nomPort + "_vers_" + portDest.nomPort + "_distant";
GameObject cableObj = new GameObject(nom);
CableRJ45 cable = cableObj.AddComponent<CableRJ45>();
cable.Initialiser(portSource, portDest, chemin, couleur, longueur, null);
portSource.Connecter(portDest, cable);
portDest.Connecter(portSource, cable);
Debug.Log($"[CablageReseau] Câble RJ45 distant créé : {portSource.nomPort} → {portDest.nomPort}");
}
[Command]
public void CmdSupprimerCableRJ45(uint equipSourceNetId, int portSourceIndex,
uint equipDestNetId, int portDestIndex)
{
Debug.Log($"[Serveur] Câble RJ45 supprimé");
RpcSupprimerCableRJ45(equipSourceNetId, portSourceIndex, equipDestNetId, portDestIndex);
}
[ClientRpc]
void RpcSupprimerCableRJ45(uint equipSourceNetId, int portSourceIndex,
uint equipDestNetId, int portDestIndex)
{
if (isLocalPlayer) return;
PortRJ45 portSource = TrouverPortRJ45(equipSourceNetId, portSourceIndex);
PortRJ45 portDest = TrouverPortRJ45(equipDestNetId, portDestIndex);
if (portSource != null && portSource.cable != null)
{
portSource.cable.SupprimerComplet();
}
else if (portDest != null && portDest.cable != null)
{
portDest.cable.SupprimerComplet();
}
Debug.Log("[CablageReseau] Câble RJ45 distant supprimé");
}
// ════════════════════════════════════════════════════════════
// SYNC LONGUEUR TORON (v6.7)
// ════════════════════════════════════════════════════════════
/// <summary>
/// v6.7 : Met à jour la SyncVar longueur du toron côté serveur.
/// Appelé par CableManager après consommation ou restitution de câble.
/// La SyncVar de ToronNetworkSync propage automatiquement la nouvelle
/// longueur à TOUS les clients via le hook.
/// </summary>
[Command]
public void CmdSyncLongueurToron(uint toronNetId, float longueurRestante, float longueurTotale)
{
if (!NetworkServer.spawned.ContainsKey(toronNetId)) return;
var obj = NetworkServer.spawned[toronNetId];
if (obj == null) return;
ToronNetworkSync sync = obj.GetComponent<ToronNetworkSync>();
if (sync != null)
{
sync.ServerSetLongueur(longueurTotale, longueurRestante);
Debug.Log($"[Serveur] Longueur toron sync : {obj.name} → {longueurRestante:F1}m / {longueurTotale:F1}m");
}
}
// ════════════════════════════════════════════════════════════
// CÂBLES ALIMENTATION
// ════════════════════════════════════════════════════════════
[Command]
public void CmdCreerCableAlim(uint pduNetId, int indexPrise,
uint equipNetId, int indexPortAlim,
Color couleur)
{
Debug.Log($"[Serveur] Câble alim créé : PDU {pduNetId} prise {indexPrise} → equip {equipNetId} port {indexPortAlim}");
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
PortAlimentation port = TrouverPortAlimentation(equipNetId, indexPortAlim);
if (prise != null && port != null && !prise.estConnectee)
{
GameObject cableObj = new GameObject("CableAlim_serveur");
CableAlimentation cable = cableObj.AddComponent<CableAlimentation>();
cable.couleurCable = couleur;
cable.Initialiser(prise, port);
prise.Connecter(cable, port);
port.Connecter(cable, prise);
}
RpcCreerCableAlim(pduNetId, indexPrise, equipNetId, indexPortAlim, couleur);
}
[ClientRpc]
void RpcCreerCableAlim(uint pduNetId, int indexPrise,
uint equipNetId, int indexPortAlim,
Color couleur)
{
if (isLocalPlayer) return;
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
PortAlimentation port = TrouverPortAlimentation(equipNetId, indexPortAlim);
if (prise == null || port == null)
{
Debug.LogWarning("[CablageReseau] Prise/Port introuvables pour câble alim distant");
return;
}
GameObject cableObj = new GameObject("CableAlim_distant");
CableAlimentation cable = cableObj.AddComponent<CableAlimentation>();
cable.couleurCable = couleur;
cable.Initialiser(prise, port);
prise.Connecter(cable, port);
port.Connecter(cable, prise);
Debug.Log($"[CablageReseau] Câble alim distant créé : PDU prise #{indexPrise} → {port.nomPort}");
}
[Command]
public void CmdSupprimerCableAlim(uint pduNetId, int indexPrise,
uint equipNetId, int indexPortAlim)
{
Debug.Log($"[Serveur] Câble alim supprimé");
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
if (prise != null && prise.cableBranche != null)
prise.cableBranche.Supprimer();
RpcSupprimerCableAlim(pduNetId, indexPrise, equipNetId, indexPortAlim);
}
[ClientRpc]
void RpcSupprimerCableAlim(uint pduNetId, int indexPrise,
uint equipNetId, int indexPortAlim)
{
if (isLocalPlayer) return;
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
if (prise != null && prise.cableBranche != null)
{
prise.cableBranche.Supprimer();
}
else
{
PortAlimentation port = TrouverPortAlimentation(equipNetId, indexPortAlim);
if (port != null && port.cableBranche != null)
port.cableBranche.Supprimer();
}
Debug.Log("[CablageReseau] Câble alim distant supprimé");
}
// ════════════════════════════════════════════════════════════
// INTERRUPTEUR PRISE
// ════════════════════════════════════════════════════════════
[Command]
public void CmdBasculerPrise(uint pduNetId, int indexPrise)
{
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
if (prise != null)
prise.BasculerInterrupteur();
RpcBasculerPrise(pduNetId, indexPrise);
}
[ClientRpc]
void RpcBasculerPrise(uint pduNetId, int indexPrise)
{
if (isLocalPlayer) return;
PriseC13 prise = TrouverPriseC13(pduNetId, indexPrise);
if (prise != null)
prise.BasculerInterrupteur();
}
// ════════════════════════════════════════════════════════════
// HELPERS — Recherche de composants par netId + index
// ════════════════════════════════════════════════════════════
// ════════════════════════════════════════════════════════════
// HELPER UNIVERSEL : trouver un NetworkIdentity spawned
// Utilise NetworkServer.spawned cote serveur (dedicated inclus),
// NetworkClient.spawned cote client. Les deux sont remplis en mode Host.
// Sans ce helper, les [Command] executees sur un dedicated server ne
// trouvaient aucun objet car NetworkClient.spawned est vide sans client local.
// ════════════════════════════════════════════════════════════
private static GameObject TrouverGameObjectNetId(uint netId)
{
if (Mirror.NetworkServer.active &&
Mirror.NetworkServer.spawned.TryGetValue(netId, out var ni1) &&
ni1 != null)
return ni1.gameObject;
if (Mirror.NetworkClient.active &&
Mirror.NetworkClient.spawned.TryGetValue(netId, out var ni2) &&
ni2 != null)
return ni2.gameObject;
return null;
}
private PortRJ45 TrouverPortRJ45(uint equipNetId, int portIndex)
{
GameObject equipGO = TrouverGameObjectNetId(equipNetId);
if (equipGO == null) return null;
PortRJ45[] ports = equipGO.GetComponentsInChildren<PortRJ45>();
foreach (var port in ports)
{
if (port.numeroPort == portIndex)
return port;
}
if (portIndex >= 0 && portIndex < ports.Length)
return ports[portIndex];
return null;
}
private PriseC13 TrouverPriseC13(uint pduNetId, int indexPrise)
{
GameObject pduGO = TrouverGameObjectNetId(pduNetId);
if (pduGO == null) return null;
PDU pdu = pduGO.GetComponent<PDU>();
if (pdu != null && indexPrise >= 0 && indexPrise < pdu.prises.Count)
return pdu.prises[indexPrise];
PriseC13[] prises = pduGO.GetComponentsInChildren<PriseC13>();
foreach (var p in prises)
if (p.indexPrise == indexPrise) return p;
return null;
}
private PortAlimentation TrouverPortAlimentation(uint equipNetId, int indexPort)
{
GameObject equipGO = TrouverGameObjectNetId(equipNetId);
if (equipGO == null) return null;
PortAlimentation[] ports = equipGO.GetComponentsInChildren<PortAlimentation>();
if (indexPort >= 0 && indexPort < ports.Length)
return ports[indexPort];
return null;
}
private List<PointAccroche> ConstruireCheminAutoLocal(Vector3 posSource, Vector3 posDest)
{
List<PointAccroche> chemin = new List<PointAccroche>();
PointAccroche[] tousPoints = FindObjectsOfType<PointAccroche>();
if (tousPoints.Length == 0) return chemin;
PointAccroche ptDepart = null;
float bestDistDepart = 3f;
foreach (var p in tousPoints)
{
float d = Vector3.Distance(posSource, p.GetPosition());
if (d < bestDistDepart) { bestDistDepart = d; ptDepart = p; }
}
PointAccroche ptArrivee = null;
float bestDistArrivee = 3f;
foreach (var p in tousPoints)
{
float d = Vector3.Distance(posDest, p.GetPosition());
if (d < bestDistArrivee) { bestDistArrivee = d; ptArrivee = p; }
}
if (ptDepart == null || ptArrivee == null) return chemin;
if (ptDepart == ptArrivee) { chemin.Add(ptDepart); return chemin; }
float distanceVoisinage = 1.5f;
Dictionary<PointAccroche, float> gScore = new Dictionary<PointAccroche, float>();
Dictionary<PointAccroche, PointAccroche> cameFrom = new Dictionary<PointAccroche, PointAccroche>();
HashSet<PointAccroche> closedSet = new HashSet<PointAccroche>();
List<PointAccroche> openSet = new List<PointAccroche>();
gScore[ptDepart] = 0;
openSet.Add(ptDepart);
int maxIter = 500;
int iter = 0;
while (openSet.Count > 0 && iter < maxIter)
{
iter++;
PointAccroche current = null;
float bestF = float.MaxValue;
foreach (var n in openSet)
{
float g = gScore.ContainsKey(n) ? gScore[n] : float.MaxValue;
float f = g + Vector3.Distance(n.GetPosition(), ptArrivee.GetPosition());
if (f < bestF) { bestF = f; current = n; }
}
if (current == null) break;
if (current == ptArrivee)
{
List<PointAccroche> result = new List<PointAccroche> { current };
while (cameFrom.ContainsKey(current))
{
current = cameFrom[current];
result.Insert(0, current);
}
return result;
}
openSet.Remove(current);
closedSet.Add(current);
foreach (var autre in tousPoints)
{
if (autre == current || closedSet.Contains(autre)) continue;
if (Vector3.Distance(current.GetPosition(), autre.GetPosition()) > distanceVoisinage) continue;
float tentG = gScore[current] + Vector3.Distance(current.GetPosition(), autre.GetPosition());
if (!openSet.Contains(autre)) openSet.Add(autre);
else if (gScore.ContainsKey(autre) && tentG >= gScore[autre]) continue;
cameFrom[autre] = current;
gScore[autre] = tentG;
}
}
chemin.Add(ptDepart);
chemin.Add(ptArrivee);
return chemin;
}
// ════════════════════════════════════════════════════════════
// HELPERS PUBLICS
// ════════════════════════════════════════════════════════════
public static uint GetEquipNetId(PortRJ45 port)
{
if (port == null) return 0;
NetworkIdentity netId = port.GetComponentInParent<NetworkIdentity>();
return netId != null ? netId.netId : 0;
}
public static uint GetPDUNetId(PriseC13 prise)
{
if (prise == null || prise.pduParent == null) return 0;
NetworkIdentity netId = prise.pduParent.GetComponent<NetworkIdentity>();
return netId != null ? netId.netId : 0;
}
public static uint GetEquipNetIdFromPortAlim(PortAlimentation port)
{
if (port == null || port.equipement == null) return 0;
NetworkIdentity netId = port.equipement.GetComponent<NetworkIdentity>();
return netId != null ? netId.netId : 0;
}
public static int GetPortAlimIndex(PortAlimentation port)
{
if (port == null || port.equipement == null) return 0;
PortAlimentation[] ports = port.equipement.GetComponentsInChildren<PortAlimentation>();
for (int i = 0; i < ports.Length; i++)
if (ports[i] == port) return i;
return 0;
}
}