using System; using System.Collections; using System.IO; using UnityEngine; using UnityEngine.Networking; using Newtonsoft.Json; public class AvatarDataDownloader : MonoBehaviour { [Header("Server Configuration")] [SerializeField] private string serverHost = "127.0.0.1"; [SerializeField] private int serverPort = 8080; [SerializeField] private string targetPlayer = "player1"; // Which player data to fetch [Header("Download Configuration")] [SerializeField] private bool autoDownload = true; [SerializeField] private float downloadInterval = 0.1f; // How often to fetch data (in seconds) [SerializeField] private string localFileName = ""; // Leave empty to use targetPlayer name [Header("Debug")] [SerializeField] private bool enableDebugMode = false; [SerializeField] private bool showConnectionStatus = true; private string syncFilesPath; private string outputFilePath; private Coroutine downloadCoroutine; private bool isConnected = false; private float lastSuccessfulDownload = 0f; private int totalDownloads = 0; private int successfulDownloads = 0; // Connection status public bool IsConnected => isConnected; public string ServerUrl => $"http://{serverHost}:{serverPort}"; public float LastDownloadTime => lastSuccessfulDownload; public float SuccessRate => totalDownloads > 0 ? (float)successfulDownloads / totalDownloads : 0f; void Start() { // Set up file paths syncFilesPath = Path.Combine(Application.dataPath, "Sync-Files"); if (!Directory.Exists(syncFilesPath)) { Directory.CreateDirectory(syncFilesPath); } // Determine output file name string fileName = string.IsNullOrEmpty(localFileName) ? $"{targetPlayer}.json" : localFileName; outputFilePath = Path.Combine(syncFilesPath, fileName); Debug.Log($"Avatar Data Downloader initialized"); Debug.Log($"Server: {ServerUrl}"); Debug.Log($"Target Player: {targetPlayer}"); Debug.Log($"Output File: {outputFilePath}"); // Start downloading if auto-download is enabled if (autoDownload) { StartDownload(); } // Test connection StartCoroutine(TestConnection()); } void OnValidate() { // Ensure valid values if (downloadInterval < 0.01f) downloadInterval = 0.01f; if (serverPort < 1 || serverPort > 65535) serverPort = 8080; } public void StartDownload() { if (downloadCoroutine == null) { downloadCoroutine = StartCoroutine(DownloadLoop()); Debug.Log("Avatar download started"); } } public void StopDownload() { if (downloadCoroutine != null) { StopCoroutine(downloadCoroutine); downloadCoroutine = null; Debug.Log("Avatar download stopped"); } } IEnumerator TestConnection() { string url = $"{ServerUrl}/status"; using (UnityWebRequest request = UnityWebRequest.Get(url)) { request.timeout = 5; // 5 second timeout for connection test yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { isConnected = true; if (showConnectionStatus) { Debug.Log($"Successfully connected to avatar sync server at {ServerUrl}"); } if (enableDebugMode) { Debug.Log($"Server status: {request.downloadHandler.text}"); } } else { isConnected = false; if (showConnectionStatus) { Debug.LogWarning($"Failed to connect to avatar sync server at {ServerUrl}: {request.error}"); } } } } IEnumerator DownloadLoop() { while (true) { yield return StartCoroutine(FetchPlayerData()); yield return new WaitForSeconds(downloadInterval); } } IEnumerator FetchPlayerData() { string url = $"{ServerUrl}/{targetPlayer}"; totalDownloads++; using (UnityWebRequest request = UnityWebRequest.Get(url)) { request.timeout = 10; // 10 second timeout yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { // Try to validate JSON structure bool isValidData = false; float dataTimestamp = 0f; try { var avatarData = JsonConvert.DeserializeObject(request.downloadHandler.text); isValidData = avatarData != null; dataTimestamp = avatarData?.timestamp ?? 0f; } catch (Exception e) { Debug.LogError($"Error parsing avatar data for {targetPlayer}: {e.Message}"); isValidData = false; } if (isValidData) { // Write to local file File.WriteAllText(outputFilePath, request.downloadHandler.text); successfulDownloads++; lastSuccessfulDownload = Time.time; isConnected = true; if (enableDebugMode) { Debug.Log($"Successfully fetched and saved data for {targetPlayer}. Timestamp: {dataTimestamp}"); } } else { if (enableDebugMode) { Debug.LogWarning($"Received invalid avatar data for {targetPlayer}"); } } } else { isConnected = false; if (enableDebugMode) { Debug.LogWarning($"Failed to fetch data for {targetPlayer}: {request.error}"); } } } } // Public methods for runtime control public void SetServerAddress(string host, int port) { serverHost = host; serverPort = port; // Test new connection StartCoroutine(TestConnection()); } public void SetTargetPlayer(string player) { targetPlayer = player; // Update output file path string fileName = string.IsNullOrEmpty(localFileName) ? $"{targetPlayer}.json" : localFileName; outputFilePath = Path.Combine(syncFilesPath, fileName); } public void ManualDownload() { if (gameObject.activeInHierarchy) { StartCoroutine(FetchPlayerData()); } } // Get current stats for UI display public string GetDownloadStats() { return $"Connected: {isConnected}\n" + $"Success Rate: {(SuccessRate * 100):F1}%\n" + $"Total Downloads: {totalDownloads}\n" + $"Last Download: {(Time.time - lastSuccessfulDownload):F1}s ago"; } // Check if the output file exists and has recent data public bool HasRecentData(float maxAgeSeconds = 5f) { if (!File.Exists(outputFilePath)) return false; try { FileInfo fileInfo = new FileInfo(outputFilePath); return (DateTime.Now - fileInfo.LastWriteTime).TotalSeconds < maxAgeSeconds; } catch { return false; } } void OnDisable() { StopDownload(); } void OnDestroy() { StopDownload(); } // GUI for runtime debugging void OnGUI() { if (!enableDebugMode) return; GUILayout.BeginArea(new Rect(320, 10, 300, 180)); GUILayout.BeginVertical("box"); GUILayout.Label($"Avatar Downloader - {targetPlayer}"); GUILayout.Label($"Server: {ServerUrl}"); GUILayout.Label($"Status: {(isConnected ? "Connected" : "Disconnected")}"); GUILayout.Label($"Success Rate: {(SuccessRate * 100):F1}%"); GUILayout.Label($"Last Download: {(Time.time - lastSuccessfulDownload):F1}s ago"); GUILayout.BeginHorizontal(); if (GUILayout.Button("Manual Download")) { ManualDownload(); } if (GUILayout.Button("Test Connection")) { StartCoroutine(TestConnection()); } GUILayout.EndHorizontal(); if (downloadCoroutine == null) { if (GUILayout.Button("Start Auto Download")) { StartDownload(); } } else { if (GUILayout.Button("Stop Auto Download")) { StopDownload(); } } GUILayout.EndVertical(); GUILayout.EndArea(); } }