From b8e1e925d4b63758690a3fd725ea77a213196cb7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albin=20Cor=C3=A9n?= <2108U9@gmail.com>
Date: Thu, 5 Apr 2018 21:21:57 +0200
Subject: [PATCH] Reworked Object spawning system
---
MLAPI/Data/NetworkConfig.cs | 13 +-
MLAPI/Data/NetworkPool.cs | 4 +-
MLAPI/Data/NetworkedPrefab.cs | 12 +
MLAPI/MLAPI.csproj | 1 +
MLAPI/MonoBehaviours/Core/NetworkedObject.cs | 31 ++-
.../MonoBehaviours/Core/NetworkingManager.cs | 184 ++++++++++----
.../Core/NetworkSceneManager.cs | 20 ++
.../Core/SpawnManager.cs | 236 ++++++++++--------
8 files changed, 329 insertions(+), 172 deletions(-)
create mode 100644 MLAPI/Data/NetworkedPrefab.cs
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());
- }
- }
}
}