private static bool InternalDestroySerializedObject([NotNull] QNetObjectBehaviour obj)
 {
     if (obj == null)
     {
         throw new ArgumentNullException(nameof(obj));
     }
     if (InternalSerializedAndInstancedObjects.Contains(obj))
     {
         InternalSerializedAndInstancedObjects.Remove(obj);
     }
     QNetObjectBehaviour.InternalDestroy(obj);
     return(true);
 }
        /// <summary>
        ///     Tags this player as ready.
        ///     An actual loading method.
        /// </summary>
        public void TagAsReady()
        {
            if (Ready)
            {
                if (!QNetManager.IsHostActive)
                {
                    throw new InvalidOperationException("Unable to tag player as ready while is already ready.");
                }
                return;
            }

            JEMLogger.Log($"> Tagging player {ToString()} as ready.");
            Ready = true;
            JEMLogger.Log("> (Tagging) Initializing player on server side.");

            if (OnPlayerCustomSpawn != null)
            {
                OnPlayerCustomSpawn.Invoke(Connection, out var obj);
                PlayerObject = obj;
            }
            else
            {
                var spawnPoint    = Vector3.one;
                var spawnRotation = Quaternion.identity;

                if (OnPlayerSpawnPosition == null)
                {
                    QNetSpawnArea.GetRandomSpawnArea().GenerateUnreliablePoint(out spawnPoint, out var spawnForward);
                    spawnRotation = Quaternion.LookRotation(spawnForward);
                }
                else
                {
                    OnPlayerSpawnPosition?.Invoke(this, out spawnPoint, out spawnRotation);
                }

                // create player's object
                PlayerObject = QNetObjectBehaviour.SpawnWithOwner(QNetManager.Database.PlayerPrefab, spawnPoint,
                                                                  spawnRotation, Connection);
            }

            // check for errors
            if (PlayerObject == null)
            {
                throw new NullReferenceException("PlayerObject is missing.");
            }

            JEMLogger.Log($"> Player {ToString()} is now ready.");
        }
        /// <summary>
        ///     Removes serialized object from memory.
        /// </summary>
        public static void RemoveSerializedObjectFromMemory(short objectIdentity)
        {
            if (QNetManager.IsHostActive) // if host is active, we will ignore this one
            {
                return;
            }

            if (WorldIsSerialized)
            {
                var qNetObject = QNetObjectBehaviour.GetSpawnedObject(objectIdentity) ??
                                 QNetObjectBehaviour.GetPredefinedObject(objectIdentity);
                if (qNetObject == null)
                {
                    JEMLogger.LogError(
                        $"System was trying to destroy de-serialized object but target of identity {objectIdentity} not exists in current world.");
                }
                else
                {
                    InternalDestroySerializedObject(qNetObject);
                }
            }
            else
            {
                var serializedObject = default(QNetWorldSerializerObject);
                for (var index = 0; index < InternalSerializedObjectsInMemory.Count; index++)
                {
                    if (InternalSerializedObjectsInMemory[index].Object.ObjectIdentity == objectIdentity)
                    {
                        serializedObject = InternalSerializedObjectsInMemory[index];
                        break;
                    }
                }

                if (serializedObject.Equals(default(QNetWorldSerializerObject)))
                {
                    JEMLogger.LogWarning(
                        $"System was trying to remove object from world serializer memory but target of identity {objectIdentity} not exist.");
                }
                else
                {
                    InternalSerializedObjectsInMemory.Remove(serializedObject);
                }
            }
        }
Пример #4
0
        internal static void OnServerObjectState(QNetMessage message, QNetMessageReader reader, ref bool disallowRecycle)
        {
            if (!QNetWorldSerializer.WorldIsSerialized)
            {
                return; // system can't receive query data while initializing,
            }
            var objectIdentity = reader.ReadInt16();
            var qNetObject     = QNetObjectBehaviour.GetObject(objectIdentity);

            if (qNetObject == null)
            {
                if (QNetManager.PrintNetworkWarnings)
                {
                    JEMLogger.LogWarning($"Local machine received QNetEntity state update message but object of identity {objectIdentity} not exists in local world.");
                }
                return;
            }

            qNetObject.DeSerializeServerState(reader);
        }
