refactored VRExperimentController to utilize SharedUDPListener for packet handling

This commit is contained in:
tom.hempel
2025-10-25 15:58:28 +02:00
parent f3b4a4ddb0
commit 868180e3ec
4 changed files with 25 additions and 102 deletions

View File

@ -93,6 +93,7 @@ namespace Convai.Scripts.Runtime.Multiplayer
ConvaiLogger.Info($" - Voice Audio: 0xC0A1", ConvaiLogger.LogCategory.Character); ConvaiLogger.Info($" - Voice Audio: 0xC0A1", ConvaiLogger.LogCategory.Character);
ConvaiLogger.Info($" - NPC Speech: 0xC0A3", ConvaiLogger.LogCategory.Character); ConvaiLogger.Info($" - NPC Speech: 0xC0A3", ConvaiLogger.LogCategory.Character);
ConvaiLogger.Info($" - Avatar Sync: 0xC0A0", ConvaiLogger.LogCategory.Character); ConvaiLogger.Info($" - Avatar Sync: 0xC0A0", ConvaiLogger.LogCategory.Character);
ConvaiLogger.Info($" - Experiment Control: JSON (text-based)", ConvaiLogger.LogCategory.Character);
// Start listening for all packets // Start listening for all packets
_ = ListenForPackets(_cancellationTokenSource.Token); _ = ListenForPackets(_cancellationTokenSource.Token);

View File

@ -2,9 +2,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading;
using UnityEngine; using UnityEngine;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -34,8 +32,6 @@ public class VRExperimentController : MonoBehaviour
[SerializeField] private bool enableDebugLogging = true; [SerializeField] private bool enableDebugLogging = true;
// Network components // Network components
private UdpClient udpClient;
private Thread udpListenerThread;
private bool isListening = false; private bool isListening = false;
private int udpPort; private int udpPort;
@ -197,70 +193,40 @@ public class VRExperimentController : MonoBehaviour
{ {
try try
{ {
if (allowPortSharing) // Wait for shared listener to be ready
if (Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance == null)
{ {
// Create UDP client with port reuse for local testing LogError("SharedUDPListener not found! Make sure it's in the scene.");
udpClient = new UdpClient(); return;
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, udpPort));
}
else
{
// Standard UDP client binding
udpClient = new UdpClient(udpPort);
} }
udpListenerThread = new Thread(new ThreadStart(UDPListenerLoop)); // Subscribe to shared listener
udpListenerThread.IsBackground = true; Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance.OnPacketReceived += HandlePacketReceived;
isListening = true; isListening = true;
udpListenerThread.Start();
LogMessage($"UDP Experiment Control Listener started on port {udpPort} (filtering JSON messages only, Port sharing: {allowPortSharing})"); LogMessage($"UDP Experiment Control Listener subscribed to shared listener on port {udpPort} (filtering JSON messages only)");
} }
catch (Exception e) catch (Exception e)
{ {
if (allowPortSharing) LogError($"Failed to subscribe to shared UDP listener: {e.Message}");
{
LogError($"Failed to start UDP listener with port sharing: {e.Message}");
LogMessage("Trying with different port...");
TryAlternativePort();
}
else
{
LogError($"Failed to start UDP listener: {e.Message}");
}
} }
} }
/// <summary> /// <summary>
/// Try alternative ports for local testing /// Handle packet received from shared listener
/// </summary> /// </summary>
private void TryAlternativePort() private void HandlePacketReceived(byte[] data, IPEndPoint senderEndPoint)
{ {
// Try a few alternative ports for local testing // Check if this is an experiment control message (JSON)
int[] alternativePorts = { 1222, 1223, 1224, 1225, 1226 }; if (!IsExperimentControlMessage(data)) return;
foreach (int port in alternativePorts) string message = Encoding.UTF8.GetString(data);
// Add message to queue for main thread processing
lock (queueLock)
{ {
try messageQueue.Enqueue(message);
{
udpClient = new UdpClient(port);
udpListenerThread = new Thread(new ThreadStart(UDPListenerLoop));
udpListenerThread.IsBackground = true;
isListening = true;
udpListenerThread.Start();
LogMessage($"UDP Experiment Control Listener started on alternative port {port}");
return;
}
catch (Exception)
{
// Try next port
continue;
}
} }
LogError("Failed to start UDP listener on any available port");
} }
/// <summary> /// <summary>
@ -270,59 +236,15 @@ public class VRExperimentController : MonoBehaviour
{ {
isListening = false; isListening = false;
if (udpClient != null) // Unsubscribe from shared listener
if (Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance != null)
{ {
udpClient.Close(); Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance.OnPacketReceived -= HandlePacketReceived;
udpClient = null;
}
if (udpListenerThread != null && udpListenerThread.IsAlive)
{
udpListenerThread.Join(1000); // Wait up to 1 second
if (udpListenerThread.IsAlive)
{
udpListenerThread.Abort();
}
udpListenerThread = null;
} }
LogMessage("UDP Listener stopped"); LogMessage("UDP Listener stopped");
} }
/// <summary>
/// UDP listener loop (runs in separate thread)
/// </summary>
private void UDPListenerLoop()
{
while (isListening)
{
try
{
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, udpPort);
byte[] data = udpClient.Receive(ref remoteEndPoint);
// Check if this looks like a JSON experiment control message
if (IsExperimentControlMessage(data))
{
string message = Encoding.UTF8.GetString(data);
// Add message to queue for main thread processing
lock (queueLock)
{
messageQueue.Enqueue(message);
}
}
// If it's not an experiment control message (likely avatar data), ignore it
}
catch (Exception e)
{
if (isListening) // Only log if we're still supposed to be listening
{
LogError($"UDP Listener error: {e.Message}");
}
}
}
}
/// <summary> /// <summary>
/// Check if the received data is an experiment control message (JSON) vs avatar data (binary) /// Check if the received data is an experiment control message (JSON) vs avatar data (binary)
@ -684,9 +606,9 @@ public class VRExperimentController : MonoBehaviour
/// </summary> /// </summary>
private int GetActualListenPort() private int GetActualListenPort()
{ {
if (udpClient?.Client?.LocalEndPoint != null) if (Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance != null)
{ {
return ((IPEndPoint)udpClient.Client.LocalEndPoint).Port; return Convai.Scripts.Runtime.Multiplayer.SharedUDPListener.Instance.ListenPort;
} }
return udpPort; return udpPort;
} }

Binary file not shown.

Binary file not shown.