using System; using System.Collections.Generic; using UnityEngine; namespace Mirror { /// /// Component that controls visibility of networked objects based on match id. /// Any object with this component on it will only be visible to other objects in the same match. /// This would be used to isolate players to their respective matches within a single game server instance. /// // Deprecated 2021-02-17 [Obsolete(NetworkVisibilityObsoleteMessage.Message)] [DisallowMultipleComponent] [AddComponentMenu("Network/NetworkMatchChecker")] [RequireComponent(typeof(NetworkIdentity))] [RequireComponent(typeof(NetworkMatch))] [HelpURL("https://mirror-networking.gitbook.io/docs/components/network-match-checker")] public class NetworkMatchChecker : NetworkVisibility { // internal for tests internal static readonly Dictionary> matchPlayers = new Dictionary>(); // internal for tests internal Guid currentMatch { get => GetComponent().matchId; set => GetComponent().matchId = value; } internal Guid lastMatch; public override void OnStartServer() { if (currentMatch == Guid.Empty) return; if (!matchPlayers.ContainsKey(currentMatch)) matchPlayers.Add(currentMatch, new HashSet()); matchPlayers[currentMatch].Add(netIdentity); // No need to rebuild anything here. // identity.RebuildObservers is called right after this from NetworkServer.SpawnObject } public override void OnStopServer() { if (currentMatch == Guid.Empty) return; if (matchPlayers.ContainsKey(currentMatch) && matchPlayers[currentMatch].Remove(netIdentity)) RebuildMatchObservers(currentMatch); } void RebuildMatchObservers(Guid specificMatch) { foreach (NetworkIdentity networkIdentity in matchPlayers[specificMatch]) networkIdentity?.RebuildObservers(false); } #region Observers /// /// Callback used by the visibility system to determine if an observer (player) can see this object. /// If this function returns true, the network connection will be added as an observer. /// /// Network connection of a player. /// True if the player can see this object. public override bool OnCheckObserver(NetworkConnection conn) { // Not Visible if not in a match if (currentMatch == Guid.Empty) return false; NetworkMatchChecker networkMatchChecker = conn.identity.GetComponent(); if (networkMatchChecker == null) return false; return networkMatchChecker.currentMatch == currentMatch; } /// /// Callback used by the visibility system to (re)construct the set of observers that can see this object. /// Implementations of this callback should add network connections of players that can see this object to the observers set. /// /// The new set of observers for this object. /// True if the set of observers is being built for the first time. public override void OnRebuildObservers(HashSet observers, bool initialize) { if (currentMatch == Guid.Empty) return; foreach (NetworkIdentity networkIdentity in matchPlayers[currentMatch]) if (networkIdentity != null && networkIdentity.connectionToClient != null) observers.Add(networkIdentity.connectionToClient); } #endregion [ServerCallback] void Update() { // only if changed if (currentMatch == lastMatch) return; // This object is in a new match so observers in the prior match // and the new match need to rebuild their respective observers lists. // Remove this object from the hashset of the match it just left if (lastMatch != Guid.Empty) { matchPlayers[lastMatch].Remove(netIdentity); // RebuildObservers of all NetworkIdentity's in the match this // object just left RebuildMatchObservers(lastMatch); } if (currentMatch != Guid.Empty) { // Make sure this new match is in the dictionary if (!matchPlayers.ContainsKey(currentMatch)) matchPlayers.Add(currentMatch, new HashSet()); // Add this object to the hashset of the new match matchPlayers[currentMatch].Add(netIdentity); // RebuildObservers of all NetworkIdentity's in the match this object just entered RebuildMatchObservers(currentMatch); } else { // Not in any match now...RebuildObservers will clear and add self netIdentity.RebuildObservers(false); } // save last rebuild's match lastMatch = currentMatch; } } }