master
Liza 2024-03-21 11:32:39 +01:00
parent 959a66bd24
commit 1174413b9a
Signed by: liza
GPG Key ID: 7199F8D727D55F67
34 changed files with 1201 additions and 110 deletions

@ -1 +1 @@
Subproject commit 2715088db81d2be34447b27b0e5e5a3e766e47c7
Subproject commit 6f0aaa55bce6ec79fd4d72f84f21597b39e5445d

@ -1 +1 @@
Subproject commit f1c688a0599b41d70230021328a575da7351cf91
Subproject commit d238d4188e8b47b11252d75cb5e4b678b8da2756

2
Influx.sln.DotSettings Normal file
View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Allagan/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

1017
Influx/.editorconfig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,13 +15,12 @@ internal sealed class AllaganToolsIpc : IDisposable
private readonly DalamudReflector _dalamudReflector;
private readonly IFramework _framework;
private readonly IPluginLog _pluginLog;
private readonly ICallGateSubscriber<bool, bool>? _initialized;
private readonly ICallGateSubscriber<bool>? _isInitialized;
private readonly ICallGateSubscriber<bool, bool> _initialized;
private readonly ICallGateSubscriber<Dictionary<string, string>> _getSearchFilters;
public ICharacterMonitor Characters { get; private set; } = new UnavailableCharacterMonitor();
public IInventoryMonitor Inventories { get; private set; } = new UnavailableInventoryMonitor();
public IFilterService Filters { get; set; } = new UnavailableFilterService();
private ICharacterMonitor _characters;
private IInventoryMonitor _inventories;
private IFilterService _filters;
public AllaganToolsIpc(DalamudPluginInterface pluginInterface, IChatGui chatGui, DalamudReflector dalamudReflector,
IFramework framework, IPluginLog pluginLog)
@ -32,14 +31,20 @@ internal sealed class AllaganToolsIpc : IDisposable
_pluginLog = pluginLog;
_initialized = pluginInterface.GetIpcSubscriber<bool, bool>("AllaganTools.Initialized");
_isInitialized = pluginInterface.GetIpcSubscriber<bool>("AllaganTools.IsInitialized");
_initialized.Subscribe(ConfigureIpc);
_getSearchFilters =
pluginInterface.GetIpcSubscriber<Dictionary<string, string>>("AllaganTools.GetSearchFilters");
_characters = new UnavailableCharacterMonitor(_pluginLog);
_inventories = new UnavailableInventoryMonitor(_pluginLog);
_filters = new UnavailableFilterService(_pluginLog);
_initialized.Subscribe(ConfigureIpc);
try
{
bool isInitialized = _isInitialized.InvokeFunc();
ICallGateSubscriber<bool> isInitializedFunc =
pluginInterface.GetIpcSubscriber<bool>("AllaganTools.IsInitialized");
bool isInitialized = isInitializedFunc.InvokeFunc();
if (isInitialized)
ConfigureIpc(true);
}
@ -60,10 +65,10 @@ internal sealed class AllaganToolsIpc : IDisposable
{
var pluginService = it.GetType().Assembly.GetType("InventoryTools.PluginService")!;
Characters = new CharacterMonitor(pluginService.GetProperty("CharacterMonitor")!.GetValue(null)!);
Inventories = new InventoryMonitor(
_characters = new CharacterMonitor(pluginService.GetProperty("CharacterMonitor")!.GetValue(null)!);
_inventories = new InventoryMonitor(
pluginService.GetProperty("InventoryMonitor")!.GetValue(null)!);
Filters = new FilterService(pluginService.GetProperty("FilterService")!.GetValue(null)!);
_filters = new FilterService(pluginService.GetProperty("FilterService")!.GetValue(null)!);
}
else
{
@ -95,7 +100,7 @@ internal sealed class AllaganToolsIpc : IDisposable
{
try
{
return Filters.GetFilterByKeyOrName(keyOrName);
return _filters.GetFilterByKeyOrName(keyOrName);
}
catch (IpcError e)
{
@ -106,9 +111,9 @@ internal sealed class AllaganToolsIpc : IDisposable
public Dictionary<Character, Currencies> CountCurrencies()
{
_pluginLog.Debug($"{Characters.GetType()}, {Inventories.GetType()}");
var characters = Characters.All.ToDictionary(x => x.CharacterId, x => x);
return Inventories.All
_pluginLog.Debug($"{_characters.GetType()}, {_inventories.GetType()}");
var characters = _characters.All.ToDictionary(x => x.CharacterId, x => x);
return _inventories.All
.Where(x => characters.ContainsKey(x.Value.CharacterId))
.ToDictionary(
x => characters[x.Value.CharacterId],
@ -130,21 +135,14 @@ internal sealed class AllaganToolsIpc : IDisposable
public void Dispose()
{
_initialized?.Unsubscribe(ConfigureIpc);
Characters = new UnavailableCharacterMonitor();
Inventories = new UnavailableInventoryMonitor();
Filters = new UnavailableFilterService();
_initialized.Unsubscribe(ConfigureIpc);
_characters = new UnavailableCharacterMonitor(_pluginLog);
_inventories = new UnavailableInventoryMonitor(_pluginLog);
_filters = new UnavailableFilterService(_pluginLog);
}
private sealed class InventoryWrapper
private sealed class InventoryWrapper(IEnumerable<InventoryItem> items)
{
private readonly IEnumerable<InventoryItem> _items;
public InventoryWrapper(IEnumerable<InventoryItem> items)
{
_items = items;
}
public long Sum(int itemId) => _items.Where(x => x.ItemId == itemId).Sum(x => x.Quantity);
public long Sum(int itemId) => items.Where(x => x.ItemId == itemId).Sum(x => x.Quantity);
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Reflection;
namespace Influx.AllaganTools;
@ -10,6 +11,7 @@ internal sealed class Character
public Character(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_name = _delegate.GetType().GetField("Name")!;
_level = _delegate.GetType().GetField("Level")!;

View File

@ -14,6 +14,7 @@ internal sealed class CharacterMonitor : ICharacterMonitor
public CharacterMonitor(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_getPlayerCharacters = _delegate.GetType().GetMethod("GetPlayerCharacters")!;
_allCharacters = _delegate.GetType().GetMethod("AllCharacters")!;
@ -22,7 +23,7 @@ internal sealed class CharacterMonitor : ICharacterMonitor
public IEnumerable<Character> PlayerCharacters => GetCharactersInternal(_getPlayerCharacters);
public IEnumerable<Character> All => GetCharactersInternal(_allCharacters);
private IEnumerable<Character> GetCharactersInternal(MethodInfo methodInfo)
private List<Character> GetCharactersInternal(MethodInfo methodInfo)
{
return ((IEnumerable)methodInfo.Invoke(_delegate, Array.Empty<object>())!)
.Cast<object>()

View File

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -13,6 +14,7 @@ internal sealed class Filter
public Filter(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_generateFilteredList = _delegate.GetType().GetMethod("GenerateFilteredList")!;
}

View File

@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
namespace Influx.AllaganTools;
@ -9,13 +10,14 @@ internal sealed class FilterService : IFilterService
public FilterService(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_getFilterByKeyOrName = _delegate.GetType().GetMethod("GetFilterByKeyOrName")!;
}
public Filter? GetFilterByKeyOrName(string keyOrName)
{
var f = _getFilterByKeyOrName.Invoke(_delegate, new object?[] { keyOrName });
var f = _getFilterByKeyOrName.Invoke(_delegate, [keyOrName]);
return f != null ? new Filter(f) : null;
}
}

View File

@ -13,6 +13,7 @@ internal sealed class Inventory
public Inventory(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_getAllInventories = _delegate.GetType().GetMethod("GetAllInventories")!;
CharacterId = (ulong)_delegate.GetType().GetProperty("CharacterId")!.GetValue(_delegate)!;

View File

@ -1,14 +1,14 @@
namespace Influx.AllaganTools;
using System;
namespace Influx.AllaganTools;
internal sealed class InventoryItem
{
private readonly object _delegate;
public InventoryItem(object @delegate)
{
_delegate = @delegate;
ItemId = (uint)_delegate.GetType().GetField("ItemId")!.GetValue(_delegate)!;
Quantity = (uint)_delegate.GetType().GetField("Quantity")!.GetValue(_delegate)!;
ArgumentNullException.ThrowIfNull(@delegate);
ItemId = (uint)@delegate.GetType().GetField("ItemId")!.GetValue(@delegate)!;
Quantity = (uint)@delegate.GetType().GetField("Quantity")!.GetValue(@delegate)!;
}
public uint ItemId { get; }

View File

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -12,6 +13,7 @@ internal sealed class InventoryMonitor : IInventoryMonitor
public InventoryMonitor(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
_delegate = @delegate;
_inventories = _delegate.GetType().GetProperty("Inventories")!;
}

View File

@ -1,10 +1,14 @@
namespace Influx.AllaganTools;
using System;
namespace Influx.AllaganTools;
using ItemFlags = FFXIVClientStructs.FFXIV.Client.Game.InventoryItem.ItemFlags;
internal sealed class SortingResult
{
public SortingResult(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
LocalContentId = (ulong)@delegate.GetType().GetProperty("SourceRetainerId")!.GetValue(@delegate)!;
Quantity = (int)@delegate.GetType().GetProperty("Quantity")!.GetValue(@delegate)!;

View File

@ -1,10 +1,26 @@
using System;
using System.Collections.Generic;
using Dalamud.Plugin.Services;
namespace Influx.AllaganTools;
internal sealed class UnavailableCharacterMonitor : ICharacterMonitor
internal sealed class UnavailableCharacterMonitor(IPluginLog pluginLog) : ICharacterMonitor
{
public IEnumerable<Character> PlayerCharacters => Array.Empty<Character>();
public IEnumerable<Character> All => Array.Empty<Character>();
public IEnumerable<Character> PlayerCharacters
{
get
{
pluginLog.Warning("Character monitor is unavailable");
return Array.Empty<Character>();
}
}
public IEnumerable<Character> All
{
get
{
pluginLog.Warning("Character monitor is unavailable");
return Array.Empty<Character>();
}
}
}

View File

@ -1,6 +1,12 @@
namespace Influx.AllaganTools;
using Dalamud.Plugin.Services;
internal sealed class UnavailableFilterService : IFilterService
namespace Influx.AllaganTools;
internal sealed class UnavailableFilterService(IPluginLog pluginLog) : IFilterService
{
public Filter? GetFilterByKeyOrName(string keyOrName) => null;
public Filter? GetFilterByKeyOrName(string keyOrName)
{
pluginLog.Warning("Filter Service is unavailable");
return null;
}
}

View File

@ -1,8 +1,16 @@
using System.Collections.Generic;
using Dalamud.Plugin.Services;
namespace Influx.AllaganTools;
internal sealed class UnavailableInventoryMonitor : IInventoryMonitor
internal sealed class UnavailableInventoryMonitor(IPluginLog pluginLog) : IInventoryMonitor
{
public IReadOnlyDictionary<ulong, Inventory> All => new Dictionary<ulong, Inventory>();
public IReadOnlyDictionary<ulong, Inventory> All
{
get
{
pluginLog.Warning("Inventory monitor is unavailable");
return new Dictionary<ulong, Inventory>();
}
}
}

View File

@ -3,14 +3,14 @@ using Dalamud.Configuration;
namespace Influx;
public sealed class Configuration : IPluginConfiguration
internal sealed class Configuration : IPluginConfiguration
{
public int Version { get; set; } = 1;
public ServerConfiguration Server { get; set; } = new();
public List<CharacterInfo> IncludedCharacters { get; set; } = new();
public List<FilterInfo> IncludedInventoryFilters { get; set; } = new();
public IList<CharacterInfo> IncludedCharacters { get; set; } = new List<CharacterInfo>();
public IList<FilterInfo> IncludedInventoryFilters { get; set; } = new List<FilterInfo>();
public sealed class ServerConfiguration
{

View File

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<Version>0.11</Version>
<LangVersion>11.0</LangVersion>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>0.12</Version>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
@ -25,7 +25,7 @@
<ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.12"/>
<PackageReference Include="InfluxDB.Client" Version="4.14.0" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.2" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.3" />
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Dalamud.Plugin.Services;
@ -23,7 +25,7 @@ internal sealed class InfluxStatisticsClient : IDisposable
private readonly IReadOnlyDictionary<byte, byte> _classJobToArrayIndex;
private readonly IReadOnlyDictionary<byte, string> _classJobNames;
private readonly IReadOnlyDictionary<sbyte, string> _expToJobs;
private readonly IReadOnlyDictionary<uint, PriceInfo> _prices;
private readonly ReadOnlyDictionary<uint, PriceInfo> _prices;
public InfluxStatisticsClient(IChatGui chatGui, Configuration configuration, IDataManager dataManager,
IClientState clientState, IPluginLog pluginLog)
@ -43,12 +45,14 @@ internal sealed class InfluxStatisticsClient : IDisposable
.Where(x => x.Abbreviation.ToString() != "SMN")
.ToDictionary(x => x.ExpArrayIndex, x => x.Abbreviation.ToString());
_prices = dataManager.GetExcelSheet<Item>()!
.AsEnumerable()
.ToDictionary(x => x.RowId, x => new PriceInfo
{
Name = x.Name.ToString(),
Normal = x.PriceLow,
UiCategory = x.ItemUICategory.Row,
});
})
.AsReadOnly();
}
public bool Enabled => _configuration.Server.Enabled &&
@ -113,7 +117,7 @@ internal sealed class InfluxStatisticsClient : IDisposable
foreach (var sub in subs)
{
values.Add(PointData.Measurement("submersibles")
.Tag("id", fc.CharacterId.ToString())
.Tag("id", fc.CharacterId.ToString(CultureInfo.InvariantCulture))
.Tag("fc_name", fc.Name)
.Tag("sub_id", $"{fc.CharacterId}_{sub.Id}")
.Tag("sub_name", sub.Name)
@ -133,7 +137,8 @@ internal sealed class InfluxStatisticsClient : IDisposable
var writeApi = client.GetWriteApiAsync();
await writeApi.WritePointsAsync(
values,
_configuration.Server.Bucket, _configuration.Server.Organization);
_configuration.Server.Bucket, _configuration.Server.Organization)
.ConfigureAwait(false);
_pluginLog.Verbose($"Influx: Sent {values.Count} data points to server");
}
@ -155,10 +160,10 @@ internal sealed class InfluxStatisticsClient : IDisposable
x.LocalContentId == character.CharacterId && x.IncludeFreeCompany);
Func<string, PointData> pointData = s => PointData.Measurement(s)
.Tag("id", character.CharacterId.ToString())
.Tag("id", character.CharacterId.ToString(CultureInfo.InvariantCulture))
.Tag("player_name", character.Name)
.Tag("type", character.CharacterType.ToString())
.Tag("fc_id", includeFc ? character.FreeCompanyId.ToString() : null)
.Tag("fc_id", includeFc ? character.FreeCompanyId.ToString(CultureInfo.InvariantCulture) : null)
.Timestamp(date, WritePrecision.S);
yield return pointData("currency")
@ -230,9 +235,9 @@ internal sealed class InfluxStatisticsClient : IDisposable
var owner = update.Currencies.Keys.First(x => x.CharacterId == character.OwnerId);
Func<string, PointData> pointData = s => PointData.Measurement(s)
.Tag("id", character.CharacterId.ToString())
.Tag("id", character.CharacterId.ToString(CultureInfo.InvariantCulture))
.Tag("player_name", owner.Name)
.Tag("player_id", character.OwnerId.ToString())
.Tag("player_id", character.OwnerId.ToString(CultureInfo.InvariantCulture))
.Tag("type", character.CharacterType.ToString())
.Tag("retainer_name", character.Name)
.Timestamp(date, WritePrecision.S);
@ -280,9 +285,9 @@ internal sealed class InfluxStatisticsClient : IDisposable
yield return pointData("items")
.Tag("filter_name", filterName)
.Tag("item_id", item.Key.ItemId.ToString())
.Tag("item_id", item.Key.ItemId.ToString(CultureInfo.InvariantCulture))
.Tag("item_name", priceInfo.Name)
.Tag("hq", (item.Key.IsHq ? 1 : 0).ToString())
.Tag("hq", (item.Key.IsHq ? 1 : 0).ToString(CultureInfo.InvariantCulture))
.Field("quantity", item.Sum(x => x.Quantity))
.Field("total_gil", item.Sum(x => x.Quantity) * (priceHq ? priceInfo.Hq : priceInfo.Normal));
}
@ -295,7 +300,7 @@ internal sealed class InfluxStatisticsClient : IDisposable
update.FcStats.TryGetValue(character.CharacterId, out FcStats? fcStats);
Func<string, PointData> pointData = s => PointData.Measurement(s)
.Tag("id", character.CharacterId.ToString())
.Tag("id", character.CharacterId.ToString(CultureInfo.InvariantCulture))
.Tag("fc_name", character.Name)
.Tag("type", character.CharacterType.ToString())
.Timestamp(date, WritePrecision.S);

View File

@ -18,7 +18,8 @@ using LLib;
namespace Influx;
[SuppressMessage("ReSharper", "UnusedType.Global")]
public sealed class InfluxPlugin : IDalamudPlugin
[SuppressMessage("Performance", "CA1812")]
internal sealed class InfluxPlugin : IDalamudPlugin
{
private readonly object _lock = new();
private readonly DalamudPluginInterface _pluginInterface;

View File

@ -16,7 +16,7 @@ using Newtonsoft.Json;
namespace Influx.LocalStatistics;
public class FcStatsCalculator : IDisposable
internal sealed class FcStatsCalculator : IDisposable
{
private readonly DalamudPluginInterface _pluginInterface;
private readonly IClientState _clientState;
@ -29,7 +29,7 @@ public class FcStatsCalculator : IDisposable
private readonly Dictionary<ulong, FcStats> _cache = new();
private Status? _status = null;
private Status? _status;
public FcStatsCalculator(
IDalamudPlugin plugin,

View File

@ -9,7 +9,7 @@ public sealed record LocalStats
public byte GcRank { get; init; }
public bool SquadronUnlocked { get; init; }
public byte MaxLevel { get; init; } = 90;
public List<short> ClassJobLevels { get; set; } = new();
public IList<short> ClassJobLevels { get; init; } = new List<short>();
public byte StartingTown { get; init; }
public int MsqCount { get; set; } = -1;
public string? MsqName { get; set; }

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@ -111,7 +112,7 @@ internal sealed class LocalStatsCalculator : IDisposable
UpdateStatistics();
}
private IReadOnlyList<QuestInfo> PopulateStartingCities(List<QuestInfo> quests, uint envoyQuestId,
private static ReadOnlyCollection<QuestInfo> PopulateStartingCities(List<QuestInfo> quests, uint envoyQuestId,
uint startingQuestId, bool popCallOfTheSea)
{
QuestInfo callOfTheSea = quests.First(x => x.PreviousQuestIds.Contains(envoyQuestId));
@ -119,12 +120,10 @@ internal sealed class LocalStatsCalculator : IDisposable
quests.Remove(callOfTheSea);
List<QuestInfo> startingCityQuests = new List<QuestInfo> { callOfTheSea };
uint? questId = envoyQuestId;
QuestInfo? quest;
uint questId = envoyQuestId;
do
{
quest = quests.First(x => x.RowId == questId);
QuestInfo quest = quests.First(x => x.RowId == questId);
quests.Remove(quest);
if (quest.Name == "Close to Home")
@ -133,14 +132,14 @@ internal sealed class LocalStatsCalculator : IDisposable
{
RowId = startingQuestId,
Name = "Coming to ...",
PreviousQuestIds = new(),
PreviousQuestIds = new List<uint>(),
Genre = quest.Genre,
};
}
startingCityQuests.Add(quest);
questId = quest.PreviousQuestIds.FirstOrDefault();
} while (questId != null && questId != 0);
} while (questId != 0);
return Enumerable.Reverse(startingCityQuests).ToList().AsReadOnly();
}

View File

@ -6,6 +6,6 @@ public sealed class QuestInfo
{
public required uint RowId { get; init; }
public required string Name { get; init; }
public required List<uint> PreviousQuestIds { get; init; }
public required IList<uint> PreviousQuestIds { get; init; }
public required uint Genre { get; init; }
}

View File

@ -2,21 +2,22 @@
namespace Influx.SubmarineTracker;
public class Build
internal sealed class Build
{
public Build(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
Type type = @delegate.GetType();
HullIdentifier =
(string)@delegate.GetType().GetProperty("HullIdentifier")!.GetValue(@delegate)!;
(string)type.GetProperty("HullIdentifier")!.GetValue(@delegate)!;
SternIdentifier =
(string)@delegate.GetType().GetProperty("SternIdentifier")!.GetValue(@delegate)!;
(string)type.GetProperty("SternIdentifier")!.GetValue(@delegate)!;
BowIdentifier =
(string)@delegate.GetType().GetProperty("BowIdentifier")!.GetValue(@delegate)!;
(string)type.GetProperty("BowIdentifier")!.GetValue(@delegate)!;
BridgeIdentifier =
(string)@delegate.GetType().GetProperty("BridgeIdentifier")!.GetValue(@delegate)!;
(string)type.GetProperty("BridgeIdentifier")!.GetValue(@delegate)!;
FullIdentifier =
(string)@delegate.GetType().GetMethod("FullIdentifier")!.Invoke(@delegate, Array.Empty<object>())!;
(string)type.GetMethod("FullIdentifier")!.Invoke(@delegate, Array.Empty<object>())!;
}
public string HullIdentifier { get; }

View File

@ -1,13 +1,15 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Influx.SubmarineTracker;
public sealed class FcSubmarines
internal sealed class FcSubmarines
{
public FcSubmarines(object @delegate)
{
ArgumentNullException.ThrowIfNull(@delegate);
Submarines = ((IEnumerable)@delegate.GetType().GetField("Submarines")!.GetValue(@delegate)!)
.Cast<object>()
.Select(x => new Submarine(x))

View File

@ -2,21 +2,23 @@
namespace Influx.SubmarineTracker;
public sealed class Submarine
internal sealed class Submarine
{
public Submarine(object @delegate)
{
Name = (string)@delegate.GetType().GetProperty("Name")!.GetValue(@delegate)!;
Level = (ushort)@delegate.GetType().GetProperty("Rank")!.GetValue(@delegate)!;
Build = new Build(@delegate.GetType().GetProperty("Build")!.GetValue(@delegate)!);
ArgumentNullException.ThrowIfNull(@delegate);
Type type = @delegate.GetType();
Name = (string)type.GetProperty("Name")!.GetValue(@delegate)!;
Level = (ushort)type.GetProperty("Rank")!.GetValue(@delegate)!;
Build = new Build(type.GetProperty("Build")!.GetValue(@delegate)!);
try
{
(uint predictedLevel, double _) = ((uint, double))@delegate.GetType().GetMethod("PredictExpGrowth")!.Invoke(@delegate, Array.Empty<object?>())!;
(uint predictedLevel, double _) = ((uint, double))type.GetMethod("PredictExpGrowth")!.Invoke(@delegate, Array.Empty<object?>())!;
PredictedLevel = (ushort)predictedLevel;
bool onVoyage = (bool)@delegate.GetType().GetMethod("IsOnVoyage")!.Invoke(@delegate, Array.Empty<object>())!;
bool returned = (bool)@delegate.GetType().GetMethod("IsDone")!.Invoke(@delegate, Array.Empty<object>())!;
bool onVoyage = (bool)type.GetMethod("IsOnVoyage")!.Invoke(@delegate, Array.Empty<object>())!;
bool returned = (bool)type.GetMethod("IsDone")!.Invoke(@delegate, Array.Empty<object>())!;
if (onVoyage)
State = returned ? EState.Returned : EState.Voyage;
else

View File

@ -1,6 +1,6 @@
namespace Influx.SubmarineTracker;
public sealed class SubmarineStats
internal sealed class SubmarineStats
{
public required string Name { get; init; }
public required int Id { get; init; }

View File

@ -1,6 +1,8 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Dalamud.Plugin;
using Influx.AllaganTools;
using LLib;
@ -15,9 +17,10 @@ internal sealed class SubmarineTrackerIpc
_dalamudReflector = dalamudReflector;
}
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
public Dictionary<Character, List<SubmarineStats>> GetSubmarineStats(List<Character> characters)
{
if (_dalamudReflector.TryGetDalamudPlugin("Submarine Tracker", out var it, false, true))
if (_dalamudReflector.TryGetDalamudPlugin("Submarine Tracker", out IDalamudPlugin? it, false, true))
{
var submarineData = it.GetType().Assembly.GetType("SubmarineTracker.Data.Submarines");
var knownSubmarineData = submarineData!.GetField("KnownSubmarines")!;

View File

@ -19,7 +19,7 @@ internal sealed class ConfigurationWindow : Window
private readonly Configuration _configuration;
private readonly AllaganToolsIpc _allaganToolsIpc;
private string[] _filterNames = Array.Empty<string>();
private int _filterIndexToAdd = 0;
private int _filterIndexToAdd;
public ConfigurationWindow(DalamudPluginInterface pluginInterface, IClientState clientState,
Configuration configuration, AllaganToolsIpc allaganToolsIpc)
@ -44,7 +44,9 @@ internal sealed class ConfigurationWindow : Window
}
}
public override void OnOpen()
public override void OnOpen() => RefreshFilters();
private void RefreshFilters()
{
_filterNames = _allaganToolsIpc.GetSearchFilters()
.Select(x => x.Value)
@ -125,8 +127,9 @@ internal sealed class ConfigurationWindow : Window
if (ImGui.Button("Remove inclusion"))
{
_configuration.IncludedCharacters.RemoveAll(
c => c.LocalContentId == _clientState.LocalContentId);
var characterInfo =
_configuration.IncludedCharacters.First(c => c.LocalContentId == _clientState.LocalContentId);
_configuration.IncludedCharacters.Remove(characterInfo);
Save();
}
}
@ -221,7 +224,8 @@ internal sealed class ConfigurationWindow : Window
{
ImGui.Combo("Add Search Filter", ref _filterIndexToAdd, _filterNames, _filterNames.Length);
ImGui.BeginDisabled(_configuration.IncludedInventoryFilters.Any(x => x.Name == _filterNames[_filterIndexToAdd]));
ImGui.BeginDisabled(
_configuration.IncludedInventoryFilters.Any(x => x.Name == _filterNames[_filterIndexToAdd]));
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Plus, "Track Filter"))
{
_configuration.IncludedInventoryFilters.Add(new Configuration.FilterInfo
@ -238,6 +242,11 @@ internal sealed class ConfigurationWindow : Window
ImGui.TextColored(ImGuiColors.DalamudRed,
"You don't have any search filters, or the AllaganTools integration doesn't work.");
}
ImGui.Separator();
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Sync, "Refresh Filters"))
RefreshFilters();
}
private void Save(bool sendEvent = false)

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using Dalamud.Interface.Windowing;
@ -36,7 +37,7 @@ internal sealed class StatisticsWindow : Window
ImGui.Text(row.Name);
if (ImGui.TableNextColumn())
ImGui.Text(row.Gil.ToString("N0"));
ImGui.Text(row.Gil.ToString("N0", CultureInfo.InvariantCulture));
}
ImGui.EndTable();

View File

@ -1,7 +1,7 @@
{
"version": 1,
"dependencies": {
"net7.0-windows7.0": {
"net8.0-windows7.0": {
"DalamudPackager": {
"type": "Direct",
"requested": "[2.1.12, )",
@ -25,9 +25,9 @@
},
"Microsoft.Extensions.ObjectPool": {
"type": "Direct",
"requested": "[8.0.2, )",
"resolved": "8.0.2",
"contentHash": "LA7lDy048CVjGCwsPqRFVwH8vl5ooHmSFji13Oczw+mOnGhqenWXttkWcJ5dhIR0bhayZrQz4BaSPEVtE8Tt0A=="
"requested": "[8.0.3, )",
"resolved": "8.0.3",
"contentHash": "sk/TGiccSeXUtVeBfFlWJnzp6xLlAxIW+bCHs7uVPLFPQk8vICNmu9Gc3JsKOn6fQuRkrPetQ8EHv4dCiMqhxg=="
},
"CsvHelper": {
"type": "Transitive",
@ -195,7 +195,7 @@
"autoretainerapi": {
"type": "Project",
"dependencies": {
"ECommons": "[2.1.0, )"
"ECommons": "[2.1.0.7, )"
}
},
"ecommons": {

2
LLib

@ -1 +1 @@
Subproject commit 2f6ef354c401a9f1bb9b807327acad7e98662a2e
Subproject commit 3792244261a9f5426a7916f5a6dd1966238ba84a

7
global.json Normal file
View File

@ -0,0 +1,7 @@
{
"sdk": {
"version": "8.0.0",
"rollForward": "latestMajor",
"allowPrerelease": false
}
}