123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- namespace Mirror
- {
- [AddComponentMenu("Network/ Interest Management/ Match/Match Interest Management")]
- public class MatchInterestManagement : InterestManagement
- {
- readonly Dictionary<Guid, HashSet<NetworkIdentity>> matchObjects =
- new Dictionary<Guid, HashSet<NetworkIdentity>>();
- readonly Dictionary<NetworkIdentity, Guid> lastObjectMatch =
- new Dictionary<NetworkIdentity, Guid>();
- readonly HashSet<Guid> dirtyMatches = new HashSet<Guid>();
- [ServerCallback]
- public override void OnSpawned(NetworkIdentity identity)
- {
- if (!identity.TryGetComponent(out NetworkMatch networkMatch))
- return;
- Guid networkMatchId = networkMatch.matchId;
- lastObjectMatch[identity] = networkMatchId;
- // Guid.Empty is never a valid matchId...do not add to matchObjects collection
- if (networkMatchId == Guid.Empty)
- return;
- // Debug.Log($"MatchInterestManagement.OnSpawned({identity.name}) currentMatch: {currentMatch}");
- if (!matchObjects.TryGetValue(networkMatchId, out HashSet<NetworkIdentity> objects))
- {
- objects = new HashSet<NetworkIdentity>();
- matchObjects.Add(networkMatchId, objects);
- }
- objects.Add(identity);
- // Match ID could have been set in NetworkBehaviour::OnStartServer on this object.
- // Since that's after OnCheckObserver is called it would be missed, so force Rebuild here.
- // Add the current match to dirtyMatches for Update to rebuild it.
- dirtyMatches.Add(networkMatchId);
- }
- [ServerCallback]
- public override void OnDestroyed(NetworkIdentity identity)
- {
- // Don't RebuildSceneObservers here - that will happen in Update.
- // Multiple objects could be destroyed in same frame and we don't
- // want to rebuild for each one...let Update do it once.
- // We must add the current match to dirtyMatches for Update to rebuild it.
- if (lastObjectMatch.TryGetValue(identity, out Guid currentMatch))
- {
- lastObjectMatch.Remove(identity);
- if (currentMatch != Guid.Empty && matchObjects.TryGetValue(currentMatch, out HashSet<NetworkIdentity> objects) && objects.Remove(identity))
- dirtyMatches.Add(currentMatch);
- }
- }
- // internal so we can update from tests
- [ServerCallback]
- internal void Update()
- {
- // for each spawned:
- // if match changed:
- // add previous to dirty
- // add new to dirty
- foreach (NetworkIdentity identity in NetworkServer.spawned.Values)
- {
- // Ignore objects that don't have a NetworkMatch component
- if (!identity.TryGetComponent(out NetworkMatch networkMatch))
- continue;
- Guid newMatch = networkMatch.matchId;
- if (!lastObjectMatch.TryGetValue(identity, out Guid currentMatch))
- continue;
- // Guid.Empty is never a valid matchId
- // Nothing to do if matchId hasn't changed
- if (newMatch == Guid.Empty || newMatch == currentMatch)
- continue;
- // Mark new/old matches as dirty so they get rebuilt
- UpdateDirtyMatches(newMatch, currentMatch);
- // This object is in a new match so observers in the prior match
- // and the new match need to rebuild their respective observers lists.
- UpdateMatchObjects(identity, newMatch, currentMatch);
- }
- // rebuild all dirty matches
- foreach (Guid dirtyMatch in dirtyMatches)
- RebuildMatchObservers(dirtyMatch);
- dirtyMatches.Clear();
- }
- void UpdateDirtyMatches(Guid newMatch, Guid currentMatch)
- {
- // Guid.Empty is never a valid matchId
- if (currentMatch != Guid.Empty)
- dirtyMatches.Add(currentMatch);
- dirtyMatches.Add(newMatch);
- }
- void UpdateMatchObjects(NetworkIdentity netIdentity, Guid newMatch, Guid currentMatch)
- {
- // 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;
- // Make sure this new match is in the dictionary
- if (!matchObjects.ContainsKey(newMatch))
- matchObjects.Add(newMatch, new HashSet<NetworkIdentity>());
- // Add this object to the hashset of the new match
- matchObjects[newMatch].Add(netIdentity);
- }
- void RebuildMatchObservers(Guid matchId)
- {
- foreach (NetworkIdentity netIdentity in matchObjects[matchId])
- if (netIdentity != null)
- NetworkServer.RebuildObservers(netIdentity, false);
- }
- public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver)
- {
- // Never observed if no NetworkMatch component
- if (!identity.TryGetComponent(out NetworkMatch identityNetworkMatch))
- return false;
- // Guid.Empty is never a valid matchId
- if (identityNetworkMatch.matchId == Guid.Empty)
- return false;
- // Never observed if no NetworkMatch component
- if (!newObserver.identity.TryGetComponent(out NetworkMatch newObserverNetworkMatch))
- return false;
- // Guid.Empty is never a valid matchId
- if (newObserverNetworkMatch.matchId == Guid.Empty)
- return false;
- return identityNetworkMatch.matchId == newObserverNetworkMatch.matchId;
- }
- public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers)
- {
- if (!identity.TryGetComponent(out NetworkMatch networkMatch))
- return;
- Guid matchId = networkMatch.matchId;
- // Guid.Empty is never a valid matchId
- if (matchId == Guid.Empty)
- return;
- if (!matchObjects.TryGetValue(matchId, out HashSet<NetworkIdentity> 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);
- }
- }
- }
|