diff --git a/MLAPI/Data/Channel.cs b/MLAPI/Data/Channel.cs index dcc92cd..d8f0044 100644 --- a/MLAPI/Data/Channel.cs +++ b/MLAPI/Data/Channel.cs @@ -1,5 +1,4 @@ using System; -using UnityEngine.Networking; namespace MLAPI.Data { @@ -16,7 +15,7 @@ namespace MLAPI.Data /// /// The Transport QOS type /// - public QosType Type; + public ChannelType Type; /// /// Wheter or not the channel should be encrypted /// diff --git a/MLAPI/Data/NetworkConfig.cs b/MLAPI/Data/NetworkConfig.cs index 2db8a8a..4bf4a2c 100644 --- a/MLAPI/Data/NetworkConfig.cs +++ b/MLAPI/Data/NetworkConfig.cs @@ -1,5 +1,6 @@ using MLAPI.NetworkingManagerComponents.Binary; using MLAPI.NetworkingManagerComponents.Cryptography; +using MLAPI.Data.Transports.UNET; using System; using System.Collections.Generic; using System.Security.Cryptography; @@ -20,15 +21,7 @@ namespace MLAPI.Data /// /// The transport hosts the sever uses /// - public List ServerTransports = new List() - { - new TransportHost() - { - Name = "UDP Socket", - Port = 7777, - Websockets = false - } - }; + public IUDPTransport NetworkTransport = new UnetTransport(); /// /// Channels used by the NetworkedTransport /// diff --git a/MLAPI/Data/Transports/ChannelType.cs b/MLAPI/Data/Transports/ChannelType.cs new file mode 100644 index 0000000..98ebff9 --- /dev/null +++ b/MLAPI/Data/Transports/ChannelType.cs @@ -0,0 +1,17 @@ +namespace MLAPI.Data +{ + public enum ChannelType + { + Unreliable, + UnreliableFragmented, + UnreliableSequenced, + Reliable, + ReliableFragmented, + ReliableSequenced, + StateUpdate, + ReliableStateUpdate, + AllCostDelivery, + UnreliableFragmentedSequenced, + ReliableFragmentedSequenced + } +} diff --git a/MLAPI/Data/Transports/IUDPTransport.cs b/MLAPI/Data/Transports/IUDPTransport.cs new file mode 100644 index 0000000..24706fb --- /dev/null +++ b/MLAPI/Data/Transports/IUDPTransport.cs @@ -0,0 +1,23 @@ +namespace MLAPI.Data +{ + public interface IUDPTransport + { + ChannelType InternalChannel { get; } + uint ServerNetId { get; } + uint HostDummyId { get; } + uint InvalidDummyId { get; } + void QueueMessageForSending(uint clientId, ref byte[] dataBuffer, int dataSize, int channelId, bool skipQueue, out byte error); + void SendQueue(uint clientId, out byte error); + NetEventType PollReceive(out uint clientId, out int channelId, ref byte[] data, int bufferSize, out int receivedSize, out byte error); + int AddChannel(ChannelType type, object settings); + void Connect(string address, int port, object settings, out byte error); + void RegisterServerListenSocket(object settings); + void DisconnectClient(uint clientId); + void DisconnectFromServer(); + int GetCurrentRTT(uint clientId, out byte error); + int GetRemoteDelayTimeMS(uint clientId, int remoteTimestamp, out byte error); + int GetNetworkTimestamp(); + object GetSettings(); + void Shutdown(); + } +} diff --git a/MLAPI/Data/Transports/NetEventType.cs b/MLAPI/Data/Transports/NetEventType.cs new file mode 100644 index 0000000..4eea45d --- /dev/null +++ b/MLAPI/Data/Transports/NetEventType.cs @@ -0,0 +1,10 @@ +namespace MLAPI.Data +{ + public enum NetEventType + { + Data, + Connect, + Disconnect, + Nothing + } +} diff --git a/MLAPI/Data/NetId.cs b/MLAPI/Data/Transports/UNET/NetId.cs similarity index 91% rename from MLAPI/Data/NetId.cs rename to MLAPI/Data/Transports/UNET/NetId.cs index 9e8e3ac..442d47d 100644 --- a/MLAPI/Data/NetId.cs +++ b/MLAPI/Data/Transports/UNET/NetId.cs @@ -1,6 +1,4 @@ -using MLAPI.MonoBehaviours.Core; - -namespace MLAPI.Data +namespace MLAPI.Data.Transports.UNET { /// /// Represents a ClientId structure @@ -37,17 +35,6 @@ namespace MLAPI.Data return Meta == 2; } /// - /// Static ServerNetId for comparison - /// - /// The server net identifier. - public static NetId ServerNetId - { - get - { - return new NetId((byte)NetworkingManager.singleton.serverHostId, (ushort)NetworkingManager.singleton.serverConnectionId, false, false); - } - } - /// /// Initializes a new instance of the netId struct from transport values /// /// Host identifier. diff --git a/MLAPI/Data/TransportHost.cs b/MLAPI/Data/Transports/UNET/TransportHost.cs similarity index 94% rename from MLAPI/Data/TransportHost.cs rename to MLAPI/Data/Transports/UNET/TransportHost.cs index ebae508..eb337e2 100644 --- a/MLAPI/Data/TransportHost.cs +++ b/MLAPI/Data/Transports/UNET/TransportHost.cs @@ -1,6 +1,6 @@ using System; -namespace MLAPI.Data +namespace MLAPI.Data.Transports.UNET { /// /// Represents a Transport host diff --git a/MLAPI/Data/Transports/UNET/UnetTransport.cs b/MLAPI/Data/Transports/UNET/UnetTransport.cs new file mode 100644 index 0000000..d66b3bb --- /dev/null +++ b/MLAPI/Data/Transports/UNET/UnetTransport.cs @@ -0,0 +1,183 @@ +using MLAPI.MonoBehaviours.Core; +using System; +using System.Collections.Generic; +using UnityEngine.Networking; + +namespace MLAPI.Data.Transports.UNET +{ + [Serializable] + public class UnetTransport : IUDPTransport + { + public ChannelType InternalChannel { get => ChannelType.ReliableFragmentedSequenced; } + + public uint HostDummyId { get => new NetId(0,0,true,false).GetClientId(); } + + public uint InvalidDummyId { get => new NetId(0, 0, false, true).GetClientId(); } + + public uint ServerNetId { get => new NetId((byte)serverHostId, (ushort)serverConnectionId, false, false).GetClientId(); } + + public int serverConnectionId; + public int serverHostId; + + public List ServerTransports = new List() + { + new TransportHost() + { + Name = "UDP Socket", + Port = 7777, + Websockets = false + } + }; + + public int Connect(string address, int port, object settings, bool websocket, out byte error) + { + NetworkTransport.Init(); + int hostId = NetworkTransport.AddHost((HostTopology)settings); + return NetworkTransport.Connect(hostId, address, port, 0, out error); + } + + public void DisconnectClient(uint clientId) + { + NetId netId = new NetId(clientId); + if (netId.IsHost() || netId.IsInvalid()) + return; + byte error; + NetworkTransport.Disconnect(netId.HostId, netId.ConnectionId, out error); + } + + public void DisconnectFromServer() + { + byte error; + NetworkTransport.Disconnect(serverHostId, serverConnectionId, out error); + } + + public int GetCurrentRTT(uint clientId, out byte error) + { + NetId netId = new NetId(clientId); + return NetworkTransport.GetCurrentRTT(netId.HostId, netId.ConnectionId, out error); + } + + public int GetNetworkTimestamp() + { + return NetworkTransport.GetNetworkTimestamp(); + } + + public int GetRemoteDelayTimeMS(uint clientId, int remoteTimestamp, out byte error) + { + NetId netId = new NetId(clientId); + return NetworkTransport.GetRemoteDelayTimeMS(netId.HostId, netId.ConnectionId, remoteTimestamp, out error); + } + + public NetEventType PollReceive(out uint clientId, out int channelId, ref byte[] data, int bufferSize, out int receivedSize, out byte error) + { + int hostId; + int connectionId; + byte err; + NetworkEventType eventType = NetworkTransport.Receive(out hostId, out connectionId, out channelId, data, bufferSize, out receivedSize, out err); + clientId = new NetId((byte)hostId, (ushort)connectionId, false, false).GetClientId(); + NetworkError errorType = (NetworkError)err; + if (errorType == NetworkError.Timeout) + eventType = NetworkEventType.DisconnectEvent; //In UNET. Timeouts are not disconnects. We have to translate that here. + error = 0; + + //Translate NetworkEventType to NetEventType + switch (eventType) + { + case NetworkEventType.DataEvent: + return NetEventType.Data; + case NetworkEventType.ConnectEvent: + return NetEventType.Connect; + case NetworkEventType.DisconnectEvent: + return NetEventType.Disconnect; + case NetworkEventType.Nothing: + return NetEventType.Nothing; + case NetworkEventType.BroadcastEvent: + return NetEventType.Nothing; + } + return NetEventType.Nothing; + } + + public void QueueMessageForSending(uint clientId, ref byte[] dataBuffer, int dataSize, int channelId, bool skipqueue, out byte error) + { + NetId netId = new NetId(clientId); + if (netId.IsHost() || netId.IsInvalid()) + { + error = 0; + return; + } + if (skipqueue) + NetworkTransport.Send(netId.HostId, netId.ConnectionId, channelId, dataBuffer, dataSize, out error); + else + NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channelId, dataBuffer, dataSize, out error); + } + + public void Shutdown() + { + NetworkTransport.Shutdown(); + } + + public void SendQueue(uint clientId, out byte error) + { + NetId netId = new NetId(clientId); + NetworkTransport.SendQueuedMessages(netId.HostId, netId.ConnectionId, out error); + } + + public void RegisterServerListenSocket(object settings) + { + HostTopology topology = new HostTopology((ConnectionConfig)settings, NetworkingManager.singleton.NetworkConfig.MaxConnections); + for (int i = 0; i < ServerTransports.Count; i++) + { + if (ServerTransports[i].Websockets) + NetworkTransport.AddWebsocketHost(topology, ServerTransports[i].Port); + else + NetworkTransport.AddHost(topology, ServerTransports[i].Port); + } + } + + public int AddChannel(ChannelType type, object settings) + { + ConnectionConfig config = (ConnectionConfig)settings; + switch (type) + { + case ChannelType.Unreliable: + return config.AddChannel(QosType.Unreliable); + case ChannelType.UnreliableFragmented: + return config.AddChannel(QosType.UnreliableFragmented); + case ChannelType.UnreliableSequenced: + return config.AddChannel(QosType.UnreliableSequenced); + case ChannelType.Reliable: + return config.AddChannel(QosType.Reliable); + case ChannelType.ReliableFragmented: + return config.AddChannel(QosType.ReliableFragmented); + case ChannelType.ReliableSequenced: + return config.AddChannel(QosType.ReliableSequenced); + case ChannelType.StateUpdate: + return config.AddChannel(QosType.StateUpdate); + case ChannelType.ReliableStateUpdate: + return config.AddChannel(QosType.ReliableStateUpdate); + case ChannelType.AllCostDelivery: + return config.AddChannel(QosType.AllCostDelivery); + case ChannelType.UnreliableFragmentedSequenced: + return config.AddChannel(QosType.UnreliableFragmentedSequenced); + case ChannelType.ReliableFragmentedSequenced: + return config.AddChannel(QosType.ReliableFragmentedSequenced); + } + return 0; + } + + public object GetSettings() + { + NetworkTransport.Init(); + return new ConnectionConfig() + { + SendDelay = 0 + }; + } + + public void Connect(string address, int port, object settings, out byte error) + { + serverHostId = NetworkTransport.AddHost(new HostTopology((ConnectionConfig)settings, 1)); + serverConnectionId = NetworkTransport.Connect(serverHostId, address, port, 0, out error); + } + } +} diff --git a/MLAPI/MLAPI.csproj b/MLAPI/MLAPI.csproj index e0b1d5b..87c5da2 100644 --- a/MLAPI/MLAPI.csproj +++ b/MLAPI/MLAPI.csproj @@ -72,15 +72,19 @@ + + + - + + @@ -106,7 +110,7 @@ - + diff --git a/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs b/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs index 8bc9137..21a0ddd 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs @@ -215,7 +215,7 @@ namespace MLAPI.MonoBehaviours.Core FieldTypeHelper.WriteFieldType(writer, methodParams[i], fieldType); } - InternalMessageHandler.Send(NetId.ServerNetId.GetClientId(), "MLAPI_COMMAND", "MLAPI_INTERNAL", writer.Finalize(), null); + InternalMessageHandler.Send(NetworkingManager.singleton.NetworkConfig.NetworkTransport.ServerNetId, "MLAPI_COMMAND", "MLAPI_INTERNAL", writer.Finalize(), null); } } @@ -505,7 +505,7 @@ namespace MLAPI.MonoBehaviours.Core } else { - if (!(isHost && new NetId(ownerClientId).IsHost())) + if (!(isHost && ownerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId)) { //It's sync time. This is the target receivers packet. using (BitWriter writer = new BitWriter()) @@ -606,7 +606,7 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: Server can not send messages to server."); return; } - InternalMessageHandler.Send(NetId.ServerNetId.GetClientId(), messageType, channelName, data, null); + InternalMessageHandler.Send(NetworkingManager.singleton.NetworkConfig.NetworkTransport.ServerNetId, messageType, channelName, data, null); } /// @@ -644,7 +644,7 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: Server can not send messages to server."); return; } - InternalMessageHandler.Send(NetId.ServerNetId.GetClientId(), messageType, channelName, data, null, networkId, networkedObject.GetOrderIndex(this)); + InternalMessageHandler.Send(NetworkingManager.singleton.NetworkConfig.NetworkTransport.ServerNetId, messageType, channelName, data, null, networkId, networkedObject.GetOrderIndex(this)); } /// diff --git a/MLAPI/MonoBehaviours/Core/NetworkedObject.cs b/MLAPI/MonoBehaviours/Core/NetworkedObject.cs index d0994ff..cb15948 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkedObject.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkedObject.cs @@ -43,7 +43,25 @@ namespace MLAPI.MonoBehaviours.Core return ownerClientId; } } - internal uint ownerClientId = new NetId(0, 0, false, true).GetClientId(); + private uint? _ownerClientId = null; + //internal uint ownerClientId = new NetId(0, 0, false, true).GetClientId(); + internal uint ownerClientId + { + get + { + if (_ownerClientId == null) + return NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId; + else + return _ownerClientId.Value; + } + set + { + if (value == NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId) + _ownerClientId = null; + else + _ownerClientId = value; + } + } /// /// The name of the NetworkedPrefab /// @@ -88,7 +106,7 @@ namespace MLAPI.MonoBehaviours.Core { get { - return isPlayerObject && (OwnerClientId == NetworkingManager.singleton.MyClientId || (new NetId(ownerClientId).IsHost() && NetworkingManager.singleton.isHost)); + return isPlayerObject && (OwnerClientId == NetworkingManager.singleton.MyClientId || (ownerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId && NetworkingManager.singleton.isHost)); } } /// @@ -98,7 +116,7 @@ namespace MLAPI.MonoBehaviours.Core { get { - return !isPlayerObject && (OwnerClientId == NetworkingManager.singleton.MyClientId || (new NetId(ownerClientId).IsHost() && NetworkingManager.singleton.isHost)); + return !isPlayerObject && (OwnerClientId == NetworkingManager.singleton.MyClientId || (ownerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId && NetworkingManager.singleton.isHost)); } } @@ -154,7 +172,7 @@ namespace MLAPI.MonoBehaviours.Core { foreach (KeyValuePair pair in NetworkingManager.singleton.connectedClients) { - if (new NetId(pair.Key).IsHost()) + if (pair.Key == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId) continue; if ((previousObservers.Contains(pair.Key) && !newObservers.Contains(pair.Key)) || (!previousObservers.Contains(pair.Key) && newObservers.Contains(pair.Key))) diff --git a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs index 03bb606..7ff1329 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs @@ -3,7 +3,6 @@ using System; using System.Collections; using System.Collections.Generic; using UnityEngine; -using UnityEngine.Networking; using System.Linq; using System.Security.Cryptography; using MLAPI.NetworkingManagerComponents.Cryptography; @@ -108,8 +107,6 @@ namespace MLAPI.MonoBehaviours.Core private bool isListening; private byte[] messageBuffer; - internal int serverConnectionId; - internal int serverHostId; /// /// Gets if we are connected as a client /// @@ -209,7 +206,7 @@ namespace MLAPI.MonoBehaviours.Core } } - private ConnectionConfig Init(bool server) + private object Init(bool server) { networkTime = 0f; lastSendTickTime = 0f; @@ -237,6 +234,7 @@ namespace MLAPI.MonoBehaviours.Core NetworkSceneManager.sceneIndexToString = new Dictionary(); NetworkSceneManager.sceneNameToIndex = new Dictionary(); InternalMessageHandler.FinalMessageBuffer = new byte[NetworkConfig.MessageBufferSize]; + object settings = NetworkConfig.NetworkTransport.GetSettings(); //Gets a new "settings" object for the transport currently used. if(NetworkConfig.HandleObjectSpawning) { @@ -276,44 +274,38 @@ namespace MLAPI.MonoBehaviours.Core } } - NetworkTransport.Init(); - ConnectionConfig cConfig = new ConnectionConfig() - { - SendDelay = 0 - }; - //MLAPI channels and messageTypes List internalChannels = new List { new Channel() { Name = "MLAPI_INTERNAL", - Type = QosType.ReliableFragmentedSequenced + Type = NetworkConfig.NetworkTransport.InternalChannel }, new Channel() { Name = "MLAPI_POSITION_UPDATE", - Type = QosType.StateUpdate + Type = ChannelType.StateUpdate }, new Channel() { Name = "MLAPI_ANIMATION_UPDATE", - Type = QosType.ReliableSequenced + Type = ChannelType.ReliableSequenced }, new Channel() { Name = "MLAPI_NAV_AGENT_STATE", - Type = QosType.ReliableSequenced + Type = ChannelType.ReliableSequenced }, new Channel() { Name = "MLAPI_NAV_AGENT_CORRECTION", - Type = QosType.StateUpdate + Type = ChannelType.StateUpdate }, new Channel() { Name = "MLAPI_TIME_SYNC", - Type = QosType.Unreliable + Type = ChannelType.Unreliable } }; @@ -363,7 +355,7 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: Duplicate channel name: " + NetworkConfig.Channels[i].Name); continue; } - int channelId = cConfig.AddChannel(internalChannels[i].Type); + int channelId = NetworkConfig.NetworkTransport.AddChannel(internalChannels[i].Type, settings); MessageManager.channels.Add(internalChannels[i].Name, channelId); channelNames.Add(internalChannels[i].Name); MessageManager.reverseChannels.Add(channelId, internalChannels[i].Name); @@ -445,7 +437,7 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: Duplicate channel name: " + NetworkConfig.Channels[i].Name); continue; } - int channelId = cConfig.AddChannel(NetworkConfig.Channels[i].Type); + int channelId = NetworkConfig.NetworkTransport.AddChannel(NetworkConfig.Channels[i].Type, settings); MessageManager.channels.Add(NetworkConfig.Channels[i].Name, channelId); channelNames.Add(NetworkConfig.Channels[i].Name); MessageManager.reverseChannels.Add(channelId, NetworkConfig.Channels[i].Name); @@ -459,7 +451,7 @@ namespace MLAPI.MonoBehaviours.Core MessageManager.reverseMessageTypes.Add(messageId, messageTypes[i].Name); messageId++; } - return cConfig; + return settings; } /// @@ -473,7 +465,6 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(true); if (NetworkConfig.ConnectionApproval) { if (ConnectionApprovalCallback == null) @@ -481,15 +472,10 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: No ConnectionApproval callback defined. Connection approval will timeout"); } } - HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); - for (int i = 0; i < NetworkConfig.ServerTransports.Count; i++) - { - if (NetworkConfig.ServerTransports[i].Websockets) - NetworkTransport.AddWebsocketHost(hostTopology, NetworkConfig.ServerTransports[i].Port); - else - NetworkTransport.AddHost(hostTopology, NetworkConfig.ServerTransports[i].Port); - } - + + object settings = Init(true); + NetworkConfig.NetworkTransport.RegisterServerListenSocket(settings); + _isServer = true; _isClient = false; isListening = true; @@ -509,37 +495,12 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(false); - HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); - serverHostId = NetworkTransport.AddHost(hostTopology, 0, null); - + object settings = Init(false); + byte error; + NetworkConfig.NetworkTransport.Connect(NetworkConfig.ConnectAddress, NetworkConfig.ConnectPort, settings, out error); _isServer = false; _isClient = true; isListening = true; - byte error; - serverConnectionId = NetworkTransport.Connect(serverHostId, NetworkConfig.ConnectAddress, NetworkConfig.ConnectPort, 0, out error); - } - - /// - /// Starts a client using Websockets - /// - public void StartClientWebsocket() - { - if (isServer || isClient) - { - Debug.LogWarning("MLAPI: Cannot start client while an instance is already running"); - return; - } - - ConnectionConfig cConfig = Init(false); - HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); - serverHostId = NetworkTransport.AddWebsocketHost(hostTopology, 0, null); - - _isServer = false; - _isClient = true; - isListening = true; - byte error; - serverConnectionId = NetworkTransport.Connect(serverHostId, NetworkConfig.ConnectAddress, NetworkConfig.ConnectPort, 0, out error); } /// @@ -554,12 +515,11 @@ namespace MLAPI.MonoBehaviours.Core if(!disconnectedIds.Contains(pair.Key)) { disconnectedIds.Add(pair.Key); - NetId netId = new NetId(pair.Key); - if (netId.IsHost()) + if (pair.Key == NetworkConfig.NetworkTransport.HostDummyId || + pair.Key == NetworkConfig.NetworkTransport.InvalidDummyId) continue; - byte error; - NetworkTransport.Disconnect(netId.HostId, netId.ConnectionId, out error); + NetworkConfig.NetworkTransport.DisconnectClient(pair.Key); } } foreach (uint clientId in pendingClients) @@ -567,12 +527,10 @@ namespace MLAPI.MonoBehaviours.Core if (!disconnectedIds.Contains(clientId)) { disconnectedIds.Add(clientId); - NetId netId = new NetId(clientId); - if (netId.IsHost()) + if (clientId == NetworkConfig.NetworkTransport.HostDummyId || + clientId == NetworkConfig.NetworkTransport.InvalidDummyId) continue; - - byte error; - NetworkTransport.Disconnect(netId.HostId, netId.ConnectionId, out error); + NetworkConfig.NetworkTransport.DisconnectClient(clientId); } } _isServer = false; @@ -596,8 +554,7 @@ namespace MLAPI.MonoBehaviours.Core public void StopClient() { _isClient = false; - byte error; - NetworkTransport.Disconnect(serverHostId, serverConnectionId, out error); + NetworkConfig.NetworkTransport.DisconnectFromServer(); Shutdown(); } @@ -612,7 +569,6 @@ namespace MLAPI.MonoBehaviours.Core return; } - ConnectionConfig cConfig = Init(true); if (NetworkConfig.ConnectionApproval) { if (ConnectionApprovalCallback == null) @@ -620,28 +576,22 @@ namespace MLAPI.MonoBehaviours.Core Debug.LogWarning("MLAPI: No ConnectionApproval callback defined. Connection approval will timeout"); } } - HostTopology hostTopology = new HostTopology(cConfig, NetworkConfig.MaxConnections); - for (int i = 0; i < NetworkConfig.ServerTransports.Count; i++) - { - if (NetworkConfig.ServerTransports[i].Websockets) - NetworkTransport.AddWebsocketHost(hostTopology, NetworkConfig.ServerTransports[i].Port); - else - NetworkTransport.AddHost(hostTopology, NetworkConfig.ServerTransports[i].Port); - } + object settings = Init(true); + NetworkConfig.NetworkTransport.RegisterServerListenSocket(settings); _isServer = true; _isClient = true; isListening = true; - NetId netId = new NetId(0, 0, true, false); - connectedClients.Add(netId.GetClientId(), new NetworkedClient() + uint hostClientId = NetworkConfig.NetworkTransport.HostDummyId; + connectedClients.Add(hostClientId, new NetworkedClient() { - ClientId = netId.GetClientId() + ClientId = hostClientId }); - if(NetworkConfig.HandleObjectSpawning) + if (NetworkConfig.HandleObjectSpawning) { - SpawnManager.SpawnPlayerObject(netId.GetClientId(), 0, pos.GetValueOrDefault(), rot.GetValueOrDefault()); + SpawnManager.SpawnPlayerObject(hostClientId, 0, pos.GetValueOrDefault(), rot.GetValueOrDefault()); } if (OnServerStarted != null) @@ -675,7 +625,7 @@ namespace MLAPI.MonoBehaviours.Core _isClient = false; _isServer = false; SpawnManager.DestroyNonSceneObjects(); - NetworkTransport.Shutdown(); + NetworkConfig.NetworkTransport.Shutdown(); } private float lastReceiveTickTime; @@ -691,57 +641,31 @@ namespace MLAPI.MonoBehaviours.Core { foreach (KeyValuePair pair in connectedClients) { - NetId netId = new NetId(pair.Key); - if (netId.IsHost() || netId.IsInvalid()) - continue; - byte error; - NetworkTransport.SendQueuedMessages(netId.HostId, netId.ConnectionId, out error); + NetworkConfig.NetworkTransport.SendQueue(pair.Key, out error); } lastSendTickTime = NetworkTime; } if((NetworkTime - lastReceiveTickTime >= (1f / NetworkConfig.ReceiveTickrate)) || NetworkConfig.ReceiveTickrate <= 0) { - NetworkEventType eventType; + NetEventType eventType; int processedEvents = 0; do { processedEvents++; - int hostId; - int connectionId; + uint clientId; int channelId; int receivedSize; byte error; - eventType = NetworkTransport.Receive(out hostId, out connectionId, out channelId, messageBuffer, messageBuffer.Length, out receivedSize, out error); - NetId netId = new NetId((byte)hostId, (ushort)connectionId, false, false); - NetworkError networkError = (NetworkError)error; - if (networkError == NetworkError.Timeout) - { - //Client timed out. - if (isServer) - { - OnClientDisconnect(netId.GetClientId()); - return; - } - else - _isClientConnected = false; - - if (OnClientDisconnectCallback != null) - OnClientDisconnectCallback.Invoke(netId.GetClientId()); - } - else if (networkError != NetworkError.Ok) - { - Debug.LogWarning("MLAPI: NetworkTransport receive error: " + networkError.ToString()); - return; - } + eventType = NetworkConfig.NetworkTransport.PollReceive(out clientId, out channelId, ref messageBuffer, messageBuffer.Length, out receivedSize, out error); switch (eventType) { - case NetworkEventType.ConnectEvent: + case NetEventType.Connect: if (isServer) { - pendingClients.Add(netId.GetClientId()); - StartCoroutine(ApprovalTimeout(netId.GetClientId())); + pendingClients.Add(clientId); + StartCoroutine(ApprovalTimeout(clientId)); } else { @@ -762,25 +686,25 @@ namespace MLAPI.MonoBehaviours.Core if (NetworkConfig.ConnectionApproval) writer.WriteByteArray(NetworkConfig.ConnectionData); - InternalMessageHandler.Send(netId.GetClientId(), "MLAPI_CONNECTION_REQUEST", "MLAPI_INTERNAL", writer.Finalize(), null, null, null, true); + InternalMessageHandler.Send(clientId, "MLAPI_CONNECTION_REQUEST", "MLAPI_INTERNAL", writer.Finalize(), null, null, null, true); } } break; - case NetworkEventType.DataEvent: - HandleIncomingData(netId.GetClientId(), messageBuffer, channelId); + case NetEventType.Data: + HandleIncomingData(clientId, messageBuffer, channelId); break; - case NetworkEventType.DisconnectEvent: + case NetEventType.Disconnect: if (isServer) - OnClientDisconnect(netId.GetClientId()); + OnClientDisconnect(clientId); else _isClientConnected = false; if (OnClientDisconnectCallback != null) - OnClientDisconnectCallback.Invoke(netId.GetClientId()); + OnClientDisconnectCallback.Invoke(clientId); break; } // Only do another iteration if: there are no more messages AND (there is no limit to max events or we have processed less than the maximum) - } while (eventType != NetworkEventType.Nothing && (NetworkConfig.MaxReceiveEventsPerTickRate <= 0 || processedEvents < NetworkConfig.MaxReceiveEventsPerTickRate)); + } while (eventType != NetEventType.Nothing && (NetworkConfig.MaxReceiveEventsPerTickRate <= 0 || processedEvents < NetworkConfig.MaxReceiveEventsPerTickRate)); lastReceiveTickTime = NetworkTime; } @@ -1029,12 +953,7 @@ namespace MLAPI.MonoBehaviours.Core foreach (KeyValuePair pair in SpawnManager.spawnedObjects) pair.Value.observers.Remove(clientId); - NetId netId = new NetId(clientId); - if (netId.IsHost() || netId.IsInvalid()) - return; - - byte error; - NetworkTransport.Disconnect(netId.HostId, netId.ConnectionId, out error); + NetworkConfig.NetworkTransport.DisconnectClient(clientId); } internal void OnClientDisconnect(uint clientId) @@ -1074,7 +993,7 @@ namespace MLAPI.MonoBehaviours.Core using (BitWriter writer = new BitWriter()) { writer.WriteFloat(NetworkTime); - int timestamp = NetworkTransport.GetNetworkTimestamp(); + int timestamp = NetworkConfig.NetworkTransport.GetNetworkTimestamp(); writer.WriteInt(timestamp); byte[] buffer = writer.Finalize(); @@ -1144,7 +1063,7 @@ namespace MLAPI.MonoBehaviours.Core } writer.WriteFloat(NetworkTime); - writer.WriteInt(NetworkTransport.GetNetworkTimestamp()); + writer.WriteInt(NetworkConfig.NetworkTransport.GetNetworkTimestamp()); writer.WriteInt(connectedClients.Count - 1); foreach (KeyValuePair item in connectedClients) @@ -1228,10 +1147,7 @@ namespace MLAPI.MonoBehaviours.Core if (diffieHellmanPublicKeys.ContainsKey(clientId)) diffieHellmanPublicKeys.Remove(clientId); - NetId netId = new NetId(clientId); - - byte error; - NetworkTransport.Disconnect(netId.HostId, netId.ConnectionId, out error); + NetworkConfig.NetworkTransport.DisconnectClient(clientId); } } } diff --git a/MLAPI/MonoBehaviours/Core/TrackedObject.cs b/MLAPI/MonoBehaviours/Core/TrackedObject.cs index ea3e938..1bf3383 100644 --- a/MLAPI/MonoBehaviours/Core/TrackedObject.cs +++ b/MLAPI/MonoBehaviours/Core/TrackedObject.cs @@ -1,6 +1,5 @@ using MLAPI.Data; using MLAPI.NetworkingManagerComponents.Core; -using System; using System.Collections.Generic; using UnityEngine; diff --git a/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs b/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs index 636088f..84c7aa9 100644 --- a/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs +++ b/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs @@ -107,7 +107,7 @@ namespace MLAPI.MonoBehaviours.Prototyping private void Update() { - if(isOwner || isLocalPlayer || (new NetId(ownerClientId).IsInvalid() && isServer)) + if(isOwner || isLocalPlayer || (ownerClientId == NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId && isServer)) { //We own the object OR we are server and the object is not owned by anyone OR we are the object. if(NetworkingManager.singleton.NetworkTime - lastSendTime >= timeForLerp && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees)) diff --git a/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs b/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs index b98d33a..8d21eed 100644 --- a/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs +++ b/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Receive.cs @@ -4,7 +4,6 @@ using MLAPI.Data; using MLAPI.MonoBehaviours.Core; using MLAPI.NetworkingManagerComponents.Binary; using UnityEngine; -using UnityEngine.Networking; namespace MLAPI.NetworkingManagerComponents.Core { @@ -73,10 +72,7 @@ namespace MLAPI.NetworkingManagerComponents.Core float netTime = reader.ReadFloat(); int remoteStamp = reader.ReadInt(); byte error; - NetId netId = new NetId(clientId); - int msDelay = NetworkTransport.GetRemoteDelayTimeMS(netId.HostId, netId.ConnectionId, remoteStamp, out error); - if ((NetworkError)error != NetworkError.Ok) - msDelay = 0; + int msDelay = NetworkingManager.singleton.NetworkConfig.NetworkTransport.GetRemoteDelayTimeMS(clientId, remoteStamp, out error); netManager.networkTime = netTime + (msDelay / 1000f); netManager.connectedClients.Add(netManager.MyClientId, new NetworkedClient() { ClientId = netManager.MyClientId }); @@ -391,11 +387,8 @@ namespace MLAPI.NetworkingManagerComponents.Core float netTime = reader.ReadFloat(); int timestamp = reader.ReadInt(); - NetId netId = new NetId(clientId); byte error; - int msDelay = NetworkTransport.GetRemoteDelayTimeMS(netId.HostId, netId.ConnectionId, timestamp, out error); - if ((NetworkError)error != NetworkError.Ok) - msDelay = 0; + int msDelay = NetworkingManager.singleton.NetworkConfig.NetworkTransport.GetRemoteDelayTimeMS(clientId, timestamp, out error); netManager.networkTime = netTime + (msDelay / 1000f); } diff --git a/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Send.cs b/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Send.cs index b9bb698..62504dc 100644 --- a/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Send.cs +++ b/MLAPI/NetworkingManagerComponents/Core/InternalMessageHandler.Send.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using MLAPI.Data; +using MLAPI.MonoBehaviours.Core; using MLAPI.NetworkingManagerComponents.Binary; using MLAPI.NetworkingManagerComponents.Cryptography; using UnityEngine; -using UnityEngine.Networking; namespace MLAPI.NetworkingManagerComponents.Core { @@ -12,8 +12,7 @@ namespace MLAPI.NetworkingManagerComponents.Core internal static byte[] FinalMessageBuffer; internal static void PassthroughSend(uint targetId, uint sourceId, ushort messageType, int channelId, byte[] data, uint? networkId = null, ushort? orderId = null) { - NetId targetNetId = new NetId(targetId); - if (netManager.isHost && targetNetId.IsHost()) + if (netManager.isHost && targetId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Host trying to send data to it's own client Debug.LogWarning("MLAPI: Send method got message aimed at server from the server?"); @@ -44,30 +43,30 @@ namespace MLAPI.NetworkingManagerComponents.Core writer.Finalize(ref FinalMessageBuffer); byte error; - NetworkTransport.QueueMessageForSending(targetNetId.HostId, targetNetId.ConnectionId, channelId, FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channelId, false, out error); } } //RETURNS IF IT SUCCEDED OR FAILED BECAUSE OF NON-OBSERVER. ANY OTHER FAIL WILL RETURN TRUE internal static bool Send(uint clientId, string messageType, string channelName, byte[] data, uint? fromNetId, uint? networkId = null, ushort? orderId = null, bool skipQueue = false) { - NetId netId = new NetId(clientId); - if (netManager.isHost && netId.IsHost()) + uint targetClientId = clientId; + if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Don't invoke the message on our own machine. Instant stack overflow. Debug.LogWarning("MLAPI: Cannot send message to own client"); return true; } - else if (netId.IsHost()) + else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Client trying to send data to host - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; } //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we return if (netManager.isServer && fromNetId != null && !SpawnManager.spawnedObjects[fromNetId.Value].observers.Contains(clientId)) return false; - bool isPassthrough = (!netManager.isServer && clientId != NetId.ServerNetId.GetClientId() && netManager.NetworkConfig.AllowPassthroughMessages); + bool isPassthrough = (!netManager.isServer && clientId != netManager.NetworkConfig.NetworkTransport.ServerNetId && netManager.NetworkConfig.AllowPassthroughMessages); if (isPassthrough && !netManager.NetworkConfig.PassthroughMessageHashSet.Contains(MessageManager.messageTypes[messageType])) { Debug.LogWarning("MLAPI: The The MessageType " + messageType + " is not registered as an allowed passthrough message type."); @@ -106,16 +105,16 @@ namespace MLAPI.NetworkingManagerComponents.Core else writer.WriteByteArray(data); - byte error; if (isPassthrough) - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; writer.Finalize(ref FinalMessageBuffer); + byte error; if (skipQueue) - NetworkTransport.Send(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), MessageManager.channels[channelName], true, out error); else - NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), MessageManager.channels[channelName], false, out error); return true; } @@ -149,16 +148,16 @@ namespace MLAPI.NetworkingManagerComponents.Core int channel = MessageManager.channels[channelName]; for (int i = 0; i < clientIds.Length; i++) { - NetId netId = new NetId(clientIds[i]); - if (netManager.isHost && netId.IsHost()) + uint targetClientId = clientIds[i]; + if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Don't invoke the message on our own machine. Instant stack overflow. continue; } - else if (netId.IsHost()) + else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Client trying to send data to host - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; } //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue @@ -168,7 +167,7 @@ namespace MLAPI.NetworkingManagerComponents.Core writer.Finalize(ref FinalMessageBuffer); byte error; - NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channel, false, out error); } } } @@ -201,16 +200,16 @@ namespace MLAPI.NetworkingManagerComponents.Core int channel = MessageManager.channels[channelName]; for (int i = 0; i < clientIds.Count; i++) { - NetId netId = new NetId(clientIds[i]); - if (netManager.isHost && netId.IsHost()) + uint targetClientId = clientIds[i]; + if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Don't invoke the message on our own machine. Instant stack overflow. continue; } - else if (netId.IsHost()) + else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Client trying to send data to host - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; } //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue @@ -219,8 +218,8 @@ namespace MLAPI.NetworkingManagerComponents.Core writer.Finalize(ref FinalMessageBuffer); - byte error; - NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + byte error; + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channel, false, out error); } } } @@ -258,16 +257,16 @@ namespace MLAPI.NetworkingManagerComponents.Core int channel = MessageManager.channels[channelName]; foreach (KeyValuePair pair in netManager.connectedClients) { - NetId netId = new NetId(pair.Key); - if (netManager.isHost && netId.IsHost()) + uint targetClientId = pair.Key; + if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Don't invoke the message on our own machine. Instant stack overflow. continue; } - else if (netId.IsHost()) + else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Client trying to send data to host - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; } //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue @@ -280,7 +279,7 @@ namespace MLAPI.NetworkingManagerComponents.Core writer.Finalize(ref FinalMessageBuffer); byte error; - NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channel, false, out error); } return nonObservedIds; } @@ -320,16 +319,16 @@ namespace MLAPI.NetworkingManagerComponents.Core if (pair.Key == clientIdToIgnore) continue; - NetId netId = new NetId(pair.Key); - if (netManager.isHost && netId.IsHost()) + uint targetClientId = pair.Key; + if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Don't invoke the message on our own machine. Instant stack overflow. continue; } - else if (netId.IsHost()) + else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId) { //Client trying to send data to host - netId = NetId.ServerNetId; + targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId; } //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue @@ -342,7 +341,7 @@ namespace MLAPI.NetworkingManagerComponents.Core writer.Finalize(ref FinalMessageBuffer); byte error; - NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, FinalMessageBuffer, (int)writer.GetFinalizeSize(), out error); + netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channel, false, out error); } return nonObservedIds; } diff --git a/MLAPI/NetworkingManagerComponents/Core/LagCompensationManager.cs b/MLAPI/NetworkingManagerComponents/Core/LagCompensationManager.cs index 2c878d7..0a138b8 100644 --- a/MLAPI/NetworkingManagerComponents/Core/LagCompensationManager.cs +++ b/MLAPI/NetworkingManagerComponents/Core/LagCompensationManager.cs @@ -1,9 +1,7 @@ -using MLAPI.Data; -using MLAPI.MonoBehaviours.Core; +using MLAPI.MonoBehaviours.Core; using System; using System.Collections.Generic; using UnityEngine; -using UnityEngine.Networking; namespace MLAPI.NetworkingManagerComponents.Core { @@ -62,8 +60,7 @@ namespace MLAPI.NetworkingManagerComponents.Core Debug.LogWarning("MLAPI: Lag compensation simulations are only to be ran on the server."); return; } - NetId netId = new NetId(clientId); - float milisecondsDelay = NetworkTransport.GetCurrentRTT(netId.HostId, netId.ConnectionId, out error) / 2f; + float milisecondsDelay = NetworkingManager.singleton.NetworkConfig.NetworkTransport.GetCurrentRTT(clientId, out error) / 2f; Simulate(milisecondsDelay * 1000f, action); } diff --git a/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs b/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs index 68dc879..229e6d7 100644 --- a/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs +++ b/MLAPI/NetworkingManagerComponents/Core/SpawnManager.cs @@ -36,7 +36,7 @@ namespace MLAPI.NetworkingManagerComponents.Core { NetworkedObject netObject = SpawnManager.spawnedObjects[netId]; NetworkingManager.singleton.connectedClients[netObject.OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == netId); - netObject.ownerClientId = new NetId(0, 0, false, true).GetClientId(); + netObject.ownerClientId = NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId; using (BitWriter writer = new BitWriter()) { @@ -250,7 +250,7 @@ namespace MLAPI.NetworkingManagerComponents.Core { if (!spawnedObjects.ContainsKey(networkId) || (netManager != null && !netManager.NetworkConfig.HandleObjectSpawning)) return; - if (!new NetId(spawnedObjects[networkId].OwnerClientId).IsInvalid() && !spawnedObjects[networkId].isPlayerObject) + 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);