diff --git a/.gitignore b/.gitignore
index 1ee5385..40dcb4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@ bld/
# Visual Studio 2015/2017 cache/options directory
.vs/
+.idea/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
diff --git a/GoodMemory/ActionType.cs b/GoodMemory/ActionType.cs
index cb653d0..bff2855 100644
--- a/GoodMemory/ActionType.cs
+++ b/GoodMemory/ActionType.cs
@@ -4,15 +4,15 @@ using System.Linq;
namespace GoodMemory {
public static class ActionTypeExt {
- private static readonly ActionType[] VALID = (ActionType[])Enum.GetValues(typeof(ActionType));
+ private static readonly ActionType[] Valid = (ActionType[])Enum.GetValues(typeof(ActionType));
- public static bool IsValidAction(ItemAction action) {
+ public static bool IsValidAction(ItemAction? action) {
if (action == null || action.RowId == 0) {
return false;
}
- ActionType type = (ActionType)action.Type;
- return VALID.Contains(type);
+ var type = (ActionType)action.Type;
+ return Valid.Contains(type);
}
}
diff --git a/GoodMemory/DalamudPackager.targets b/GoodMemory/DalamudPackager.targets
new file mode 100644
index 0000000..41f4094
--- /dev/null
+++ b/GoodMemory/DalamudPackager.targets
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/GoodMemory/GameFunctions.cs b/GoodMemory/GameFunctions.cs
index 4581be4..dfd409a 100644
--- a/GoodMemory/GameFunctions.cs
+++ b/GoodMemory/GameFunctions.cs
@@ -4,58 +4,57 @@ using System.Runtime.InteropServices;
namespace GoodMemory {
public class GameFunctions {
- private readonly Plugin plugin;
+ private Plugin Plugin { get; }
private delegate byte HasItemActionUnlockedDelegate(long itemActionId);
- private readonly HasItemActionUnlockedDelegate hasItemActionUnlocked;
+
+ private readonly HasItemActionUnlockedDelegate _hasItemActionUnlocked;
private delegate byte HasCardDelegate(IntPtr localPlayer, ushort cardId);
- private readonly HasCardDelegate hasCard;
- private readonly IntPtr cardStaticAddr;
+ private readonly HasCardDelegate _hasCard;
+
+ private readonly IntPtr _cardStaticAddr;
public GameFunctions(Plugin plugin) {
- this.plugin = plugin ?? throw new ArgumentNullException(nameof(plugin), "Plugin cannot be null");
+ this.Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin), "Plugin cannot be null");
- IntPtr hasIAUnlockedPtr = plugin.Interface.TargetModuleScanner.ScanText("48 83 EC 28 E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ??");
- IntPtr hasCardPtr = plugin.Interface.TargetModuleScanner.ScanText("40 53 48 83 EC 20 48 8B D9 66 85 D2 74 ??");
- this.cardStaticAddr = plugin.Interface.TargetModuleScanner.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 ?? 48 8B 53 ?? 48 8D 4B ?? 48 83 C2 0C 48 8D 14 ?? E8 ?? ?? ?? ?? 40 FE C7 40 3A FD 72 ?? 48 8B 5C 24 ??");
+ var hasIaUnlockedPtr = plugin.Interface.TargetModuleScanner.ScanText("48 83 EC 28 E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ??");
+ var hasCardPtr = plugin.Interface.TargetModuleScanner.ScanText("40 53 48 83 EC 20 48 8B D9 66 85 D2 74 ??");
+ this._cardStaticAddr = plugin.Interface.TargetModuleScanner.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 ?? 48 8B 53 ?? 48 8D 4B ?? 48 83 C2 0C 48 8D 14 ?? E8 ?? ?? ?? ?? 40 FE C7 40 3A FD 72 ?? 48 8B 5C 24 ??");
- if (hasIAUnlockedPtr == IntPtr.Zero || hasCardPtr == IntPtr.Zero || this.cardStaticAddr == IntPtr.Zero) {
+ if (hasIaUnlockedPtr == IntPtr.Zero || hasCardPtr == IntPtr.Zero || this._cardStaticAddr == IntPtr.Zero) {
throw new ApplicationException("Could not get pointers for game functions");
}
- this.hasItemActionUnlocked = Marshal.GetDelegateForFunctionPointer(hasIAUnlockedPtr);
- this.hasCard = Marshal.GetDelegateForFunctionPointer(hasCardPtr);
+ this._hasItemActionUnlocked = Marshal.GetDelegateForFunctionPointer(hasIaUnlockedPtr);
+ this._hasCard = Marshal.GetDelegateForFunctionPointer(hasCardPtr);
}
public bool HasAcquired(Item item) {
- ItemAction action = item.ItemAction.Value;
+ var action = item.ItemAction.Value;
if (action == null) {
return false;
}
- ActionType type = (ActionType)action.Type;
+ var type = (ActionType)action.Type;
- if (type == ActionType.Cards) {
- uint cardId = item.AdditionalData;
- TripleTriadCard card = this.plugin.Interface.Data.GetExcelSheet().GetRow(cardId);
- if (card == null) {
- return false;
- }
- return this.HasCard((ushort)card.RowId);
+ if (type != ActionType.Cards) {
+ return this.HasItemActionUnlocked(action.RowId);
}
- return this.HasItemActionUnlocked(action.RowId);
+ var cardId = item.AdditionalData;
+ var card = this.Plugin.Interface.Data.GetExcelSheet().GetRow(cardId);
+ return card != null && this.HasCard((ushort)card.RowId);
}
private bool HasItemActionUnlocked(long itemActionId) {
- return this.hasItemActionUnlocked(itemActionId) == 1;
+ return this._hasItemActionUnlocked(itemActionId) == 1;
}
private bool HasCard(ushort cardId) {
- return this.hasCard(this.cardStaticAddr, cardId) == 1;
+ return this._hasCard(this._cardStaticAddr, cardId) == 1;
}
}
}
diff --git a/GoodMemory/GoodMemory.csproj b/GoodMemory/GoodMemory.csproj
index 0bb4bc0..7c05cd1 100644
--- a/GoodMemory/GoodMemory.csproj
+++ b/GoodMemory/GoodMemory.csproj
@@ -1,64 +1,29 @@
-
-
-
- Debug
- AnyCPU
- {2B53DAAE-5F20-4EAF-8BC5-97FCE68C1738}
- Library
- Properties
- GoodMemory
- GoodMemory
- v4.8
- 512
- true
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- true
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- true
-
-
-
- $(AppData)\XIVLauncher\addon\Hooks\Dalamud.dll
-
-
- $(AppData)\XIVLauncher\addon\Hooks\Lumina.dll
-
-
- $(AppData)\XIVLauncher\addon\Hooks\Lumina.Excel.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ 8
+ enable
+ 1.0.4
+ 1.0.4
+ net48
+ true
+ x64
+
+
+
+ $(AppData)\XIVLauncher\addon\Hooks\Dalamud.dll
+ false
+
+
+ $(AppData)\XIVLauncher\addon\Hooks\Lumina.dll
+ false
+
+
+ $(AppData)\XIVLauncher\addon\Hooks\Lumina.Excel.dll
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/GoodMemory/GoodMemory.json b/GoodMemory/GoodMemory.json
deleted file mode 100644
index c46e447..0000000
--- a/GoodMemory/GoodMemory.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "Author": "ascclemens",
- "Name": "Good Memory",
- "Description": "Adds an indicator in item tooltips to show whether you have acquired that item.",
- "InternalName": "GoodMemory",
- "AssemblyVersion": "1.0.4",
- "RepoUrl": "https://git.sr.ht/~jkcclemens/GoodMemory",
- "ApplicableVersion": "any",
- "DalamudApiLevel": 2
-}
diff --git a/GoodMemory/GoodMemory.yaml b/GoodMemory/GoodMemory.yaml
new file mode 100644
index 0000000..719e67e
--- /dev/null
+++ b/GoodMemory/GoodMemory.yaml
@@ -0,0 +1,8 @@
+author: ascclemens
+name: GoodMemory
+description: |-
+ Adds an indicator in item tooltips to show whether you have acquired that item.
+
+ This indicator is in the item's description near the bottom and only appears for
+ items that are unlockable, such as orchestrion rolls, minions, etc.
+repo_url: https://git.sr.ht/~jkcclemens/GoodMemory
diff --git a/GoodMemory/Plugin.cs b/GoodMemory/Plugin.cs
index 4774ccf..c8b5e71 100644
--- a/GoodMemory/Plugin.cs
+++ b/GoodMemory/Plugin.cs
@@ -9,14 +9,14 @@ using System.Text;
namespace GoodMemory {
public class Plugin : IDalamudPlugin {
- private bool disposedValue;
+ private bool _disposedValue;
public string Name => "Good Memory";
- public DalamudPluginInterface Interface { get; private set; }
- private GameFunctions Functions { get; set; }
- private readonly IntPtr alloc = Marshal.AllocHGlobal(4096);
- private Hook tooltipHook;
+ public DalamudPluginInterface Interface { get; private set; } = null!;
+ private GameFunctions Functions { get; set; } = null!;
+ private readonly IntPtr _alloc = Marshal.AllocHGlobal(4096);
+ private Hook? _tooltipHook;
private unsafe delegate IntPtr TooltipDelegate(IntPtr a1, uint** a2, byte*** a3);
@@ -27,46 +27,48 @@ namespace GoodMemory {
}
protected virtual void Dispose(bool disposing) {
- if (!this.disposedValue) {
- if (disposing) {
- this.tooltipHook?.Dispose();
- Marshal.FreeHGlobal(this.alloc);
- }
-
- this.disposedValue = true;
+ if (this._disposedValue) {
+ return;
}
+
+ if (disposing) {
+ this._tooltipHook?.Dispose();
+ Marshal.FreeHGlobal(this._alloc);
+ }
+
+ this._disposedValue = true;
}
public void Dispose() {
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
+ Dispose(true);
GC.SuppressFinalize(this);
}
private void SetUpHook() {
- IntPtr tooltipPtr = this.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 50 48 8B 42 ??");
+ var tooltipPtr = this.Interface.TargetModuleScanner.ScanText("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 50 48 8B 42 ??");
if (tooltipPtr == IntPtr.Zero) {
throw new ApplicationException("Could not set up tooltip hook because of null pointer");
}
unsafe {
- this.tooltipHook = new Hook(tooltipPtr, new TooltipDelegate(this.OnTooltip));
+ this._tooltipHook = new Hook(tooltipPtr, new TooltipDelegate(this.OnTooltip));
}
- this.tooltipHook.Enable();
+ this._tooltipHook.Enable();
}
- private unsafe void TooltipLogic(IntPtr a1, uint** a2, byte*** a3) {
+ private unsafe void TooltipLogic(uint** a2, byte*** a3) {
// this can be replaced with a mid-func hook when reloaded hooks is in dalamud
// but for now, do the same logic the func does and replace the text after
- uint* v3 = *(a2 + 4);
- uint v9 = *(v3 + 4);
+ var v3 = *(a2 + 4);
+ var v9 = *(v3 + 4);
if ((v9 & 2) == 0) {
return;
}
- ulong itemId = this.Interface.Framework.Gui.HoveredItem;
+ var itemId = this.Interface.Framework.Gui.HoveredItem;
if (itemId > 2_000_000) {
return;
}
@@ -75,19 +77,19 @@ namespace GoodMemory {
itemId -= 1_000_000;
}
- Item item = this.Interface.Data.GetExcelSheet- ().GetRow((uint)itemId);
+ var item = this.Interface.Data.GetExcelSheet
- ().GetRow((uint)itemId);
if (item == null) {
return;
}
// get the pointer to the text
- byte** startPtr = *(a3 + 4) + 13;
+ var startPtr = *(a3 + 4) + 13;
// get the text pointer
- byte* start = *startPtr;
+ var start = *startPtr;
// work around function being called twice
- if (start == (byte*)this.alloc) {
+ if (start == (byte*)this._alloc) {
return;
}
@@ -95,7 +97,7 @@ namespace GoodMemory {
// Faded Copies
if (item.FilterGroup == 12 && item.ItemUICategory.Value?.RowId == 94 && item.LevelItem.Value?.RowId == 1) {
- Item[] recipeResults = this.Interface.Data.GetExcelSheet()
+ var recipeResults = this.Interface.Data.GetExcelSheet()
.Where(recipe => recipe.UnkStruct5.Any(ritem => ritem.ItemIngredient == item.RowId))
.Select(recipe => recipe.ItemResult.Value)
.Where(result => result != null)
@@ -103,16 +105,16 @@ namespace GoodMemory {
overwrite = ReadString(start);
- foreach (Item result in recipeResults) {
- ItemAction resultAction = result.ItemAction?.Value;
+ foreach (var result in recipeResults) {
+ var resultAction = result.ItemAction?.Value;
if (!ActionTypeExt.IsValidAction(resultAction)) {
continue;
}
Debug.Assert(resultAction != null, nameof(resultAction) + " != null");
- uint orchId = resultAction.Data[0];
- Orchestrion orch = this.Interface.Data.GetExcelSheet().GetRow(orchId);
+ uint orchId = resultAction!.Data[0];
+ var orch = this.Interface.Data.GetExcelSheet().GetRow(orchId);
if (orch == null) {
continue;
}
@@ -120,7 +122,7 @@ namespace GoodMemory {
this.AppendIfAcquired(ref overwrite, result, orch.Name);
}
} else {
- ItemAction action = item.ItemAction?.Value;
+ var action = item.ItemAction?.Value;
if (!ActionTypeExt.IsValidAction(action)) {
return;
@@ -134,23 +136,23 @@ namespace GoodMemory {
}
// write our replacement text into our own managed memory (4096 bytes)
- WriteString((byte*)this.alloc, overwrite, true);
+ WriteString((byte*)this._alloc, overwrite, true);
// overwrite the original pointer with our own
- *startPtr = (byte*)this.alloc;
+ *startPtr = (byte*)this._alloc;
}
private unsafe IntPtr OnTooltip(IntPtr a1, uint** a2, byte*** a3) {
try {
- this.TooltipLogic(a1, a2, a3);
+ this.TooltipLogic(a2, a3);
} catch (Exception ex) {
PluginLog.Error($"Could not modify tooltip:\n{ex.Message}\n{ex.StackTrace}");
}
- return this.tooltipHook.Original(a1, a2, a3);
+ return this._tooltipHook!.Original(a1, a2, a3);
}
- private void AppendIfAcquired(ref string txt, Item item, string name = null) {
+ private void AppendIfAcquired(ref string txt, Item item, string? name = null) {
string yes;
string no;
string acquired;
@@ -158,7 +160,6 @@ namespace GoodMemory {
string parenL;
string parenR;
switch (this.Interface.ClientState.ClientLanguage) {
- case Dalamud.ClientLanguage.English:
default:
acquired = "Acquired";
colon = ": ";
@@ -193,18 +194,16 @@ namespace GoodMemory {
break;
}
- string has = this.Functions.HasAcquired(item) ? yes : no;
- if (name != null) {
- txt = $"{txt}\n{acquired}{parenL}{name}{parenR}{colon}{has}";
- } else {
- txt = $"{txt}\n{acquired}{colon}{has}";
- }
+ var has = this.Functions.HasAcquired(item) ? yes : no;
+ txt = name == null
+ ? $"{txt}\n{acquired}{colon}{has}"
+ : $"{txt}\n{acquired}{parenL}{name}{parenR}{colon}{has}";
}
private unsafe static string ReadString(byte* ptr) {
- int offset = 0;
+ var offset = 0;
while (true) {
- byte b = *(ptr + offset);
+ var b = *(ptr + offset);
if (b == 0) {
break;
}
@@ -216,8 +215,8 @@ namespace GoodMemory {
}
private unsafe static void WriteString(byte* dst, string s, bool finalise = false) {
- byte[] bytes = Encoding.UTF8.GetBytes(s);
- for (int i = 0; i < bytes.Length; i++) {
+ var bytes = Encoding.UTF8.GetBytes(s);
+ for (var i = 0; i < bytes.Length; i++) {
*(dst + i) = bytes[i];
}
diff --git a/GoodMemory/Properties/AssemblyInfo.cs b/GoodMemory/Properties/AssemblyInfo.cs
deleted file mode 100644
index 9efa092..0000000
--- a/GoodMemory/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System.Resources;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("GoodMemory")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("GoodMemory")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("2b53daae-5f20-4eaf-8bc5-97fce68c1738")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.4")]
-[assembly: AssemblyFileVersion("1.0.4")]
-[assembly: NeutralResourcesLanguage("en-GB")]