using FishNet.Connection; using FishNet.Managing.Logging; using FishNet.Observing; using System; using System.Collections.Generic; using UnityEngine; namespace FishNet.Object { public sealed partial class NetworkObject : MonoBehaviour { #region Public. /// /// Called when this NetworkObject losses all observers or gains observers while previously having none. /// public event Action OnObserversActive; /// /// NetworkObserver on this object. May be null if not using observers. /// [HideInInspector] public NetworkObserver NetworkObserver = null; /// /// Clients which can see and get messages from this NetworkObject. /// public HashSet Observers = new HashSet(); #endregion #region Private. /// /// True if NetworkObserver has been initialized. /// private bool _networkObserverInitiliazed = false; /// /// Found renderers on the NetworkObject and it's children. This is only used as clientHost to hide non-observers objects. /// [System.NonSerialized] private Renderer[] _renderers; /// /// True if renderers have been looked up. /// private bool _renderersPopulated; #endregion /// /// Sets the renderer visibility for clientHost. /// /// True if renderers are to be visibile. /// True to skip blocking checks. public void SetRenderersVisible(bool visible, bool force = false) { if (!force) { if (NetworkObserver != null && !NetworkObserver.UpdateHostVisibility) return; } if (!_renderersPopulated) { _renderers = GetComponentsInChildren(true); _renderersPopulated = true; } Renderer[] rs = _renderers; int count = rs.Length; for (int i = 0; i < count; i++) rs[i].enabled = visible; } /// /// Adds the default NetworkObserver conditions using the ObserverManager. /// private void AddDefaultNetworkObserverConditions() { if (_networkObserverInitiliazed) return; NetworkObserver = GetComponent(); NetworkManager.ObserverManager.AddDefaultConditions(this, ref NetworkObserver); } /// /// Initializes NetworkObserver. This will only call once even as host. /// private void InitializeOnceObservers() { if (_networkObserverInitiliazed) return; if (NetworkObserver != null) NetworkObserver.PreInitialize(this); _networkObserverInitiliazed = true; } /// /// Removes a connection from observers for this object. /// /// internal bool RemoveObserver(NetworkConnection connection) { int startCount = Observers.Count; bool removed = Observers.Remove(connection); if (removed) TryInvokeOnObserversActive(startCount); return removed; } /// /// Adds the connection to observers if conditions are met. /// /// /// True if added to Observers. internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool timedOnly) { //If not a valid connection. if (!connection.IsValid) { if (NetworkManager.CanLog(LoggingType.Warning)) Debug.LogWarning($"An invalid connection was used when rebuilding observers."); return ObserverStateChange.Unchanged; } //Valid not not active. else if (!connection.IsActive) { /* Just remove from observers since connection isn't active * and return unchanged because nothing should process * given the connection isnt active. */ Observers.Remove(connection); return ObserverStateChange.Unchanged; } else if (IsDeinitializing) { /* If object is deinitializing it's either being despawned * this frame or it's not spawned. If we've made it this far, * it's most likely being despawned. */ return ObserverStateChange.Unchanged; } int startCount = Observers.Count; //Not using observer system, this object is seen by everything. if (NetworkObserver == null) { bool added = Observers.Add(connection); if (added) TryInvokeOnObserversActive(startCount); return (added) ? ObserverStateChange.Added : ObserverStateChange.Unchanged; } else { ObserverStateChange osc = NetworkObserver.RebuildObservers(connection, timedOnly); if (osc == ObserverStateChange.Added) Observers.Add(connection); else if (osc == ObserverStateChange.Removed) Observers.Remove(connection); if (osc != ObserverStateChange.Unchanged) TryInvokeOnObserversActive(startCount); return osc; } } /// /// Invokes OnObserversActive if observers are now 0 but previously were not, or if was previously 0 but now has observers. /// /// private void TryInvokeOnObserversActive(int startCount) { if ((Observers.Count > 0 && startCount == 0) || Observers.Count == 0 && startCount > 0) OnObserversActive?.Invoke(this); } } }