Squashed 'Runtime/HumanoidControl/Scripts/Networking/Roboid/ControlCore/' changes from 9919aa6..aebe4c0

aebe4c0 Arduino Ant now works.
d3cb4c1 Merge commit 'fbeed8e80922152c3404fbd5d2b243ae95792ec1' into V2
fbeed8e Used Client override for processing messages
394dc22 Merge commit '355dd5c1c519cf07cfb6b9f9200f7f7311e68f20' into V2
355dd5c Fixed ThingMsg format
becb194 Merge commit 'f35d60369daf41a4fcd987ef8b31bd384b9536ba' into V2
9b53eee Merge commit 'a48ae12fc2f6d4a99119c128e78bf4b103e607c3' into V2
f35d603 Further improvements
a48ae12 ControlCore mostly works (but I don't see a model on the site server yet)
d8fc41f First step for ControlCore support

git-subtree-dir: Runtime/HumanoidControl/Scripts/Networking/Roboid/ControlCore
git-subtree-split: aebe4c0f8e805259a5aea4a4cb6b72343d73257a
This commit is contained in:
Pascal Serrarens 2024-12-09 12:12:08 +01:00
parent b3bb7d2f34
commit 7781fcf2de
8 changed files with 900 additions and 361 deletions

109
Client.cs Normal file
View File

@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net.Sockets;
namespace Passer.Control {
public class Client {
//public ConnectionMethod connection;
public UdpClient udpClient;
public string ipAddress;
public int port;
public byte networkId = 0;
public readonly ConcurrentQueue<IMessage> messageQueue = new();
public static Client GetClient(string ipAddress, int port) {
foreach (Client c in clients) {
if (c.ipAddress == ipAddress && c.port == port)
return c;
}
return null;
}
static public List<Client> clients = new List<Client>();
//// These static functions are deprecated
//public static Client NewClient() {
// Client client = new();
// clients.Add(client);
// client.networkId = 0;
// return client;
//}
//public static Client NewUDPClient(UdpClient udpClient, string ipAddress, int port) {
// Client client = NewClient();
// client.ipAddress = null;
// client.port = port;
// client.udpClient = udpClient;
// return client;
//}
//public Client() {
//}
public Client(UdpClient udpClient, int port) {
this.udpClient = udpClient;
this.ipAddress = null;
this.port = port;
clients.Add(this);
}
public void ProcessMessage(IMessage msg) {
switch (msg) {
case ClientMsg clientMsg:
ProcessClient(clientMsg);
break;
case NetworkIdMsg networkId:
ProcessNetworkId(networkId);
break;
case InvestigateMsg investigate:
ProcessInvestigate(investigate);
break;
case ThingMsg thing:
ProcessThing(thing);
break;
case NameMsg name:
ProcessName(name);
break;
case ModelUrlMsg modelUrl:
ProcessModelUrl(modelUrl);
break;
case PoseMsg pose:
ProcessPose(pose);
break;
case CustomMsg custom:
ProcessCustom(custom);
break;
case TextMsg text:
ProcessText(text);
break;
case DestroyMsg destroy:
ProcessDestroy(destroy);
break;
}
}
protected virtual void ProcessClient(ClientMsg client) { }
protected virtual void ProcessNetworkId(NetworkIdMsg networkId) { }
protected virtual void ProcessInvestigate(InvestigateMsg investigate) { }
protected virtual void ProcessThing(ThingMsg thing) { }
protected virtual void ProcessName(NameMsg name) { }
protected virtual void ProcessModelUrl(ModelUrlMsg modelUrl) { }
protected virtual void ProcessPose(PoseMsg pose) { }
protected virtual void ProcessCustom(CustomMsg custom) { }
protected virtual void ProcessText(TextMsg text) { }
protected virtual void ProcessDestroy(DestroyMsg destroy) { }
}
}

2
Client.cs.meta Normal file
View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: db9cd79cff119a9438110ead000031c3

173
EchoStream.cs Normal file
View File

@ -0,0 +1,173 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;
public class EchoStream : Stream {
public override bool CanTimeout { get; } = true;
public override int ReadTimeout { get; set; } = Timeout.Infinite;
public override int WriteTimeout { get; set; } = Timeout.Infinite;
public override bool CanRead { get; } = true;
public override bool CanSeek { get; } = false;
public override bool CanWrite { get; } = true;
public bool CopyBufferOnWrite { get; set; } = false;
private readonly object _lock = new object();
// Default underlying mechanism for BlockingCollection is ConcurrentQueue<T>, which is what we want
private readonly BlockingCollection<byte[]> _Buffers;
private int _maxQueueDepth = 10;
private byte[] m_buffer = null;
private int m_offset = 0;
private int m_count = 0;
private bool m_Closed = false;
private bool m_FinalZero = false; //after the stream is closed, set to true after returning a 0 for read()
public override void Close() {
m_Closed = true;
// release any waiting writes
_Buffers.CompleteAdding();
}
public bool DataAvailable {
get {
return _Buffers.Count > 0;
}
}
private long _Length = 0L;
public override long Length {
get {
return _Length;
}
}
private long _Position = 0L;
public override long Position {
get {
return _Position;
}
set {
throw new NotImplementedException();
}
}
public EchoStream() : this(10) {
}
public EchoStream(int maxQueueDepth) {
_maxQueueDepth = maxQueueDepth;
_Buffers = new BlockingCollection<byte[]>(_maxQueueDepth);
}
// we override the xxxxAsync functions because the default base class shares state between ReadAsync and WriteAsync, which causes a hang if both are called at once
public new Task WriteAsync(byte[] buffer, int offset, int count) {
return Task.Run(() => Write(buffer, offset, count));
}
// we override the xxxxAsync functions because the default base class shares state between ReadAsync and WriteAsync, which causes a hang if both are called at once
public new Task<int> ReadAsync(byte[] buffer, int offset, int count) {
return Task.Run(() => {
return Read(buffer, offset, count);
});
}
public override void Write(byte[] buffer, int offset, int count) {
if (m_Closed || buffer.Length - offset < count || count <= 0)
return;
byte[] newBuffer;
if (!CopyBufferOnWrite && offset == 0 && count == buffer.Length)
newBuffer = buffer;
else {
newBuffer = new byte[count];
System.Buffer.BlockCopy(buffer, offset, newBuffer, 0, count);
}
if (!_Buffers.TryAdd(newBuffer, WriteTimeout))
throw new TimeoutException("EchoStream Write() Timeout");
_Length += count;
}
public override int Read(byte[] buffer, int offset, int count) {
if (count == 0)
return 0;
lock (_lock) {
if (m_count == 0 && _Buffers.Count == 0) {
if (m_Closed) {
if (!m_FinalZero) {
m_FinalZero = true;
return 0;
}
else {
return -1;
}
}
if (_Buffers.TryTake(out m_buffer, ReadTimeout)) {
m_offset = 0;
m_count = m_buffer.Length;
}
else {
if (m_Closed) {
if (!m_FinalZero) {
m_FinalZero = true;
return 0;
}
else {
return -1;
}
}
else {
return 0;
}
}
}
int returnBytes = 0;
while (count > 0) {
if (m_count == 0) {
if (_Buffers.TryTake(out m_buffer, 0)) {
m_offset = 0;
m_count = m_buffer.Length;
}
else
break;
}
var bytesToCopy = (count < m_count) ? count : m_count;
System.Buffer.BlockCopy(m_buffer, m_offset, buffer, offset, bytesToCopy);
m_offset += bytesToCopy;
m_count -= bytesToCopy;
offset += bytesToCopy;
count -= bytesToCopy;
returnBytes += bytesToCopy;
}
_Position += returnBytes;
return returnBytes;
}
}
public override int ReadByte() {
byte[] returnValue = new byte[1];
return (Read(returnValue, 0, 1) <= 0 ? -1 : (int)returnValue[0]);
}
public override void Flush() {
}
public override long Seek(long offset, SeekOrigin origin) {
throw new NotImplementedException();
}
public override void SetLength(long value) {
throw new NotImplementedException();
}
}

2
EchoStream.cs.meta Normal file
View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 422516a56cbf14d46aaa0b1bc09115bf

View File

@ -1,6 +1,13 @@
using Passer;
public class LowLevelMessages {
public static void SendSpherical(byte[] buffer, ref uint ix, Spherical v) {
SendAngle8(buffer, ref ix, v.horizontal);
SendAngle8(buffer, ref ix, v.vertical);
SendFloat16(buffer, ref ix, new float16(v.distance));
}
public static Spherical ReceiveSpherical(byte[] data, ref uint ix) {
float horizontal = ReceiveAngle8(data, ref ix);
float vertical = ReceiveAngle8(data, ref ix);
@ -9,6 +16,23 @@ public class LowLevelMessages {
return v;
}
public static void SendQuat32(byte[] buffer, ref uint ix, Quat32 q) {
int qx = (int)(q.x * 127 + 128);
int qy = (int)(q.y * 127 + 128);
int qz = (int)(q.z * 127 + 128);
int qw = (int)(q.w * 255);
if (q.w < 0) {
qx = -qx;
qy = -qy;
qz = -qz;
qw = -qw;
}
buffer[ix++] = (byte)qx;
buffer[ix++] = (byte)qy;
buffer[ix++] = (byte)qz;
buffer[ix++] = (byte)qw;
}
public static Quat32 ReceiveQuat32(byte[] data, ref uint ix) {
Quat32 q = new(
(data[ix++] - 128.0F) / 127.0F,
@ -18,11 +42,26 @@ public class LowLevelMessages {
return q;
}
public static void SendAngle8(byte[] buffer, ref uint ix, float angle) {
// Normalize angle
while (angle >= 180)
angle -= 360;
while (angle < -180)
angle += 360;
buffer[ix++] = (byte)((angle / 360.0f) * 256.0f);
}
public static float ReceiveAngle8(byte[] data, ref uint ix) {
float value = (data[ix++] * 180) / 128.0F;
return value;
}
public static void SendFloat16(byte[] data, ref uint ix, float16 f) {
ushort binary = f.GetBinary();
data[ix++] = (byte)(binary >> 8);
data[ix++] = (byte)(binary & 255);
}
public static float ReceiveFloat16(byte[] data, ref uint ix) {
ushort value = (ushort)(data[ix++] << 8 | data[ix++]);
float16 f16 = new();
@ -30,6 +69,4 @@ public class LowLevelMessages {
float f = f16.toFloat();
return f;
}
}

View File

@ -1,47 +1,8 @@
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Passer.Control {
public class Client {
//public ConnectionMethod connection;
public UdpClient udpClient;
public string ipAddress;
public int port;
public byte networkId;
public readonly ConcurrentQueue<IMessage> messageQueue = new();
public static Client GetClient(string ipAddress, int port) {
foreach (Client c in clients) {
if (c.ipAddress == ipAddress && c.port == port)
return c;
}
return null;
}
static public List<Client> clients = new List<Client>();
public static Client NewClient() {
Client client = new();
clients.Add(client);
client.networkId = 0;
return client;
}
public static Client NewUDPClient(UdpClient udpClient, string ipAddress, int port) {
Client client = NewClient();
client.ipAddress = null;
client.port = port;
client.udpClient = udpClient;
return client;
}
}
public class IMessage {
public IMessage() { }
public IMessage(byte[] data) {
@ -61,6 +22,18 @@ namespace Passer.Control {
client.udpClient.Send(data, data.Length, client.ipAddress, client.port);
return true;
}
public static bool PublishMsg(Client client, IMessage msg) {
return PublishMsg(client, msg.Serialize());
}
public static bool PublishMsg(Client client, byte[] data) {
if (client == null)
return false;
client.udpClient.Send(data, data.Length, "127.0.0.1", client.port);
return true;
}
public static async Task<byte[]> Receive(Stream dataStream, byte packetSize) {
byte[] buffer = new byte[packetSize - 1]; // without msgId
int byteCount = dataStream.Read(buffer, 0, packetSize - 1);
@ -76,16 +49,35 @@ namespace Passer.Control {
#region Client
public class ClientMsg : IMessage {
public const byte Id = 0xA0;
public const byte length = 2;
public byte clientId;
public byte networkId;
public ClientMsg(byte networkId) {
this.networkId = networkId;
}
public ClientMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] buffer = new byte[ClientMsg.length];
buffer[0] = ClientMsg.Id;
buffer[1] = networkId;
return buffer;
}
public override void Deserialize(byte[] data) {
base.Deserialize(data);
uint ix = 0;
clientId = data[ix++];
networkId = data[ix];
}
public static bool Send(Client client, byte networkId) {
ClientMsg msg = new(networkId);
return SendMsg(client, msg);
}
public static bool Publish(Client client, byte networkId) {
ClientMsg msg = new(networkId);
return PublishMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
if (packetSize != length)
return false;
@ -95,12 +87,12 @@ namespace Passer.Control {
if (client.networkId == 0) {
client.networkId = (byte)(Client.clients.Count);
NetworkIdMsg.Send(client);
NetworkIdMsg.Send(client, client.networkId);
//if (string.IsNullOrEmpty(sceneUrl) == false)
//SendModelUrl(client, sceneUrl);
}
else if (msg.clientId == 0) {
NetworkIdMsg.Send(client);
else if (msg.networkId == 0) {
NetworkIdMsg.Send(client, client.networkId);
//if (string.IsNullOrEmpty(sceneUrl) == false)
//SendModelUrl(client, sceneUrl);
}
@ -116,42 +108,125 @@ namespace Passer.Control {
public class NetworkIdMsg : IMessage {
public const byte Id = 0xA1;
public const byte length = 2;
public byte networkId;
public static bool Send(Client client) {
NetworkIdMsg(byte networkId) {
this.networkId = networkId;
}
NetworkIdMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] data = new byte[NetworkIdMsg.length];
data[0] = NetworkIdMsg.Id;
data[1] = client.networkId;
return SendMsg(client, data);
data[1] = this.networkId;
return data;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
this.networkId = data[ix];
}
public static bool Send(Client client, byte networkId) {
NetworkIdMsg msg = new(networkId);
return SendMsg(client, msg);
//byte[] data = new byte[NetworkIdMsg.length];
//data[0] = NetworkIdMsg.Id;
//data[1] = client.networkId;
//return SendMsg(client, data);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
if (packetSize != length)
return false;
byte[] buffer = await Receive(dataStream, packetSize);
NetworkIdMsg msg = new(buffer);
client.messageQueue.Enqueue(msg);
return true;
}
}
#endregion Network Id
#region Investigate
public class InvestigateMsg : IMessage {
public const byte Id = 0x81;
public const byte length = 3;
public byte networkId;
public byte thingId;
public InvestigateMsg(byte networkId, byte thingId) {
this.networkId = networkId;
this.thingId = thingId;
}
public InvestigateMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] buffer = new byte[InvestigateMsg.length];
buffer[0] = InvestigateMsg.Id;
buffer[1] = this.networkId;
buffer[2] = this.thingId;
return buffer;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
this.networkId = data[ix++];
this.thingId = data[ix++];
}
public static bool Send(Client client, byte thingId) {
InvestigateMsg msg = new(client.networkId, thingId);
return SendMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
if (packetSize != length)
return false;
byte[] buffer = await Receive(dataStream, packetSize);
InvestigateMsg msg = new(buffer);
client.messageQueue.Enqueue(msg);
return true;
}
}
#endregion Investigate
#region Thing
public class ThingMsg : IMessage {
public const byte length = 4;
public const byte Id = 0x80;
public byte objectId;
public byte objectType;
public byte thingId;
public byte thingType;
public byte parentId;
public ThingMsg(byte thingId, byte thingType, byte parentId) {
this.thingId = thingId;
this.thingType = thingType;
this.parentId = parentId;
}
public ThingMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] data = new byte[ThingMsg.length];
byte ix = 0;
data[ix++] = ThingMsg.Id;
data[ix++] = this.thingId;
data[ix++] = this.thingType;
data[ix] = this.parentId;
return data;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
objectId = data[ix++];
objectType = data[ix++];
parentId = data[ix];
this.thingId = data[ix++];
this.thingType = data[ix++];
this.parentId = data[ix];
}
public static bool Send(Client client, byte networkId, byte thingId, byte thingType) {
byte[] data = new byte[4];
data[0] = ThingMsg.Id;
data[1] = networkId;
data[2] = thingId;
data[3] = thingType;
data[4] = 0x00; // parent not supported yet
return SendMsg(client, data);
public static bool Send(Client client, byte thingId, byte thingType, byte parentId) {
ThingMsg msg = new(thingId, thingType, parentId);
return SendMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
if (packetSize != length)
@ -170,19 +245,38 @@ namespace Passer.Control {
#region Name
public class NameMsg : IMessage {
public byte networkId = 0;
public byte objectId;
public const byte Id = 0x91; // 145
public const byte length = 3;
public byte thingId;
public byte len;
public string name;
public NameMsg(byte thingId, string name) {
this.thingId = thingId;
this.name = name;
}
public NameMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] buffer = new byte[length + this.name.Length];
buffer[0] = NameMsg.Id;
buffer[1] = this.thingId;
buffer[2] = (byte)this.name.Length;
for (int ix = 0; ix < this.name.Length; ix++)
buffer[3 + ix] = (byte)this.name[ix];
return buffer;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
this.objectId = data[ix++];
this.thingId = data[ix++];
int strlen = data[ix++];
this.name = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen);
}
public static bool Send(Client client, byte thingId, string name) {
NameMsg msg = new(thingId, name);
return SendMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
byte[] buffer = await Receive(dataStream, packetSize);
NameMsg msg = new(buffer);
@ -198,12 +292,13 @@ namespace Passer.Control {
public class ModelUrlMsg : IMessage {
public const byte Id = 0x90; // (144) Model URL
public byte objectId;
public byte thingId;
public Spherical position;
public float scale;
public string url;
public ModelUrlMsg(string url, float scale = 1) {
public ModelUrlMsg(byte thingId, string url, float scale = 1) {
this.thingId = thingId;
this.url = url;
this.scale = scale;
this.position = Spherical.zero;
@ -213,7 +308,7 @@ namespace Passer.Control {
public override byte[] Serialize() {
byte[] data = new byte[this.url.Length + 9];
data[0] = ModelUrlMsg.Id;
data[1] = 0x00; // Thing Id
data[1] = this.thingId; // Thing Id
// data[2]..[5] == position 0, 0, 0
data[6] = 0x3C; // Dummy float16 value 1
data[7] = 0x00;
@ -225,15 +320,15 @@ namespace Passer.Control {
}
public override void Deserialize(byte[] data) {
uint ix = 0;
this.objectId = data[ix++];
this.thingId = data[ix++];
this.position = LowLevelMessages.ReceiveSpherical(data, ref ix);
this.scale = LowLevelMessages.ReceiveFloat16(data, ref ix);
int strlen = data[ix++];
url = System.Text.Encoding.UTF8.GetString(data, (int)ix, strlen);
}
public static bool Send(Client client, string modelUrl) {
ModelUrlMsg msg = new(modelUrl);
public static bool Send(Client client, byte thingId, string modelUrl) {
ModelUrlMsg msg = new(thingId, modelUrl);
return SendMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
@ -249,15 +344,44 @@ namespace Passer.Control {
#region Pose
public class PoseMsg : IMessage {
public const byte Id = 0x10;
public const byte length = 3 + 4 + 4;
public byte thingId;
public byte poseType;
public const byte Pose_Position = 0x01;
public const byte Pose_Orientation = 0x02;
public Spherical position;
public Quat32 orientation;
public PoseMsg(byte thingId, Spherical position, Quat32 orientation) {
this.thingId = thingId;
this.position = position;
this.orientation = orientation;
this.poseType = 0;
if (this.position != null)
this.poseType |= Pose_Position;
else
this.position = new Spherical(0, 0, 0);
if (this.orientation != null)
this.poseType |= Pose_Orientation;
else
this.orientation = new Quat32(0, 0, 0, 1);
}
public PoseMsg(byte[] data) : base(data) { }
public override byte[] Serialize() {
byte[] buffer = new byte[PoseMsg.length];
uint ix = 0;
buffer[ix++] = PoseMsg.Id;
buffer[ix++] = this.thingId;
buffer[ix++] = this.poseType;
LowLevelMessages.SendSpherical(buffer, ref ix, position);
LowLevelMessages.SendQuat32(buffer, ref ix, orientation);
return buffer;
}
public override void Deserialize(byte[] data) {
uint ix = 0;
thingId = data[ix++];
@ -269,6 +393,10 @@ namespace Passer.Control {
orientation = LowLevelMessages.ReceiveQuat32(data, ref ix);
}
public static bool Send(Client client, byte thingId, Spherical position, Quat32 orientation) {
PoseMsg msg = new(thingId, position, orientation);
return SendMsg(client, msg);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
if (packetSize != length)
return false;
@ -278,30 +406,30 @@ namespace Passer.Control {
client.messageQueue.Enqueue(msg);
return true;
}
}
#endregion Pose
#region Bytes
#region Custom
public class BytesMsg : IMessage {
public class CustomMsg : IMessage {
public const byte Id = 0xB1;
public byte networkId;
public byte thingId;
public byte[] bytes;
public BytesMsg(byte[] data) : base(data) { }
public BytesMsg(byte networkId, byte thingId, byte[] bytes) : base() {
public CustomMsg(byte[] data) : base(data) { }
public CustomMsg(byte networkId, byte thingId, byte[] bytes) : base() {
this.networkId = networkId;
this.thingId = thingId;
this.bytes = bytes;
}
public override byte[] Serialize() {
byte[] buffer = new byte[4 + this.bytes.Length];
int ix = 0;
buffer[ix++] = BytesMsg.Id;
buffer[ix++] = CustomMsg.Id;
buffer[ix++] = this.networkId;
buffer[ix++] = this.thingId;
buffer[ix++] = (byte)bytes.Length;
@ -311,7 +439,6 @@ namespace Passer.Control {
return buffer;
}
public override void Deserialize(byte[] data) {
//this.bytes = data;
uint ix = 0;
this.thingId = data[ix++];
this.bytes = new byte[data.Length - ix];
@ -321,24 +448,47 @@ namespace Passer.Control {
public static void Send(Client client, byte thingId, byte[] bytes) {
BytesMsg msg = new(client.networkId, thingId, bytes);
CustomMsg msg = new(client.networkId, thingId, bytes);
SendMsg(client, msg);
}
// received bytes
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
byte[] buffer = await Receive(dataStream, packetSize);
BytesMsg msg = new(buffer);
CustomMsg msg = new(buffer);
client.messageQueue.Enqueue(msg);
return true;
}
}
#endregion Bytes
#endregion Custom
#region Text
public class TextMsg : IMessage {
public const byte Id = 0xB0;
public string text;
public TextMsg(byte[] data) : base(data) { }
public override void Deserialize(byte[] data) {
uint ix = 0;
uint strlen = data[ix++];
this.text = System.Text.Encoding.UTF8.GetString(data, (int)ix, (int)strlen);
}
public static async Task<bool> Receive(Stream dataStream, Client client, byte packetSize) {
byte[] buffer = await Receive(dataStream, packetSize);
TextMsg msg = new(buffer);
client.messageQueue.Enqueue(msg);
return true;
}
}
#endregion
#region Destroy
public class DestroyMsg : IMessage {
public const byte Id = 0x20;
public const byte length = 2;
public byte objectId;

64
SiteServer.cs Normal file
View File

@ -0,0 +1,64 @@
using System.IO;
using System.Threading.Tasks;
namespace Passer.Control {
public static class SiteServer {
public static async Task ReceiveData(Stream dataStream, Client client) {
while (true) {
byte packetSize = (byte)dataStream.ReadByte();
if (packetSize != 0xFF)
await ReceiveData(dataStream, client, packetSize);
// else timeout
}
}
public static async Task ReceiveData(Stream dataStream, Client client, byte packetSize) {
byte msgId = (byte)dataStream.ReadByte();
if (msgId == 0xFF) {
// Timeout
return;
}
bool result = false;
switch (msgId) {
case ClientMsg.Id: // 0xA0 / 160
result = await ClientMsg.Receive(dataStream, client, packetSize);
break;
case NetworkIdMsg.Id: // 0xA1 / 161
result = await NetworkIdMsg.Receive(dataStream, client, packetSize);
break;
case InvestigateMsg.Id: // 0x81
result = await InvestigateMsg.Receive(dataStream, client, packetSize);
break;
case ThingMsg.Id: // 0x80 / 128
result = await ThingMsg.Receive(dataStream, client, packetSize);
break;
case NameMsg.Id: // 0x91 / 145
result = await NameMsg.Receive(dataStream, client, packetSize);
break;
case ModelUrlMsg.Id: // 0x90 / 144
result = await ModelUrlMsg.Receive(dataStream, client, packetSize);
break;
case PoseMsg.Id: // 0x10 / 16
result = await PoseMsg.Receive(dataStream, client, packetSize);
break;
case CustomMsg.Id: // 0xB1 / 177
result = await CustomMsg.Receive(dataStream, client, packetSize);
break;
case TextMsg.Id: // 0xB0 / 176
result = await TextMsg.Receive(dataStream, client, packetSize);
break;
case DestroyMsg.Id: // 0x20 / 32
result = await DestroyMsg.Receive(dataStream, client, packetSize);
break;
default:
break;
}
if (result == false) {
packetSize = msgId; // skip 1 byte, msgId is possibly a packet size byte
await ReceiveData(dataStream, client, packetSize);
}
}
}
}

2
SiteServer.cs.meta Normal file
View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 53345abb9310d344baa67c19a8d8249f