/// <summary>
        ///     Spawns new object in world by QNet.
        /// </summary>
        /// <param name="prefab">Prefab of object to spawn.</param>
        /// <param name="position">Position of object to spawn.</param>
        /// <param name="rotation">Rotation of object to spawn.</param>
        /// <param name="ownerIdentity">Identity of owner.</param>
        /// <param name="skipObjectBroadcast">If true, system will skip SendObjectToAllConnection method.</param>
        public static QNetObjectBehaviour SpawnWithOwner(QNetObjectPrefab prefab, Vector3 position, Quaternion rotation,
                                                         short ownerIdentity, bool skipObjectBroadcast = false)
        {
            if (!QNetManager.IsServerActive)
            {
                throw new InvalidOperationException("You can only spawn QNetObjects from server.");
            }

            // then spawn local instance of object to make sure that everything is ok.
            var behaviour = InternalSpawn(GenerateObjectIdentity(), prefab, position, rotation, ownerIdentity);

            if (behaviour == null)
            {
                return(null);
            }

            if (!skipObjectBroadcast)
            {
                QNetServerObjects.SendObjectToAllConnections(behaviour);
            }

            return(behaviour);
        }
        /// <summary>
        ///     Spawns new object in local world by QNet.
        /// </summary>
        /// <param name="identity">Identity of this object.</param>
        /// <param name="prefab">Prefab of object to spawn.</param>
        /// <param name="position">Position of object to spawn.</param>
        /// <param name="rotation">Rotation of object to spawn.</param>
        /// <param name="ownerIdentity">Identity of owner.</param>
        public static QNetObjectBehaviour InternalSpawn(short identity, [NotNull] QNetObjectPrefab prefab,
                                                        Vector3 position,
                                                        Quaternion rotation, short ownerIdentity)
        {
            if (prefab == null)
            {
                throw new ArgumentNullException(nameof(prefab));
            }
            if (prefab.Prefab == null)
            {
                throw new ArgumentNullException(nameof(prefab.Prefab));
            }
            // fist, check if given prefab is added to QNetDatabase
            if (QNetManager.Database.GetPrefab(prefab.PrefabIdentity) == null)
            {
                JEMLogger.LogError(
                    $"System is trying to spawn QNetObject that isn't registered in database ({prefab.PrefabIdentity}).");
                return(null);
            }

            var existedObject = GetSpawnedObject(identity);

            if (existedObject != null)
            {
                if (QNetManager.IsHostActive)
                {
                    return(existedObject);
                }

                JEMLogger.LogError(
                    $"System is trying to spawn QNetObject of identity that already exists. ({identity})");
                return(null);
            }

            // now, spawn this bad boy
            var instance  = Instantiate(prefab.Prefab.gameObject, position, rotation);
            var behaviour = instance.GetComponent <QNetObjectBehaviour>();

            if (behaviour == null)
            {
                throw new InvalidOperationException(
                          "System is unable to resolve QNetObjectBehaviour from spawned object.");
            }
            behaviour.Spawned       = true;
            behaviour.objIdentity   = identity;
            behaviour.OwnerIdentity = ownerIdentity;
            if (QNetManager.IsServerActive &&
                (ownerIdentity == 0 || ownerIdentity == (QNetManager.Client?.ConnectionIdentity ?? 0)))
            {
                behaviour.IsOwner = true;
            }
            else
            {
                behaviour.IsOwner = QNetManager.Client != null && ownerIdentity != 0 &&
                                    ownerIdentity == QNetManager.Client.ConnectionIdentity;
            }

            behaviour.Prefab = prefab;
            behaviour.OnInternalSpawned();

            _spawnedBehaviours.Add(behaviour);
            // rebuild array
            SpawnedBehaviours = _spawnedBehaviours.ToArray();
            return(behaviour);
        }
 /// <summary>
 ///     Spawns new object in world by QNet.
 /// </summary>
 /// <param name="prefab">Prefab of object to spawn.</param>
 /// <param name="position">Position of object to spawn.</param>
 /// <param name="rotation">Rotation of object to spawn.</param>
 /// <param name="ownerConnection">Connection of owner.</param>
 /// <param name="skipObjectBroadcast">If true, system will skip SendObjectToAllConnection method.</param>
 public static QNetObjectBehaviour SpawnWithOwner(QNetObjectPrefab prefab, Vector3 position, Quaternion rotation,
                                                  QNetConnection ownerConnection, bool skipObjectBroadcast = false)
 {
     return(SpawnWithOwner(prefab, position, rotation, ownerConnection.ConnectionIdentity, skipObjectBroadcast));
 }
 /// <summary>
 ///     Spawns new object in world by QNet.
 /// </summary>
 /// <param name="prefab">Prefab of object to spawn.</param>
 /// <param name="position">Position of object to spawn.</param>
 /// <param name="rotation">Rotation of object to spawn.</param>
 /// \
 /// <param name="skipObjectBroadcast">If true, system will skip SendObjectToAllConnection method.</param>
 public static QNetObjectBehaviour Spawn(QNetObjectPrefab prefab, Vector3 position, Quaternion rotation,
                                         bool skipObjectBroadcast = false)
 {
     return(SpawnWithOwner(prefab, position, rotation, 0, skipObjectBroadcast));
 }