Téléverser les fichiers vers "/"
This commit is contained in:
parent
fd4deaaa07
commit
b052a0ef10
94
DebugFalling.cs
Normal file
94
DebugFalling.cs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TEMPORAIRE - Debug pour diagnostiquer le problème de chute sous la map.
|
||||||
|
/// Ajouter sur le prefab PlayerCapsule, supprimer après diagnostic.
|
||||||
|
/// </summary>
|
||||||
|
public class DebugFalling : MonoBehaviour, IClientOnly
|
||||||
|
{
|
||||||
|
private CharacterController _cc;
|
||||||
|
private StarterAssets.FirstPersonController _fpc;
|
||||||
|
private float _lastLogTime = 0f;
|
||||||
|
private float _lastY;
|
||||||
|
private bool _wasFalling = false;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
_cc = GetComponent<CharacterController>();
|
||||||
|
_fpc = GetComponent<StarterAssets.FirstPersonController>();
|
||||||
|
_lastY = transform.position.y;
|
||||||
|
|
||||||
|
if (_cc != null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[DebugFall] CharacterController: center={_cc.center} height={_cc.height} radius={_cc.radius} skinWidth={_cc.skinWidth}");
|
||||||
|
Debug.Log($"[DebugFall] Layer joueur: {gameObject.layer} ({LayerMask.LayerToName(gameObject.layer)})");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_fpc != null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[DebugFall] FPC enabled={_fpc.enabled} GroundLayers={_fpc.GroundLayers.value} GroundedOffset={_fpc.GroundedOffset} GroundedRadius={_fpc.GroundedRadius}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test : y a-t-il un sol sous nous ?
|
||||||
|
RaycastHit hit;
|
||||||
|
if (Physics.Raycast(transform.position + Vector3.up * 0.5f, Vector3.down, out hit, 50f))
|
||||||
|
Debug.Log($"[DebugFall] Sol détecté: {hit.collider.gameObject.name} layer={LayerMask.LayerToName(hit.collider.gameObject.layer)} distance={hit.distance:F2} point={hit.point}");
|
||||||
|
else
|
||||||
|
Debug.Log("[DebugFall] AUCUN SOL DÉTECTÉ sous le joueur !");
|
||||||
|
|
||||||
|
// Test GroundLayers
|
||||||
|
if (_fpc != null)
|
||||||
|
{
|
||||||
|
int solLayer = LayerMask.NameToLayer("Sol");
|
||||||
|
bool solInclus = (_fpc.GroundLayers.value & (1 << solLayer)) != 0;
|
||||||
|
Debug.Log($"[DebugFall] Layer Sol ({solLayer}) inclus dans GroundLayers: {solInclus}");
|
||||||
|
|
||||||
|
// Test CheckSphere comme le fait le FPC
|
||||||
|
Vector3 spherePos = new Vector3(transform.position.x, transform.position.y - _fpc.GroundedOffset, transform.position.z);
|
||||||
|
bool grounded = Physics.CheckSphere(spherePos, _fpc.GroundedRadius, _fpc.GroundLayers, QueryTriggerInteraction.Ignore);
|
||||||
|
Debug.Log($"[DebugFall] CheckSphere grounded={grounded} spherePos={spherePos} radius={_fpc.GroundedRadius}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (_fpc == null || _cc == null) return;
|
||||||
|
|
||||||
|
float y = transform.position.y;
|
||||||
|
bool falling = y < _lastY - 0.01f;
|
||||||
|
|
||||||
|
// Log quand on commence à tomber
|
||||||
|
if (falling && !_wasFalling)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[DebugFall] DÉBUT CHUTE à Y={y:F2} pos={transform.position} Grounded={_fpc.Grounded} FPC.enabled={_fpc.enabled} CC.enabled={_cc.enabled} CC.isGrounded={_cc.isGrounded}");
|
||||||
|
|
||||||
|
// Vérifier ce qu'il y a sous nous
|
||||||
|
RaycastHit hit;
|
||||||
|
if (Physics.Raycast(transform.position, Vector3.down, out hit, 50f))
|
||||||
|
Debug.LogWarning($"[DebugFall] Sous nous: {hit.collider.gameObject.name} layer={LayerMask.LayerToName(hit.collider.gameObject.layer)} dist={hit.distance:F2}");
|
||||||
|
else
|
||||||
|
Debug.LogWarning("[DebugFall] RIEN sous le joueur !");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log continu pendant la chute (1x par seconde)
|
||||||
|
if (falling && Time.time - _lastLogTime > 1f)
|
||||||
|
{
|
||||||
|
_lastLogTime = Time.time;
|
||||||
|
Debug.LogWarning($"[DebugFall] EN CHUTE Y={y:F2} velocity.y={_cc.velocity.y:F2} Grounded={_fpc.Grounded} CC.isGrounded={_cc.isGrounded}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log quand on tombe trop bas
|
||||||
|
if (y < -5f && Time.time - _lastLogTime > 2f)
|
||||||
|
{
|
||||||
|
_lastLogTime = Time.time;
|
||||||
|
Debug.LogError($"[DebugFall] SOUS LA MAP Y={y:F2} téléportation de secours !");
|
||||||
|
// Téléporter au spawn de secours
|
||||||
|
_cc.enabled = false;
|
||||||
|
transform.position = new Vector3(0, 2, 0);
|
||||||
|
_cc.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_wasFalling = falling;
|
||||||
|
_lastY = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
422
MasterServerClient.cs
Normal file
422
MasterServerClient.cs
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Mirror;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MasterServerClient.cs - v6.6
|
||||||
|
///
|
||||||
|
/// v6.6 : Robustesse du heartbeat pour dedicated server
|
||||||
|
/// - Heartbeat passe de 30s a 10s par defaut (reduit la fenetre
|
||||||
|
/// ou le master server peut purger un serveur inactif)
|
||||||
|
/// - Sur reponse 404 (serveur inconnu), re-enregistrement AUTOMATIQUE
|
||||||
|
/// immediat avec les memes parametres que le register initial (au lieu
|
||||||
|
/// de juste reset les variables et attendre le prochain heartbeat)
|
||||||
|
/// - Memoire des parametres de registration pour pouvoir re-register
|
||||||
|
/// sans intervention exterieure
|
||||||
|
/// - Apres 3 echecs consecutifs, abandon et log d'erreur
|
||||||
|
///
|
||||||
|
/// v6.5 : Version originale
|
||||||
|
///
|
||||||
|
/// Usage :
|
||||||
|
/// Placer sur le meme GameObject que le NetworkManager (ou un singleton).
|
||||||
|
/// Configurer masterServerUrl dans l'Inspector.
|
||||||
|
/// </summary>
|
||||||
|
public class MasterServerClient : MonoBehaviour
|
||||||
|
{
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// CONFIGURATION
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
[Header("Master Server")]
|
||||||
|
[Tooltip("URL du master server (ex: http://192.168.1.50:8080)")]
|
||||||
|
public string masterServerUrl = "http://localhost:8080";
|
||||||
|
|
||||||
|
[Tooltip("Token d'authentification (doit correspondre au serveur)")]
|
||||||
|
public string token = "dcsim-2026-secret";
|
||||||
|
|
||||||
|
[Header("Heartbeat")]
|
||||||
|
[Tooltip("Intervalle du heartbeat en secondes (10s recommande pour dedicated)")]
|
||||||
|
public float heartbeatInterval = 10f;
|
||||||
|
|
||||||
|
[Tooltip("Nombre max d'echecs consecutifs avant abandon (reset si succes)")]
|
||||||
|
public int maxEchecsConsecutifs = 3;
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// ETAT
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
[HideInInspector] public string serverId = "";
|
||||||
|
[HideInInspector] public bool estEnregistre = false;
|
||||||
|
[HideInInspector] public List<ServerData> derniereListeServeurs = new List<ServerData>();
|
||||||
|
[HideInInspector] public bool requeteEnCours = false;
|
||||||
|
[HideInInspector] public string dernierStatut = "";
|
||||||
|
|
||||||
|
// Singleton
|
||||||
|
public static MasterServerClient Instance { get; private set; }
|
||||||
|
|
||||||
|
private Coroutine _heartbeatCoroutine;
|
||||||
|
private int _echecsConsecutifs = 0;
|
||||||
|
|
||||||
|
// v6.6 : memoire des parametres d'enregistrement pour re-register automatique
|
||||||
|
private string _dernierNom = "";
|
||||||
|
private int _dernierPort = 7777;
|
||||||
|
private int _dernierMaxJoueurs = 4;
|
||||||
|
private int _derniereLangue = 1;
|
||||||
|
private string _dernierMode = "Sandbox";
|
||||||
|
private string _derniereVersion = "v6.5g";
|
||||||
|
private bool _dernierMotDePasse = false;
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// MODELES DE DONNEES
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class ServerData
|
||||||
|
{
|
||||||
|
public string id;
|
||||||
|
public string nom;
|
||||||
|
public string ip;
|
||||||
|
public int port;
|
||||||
|
public int joueurs;
|
||||||
|
public int max_joueurs;
|
||||||
|
public int ping;
|
||||||
|
public int langue;
|
||||||
|
public string mode;
|
||||||
|
public string version;
|
||||||
|
public bool mot_de_passe;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
private class ServerListWrapper
|
||||||
|
{
|
||||||
|
public List<ServerData> servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
private class RegisterRequest
|
||||||
|
{
|
||||||
|
public string nom;
|
||||||
|
public int port;
|
||||||
|
public int max_joueurs;
|
||||||
|
public int langue;
|
||||||
|
public string mode;
|
||||||
|
public string version;
|
||||||
|
public bool mot_de_passe;
|
||||||
|
public string token;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
private class RegisterResponse
|
||||||
|
{
|
||||||
|
public string server_id;
|
||||||
|
public string status;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
private class HeartbeatRequest
|
||||||
|
{
|
||||||
|
public int joueurs;
|
||||||
|
public string token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// LIFECYCLE
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Instance = this;
|
||||||
|
Debug.Log($"[MasterServer] Awake → Instance initialisee, URL={masterServerUrl}");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
if (Instance == this)
|
||||||
|
Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
if (estEnregistre && !string.IsNullOrEmpty(serverId))
|
||||||
|
{
|
||||||
|
var request = new UnityWebRequest(
|
||||||
|
$"{masterServerUrl}/unregister/{serverId}", "DELETE");
|
||||||
|
request.timeout = 2;
|
||||||
|
request.SendWebRequest();
|
||||||
|
Debug.Log($"[MasterServer] Desenregistrement envoye ({serverId})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// API PUBLIQUE
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public void EnregistrerServeur(string nom, int port, int maxJoueurs,
|
||||||
|
int langue, string mode, string version, bool motDePasse)
|
||||||
|
{
|
||||||
|
// v6.6 : memorise les parametres pour pouvoir re-register en cas de 404
|
||||||
|
_dernierNom = nom;
|
||||||
|
_dernierPort = port;
|
||||||
|
_dernierMaxJoueurs = maxJoueurs;
|
||||||
|
_derniereLangue = langue;
|
||||||
|
_dernierMode = mode;
|
||||||
|
_derniereVersion = version;
|
||||||
|
_dernierMotDePasse = motDePasse;
|
||||||
|
|
||||||
|
StartCoroutine(Register(nom, port, maxJoueurs, langue, mode, version, motDePasse));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DesenregistrerServeur()
|
||||||
|
{
|
||||||
|
if (estEnregistre && !string.IsNullOrEmpty(serverId))
|
||||||
|
StartCoroutine(Unregister());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RecupererServeurs(System.Action<List<ServerData>, string> callback)
|
||||||
|
{
|
||||||
|
StartCoroutine(FetchServers(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void VerifierConnexion(System.Action<bool> callback)
|
||||||
|
{
|
||||||
|
StartCoroutine(CheckHealth(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
// COROUTINES HTTP
|
||||||
|
// ══════════════════════════════════════════════════
|
||||||
|
|
||||||
|
private IEnumerator Register(string nom, int port, int maxJoueurs,
|
||||||
|
int langue, string mode, string version, bool motDePasse)
|
||||||
|
{
|
||||||
|
requeteEnCours = true;
|
||||||
|
dernierStatut = "Enregistrement...";
|
||||||
|
|
||||||
|
var body = new RegisterRequest
|
||||||
|
{
|
||||||
|
nom = nom,
|
||||||
|
port = port,
|
||||||
|
max_joueurs = maxJoueurs,
|
||||||
|
langue = langue,
|
||||||
|
mode = mode,
|
||||||
|
version = version,
|
||||||
|
mot_de_passe = motDePasse,
|
||||||
|
token = token
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonUtility.ToJson(body);
|
||||||
|
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
|
||||||
|
|
||||||
|
var request = new UnityWebRequest($"{masterServerUrl}/register", "POST");
|
||||||
|
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
|
request.downloadHandler = new DownloadHandlerBuffer();
|
||||||
|
request.SetRequestHeader("Content-Type", "application/json");
|
||||||
|
request.timeout = 10;
|
||||||
|
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
if (request.result == UnityWebRequest.Result.Success)
|
||||||
|
{
|
||||||
|
var response = JsonUtility.FromJson<RegisterResponse>(request.downloadHandler.text);
|
||||||
|
serverId = response.server_id;
|
||||||
|
estEnregistre = true;
|
||||||
|
_echecsConsecutifs = 0;
|
||||||
|
dernierStatut = $"Enregistre ({serverId})";
|
||||||
|
Debug.Log($"[MasterServer] Serveur enregistre : {nom} → ID={serverId}");
|
||||||
|
|
||||||
|
// Demarrer le heartbeat (une seule coroutine active a la fois)
|
||||||
|
if (_heartbeatCoroutine != null)
|
||||||
|
StopCoroutine(_heartbeatCoroutine);
|
||||||
|
_heartbeatCoroutine = StartCoroutine(HeartbeatLoop());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dernierStatut = $"Erreur enregistrement : {request.error}";
|
||||||
|
Debug.LogWarning($"[MasterServer] Erreur register : {request.error} (code {request.responseCode})");
|
||||||
|
}
|
||||||
|
|
||||||
|
requeteEnCours = false;
|
||||||
|
request.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator Unregister()
|
||||||
|
{
|
||||||
|
requeteEnCours = true;
|
||||||
|
dernierStatut = "Desenregistrement...";
|
||||||
|
|
||||||
|
if (_heartbeatCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(_heartbeatCoroutine);
|
||||||
|
_heartbeatCoroutine = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = UnityWebRequest.Delete($"{masterServerUrl}/unregister/{serverId}");
|
||||||
|
request.timeout = 5;
|
||||||
|
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
if (request.result == UnityWebRequest.Result.Success)
|
||||||
|
{
|
||||||
|
Debug.Log($"[MasterServer] Serveur desenregistre : {serverId}");
|
||||||
|
dernierStatut = "Serveur retire de la liste";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[MasterServer] Erreur unregister : {request.error}");
|
||||||
|
dernierStatut = "Erreur desenregistrement (le cleanup nettoiera)";
|
||||||
|
}
|
||||||
|
|
||||||
|
estEnregistre = false;
|
||||||
|
serverId = "";
|
||||||
|
requeteEnCours = false;
|
||||||
|
request.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator HeartbeatLoop()
|
||||||
|
{
|
||||||
|
while (estEnregistre && !string.IsNullOrEmpty(serverId))
|
||||||
|
{
|
||||||
|
yield return new WaitForSecondsRealtime(heartbeatInterval);
|
||||||
|
|
||||||
|
if (!estEnregistre || string.IsNullOrEmpty(serverId))
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
int nbJoueurs = NetworkServer.active ? NetworkServer.connections.Count : 0;
|
||||||
|
|
||||||
|
var body = new HeartbeatRequest
|
||||||
|
{
|
||||||
|
joueurs = nbJoueurs,
|
||||||
|
token = token
|
||||||
|
};
|
||||||
|
|
||||||
|
string json = JsonUtility.ToJson(body);
|
||||||
|
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(json);
|
||||||
|
|
||||||
|
var request = new UnityWebRequest(
|
||||||
|
$"{masterServerUrl}/heartbeat/{serverId}", "PUT");
|
||||||
|
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
|
request.downloadHandler = new DownloadHandlerBuffer();
|
||||||
|
request.SetRequestHeader("Content-Type", "application/json");
|
||||||
|
request.timeout = 10;
|
||||||
|
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
if (request.result == UnityWebRequest.Result.Success)
|
||||||
|
{
|
||||||
|
// Reset du compteur d'echecs
|
||||||
|
_echecsConsecutifs = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_echecsConsecutifs++;
|
||||||
|
long code = request.responseCode;
|
||||||
|
string err = request.error;
|
||||||
|
Debug.LogWarning($"[MasterServer] Heartbeat echoue ({_echecsConsecutifs}/{maxEchecsConsecutifs}) : HTTP {code} - {err}");
|
||||||
|
|
||||||
|
// v6.6 : si 404, le master server nous a purges → on re-register AUTOMATIQUEMENT
|
||||||
|
// et IMMEDIATEMENT, sans attendre le prochain cycle de heartbeat
|
||||||
|
if (code == 404)
|
||||||
|
{
|
||||||
|
Debug.Log("[MasterServer] Serveur inconnu (404), re-enregistrement automatique...");
|
||||||
|
request.Dispose();
|
||||||
|
|
||||||
|
// Reset de l'etat
|
||||||
|
estEnregistre = false;
|
||||||
|
string ancienId = serverId;
|
||||||
|
serverId = "";
|
||||||
|
|
||||||
|
// Relance Register() avec les parametres memorises
|
||||||
|
yield return StartCoroutine(Register(
|
||||||
|
_dernierNom, _dernierPort, _dernierMaxJoueurs,
|
||||||
|
_derniereLangue, _dernierMode, _derniereVersion, _dernierMotDePasse
|
||||||
|
));
|
||||||
|
|
||||||
|
if (estEnregistre)
|
||||||
|
{
|
||||||
|
Debug.Log($"[MasterServer] Re-enregistrement OK : {ancienId} → {serverId}");
|
||||||
|
// Le HeartbeatLoop continue, mais on vient de demarrer un nouveau via Register.
|
||||||
|
// On sort de cette boucle pour eviter d'en avoir deux en parallele.
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"[MasterServer] Re-enregistrement echoue, abandon du heartbeat");
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apres trop d'echecs consecutifs (pas 404 mais reseau/timeout/etc), abandon
|
||||||
|
if (_echecsConsecutifs >= maxEchecsConsecutifs)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[MasterServer] Abandon du heartbeat apres {maxEchecsConsecutifs} echecs consecutifs");
|
||||||
|
estEnregistre = false;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator FetchServers(System.Action<List<ServerData>, string> callback)
|
||||||
|
{
|
||||||
|
requeteEnCours = true;
|
||||||
|
dernierStatut = "Recherche de serveurs...";
|
||||||
|
|
||||||
|
float startTime = Time.realtimeSinceStartup;
|
||||||
|
|
||||||
|
var request = UnityWebRequest.Get($"{masterServerUrl}/servers");
|
||||||
|
request.timeout = 10;
|
||||||
|
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
int pingMs = Mathf.RoundToInt((Time.realtimeSinceStartup - startTime) * 1000f);
|
||||||
|
|
||||||
|
if (request.result == UnityWebRequest.Result.Success)
|
||||||
|
{
|
||||||
|
string responseText = request.downloadHandler.text;
|
||||||
|
string wrapped = "{\"servers\":" + responseText + "}";
|
||||||
|
var wrapper = JsonUtility.FromJson<ServerListWrapper>(wrapped);
|
||||||
|
|
||||||
|
derniereListeServeurs = wrapper.servers ?? new List<ServerData>();
|
||||||
|
|
||||||
|
foreach (var srv in derniereListeServeurs)
|
||||||
|
srv.ping = pingMs;
|
||||||
|
|
||||||
|
dernierStatut = $"{derniereListeServeurs.Count} serveur(s) trouve(s)";
|
||||||
|
Debug.Log($"[MasterServer] {derniereListeServeurs.Count} serveurs recuperes (ping={pingMs}ms)");
|
||||||
|
|
||||||
|
callback?.Invoke(derniereListeServeurs, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string erreur = $"Erreur : {request.error}";
|
||||||
|
dernierStatut = erreur;
|
||||||
|
Debug.LogWarning($"[MasterServer] Erreur fetch : {request.error}");
|
||||||
|
callback?.Invoke(new List<ServerData>(), erreur);
|
||||||
|
}
|
||||||
|
|
||||||
|
requeteEnCours = false;
|
||||||
|
request.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator CheckHealth(System.Action<bool> callback)
|
||||||
|
{
|
||||||
|
var request = UnityWebRequest.Get($"{masterServerUrl}/health");
|
||||||
|
request.timeout = 5;
|
||||||
|
|
||||||
|
yield return request.SendWebRequest();
|
||||||
|
|
||||||
|
bool ok = request.result == UnityWebRequest.Result.Success;
|
||||||
|
callback?.Invoke(ok);
|
||||||
|
request.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
47
README_PATCHES_V2.md
Normal file
47
README_PATCHES_V2.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Patches v2 - Correction des problèmes du premier déploiement
|
||||||
|
|
||||||
|
## Ce qui est dans ce ZIP
|
||||||
|
|
||||||
|
### Scripts modifiés (2)
|
||||||
|
|
||||||
|
- **`MasterServerClient.cs` v6.6**
|
||||||
|
- Heartbeat passe de 30s → 10s par défaut
|
||||||
|
- Sur 404, re-registration automatique IMMÉDIATE (mémoise les paramètres)
|
||||||
|
- Compteur d'échecs consécutifs (abandon après 3)
|
||||||
|
|
||||||
|
- **`DebugFalling.cs`**
|
||||||
|
- Marqué `IClientOnly` → détruit au boot serveur, zéro log parasite
|
||||||
|
|
||||||
|
## Actions manuelles dans Unity (à faire AVANT de rebuild)
|
||||||
|
|
||||||
|
### 1. Remplacer les 2 scripts
|
||||||
|
Copie les 2 `.cs` dans `Assets/Scripts/`, écrase les fichiers existants.
|
||||||
|
|
||||||
|
### 2. Assigner le catalogue à BoutiqueReseau (Inspector)
|
||||||
|
|
||||||
|
Dans la scène `Datacenter_01` :
|
||||||
|
1. Sélectionne le GameObject qui porte le composant `BoutiqueReseau` (probablement sur le même GameObject que le `NetworkManager` ou sur un "Managers")
|
||||||
|
2. Dans l'Inspector, déplie le composant `BoutiqueReseau`
|
||||||
|
3. Champ **Catalogue** → clique sur le petit triangle pour déplier, mets la taille à X
|
||||||
|
4. Glisse-dépose tes `ArticleCatalogue` ScriptableObjects depuis le Project Window vers les slots
|
||||||
|
5. Sauvegarde la scène (Ctrl+S)
|
||||||
|
|
||||||
|
💡 **Pour retrouver tes articles plus rapidement** : sélectionne l'objet qui porte `UIBoutique` actuellement et regarde son champ `catalogue`, tu dois y voir tous les ScriptableObjects. Note-les ou fais un drag multi-sélection.
|
||||||
|
|
||||||
|
### 3. Rebuild
|
||||||
|
|
||||||
|
Build settings → Linux Dedicated Server → Build → déploie sur la Debian.
|
||||||
|
|
||||||
|
## Effet attendu
|
||||||
|
|
||||||
|
Après ces patches, plus de :
|
||||||
|
- ❌ `[MasterServer] Heartbeat échoué : HTTP/1.1 404 Not Found`
|
||||||
|
→ Résolu par re-registration automatique + intervalle réduit à 10s
|
||||||
|
|
||||||
|
- ❌ `[BoutiqueReseau] Article introuvable : Baie 42U`
|
||||||
|
→ Résolu par l'assignation directe du catalogue dans l'Inspector
|
||||||
|
|
||||||
|
- ❌ Spam de logs `[DebugFall] ...`
|
||||||
|
→ Résolu par le marqueur IClientOnly
|
||||||
|
|
||||||
|
Logs serveur propres = monitoring plus efficace.
|
||||||
Loading…
x
Reference in New Issue
Block a user