feat: add some data handling
This commit is contained in:
parent
d4bfbcbdf9
commit
60d766ced4
34
Client.cs
34
Client.cs
@ -1,5 +1,7 @@
|
|||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace PartyDamage;
|
namespace PartyDamage;
|
||||||
|
|
||||||
@ -9,6 +11,8 @@ public class Client : IDisposable {
|
|||||||
private Task? MainTask { get; set; }
|
private Task? MainTask { get; set; }
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
|
internal CombatData? Data { get; private set; }
|
||||||
|
|
||||||
internal Client() {
|
internal Client() {
|
||||||
this.WebSocket = new ClientWebSocket();
|
this.WebSocket = new ClientWebSocket();
|
||||||
this.TokenSource = new CancellationTokenSource();
|
this.TokenSource = new CancellationTokenSource();
|
||||||
@ -16,6 +20,8 @@ public class Client : IDisposable {
|
|||||||
while (!this._disposed) {
|
while (!this._disposed) {
|
||||||
try {
|
try {
|
||||||
await this.Main();
|
await this.Main();
|
||||||
|
} catch (TaskCanceledException) {
|
||||||
|
break;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Plugin.Log.Error(ex, "Error in WebSocket loop");
|
Plugin.Log.Error(ex, "Error in WebSocket loop");
|
||||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
await Task.Delay(TimeSpan.FromSeconds(3));
|
||||||
@ -32,24 +38,30 @@ public class Client : IDisposable {
|
|||||||
this._disposed = true;
|
this._disposed = true;
|
||||||
this.TokenSource.Cancel();
|
this.TokenSource.Cancel();
|
||||||
this.WebSocket.Dispose();
|
this.WebSocket.Dispose();
|
||||||
this.MainTask?.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Main() {
|
private async Task Main() {
|
||||||
await this.WebSocket.ConnectAsync(new Uri("http://127.0.0.1:10501/"), this.TokenSource.Token);
|
await this.WebSocket.ConnectAsync(new Uri("ws://127.0.0.1:10501/ws"), this.TokenSource.Token);
|
||||||
var msg = "{\"call\": \"subscribe\", \"events\": [\"CombatData\"]}";
|
const string msg = "{\"call\": \"subscribe\", \"events\": [\"CombatData\"]}";
|
||||||
var msgBytes = Encoding.UTF8.GetBytes(msg);
|
var msgBytes = Encoding.UTF8.GetBytes(msg);
|
||||||
await this.WebSocket.SendAsync(msgBytes, WebSocketMessageType.Text, true, this.TokenSource.Token);
|
await this.WebSocket.SendAsync(msgBytes, WebSocketMessageType.Text, true, this.TokenSource.Token);
|
||||||
|
|
||||||
var received = new List<byte>();
|
var buf = new byte[1024];
|
||||||
|
var bytes = new List<byte>();
|
||||||
while (this.WebSocket.State == WebSocketState.Open) {
|
while (this.WebSocket.State == WebSocketState.Open) {
|
||||||
var bytes = new byte[1024];
|
var resp = await this.WebSocket.ReceiveAsync(buf, this.TokenSource.Token);
|
||||||
var resp = await this.WebSocket.ReceiveAsync(bytes, this.TokenSource.Token);
|
bytes.AddRange(buf[..resp.Count]);
|
||||||
received.AddRange(bytes[..resp.Count]);
|
if (!resp.EndOfMessage) {
|
||||||
if (resp.EndOfMessage) {
|
continue;
|
||||||
var text = Encoding.UTF8.GetString(bytes.AsSpan());
|
}
|
||||||
received.Clear();
|
|
||||||
Plugin.Log.Info(text);
|
var text = Encoding.UTF8.GetString(bytes.ToArray());
|
||||||
|
bytes.Clear();
|
||||||
|
|
||||||
|
var jobj = JObject.Parse(text);
|
||||||
|
if (jobj["type"]?.Value<string>() == "CombatData") {
|
||||||
|
var data = JsonConvert.DeserializeObject<CombatData>(text);
|
||||||
|
this.Data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,10 @@ public class Combatant {
|
|||||||
[JsonProperty("encdps")]
|
[JsonProperty("encdps")]
|
||||||
public string EncDps;
|
public string EncDps;
|
||||||
|
|
||||||
|
// seems like newtonsoft gets confused if we don't also specify this one
|
||||||
|
[JsonProperty("ENCDPS")]
|
||||||
|
public string EncDps2;
|
||||||
|
|
||||||
public string Hits;
|
public string Hits;
|
||||||
|
|
||||||
[JsonProperty("crithits")]
|
[JsonProperty("crithits")]
|
||||||
|
6
PartyDamage.yaml
Executable file
6
PartyDamage.yaml
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
name: Party Damage
|
||||||
|
author: anna
|
||||||
|
punchline: Show your DPS in the party list
|
||||||
|
description: |-
|
||||||
|
Does what it says on the tin.
|
||||||
|
repo_url: https://git.anna.lgbt/anna/PartyDamage
|
56
Plugin.cs
56
Plugin.cs
@ -1,6 +1,9 @@
|
|||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game.Group;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
|
|
||||||
namespace PartyDamage;
|
namespace PartyDamage;
|
||||||
|
|
||||||
@ -8,13 +11,66 @@ public class Plugin : IDalamudPlugin {
|
|||||||
[PluginService]
|
[PluginService]
|
||||||
internal static IPluginLog Log { get; private set; }
|
internal static IPluginLog Log { get; private set; }
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
private IClientState ClientState { get; init; }
|
||||||
|
|
||||||
|
[PluginService]
|
||||||
|
private IFramework Framework { get; init; }
|
||||||
|
|
||||||
private Client Client { get; }
|
private Client Client { get; }
|
||||||
|
|
||||||
public Plugin() {
|
public Plugin() {
|
||||||
this.Client = new Client();
|
this.Client = new Client();
|
||||||
|
this.Framework!.Update += this.OnFramework;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
|
this.Framework!.Update -= this.OnFramework;
|
||||||
this.Client.Dispose();
|
this.Client.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe void OnFramework(IFramework framework) {
|
||||||
|
if (this.Client.Data is not { } data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.ClientState.LocalPlayer is not { } player) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = (AddonPartyList*) AtkStage.Instance()->RaptureAtkUnitManager->GetAddonByName("_PartyList");
|
||||||
|
|
||||||
|
var names = new List<string>();
|
||||||
|
var group = GroupManager.Instance()->GetGroup();
|
||||||
|
if (group == null) {
|
||||||
|
Plugin.Log.Info("group null");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < group->MemberCount; i++) {
|
||||||
|
names.Add(group->PartyMembers[i].NameString);
|
||||||
|
}
|
||||||
|
|
||||||
|
var numPlayers = list->PartyMembers.Length;
|
||||||
|
foreach (var combatant in data.Combatants.Values) {
|
||||||
|
var idx = combatant.Name == "YOU"
|
||||||
|
? 0
|
||||||
|
: names.IndexOf(combatant.Name);
|
||||||
|
if (idx == -1 || idx >= numPlayers) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!float.TryParse(combatant.EncDps, out var dps)) {
|
||||||
|
dps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dpsText = dps switch {
|
||||||
|
float.PositiveInfinity => "0",
|
||||||
|
float.NegativeInfinity => "0",
|
||||||
|
< 1_000 => dps.ToString("N1"),
|
||||||
|
< 1_000_000 => $"{dps / 1_000:N1}K",
|
||||||
|
_ => $"{dps / 1_000_000:N1}M",
|
||||||
|
};
|
||||||
|
list->PartyMembers[idx].Name->SetText(dpsText);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user