Retainer Stats

This commit is contained in:
Liza 2023-08-24 00:23:30 +02:00
parent 87d6dbad28
commit 76822cd50a
Signed by: liza
GPG Key ID: 7199F8D727D55F67
5 changed files with 67 additions and 6 deletions

View File

@ -6,21 +6,26 @@ internal sealed class Character
{ {
private readonly object _delegate; private readonly object _delegate;
private readonly FieldInfo _name; private readonly FieldInfo _name;
private readonly FieldInfo _level;
public Character(object @delegate) public Character(object @delegate)
{ {
_delegate = @delegate; _delegate = @delegate;
_name = _delegate.GetType().GetField("Name")!; _name = _delegate.GetType().GetField("Name")!;
_level = _delegate.GetType().GetField("Level")!;
CharacterId = (ulong)_delegate.GetType().GetField("CharacterId")!.GetValue(_delegate)!; CharacterId = (ulong)_delegate.GetType().GetField("CharacterId")!.GetValue(_delegate)!;
CharacterType = (CharacterType)_delegate.GetType().GetProperty("CharacterType")!.GetValue(_delegate)!; CharacterType = (CharacterType)_delegate.GetType().GetProperty("CharacterType")!.GetValue(_delegate)!;
ClassJob = (byte)_delegate.GetType().GetField("ClassJob")!.GetValue(_delegate)!;
OwnerId = (ulong)_delegate.GetType().GetField("OwnerId")!.GetValue(_delegate)!; OwnerId = (ulong)_delegate.GetType().GetField("OwnerId")!.GetValue(_delegate)!;
FreeCompanyId = (ulong)_delegate.GetType().GetField("FreeCompanyId")!.GetValue(_delegate)!; FreeCompanyId = (ulong)_delegate.GetType().GetField("FreeCompanyId")!.GetValue(_delegate)!;
} }
public ulong CharacterId { get; } public ulong CharacterId { get; }
public CharacterType CharacterType { get; } public CharacterType CharacterType { get; }
public byte ClassJob { get; }
public ulong OwnerId { get; } public ulong OwnerId { get; }
public ulong FreeCompanyId { get; } public ulong FreeCompanyId { get; }
public string Name => (string)_name.GetValue(_delegate)!; public string Name => (string)_name.GetValue(_delegate)!;
public uint Level => (uint)_level.GetValue(_delegate)!;
} }

View File

