using Fusion; using Baba_yaga.Game; using Baba_yaga.UI; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; namespace Baba_yaga.Network { /// /// Orchestrates the Elo calculation and persistence on the Host. /// Broadcasts results to all clients. /// [UnityEngine.Scripting.APIUpdating.MovedFrom(true, sourceNamespace: "Hallucinate.Network", sourceAssembly: "Opsive.UltimateCharacterController")] public class MatchEloManager : NetworkBehaviour { [Networked] public EloResult LastMatchResult { get; set; } [Networked] public bool IsCalculating { get; set; } private Dictionary _playerUsernames = new Dictionary(); // Simulating the database locally instead of Firebase private static Dictionary _localEloDatabase = new Dictionary(); private Task GetLocalPlayerData(string username) { if (!_localEloDatabase.TryGetValue(username, out var data)) { data = PlayerEloData.Default; _localEloDatabase[username] = data; } return Task.FromResult(data); } private Task SaveLocalPlayerData(string username, PlayerEloData data) { _localEloDatabase[username] = data; return Task.CompletedTask; } public override void Spawned() { if (Object.HasStateAuthority) { // In a real scenario, you'd collect usernames as players join. // For now, we assume they are provided or stored in PlayerRef custom data. // Placeholder: Use a mock or collect from Session properties. } } /// /// Registers a player's username when they join. /// [Rpc(RpcSources.All, RpcTargets.StateAuthority)] public void RPC_RegisterUsername(PlayerRef player, string username) { if (!_playerUsernames.ContainsKey(player)) { _playerUsernames.Add(player, username); Debug.Log($"[EloManager] Registered {username} for {player}"); } } /// /// Called by GameManager on Host when match ends. /// public async void ProcessMatchResult(PlayerRef winner, PlayerRef loser, bool isDraw = false) { if (!Object.HasStateAuthority) return; IsCalculating = true; string nameA = _playerUsernames.GetValueOrDefault(winner, "Unknown_A"); string nameB = _playerUsernames.GetValueOrDefault(loser, "Unknown_B"); // 1. Fetch from local simulated database var dataA = await GetLocalPlayerData(nameA); var dataB = await GetLocalPlayerData(nameB); // 2. Calculate float resultA = isDraw ? 0.5f : 1.0f; var result = EloSystem.Calculate(dataA.Rating, dataB.Rating, dataA.GamesPlayed, dataB.GamesPlayed, resultA); // 3. Update Data Objects dataA.Rating = result.NewRatingA; dataA.GamesPlayed++; dataB.Rating = result.NewRatingB; dataB.GamesPlayed++; // 4. Save to local simulated database await Task.WhenAll( SaveLocalPlayerData(nameA, dataA), SaveLocalPlayerData(nameB, dataB) ); // 5. Broadcast LastMatchResult = result; IsCalculating = false; Debug.Log($"[EloManager] Match Processed. Winner: {nameA} (+{result.DeltaA}), Loser: {nameB} ({result.DeltaB})"); // Send RPC to show UI RPC_NotifyClients(result); } [Rpc(RpcSources.StateAuthority, RpcTargets.All)] private void RPC_NotifyClients(EloResult result) { // This is where you'd trigger the Post-Match Rive/UI Debug.Log($"[Client] Received Elo Update: {result.DeltaA} / {result.DeltaB}"); } } }