2024-07-24 20:30:12 +00:00
|
|
|
using System.Net.WebSockets;
|
|
|
|
using System.Text;
|
2024-07-24 21:48:24 +00:00
|
|
|
using Newtonsoft.Json;
|
|
|
|
using Newtonsoft.Json.Linq;
|
2024-07-24 20:30:12 +00:00
|
|
|
|
|
|
|
namespace PartyDamage;
|
|
|
|
|
|
|
|
public class Client : IDisposable {
|
2024-07-24 22:04:52 +00:00
|
|
|
private ClientWebSocket? WebSocket { get; set; }
|
2024-07-24 20:30:12 +00:00
|
|
|
private CancellationTokenSource TokenSource { get; }
|
|
|
|
private Task? MainTask { get; set; }
|
|
|
|
private bool _disposed;
|
|
|
|
|
2024-07-24 21:48:24 +00:00
|
|
|
internal CombatData? Data { get; private set; }
|
|
|
|
|
2024-07-24 20:30:12 +00:00
|
|
|
internal Client() {
|
|
|
|
this.TokenSource = new CancellationTokenSource();
|
|
|
|
this.MainTask = Task.Run(async () => {
|
|
|
|
while (!this._disposed) {
|
|
|
|
try {
|
|
|
|
await this.Main();
|
2024-07-24 21:48:24 +00:00
|
|
|
} catch (TaskCanceledException) {
|
|
|
|
break;
|
2024-07-24 20:30:12 +00:00
|
|
|
} catch (Exception ex) {
|
|
|
|
Plugin.Log.Error(ex, "Error in WebSocket loop");
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(3));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose() {
|
|
|
|
if (this._disposed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._disposed = true;
|
|
|
|
this.TokenSource.Cancel();
|
2024-07-24 22:04:52 +00:00
|
|
|
this.WebSocket?.Dispose();
|
2024-07-24 20:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private async Task Main() {
|
2024-07-24 22:04:52 +00:00
|
|
|
this.WebSocket = new ClientWebSocket();
|
2024-07-24 21:48:24 +00:00
|
|
|
await this.WebSocket.ConnectAsync(new Uri("ws://127.0.0.1:10501/ws"), this.TokenSource.Token);
|
|
|
|
const string msg = "{\"call\": \"subscribe\", \"events\": [\"CombatData\"]}";
|
2024-07-24 20:30:12 +00:00
|
|
|
var msgBytes = Encoding.UTF8.GetBytes(msg);
|
|
|
|
await this.WebSocket.SendAsync(msgBytes, WebSocketMessageType.Text, true, this.TokenSource.Token);
|
|
|
|
|
2024-07-24 21:48:24 +00:00
|
|
|
var buf = new byte[1024];
|
|
|
|
var bytes = new List<byte>();
|
2024-07-24 20:30:12 +00:00
|
|
|
while (this.WebSocket.State == WebSocketState.Open) {
|
2024-07-24 21:48:24 +00:00
|
|
|
var resp = await this.WebSocket.ReceiveAsync(buf, this.TokenSource.Token);
|
|
|
|
bytes.AddRange(buf[..resp.Count]);
|
|
|
|
if (!resp.EndOfMessage) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
var text = Encoding.UTF8.GetString(bytes.ToArray());
|
|
|
|
bytes.Clear();
|
|
|
|
|
|
|
|
var jobj = JObject.Parse(text);
|
|
|
|
if (jobj["type"]?.Value<string>() == "CombatData") {
|
2024-07-24 22:04:52 +00:00
|
|
|
var data = JsonConvert.DeserializeObject<RawCombatData>(text);
|
|
|
|
if (data == null) {
|
|
|
|
this.Data = null;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.Data = new CombatData(data);
|
2024-07-24 20:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Plugin.Log.Info("websocket loop shut down");
|
|
|
|
}
|
|
|
|
}
|