WerWolfInteraktion/OSCClient.cs

278 lines
8.8 KiB
C#

using CoreOSC;
using CoreOSC.IO;
using CoreOSC.Types;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
namespace Wolf
{
internal class OSCClient
{
UdpClient udpClientSend;
UdpClient udpClientReceive;
public OSCClient(string hostname, int port)
{
// 1. Lokalen Port binden (für Empfang)
udpClientSend = new UdpClient(hostname, port);
udpClientReceive = new UdpClient(new IPEndPoint(IPAddress.Any, port));
}
public async Task SendMessage(string endpoint)
{
var message = new OscMessage(new Address(endpoint));
await udpClientSend.SendMessageAsync(message);
}
public async Task SpeakId(int textId)
{
var message = new OscMessage(
address: new Address("/speak"),
arguments: new object[]
{
textId
});
await udpClientSend.SendMessageAsync(message);
}
public async Task Read(string text, bool readStory = true)
{
string endpoint = readStory ? "/read_story" : "/read";
var message = new OscMessage(
address: new Address(endpoint),
arguments: new object[]
{
text, 2
});
await udpClientSend.SendMessageAsync(message);
}
public async Task SendMessageWithArguments(string endpoint, params object[] param)
{
var message = new OscMessage(
address: new Address(endpoint),
arguments: param
);
await udpClientSend.SendMessageAsync(message);
}
public async Task ReceiveMessageWithoutArguments()
{
var response = await udpClientReceive.ReceiveMessageAsync();
Console.WriteLine(response.Address.Value);
// Do something with the arguments, (depending on the address)
foreach (var argument in response.Arguments)
{
Console.WriteLine(argument.GetType());
}
}
public async Task ReceiveMessageWithArguments()
{
var response = await udpClientReceive.ReceiveMessageAsync();
if (response.Address.Value == "/example4")
{
Console.WriteLine("/example4");
var stringArgument = (string)response.Arguments.ElementAt(0);
var intArgument = (int)response.Arguments.ElementAt(1);
var falseArgument = (OscFalse)response.Arguments.ElementAt(2);
Console.WriteLine($"First string argument: {stringArgument}");
Console.WriteLine($"Second int argument: {intArgument}");
Console.WriteLine($"Third OscFalse argument:{falseArgument}");
}
}
public async Task<List<int>> GetAllIds()
{
SendMessage("/getAllIds");
var response = await udpClientReceive.ReceiveMessageAsync();
if (response.Address.Value == "/getAllIds")
{
List<int> playerIds = new List<int>();
foreach (var argument in response.Arguments)
{
playerIds.Add((int)argument);
}
return playerIds;
}
return new List<int>();
}
// < 0 = no confirmation; 0 = confirm; > 0 = player id
//public async Task<int> GetPlayerId(List<Player> targets, List<Player> pois)
//{
// //SendMessageWithArguments("/getPlayerID", targets.Select(p => p.id).ToArray(), pois.Select(p => p.id).ToArray());
// var message = new OscMessage(
// address: new Address("/getPlayerID"),
// //arguments: new object[] { targets.Select(p => p.id).ToArray(), pois.Select(p => p.id).ToArray() }
// arguments: Concat(targets.Select(p => p.id).Cast<object>().ToArray().Concat(pois.Select(p => p.id).Cast<object>()).ToArray()
// );
// await udpClientSend.SendMessageAsync(message);
// var response = await udpClientReceive.ReceiveMessageAsync();
// if (response.Address.Value == "/getPlayerID")
// {
// return (int)response.Arguments.ElementAt(0);
// }
// return -1;
//}
public async Task<int> GetPlayerId(List<Player> targets, List<Player> pois)
{
//return (int) targets.FirstOrDefault().id;
// Arrays extrahieren
var arr2 = targets.Select(p => p.id).ToArray();
var arr1 = pois.Select(p => p.id).ToArray();
// OSC-kompatibles int-Argument-Array bauen:
// Länge1 | Werte1 | Länge2 | Werte2
var args = new List<object>();
args.Add(arr1.Length);
foreach (var id in arr1)
args.Add(id);
args.Add(arr2.Length);
foreach (var id in arr2)
args.Add(id);
// Nachricht senden
var message = new OscMessage(
new Address("/getPlayerID"),
args.ToArray()
);
int maxRetries = 50;
int timeoutSeconds = 20;
// Anfrage senden
await udpClientSend.SendMessageAsync(message);
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
// Timeout für Receive
var receiveTask = udpClientReceive.ReceiveMessageAsync();
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));
var completed = await Task.WhenAny(receiveTask, timeoutTask);
if (completed == receiveTask)
{
var response = await receiveTask;
// Prüfen, ob es die erwartete Antwort ist
if (response.Address.Value == "/getPlayerID")
{
return (int)response.Arguments.ElementAt(0);
}
// Falsche Antwort → ignorieren und weiter versuchen
continue;
}
await udpClientSend.SendMessageAsync(message);
}
return -1;
}
public async Task<bool> GetConfirmation(List<Player> players)
{
int maxRetries = 50;
int timeoutSeconds = 20;
var args = new List<object>();
foreach (var p in players)
{
args.Add(p.id);
}
// Anfrage senden
var message = new OscMessage(
new Address("/confirmation"),
args.ToArray()
);
await udpClientSend.SendMessageAsync(message);
//await udpClientReceive.ReceiveMessageAsync();
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
// Timeout für Receive
var receiveTask = udpClientReceive.ReceiveMessageAsync();
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));
var completed = await Task.WhenAny(receiveTask, timeoutTask);
if (completed == receiveTask)
{
var response = await receiveTask;
// Prüfen, ob es die erwartete Antwort ist
if (response.Address.Value == "/confirmation")
{
if (response.Arguments.ElementAt(0) is OscFalse)
{
return false;
}
if (response.Arguments.ElementAt(0) is OscTrue)
{
return true;
}
}
// Falsche Antwort → ignorieren und weiter versuchen
continue;
}
await udpClientSend.SendMessageAsync(message);
}
return false;
}
public async Task<bool> GetConfirmationEveryoneAsleep()
{
return true;
SendMessage("/everyoneAsleep");
var response = await udpClientReceive.ReceiveMessageAsync();
if (response.Address.Value == "/everyoneAsleep")
{
if (response.Arguments.ElementAt(0) is OscFalse)
{
return false;
}
if (response.Arguments.ElementAt(0) is OscTrue)
{
return true;
}
}
return false;
}
}
}