/// <summary> /// Compares the server player list to the client one, and updates if needed. /// </summary> private void UpdatePlayerList(IEnumerable <PlayerState> remotePlayers) { var dirty = false; var hitSet = new List <NetSessionId>(); foreach (var state in remotePlayers) { hitSet.Add(state.SessionId); if (_sessions.TryGetValue(state.SessionId, out var local)) { // Exists, update data. if (local.Name == state.Name && local.Status == state.Status && local.Ping == state.Ping) { continue; } dirty = true; local.Name = state.Name; local.Status = state.Status; local.Ping = state.Ping; } else { // New, give him a slot. dirty = true; var newSession = new PlayerSession(state.SessionId) { Name = state.Name, Status = state.Status, Ping = state.Ping }; _sessions.Add(state.SessionId, newSession); if (state.SessionId == LocalPlayer.SessionId) { LocalPlayer.Session = newSession; } } } foreach (var existing in hitSet) { // clear slot, player left if (!_sessions.ContainsKey(existing)) { DebugTools.Assert(LocalPlayer.SessionId != existing, "I'm still connected to the server, but i left?"); _sessions.Remove(existing); dirty = true; } } if (dirty) { PlayerListUpdated?.Invoke(this, EventArgs.Empty); } }
/// <summary> /// Compares the server player list to the client one, and updates if needed. /// </summary> private void UpdatePlayerList(IEnumerable <PlayerState> remotePlayers) { var dirty = false; // diff the sessions to the states for (var i = 0; i < MaxPlayers; i++) { // try to get local session var cSession = _sessions.ContainsKey(i) ? _sessions[i] : null; // should these be mapped NetId -> PlyInfo? var info = remotePlayers.FirstOrDefault(state => state.Index == i); // slot already occupied if (cSession != null && info != null) { if (info.Uuid != cSession.Uuid) // not the same player { Debug.Assert(LocalPlayer.Index != info.Index, "my uuid should not change"); dirty = true; _sessions.Remove(info.Index); var newSession = new PlayerSession(info.Index, info.Uuid); newSession.Name = info.Name; newSession.Status = info.Status; newSession.Ping = info.Ping; _sessions.Add(info.Index, newSession); } else // same player, update info { if (cSession.Name == info.Name && cSession.Status == info.Status && cSession.Ping == info.Ping) { continue; } dirty = true; cSession.Name = info.Name; cSession.Status = info.Status; cSession.Ping = info.Ping; } } // clear slot, player left else if (cSession != null) { Debug.Assert(LocalPlayer.Index != i, "I'm still connected to the server, but i left?"); dirty = true; _sessions.Remove(cSession.Index); } // add new session to slot else if (info != null) { Debug.Assert(LocalPlayer.Index != info.Index || LocalPlayer.Session == null, "I already have a session, why am i getting a new one?"); dirty = true; var newSession = new PlayerSession(info.Index, info.Uuid); newSession.Name = info.Name; newSession.Status = info.Status; newSession.Ping = info.Ping; _sessions.Add(info.Index, newSession); if (LocalPlayer.Index == info.Index) { LocalPlayer.Session = newSession; } } // else they are both null, continue } //raise event if (dirty) { PlayerListUpdated?.Invoke(this, EventArgs.Empty); } }