using System; using System.Collections.Generic; namespace Mirror { public class MatchInterestManagement : InterestManagement { readonly Dictionary> matchObjects = new Dictionary>(); readonly Dictionary lastObjectMatch = new Dictionary(); HashSet dirtyMatches = new HashSet(); public override void OnSpawned(NetworkIdentity identity) { Guid currentMatch = identity.GetComponent().matchId; lastObjectMatch[identity] = currentMatch; // Guid.Empty is never a valid matchId...do not add to matchObjects collection if (currentMatch == Guid.Empty) return; // Debug.Log($"MatchInterestManagement.OnSpawned({identity.name}) currentMatch: {currentMatch}"); if (!matchObjects.TryGetValue(currentMatch, out HashSet objects)) { objects = new HashSet(); matchObjects.Add(currentMatch, objects); } objects.Add(identity); } public override void OnDestroyed(NetworkIdentity identity) { Guid currentMatch = lastObjectMatch[identity]; lastObjectMatch.Remove(identity); if (currentMatch != Guid.Empty && matchObjects.TryGetValue(currentMatch, out HashSet objects) && objects.Remove(identity)) RebuildMatchObservers(currentMatch); } void Update() { // only on server if (!NetworkServer.active) return; // for each spawned: // if match changed: // add previous to dirty // add new to dirty foreach (NetworkIdentity netIdentity in NetworkIdentity.spawned.Values) { Guid currentMatch = lastObjectMatch[netIdentity]; Guid newMatch = netIdentity.GetComponent().matchId; if (newMatch == currentMatch) continue; // Mark new/old scenes as dirty so they get rebuilt // Guid.Empty is never a valid matchId if (currentMatch != Guid.Empty) dirtyMatches.Add(currentMatch); dirtyMatches.Add(newMatch); // This object is in a new match so observers in the prior match // and the new scene need to rebuild their respective observers lists. // Remove this object from the hashset of the match it just left // Guid.Empty is never a valid matchId if (currentMatch != Guid.Empty) matchObjects[currentMatch].Remove(netIdentity); // Set this to the new match this object just entered lastObjectMatch[netIdentity] = newMatch; // Guid.Empty is never a valid matchId...do not add to matchObjects collection if (newMatch == Guid.Empty) continue; // Make sure this new match is in the dictionary if (!matchObjects.ContainsKey(newMatch)) matchObjects.Add(newMatch, new HashSet()); // Add this object to the hashset of the new match matchObjects[newMatch].Add(netIdentity); } // rebuild all dirty matchs foreach (Guid dirtyMatch in dirtyMatches) { RebuildMatchObservers(dirtyMatch); } dirtyMatches.Clear(); } void RebuildMatchObservers(Guid matchId) { foreach (NetworkIdentity netIdentity in matchObjects[matchId]) if (netIdentity != null) NetworkServer.RebuildObservers(netIdentity, false); } public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnection newObserver) { return identity.GetComponent().matchId == newObserver.identity.GetComponent().matchId; } public override void OnRebuildObservers(NetworkIdentity identity, HashSet newObservers, bool initialize) { Guid matchId = identity.GetComponent().matchId; // Guid.Empty is never a valid matchId if (matchId == Guid.Empty) return; if (!matchObjects.TryGetValue(matchId, out HashSet objects)) return; // Add everything in the hashset for this object's current match foreach (NetworkIdentity networkIdentity in objects) if (networkIdentity != null && networkIdentity.connectionToClient != null) newObservers.Add(networkIdentity.connectionToClient); } } }