Пример #5
0
        public static void OnClientEntityQuery(QNetMessage message, QNetMessageReader reader, ref bool disallowRecycle)
        {
            if (!QNetWorldSerializer.WorldIsSerialized)
            {
                return; // system can't receive entity query data while initializing,
            }
            var objectIdentity = reader.ReadInt16();
            var qNetObject     = QNetObjectBehaviour.GetObject(objectIdentity);

            if (qNetObject == null)
            {
                if (QNetManager.PrintNetworkWarnings)
                {
                    JEMLogger.LogWarning(
                        $"Local machine received QNetEntity query message but object of identity {objectIdentity} not exists in local world.");
                }
                return;
            }

            var entity = qNetObject.GetComponent <QNetEntity>();

            if (entity == null)
            {
                throw new NullReferenceException(
                          $"QNetEntity query target exists but does not have {nameof(QNetEntity)} based script.");
            }

            if (message.IsClientMessage)
            {
                QNetSimulation.ReceivedServerFrame = reader.ReadUInt32();
                QNetSimulation.AdjustServerFrames  = QNetSimulation.ReceivedServerFrame > QNetTime.ServerFrame;
            }

            var index = reader.ReadByte();

            entity.InvokeNetworkMessage(index, reader);
        }
        private void OnEnable()
        {
            _script = (QNetObjectBehaviour)target;
            // var assetType = PrefabUtility.GetPrefabAssetType(target);
            // var instanceStatus = PrefabUtility.GetPrefabInstanceStatus(target);
            var type = PrefabUtility.GetPrefabType(target);

            _work = type == PrefabType.None || type == PrefabType.PrefabInstance ||
                    type == PrefabType.MissingPrefabInstance || type == PrefabType.ModelPrefabInstance ||
                    type == PrefabType.DisconnectedPrefabInstance || type == PrefabType.DisconnectedModelPrefabInstance;
            if (_work)
            {
                Identity = _script.ObjectIdentity;
                Identity = FixPredefinedIdentity(Identity);
                if (!Application.isPlaying)
                {
                    _script.UpdateIdentity(Identity, 0);
                }
            }
            else
            {
                _script.UpdateIdentity(0, 0);
            }
        }
