214 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using FishNet.Connection;
 | |
| using FishNet.Observing;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Runtime.CompilerServices;
 | |
| using UnityEngine;
 | |
| 
 | |
| namespace FishNet.Object
 | |
| {
 | |
|     public sealed partial class NetworkObject : MonoBehaviour
 | |
|     {
 | |
|         #region Public.
 | |
|         /// <summary>
 | |
|         /// Called when this NetworkObject losses all observers or gains observers while previously having none.
 | |
|         /// </summary>
 | |
|         public event Action<NetworkObject> OnObserversActive;
 | |
|         /// <summary>
 | |
|         /// NetworkObserver on this object.
 | |
|         /// </summary>
 | |
|         [HideInInspector]
 | |
|         public NetworkObserver NetworkObserver = null;
 | |
|         /// <summary>
 | |
|         /// Clients which can see and get messages from this NetworkObject.
 | |
|         /// </summary>
 | |
|         public HashSet<NetworkConnection> Observers = new HashSet<NetworkConnection>();
 | |
|         #endregion
 | |
| 
 | |
|         #region Private.
 | |
|         /// <summary>
 | |
|         /// True if NetworkObserver has been initialized.
 | |
|         /// </summary>
 | |
|         private bool _networkObserverInitiliazed = false;
 | |
|         /// <summary>
 | |
|         /// Found renderers on the NetworkObject and it's children. This is only used as clientHost to hide non-observers objects.
 | |
|         /// </summary>
 | |
|         [System.NonSerialized]
 | |
|         private Renderer[] _renderers;
 | |
|         /// <summary>
 | |
|         /// True if renderers have been looked up.
 | |
|         /// </summary>
 | |
|         private bool _renderersPopulated;
 | |
|         /// <summary>
 | |
|         /// Last visibility value for clientHost on this object.
 | |
|         /// </summary>
 | |
|         private bool _lastClientHostVisibility;
 | |
|         #endregion
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Updates cached renderers used to managing clientHost visibility.
 | |
|         /// </summary>
 | |
|         /// <param name="updateVisibility">True to also update visibility if clientHost.</param>
 | |
|         [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | |
|         public void UpdateRenderers(bool updateVisibility = true)
 | |
|         {
 | |
|             UpdateRenderers_Internal(updateVisibility);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Sets the renderer visibility for clientHost.
 | |
|         /// </summary>
 | |
|         /// <param name="visible">True if renderers are to be visibile.</param>
 | |
|         /// <param name="force">True to skip blocking checks.</param>
 | |
|         [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | |
|         public void SetRenderersVisible(bool visible, bool force = false)
 | |
|         {
 | |
|             if (!force)
 | |
|             {
 | |
|                 if (!NetworkObserver.UpdateHostVisibility)
 | |
|                     return;
 | |
|             }
 | |
| 
 | |
|             if (!_renderersPopulated)
 | |
|             {
 | |
|                 UpdateRenderers_Internal(false);
 | |
|                 _renderersPopulated = true;
 | |
|             }
 | |
| 
 | |
|             UpdateRenderVisibility(visible);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Clears and updates renderers.
 | |
|         /// </summary>
 | |
|         [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | |
|         private void UpdateRenderers_Internal(bool updateVisibility)
 | |
|         {
 | |
|             _renderers = GetComponentsInChildren<Renderer>(true);
 | |
|             List<Renderer> enabledRenderers = new List<Renderer>();
 | |
|             foreach (Renderer r in _renderers)
 | |
|             {
 | |
|                 if (r.enabled)
 | |
|                     enabledRenderers.Add(r);
 | |
|             }
 | |
|             //If there are any disabled renderers then change _renderers to cached values.
 | |
|             if (enabledRenderers.Count != _renderers.Length)
 | |
|                 _renderers = enabledRenderers.ToArray();
 | |
| 
 | |
|             if (updateVisibility)
 | |
|                 UpdateRenderVisibility(_lastClientHostVisibility);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Updates visibilites on renders without checks.
 | |
|         /// </summary>
 | |
|         /// <param name="visible"></param>
 | |
|         private void UpdateRenderVisibility(bool visible)
 | |
|         {
 | |
|             bool rebuildRenderers = false;
 | |
| 
 | |
|             Renderer[] rs = _renderers;
 | |
|             int count = rs.Length;
 | |
|             for (int i = 0; i < count; i++)
 | |
|             {
 | |
|                 Renderer r = rs[i];
 | |
|                 if (r == null)
 | |
|                 {
 | |
|                     rebuildRenderers = true;
 | |
|                     break;
 | |
|                 }
 | |
| 
 | |
|                 r.enabled = visible;
 | |
|             }
 | |
| 
 | |
|             _lastClientHostVisibility = visible;
 | |
|             //If to rebuild then do so, while updating visibility.
 | |
|             if (rebuildRenderers)
 | |
|                 UpdateRenderers(true);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Adds the default NetworkObserver conditions using the ObserverManager.
 | |
|         /// </summary>
 | |
|         private void AddDefaultNetworkObserverConditions()
 | |
|         {
 | |
|             if (_networkObserverInitiliazed)
 | |
|                 return;
 | |
| 
 | |
|             NetworkObserver = NetworkManager.ObserverManager.AddDefaultConditions(this);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Removes a connection from observers for this object returning if the connection was removed.
 | |
|         /// </summary>
 | |
|         /// <param name="connection"></param>
 | |
|         internal bool RemoveObserver(NetworkConnection connection)
 | |
|         {
 | |
|             int startCount = Observers.Count;
 | |
|             bool removed = Observers.Remove(connection);
 | |
|             if (removed)
 | |
|                 TryInvokeOnObserversActive(startCount);
 | |
| 
 | |
|             return removed;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Adds the connection to observers if conditions are met.
 | |
|         /// </summary>
 | |
|         /// <param name="connection"></param>
 | |
|         /// <returns>True if added to Observers.</returns>
 | |
|         internal ObserverStateChange RebuildObservers(NetworkConnection connection, bool timedOnly)
 | |
|         {
 | |
|             //If not a valid connection.
 | |
|             if (!connection.IsValid)
 | |
|             {
 | |
|                 NetworkManager.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;
 | |
|             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;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Invokes OnObserversActive if observers are now 0 but previously were not, or if was previously 0 but now has observers.
 | |
|         /// </summary>
 | |
|         /// <param name="startCount"></param>
 | |
|         private void TryInvokeOnObserversActive(int startCount)
 | |
|         {
 | |
|             if ((Observers.Count > 0 && startCount == 0) ||
 | |
|                 Observers.Count == 0 && startCount > 0)
 | |
|                 OnObserversActive?.Invoke(this);
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 |