Switched the Generic MLAPI message layer to BitWriter & BitReader

This commit is contained in:
Albin Corén 2018-04-17 21:38:08 +02:00
parent 85ecca2af9
commit 4d28f3420e
2 changed files with 305 additions and 348 deletions

View File

@ -10,6 +10,7 @@ using System.Security.Cryptography;
using MLAPI.NetworkingManagerComponents.Cryptography; using MLAPI.NetworkingManagerComponents.Cryptography;
using MLAPI.NetworkingManagerComponents.Core; using MLAPI.NetworkingManagerComponents.Core;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using MLAPI.NetworkingManagerComponents.Binary;
namespace MLAPI.MonoBehaviours.Core namespace MLAPI.MonoBehaviours.Core
{ {
@ -821,200 +822,198 @@ namespace MLAPI.MonoBehaviours.Core
private void HandleIncomingData(uint clientId, byte[] data, int channelId) private void HandleIncomingData(uint clientId, byte[] data, int channelId)
{ {
using(MemoryStream readStream = new MemoryStream(data)) BitReader reader = new BitReader(data);
ushort messageType = reader.ReadUShort();
bool targeted = reader.ReadBool();
uint targetNetworkId = 0;
ushort networkOrderId = 0;
if (targeted)
{ {
using (BinaryReader reader = new BinaryReader(readStream)) targetNetworkId = reader.ReadUInt();
networkOrderId = reader.ReadUShort();
}
bool isPassthrough = reader.ReadBool();
uint passthroughOrigin = 0;
uint passthroughTarget = 0;
if (isPassthrough && isServer)
passthroughTarget = reader.ReadUInt();
else if (isPassthrough && !isServer)
passthroughOrigin = reader.ReadUInt();
//Client tried to send a network message that was not the connection request before he was accepted.
if (isServer && pendingClients.Contains(clientId) && messageType != 0)
{
Debug.LogWarning("MLAPI: Message recieved from clientId " + clientId + " before it has been accepted");
return;
}
//ushort bytesToRead = reader.ReadUShort();
reader.SkipPadded();
byte[] incommingData = reader.ReadByteArray();
if (NetworkConfig.EncryptedChannelsHashSet.Contains(MessageManager.reverseChannels[channelId]))
{
//Encrypted message
if (isServer)
incommingData = CryptographyHelper.Decrypt(incommingData, connectedClients[clientId].AesKey);
else
incommingData = CryptographyHelper.Decrypt(incommingData, clientAesKey);
}
if (isServer && isPassthrough && !NetworkConfig.PassthroughMessageHashSet.Contains(messageType))
{
Debug.LogWarning("MLAPI: Client " + clientId + " tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if (isClient && isPassthrough && !NetworkConfig.PassthroughMessageHashSet.Contains(messageType))
{
Debug.LogWarning("MLAPI: Server tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if (isServer && isPassthrough)
{
if (!connectedClients.ContainsKey(passthroughTarget))
{ {
ushort messageType = reader.ReadUInt16(); Debug.LogWarning("MLAPI: Passthrough message was sent with invalid target: " + passthroughTarget + " from client " + clientId);
bool targeted = reader.ReadBoolean(); return;
uint targetNetworkId = 0; }
ushort networkOrderId = 0; uint? netIdTarget = null;
if(targeted) ushort? netOrderId = null;
if (targeted)
{
netIdTarget = targetNetworkId;
netOrderId = networkOrderId;
}
InternalMessageHandler.PassthroughSend(passthroughTarget, clientId, messageType, channelId, incommingData, netIdTarget, netOrderId);
return;
}
if (messageType >= 32)
{
#region CUSTOM MESSAGE
//Custom message, invoke all message handlers
if (targeted)
{
if (!SpawnManager.spawnedObjects.ContainsKey(targetNetworkId))
{ {
targetNetworkId = reader.ReadUInt32(); Debug.LogWarning("MLAPI: No target for message found");
networkOrderId = reader.ReadUInt16();
}
bool isPassthrough = reader.ReadBoolean();
uint passthroughOrigin = 0;
uint passthroughTarget = 0;
if (isPassthrough && isServer)
passthroughTarget = reader.ReadUInt32();
else if (isPassthrough && !isServer)
passthroughOrigin = reader.ReadUInt32();
//Client tried to send a network message that was not the connection request before he was accepted.
if (isServer && pendingClients.Contains(clientId) && messageType != 0)
{
Debug.LogWarning("MLAPI: Message recieved from clientId " + clientId + " before it has been accepted");
return; return;
} }
else if (!SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions.ContainsKey(networkOrderId))
ushort bytesToRead = reader.ReadUInt16();
byte[] incommingData = reader.ReadBytes(bytesToRead);
if(NetworkConfig.EncryptedChannelsHashSet.Contains(MessageManager.reverseChannels[channelId]))
{ {
//Encrypted message Debug.LogWarning("MLAPI: No target messageType for message found");
if (isServer) return;
incommingData = CryptographyHelper.Decrypt(incommingData, connectedClients[clientId].AesKey); }
else if (!SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions[networkOrderId].ContainsKey(messageType))
{
Debug.LogWarning("MLAPI: No target found with the given messageType");
return;
}
SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions[networkOrderId][messageType].Invoke(clientId, incommingData);
}
else
{
foreach (KeyValuePair<int, Action<uint, byte[]>> pair in MessageManager.messageCallbacks[messageType])
{
if (isPassthrough)
pair.Value(passthroughOrigin, incommingData);
else else
incommingData = CryptographyHelper.Decrypt(incommingData, clientAesKey); pair.Value(clientId, incommingData);
}
if (isServer && isPassthrough && !NetworkConfig.PassthroughMessageHashSet.Contains(messageType))
{
Debug.LogWarning("MLAPI: Client " + clientId + " tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if(isClient && isPassthrough && !NetworkConfig.PassthroughMessageHashSet.Contains(messageType))
{
Debug.LogWarning("MLAPI: Server tried to send a passthrough message for a messageType not registered as passthrough");
return;
}
else if(isServer && isPassthrough)
{
if (!connectedClients.ContainsKey(passthroughTarget))
{
Debug.LogWarning("MLAPI: Passthrough message was sent with invalid target: " + passthroughTarget + " from client " + clientId);
return;
}
uint? netIdTarget = null;
ushort? netOrderId = null;
if (targeted)
{
netIdTarget = targetNetworkId;
netOrderId = networkOrderId;
}
InternalMessageHandler.PassthroughSend(passthroughTarget, clientId, messageType, channelId, incommingData, netIdTarget, netOrderId);
return;
}
if (messageType >= 32)
{
#region CUSTOM MESSAGE
//Custom message, invoke all message handlers
if(targeted)
{
if (!SpawnManager.spawnedObjects.ContainsKey(targetNetworkId))
{
Debug.LogWarning("MLAPI: No target for message found");
return;
}
else if (!SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions.ContainsKey(networkOrderId))
{
Debug.LogWarning("MLAPI: No target messageType for message found");
return;
}
else if (!SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions[networkOrderId].ContainsKey(messageType))
{
Debug.LogWarning("MLAPI: No target found with the given messageType");
return;
}
SpawnManager.spawnedObjects[targetNetworkId].targetMessageActions[networkOrderId][messageType].Invoke(clientId, incommingData);
}
else
{
foreach (KeyValuePair<int, Action<uint, byte[]>> pair in MessageManager.messageCallbacks[messageType])
{
if (isPassthrough)
pair.Value(passthroughOrigin, incommingData);
else
pair.Value(clientId, incommingData);
}
}
#endregion
}
else
{
#region INTERNAL MESSAGE
//MLAPI message
switch (messageType)
{
case 0: //Client to server > sends connection buffer
if (isServer)
{
InternalMessageHandler.HandleConnectionRequest(clientId, incommingData, channelId);
}
break;
case 1: //Server informs client it has been approved:
if (isClient)
{
InternalMessageHandler.HandleConnectionApproved(clientId, incommingData, channelId);
}
break;
case 2:
//Server informs client another client connected
//MLAPI_ADD_OBJECT
if (isClient)
{
InternalMessageHandler.HandleAddObject(clientId, incommingData, channelId);
}
break;
case 3:
//Server informs client another client disconnected
//MLAPI_CLIENT_DISCONNECT
if (isClient)
{
InternalMessageHandler.HandleClientDisconnect(clientId, incommingData, channelId);
}
break;
case 4:
//Server infroms clients to destroy an object
if (isClient)
{
InternalMessageHandler.HandleDestroyObject(clientId, incommingData, channelId);
}
break;
case 5:
//Scene switch
if (isClient)
{
InternalMessageHandler.HandleSwitchScene(clientId, incommingData, channelId);
}
break;
case 6: //Spawn pool object
if (isClient)
{
InternalMessageHandler.HandleSpawnPoolObject(clientId, incommingData, channelId);
}
break;
case 7: //Destroy pool object
if (isClient)
{
InternalMessageHandler.HandleDestroyPoolObject(clientId, incommingData, channelId);
}
break;
case 8: //Change owner
if (isClient)
{
InternalMessageHandler.HandleChangeOwner(clientId, incommingData, channelId);
}
break;
case 9: //Syncvar
if (isClient)
{
InternalMessageHandler.HandleSyncVarUpdate(clientId, incommingData, channelId);
}
break;
case 10:
if (isClient) //MLAPI_ADD_OBJECTS (plural)
{
InternalMessageHandler.HandleAddObjects(clientId, incommingData, channelId);
}
break;
case 11:
if (isClient)
{
InternalMessageHandler.HandleTimeSync(clientId, incommingData, channelId);
}
break;
}
#endregion
} }
} }
#endregion
}
else
{
#region INTERNAL MESSAGE
//MLAPI message
switch (messageType)
{
case 0: //Client to server > sends connection buffer
if (isServer)
{
InternalMessageHandler.HandleConnectionRequest(clientId, incommingData, channelId);
}
break;
case 1: //Server informs client it has been approved:
if (isClient)
{
InternalMessageHandler.HandleConnectionApproved(clientId, incommingData, channelId);
}
break;
case 2:
//Server informs client another client connected
//MLAPI_ADD_OBJECT
if (isClient)
{
InternalMessageHandler.HandleAddObject(clientId, incommingData, channelId);
}
break;
case 3:
//Server informs client another client disconnected
//MLAPI_CLIENT_DISCONNECT
if (isClient)
{
InternalMessageHandler.HandleClientDisconnect(clientId, incommingData, channelId);
}
break;
case 4:
//Server infroms clients to destroy an object
if (isClient)
{
InternalMessageHandler.HandleDestroyObject(clientId, incommingData, channelId);
}
break;
case 5:
//Scene switch
if (isClient)
{
InternalMessageHandler.HandleSwitchScene(clientId, incommingData, channelId);
}
break;
case 6: //Spawn pool object
if (isClient)
{
InternalMessageHandler.HandleSpawnPoolObject(clientId, incommingData, channelId);
}
break;
case 7: //Destroy pool object
if (isClient)
{
InternalMessageHandler.HandleDestroyPoolObject(clientId, incommingData, channelId);
}
break;
case 8: //Change owner
if (isClient)
{
InternalMessageHandler.HandleChangeOwner(clientId, incommingData, channelId);
}
break;
case 9: //Syncvar
if (isClient)
{
InternalMessageHandler.HandleSyncVarUpdate(clientId, incommingData, channelId);
}
break;
case 10:
if (isClient) //MLAPI_ADD_OBJECTS (plural)
{
InternalMessageHandler.HandleAddObjects(clientId, incommingData, channelId);
}
break;
case 11:
if (isClient)
{
InternalMessageHandler.HandleTimeSync(clientId, incommingData, channelId);
}
break;
}
#endregion
} }
} }

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System;
using System.IO; using System.Collections.Generic;
using MLAPI.Data; using MLAPI.Data;
using MLAPI.MonoBehaviours.Core; using MLAPI.NetworkingManagerComponents.Binary;
using MLAPI.NetworkingManagerComponents.Cryptography; using MLAPI.NetworkingManagerComponents.Cryptography;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;
@ -20,41 +20,29 @@ namespace MLAPI.NetworkingManagerComponents.Core
return; return;
} }
int sizeOfStream = 10; using (BitWriter writer = new BitWriter())
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(messageType);
{ writer.WriteBool(networkId != null);
writer.Write(messageType);
writer.Write(networkId != null); if (networkId != null)
if (networkId != null) writer.WriteUInt(networkId.Value);
writer.Write(networkId.Value);
if (orderId != null) if (orderId != null)
writer.Write(orderId.Value); writer.WriteUShort(orderId.Value);
writer.Write(true);
writer.Write(sourceId); writer.WriteBool(true);
if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(MessageManager.reverseChannels[channelId])) writer.WriteUInt(sourceId);
{
//Encrypted message writer.WriteAlignBits();
byte[] encrypted = CryptographyHelper.Encrypt(data, netManager.connectedClients[targetId].AesKey);
writer.Write((ushort)encrypted.Length); if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(MessageManager.reverseChannels[channelId]))
writer.Write(encrypted); writer.WriteByteArray(CryptographyHelper.Encrypt(data, netManager.connectedClients[targetId].AesKey));
} else
else writer.WriteByteArray(data);
{
writer.Write((ushort)data.Length);
writer.Write(data);
}
}
byte error; byte error;
NetworkTransport.QueueMessageForSending(targetNetId.HostId, targetNetId.ConnectionId, channelId, stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(targetNetId.HostId, targetNetId.ConnectionId, channelId, writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
@ -80,55 +68,45 @@ namespace MLAPI.NetworkingManagerComponents.Core
return; return;
} }
int sizeOfStream = 6; using (BitWriter writer = new BitWriter())
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
if (isPassthrough)
sizeOfStream += 4;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(MessageManager.messageTypes[messageType]);
writer.WriteBool(networkId != null);
if (networkId != null)
writer.WriteUInt(networkId.Value);
if (orderId != null)
writer.WriteUShort(orderId.Value);
writer.WriteBool(isPassthrough);
if (isPassthrough)
writer.WriteUInt(clientId);
writer.WriteAlignBits();
if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(channelName))
{ {
writer.Write(MessageManager.messageTypes[messageType]); //This is an encrypted message.
writer.Write(networkId != null); byte[] encrypted;
if (networkId != null) if (netManager.isServer)
writer.Write(networkId.Value); encrypted = CryptographyHelper.Encrypt(data, netManager.connectedClients[clientId].AesKey);
if (orderId != null)
writer.Write(orderId.Value);
writer.Write(isPassthrough);
if (isPassthrough)
writer.Write(clientId);
if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(channelName))
{
//This is an encrypted message.
byte[] encrypted;
if (netManager.isServer)
encrypted = CryptographyHelper.Encrypt(data, netManager.connectedClients[clientId].AesKey);
else
encrypted = CryptographyHelper.Encrypt(data, netManager.clientAesKey);
writer.Write((ushort)encrypted.Length);
writer.Write(encrypted);
}
else else
{ encrypted = CryptographyHelper.Encrypt(data, netManager.clientAesKey);
//Send in plaintext.
writer.Write((ushort)data.Length); writer.WriteByteArray(encrypted);
writer.Write(data);
}
} }
else
writer.WriteByteArray(data);
byte error; byte error;
if (isPassthrough) if (isPassthrough)
netId = NetId.ServerNetId; netId = NetId.ServerNetId;
if (skipQueue) if (skipQueue)
NetworkTransport.Send(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.Send(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
else else
NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, MessageManager.channels[channelName], writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
@ -140,27 +118,23 @@ namespace MLAPI.NetworkingManagerComponents.Core
return; return;
} }
int sizeOfStream = 6; using (BitWriter writer = new BitWriter())
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(MessageManager.messageTypes[messageType]);
{ writer.WriteBool(networkId != null);
writer.Write(MessageManager.messageTypes[messageType]);
writer.Write(networkId != null); if (networkId != null)
if (networkId != null) writer.WriteUInt(networkId.Value);
writer.Write(networkId.Value);
if (orderId != null) if (orderId != null)
writer.Write(orderId.Value); writer.WriteUShort(orderId.Value);
writer.Write(false);
writer.Write((ushort)data.Length); writer.WriteBool(false);
writer.Write(data);
} writer.WriteAlignBits();
writer.WriteByteArray(data);
int channel = MessageManager.channels[channelName]; int channel = MessageManager.channels[channelName];
for (int i = 0; i < clientIds.Length; i++) for (int i = 0; i < clientIds.Length; i++)
{ {
@ -176,7 +150,7 @@ namespace MLAPI.NetworkingManagerComponents.Core
netId = NetId.ServerNetId; netId = NetId.ServerNetId;
} }
byte error; byte error;
NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
} }
@ -189,28 +163,23 @@ namespace MLAPI.NetworkingManagerComponents.Core
return; return;
} }
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool using (BitWriter writer = new BitWriter())
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(MessageManager.messageTypes[messageType]);
{ writer.WriteBool(networkId != null);
writer.Write(MessageManager.messageTypes[messageType]);
writer.Write(networkId != null); if (networkId != null)
if (networkId != null) writer.WriteUInt(networkId.Value);
writer.Write(networkId.Value);
if (orderId != null) if (orderId != null)
writer.Write(orderId.Value); writer.WriteUShort(orderId.Value);
writer.Write(false);
writer.Write((ushort)data.Length); writer.WriteBool(false);
writer.Write(data);
} writer.WriteAlignBits();
writer.WriteByteArray(data);
int channel = MessageManager.channels[channelName]; int channel = MessageManager.channels[channelName];
for (int i = 0; i < clientIds.Count; i++) for (int i = 0; i < clientIds.Count; i++)
{ {
@ -226,7 +195,7 @@ namespace MLAPI.NetworkingManagerComponents.Core
netId = NetId.ServerNetId; netId = NetId.ServerNetId;
} }
byte error; byte error;
NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
} }
@ -240,29 +209,23 @@ namespace MLAPI.NetworkingManagerComponents.Core
Debug.LogWarning("MLAPI: Cannot send messages over encrypted channel to multiple clients."); Debug.LogWarning("MLAPI: Cannot send messages over encrypted channel to multiple clients.");
return; return;
} }
using (BitWriter writer = new BitWriter())
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool
int sizeOfStream = 6;
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(MessageManager.messageTypes[messageType]);
{ writer.WriteBool(networkId != null);
writer.Write(MessageManager.messageTypes[messageType]);
writer.Write(networkId != null); if (networkId != null)
if (networkId != null) writer.WriteUInt(networkId.Value);
writer.Write(networkId.Value);
if (orderId != null) if (orderId != null)
writer.Write(orderId.Value); writer.WriteUShort(orderId.Value);
writer.Write(false);
writer.Write((ushort)data.Length); writer.WriteBool(false);
writer.Write(data);
} writer.WriteAlignBits();
writer.WriteByteArray(data);
int channel = MessageManager.channels[channelName]; int channel = MessageManager.channels[channelName];
foreach (KeyValuePair<uint, NetworkedClient> pair in netManager.connectedClients) foreach (KeyValuePair<uint, NetworkedClient> pair in netManager.connectedClients)
{ {
@ -278,7 +241,7 @@ namespace MLAPI.NetworkingManagerComponents.Core
netId = NetId.ServerNetId; netId = NetId.ServerNetId;
} }
byte error; byte error;
NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
} }
@ -291,28 +254,23 @@ namespace MLAPI.NetworkingManagerComponents.Core
return; return;
} }
//2 bytes for messageType, 2 bytes for buffer length and one byte for target bool using (BitWriter writer = new BitWriter())
int sizeOfStream = 5;
if (networkId != null)
sizeOfStream += 4;
if (orderId != null)
sizeOfStream += 2;
sizeOfStream += data.Length;
using (MemoryStream stream = new MemoryStream(sizeOfStream))
{ {
using (BinaryWriter writer = new BinaryWriter(stream)) writer.WriteUShort(MessageManager.messageTypes[messageType]);
{ writer.WriteBool(networkId != null);
writer.Write(MessageManager.messageTypes[messageType]);
writer.Write(networkId != null); if (networkId != null)
if (networkId != null) writer.WriteUInt(networkId.Value);
writer.Write(networkId.Value);
if (orderId != null) if (orderId != null)
writer.Write(orderId.Value); writer.WriteUShort(orderId.Value);
writer.Write(false);
writer.Write((ushort)data.Length); writer.WriteBool(false);
writer.Write(data);
} writer.WriteAlignBits();
writer.WriteByteArray(data);
int channel = MessageManager.channels[channelName]; int channel = MessageManager.channels[channelName];
foreach (KeyValuePair<uint, NetworkedClient> pair in netManager.connectedClients) foreach (KeyValuePair<uint, NetworkedClient> pair in netManager.connectedClients)
{ {
@ -331,7 +289,7 @@ namespace MLAPI.NetworkingManagerComponents.Core
netId = NetId.ServerNetId; netId = NetId.ServerNetId;
} }
byte error; byte error;
NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, stream.GetBuffer(), sizeOfStream, out error); NetworkTransport.QueueMessageForSending(netId.HostId, netId.ConnectionId, channel, writer.Finalize(), (int)writer.GetFinalizeSize(), out error);
} }
} }
} }