using FishNet.Component.ColliderRollback; using FishNet.Connection; using FishNet.Managing; using FishNet.Managing.Client; using FishNet.Managing.Logging; using FishNet.Managing.Observing; using FishNet.Managing.Scened; using FishNet.Managing.Server; using FishNet.Managing.Timing; using FishNet.Managing.Transporting; using System; using UnityEngine; namespace FishNet.Object { public sealed partial class NetworkObject : MonoBehaviour { #region Public. /// /// True if this object has been initialized on the client side. /// This is set true right before client callbacks. /// public bool ClientInitialized { get; private set; } /// /// /// private bool _isClient; /// /// True if the client is active and authenticated. /// public bool IsClient { /* This needs to use a special check when * player is acting as host. Clients won't * set IsClient until they receive the spawn message * but the user may expect this true after client * gains observation but before client gets spawn. */ get { if (IsServer) return (NetworkManager == null) ? false : NetworkManager.IsClient; else return _isClient; } private set => _isClient = value; } /// /// True if only the client is active and authenticated. /// public bool IsClientOnly => (IsClient && !IsServer); /// /// True if server is active. /// public bool IsServer { get; private set; } /// /// True if only the server is active. /// public bool IsServerOnly => (IsServer && !IsClient); /// /// True if client and server are active. /// public bool IsHost => (IsClient && IsServer); /// /// True if client nor server are active. /// public bool IsOffline => (!IsClient && !IsServer); /// /// True if the local client is the owner of this object. /// public bool IsOwner { get { /* ClientInitialized becomes true when this * NetworkObject has been initialized on the client side. * * This value is used to prevent IsOwner from returning true * when running as host. * * EG: server will set owner when it spawns the object. * If IsOwner is checked before the object spawns on the * client-host then it would also return true, since the * Owner reference would be the same as what was set by server. * This is however bad when the client hasn't initialized the object * yet because it gives a false sense of initialization. * * Wait for client-host being initialized before potentially * returning true. */ /* Removed this restriction because people may want to use * base.IsOwner for initializing in OnNetworkStart. While this * would return true for client only, it wouldn't for host. That * would be bad. */ //if (!ClientInitialized) //return false; return Owner.IsLocalClient; } } /// /// /// private NetworkConnection _owner; /// /// Owner of this object. /// public NetworkConnection Owner { get { //Ensures a null Owner is never returned. if (_owner == null) return FishNet.Managing.NetworkManager.EmptyConnection; return _owner; } private set { _owner = value; } } /// /// ClientId for this NetworkObject owner. /// public int OwnerId => (!Owner.IsValid) ? -1 : Owner.ClientId; /// /// True if the object is initialized for the network. /// public bool IsSpawned => (!IsDeinitializing && ObjectId >= 0); /// /// The local connection of the client calling this method. /// public NetworkConnection LocalConnection => (NetworkManager == null) ? new NetworkConnection() : NetworkManager.ClientManager.Connection; /// /// NetworkManager for this object. /// public NetworkManager NetworkManager { get; private set; } /// /// ServerManager for this object. /// public ServerManager ServerManager { get; private set; } /// /// ClientManager for this object. /// public ClientManager ClientManager { get; private set; } /// /// ObserverManager for this object. /// public ObserverManager ObserverManager { get; private set; } /// /// TransportManager for this object. /// public TransportManager TransportManager { get; private set; } /// /// TimeManager for this object. /// public TimeManager TimeManager { get; private set; } /// /// SceneManager for this object. /// public SceneManager SceneManager { get; private set; } /// /// RollbackManager for this object. /// public RollbackManager RollbackManager { get; private set; } #endregion /// /// Returns a NetworkBehaviour on this NetworkObject. /// /// ComponentIndex of the NetworkBehaviour. /// True to error if not found. /// public NetworkBehaviour GetNetworkBehaviour(byte componentIndex, bool error) { if (componentIndex >= NetworkBehaviours.Length) { if (error) { bool staticLog = (NetworkManager == null); string errMsg = $"ComponentIndex of {componentIndex} is out of bounds on {gameObject.name} [id {ObjectId}]. This may occur if you have modified your gameObject/prefab without saving it, or the scene."; if (staticLog && NetworkManager.StaticCanLog(LoggingType.Error)) Debug.LogError(errMsg); else if (!staticLog && NetworkManager.CanLog(LoggingType.Error)) Debug.LogError(errMsg); } } return NetworkBehaviours[componentIndex]; } /// /// Despawns this NetworkObject. Only call from the server. /// /// Overrides the default DisableOnDespawn value for this single despawn. Scene objects will never be destroyed. public void Despawn(bool? disableOnDespawnOverride = null) { NetworkObject nob = this; NetworkManager.ServerManager.Despawn(nob, disableOnDespawnOverride); } /// /// Spawns an object over the network. Only call from the server. /// public void Spawn(GameObject go, NetworkConnection ownerConnection = null) { if (!CanSpawnOrDespawn(true)) return; NetworkManager.ServerManager.Spawn(go, ownerConnection); } /// /// Spawns an object over the network. Only call from the server. /// public void Spawn(NetworkObject nob, NetworkConnection ownerConnection = null) { if (!CanSpawnOrDespawn(true)) return; NetworkManager.ServerManager.Spawn(nob, ownerConnection); } /// /// Returns if Spawn or Despawn can be called. /// /// True to warn if not able to execute spawn or despawn. /// internal bool CanSpawnOrDespawn(bool warn) { bool canExecute = true; if (NetworkManager == null) { canExecute = false; if (warn) { if (NetworkManager.StaticCanLog(LoggingType.Warning)) Debug.LogWarning($"Cannot despawn {gameObject.name}, NetworkManager reference is null. This may occur if the object is not spawned or initialized."); } } else if (IsDeinitializing) { canExecute = false; if (warn) { if (NetworkManager.CanLog(LoggingType.Warning)) Debug.LogWarning($"Cannot despawn {gameObject.name}, it is already deinitializing."); } } return canExecute; } } }