diff --git a/MLAPI/Data/NetworkConfig.cs b/MLAPI/Data/NetworkConfig.cs index 518db21..0a27b63 100644 --- a/MLAPI/Data/NetworkConfig.cs +++ b/MLAPI/Data/NetworkConfig.cs @@ -50,11 +50,13 @@ namespace MLAPI.Data /// /// A list of spawnable prefabs /// - public List SpawnablePrefabs = new List(); + public List NetworkedPrefabs = new List(); + internal Dictionary NetworkPrefabIds; + internal Dictionary NetworkPrefabNames; /// /// The default player prefab /// - public GameObject PlayerPrefab; + public string PlayerPrefabName; /// /// The size of the receive message buffer. This is the max message size. /// @@ -132,7 +134,7 @@ namespace MLAPI.Data /// /// Wheter or not to enable scene switching /// - public bool EnableSceneSwitching = false; + public bool EnableSceneSwitching = true; private byte[] ConfigHash = null; /// @@ -172,7 +174,10 @@ namespace MLAPI.Data } if(HandleObjectSpawning) { - writer.Write(SpawnablePrefabs.Count); + for (int i = 0; i < NetworkedPrefabs.Count; i++) + { + writer.Write(NetworkedPrefabs[i].name); + } } writer.Write(HandleObjectSpawning); writer.Write(EnableEncryption); diff --git a/MLAPI/Data/NetworkPool.cs b/MLAPI/Data/NetworkPool.cs index dfebaf3..938c420 100644 --- a/MLAPI/Data/NetworkPool.cs +++ b/MLAPI/Data/NetworkPool.cs @@ -8,13 +8,13 @@ namespace MLAPI.Data internal GameObject[] objects; internal ushort poolId; - internal NetworkPool(int prefabIndex, uint size, ushort poolIndex) + internal NetworkPool(int prefabId, uint size, ushort poolIndex) { objects = new GameObject[size]; poolId = poolIndex; for (int i = 0; i < size; i++) { - GameObject go = Object.Instantiate(NetworkingManager.singleton.NetworkConfig.SpawnablePrefabs[prefabIndex], Vector3.zero, Quaternion.identity); + GameObject go = MonoBehaviour.Instantiate(NetworkingManager.singleton.NetworkConfig.NetworkedPrefabs[prefabId].prefab, Vector3.zero, Quaternion.identity); go.GetComponent()._isPooledObject = true; go.GetComponent().poolId = poolId; go.GetComponent().Spawn(); diff --git a/MLAPI/Data/NetworkedPrefab.cs b/MLAPI/Data/NetworkedPrefab.cs new file mode 100644 index 0000000..e42b548 --- /dev/null +++ b/MLAPI/Data/NetworkedPrefab.cs @@ -0,0 +1,12 @@ +using System; +using UnityEngine; + +namespace MLAPI.Data +{ + [Serializable] + public class NetworkedPrefab + { + public string name; + public GameObject prefab; + } +} diff --git a/MLAPI/MLAPI.csproj b/MLAPI/MLAPI.csproj index c9f409e..d9d439f 100644 --- a/MLAPI/MLAPI.csproj +++ b/MLAPI/MLAPI.csproj @@ -71,6 +71,7 @@ + diff --git a/MLAPI/MonoBehaviours/Core/NetworkedObject.cs b/MLAPI/MonoBehaviours/Core/NetworkedObject.cs index 402ee97..d6f42bd 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkedObject.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkedObject.cs @@ -12,6 +12,15 @@ namespace MLAPI.MonoBehaviours.Core [AddComponentMenu("MLAPI/NetworkedObject", -99)] public sealed class NetworkedObject : MonoBehaviour { + private void OnValidate() + { + if(string.IsNullOrEmpty(NetworkedPrefabName)) + { + Debug.LogWarning("MLAPI: The networked object " + gameObject.name + " has not been assigned a networkedPrefabName. Setting it to " + gameObject.name); + NetworkedPrefabName = gameObject.name; + } + } + /// /// Gets the unique ID of this object that is synced across the network /// @@ -35,16 +44,9 @@ namespace MLAPI.MonoBehaviours.Core } internal uint ownerClientId = new NetId(0, 0, false, true).GetClientId(); /// - /// The index of the prefab used to spawn this in the spawnablePrefabs list + /// The name of the NetworkedPrefab /// - public int SpawnablePrefabIndex - { - get - { - return spawnablePrefabIndex; - } - } - internal int spawnablePrefabIndex; + public string NetworkedPrefabName = string.Empty; /// /// Gets if this object is a player object /// @@ -57,11 +59,6 @@ namespace MLAPI.MonoBehaviours.Core } internal bool _isPlayerObject = false; /// - /// Gets or sets if this object should be replicated across the network. Can only be changed before the object is spawned - /// - [SerializeField] - public bool ServerOnly = false; - /// /// Gets if this object is part of a pool /// public bool isPooledObject @@ -115,7 +112,7 @@ namespace MLAPI.MonoBehaviours.Core } } internal bool _isSpawned = false; - internal bool sceneObject = false; + internal bool? sceneObject = null; private void OnDestroy() { @@ -129,7 +126,7 @@ namespace MLAPI.MonoBehaviours.Core public void Spawn() { if (NetworkingManager.singleton != null) - SpawnManager.OnSpawnObject(this); + SpawnManager.SpawnPrefabIndexServer(this); } /// /// Spawns an object across the network with a given owner. Can only be called from server @@ -138,7 +135,7 @@ namespace MLAPI.MonoBehaviours.Core public void SpawnWithOwnership(uint clientId) { if (NetworkingManager.singleton != null) - SpawnManager.OnSpawnObject(this, clientId); + SpawnManager.SpawnPrefabIndexServer(this, clientId); } /// /// Removes all ownership of an object from any client. Can only be called from server diff --git a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs index 64bd323..27e6139 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Security.Cryptography; using MLAPI.NetworkingManagerComponents.Cryptography; using MLAPI.NetworkingManagerComponents.Core; +using UnityEngine.SceneManagement; namespace MLAPI.MonoBehaviours.Core { @@ -152,24 +153,29 @@ namespace MLAPI.MonoBehaviours.Core private void OnValidate() { - if (NetworkConfig.SpawnablePrefabs != null) + if(NetworkConfig.EnableSceneSwitching && !NetworkConfig.RegisteredScenes.Contains(SceneManager.GetActiveScene().name)) { - for (int i = 0; i < NetworkConfig.SpawnablePrefabs.Count; i++) + Debug.LogWarning("MLAPI: The active scene is not registered as a networked scene. The MLAPI has added it"); + NetworkConfig.RegisteredScenes.Add(SceneManager.GetActiveScene().name); + } + if(!NetworkConfig.EnableSceneSwitching && NetworkConfig.HandleObjectSpawning) + { + Debug.LogWarning("MLAPI: Please be aware that Scene objects are NOT supported if SceneManagement is turned on, even if HandleObjectSpawning is turned on"); + } + if(NetworkConfig.HandleObjectSpawning) + { + for (int i = 0; i < NetworkConfig.NetworkedPrefabs.Count; i++) { - if (NetworkConfig.SpawnablePrefabs[i] == null) - continue; - NetworkedObject netObject = NetworkConfig.SpawnablePrefabs[i].GetComponentInChildren(); - if (netObject == null) + if (string.IsNullOrEmpty(NetworkConfig.NetworkedPrefabs[i].name)) { - Debug.LogWarning("MLAPI: All SpawnablePrefabs need a NetworkedObject component. Please add one to the prefab " + NetworkConfig.SpawnablePrefabs[i].gameObject.name); - continue; + Debug.LogWarning("MLAPI: The prefab " + NetworkConfig.NetworkedPrefabs[i].prefab.name + " does not have a set NetworkedPrefab name. Setting it to " + NetworkConfig.NetworkedPrefabs[i].prefab.name); + NetworkConfig.NetworkedPrefabs[i].name = NetworkConfig.NetworkedPrefabs[i].prefab.name; } - netObject.spawnablePrefabIndex = i; } } - if (NetworkConfig.PlayerPrefab != null) + if (!string.IsNullOrEmpty(NetworkConfig.PlayerPrefabName)) { - NetworkedObject netObject = NetworkConfig.PlayerPrefab.GetComponentInChildren(); + NetworkedObject netObject = NetworkConfig.NetworkedPrefabs.Find(x => x.name == NetworkConfig.PlayerPrefabName).prefab.GetComponentInChildren(); if (netObject == null) { Debug.LogWarning("MLAPI: The player object needs a NetworkedObject component."); @@ -193,7 +199,7 @@ namespace MLAPI.MonoBehaviours.Core } } - private ConnectionConfig Init() + private ConnectionConfig Init(bool server) { networkTime = 0f; lastSendTickTime = 0; @@ -218,16 +224,34 @@ namespace MLAPI.MonoBehaviours.Core NetworkSceneManager.sceneIndexToString = new Dictionary(); NetworkSceneManager.sceneNameToIndex = new Dictionary(); - if (NetworkConfig.HandleObjectSpawning) + if(NetworkConfig.HandleObjectSpawning) { - NetworkedObject[] sceneObjects = FindObjectsOfType(); - for (int i = 0; i < sceneObjects.Length; i++) + NetworkConfig.NetworkPrefabIds = new Dictionary(); + NetworkConfig.NetworkPrefabNames = new Dictionary(); + NetworkConfig.NetworkedPrefabs.OrderBy(x => x.name); + for (int i = 0; i < NetworkConfig.NetworkedPrefabs.Count; i++) { - uint networkId = SpawnManager.GetNetworkObjectId(); - SpawnManager.spawnedObjects.Add(networkId, sceneObjects[i]); - sceneObjects[i]._isSpawned = true; - sceneObjects[i].sceneObject = true; - sceneObjects[i].InvokeBehaviourNetworkSpawn(); + NetworkConfig.NetworkPrefabIds.Add(NetworkConfig.NetworkedPrefabs[i].name, i); + NetworkConfig.NetworkPrefabNames.Add(i, NetworkConfig.NetworkedPrefabs[i].name); + } + if (NetworkConfig.EnableSceneSwitching) + { + SpawnManager.MarkSceneObjects(); + if (NetworkConfig.HandleObjectSpawning) + { + if (server) + { + bool isServerState = _isServer; + _isServer = true; + NetworkedObject[] networkedObjects = FindObjectsOfType(); + for (int i = 0; i < networkedObjects.Length; i++) + { + if (networkedObjects[i].sceneObject == null || networkedObjects[i].sceneObject == true) + networkedObjects[i].Spawn(); + } + _isServer = isServerState; + } + } } } @@ -313,6 +337,7 @@ namespace MLAPI.MonoBehaviours.Core MessageManager.messageTypes.Add("MLAPI_DESTROY_POOL_OBJECT", 7); MessageManager.messageTypes.Add("MLAPI_CHANGE_OWNER", 8); MessageManager.messageTypes.Add("MLAPI_SYNC_VAR_UPDATE", 9); + MessageManager.messageTypes.Add("MLAPI_ADD_OBJECTS", 10); List messageTypes = new List(NetworkConfig.MessageTypes) { @@ -401,7 +426,7 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(); + ConnectionConfig cConfig = Init(true); if (NetworkConfig.ConnectionApproval) { if (ConnectionApprovalCallback == null) @@ -437,7 +462,7 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(); + ConnectionConfig cConfig = Init(false); HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); serverHostId = NetworkTransport.AddHost(hostTopology, 0, null); @@ -446,7 +471,6 @@ namespace MLAPI.MonoBehaviours.Core isListening = true; byte error; serverConnectionId = NetworkTransport.Connect(serverHostId, NetworkConfig.ConnectAddress, NetworkConfig.ConnectPort, 0, out error); - Debug.LogWarning("MLAPI: Connection failed: " + ((NetworkError)error).ToString()); } /// @@ -460,7 +484,7 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(); + ConnectionConfig cConfig = Init(false); HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); serverHostId = NetworkTransport.AddWebsocketHost(hostTopology, 0, null); @@ -469,7 +493,6 @@ namespace MLAPI.MonoBehaviours.Core isListening = true; byte error; serverConnectionId = NetworkTransport.Connect(serverHostId, NetworkConfig.ConnectAddress, NetworkConfig.ConnectPort, 0, out error); - Debug.LogWarning("MLAPI: Connection failed: " + ((NetworkError)error).ToString()); } /// @@ -541,7 +564,7 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: Cannot start host while an instance is already running"); return; } - ConnectionConfig cConfig = Init(); + ConnectionConfig cConfig = Init(true); if (NetworkConfig.ConnectionApproval) { if (ConnectionApprovalCallback == null) @@ -876,7 +899,7 @@ namespace MLAPI.MonoBehaviours.Core return; } byte[] aesKey = new byte[0]; - if(NetworkConfig.EnableEncryption) + if (NetworkConfig.EnableEncryption) { ushort diffiePublicSize = messageReader.ReadUInt16(); byte[] diffiePublic = messageReader.ReadBytes(diffiePublicSize); @@ -906,7 +929,7 @@ namespace MLAPI.MonoBehaviours.Core { myClientId = messageReader.ReadUInt32(); uint sceneIndex = 0; - if(NetworkConfig.EnableSceneSwitching) + if (NetworkConfig.EnableSceneSwitching) { sceneIndex = messageReader.ReadUInt32(); } @@ -924,7 +947,7 @@ namespace MLAPI.MonoBehaviours.Core { rsa.PersistKeyInCsp = false; rsa.FromXmlString(NetworkConfig.RSAPublicKey); - if(!rsa.VerifyData(serverPublicKey, new SHA512CryptoServiceProvider(), publicKeySignature)) + if (!rsa.VerifyData(serverPublicKey, new SHA512CryptoServiceProvider(), publicKeySignature)) { //Man in the middle. Debug.LogWarning("MLAPI: Signature doesnt match for the key exchange public part. Disconnecting"); @@ -951,7 +974,7 @@ namespace MLAPI.MonoBehaviours.Core uint _clientId = messageReader.ReadUInt32(); connectedClients.Add(_clientId, new NetworkedClient() { ClientId = _clientId }); } - if(NetworkConfig.HandleObjectSpawning) + if (NetworkConfig.HandleObjectSpawning) { SpawnManager.DestroySceneObjects(); int objectCount = messageReader.ReadInt32(); @@ -962,6 +985,7 @@ namespace MLAPI.MonoBehaviours.Core uint ownerId = messageReader.ReadUInt32(); int prefabId = messageReader.ReadInt32(); bool isActive = messageReader.ReadBoolean(); + bool sceneObject = messageReader.ReadBoolean(); float xPos = messageReader.ReadSingle(); float yPos = messageReader.ReadSingle(); @@ -977,14 +1001,15 @@ namespace MLAPI.MonoBehaviours.Core } else { - GameObject go = SpawnManager.SpawnObject(prefabId, networkId, ownerId, + GameObject go = SpawnManager.SpawnPrefabIndexClient(prefabId, networkId, ownerId, new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot)); + go.GetComponent().sceneObject = sceneObject; go.SetActive(isActive); } } } - if(NetworkConfig.EnableSceneSwitching) + if (NetworkConfig.EnableSceneSwitching) { NetworkSceneManager.OnSceneSwitch(sceneIndex); } @@ -1004,12 +1029,13 @@ namespace MLAPI.MonoBehaviours.Core { using (BinaryReader messageReader = new BinaryReader(messageReadStream)) { - if(NetworkConfig.HandleObjectSpawning) + if (NetworkConfig.HandleObjectSpawning) { bool isPlayerObject = messageReader.ReadBoolean(); uint networkId = messageReader.ReadUInt32(); uint ownerId = messageReader.ReadUInt32(); int prefabId = messageReader.ReadInt32(); + bool sceneObject = messageReader.ReadBoolean(); float xPos = messageReader.ReadSingle(); float yPos = messageReader.ReadSingle(); @@ -1026,8 +1052,9 @@ namespace MLAPI.MonoBehaviours.Core } else { - SpawnManager.SpawnObject(prefabId, networkId, ownerId, - new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot)); + GameObject go = SpawnManager.SpawnPrefabIndexClient(prefabId, networkId, ownerId, + new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot)); + go.GetComponent().sceneObject = sceneObject; } } else @@ -1042,7 +1069,7 @@ namespace MLAPI.MonoBehaviours.Core case 3: //Server informs client another client disconnected //MLAPI_CLIENT_DISCONNECT - if(isClient) + if (isClient) { using (MemoryStream messageReadStream = new MemoryStream(incommingData)) { @@ -1056,7 +1083,7 @@ namespace MLAPI.MonoBehaviours.Core break; case 4: //Server infroms clients to destroy an object - if(isClient) + if (isClient) { using (MemoryStream messageReadStream = new MemoryStream(incommingData)) { @@ -1079,10 +1106,10 @@ namespace MLAPI.MonoBehaviours.Core NetworkSceneManager.OnSceneSwitch(messageReader.ReadUInt32()); } } - } + } break; case 6: //Spawn pool object - if(isClient) + if (isClient) { using (MemoryStream messageReadStream = new MemoryStream(incommingData)) { @@ -1103,7 +1130,7 @@ namespace MLAPI.MonoBehaviours.Core } break; case 7: //Destroy pool object - if(isClient) + if (isClient) { using (MemoryStream messageReadStream = new MemoryStream(incommingData)) { @@ -1116,7 +1143,7 @@ namespace MLAPI.MonoBehaviours.Core } break; case 8: //Change owner - if(isClient) + if (isClient) { using (MemoryStream messageReadStream = new MemoryStream(incommingData)) { @@ -1129,7 +1156,7 @@ namespace MLAPI.MonoBehaviours.Core //We are current owner. SpawnManager.spawnedObjects[netId].InvokeBehaviourOnLostOwnership(); } - if(ownerClientId == MyClientId) + if (ownerClientId == MyClientId) { //We are new owner. SpawnManager.spawnedObjects[netId].InvokeBehaviourOnGainedOwnership(); @@ -1154,17 +1181,17 @@ namespace MLAPI.MonoBehaviours.Core for (int i = 0; i < dirtyCount; i++) { byte fieldIndex = messageReader.ReadByte(); - if(!SpawnManager.spawnedObjects.ContainsKey(netId)) + if (!SpawnManager.spawnedObjects.ContainsKey(netId)) { Debug.LogWarning("MLAPI: Sync message recieved for a non existant object with id: " + netId); return; } - else if(SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex) == null) + else if (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex) == null) { Debug.LogWarning("MLAPI: Sync message recieved for a non existant behaviour"); return; } - else if(fieldIndex > (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedFieldTypes.Count - 1)) + else if (fieldIndex > (SpawnManager.spawnedObjects[netId].GetBehaviourAtOrderIndex(orderIndex).syncedFieldTypes.Count - 1)) { Debug.LogWarning("MLAPI: Sync message recieved for field out of bounds"); return; @@ -1240,6 +1267,51 @@ namespace MLAPI.MonoBehaviours.Core } } } + break; + case 10: + if (isClient) //MLAPI_ADD_OBJECTS (plural) + { + Debug.LogError("AddObjects"); + using (MemoryStream messageReadStream = new MemoryStream(incommingData)) + { + using (BinaryReader messageReader = new BinaryReader(messageReadStream)) + { + if (NetworkConfig.HandleObjectSpawning) + { + ushort objectCount = messageReader.ReadUInt16(); + for (int i = 0; i < objectCount; i++) + { + bool isPlayerObject = messageReader.ReadBoolean(); + uint networkId = messageReader.ReadUInt32(); + uint ownerId = messageReader.ReadUInt32(); + int prefabId = messageReader.ReadInt32(); + bool sceneObject = messageReader.ReadBoolean(); + + float xPos = messageReader.ReadSingle(); + float yPos = messageReader.ReadSingle(); + float zPos = messageReader.ReadSingle(); + + float xRot = messageReader.ReadSingle(); + float yRot = messageReader.ReadSingle(); + float zRot = messageReader.ReadSingle(); + + if (isPlayerObject) + { + connectedClients.Add(ownerId, new NetworkedClient() { ClientId = ownerId }); + SpawnManager.SpawnPlayerObject(ownerId, networkId); + } + else + { + GameObject go = SpawnManager.SpawnPrefabIndexClient(prefabId, networkId, ownerId, + new Vector3(xPos, yPos, zPos), Quaternion.Euler(xRot, yRot, zRot)); + go.GetComponent().sceneObject = sceneObject; + } + } + } + } + } + } + break; } #endregion @@ -1472,6 +1544,8 @@ namespace MLAPI.MonoBehaviours.Core internal void Send(string messageType, string channelName, byte[] data, uint? networkId = null, ushort? orderId = null) { + if (connectedClients.Count == 0) + return; if (NetworkConfig.EncryptedChannels.Contains(channelName)) { Debug.LogWarning("MLAPI: Cannot send messages over encrypted channel to multiple clients."); @@ -1672,9 +1746,9 @@ namespace MLAPI.MonoBehaviours.Core GameObject go = SpawnManager.SpawnPlayerObject(clientId, networkId); connectedClients[clientId].PlayerObject = go; } - int sizeOfStream = 16 + ((connectedClients.Count - 1) * 4); + int sizeOfStream = 17 + ((connectedClients.Count - 1) * 4); - int amountOfObjectsToSend = SpawnManager.spawnedObjects.Values.Count(x => x.ServerOnly == false); + int amountOfObjectsToSend = SpawnManager.spawnedObjects.Values.Count(); if (NetworkConfig.HandleObjectSpawning) { @@ -1734,13 +1808,12 @@ namespace MLAPI.MonoBehaviours.Core foreach (KeyValuePair pair in SpawnManager.spawnedObjects) { - if (pair.Value.ServerOnly) - continue; writer.Write(pair.Value.isPlayerObject); writer.Write(pair.Value.NetworkId); writer.Write(pair.Value.OwnerClientId); - writer.Write(pair.Value.SpawnablePrefabIndex); + writer.Write(NetworkConfig.NetworkPrefabIds[pair.Value.NetworkedPrefabName]); writer.Write(pair.Value.gameObject.activeInHierarchy); + writer.Write(pair.Value.sceneObject == null ? true : pair.Value.sceneObject.Value); writer.Write(pair.Value.transform.position.x); writer.Write(pair.Value.transform.position.y); @@ -1761,7 +1834,7 @@ namespace MLAPI.MonoBehaviours.Core //Inform old clients of the new player if(NetworkConfig.HandleObjectSpawning) - sizeOfStream = 13; + sizeOfStream = 38; else sizeOfStream = 4; @@ -1775,6 +1848,15 @@ namespace MLAPI.MonoBehaviours.Core writer.Write(connectedClients[clientId].PlayerObject.GetComponent().NetworkId); writer.Write(clientId); writer.Write(-1); + writer.Write(false); + + writer.Write(connectedClients[clientId].PlayerObject.transform.position.x); + writer.Write(connectedClients[clientId].PlayerObject.transform.position.y); + writer.Write(connectedClients[clientId].PlayerObject.transform.position.z); + + writer.Write(connectedClients[clientId].PlayerObject.transform.rotation.eulerAngles.x); + writer.Write(connectedClients[clientId].PlayerObject.transform.rotation.eulerAngles.y); + writer.Write(connectedClients[clientId].PlayerObject.transform.rotation.eulerAngles.z); } else { diff --git a/MLAPI/NetworkingManagerComponents/Core/NetworkSceneManager.cs b/MLAPI/NetworkingManagerComponents/Core/NetworkSceneManager.cs index 1d6baa5..eb5078f 100644 --- a/MLAPI/NetworkingManagerComponents/Core/NetworkSceneManager.cs +++ b/MLAPI/NetworkingManagerComponents/Core/NetworkSceneManager.cs @@ -51,6 +51,7 @@ namespace MLAPI.NetworkingManagerComponents.Core 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(); @@ -67,6 +68,10 @@ namespace MLAPI.NetworkingManagerComponents.Core } } + /// + /// Called on client + /// + /// internal static void OnSceneSwitch(uint sceneIndex) { if (!NetworkingManager.singleton.NetworkConfig.EnableSceneSwitching) @@ -79,6 +84,11 @@ namespace MLAPI.NetworkingManagerComponents.Core Debug.LogWarning("MLAPI: Server requested a scene switch to a non registered scene"); return; } + else if(SceneManager.GetActiveScene().name == sceneIndexToString[sceneIndex]) + { + return; //This scene is already loaded. This usually happends at first load + } + SpawnManager.DestroySceneObjects(); lastScene = SceneManager.GetActiveScene(); AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneIndexToString[sceneIndex], LoadSceneMode.Additive); sceneLoad.completed += OnSceneLoaded; @@ -100,6 +110,16 @@ namespace MLAPI.NetworkingManagerComponents.Core private static void OnSceneUnload(AsyncOperation operation) { isSwitching = false; + if(NetworkingManager.singleton.isServer) + { + SpawnManager.MarkSceneObjects(); + SpawnManager.FlushSceneObjects(); + } + else + { + Debug.LogError("DESTROING OBJECTS"); + SpawnManager.DestroySceneObjects(); + } } } } diff --git a/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs b/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs index beb1ec4..81ac495 100644 --- a/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs +++ b/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs @@ -65,81 +65,183 @@ namespace MLAPI.NetworkingManagerComponents.Core netManager.Send("MLAPI_CHANGE_OWNER", "MLAPI_INTERNAL", stream.GetBuffer()); } } - - internal static void DestroySceneObjects() - { - NetworkedObject[] netObjects = MonoBehaviour.FindObjectsOfType(); - for (int i = 0; i < netObjects.Length; i++) - { - if (netObjects[i].sceneObject) - MonoBehaviour.Destroy(netObjects[i].gameObject); - } - } - + internal static void DestroyNonSceneObjects() { if(spawnedObjects != null) { foreach (KeyValuePair netObject in spawnedObjects) { - if (!netObject.Value.sceneObject) + if (netObject.Value.sceneObject != null && netObject.Value.sceneObject.Value == false) MonoBehaviour.Destroy(netObject.Value.gameObject); } } } - internal static GameObject SpawnObject(int spawnablePrefabIndex, uint networkId, uint ownerId, Vector3 position, Quaternion rotation) + internal static void DestroySceneObjects() { - if (spawnablePrefabIndex >= netManager.NetworkConfig.SpawnablePrefabs.Count) + NetworkedObject[] netObjects = MonoBehaviour.FindObjectsOfType(); + for (int i = 0; i < netObjects.Length; i++) + { + if (netObjects[i].sceneObject == null || netObjects[i].sceneObject.Value == true) + MonoBehaviour.Destroy(netObjects[i].gameObject); + } + } + + internal static void MarkSceneObjects() + { + NetworkedObject[] netObjects = MonoBehaviour.FindObjectsOfType(); + for (int i = 0; i < netObjects.Length; i++) + { + if (netObjects[i].sceneObject == null) + netObjects[i].sceneObject = true; + } + } + + internal static void FlushSceneObjects() + { + if (!NetworkingManager.singleton.isServer) + return; + + List sceneObjectsToSync = new List(); + foreach (KeyValuePair pair in SpawnManager.spawnedObjects) + { + if (pair.Value.sceneObject == null || pair.Value.sceneObject == true) + sceneObjectsToSync.Add(pair.Value); + } + int sizeOfStream = 2 + (38 * sceneObjectsToSync.Count); //The two is the base size, it's a ushort containing the amount of objects. Each object takes 38 bytes + using (MemoryStream stream = new MemoryStream(sizeOfStream)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + writer.Write((ushort)sceneObjectsToSync.Count); + for (int i = 0; i < sceneObjectsToSync.Count; i++) + { + writer.Write(false); //isLocalPlayer + writer.Write(sceneObjectsToSync[i].NetworkId); + writer.Write(sceneObjectsToSync[i].OwnerClientId); + writer.Write(NetworkingManager.singleton.NetworkConfig.NetworkPrefabIds[sceneObjectsToSync[i].NetworkedPrefabName]); + + writer.Write(sceneObjectsToSync[i].transform.position.x); + writer.Write(sceneObjectsToSync[i].transform.position.y); + writer.Write(sceneObjectsToSync[i].transform.position.z); + + writer.Write(sceneObjectsToSync[i].transform.rotation.eulerAngles.x); + writer.Write(sceneObjectsToSync[i].transform.rotation.eulerAngles.y); + writer.Write(sceneObjectsToSync[i].transform.rotation.eulerAngles.z); + } + } + NetworkingManager.singleton.Send("MLAPI_ADD_OBJECTS", "MLAPI_INTERNAL", stream.GetBuffer()); + } + } + + internal static GameObject SpawnPrefabIndexClient(int networkedPrefabId, uint networkId, uint owner, Vector3 position, Quaternion rotation) + { + if (!netManager.NetworkConfig.NetworkPrefabNames.ContainsKey(networkedPrefabId)) + { + Debug.LogWarning("MLAPI: Cannot spawn the object, invalid prefabIndex"); return null; - GameObject go = MonoBehaviour.Instantiate(netManager.NetworkConfig.SpawnablePrefabs[spawnablePrefabIndex]); + } + + GameObject go = MonoBehaviour.Instantiate(netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].prefab); NetworkedObject netObject = go.GetComponent(); if (netObject == null) { Debug.LogWarning("MLAPI: Please add a NetworkedObject component to the root of all spawnable objects"); netObject = go.AddComponent(); } - netObject.spawnablePrefabIndex = spawnablePrefabIndex; - if (netManager.isServer) - { - netObject.networkId = GetNetworkObjectId(); - } - else - { - netObject.networkId = networkId; - } - netObject.ownerClientId = ownerId; + netObject.NetworkedPrefabName = netManager.NetworkConfig.NetworkPrefabNames[networkedPrefabId]; + netObject._isSpawned = true; + netObject._isPooledObject = false; + netObject.networkId = networkId; + netObject.ownerClientId = owner; netObject.transform.position = position; netObject.transform.rotation = rotation; - netObject._isSpawned = true; - spawnedObjects.Add(netObject.NetworkId, netObject); netObject.InvokeBehaviourNetworkSpawn(); return go; } + 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 (MemoryStream stream = new MemoryStream(37)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + writer.Write(false); + writer.Write(netObject.NetworkId); + writer.Write(netObject.OwnerClientId); + writer.Write(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]); + + writer.Write(netObject.transform.position.x); + writer.Write(netObject.transform.position.y); + writer.Write(netObject.transform.position.z); + + writer.Write(netObject.transform.rotation.eulerAngles.x); + writer.Write(netObject.transform.rotation.eulerAngles.y); + writer.Write(netObject.transform.rotation.eulerAngles.z); + } + + netManager.Send("MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", stream.GetBuffer()); + } + } + internal static GameObject SpawnPlayerObject(uint clientId, uint networkId) { - if (netManager.NetworkConfig.PlayerPrefab == null) + if (string.IsNullOrEmpty(netManager.NetworkConfig.PlayerPrefabName) || !netManager.NetworkConfig.NetworkPrefabIds.ContainsKey(netManager.NetworkConfig.PlayerPrefabName)) + { + Debug.LogWarning("MLAPI: There is no player prefab in the NetworkConfig, or it's not registered at as a spawnable prefab"); return null; - GameObject go = MonoBehaviour.Instantiate(netManager.NetworkConfig.PlayerPrefab); + } + GameObject go = MonoBehaviour.Instantiate(netManager.NetworkConfig.NetworkedPrefabs[netManager.NetworkConfig.NetworkPrefabIds[netManager.NetworkConfig.PlayerPrefabName]].prefab); NetworkedObject netObject = go.GetComponent(); if (netObject == null) { Debug.LogWarning("MLAPI: Please add a NetworkedObject component to the root of the player prefab"); netObject = go.AddComponent(); } - netObject.ownerClientId = clientId; + if (NetworkingManager.singleton.isServer) - { netObject.networkId = GetNetworkObjectId(); - } else - { netObject.networkId = networkId; - } + + netObject._isPooledObject = false; + netObject.ownerClientId = clientId; netObject._isPlayerObject = true; netObject._isSpawned = true; + netObject.sceneObject = false; netManager.connectedClients[clientId].PlayerObject = go; spawnedObjects.Add(netObject.NetworkId, netObject); netObject.InvokeBehaviourNetworkSpawn(); @@ -159,7 +261,7 @@ namespace MLAPI.NetworkingManagerComponents.Core if (netManager != null && netManager.isServer) { releasedNetworkObjectIds.Push(networkId); - if (spawnedObjects[networkId] != null && !spawnedObjects[networkId].ServerOnly) + if (spawnedObjects[networkId] != null) { using (MemoryStream stream = new MemoryStream(4)) { @@ -167,11 +269,7 @@ namespace MLAPI.NetworkingManagerComponents.Core { writer.Write(networkId); } - //If we are host, send to everyone except ourselves. Otherwise, send to all - if (netManager != null && netManager.isHost) - netManager.Send("MLAPI_DESTROY_OBJECT", "MLAPI_INTERNAL", stream.GetBuffer(), new NetId(0, 0, true, false).GetClientId()); - else - netManager.Send("MLAPI_DESTROY_OBJECT", "MLAPI_INTERNAL", stream.GetBuffer()); + netManager.Send("MLAPI_DESTROY_OBJECT", "MLAPI_INTERNAL", stream.GetBuffer()); } } } @@ -179,63 +277,5 @@ namespace MLAPI.NetworkingManagerComponents.Core MonoBehaviour.Destroy(go); spawnedObjects.Remove(networkId); } - - internal static void OnSpawnObject(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 (netObject.SpawnablePrefabIndex == -1) - { - Debug.LogWarning("MLAPI: Invalid prefab index"); - return; - } - else if (netObject.ServerOnly) - { - Debug.LogWarning("MLAPI: Server only objects does not have to be spawned"); - return; - } - else if (!netManager.NetworkConfig.HandleObjectSpawning) - { - Debug.LogWarning("MLAPI: NetworkingConfiguration is set to not handle object spawning"); - return; - } - uint netId = GetNetworkObjectId(); - netObject.networkId = netId; - spawnedObjects.Add(netId, netObject); - netObject._isSpawned = true; - if (clientOwnerId != null) - { - netObject.ownerClientId = clientOwnerId.Value; - NetworkingManager.singleton.connectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject); - } - using (MemoryStream stream = new MemoryStream(37)) - { - using (BinaryWriter writer = new BinaryWriter(stream)) - { - writer.Write(false); - writer.Write(netObject.NetworkId); - writer.Write(netObject.OwnerClientId); - writer.Write(netObject.SpawnablePrefabIndex); - - writer.Write(netObject.transform.position.x); - writer.Write(netObject.transform.position.y); - writer.Write(netObject.transform.position.z); - - writer.Write(netObject.transform.rotation.eulerAngles.x); - writer.Write(netObject.transform.rotation.eulerAngles.y); - writer.Write(netObject.transform.rotation.eulerAngles.z); - } - - netManager.Send("MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", stream.GetBuffer()); - } - } } }