using FishNet.Connection; //remove on 2023/01/01 move to correct folder. using FishNet.Object; using FishNet.Observing; using System.Collections.Generic; using UnityEngine; using UnityEngine.Serialization; namespace FishNet.Managing.Observing { /// /// Additional options for managing the observer system. /// [DisallowMultipleComponent] [AddComponentMenu("FishNet/Manager/ObserverManager")] public sealed class ObserverManager : MonoBehaviour { #region Serialized. /// /// /// [Tooltip("True to update visibility for clientHost based on if they are an observer or not.")] [FormerlySerializedAs("_setHostVisibility")] [SerializeField] private bool _updateHostVisibility = true; /// /// True to update visibility for clientHost based on if they are an observer or not. /// public bool UpdateHostVisibility { get => _updateHostVisibility; private set => _updateHostVisibility = value; } /// /// /// [Tooltip("Default observer conditions for networked objects.")] [SerializeField] private List _defaultConditions = new List(); /// /// NetworkManager on object. /// private NetworkManager _networkManager; #endregion /// /// Initializes this script for use. /// /// internal void InitializeOnceInternal(NetworkManager manager) { _networkManager = manager; } /// /// Sets a new value for UpdateHostVisibility. /// /// New value. /// Which objects to update. public void SetUpdateHostVisibility(bool value, HostVisibilityUpdateTypes updateType) { //Unchanged. if (value == UpdateHostVisibility) return; /* Update even if server state is not known. * The setting should be updated so when the server * does start spawned objects have latest setting. */ if (HostVisibilityUpdateContains(updateType, HostVisibilityUpdateTypes.Manager)) UpdateHostVisibility = value; /* If to update spawned as well then update all networkobservers * with the setting and also update renderers. */ if (_networkManager.IsServer && HostVisibilityUpdateContains(updateType, HostVisibilityUpdateTypes.Spawned)) { NetworkConnection clientConn = _networkManager.ClientManager.Connection; foreach (NetworkObject n in _networkManager.ServerManager.Objects.Spawned.Values) { if (n.NetworkObserver != null) n.NetworkObserver.SetUpdateHostVisibility(value); //Only check to update renderers if clientHost. If not client then clientConn won't be active. if (clientConn.IsActive) n.SetRenderersVisible(n.Observers.Contains(clientConn), true); } } bool HostVisibilityUpdateContains(HostVisibilityUpdateTypes whole, HostVisibilityUpdateTypes part) { return (whole & part) == part; } } /// /// Adds default observer conditions to nob and returns the NetworkObserver used. /// internal NetworkObserver AddDefaultConditions(NetworkObject nob, ref NetworkObserver obs) { bool isGlobal = (nob.IsGlobal && !nob.IsSceneObject); bool nullObs = (obs == null); /* NetworkObserver is null and there are no * conditions to add. Nothing will change by adding * the NetworkObserver component so exit early. */ if (nullObs && _defaultConditions.Count == 0) return obs; //If NetworkObject does not have a NetworkObserver component. if (nullObs) { /* Global nobs do not need a NetworkObserver. * Ultimately, a global NetworkObject is one without * any conditions. */ if (isGlobal) return null; //If there are no conditions then there's nothing to add. if (_defaultConditions.Count == 0) return null; /* If here then there not a global networkobject and there are conditions to use. * Since the NetworkObserver is being added fresh, set OverrideType to UseManager * so that the NetworkObserver is populated with the manager conditions. */ obs = nob.gameObject.AddComponent(); obs.OverrideType = NetworkObserver.ConditionOverrideType.UseManager; } //NetworkObject has a NetworkObserver already on it. else { //If global the NetworkObserver has to be cleared and set to ignore manager. if (isGlobal) { obs.ObserverConditionsInternal.Clear(); obs.OverrideType = NetworkObserver.ConditionOverrideType.IgnoreManager; } } //If ignoring manager then use whatever is already configured. if (obs.OverrideType == NetworkObserver.ConditionOverrideType.IgnoreManager) { //Do nothing. } //If using manager then replace all with conditions. else if (obs.OverrideType == NetworkObserver.ConditionOverrideType.UseManager) { obs.ObserverConditionsInternal.Clear(); AddMissing(obs); } //Adding only new. else if (obs.OverrideType == NetworkObserver.ConditionOverrideType.AddMissing) { AddMissing(obs); } void AddMissing(NetworkObserver networkObserver) { int count = _defaultConditions.Count; for (int i = 0; i < count; i++) { ObserverCondition oc = _defaultConditions[i]; if (!networkObserver.ObserverConditionsInternal.Contains(oc)) networkObserver.ObserverConditionsInternal.Add(oc); } } return obs; } } }