moved message encoding to binary instead of string
parent
7d110bb8ad
commit
94333a389d
|
|
@ -21,14 +21,6 @@ namespace VelNet
|
|||
public Dropdown microphones;
|
||||
private DissonanceComms comms;
|
||||
|
||||
public void HandleSend()
|
||||
{
|
||||
if (sendInput.text != "")
|
||||
{
|
||||
VelNetManager.SendToRoom(Encoding.UTF8.GetBytes(sendInput.text));
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleLogin()
|
||||
{
|
||||
if (userInput.text != "")
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace VelNet
|
|||
}
|
||||
else
|
||||
{
|
||||
owner.SendMessage(this, index.ToString(), message, reliable);
|
||||
VelNetPlayer.SendMessage(this, (byte)index, message, reliable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ namespace VelNet
|
|||
|
||||
// send the message and an identifier for which component it belongs to
|
||||
int index = syncedComponents.IndexOf(component);
|
||||
owner.SendGroupMessage(this, group, index.ToString(), message, reliable);
|
||||
VelNetPlayer.SendGroupMessage(this, group, (byte)index, message, reliable);
|
||||
}
|
||||
|
||||
public void ReceiveBytes(string identifier, byte[] message)
|
||||
|
|
@ -128,6 +128,7 @@ namespace VelNet
|
|||
foreach (NetworkComponent c in comps)
|
||||
{
|
||||
c.networkObject = t;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(c);
|
||||
}
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(t);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,14 +65,20 @@ namespace VelNet
|
|||
#endregion
|
||||
|
||||
|
||||
public static bool SameAs(this byte[] bytes, byte[] otherBytes)
|
||||
public static bool BytesSame(byte[] b1, byte[] b2)
|
||||
{
|
||||
if (bytes.Length != otherBytes.Length)
|
||||
if (b1 == null && b2 != null) return false; // only one null
|
||||
if (b1 != null && b2 == null) return false; // only one null
|
||||
if (b1 == null) return true; // both null
|
||||
|
||||
// length doesn't match
|
||||
if (b1.Length != b2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !bytes.Where((t, i) => t != otherBytes[i]).Any();
|
||||
// check if any bytes are different
|
||||
return !b1.Where((t, i) => t != b2[i]).Any();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace VelNet
|
|||
byte[] newBytes = SendState();
|
||||
if (hybridOnChangeCompression)
|
||||
{
|
||||
if (Time.timeAsDouble - lastSendTime > slowSendInterval || !lastSentBytes.SameAs(newBytes))
|
||||
if (Time.timeAsDouble - lastSendTime > slowSendInterval || !BinaryWriterExtensions.BytesSame(lastSentBytes, newBytes))
|
||||
{
|
||||
SendBytes(newBytes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace VelNet
|
|||
byte[] newBytes = mem.ToArray();
|
||||
if (hybridOnChangeCompression)
|
||||
{
|
||||
if (Time.timeAsDouble - lastSendTime > slowSendInterval || !lastSentBytes.SameAs(newBytes))
|
||||
if (Time.timeAsDouble - lastSendTime > slowSendInterval || !BinaryWriterExtensions.BytesSame(lastSentBytes, newBytes))
|
||||
{
|
||||
SendBytes(newBytes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@ namespace VelNet
|
|||
MESSAGE_SETGROUP = 6
|
||||
};
|
||||
|
||||
public enum MessageType
|
||||
{
|
||||
ObjectSync,
|
||||
TakeOwnership,
|
||||
Instantiate,
|
||||
Destroy,
|
||||
DeleteSceneObjects
|
||||
}
|
||||
|
||||
public string host;
|
||||
public int port;
|
||||
|
||||
|
|
@ -455,6 +464,8 @@ namespace VelNet
|
|||
private void OnApplicationQuit()
|
||||
{
|
||||
socketConnection?.Close();
|
||||
clientReceiveThreadUDP?.Abort();
|
||||
clientReceiveThread?.Abort();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -473,10 +484,12 @@ namespace VelNet
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Runs in background clientReceiveThread; Listens for incoming data.
|
||||
/// Reads N bytes
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="N"></param>
|
||||
/// <returns></returns>
|
||||
private static byte[] ReadExact(Stream stream, int N)
|
||||
{
|
||||
byte[] toReturn = new byte[N];
|
||||
|
|
@ -505,6 +518,7 @@ namespace VelNet
|
|||
socketConnection = new TcpClient(host, port);
|
||||
socketConnection.NoDelay = true;
|
||||
NetworkStream stream = socketConnection.GetStream();
|
||||
using BinaryReader reader = new BinaryReader(stream);
|
||||
//now we are connected, so add a message to the queue
|
||||
AddMessage(new ConnectedMessage());
|
||||
//Join("MyRoom");
|
||||
|
|
@ -515,22 +529,26 @@ namespace VelNet
|
|||
{
|
||||
// Get a stream object for reading
|
||||
|
||||
|
||||
//read a byte
|
||||
byte type = (byte)stream.ReadByte();
|
||||
byte type = reader.ReadByte();
|
||||
|
||||
if (type == 0) //login
|
||||
switch (type)
|
||||
{
|
||||
//login
|
||||
case 0:
|
||||
{
|
||||
LoginMessage m = new LoginMessage();
|
||||
m.userId = GetIntFromBytes(ReadExact(stream, 4)); //not really the sender...
|
||||
m.userId = reader.ReadInt32(); //not really the sender...
|
||||
AddMessage(m);
|
||||
break;
|
||||
}
|
||||
else if (type == 1) //rooms
|
||||
//rooms
|
||||
case 1:
|
||||
{
|
||||
RoomsMessage m = new RoomsMessage();
|
||||
m.rooms = new List<ListedRoom>();
|
||||
int N = GetIntFromBytes(ReadExact(stream, 4)); //the size of the payload
|
||||
byte[] utf8data = ReadExact(stream, N);
|
||||
int N = reader.ReadInt32(); //the size of the payload
|
||||
byte[] utf8data = reader.ReadBytes(N);
|
||||
string roomMessage = Encoding.UTF8.GetString(utf8data);
|
||||
|
||||
|
||||
|
|
@ -548,29 +566,37 @@ namespace VelNet
|
|||
}
|
||||
|
||||
AddMessage(m);
|
||||
break;
|
||||
}
|
||||
else if (type == 2) //joined
|
||||
//joined
|
||||
case 2:
|
||||
{
|
||||
JoinMessage m = new JoinMessage();
|
||||
m.userId = GetIntFromBytes(ReadExact(stream, 4));
|
||||
int N = stream.ReadByte();
|
||||
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
|
||||
m.userId = reader.ReadInt32();
|
||||
int N = reader.ReadByte();
|
||||
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
|
||||
m.room = Encoding.UTF8.GetString(utf8data);
|
||||
AddMessage(m);
|
||||
break;
|
||||
}
|
||||
else if (type == 3) //data
|
||||
//data
|
||||
case 3:
|
||||
{
|
||||
DataMessage m = new DataMessage();
|
||||
m.senderId = GetIntFromBytes(ReadExact(stream, 4));
|
||||
int N = GetIntFromBytes(ReadExact(stream, 4)); //the size of the payload
|
||||
m.data = ReadExact(stream, N); //the message
|
||||
m.senderId = reader.ReadInt32();
|
||||
int N = reader.ReadInt32(); //the size of the payload
|
||||
m.data = reader.ReadBytes(N); //the message
|
||||
AddMessage(m);
|
||||
break;
|
||||
}
|
||||
else if (type == 4) //new master
|
||||
//new master
|
||||
case 4:
|
||||
{
|
||||
ChangeMasterMessage m = new ChangeMasterMessage();
|
||||
m.masterId = GetIntFromBytes(ReadExact(stream, 4)); //sender is the new master
|
||||
m.masterId = reader.ReadInt32(); //sender is the new master
|
||||
AddMessage(m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -684,15 +710,14 @@ namespace VelNet
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the server with a username
|
||||
/// </summary>
|
||||
///
|
||||
public static byte[] get_be_bytes(int n)
|
||||
{
|
||||
return BitConverter.GetBytes(n).Reverse().ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connects to the server with a username
|
||||
/// </summary>
|
||||
public static void Login(string username, string password)
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
|
|
@ -742,7 +767,7 @@ namespace VelNet
|
|||
}
|
||||
}
|
||||
|
||||
public static void SendToRoom(byte[] message, bool include_self = false, bool reliable = true, bool ordered = false)
|
||||
internal static void SendToRoom(byte[] message, bool include_self = false, bool reliable = true, bool ordered = false)
|
||||
{
|
||||
byte sendType = (byte)MessageSendType.MESSAGE_OTHERS;
|
||||
if (include_self && ordered) sendType = (byte)MessageSendType.MESSAGE_ALL_ORDERED;
|
||||
|
|
@ -752,12 +777,12 @@ namespace VelNet
|
|||
|
||||
if (reliable)
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter(stream);
|
||||
MemoryStream mem = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write(sendType);
|
||||
writer.Write(get_be_bytes(message.Length));
|
||||
writer.Write(message);
|
||||
SendTcpMessage(stream.ToArray());
|
||||
SendTcpMessage(mem.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -770,7 +795,7 @@ namespace VelNet
|
|||
}
|
||||
|
||||
|
||||
public static void SendToGroup(string group, byte[] message, bool reliable = true)
|
||||
internal static void SendToGroup(string group, byte[] message, bool reliable = true)
|
||||
{
|
||||
byte[] utf8bytes = Encoding.UTF8.GetBytes(group);
|
||||
if (reliable)
|
||||
|
|
@ -845,8 +870,14 @@ namespace VelNet
|
|||
newObject.owner = localPlayer;
|
||||
instance.objects.Add(newObject.networkId, newObject);
|
||||
|
||||
|
||||
// only sent to others, as I already instantiated this. Nice that it happens immediately.
|
||||
SendToRoom(Encoding.UTF8.GetBytes("7," + newObject.networkId + "," + prefabName), false, true);
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)MessageType.Instantiate);
|
||||
writer.Write(newObject.networkId);
|
||||
writer.Write(prefabName);
|
||||
SendToRoom(mem.ToArray(), include_self:false, reliable:true);
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
|
@ -917,8 +948,13 @@ namespace VelNet
|
|||
// immediately successful
|
||||
instance.objects[networkId].owner = LocalPlayer;
|
||||
|
||||
// must be ordered, so that ownership transfers are not confused. Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
SendToRoom(Encoding.UTF8.GetBytes("6," + networkId));
|
||||
// must be ordered, so that ownership transfers are not confused.
|
||||
// Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)MessageType.TakeOwnership);
|
||||
writer.Write(networkId);
|
||||
SendToRoom(mem.ToArray(), false, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace VelNet
|
||||
|
|
@ -40,7 +41,12 @@ namespace VelNet
|
|||
{
|
||||
if (kvp.Value.owner == this && kvp.Value.prefabName != "")
|
||||
{
|
||||
VelNetManager.SendToRoom(Encoding.UTF8.GetBytes("7," + kvp.Value.networkId + "," + kvp.Value.prefabName),false,true);
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.Instantiate);
|
||||
writer.Write(kvp.Value.networkId);
|
||||
writer.Write(kvp.Value.prefabName);
|
||||
VelNetManager.SendToRoom(mem.ToArray(), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,27 +60,39 @@ namespace VelNet
|
|||
|
||||
/// <summary>
|
||||
/// These are generally things that come from the "owner" and should be enacted locally, where appropriate
|
||||
///
|
||||
/// Overall message encoding:
|
||||
/// uint16: numMessages
|
||||
/// for m in numMessages
|
||||
/// int32: message size (including message type)
|
||||
/// byte: message type
|
||||
/// byte[]: message
|
||||
/// </summary>
|
||||
public void HandleMessage(VelNetManager.DataMessage m)
|
||||
{
|
||||
//for now, we can just convert to text...because
|
||||
using MemoryStream mem = new MemoryStream(m.data);
|
||||
using BinaryReader reader = new BinaryReader(mem);
|
||||
|
||||
string text = Encoding.UTF8.GetString(m.data);
|
||||
ushort numMessages = reader.ReadUInt16();
|
||||
|
||||
//types of messages
|
||||
string[] messages = text.Split(';'); //messages are split by ;
|
||||
foreach (string s in messages)
|
||||
for (int i = 0; i < numMessages; i++)
|
||||
{
|
||||
//individual message parameters separated by comma
|
||||
string[] sections = s.Split(',');
|
||||
int messageLength = reader.ReadInt32();
|
||||
VelNetManager.MessageType messageType = (VelNetManager.MessageType)reader.ReadByte();
|
||||
byte[] message = reader.ReadBytes(messageLength-1);
|
||||
|
||||
switch (sections[0])
|
||||
// make a separate reader to prevent malformed messages from messing us up
|
||||
using MemoryStream messageMem = new MemoryStream(message);
|
||||
using BinaryReader messageReader = new BinaryReader(messageMem);
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case "5": // sync update for an object I may own
|
||||
case VelNetManager.MessageType.ObjectSync: // sync update for an object I may own
|
||||
{
|
||||
string objectKey = sections[1];
|
||||
string identifier = sections[2];
|
||||
string syncMessage = sections[3];
|
||||
string objectKey = messageReader.ReadString();
|
||||
string identifier = messageReader.ReadString();
|
||||
string syncMessage = messageReader.ReadString();
|
||||
byte[] messageBytes = Convert.FromBase64String(syncMessage);
|
||||
if (manager.objects.ContainsKey(objectKey))
|
||||
{
|
||||
|
|
@ -86,9 +104,9 @@ namespace VelNet
|
|||
|
||||
break;
|
||||
}
|
||||
case "6": // I'm trying to take ownership of an object
|
||||
case VelNetManager.MessageType.TakeOwnership: // I'm trying to take ownership of an object
|
||||
{
|
||||
string networkId = sections[1];
|
||||
string networkId = messageReader.ReadString();
|
||||
|
||||
if (manager.objects.ContainsKey(networkId))
|
||||
{
|
||||
|
|
@ -97,10 +115,10 @@ namespace VelNet
|
|||
|
||||
break;
|
||||
}
|
||||
case "7": // I'm trying to instantiate an object
|
||||
case VelNetManager.MessageType.Instantiate: // I'm trying to instantiate an object
|
||||
{
|
||||
string networkId = sections[1];
|
||||
string prefabName = sections[2];
|
||||
string networkId = messageReader.ReadString();
|
||||
string prefabName = messageReader.ReadString();
|
||||
if (manager.objects.ContainsKey(networkId))
|
||||
{
|
||||
break; //we already have this one, ignore
|
||||
|
|
@ -110,22 +128,25 @@ namespace VelNet
|
|||
|
||||
break;
|
||||
}
|
||||
case "8": // I'm trying to destroy a gameobject I own
|
||||
case VelNetManager.MessageType.Destroy: // I'm trying to destroy a gameobject I own
|
||||
{
|
||||
string networkId = sections[1];
|
||||
string networkId = messageReader.ReadString();
|
||||
|
||||
VelNetManager.NetworkDestroy(networkId);
|
||||
break;
|
||||
}
|
||||
case "9": //deleted scene objects
|
||||
case VelNetManager.MessageType.DeleteSceneObjects: //deleted scene objects
|
||||
{
|
||||
for (int k = 1; k < sections.Length; k++)
|
||||
int len = messageReader.ReadInt32();
|
||||
for (int k = 1; k < len; k++)
|
||||
{
|
||||
VelNetManager.NetworkDestroy(sections[k]);
|
||||
VelNetManager.NetworkDestroy(messageReader.ReadString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -137,22 +158,39 @@ namespace VelNet
|
|||
//FindObjectsOfType<NetworkObject>();
|
||||
}
|
||||
|
||||
public void SendGroupMessage(NetworkObject obj, string group, string identifier, byte[] data, bool reliable = true)
|
||||
public static void SendGroupMessage(NetworkObject obj, string group, byte componentIdx, byte[] data, bool reliable = true)
|
||||
{
|
||||
string message = "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data);
|
||||
VelNetManager.SendToGroup(group, Encoding.UTF8.GetBytes(message), reliable);
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.ObjectSync);
|
||||
writer.Write(obj.networkId);
|
||||
writer.Write(componentIdx);
|
||||
writer.Write(data);
|
||||
VelNetManager.SendToGroup(group, mem.ToArray(), reliable);
|
||||
}
|
||||
|
||||
public void SendMessage(NetworkObject obj, string identifier, byte[] data, bool reliable = true)
|
||||
public static void SendMessage(NetworkObject obj, byte componentIdx, byte[] data, bool reliable = true)
|
||||
{
|
||||
string message = "5," + obj.networkId + "," + identifier + "," + Convert.ToBase64String(data);
|
||||
VelNetManager.SendToRoom(Encoding.UTF8.GetBytes(message), false, reliable);
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.ObjectSync);
|
||||
writer.Write(obj.networkId);
|
||||
writer.Write(componentIdx);
|
||||
writer.Write(data);
|
||||
VelNetManager.SendToRoom(mem.ToArray(), false, reliable);
|
||||
}
|
||||
|
||||
public void SendSceneUpdate()
|
||||
{
|
||||
string message = "9," + string.Join(",", manager.deletedSceneObjects);
|
||||
VelNetManager.SendToRoom( Encoding.UTF8.GetBytes(message));
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.DeleteSceneObjects);
|
||||
writer.Write(manager.deletedSceneObjects.Count);
|
||||
foreach (string o in manager.deletedSceneObjects)
|
||||
{
|
||||
writer.Write(o);
|
||||
}
|
||||
VelNetManager.SendToRoom(mem.ToArray());
|
||||
}
|
||||
|
||||
[Obsolete("Use VelNetManager.NetworkDestroy() instead.")]
|
||||
|
|
@ -162,7 +200,12 @@ namespace VelNet
|
|||
if (!manager.objects.ContainsKey(networkId) || manager.objects[networkId].owner != this || !isLocal) return;
|
||||
|
||||
// send to all, which will make me delete as well
|
||||
VelNetManager.SendToRoom(Encoding.UTF8.GetBytes("8," + networkId), true, true);
|
||||
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.Destroy);
|
||||
writer.Write(networkId);
|
||||
VelNetManager.SendToRoom(mem.ToArray(), true, true);
|
||||
}
|
||||
|
||||
/// <returns>True if successful, False if failed to transfer ownership</returns>
|
||||
|
|
@ -178,8 +221,13 @@ namespace VelNet
|
|||
// immediately successful
|
||||
manager.objects[networkId].owner = this;
|
||||
|
||||
// must be ordered, so that ownership transfers are not confused. Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
VelNetManager.SendToRoom(Encoding.UTF8.GetBytes("6," + networkId),true,true);
|
||||
// must be ordered, so that ownership transfers are not confused.
|
||||
// Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
writer.Write((byte)VelNetManager.MessageType.TakeOwnership);
|
||||
writer.Write(networkId);
|
||||
VelNetManager.SendToRoom(mem.ToArray(), true, true, ordered: true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue