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