Update to API 9 without the Kami touch
parent
32f251720c
commit
2cf6ded1cd
|
@ -1,4 +1,5 @@
|
|||
.vs/
|
||||
obj/
|
||||
bin/
|
||||
*.user
|
||||
*.user
|
||||
/.idea
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "KamiLib"]
|
||||
path = KamiLib
|
||||
url = https://github.com/MidoriKami/KamiLib
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AssemblyName>CurrencyAlertClassic</AssemblyName>
|
||||
<Version>0.5.0.1</Version>
|
||||
<Description>Currency Alert</Description>
|
||||
<PackageProjectUrl>https://github.com/Lharz/xiv-currency-alert</PackageProjectUrl>
|
||||
|
@ -26,7 +27,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.10" />
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.12" />
|
||||
<Reference Include="FFXIVClientStructs">
|
||||
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
|
||||
<Private>false</Private>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"Author": "Lharz",
|
||||
"Name": "CurrencyAlert",
|
||||
"Name": "CurrencyAlert Classic",
|
||||
"Punchline": "Display alerts upon reaching configurable currencies thresholds (such as Poetics or PVP marks).",
|
||||
"Description": "This plugin lets you easily manage your various currencies to prevent from wasting precious resources.",
|
||||
"Tags": [
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Utility;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using ImGuiScene;
|
||||
|
@ -13,7 +14,7 @@ public class CurrencyInfo : IDisposable
|
|||
public uint ItemID { get; }
|
||||
public string ItemName { get; } = string.Empty;
|
||||
public uint IconID { get; }
|
||||
public TextureWrap? IconTexture { get; }
|
||||
public IDalamudTextureWrap? IconTexture { get; }
|
||||
|
||||
public CurrencyInfo(CurrencyName currency)
|
||||
{
|
||||
|
@ -81,4 +82,4 @@ public class CurrencyInfo : IDisposable
|
|||
.First()
|
||||
.Item.Row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,16 @@ using Dalamud.Game;
|
|||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
|
||||
namespace CurrencyAlert;
|
||||
|
||||
public class Service
|
||||
{
|
||||
[PluginService] public static DalamudPluginInterface PluginInterface { get; private set; } = null!;
|
||||
[PluginService] public static Framework Framework { get; private set; } = null!;
|
||||
[PluginService] public static ClientState ClientState { get; private set; } = null!;
|
||||
[PluginService] public static IFramework Framework { get; private set; } = null!;
|
||||
[PluginService] public static IClientState ClientState { get; private set; } = null!;
|
||||
|
||||
public static Configuration Configuration { get; set; } = null!;
|
||||
public static CurrencyTracker CurrencyTracker { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class CurrencyTracker : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void OnZoneChange(object? sender, ushort e)
|
||||
private void OnZoneChange(ushort e)
|
||||
{
|
||||
if (!Service.Configuration.ChatNotification) return;
|
||||
if (Condition.IsBoundByDuty()) return;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using CurrencyAlert.DataModels;
|
||||
using CurrencyAlert.Localization;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using KamiLib.Drawing;
|
||||
using KamiLib.Interfaces;
|
||||
|
@ -45,4 +46,4 @@ public class GeneralSettingsSelectable : ISelectable, IDrawable
|
|||
.AddConfigColor(Strings.TextColor, Strings.Default, DisplaySettings.TextColor, Colors.White)
|
||||
.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using CurrencyAlert.DataModels;
|
||||
using CurrencyAlert.Localization;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using KamiLib.Drawing;
|
||||
using KamiLib.Interfaces;
|
||||
|
@ -43,4 +44,4 @@ public class TrackedCurrencySelectable : ISelectable, IDrawable
|
|||
.AddInputInt(Strings.Threshold, currency.Threshold, 0, 100000, 0, 0, innerWidth / 2.0f)
|
||||
.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Numerics;
|
|||
using System.Reflection;
|
||||
using CurrencyAlert.Windows.Components;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using KamiLib.Drawing;
|
||||
using KamiLib.Interfaces;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
"net7.0-windows7.0": {
|
||||
"DalamudPackager": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.1.10, )",
|
||||
"resolved": "2.1.10",
|
||||
"contentHash": "S6NrvvOnLgT4GDdgwuKVJjbFo+8ZEj+JsEYk9ojjOR/MMfv1dIFpT8aRJQfI24rtDcw1uF+GnSSMN4WW1yt7fw=="
|
||||
"requested": "[2.1.12, )",
|
||||
"resolved": "2.1.12",
|
||||
"contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg=="
|
||||
},
|
||||
"kamilib": {
|
||||
"type": "Project"
|
||||
|
|
1
KamiLib
1
KamiLib
|
@ -1 +0,0 @@
|
|||
Subproject commit f50ff8903e0adeb2dfe1d64103f54da13e055f89
|
|
@ -0,0 +1,4 @@
|
|||
/obj/
|
||||
/bin/x64/Debug/KamiLib.deps.json
|
||||
/bin/x64/Debug/KamiLib.dll
|
||||
/bin/x64/Debug/KamiLib.pdb
|
|
@ -0,0 +1,13 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
/.idea.KamiLib.iml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Logging;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
||||
|
||||
namespace KamiLib.Atk;
|
||||
|
||||
public static class AtkValueHelper
|
||||
{
|
||||
public static unsafe void PrintAtkValue(AtkValue value, int index)
|
||||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case ValueType.Int:
|
||||
PluginLog.Debug($"[{index:D3}] [{"int", 7}]: {value.Int}");
|
||||
break;
|
||||
case ValueType.Bool:
|
||||
PluginLog.Debug($"[{index:D3}] [{"bool", 7}]: {(value.Byte != 0 ? "true" : "false")}");
|
||||
break;
|
||||
case ValueType.UInt:
|
||||
PluginLog.Debug($"[{index:D3}] [{"uint", 7}]: {value.UInt}");
|
||||
break;
|
||||
case ValueType.Float:
|
||||
PluginLog.Debug($"[{index:D3}] [{"float", 7}]: {value.Float}");
|
||||
break;
|
||||
case ValueType.String:
|
||||
PluginLog.Debug($"[{index:D3}] [{"string", 7}]: {Marshal.PtrToStringUTF8(new nint(value.String))}");
|
||||
break;
|
||||
case ValueType.String8:
|
||||
PluginLog.Debug($"[{index:D3}] [{"string8", 7}]: {Marshal.PtrToStringUTF8(new nint(value.String))}");
|
||||
break;
|
||||
case ValueType.Vector:
|
||||
PluginLog.Debug($"[{index:D3}] [{"vector", 7}]: No Representation Implemented");
|
||||
break;
|
||||
case ValueType.AllocatedString:
|
||||
PluginLog.Debug($"[{index:D3}] [{"aString", 7}]: {Marshal.PtrToStringUTF8(new nint(value.String))}");
|
||||
break;
|
||||
case ValueType.AllocatedVector:
|
||||
PluginLog.Debug($"[{index:D3}] [{"aVector", 7}]: No Representation Implemented");
|
||||
break;
|
||||
default:
|
||||
PluginLog.Debug($"[{index:D3}] [{"unknown", 7}]: [{value.Type}]: {BitConverter.ToString(BitConverter.GetBytes((long)value.String)).Replace("-", " ")}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AtkValueExtensions
|
||||
{
|
||||
public static unsafe string GetString(this AtkValue value)
|
||||
{
|
||||
return Marshal.PtrToStringUTF8(new nint(value.String)) ?? "Unable to Allocate String";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
using System.Linq;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using KamiLib.ChatCommands;
|
||||
|
||||
namespace KamiLib.Atk;
|
||||
|
||||
public unsafe class BaseNode
|
||||
{
|
||||
private readonly AtkUnitBase* node;
|
||||
|
||||
public bool NodeValid => node != null;
|
||||
|
||||
public BaseNode(string addon)
|
||||
{
|
||||
node = (AtkUnitBase*) Service.GameGui.GetAddonByName(addon, 1);
|
||||
}
|
||||
|
||||
public BaseNode Print()
|
||||
{
|
||||
Chat.Print("AtkUnitBase", $"{new nint(node):X8}");
|
||||
return this;
|
||||
}
|
||||
|
||||
public AtkResNode* GetRootNode() => node == null ? null : node->RootNode;
|
||||
|
||||
public T* GetNode<T>(uint id) where T : unmanaged
|
||||
{
|
||||
if (node == null) return null;
|
||||
|
||||
var targetNode = (T*) node->GetNodeById(id);
|
||||
|
||||
return targetNode;
|
||||
}
|
||||
|
||||
public ComponentNode GetComponentNode(uint id)
|
||||
{
|
||||
if (node == null) return new ComponentNode(null);
|
||||
|
||||
var targetNode = (AtkComponentNode*) node->GetNodeById(id);
|
||||
|
||||
return new ComponentNode(targetNode);
|
||||
}
|
||||
|
||||
public ComponentNode GetNestedNode(params uint[] idList)
|
||||
{
|
||||
uint index = 0;
|
||||
|
||||
ComponentNode startingNode;
|
||||
|
||||
do
|
||||
{
|
||||
startingNode = GetComponentNode(idList[index]);
|
||||
|
||||
} while (index++ < idList.Length);
|
||||
|
||||
return startingNode;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe class ComponentNode
|
||||
{
|
||||
private readonly AtkComponentNode* node;
|
||||
private readonly AtkComponentBase* componentBase;
|
||||
|
||||
public ComponentNode(AtkComponentNode* node)
|
||||
{
|
||||
this.node = node;
|
||||
|
||||
componentBase = node == null ? null : node->Component;
|
||||
}
|
||||
|
||||
public ComponentNode Print()
|
||||
{
|
||||
Chat.Print("AtkComponentNode", $"{new nint(node):X8}");
|
||||
return this;
|
||||
}
|
||||
|
||||
public ComponentNode GetComponentNode(uint id)
|
||||
{
|
||||
if (componentBase == null) return new ComponentNode(null);
|
||||
|
||||
var targetNode = Node.GetNodeByID<AtkComponentNode>(componentBase->UldManager, id);
|
||||
|
||||
return new ComponentNode(targetNode);
|
||||
}
|
||||
|
||||
public T* GetNode<T>(uint id) where T : unmanaged => componentBase == null ? null : Node.GetNodeByID<T>(componentBase->UldManager, id);
|
||||
|
||||
public AtkComponentNode* GetPointer() => node;
|
||||
}
|
||||
|
||||
public static unsafe class Node
|
||||
{
|
||||
public static T* GetNodeByID<T>(AtkUldManager uldManager, uint nodeId) where T : unmanaged
|
||||
{
|
||||
foreach (var index in Enumerable.Range(0, uldManager.NodeListCount))
|
||||
{
|
||||
var currentNode = uldManager.NodeList[index];
|
||||
if (currentNode->NodeID != nodeId) continue;
|
||||
|
||||
return (T*) currentNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Utility;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using KamiLib.Caching;
|
||||
using KamiLib.Configuration;
|
||||
using KamiLib.Drawing;
|
||||
using KamiLib.Extensions;
|
||||
using KamiLib.Localization;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace KamiLib.Blacklist;
|
||||
|
||||
public static class BlacklistDraw
|
||||
{
|
||||
private static readonly List<uint> EntriesToRemove = new();
|
||||
private static readonly List<uint> EntriesToAdd = new();
|
||||
private static string _searchString = string.Empty;
|
||||
private static List<SearchResult>? _searchResults = new();
|
||||
|
||||
public static void DrawBlacklist(Setting<List<uint>> blacklistedAreas)
|
||||
{
|
||||
InfoBox.Instance
|
||||
.AddTitle(Strings.Blacklist_CurrentlyBlacklisted, out var innerWidth, 1.0f)
|
||||
.AddDummy(5.0f)
|
||||
.AddAction(() => BlacklistedAreasList(blacklistedAreas))
|
||||
.AddDisabledButton(EntriesToRemove.Count == 0 ? Strings.Blacklist_ClearBlacklist : Strings.Blacklist_RemoveSelectedAreas.Format(EntriesToRemove.Count), () =>
|
||||
{
|
||||
if (EntriesToRemove.Count == 0)
|
||||
{
|
||||
blacklistedAreas.Value.Clear();
|
||||
KamiCommon.SaveConfiguration();
|
||||
}
|
||||
else
|
||||
{
|
||||
blacklistedAreas.Value.RemoveAll(entry => EntriesToRemove.Contains(entry));
|
||||
EntriesToRemove.Clear();
|
||||
KamiCommon.SaveConfiguration();
|
||||
}
|
||||
}, !ImGui.GetIO().KeyShift, Strings.DisabledButton_HoldShift, innerWidth)
|
||||
.Draw();
|
||||
}
|
||||
|
||||
public static void DrawAddRemoveHere(Setting<List<uint>> blacklistedZones)
|
||||
{
|
||||
InfoBox.Instance
|
||||
.AddTitle(Strings.Blacklist_AddRemoveZone, 1.0f)
|
||||
.AddAction(() => LuminaCache<TerritoryType>.Instance.GetRow(Service.ClientState.TerritoryType)?.DrawLabel())
|
||||
.BeginTable()
|
||||
.BeginRow()
|
||||
.AddDisabledButton(Strings.Common_Add, () =>
|
||||
{
|
||||
Add(blacklistedZones, Service.ClientState.TerritoryType);
|
||||
}, blacklistedZones.Value.Contains(Service.ClientState.TerritoryType), buttonSize: InfoBox.Instance.InnerWidth / 2.0f - 5.0f * ImGuiHelpers.GlobalScale)
|
||||
.AddDisabledButton(Strings.Common_Remove, () =>
|
||||
{
|
||||
Remove(blacklistedZones, Service.ClientState.TerritoryType);
|
||||
}, !blacklistedZones.Value.Contains(Service.ClientState.TerritoryType), buttonSize: InfoBox.Instance.InnerWidth / 2.0f - 5.0f * ImGuiHelpers.GlobalScale)
|
||||
.EndRow()
|
||||
.EndTable()
|
||||
.Draw();
|
||||
}
|
||||
|
||||
public static void DrawTerritorySearch(Setting<List<uint>> blacklistedZones)
|
||||
{
|
||||
InfoBox.Instance
|
||||
.AddTitle(Strings.Blacklist_ZoneSearch, out var innerWidth, 1.0f)
|
||||
.AddAction(() =>
|
||||
{
|
||||
ImGui.PushItemWidth(InfoBox.Instance.InnerWidth);
|
||||
if (ImGui.InputTextWithHint("###TerritorySearch", Strings.Blacklist_Search, ref _searchString, 60, ImGuiInputTextFlags.AutoSelectAll))
|
||||
{
|
||||
_searchResults = Search(_searchString, 5);
|
||||
PluginLog.Debug("Updating TerritorySearch Results");
|
||||
}
|
||||
})
|
||||
.AddAction(() => DisplayResults(_searchResults))
|
||||
.AddDisabledButton(Strings.Blacklist_AddSelectedAreas.Format(EntriesToAdd.Count), () =>
|
||||
{
|
||||
blacklistedZones.Value.AddRange(EntriesToAdd);
|
||||
EntriesToAdd.Clear();
|
||||
KamiCommon.SaveConfiguration();
|
||||
|
||||
}, !EntriesToAdd.Any(), Strings.Blacklist_SelectZones, innerWidth)
|
||||
.Draw();
|
||||
}
|
||||
|
||||
public static void PrimeSearch()
|
||||
{
|
||||
_searchResults = Search("", 5);
|
||||
}
|
||||
|
||||
private static List<SearchResult> Search(string searchTerms, int numResults)
|
||||
{
|
||||
return Service.DataManager.GetExcelSheet<TerritoryType>()!
|
||||
.Where(territory => territory.PlaceName.Row is not 0)
|
||||
.Where(territory => territory.PlaceName.Value is not null)
|
||||
.GroupBy(territory => territory.PlaceName.Value!.Name.ToDalamudString().TextValue)
|
||||
.Select(territory => territory.First())
|
||||
.Where(territory => territory.PlaceName.Value!.Name.ToDalamudString().TextValue.ToLower().Contains(searchTerms.ToLower()))
|
||||
.Select(territory => new SearchResult {
|
||||
TerritoryID = territory.RowId
|
||||
})
|
||||
.OrderBy(searchResult => searchResult.TerritoryName)
|
||||
.Take(numResults)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static void DisplayResults(List<SearchResult>? results)
|
||||
{
|
||||
if (results is null) return;
|
||||
|
||||
if (ImGui.BeginChild("###SearchResultsChild", new Vector2(InfoBox.Instance.InnerWidth, 21.0f * 5 * ImGuiHelpers.GlobalScale )))
|
||||
{
|
||||
foreach (var result in results)
|
||||
{
|
||||
if (ImGui.Selectable($"###SearchResult{result.TerritoryID}", EntriesToAdd.Contains(result.TerritoryID)))
|
||||
{
|
||||
if (!EntriesToAdd.Contains(result.TerritoryID))
|
||||
{
|
||||
EntriesToAdd.Add(result.TerritoryID);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntriesToAdd.Remove(result.TerritoryID);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
LuminaCache<TerritoryType>.Instance.GetRow(result.TerritoryID)?.DrawLabel();
|
||||
}
|
||||
}
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
private static void BlacklistedAreasList(Setting<List<uint>> blacklistedAreas)
|
||||
{
|
||||
var itemCount = Math.Min(blacklistedAreas.Value.Count, 10);
|
||||
var listHeight = itemCount * ImGuiHelpers.GlobalScale * 21.0f;
|
||||
var minHeight = 21.0f * ImGuiHelpers.GlobalScale;
|
||||
|
||||
var size = new Vector2(InfoBox.Instance.InnerWidth, MathF.Max(listHeight, minHeight));
|
||||
|
||||
if(ImGui.BeginChild("###BlacklistFrame", size, false))
|
||||
{
|
||||
if (!blacklistedAreas.Value.Any())
|
||||
{
|
||||
ImGui.SetCursorPos(ImGui.GetCursorPos() with { X = ImGui.GetContentRegionAvail().X / 2 - ImGui.CalcTextSize(Strings.Blacklist_Empty).X / 2.0f});
|
||||
ImGui.TextColored(Colors.Orange, Strings.Blacklist_Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBlacklistedAreas(blacklistedAreas);
|
||||
}
|
||||
}
|
||||
ImGui.EndChild();
|
||||
}
|
||||
|
||||
private static void DrawBlacklistedAreas(Setting<List<uint>> blacklistedAreas)
|
||||
{
|
||||
var territories = blacklistedAreas.Value
|
||||
.Select(area => LuminaCache<TerritoryType>.Instance.GetRow(area))
|
||||
.OfType<TerritoryType>()
|
||||
.OrderBy(territory => territory.GetPlaceNameString());
|
||||
|
||||
foreach (var territory in territories)
|
||||
{
|
||||
ImGui.PushItemWidth(InfoBox.Instance.InnerWidth);
|
||||
if (ImGui.Selectable($"###{territory}", EntriesToRemove.Contains(territory.RowId)))
|
||||
{
|
||||
if (!EntriesToRemove.Contains(territory.RowId))
|
||||
{
|
||||
EntriesToRemove.Add(territory.RowId);
|
||||
}
|
||||
else
|
||||
{
|
||||
EntriesToRemove.Remove(territory.RowId);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
territory.DrawLabel();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Add(Setting<List<uint>> zones, uint id)
|
||||
{
|
||||
if (!zones.Value.Contains(id))
|
||||
{
|
||||
zones.Value.Add(id);
|
||||
KamiCommon.SaveConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Remove(Setting<List<uint>> zones, uint id)
|
||||
{
|
||||
if (zones.Value.Contains(id))
|
||||
{
|
||||
zones.Value.Remove(id);
|
||||
KamiCommon.SaveConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using Dalamud.Utility;
|
||||
using KamiLib.Caching;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
|
||||
namespace KamiLib.Blacklist;
|
||||
|
||||
public class SearchResult
|
||||
{
|
||||
public uint TerritoryID { get; init; }
|
||||
private uint PlaceNameRow => LuminaCache<TerritoryType>.Instance.GetRow(TerritoryID)?.PlaceName.Row ?? 0;
|
||||
public string TerritoryName => LuminaCache<PlaceName>.Instance.GetRow(PlaceNameRow)?.Name.ToDalamudString().TextValue ?? "Unknown PlaceName Row";
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiScene;
|
||||
|
||||
namespace KamiLib.Caching;
|
||||
|
||||
public class IconCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<uint, IDalamudTextureWrap?> iconTextures = new();
|
||||
|
||||
private const string IconFilePath = "ui/icon/{0:D3}000/{1:D6}_hr1.tex";
|
||||
|
||||
private static IconCache? _instance;
|
||||
public static IconCache Instance => _instance ??= new IconCache();
|
||||
|
||||
public static void Cleanup()
|
||||
{
|
||||
_instance?.Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var texture in iconTextures.Values)
|
||||
{
|
||||
texture?.Dispose();
|
||||
}
|
||||
|
||||
iconTextures.Clear();
|
||||
}
|
||||
|
||||
private void LoadIconTexture(uint iconId)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var path = IconFilePath.Format(iconId / 1000, iconId);
|
||||
var tex = Service.TextureProvider.GetTextureFromGame(path);
|
||||
|
||||
if (tex is not null && tex.ImGuiHandle != nint.Zero)
|
||||
{
|
||||
iconTextures[iconId] = tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
tex?.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginLog.LogError($"Failed loading texture for icon {iconId} - {ex.Message}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IDalamudTextureWrap? GetIcon(uint iconId)
|
||||
{
|
||||
if (iconTextures.TryGetValue(iconId, out var value)) return value;
|
||||
|
||||
iconTextures.Add(iconId, null);
|
||||
LoadIconTexture(iconId);
|
||||
|
||||
return iconTextures[iconId];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud;
|
||||
using Lumina.Excel;
|
||||
|
||||
namespace KamiLib.Caching;
|
||||
|
||||
public class LuminaCache<T> : IEnumerable<T> where T : ExcelRow
|
||||
{
|
||||
private readonly Func<uint, T?> searchAction;
|
||||
|
||||
private static LuminaCache<T>? _instance;
|
||||
public static LuminaCache<T> Instance => _instance ??= new LuminaCache<T>();
|
||||
|
||||
private LuminaCache(Func<uint, T?>? action = null)
|
||||
{
|
||||
searchAction = action ?? (row => Service.DataManager.GetExcelSheet<T>()!.GetRow(row));
|
||||
}
|
||||
|
||||
private readonly Dictionary<uint, T> cache = new();
|
||||
private readonly Dictionary<Tuple<uint, uint>, T> subRowCache = new ();
|
||||
|
||||
public ExcelSheet<T> OfLanguage(ClientLanguage language)
|
||||
{
|
||||
return Service.DataManager.GetExcelSheet<T>(language)!;
|
||||
}
|
||||
|
||||
public T? GetRow(uint id)
|
||||
{
|
||||
if (cache.TryGetValue(id, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (searchAction(id) is not { } result) return null;
|
||||
|
||||
return cache[id] = result;
|
||||
}
|
||||
}
|
||||
|
||||
public T? GetRow(uint row, uint subRow)
|
||||
{
|
||||
var targetRow = new Tuple<uint, uint>(row, subRow);
|
||||
|
||||
if (subRowCache.TryGetValue(targetRow, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Service.DataManager.GetExcelSheet<T>()!.GetRow(row, subRow) is not { } result) return null;
|
||||
|
||||
return subRowCache[targetRow] = result;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => Service.DataManager.GetExcelSheet<T>()!.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
using KamiLib.Localization;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public static class Chat
|
||||
{
|
||||
public static void Print(string tag, string message) => Service.Chat.Print(GetBaseString(tag, message).BuiltString);
|
||||
|
||||
public static void PrintHelp(string command, string? helpText = null)
|
||||
{
|
||||
var message = GetBaseString(Strings.Command_Label, command);
|
||||
|
||||
if (helpText is not null)
|
||||
{
|
||||
message.AddUiForeground("- " + helpText, 32);
|
||||
}
|
||||
|
||||
Service.Chat.Print(message.BuiltString);
|
||||
}
|
||||
|
||||
public static void Print(string tag, string message, DalamudLinkPayload? payload)
|
||||
{
|
||||
if (payload is null)
|
||||
{
|
||||
Print(tag, message);
|
||||
return;
|
||||
}
|
||||
|
||||
Service.Chat.Print(GetBaseString(tag, message, payload).BuiltString);
|
||||
}
|
||||
|
||||
public static void PrintError(string message) => Service.Chat.PrintError(GetBaseString(Strings.Common_Error, message).BuiltString);
|
||||
|
||||
private static SeStringBuilder GetBaseString(string tag, string message, DalamudLinkPayload? payload = null)
|
||||
{
|
||||
if (payload is null)
|
||||
{
|
||||
return new SeStringBuilder()
|
||||
.AddUiForeground($"[{KamiCommon.PluginName}] ", 45)
|
||||
.AddUiForeground($"[{tag}] ", 62)
|
||||
.AddText(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new SeStringBuilder()
|
||||
.AddUiForeground($"[{KamiCommon.PluginName}] ", 45)
|
||||
.AddUiForeground($"[{tag}] ", 62)
|
||||
.Add(payload)
|
||||
.AddUiForeground(message, 35)
|
||||
.Add(RawPayload.LinkTerminator);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
internal record ChatLinkPayload(uint CommandID, uint Type, DalamudLinkPayload Payload);
|
||||
|
||||
public class ChatPayloadManager : IDisposable
|
||||
{
|
||||
private static ChatPayloadManager? _instance;
|
||||
public static ChatPayloadManager Instance => _instance ??= new ChatPayloadManager();
|
||||
|
||||
private List<ChatLinkPayload> ChatLinkPayloads { get; } = new();
|
||||
|
||||
public static void Cleanup()
|
||||
{
|
||||
_instance?.Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var payload in ChatLinkPayloads)
|
||||
{
|
||||
Service.PluginInterface.RemoveChatLinkHandler( payload.Type + 1000 );
|
||||
}
|
||||
}
|
||||
|
||||
public DalamudLinkPayload AddChatLink(Enum type, Action<uint, SeString> payloadAction) => AddChatLink(Convert.ToUInt32(type), payloadAction);
|
||||
|
||||
private DalamudLinkPayload AddChatLink(uint type, Action<uint, SeString> payloadAction)
|
||||
{
|
||||
// If the payload is already registered
|
||||
var payload = ChatLinkPayloads.FirstOrDefault(linkPayload => linkPayload.CommandID == type + 1000)?.Payload;
|
||||
if (payload != null) return payload;
|
||||
|
||||
// else
|
||||
Service.PluginInterface.RemoveChatLinkHandler(type + 1000);
|
||||
payload = Service.PluginInterface.AddChatLinkHandler(type + 1000, payloadAction);
|
||||
|
||||
ChatLinkPayloads.Add(new ChatLinkPayload(type + 1000, type, payload));
|
||||
|
||||
return payload;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using KamiLib.Interfaces;
|
||||
using KamiLib.Localization;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public static class Command
|
||||
{
|
||||
public static CommandData GetCommandData(string baseCommand, string arguments) => new(baseCommand, arguments);
|
||||
|
||||
public static void ProcessCommand(CommandData data, IEnumerable<IPluginCommand> commands)
|
||||
{
|
||||
var matchingCommands = commands.Where(command => command.CommandArgument == data.Command).ToList();
|
||||
|
||||
if (matchingCommands.Any())
|
||||
{
|
||||
if (!matchingCommands.Any(command => command.Execute(data)))
|
||||
{
|
||||
Chat.PrintError(string.Format(Strings.Command_DoesntExistExtended, data.BaseCommand, data.Command, data.SubCommand));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Chat.PrintError(string.Format(Strings.Command_DoesntExist, data.BaseCommand, data.Command));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public class CommandData
|
||||
{
|
||||
public string? BaseCommand;
|
||||
public string? Command;
|
||||
public string? SubCommand;
|
||||
public string?[]? Arguments;
|
||||
|
||||
public CommandData(string rootCommand, string arguments)
|
||||
{
|
||||
BaseCommand = rootCommand;
|
||||
|
||||
if (arguments != string.Empty)
|
||||
{
|
||||
var splits = arguments.Split(' ');
|
||||
|
||||
if (splits.Length >= 1)
|
||||
{
|
||||
Command = splits[0];
|
||||
}
|
||||
|
||||
if (splits.Length >= 2)
|
||||
{
|
||||
SubCommand = splits[1];
|
||||
}
|
||||
|
||||
if (splits.Length >= 3)
|
||||
{
|
||||
Arguments = splits[2..];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => $"{BaseCommand ?? "Empty Base Command"}, " +
|
||||
$"{Command ?? "Empty Command"}, " +
|
||||
$"{SubCommand ?? "Empty SubCommand"}, " +
|
||||
$"{(Arguments is null ? "Empty Args" : string.Join(", ", Arguments))}";
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.Logging;
|
||||
using KamiLib.Interfaces;
|
||||
using KamiLib.Localization;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public class CommandManager : IDisposable
|
||||
{
|
||||
private static string SettingsCommand => $"/{KamiCommon.PluginName.ToLower()}";
|
||||
private static string HelpCommand => $"/{KamiCommon.PluginName.ToLower()} help";
|
||||
|
||||
public readonly List<IPluginCommand> Commands = new();
|
||||
|
||||
private readonly List<string> additionalCommands = new();
|
||||
|
||||
public CommandManager()
|
||||
{
|
||||
Commands.Add(new HelpCommands());
|
||||
|
||||
Service.Commands.AddHandler(SettingsCommand, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = Strings.Command_OpenConfigWindow
|
||||
});
|
||||
|
||||
Service.Commands.AddHandler(HelpCommand, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = Strings.Command_DisplayHelpText
|
||||
});
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Service.Commands.RemoveHandler(SettingsCommand);
|
||||
Service.Commands.RemoveHandler(HelpCommand);
|
||||
|
||||
foreach (var additionalCommand in additionalCommands)
|
||||
{
|
||||
Service.Commands.RemoveHandler(additionalCommand);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddHandler(string additionalCommand, string description)
|
||||
{
|
||||
additionalCommands.Add(additionalCommand);
|
||||
Service.Commands.AddHandler(additionalCommand, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = description
|
||||
});
|
||||
}
|
||||
|
||||
public void AddCommand(IPluginCommand command)
|
||||
{
|
||||
Commands.Add(command);
|
||||
}
|
||||
|
||||
public void OnCommand(string command, string arguments)
|
||||
{
|
||||
var commandData = Command.GetCommandData(command.ToLower(), arguments.ToLower());
|
||||
|
||||
PluginLog.Debug($"[{KamiCommon.PluginName}] Received Command: {commandData}");
|
||||
Command.ProcessCommand(commandData, Commands);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using KamiLib.Interfaces;
|
||||
using KamiLib.Localization;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public class HelpCommands: IPluginCommand
|
||||
{
|
||||
public string CommandArgument => "help";
|
||||
|
||||
public IEnumerable<ISubCommand> SubCommands { get; } = new List<ISubCommand>
|
||||
{
|
||||
new SubCommand
|
||||
{
|
||||
CommandKeyword = null,
|
||||
CommandAction = () =>
|
||||
{
|
||||
foreach (var command in KamiCommon.CommandManager.Commands)
|
||||
{
|
||||
PrintSubCommands(command);
|
||||
}
|
||||
},
|
||||
GetHelpText = () => Strings.Command_ShowThisMessage
|
||||
}
|
||||
};
|
||||
|
||||
private static void PrintSubCommands(IPluginCommand command)
|
||||
{
|
||||
foreach (var subCommand in command.SubCommands.GroupBy(subCommand => subCommand.GetCommand()))
|
||||
{
|
||||
var selectedSubCommand = subCommand.First();
|
||||
|
||||
if (!selectedSubCommand.Hidden)
|
||||
{
|
||||
PrintHelpText(command, selectedSubCommand);
|
||||
|
||||
if (selectedSubCommand.GetAliases() is { } aliases)
|
||||
{
|
||||
foreach (var alias in aliases)
|
||||
{
|
||||
PrintAliasHelpText(command, alias, selectedSubCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintHelpText(IPluginCommand mainCommand, ISubCommand subCommand)
|
||||
{
|
||||
var commandString = $"/{KamiCommon.PluginName.ToLower()} ";
|
||||
|
||||
if (mainCommand.CommandArgument is not null)
|
||||
{
|
||||
commandString += mainCommand.CommandArgument + " ";
|
||||
}
|
||||
|
||||
if (subCommand.GetCommand() is not null)
|
||||
{
|
||||
commandString += subCommand.GetCommand() + " ";
|
||||
}
|
||||
|
||||
if (subCommand.HasParameterAction)
|
||||
{
|
||||
commandString += $"[{Strings.Common_Value}] ";
|
||||
}
|
||||
|
||||
Chat.PrintHelp(commandString, subCommand.GetHelpText());
|
||||
}
|
||||
|
||||
private static void PrintAliasHelpText(IPluginCommand mainCommand, string? alias, ISubCommand subCommand)
|
||||
{
|
||||
var commandString = $"/{KamiCommon.PluginName.ToLower()} ";
|
||||
|
||||
if (mainCommand.CommandArgument is not null)
|
||||
{
|
||||
commandString += mainCommand.CommandArgument + " ";
|
||||
}
|
||||
|
||||
if (alias is not null)
|
||||
{
|
||||
commandString += alias + " ";
|
||||
}
|
||||
|
||||
if (subCommand.HasParameterAction)
|
||||
{
|
||||
commandString += $"[{Strings.Common_Value}] ";
|
||||
}
|
||||
|
||||
Chat.PrintHelp(commandString, subCommand.GetHelpText());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using KamiLib.Interfaces;
|
||||
using KamiLib.Localization;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public class OpenWindowCommand<T> : IPluginCommand where T : Window
|
||||
{
|
||||
public string? CommandArgument { get; }
|
||||
|
||||
public OpenWindowCommand( string? commandArgument = null, bool silent = false, string? windowName = null)
|
||||
{
|
||||
CommandArgument = commandArgument?.ToLower();
|
||||
|
||||
if (commandArgument is not null)
|
||||
{
|
||||
windowName ??= CultureInfo.CurrentCulture.TextInfo.ToTitleCase(commandArgument);
|
||||
}
|
||||
|
||||
SubCommands = new List<ISubCommand>
|
||||
{
|
||||
new SubCommand
|
||||
{
|
||||
CommandKeyword = null,
|
||||
CommandAction = () => Chat.PrintError(string.Format(Strings.Command_PvPError, windowName)),
|
||||
CanExecute = () => Service.ClientState.IsPvP,
|
||||
GetHelpText = () => string.Format(Strings.Command_OpenWindow, windowName),
|
||||
Hidden = silent,
|
||||
},
|
||||
new SubCommand
|
||||
{
|
||||
CommandKeyword = null,
|
||||
CommandAction = () =>
|
||||
{
|
||||
if ( KamiCommon.WindowManager.GetWindowOfType<T>() is {} mainWindow )
|
||||
{
|
||||
if (!silent)
|
||||
{
|
||||
Chat.Print(Strings.Command_Label,
|
||||
!mainWindow.IsOpen ?
|
||||
string.Format(Strings.Command_OpeningWindow, windowName) :
|
||||
string.Format(Strings.Command_ClosingWindow, windowName));
|
||||
}
|
||||
|
||||
mainWindow.IsOpen = !mainWindow.IsOpen;
|
||||
}
|
||||
else
|
||||
{
|
||||
Chat.PrintError($"Something went wrong trying to open {windowName} Window");
|
||||
}
|
||||
},
|
||||
CanExecute = () => !Service.ClientState.IsPvP,
|
||||
GetHelpText = () => string.Format(Strings.Command_OpenWindow, windowName),
|
||||
Hidden = silent,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<ISubCommand> SubCommands { get; }
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using KamiLib.Interfaces;
|
||||
|
||||
namespace KamiLib.ChatCommands;
|
||||
|
||||
public class SubCommand : ISubCommand
|
||||
{
|
||||
public string? CommandKeyword { get; init; }
|
||||
public List<string>? Aliases { get; init; }
|
||||
public Action? CommandAction { get; init; }
|
||||
public Action<string?[]?>? ParameterAction { get; init; }
|
||||
public Func<bool>? CanExecute { get; init; }
|
||||
public Func<string>? GetHelpText { get; init; }
|
||||
public bool Hidden { get; init; }
|
||||
public bool HasParameterAction => ParameterAction is not null;
|
||||
|
||||
public string? GetCommand() => CommandKeyword;
|
||||
public IEnumerable<string>? GetAliases() => Aliases;
|
||||
|
||||
string? ISubCommand.GetHelpText() => GetHelpText?.Invoke();
|
||||
|
||||
public bool Execute(CommandData commandData)
|
||||
{
|
||||
if (CanExecute?.Invoke() is null or true)
|
||||
{
|
||||
if (CommandAction is not null)
|
||||
{
|
||||
CommandAction.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ParameterAction is not null)
|
||||
{
|
||||
ParameterAction.Invoke(commandData.Arguments);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace KamiLib.Configuration;
|
||||
|
||||
public static class Migrate
|
||||
{
|
||||
private static JObject? _parsedJson;
|
||||
|
||||
public static void LoadFile(FileInfo configFilePath)
|
||||
{
|
||||
var reader = new StreamReader(configFilePath.FullName);
|
||||
var fileText = reader.ReadToEnd();
|
||||
reader.Dispose();
|
||||
|
||||
_parsedJson = JObject.Parse(fileText);
|
||||
}
|
||||
|
||||
public static int GetFileVersion()
|
||||
{
|
||||
return _parsedJson?.GetValue("Version")?.Value<int>() ?? 0;
|
||||
}
|
||||
|
||||
public static Setting<T> GetSettingValue<T>(string key) where T : struct
|
||||
{
|
||||
return new Setting<T>(_parsedJson!.SelectToken(key)!.Value<T>());
|
||||
}
|
||||
|
||||
public static Setting<T> GetSettingEnum<T>(string key) where T : struct
|
||||
{
|
||||
var readValue = _parsedJson!.SelectToken(key)!.Value<int>();
|
||||
|
||||
return new Setting<T>((T) Enum.ToObject(typeof(T), readValue));
|
||||
}
|
||||
|
||||
public static T GetValue<T>(string key)
|
||||
{
|
||||
return _parsedJson!.SelectToken(key)!.Value<T>()!;
|
||||
}
|
||||
|
||||
public static JArray GetArray(string key)
|
||||
{
|
||||
return (JArray) _parsedJson!.SelectToken(key)!;
|
||||
}
|
||||
|
||||
public static List<T> GetArray<T>(string key)
|
||||
{
|
||||
var array = GetArray(key);
|
||||
|
||||
return array.ToObject<List<T>>()!;
|
||||
}
|
||||
|
||||
public static Setting<Vector4> GetVector4(string key)
|
||||
{
|
||||
return new Setting<Vector4>(new Vector4
|
||||
{
|
||||
X = GetValue<float>($"{key}.X"),
|
||||
Y = GetValue<float>($"{key}.Y"),
|
||||
Z = GetValue<float>($"{key}.Z"),
|
||||
W = GetValue<float>($"{key}.W"),
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace KamiLib.Configuration;
|
||||
|
||||
public sealed record Setting<T>(T Value) : IEquatable<T> where T : notnull
|
||||
{
|
||||
public T Value = Value;
|
||||
|
||||
public override string ToString() => Value.ToString() ?? "Null";
|
||||
|
||||
public bool Equals(T? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return EqualityComparer<T>.Default.Equals(Value, other);
|
||||
}
|
||||
|
||||
public static bool operator ==(Setting<T> leftSide, T rightSide)
|
||||
{
|
||||
return leftSide.Equals(rightSide);
|
||||
}
|
||||
|
||||
public static bool operator !=(Setting<T> leftSide, T rightSide)
|
||||
{
|
||||
return !leftSide.Equals(rightSide);
|
||||
}
|
||||
|
||||
public static implicit operator bool(Setting<T> obj)
|
||||
{
|
||||
if (obj.Value is bool value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception("Invalid implicit conversion to bool");
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
return EqualityComparer<T>.Default.GetHashCode(Value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System.Numerics;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace KamiLib.Drawing;
|
||||
|
||||
public static class Colors
|
||||
{
|
||||
public static Vector4 Purple = new(176 / 255.0f, 38 / 255.0f, 236 / 255.0f, 1.0f);
|
||||
public static Vector4 Blue = new(37 / 255.0f, 168 / 255.0f, 1.0f, 1.0f);
|
||||
public static Vector4 ForestGreen = new(0.133f, 0.545f, 0.1333f, 1.0f);
|
||||
public static Vector4 White = new(1.0f, 1.0f, 1.0f,1.0f);
|
||||
public static Vector4 Red = new(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
public static Vector4 Green = new(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
public static Vector4 Black = new(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
public static Vector4 HealerGreen = new(33 / 255f, 193 / 255f, 0, 1.0f);
|
||||
public static Vector4 DPSRed = new(210/255f, 42/255f, 43/255f, 1.0f);
|
||||
public static Vector4 SoftRed = new(0.8f, 0.2f, 0.2f, 1.0f);
|
||||
public static Vector4 Grey = new(0.6f, 0.6f, 0.6f, 1.0f);
|
||||
public static Vector4 LightGrey = new(220/250.0f, 220/250.0f, 220/250f, 1.0f);
|
||||
public static Vector4 Orange = new(1.0f, 165.0f / 255.0f, 0.0f, 1.0f);
|
||||
public static Vector4 SoftGreen = new(0.2f, 0.8f, 0.2f, 1.0f);
|
||||
public static Vector4 FatePink = new(0.58f, 0.388f, 0.827f, 0.33f);
|
||||
public static Vector4 FateDarkPink = new(0.58f, 0.388f, 0.827f, 1.0f);
|
||||
public static Vector4 MapTextBrown = new(0.655f, 0.396f, 0.149f, 1.0f);
|
||||
public static Vector4 BabyBlue = new(0.537f, 0.812f, 0.941f, 1.0f);
|
||||
}
|
||||
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static uint ToU32(this Vector4 color) => ImGui.GetColorU32(color);
|
||||
}
|
|
@ -0,0 +1,491 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Utility;
|
||||
using ImGuiNET;
|
||||
using KamiLib.Caching;
|
||||
using KamiLib.Configuration;
|
||||
using Action = System.Action;
|
||||
|
||||
namespace KamiLib.Drawing;
|
||||
|
||||
public abstract class DrawList<T>
|
||||
{
|
||||
protected T DrawListOwner { get; init; } = default!;
|
||||
protected List<Action> DrawActions { get; } = new();
|
||||
|
||||
protected void DrawListContents()
|
||||
{
|
||||
foreach (var action in DrawActions)
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
public T AddDummy(float value)
|
||||
{
|
||||
DrawActions.Add(() => ImGuiHelpers.ScaledDummy(value));
|
||||
|
||||
return DrawListOwner;
|
||||
}
|
||||
|
||||
public T AddIndent(int tab)
|
||||
{
|
||||
DrawActions.Add(() => ImGui.Indent(15.0f * tab));
|
||||
|
||||
return DrawListOwner;
|
||||
}
|
||||
|
||||
public T AddIcon(uint iconID, Vector2 size, Vector4 color)
|
||||
{
|
||||
var icon = IconCache.Instance.GetIcon(iconID);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
DrawActions.Add(() =>
|
||||
{
|
||||
ImGui.Image(icon.ImGuiHandle, size, Vector2.Zero, Vector2.One, color);
|
||||
});
|
||||
}
|
||||
|
||||
return DrawListOwner;
|
||||
}
|
||||
|
||||
public T AddIcon(uint iconID, Vector2 size, float transparency)
|
||||
{
|
||||
var icon = IconCache.Instance.GetIcon(iconID);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
DrawActions.Add(() =>
|
||||
{
|
||||
ImGui.Image(icon.ImGuiHandle, size, Vector2.Zero, Vector2.One, Vector4.One with {W = transparency});
|
||||
});
|
||||
}
|
||||
|
||||
return DrawListOwner;
|
||||
}
|
||||
|
||||
public T AddString(string message, Vector4? color = null)
|
||||
{
|
||||
if (color == null)
|
||||
{
|
||||
DrawActions.Add(() => ImGui.Text(message));
|