/// <summary> /// Switches to a scene with a given name. Can only be called from Server /// </summary> /// <param name="sceneName">The name of the scene to switch to</param> public static void SwitchScene(string sceneName) { if (!NetworkingManager.singleton.NetworkConfig.EnableSceneSwitching) { Debug.LogWarning("MLAPI: Scene switching is not enabled"); return; } else if (isSwitching) { Debug.LogWarning("MLAPI: Scene switch already in progress"); return; } else if (!registeredSceneNames.Contains(sceneName)) { Debug.LogWarning("MLAPI: The scene " + sceneName + " is not registered as a switchable scene."); return; } SpawnManager.DestroySceneObjects(); //Destroy current scene objects before switching. CurrentSceneIndex = sceneNameToIndex[sceneName]; isSwitching = true; lastScene = SceneManager.GetActiveScene(); AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); sceneLoad.completed += OnSceneLoaded; using (BitWriter writer = new BitWriter()) { writer.WriteUInt(sceneNameToIndex[sceneName]); InternalMessageHandler.Send("MLAPI_SWITCH_SCENE", "MLAPI_INTERNAL", writer.Finalize(), null); } }
/// <summary> /// Spawns a object from the pool at a given position and rotation. Can only be called from server. /// </summary> /// <param name="poolName">The name of the pool</param> /// <param name="position">The position to spawn the object at</param> /// <param name="rotation">The rotation to spawn the object at</param> /// <returns></returns> public static GameObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation) { if (!NetworkingManager.singleton.isServer) { Debug.LogWarning("MLAPI: Object spawning can only occur on server"); return(null); } GameObject go = Pools[PoolNamesToIndexes[poolName]].SpawnObject(position, rotation); using (BitWriter writer = new BitWriter()) { writer.WriteUInt(go.GetComponent <NetworkedObject>().NetworkId); writer.WriteFloat(position.x); writer.WriteFloat(position.y); writer.WriteFloat(position.z); writer.WriteFloat(rotation.eulerAngles.x); writer.WriteFloat(rotation.eulerAngles.y); writer.WriteFloat(rotation.eulerAngles.z); InternalMessageHandler.Send("MLAPI_SPAWN_POOL_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), null); } return(go); }
internal static void OnDestroyObject(uint networkId, bool destroyGameObject) { if (!spawnedObjects.ContainsKey(networkId) || (netManager != null && !netManager.NetworkConfig.HandleObjectSpawning)) { return; } if (spawnedObjects[networkId].OwnerClientId != NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId && !spawnedObjects[networkId].isPlayerObject) { //Someone owns it. NetworkingManager.singleton.connectedClients[spawnedObjects[networkId].OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == networkId); } GameObject go = spawnedObjects[networkId].gameObject; if (netManager != null && netManager.isServer) { releasedNetworkObjectIds.Push(networkId); if (spawnedObjects[networkId] != null) { using (BitWriter writer = new BitWriter()) { writer.WriteUInt(networkId); InternalMessageHandler.Send("MLAPI_DESTROY_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), null); } } } if (destroyGameObject && go != null) { MonoBehaviour.Destroy(go); } spawnedObjects.Remove(networkId); }
/// <summary> /// Spawns a object from the pool at a given position and rotation. Can only be called from server. /// </summary> /// <param name="poolName">The name of the pool</param> /// <param name="position">The position to spawn the object at</param> /// <param name="rotation">The rotation to spawn the object at</param> /// <returns></returns> public static NetworkedObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation) { if (!NetworkingManager.singleton.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Object spawning can only occur on server"); } return(null); } NetworkedObject netObject = Pools[PoolNamesToIndexes[poolName]].SpawnObject(position, rotation); using (BitWriter writer = BitWriter.Get()) { writer.WriteUInt(netObject.NetworkId); writer.WriteFloat(position.x); writer.WriteFloat(position.y); writer.WriteFloat(position.z); writer.WriteFloat(rotation.eulerAngles.x); writer.WriteFloat(rotation.eulerAngles.y); writer.WriteFloat(rotation.eulerAngles.z); InternalMessageHandler.Send("MLAPI_SPAWN_POOL_OBJECT", "MLAPI_INTERNAL", writer, null); } return(netObject); }
internal static void SpawnPrefabIndexServer(NetworkedObject netObject, uint?clientOwnerId = null) { if (netObject.isSpawned) { Debug.LogWarning("MLAPI: Object already spawned"); return; } else if (!netManager.isServer) { Debug.LogWarning("MLAPI: Only server can spawn objects"); return; } else if (!netManager.NetworkConfig.NetworkPrefabIds.ContainsKey(netObject.NetworkedPrefabName)) { Debug.LogWarning("MLAPI: The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab"); return; } else if (!netManager.NetworkConfig.HandleObjectSpawning) { Debug.LogWarning("MLAPI: NetworkConfig is set to not handle object spawning"); return; } uint netId = GetNetworkObjectId(); netObject.networkId = netId; spawnedObjects.Add(netId, netObject); netObject._isSpawned = true; netObject.sceneObject = false; netObject.InvokeBehaviourNetworkSpawn(); if (clientOwnerId != null) { netObject.ownerClientId = clientOwnerId.Value; NetworkingManager.singleton.connectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject); } using (BitWriter writer = new BitWriter()) { writer.WriteBool(false); writer.WriteUInt(netObject.NetworkId); writer.WriteUInt(netObject.OwnerClientId); writer.WriteInt(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]); writer.WriteBool(netObject.sceneObject == null ? true : netObject.sceneObject.Value); writer.WriteFloat(netObject.transform.position.x); writer.WriteFloat(netObject.transform.position.y); writer.WriteFloat(netObject.transform.position.z); writer.WriteFloat(netObject.transform.rotation.eulerAngles.x); writer.WriteFloat(netObject.transform.rotation.eulerAngles.y); writer.WriteFloat(netObject.transform.rotation.eulerAngles.z); InternalMessageHandler.Send("MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), null); } }
internal static void FlushSceneObjects() { if (!NetworkingManager.singleton.isServer) { return; } //This loop is bad. For each client, we loop over every object twice. foreach (KeyValuePair <uint, NetworkedClient> client in netManager.connectedClients) { int sceneObjects = 0; foreach (var netObject in SpawnManager.spawnedObjects) { if (netObject.Value.sceneObject == null || netObject.Value.sceneObject == true) { sceneObjects++; } } using (BitWriter writer = BitWriter.Get()) { writer.WriteUShort((ushort)sceneObjects); foreach (var netObject in SpawnManager.spawnedObjects) { if (netObject.Value.sceneObject == null || netObject.Value.sceneObject == true) { writer.WriteBool(false); //isLocalPlayer writer.WriteUInt(netObject.Value.NetworkId); writer.WriteUInt(netObject.Value.OwnerClientId); writer.WriteInt(NetworkingManager.singleton.NetworkConfig.NetworkPrefabIds[netObject.Value.NetworkedPrefabName]); writer.WriteBool(netObject.Value.sceneObject == null ? true : netObject.Value.sceneObject.Value); writer.WriteBool(netObject.Value.observers.Contains(client.Key)); writer.WriteFloat(netObject.Value.transform.position.x); writer.WriteFloat(netObject.Value.transform.position.y); writer.WriteFloat(netObject.Value.transform.position.z); writer.WriteFloat(netObject.Value.transform.rotation.eulerAngles.x); writer.WriteFloat(netObject.Value.transform.rotation.eulerAngles.y); writer.WriteFloat(netObject.Value.transform.rotation.eulerAngles.z); if (netObject.Value.observers.Contains(client.Key)) { netObject.Value.WriteFormattedSyncedVarData(writer); } } } InternalMessageHandler.Send(client.Key, "MLAPI_ADD_OBJECTS", "MLAPI_INTERNAL", writer, null); } } }
/// <summary> /// Destroys a NetworkedObject if it's part of a pool. Use this instead of the MonoBehaviour Destroy method. Can only be called from Server. /// </summary> /// <param name="netObject">The NetworkedObject instance to destroy</param> public static void DestroyPoolObject(NetworkedObject netObject) { if (!NetworkingManager.singleton.isServer) { Debug.LogWarning("MLAPI: Objects can only be destroyed on the server"); return; } netObject.gameObject.SetActive(false); using (BitWriter writer = new BitWriter()) { writer.WriteUInt(netObject.NetworkId); InternalMessageHandler.Send("MLAPI_DESTROY_POOL_OBJECT", "MLAPI_INTERNAL", writer.Finalize(), null); } }
internal static void RemoveOwnership(uint netId) { NetworkedObject netObject = SpawnManager.spawnedObjects[netId]; NetworkingManager.singleton.connectedClients[netObject.OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == netId); netObject.ownerClientId = NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId; using (BitWriter writer = new BitWriter()) { writer.WriteUInt(netId); writer.WriteUInt(netObject.ownerClientId); InternalMessageHandler.Send("MLAPI_CHANGE_OWNER", "MLAPI_INTERNAL", writer.Finalize(), null); } }
/// <summary> /// Destroys a NetworkedObject if it's part of a pool. Use this instead of the MonoBehaviour Destroy method. Can only be called from Server. /// </summary> /// <param name="netObject">The NetworkedObject instance to destroy</param> public static void DestroyPoolObject(NetworkedObject netObject) { if (!NetworkingManager.singleton.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Objects can only be destroyed on the server"); } return; } netObject.gameObject.SetActive(false); using (BitWriter writer = BitWriter.Get()) { writer.WriteUInt(netObject.NetworkId); InternalMessageHandler.Send("MLAPI_DESTROY_POOL_OBJECT", "MLAPI_INTERNAL", writer, null); } }
internal static void FlushSceneObjects() { if (!NetworkingManager.singleton.isServer) { return; } List <NetworkedObject> sceneObjectsToSync = new List <NetworkedObject>(); foreach (KeyValuePair <uint, NetworkedObject> pair in SpawnManager.spawnedObjects) { if (pair.Value.sceneObject == null || pair.Value.sceneObject == true) { sceneObjectsToSync.Add(pair.Value); } } using (BitWriter writer = new BitWriter()) { writer.WriteUShort((ushort)sceneObjectsToSync.Count); for (int i = 0; i < sceneObjectsToSync.Count; i++) { writer.WriteBool(false); //isLocalPlayer writer.WriteUInt(sceneObjectsToSync[i].NetworkId); writer.WriteUInt(sceneObjectsToSync[i].OwnerClientId); writer.WriteInt(NetworkingManager.singleton.NetworkConfig.NetworkPrefabIds[sceneObjectsToSync[i].NetworkedPrefabName]); writer.WriteBool(sceneObjectsToSync[i].sceneObject == null ? true : sceneObjectsToSync[i].sceneObject.Value); writer.WriteFloat(sceneObjectsToSync[i].transform.position.x); writer.WriteFloat(sceneObjectsToSync[i].transform.position.y); writer.WriteFloat(sceneObjectsToSync[i].transform.position.z); writer.WriteFloat(sceneObjectsToSync[i].transform.rotation.eulerAngles.x); writer.WriteFloat(sceneObjectsToSync[i].transform.rotation.eulerAngles.y); writer.WriteFloat(sceneObjectsToSync[i].transform.rotation.eulerAngles.z); } InternalMessageHandler.Send("MLAPI_ADD_OBJECTS", "MLAPI_INTERNAL", writer.Finalize(), null); } }
internal static void RemoveOwnership(uint netId) { if (!netManager.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("You can only remove ownership from Server"); } return; } NetworkedObject netObject = SpawnManager.spawnedObjects[netId]; NetworkingManager.singleton.connectedClients[netObject.OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == netId); netObject.ownerClientId = NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId; using (BitWriter writer = BitWriter.Get()) { writer.WriteUInt(netId); writer.WriteUInt(netObject.ownerClientId); InternalMessageHandler.Send("MLAPI_CHANGE_OWNER", "MLAPI_INTERNAL", writer, null); } }
internal static void SpawnObject(NetworkedObject netObject, uint?clientOwnerId = null, BitWriter payload = null) { if (netObject.isSpawned) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Object already spawned"); } return; } else if (!netManager.isServer) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("Only server can spawn objects"); } return; } else if (!netManager.NetworkConfig.NetworkPrefabIds.ContainsKey(netObject.NetworkedPrefabName)) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab"); } return; } else if (!netManager.NetworkConfig.HandleObjectSpawning) { if (LogHelper.CurrentLogLevel <= LogLevel.Normal) { LogHelper.LogWarning("NetworkConfig is set to not handle object spawning"); } return; } uint netId = GetNetworkObjectId(); netObject.networkId = netId; spawnedObjects.Add(netId, netObject); netObject._isSpawned = true; netObject.sceneObject = false; if (clientOwnerId != null) { netObject.ownerClientId = clientOwnerId.Value; NetworkingManager.singleton.connectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject); } if (payload == null) { netObject.InvokeBehaviourNetworkSpawn(null); } else { using (BitReader payloadReader = BitReader.Get(payload.Finalize())) netObject.InvokeBehaviourNetworkSpawn(payloadReader); } foreach (var client in netManager.connectedClients) { netObject.RebuildObservers(client.Key); using (BitWriter writer = BitWriter.Get()) { writer.WriteBool(false); writer.WriteUInt(netObject.NetworkId); writer.WriteUInt(netObject.OwnerClientId); writer.WriteInt(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]); writer.WriteBool(netObject.sceneObject == null ? true : netObject.sceneObject.Value); writer.WriteBool(netObject.observers.Contains(client.Key)); writer.WriteFloat(netObject.transform.position.x); writer.WriteFloat(netObject.transform.position.y); writer.WriteFloat(netObject.transform.position.z); writer.WriteFloat(netObject.transform.rotation.eulerAngles.x); writer.WriteFloat(netObject.transform.rotation.eulerAngles.y); writer.WriteFloat(netObject.transform.rotation.eulerAngles.z); writer.WriteBool(payload != null); if (netObject.observers.Contains(client.Key)) { netObject.WriteFormattedSyncedVarData(writer); } if (payload != null) { writer.WriteWriter(payload); } InternalMessageHandler.Send(client.Key, "MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", writer, null); } } }