Пример #7
0
        private IEnumerator InternalLoadServerLevelOnFly(string levelName)
        {
            JEMLogger.Log($"QNetUnity is loading map '{levelName}' on fly.");
            GameIsDeInitializing = true;
            GameIsInitializing   = true;
            GameInitialized      = false;

            QNetManager.Server.AcceptNewConnections = false;
            for (var index = 0; index < QNetPlayer.QNetPlayers.Length; index++)
            {
                var p = QNetPlayer.QNetPlayers[index];
                p.Loaded = false;
            }

            LastMapState = QNetMapState.Unloading;
            OnMapStateChanged?.Invoke(LastMapState);

            // destroy players
            yield return(QNetPlayer.DestroyAllQNetPlayers());

            // activate loading screen
            OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING WORLD",
                                               $"Destroying {QNetWorldSerializer.SerializedAndInstancedObjects.Count} objects.");

            // destroy world objects
            var isDestroyingWorldObjects = true;

            QNetWorldSerializer.DestroySerializedObjects(() => { isDestroyingWorldObjects = false; });
            while (isDestroyingWorldObjects)
            {
                yield return(new WaitForEndOfFrame());
            }

            // try to destroy rest of QNet objects just for sure
            if (QNetObjectBehaviour.SpawnedBehaviours.Length != 0)
            {
                JEMLogger.Log(
                    $"QNetUnity find and will destroy {QNetObjectBehaviour.SpawnedBehaviours.Length} additional objects that has been created not by QNetWorldSerializer.");
            }

            // Destroy all behaviours
            yield return(QNetObjectBehaviour.DestroyAll());

            // clear behaviours just for sure
            QNetObjectBehaviour.ClearBehaviours();

            // activate loading screen
            OnClientLoadingInfoUpdated?.Invoke(true, "LOADING LEVEL", "Loading level.");

            LastMapState = QNetMapState.Loading;
            OnMapStateChanged?.Invoke(LastMapState);

            var isLevelLoading = true;

            QNetLevelLoader.Load(levelName, () => { isLevelLoading = false; });
            while (isLevelLoading)
            {
                yield return(new WaitForEndOfFrame());
            }

            LastMapState = QNetMapState.Loaded;
            OnMapStateChanged?.Invoke(LastMapState);

            if (QNetManager.IsServerActive)
            {
                // we are on server!
                // here, we need to send level change info to all clients
                //var writer = QNetManager.Server.GenerateOutgoingMessage((ushort)QNetUnityLocalHeader.LEVEL_LOAD_ON_FLY);
                //writer.WriteString(QNetLevelLoader.LevelName);
                //QNetManager.Server.SendToAll(QNetLocalChannel.DEFAULT, QNetMessageMethod.ReliableOrdered, writer);
            }

            GameIsDeInitializing = false;
            GameIsInitializing   = false;
            GameInitialized      = true;
            QNetManager.Server.AcceptNewConnections = true;

            JEMLogger.Log($"QNetUnity has loaded map '{levelName}' on fly.");
        }
        private static IEnumerator InternalDeInitialize(Action onDone)
        {
            var sw = Stopwatch.StartNew();

            // the initialize client
            OnUnloadClientSideContent?.Invoke();

            // activate loading screen
            OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING WORLD", "Destroying players.");
            OnClientLoadingStart?.Invoke();

            LastMapState = QNetMapState.Unloading;
            OnMapStateChanged?.Invoke(LastMapState);

            // destroy players
            yield return(QNetPlayer.DestroyAllQNetPlayers());

            // activate loading screen
            OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING WORLD",
                                               $"Destroying {QNetWorldSerializer.SerializedAndInstancedObjects.Count} objects.");

            // destroy world objects
            var isDestroyingWorldObjects = true;

            QNetWorldSerializer.DestroySerializedObjects(() => { isDestroyingWorldObjects = false; });
            while (isDestroyingWorldObjects)
            {
                yield return(new WaitForEndOfFrame());
            }

            // try to destroy rest of QNet objects just for sure
            if (QNetObjectBehaviour.SpawnedBehaviours.Length != 0)
            {
                JEMLogger.Log(
                    $"QNetUnity find and will destroy {QNetObjectBehaviour.SpawnedBehaviours.Length} additional objects that has been created not by QNetWorldSerializer.");
            }

            while (QNetObjectBehaviour.SpawnedBehaviours.Length > 0)
            {
                QNetObjectBehaviour.InternalDestroy(QNetObjectBehaviour.SpawnedBehaviours[0]);
                yield return(new WaitForEndOfFrame());
            }

            // activate loading screen
            OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING LEVEL", "Unloading level.");

            // unload world
            var isLevelUnLoading = true;

            QNetLevelLoader.UnLoad(() => { isLevelUnLoading = false; });
            while (isLevelUnLoading)
            {
                yield return(new WaitForEndOfFrame());
            }

            // clear behaviours just for sure
            QNetObjectBehaviour.ClearBehaviours();

            LastMapState = QNetMapState.NotLoaded;
            OnMapStateChanged?.Invoke(LastMapState);

            GameIsDeInitializing = false;
            GameInitialized      = false;
            OnClientLoadingEnd?.Invoke();

            JEMLogger.Log($"QNetUnity DeInitialization main work took {sw.Elapsed.Milliseconds:0.00}ms.");
            onDone?.Invoke();
        }
        private static IEnumerator InternalFromSerializedObject(QNetWorldSerializerObject obj, Action onDone)
        {
            var predefined = QNetObjectBehaviour.GetPredefinedObject(obj.Object.ObjectIdentity);

            if (predefined != null)
            {
                if (predefined.Prefab != null && predefined.Prefab.PrefabIdentity != obj.Object.PrefabIdentity)
                {
                    JEMLogger.LogError("Local predefined object does not have the same prefab identity as server.");
                }

                // update predefined object transform
                predefined.transform.position = obj.Object.Position;
                predefined.transform.rotation = obj.Object.Rotation;

                // identity
                predefined.UpdateIdentity(predefined.ObjectIdentity, obj.Object.OwnerIdentity);

                // call network methods
                predefined.OnInternalSpawned();
                predefined.OnNetworkActive();

                // scale?
                predefined.transform.localScale = obj.Object.Scale;

                // de-serialize server state
                predefined.DeSerializeServerState(obj.SerializedServerState);

                // activate predefined object
                predefined.gameObject.SetActive(true);
                yield return(predefined);

                // manual recycling
                QNetManager.Client.OriginalClient.Recycle(obj.SerializedServerState.GetMessage());
                onDone.Invoke();
                yield break;
            }

            var prefab = QNetManager.Database.GetPrefab(obj.Object.PrefabIdentity);

            if (prefab == null)
            {
                JEMLogger.Log(
                    $"World serializer is trying to create object but prefab of given id not exists in database. ({obj.Object.PrefabIdentity})");

                // manual recycling
                QNetManager.Client.OriginalClient.Recycle(obj.SerializedServerState.GetMessage());
                onDone.Invoke();
                yield break;
            }

            // create local instance of received
            var behaviour = QNetObjectBehaviour.InternalSpawn(obj.Object.ObjectIdentity, prefab, obj.Object.Position,
                                                              obj.Object.Rotation, obj.Object.OwnerIdentity);

            yield return(behaviour);

            if (behaviour != null)
            {
                // scale?
                behaviour.transform.localScale = obj.Object.Scale;

                // de-serialize server state
                behaviour.DeSerializeServerState(obj.SerializedServerState);

                // add created object to local array.
                InternalSerializedAndInstancedObjects.Add(behaviour);
            } // ignore, if system fail to spawn new object (most likely because of duplicate)

            // manual recycling
            QNetManager.Client.OriginalClient.Recycle(obj.SerializedServerState.GetMessage());
            onDone.Invoke();
        }