@ -3,12 +3,15 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Data;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using FFXIVClientStructs.FFXIV.Client.UI.Agent; using Dalamud.Logging;
using Influx.AllaganTools; using Influx.AllaganTools;
using InfluxDB.Client; using InfluxDB.Client;
using InfluxDB.Client.Api.Domain; using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes; using InfluxDB.Client.Writes;
using Lumina.Excel.GeneratedSheets;
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
namespace Influx.Influx; namespace Influx.Influx;
@ -21,13 +24,19 @@ internal class InfluxStatisticsClient : IDisposable
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly Mutex _mutex; private readonly Mutex _mutex;
private readonly bool _mutexCreated; private readonly bool _mutexCreated;
private readonly IReadOnlyDictionary<byte, byte> _classJobToArrayIndex;
private readonly IReadOnlyDictionary<byte, string> _classJobNames;
public InfluxStatisticsClient(ChatGui chatGui, Configuration configuration) public InfluxStatisticsClient(ChatGui chatGui, Configuration configuration, DataManager dataManager)
{ {
_influxClient = new InfluxDBClient(configuration.Server.Server, configuration.Server.Token); _influxClient = new InfluxDBClient(configuration.Server.Server, configuration.Server.Token);
_chatGui = chatGui; _chatGui = chatGui;
_configuration = configuration; _configuration = configuration;
_mutex = new Mutex(true, MutexName, out _mutexCreated); _mutex = new Mutex(true, MutexName, out _mutexCreated);
_classJobToArrayIndex = dataManager.GetExcelSheet<ClassJob>()!.Where(x => x.RowId > 0)
.ToDictionary(x => (byte)x.RowId, x => (byte)x.ExpArrayIndex);
_classJobNames = dataManager.GetExcelSheet<ClassJob>()!.Where(x => x.RowId > 0)
.ToDictionary(x => (byte)x.RowId, x => x.Abbreviation.ToString());
} }
public bool Enabled => _configuration.Server.Enabled; public bool Enabled => _configuration.Server.Enabled;
@ -109,6 +118,30 @@ internal class InfluxStatisticsClient : IDisposable
.Field("ceruleum_tanks", currencies.CeruleumTanks) .Field("ceruleum_tanks", currencies.CeruleumTanks)
.Field("repair_kits", currencies.RepairKits) .Field("repair_kits", currencies.RepairKits)
.Timestamp(date, WritePrecision.S)); .Timestamp(date, WritePrecision.S));
if (update.LocalStats.TryGetValue(owner, out var ownerStats) && character.ClassJob != 0)
{
values.Add(PointData.Measurement("retainer")
.Tag("id", character.CharacterId.ToString())
.Tag("player_name", owner.Name)
.Tag("type", character.CharacterType.ToString())
.Tag("retainer_name", character.Name)
.Tag("class", _classJobNames[character.ClassJob])
.Field("level", character.Level)
.Field("is_max_level", character.Level == ownerStats.MaxLevel ? 1 : 0)
.Field("can_reach_max_level",
ownerStats.ClassJobLevels.Count > 0 &&
ownerStats.ClassJobLevels[_classJobToArrayIndex[character.ClassJob]] ==
ownerStats.MaxLevel
? 1
: 0)
.Field("levels_before_cap",
ownerStats.ClassJobLevels.Count > 0
? ownerStats.ClassJobLevels[_classJobToArrayIndex[character.ClassJob]] -
character.Level
: 0)
.Timestamp(date, WritePrecision.S));
}
} }
else if (character.CharacterType == CharacterType.FreeCompanyChest && else if (character.CharacterType == CharacterType.FreeCompanyChest &&
validFcIds.Contains(character.CharacterId)) validFcIds.Contains(character.CharacterId))

View File

