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 FieldInfo _name;
private readonly FieldInfo _level;
public Character(object @delegate)
{
_delegate = @delegate;
_name = _delegate.GetType().GetField("Name")!;
_level = _delegate.GetType().GetField("Level")!;
CharacterId = (ulong)_delegate.GetType().GetField("CharacterId")!.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)!;
FreeCompanyId = (ulong)_delegate.GetType().GetField("FreeCompanyId")!.GetValue(_delegate)!;
}
public ulong CharacterId { get; }
public CharacterType CharacterType { get; }
public byte ClassJob { get; }
public ulong OwnerId { get; }
public ulong FreeCompanyId { get; }
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.Threading;
using System.Threading.Tasks;
using Dalamud.Data;
using Dalamud.Game.Gui;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Dalamud.Logging;
using Influx.AllaganTools;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;
using Lumina.Excel.GeneratedSheets;
using GrandCompany = FFXIVClientStructs.FFXIV.Client.UI.Agent.GrandCompany;
namespace Influx.Influx;
@ -21,13 +24,19 @@ internal class InfluxStatisticsClient : IDisposable
private readonly Configuration _configuration;
private readonly Mutex _mutex;
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);
_chatGui = chatGui;
_configuration = configuration;
_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;
@ -109,6 +118,30 @@ internal class InfluxStatisticsClient : IDisposable
.Field("ceruleum_tanks", currencies.CeruleumTanks)
.Field("repair_kits", currencies.RepairKits)
.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 &&
validFcIds.Contains(character.CharacterId))

View File

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

View File

@ -1,4 +1,6 @@
namespace Influx.LocalStatistics;
using System.Collections.Generic;
namespace Influx.LocalStatistics;
public record LocalStats
{
@ -6,4 +8,6 @@ public record LocalStats
public byte GrandCompany { get; init; }
public byte GcRank { 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.Collections.Generic;
using System.IO;
using Dalamud.Data;
using Dalamud.Game.ClientState;
using Dalamud.Game.Gui;
using Dalamud.Logging;
@ -19,7 +20,10 @@ public class LocalStatsCalculator : IDisposable
private readonly ChatGui _chatGui;
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;
_clientState = clientState;
@ -87,6 +91,8 @@ public class LocalStatsCalculator : IDisposable
GrandCompany.ImmortalFlames => QuestManager.IsQuestComplete(67927),
_ => false
},
MaxLevel = playerState->MaxLevel,
ClassJobLevels = ExtractClassJobLevels(playerState),
};
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();
}