Moved ip/port out of participant to participantUDP

This commit is contained in:
Pascal Serrarens 2025-06-06 17:20:39 +02:00
parent 57cff2d4b2
commit 027c0c7b80
7 changed files with 196 additions and 109 deletions

View File

@ -22,18 +22,19 @@ namespace RoboidControl.Unity {
case ThingMsg.id: case ThingMsg.id:
HandleThingEvent(e); HandleThingEvent(e);
break; break;
default:
Debug.Log($"Unhandled event: {e.messageId}");
break;
} }
} }
protected virtual void HandleThingEvent(RoboidControl.Participant.UpdateEvent e) { protected virtual void HandleThingEvent(RoboidControl.Participant.UpdateEvent e) {
switch (e.thing) { switch (e.thing) {
case RoboidControl.TouchSensor coreTouchSensor: case RoboidControl.TouchSensor coreTouchSensor:
Debug.Log("Handle TouchSensor");
TouchSensor touchSensor = TouchSensor.Create(coreTouchSensor); TouchSensor touchSensor = TouchSensor.Create(coreTouchSensor);
coreTouchSensor.component = touchSensor; coreTouchSensor.component = touchSensor;
break; break;
case RoboidControl.DifferentialDrive coreDrive: case RoboidControl.DifferentialDrive coreDrive:
Debug.Log("Handle Diff.Drive");
DifferentialDrive differentialDrive = DifferentialDrive.Create(coreDrive); DifferentialDrive differentialDrive = DifferentialDrive.Create(coreDrive);
coreDrive.component = differentialDrive; coreDrive.component = differentialDrive;
break; break;
@ -44,7 +45,6 @@ namespace RoboidControl.Unity {
// before we can create the wheel reliably // before we can create the wheel reliably
break; break;
case RoboidControl.Thing coreThing: case RoboidControl.Thing coreThing:
// Debug.Log("Handle Thing");
if (coreThing.component == null) { if (coreThing.component == null) {
Thing[] things = FindObjectsByType<Thing>(FindObjectsSortMode.None); Thing[] things = FindObjectsByType<Thing>(FindObjectsSortMode.None);
// Debug.Log(things.Length); // Debug.Log(things.Length);

View File

@ -49,8 +49,11 @@ namespace RoboidControl.Unity {
Participant participant = remoteParticipant.AddComponent<Participant>(); Participant participant = remoteParticipant.AddComponent<Participant>();
participant.coreParticipant = e.participant; participant.coreParticipant = e.participant;
participant.coreParticipant.component = participant; participant.coreParticipant.component = participant;
participant.ipAddress = e.participant.ipAddress; ParticipantUDP participantUDP = participant.coreParticipant as ParticipantUDP;
participant.port = e.participant.port; if (participantUDP != null) {
participant.ipAddress = participantUDP.ipAddress;
participant.port = participantUDP.port;
}
foreach (RoboidControl.Thing thing in this.site.things) foreach (RoboidControl.Thing thing in this.site.things)
participant.coreParticipant.SendThingInfo(thing); participant.coreParticipant.SendThingInfo(thing);

View File

@ -29,7 +29,6 @@ namespace RoboidControl.Unity {
/// <param name="core">The core of the thing</param> /// <param name="core">The core of the thing</param>
/// <returns>The created thing</returns> /// <returns>The created thing</returns>
public static Thing Create(RoboidControl.Thing core) { public static Thing Create(RoboidControl.Thing core) {
Debug.Log("Creating new Unity thing");
GameObject gameObj = string.IsNullOrEmpty(core.name) ? GameObject gameObj = string.IsNullOrEmpty(core.name) ?
new("Thing") : new("Thing") :
new(core.name); new(core.name);
@ -117,18 +116,15 @@ namespace RoboidControl.Unity {
private void HandleCoreEvent(RoboidControl.Thing.CoreEvent coreEvent) { private void HandleCoreEvent(RoboidControl.Thing.CoreEvent coreEvent) {
switch (coreEvent.messageId) { switch (coreEvent.messageId) {
case ThingMsg.id: case ThingMsg.id:
Debug.Log($"{this.core.id} Handle Thing");
if (core.parent == null) if (core.parent == null)
this.transform.SetParent(core.owner.component.transform, true); this.transform.SetParent(core.owner.component.transform, true);
else if (core.parent.component != null) else if (core.parent.component != null)
this.transform.SetParent(core.parent.component.transform, true); this.transform.SetParent(core.parent.component.transform, true);
break; break;
case NameMsg.Id: case NameMsg.Id:
Debug.Log($"{this.core.id} Handle Name");
this.gameObject.name = core.name; this.gameObject.name = core.name;
break; break;
case ModelUrlMsg.Id: case ModelUrlMsg.Id:
Debug.Log($"{this.core.id} Handle Model URL");
string extension = core.modelUrl[core.modelUrl.LastIndexOf(".")..]; string extension = core.modelUrl[core.modelUrl.LastIndexOf(".")..];
if (extension == ".jpg" || extension == ".png") if (extension == ".jpg" || extension == ".png")
StartCoroutine(LoadJPG()); StartCoroutine(LoadJPG());
@ -138,11 +134,9 @@ namespace RoboidControl.Unity {
#endif #endif
break; break;
case PoseMsg.Id: case PoseMsg.Id:
Debug.Log($"{this.core.id} Handle Pose");
this.HandlePose(); this.HandlePose();
break; break;
case BinaryMsg.Id: case BinaryMsg.Id:
Debug.Log($"{this.core.id} Handle Binary");
this.HandleBinary(); this.HandleBinary();
break; break;
} }
@ -185,7 +179,9 @@ namespace RoboidControl.Unity {
if (!loadingModel) { if (!loadingModel) {
loadingModel = true; loadingModel = true;
#if DEBUG
Debug.Log("Loading GLTF model from :" + coreThing.modelUrl); Debug.Log("Loading GLTF model from :" + coreThing.modelUrl);
#endif
GltfImport gltfImport = new GltfImport(); GltfImport gltfImport = new GltfImport();
bool success = await gltfImport.Load(coreThing.modelUrl); bool success = await gltfImport.Load(coreThing.modelUrl);
if (success) { if (success) {
@ -206,7 +202,7 @@ namespace RoboidControl.Unity {
if (meshRenderers.Length > 0) { if (meshRenderers.Length > 0) {
foreach (SkinnedMeshRenderer meshRenderer in meshRenderers) { foreach (SkinnedMeshRenderer meshRenderer in meshRenderers) {
if (meshRenderer.rootBone != null) { if (meshRenderer.rootBone != null) {
Debug.Log("Found a skinned mesh with bones"); // Debug.Log("Found a skinned mesh with bones");
ScanForThings(meshRenderer.rootBone); ScanForThings(meshRenderer.rootBone);
break; break;
} }
@ -232,7 +228,7 @@ namespace RoboidControl.Unity {
if (foundObj != null && (thing.component != null && foundObj != thing.component.gameObject)) { if (foundObj != null && (thing.component != null && foundObj != thing.component.gameObject)) {
Thing foundThing = foundObj.GetComponent<Thing>(); Thing foundThing = foundObj.GetComponent<Thing>();
if (foundThing == null) { if (foundThing == null) {
Debug.Log($"move thing [{thing.owner.networkId}/{thing.id}] to {foundObj.name}"); // Debug.Log($"move thing [{thing.owner.networkId}/{thing.id}] to {foundObj.name}");
foundThing = foundObj.AddComponent<Thing>(); foundThing = foundObj.AddComponent<Thing>();
foundThing.core = thing; foundThing.core = thing;
foundThing.core.position = LinearAlgebra.Spherical.FromVector3(foundObj.transform.localPosition); foundThing.core.position = LinearAlgebra.Spherical.FromVector3(foundObj.transform.localPosition);

View File

@ -31,13 +31,13 @@ namespace RoboidControl {
/// <param name="port">The UDP port of the participant</param> /// <param name="port">The UDP port of the participant</param>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future /// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public Participant(string ipAddress, int port, Participant localParticipant = null) { public Participant(string ipAddress, int port, Participant localParticipant = null) {
this.ipAddress = ipAddress; // this.ipAddress = ipAddress;
this.port = port; // this.port = port;
Thing.CreateRoot(this); Thing.CreateRoot(this);
if (localParticipant != null) // if (localParticipant != null)
this.udpClient = localParticipant.udpClient; // this.udpClient = localParticipant.udpClient;
} }
/// <summary> /// <summary>
@ -56,28 +56,32 @@ namespace RoboidControl {
#region Properties #region Properties
/*
/// <summary> /// <summary>
/// The Ip Address of a participant. When the participant is local, this contains 0.0.0.0 /// The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
/// </summary> /// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future /// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public string ipAddress = "0.0.0.0"; protected string ipAddress = "0.0.0.0";
/// <summary> /// <summary>
/// The port number for UDP communication with the participant. This is 0 for isolated participants. /// The port number for UDP communication with the participant. This is 0 for isolated participants.
/// </summary> /// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future /// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public int port = 0; protected int port = 0;
/// <summary> /// <summary>
/// The udpClient for this participant /// The udpClient for this participant
/// </summary> /// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future /// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public UdpClient udpClient = null; public UdpClient udpClient = null;
*/
/// <summary> /// <summary>
/// The network Id to identify the participant /// The network Id to identify the participant
/// </summary> /// </summary>
public byte networkId = 0; public byte networkId = 0;
public bool isRemote = false;
/// <summary> /// <summary>
/// The root thing for this participant /// The root thing for this participant
/// </summary> /// </summary>
@ -178,17 +182,18 @@ namespace RoboidControl {
public byte[] buffer = new byte[1024]; public byte[] buffer = new byte[1024];
public virtual bool Send(IMessage msg) { public virtual bool Send(IMessage msg) {
int bufferSize = msg.Serialize(ref this.buffer); return false;
if (bufferSize <= 0) // int bufferSize = msg.Serialize(ref this.buffer);
return true; // if (bufferSize <= 0)
// return true;
IPEndPoint participantEndpoint = new IPEndPoint(IPAddress.Parse(this.ipAddress), this.port); // IPEndPoint participantEndpoint = new IPEndPoint(IPAddress.Parse(this.ipAddress), this.port);
// Console.WriteLine($"msg to remote participant {participantEndpoint.Address.ToString()} {participantEndpoint.Port}"); // // Console.WriteLine($"msg to remote participant {participantEndpoint.Address.ToString()} {participantEndpoint.Port}");
if (udpClient != null) { // if (udpClient != null) {
//Console.WriteLine("sending..."); // //Console.WriteLine("sending...");
this.udpClient?.Send(this.buffer, bufferSize, participantEndpoint); // this.udpClient?.Send(this.buffer, bufferSize, participantEndpoint);
} // }
return true; // return true;
} }
public void SendThingInfo(Thing thing) { public void SendThingInfo(Thing thing) {
@ -214,14 +219,14 @@ namespace RoboidControl {
/// <param name="ipAddress">The ip address of the participant</param> /// <param name="ipAddress">The ip address of the participant</param>
/// <param name="port">The port number used to send messages to the participant</param> /// <param name="port">The port number used to send messages to the participant</param>
/// <returns>The participant or null if it is not found.</returns> /// <returns>The participant or null if it is not found.</returns>
public static Participant GetParticipant(string ipAddress, int port) { // public static Participant GetParticipant(string ipAddress, int port) {
//Console.WriteLine($"Get Participant {ipAddress}:{port}"); // //Console.WriteLine($"Get Participant {ipAddress}:{port}");
foreach (Participant participant in Participant.participants) { // foreach (Participant participant in Participant.participants) {
if (participant.ipAddress == ipAddress && participant.port == port) // if (participant.ipAddress == ipAddress && participant.port == port)
return participant; // return participant;
} // }
return null; // return null;
} // }
/// <summary> /// <summary>
/// Retrieve a participant using a network ID /// Retrieve a participant using a network ID
/// </summary> /// </summary>
@ -236,21 +241,21 @@ namespace RoboidControl {
return null; return null;
} }
/// <summary> // /// <summary>
/// Add a new participant to the collection of participants // /// Add a new participant to the collection of participants
/// </summary> // /// </summary>
/// <param name="ipAddress">The IP address of the participant</param> // /// <param name="ipAddress">The IP address of the participant</param>
/// <param name="port">The port used to send messages to this participant</param> // /// <param name="port">The port used to send messages to this participant</param>
/// <returns>The added participant</returns> // /// <returns>The added participant</returns>
public static Participant AddParticipant(string ipAddress, int port, Participant localParticipant = null) { // public static Participant AddParticipant(string ipAddress, int port, Participant localParticipant = null) {
Console.WriteLine($"New Participant {ipAddress}:{port}"); // Console.WriteLine($"New Participant {ipAddress}:{port}");
// This code is only valid for site, because those can distribute networkIds..... // // This code is only valid for site, because those can distribute networkIds.....
Participant participant = new(ipAddress, port, localParticipant) { // Participant participant = new(ipAddress, port, localParticipant) {
networkId = (byte)(Participant.participants.Count + 1) // networkId = (byte)(Participant.participants.Count + 1)
}; // };
Participant.participants.Add(participant); // Participant.participants.Add(participant);
return participant; // return participant;
} // }
/// <summary> /// <summary>
/// Add a new participant to the collection of participants /// Add a new participant to the collection of participants
/// </summary> /// </summary>

View File

@ -83,6 +83,15 @@ namespace RoboidControl {
Participant.ReplaceLocalParticipant(this); Participant.ReplaceLocalParticipant(this);
} }
public ParticipantUDP(string ipAddress, int port, ParticipantUDP localParticipant) : base(ipAddress, port, localParticipant) {
this.ipAddress = ipAddress;
this.port = port;
if (localParticipant != null)
this.udpClient = localParticipant.udpClient;
}
#endregion Init #endregion Init
#region Properties #region Properties
@ -92,6 +101,23 @@ namespace RoboidControl {
/// </summary> /// </summary>
public string name = "ParticipantUDP"; public string name = "ParticipantUDP";
/// <summary>
/// The Ip Address of a participant. When the participant is local, this contains 0.0.0.0
/// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public string ipAddress = "0.0.0.0";
/// <summary>
/// The port number for UDP communication with the participant. This is 0 for isolated participants.
/// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public int port = 0;
/// <summary>
/// The udpClient for this participant
/// </summary>
/// <remarks>This does not belong here, it should move to ParticipantUDP or something like that in the future
public UdpClient udpClient = null;
/// <summary> /// <summary>
/// True if the participant is running isolated. /// True if the participant is running isolated.
/// </summary> /// </summary>
@ -109,10 +135,7 @@ namespace RoboidControl {
public ulong publishIntervalMS = 3000; // = 3 seconds public ulong publishIntervalMS = 3000; // = 3 seconds
public ulong sendUpdateIntervalMS = 100; // = 0.1 seconds for object updates public ulong sendUpdateIntervalMS = 100; // = 0.1 seconds for object updates
//public byte[] buffer = new byte[1024];
public IPEndPoint endPoint = null; public IPEndPoint endPoint = null;
//public UdpClient udpClient = null;
public string broadcastIpAddress = "255.255.255.255"; public string broadcastIpAddress = "255.255.255.255";
public readonly ConcurrentQueue<IMessage> messageQueue = new ConcurrentQueue<IMessage>(); public readonly ConcurrentQueue<IMessage> messageQueue = new ConcurrentQueue<IMessage>();
@ -132,8 +155,8 @@ namespace RoboidControl {
IPAddress broadcastAddress = new(broadcastBytes); IPAddress broadcastAddress = new(broadcastBytes);
this.broadcastIpAddress = broadcastAddress.ToString(); this.broadcastIpAddress = broadcastAddress.ToString();
Console.WriteLine($"Subnet mask: {subnetMask.ToString()}"); // Console.WriteLine($"Subnet mask: {subnetMask.ToString()}");
Console.WriteLine($"Broadcast address: {this.broadcastIpAddress}"); // Console.WriteLine($"Broadcast address: {this.broadcastIpAddress}");
} }
#endregion Properties #endregion Properties
@ -143,7 +166,7 @@ namespace RoboidControl {
public override void Update() { public override void Update() {
ulong currentTimeMS = Thing.GetTimeMs(); ulong currentTimeMS = Thing.GetTimeMs();
if (this.isIsolated == false) { if (this.isIsolated == false && this.isRemote == false) {
if (this.publishIntervalMS > 0 && currentTimeMS > this.nextPublishMe) { if (this.publishIntervalMS > 0 && currentTimeMS > this.nextPublishMe) {
ParticipantMsg msg = new(this.networkId); ParticipantMsg msg = new(this.networkId);
if (this.remoteSite == null) if (this.remoteSite == null)
@ -156,6 +179,7 @@ namespace RoboidControl {
} }
UpdateMyThings(currentTimeMS); UpdateMyThings(currentTimeMS);
if (this.isRemote == false)
UpdateOtherThings(currentTimeMS); UpdateOtherThings(currentTimeMS);
} }
@ -167,11 +191,11 @@ namespace RoboidControl {
if (thing == null) if (thing == null)
continue; continue;
if (thing.hierarchyChanged && !(this.isIsolated || this.networkId == 0)) { // if (thing.hierarchyChanged && !(this.isIsolated || this.networkId == 0)) {
ThingMsg thingMsg = new(this.networkId, thing); // ThingMsg thingMsg = new(this.networkId, thing);
// this.Send(this.remoteSite, thingMsg); // // this.Send(this.remoteSite, thingMsg);
this.remoteSite.Send(thingMsg); // this.remoteSite.Send(thingMsg);
} // }
// Why don't we do recursive? // Why don't we do recursive?
// Because when a thing creates a thing in the update, // Because when a thing creates a thing in the update,
@ -184,15 +208,15 @@ namespace RoboidControl {
// this.Send(this.remoteSite, destroyMsg); // this.Send(this.remoteSite, destroyMsg);
this.remoteSite.Send(destroyMsg); this.remoteSite.Send(destroyMsg);
} }
else { // else {
// Send to remote site // // Send to remote site
// PoseMsg poseMsg = new(thing.owner.networkId, thing); // // PoseMsg poseMsg = new(thing.owner.networkId, thing);
// this.Send(this.remoteSite, poseMsg); // // this.Send(this.remoteSite, poseMsg);
// BinaryMsg binaryMsg = new(thing.owner.networkId, thing); // // BinaryMsg binaryMsg = new(thing.owner.networkId, thing);
// this.Send(this.remoteSite, binaryMsg); // // this.Send(this.remoteSite, binaryMsg);
this.remoteSite.Send(new PoseMsg(thing.owner.networkId, thing)); // this.remoteSite.Send(new PoseMsg(thing.owner.networkId, thing));
this.remoteSite.Send(new BinaryMsg(thing.owner.networkId, thing)); // this.remoteSite.Send(new BinaryMsg(thing.owner.networkId, thing));
} // }
} }
if (thing.terminate) if (thing.terminate)
this.Remove(thing); this.Remove(thing);
@ -209,29 +233,42 @@ namespace RoboidControl {
if (this.isIsolated) if (this.isIsolated)
continue; continue;
if (currentTimeMS > this.nextSendUpdate) { // if (currentTimeMS > this.nextSendUpdate) {
for (int thingIx = 0; thingIx < participant.things.Count; thingIx++) { // for (int thingIx = 0; thingIx < participant.things.Count; thingIx++) {
Thing thing = participant.things[thingIx]; // Thing thing = participant.things[thingIx];
if (thing == null) // if (thing == null)
continue; // continue;
// PoseMsg poseMsg = new(thing.owner.networkId, thing); // // PoseMsg poseMsg = new(thing.owner.networkId, thing);
// this.Send(participant, poseMsg); // // this.Send(participant, poseMsg);
// BinaryMsg binaryMsg = new(thing.owner.networkId, thing); // // BinaryMsg binaryMsg = new(thing.owner.networkId, thing);
// this.Send(participant, binaryMsg); // // this.Send(participant, binaryMsg);
// participant.Send(new PoseMsg(thing.owner.networkId, thing)); // // participant.Send(new PoseMsg(thing.owner.networkId, thing));
// participant.Send(new BinaryMsg(thing.owner.networkId, thing)); // // participant.Send(new BinaryMsg(thing.owner.networkId, thing));
// }
// this.nextSendUpdate = currentTimeMS + this.sendUpdateIntervalMS;
// }
} }
this.nextSendUpdate = currentTimeMS + this.sendUpdateIntervalMS;
}
}
} }
#endregion Update #endregion Update
#region Send #region Send
public override bool Send(IMessage msg) {
int bufferSize = msg.Serialize(ref this.buffer);
if (bufferSize <= 0)
return true;
IPEndPoint participantEndpoint = new IPEndPoint(IPAddress.Parse(this.ipAddress), this.port);
// Console.WriteLine($"msg to remote participant {participantEndpoint.Address.ToString()} {participantEndpoint.Port}");
if (udpClient != null) {
//Console.WriteLine("sending...");
this.udpClient?.Send(this.buffer, bufferSize, participantEndpoint);
}
return true;
}
public void PublishThingInfo(Thing thing) { public void PublishThingInfo(Thing thing) {
// Console.WriteLine("Publish thing info"); // Console.WriteLine("Publish thing info");
this.Publish(new ThingMsg(this.networkId, thing)); this.Publish(new ThingMsg(this.networkId, thing));
@ -281,10 +318,19 @@ namespace RoboidControl {
// It is hard to determine our source port // It is hard to determine our source port
string ipAddress = endPoint.Address.ToString(); string ipAddress = endPoint.Address.ToString();
if (ipAddress != this.ipAddress) { if (ipAddress != this.ipAddress) {
Participant remoteParticipant = GetParticipant(ipAddress, endPoint.Port); Participant sender = GetParticipant(ipAddress, endPoint.Port);
remoteParticipant ??= AddParticipant(ipAddress, endPoint.Port, this); if (sender == null) {
sender = AddParticipant(ipAddress, endPoint.Port, this);
sender.isRemote = true;
}
ReceiveData(data, remoteParticipant); UpdateEvent e = new() {
messageId = NetworkIdMsg.Id,
participant = sender
};
this.updateQueue.Enqueue(e);
ReceiveData(data, sender);
} }
} }
@ -383,12 +429,6 @@ namespace RoboidControl {
// HACK to get the networkId for sites corrected to 0. // HACK to get the networkId for sites corrected to 0.
// This is needed because AddParticipant assigns a networkId for non-sites // This is needed because AddParticipant assigns a networkId for non-sites
sender.networkId = 0; sender.networkId = 0;
UpdateEvent e = new() {
messageId = NetworkIdMsg.Id,
participant = sender
};
this.updateQueue.Enqueue(e);
} }
} }
@ -414,6 +454,7 @@ namespace RoboidControl {
// Console.Write($"Dropped {thing.id}"); // Console.Write($"Dropped {thing.id}");
thing.parent = null; thing.parent = null;
} }
ForwardMessage(sender, msg);
} }
protected virtual Thing ProcessNewThing(Participant sender, ThingMsg msg) { protected virtual Thing ProcessNewThing(Participant sender, ThingMsg msg) {
@ -448,7 +489,7 @@ namespace RoboidControl {
} }
protected virtual void Process(Participant sender, PoseMsg msg) { protected virtual void Process(Participant sender, PoseMsg msg) {
#if DEBUG #if DEBUG2
Console.WriteLine($"{this.name}: Process PoseMsg [{msg.networkId}/{msg.thingId}] {msg.poseType}"); Console.WriteLine($"{this.name}: Process PoseMsg [{msg.networkId}/{msg.thingId}] {msg.poseType}");
#endif #endif
Participant owner = Participant.GetParticipant(msg.networkId); Participant owner = Participant.GetParticipant(msg.networkId);
@ -496,17 +537,51 @@ namespace RoboidControl {
#endif #endif
} }
private void ForwardMessage(IMessage msg) { private void ForwardMessage(Participant sender, IMessage msg) {
// foreach (Participant client in senders) { foreach (Participant participant in Participant.participants) {
// if (client == this) if (participant == this || participant == sender)
// continue; continue;
// //UnityEngine.Debug.Log($"---> {client.ipAddress}");
// //IMessage.SendMsg(client, msg); Console.WriteLine($"---> {participant.networkId}");
// msg.Serialize(ref client.buffer); participant.Send(msg);
// client.SendBuffer(client.buffer.Length); }
// }
} }
#endregion #endregion
#region Participant Registry
/// <summary>
/// Retrieve a participant using ip address and port number
/// </summary>
/// <param name="ipAddress">The ip address of the participant</param>
/// <param name="port">The port number used to send messages to the participant</param>
/// <returns>The participant or null if it is not found.</returns>
public static ParticipantUDP GetParticipant(string ipAddress, int port) {
//Console.WriteLine($"Get Participant {ipAddress}:{port}");
foreach (Participant participant in Participant.participants) {
ParticipantUDP participantUDP = participant as ParticipantUDP;
if (participantUDP.ipAddress == ipAddress && participantUDP.port == port)
return participantUDP;
}
return null;
}
/// <summary>
/// Add a new participant to the collection of participants
/// </summary>
/// <param name="ipAddress">The IP address of the participant</param>
/// <param name="port">The port used to send messages to this participant</param>
/// <returns>The added participant</returns>
public static ParticipantUDP AddParticipant(string ipAddress, int port, ParticipantUDP localParticipant = null) {
Console.WriteLine($"New Participant {ipAddress}:{port}");
// This code is only valid for site, because those can distribute networkIds.....
ParticipantUDP participant = new(ipAddress, port, localParticipant) {
networkId = (byte)(Participant.participants.Count + 1)
};
Participant.participants.Add(participant);
return participant;
}
#endregion
} }
} }

View File

@ -63,6 +63,13 @@ namespace RoboidControl {
#region Update #region Update
public override void Update() {
ulong currentTimeMS = Thing.GetTimeMs();
UpdateMyThings(currentTimeMS);
UpdateOtherThings(currentTimeMS);
}
protected override void UpdateMyThings(ulong currentTimeMS) { protected override void UpdateMyThings(ulong currentTimeMS) {
// We don't use foreach to prevent the 'Collection was modified' error // We don't use foreach to prevent the 'Collection was modified' error
int n = this.things.Count; int n = this.things.Count;

View File

@ -84,6 +84,7 @@ namespace RoboidControl {
this.owner = owner; this.owner = owner;
this.parent = null; this.parent = null;
this.owner.Add(this); this.owner.Add(this);
this.id = 0; // Root always has id 0
} }
/// <summary> /// <summary>
@ -166,7 +167,7 @@ namespace RoboidControl {
public string modelUrl { public string modelUrl {
get => _modelUrl; get => _modelUrl;
set { set {
if (_modelUrl != value) { if (value != _modelUrl) {
_modelUrl = value; _modelUrl = value;
this.updateQueue.Enqueue(new CoreEvent(ModelUrlMsg.Id)); this.updateQueue.Enqueue(new CoreEvent(ModelUrlMsg.Id));
} }