@ -2,6 +2,7 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Dalamud.Data;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
@ -36,7 +37,7 @@ public class InfluxPlugin : IDalamudPlugin
private readonly Timer _timer; private readonly Timer _timer;
public InfluxPlugin(DalamudPluginInterface pluginInterface, ClientState clientState, public InfluxPlugin(DalamudPluginInterface pluginInterface, ClientState clientState,
CommandManager commandManager, ChatGui chatGui) CommandManager commandManager, ChatGui chatGui, DataManager dataManager)
{ {
ECommonsMain.Init(pluginInterface, this, Module.DalamudReflector); ECommonsMain.Init(pluginInterface, this, Module.DalamudReflector);
@ -47,7 +48,7 @@ public class InfluxPlugin : IDalamudPlugin
_allaganToolsIpc = new AllaganToolsIpc(pluginInterface, chatGui, _configuration); _allaganToolsIpc = new AllaganToolsIpc(pluginInterface, chatGui, _configuration);
_submarineTrackerIpc = new SubmarineTrackerIpc(chatGui); _submarineTrackerIpc = new SubmarineTrackerIpc(chatGui);
_localStatsCalculator = new LocalStatsCalculator(pluginInterface, clientState, chatGui); _localStatsCalculator = new LocalStatsCalculator(pluginInterface, clientState, chatGui);
_influxStatisticsClient = new InfluxStatisticsClient(chatGui, _configuration); _influxStatisticsClient = new InfluxStatisticsClient(chatGui, _configuration, dataManager);
_windowSystem = new WindowSystem(typeof(InfluxPlugin).FullName); _windowSystem = new WindowSystem(typeof(InfluxPlugin).FullName);
_statisticsWindow = new StatisticsWindow(); _statisticsWindow = new StatisticsWindow();
@ -85,11 +86,15 @@ public class InfluxPlugin : IDalamudPlugin
{ {
var currencies = _allaganToolsIpc.CountCurrencies(); var currencies = _allaganToolsIpc.CountCurrencies();
var characters = currencies.Keys.ToList(); var characters = currencies.Keys.ToList();
if (characters.Count == 0)
return;
var update = new StatisticsUpdate var update = new StatisticsUpdate
{ {
Currencies = currencies, Currencies = currencies,
Submarines = _submarineTrackerIpc.GetSubmarineStats(characters), Submarines = _submarineTrackerIpc.GetSubmarineStats(characters),
LocalStats = _localStatsCalculator.GetAllCharacterStats() LocalStats = _localStatsCalculator.GetAllCharacterStats()
.Where(x => characters.Any(y => y.CharacterId == x.Key))
.ToDictionary(x => characters.First(y => y.CharacterId == x.Key), x => x.Value), .ToDictionary(x => characters.First(y => y.CharacterId == x.Key), x => x.Value),
}; };
_statisticsWindow.OnStatisticsUpdate(update); _statisticsWindow.OnStatisticsUpdate(update);

View File

@ -1,4 +1,6 @@
namespace Influx.LocalStatistics; using System.Collections.Generic;
namespace Influx.LocalStatistics;
public record LocalStats public record LocalStats
{ {
@ -6,4 +8,6 @@ public record LocalStats
public byte GrandCompany { get; init; } public byte GrandCompany { get; init; }
public byte GcRank { get; init; } public byte GcRank { get; init; }
public bool SquadronUnlocked { get; init; } public bool SquadronUnlocked { get; init; }
public byte MaxLevel { get; init; } = 90;
public List<short> ClassJobLevels { get; set; } = new();
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Dalamud.Data;
using Dalamud.Game.ClientState; using Dalamud.Game.ClientState;
using Dalamud.Game.Gui; using Dalamud.Game.Gui;
using Dalamud.Logging; using Dalamud.Logging;
@ -19,7 +20,10 @@ public class LocalStatsCalculator : IDisposable
private readonly ChatGui _chatGui; private readonly ChatGui _chatGui;
private readonly Dictionary<ulong, LocalStats> _cache = new(); private readonly Dictionary<ulong, LocalStats> _cache = new();
public LocalStatsCalculator(DalamudPluginInterface pluginInterface, ClientState clientState, ChatGui chatGui) public LocalStatsCalculator(
DalamudPluginInterface pluginInterface,
ClientState clientState,
ChatGui chatGui)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_clientState = clientState; _clientState = clientState;
@ -87,6 +91,8 @@ public class LocalStatsCalculator : IDisposable
GrandCompany.ImmortalFlames => QuestManager.IsQuestComplete(67927), GrandCompany.ImmortalFlames => QuestManager.IsQuestComplete(67927),
_ => false _ => false
}, },
MaxLevel = playerState->MaxLevel,
ClassJobLevels = ExtractClassJobLevels(playerState),
}; };
if (_cache.TryGetValue(localContentId, out var existingStats)) if (_cache.TryGetValue(localContentId, out var existingStats))
@ -113,5 +119,13 @@ public class LocalStatsCalculator : IDisposable
} }
} }
private unsafe List<short> ExtractClassJobLevels(PlayerState* playerState)
{
List<short> levels = new();
for (int i = 0; i < 30; ++i)
levels.Add(playerState->ClassJobLevelArray[i]);
return levels;
}
public IReadOnlyDictionary<ulong, LocalStats> GetAllCharacterStats() => _cache.AsReadOnly(); public IReadOnlyDictionary<ulong, LocalStats> GetAllCharacterStats() => _cache.AsReadOnly();
} }