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);
}
}
}