Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi action support #15

Merged
merged 4 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ReleaseCheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ jobs:
- name: Build
run: |
dotnet build --no-restore --configuration Release
- name: Tests
run: |
dotnet test
3 changes: 3 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ jobs:
- name: Build
run: |
dotnet build --no-restore --configuration Release
- name: Tests
run: |
dotnet test
66 changes: 63 additions & 3 deletions OpenerCreator/Actions/GroupOfActions.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Interface.Textures;
using OpenerCreator.Helpers;

namespace OpenerCreator.Actions;

public readonly struct GroupOfActions(string name, string iconLocation, IEnumerable<uint> actions, bool isGCD = true)
public readonly struct GroupOfActions(int id, string name, Jobs job, IEnumerable<uint> actions, bool isGCD = true)

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'name' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'job' is unread.

Check warning on line 9 in OpenerCreator/Actions/GroupOfActions.cs

View workflow job for this annotation

GitHub Actions / build

Parameter 'isGCD' is unread.
{
public ISharedImmediateTexture texture => OpenerCreator.TextureProvider.GetFromGame(iconLocation);
public ISharedImmediateTexture texture => throw new NotImplementedException();

public bool isMember(uint a)
public bool IsMember(uint a)
{
return actions.Contains(a);
}

public bool HasId(int i)
{
return id == i;
}

public static IEnumerable<GroupOfActions> DefaultGroups()
{
return new[]
{
new GroupOfActions(
-1,
"Dancer Steps",
Jobs.DNC,
new List<uint>
{
15999, // Emboite
16000, // Entrechat
160001, // Jete
160002 // Pirouette
}
),
new GroupOfActions(
-2,
"Mudras",
Jobs.NIN,
new List<uint>
{
2259, // Ten
18805, // Ten
2261, // Chi
18806, // Chi
2263, // Jin
18807 // Jin
}
),
new GroupOfActions(
-3,
"Refulgent Arrow Proc",
Jobs.BRD,
new List<uint>
{
16495, // Burst Shot
7409 // Refulgent Arrow
}
),
new GroupOfActions(
-4,
"Venthunder/Veraero",
Jobs.RDM,
new List<uint>
{
25855, // Verthunder III
25855 // Veraero III
}
)
};
}
}
17 changes: 4 additions & 13 deletions OpenerCreator/Actions/PvEActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public class PvEActions : IActionManager
private static readonly object LockObject = new();
private readonly IEnumerable<LuminaAction> actionsSheet;
private readonly Dictionary<uint, LuminaAction> actionsSheetDictionary;
private readonly IEnumerable<GroupOfActions> groupOfActions;

private PvEActions()
{
Expand All @@ -22,14 +21,6 @@ private PvEActions()
.ToList();
actionsSheetDictionary = pve.ToDictionary(a => a.RowId);
actionsSheet = pve;
groupOfActions = new[]
{
new GroupOfActions(
"Dancer Steps",
"lmao",
new List<uint> { 1, 2, 3, 4, 5 }
)
};
}

public static uint TrueNorthId => 7546;
Expand Down Expand Up @@ -62,11 +53,11 @@ public bool SameActionsByName(string name, uint aId)
return GetActionName(aId).Contains(name, StringComparison.CurrentCultureIgnoreCase);
}

public List<uint> ActionsIdList(ActionTypes actionType)
public List<int> ActionsIdList(ActionTypes actionType)
{
return actionsSheet
.Where(a => ActionTypesExtension.GetType(a) == actionType || actionType == ActionTypes.ANY)
.Select(a => a.RowId)
.Select(a => (int)a.RowId)
.ToList();
}

Expand All @@ -83,7 +74,7 @@ public LuminaAction GetAction(uint id)
}


public List<uint> GetNonRepeatedActionsByName(string name, Jobs job, ActionTypes actionType)
public List<int> GetNonRepeatedActionsByName(string name, Jobs job, ActionTypes actionType)
{
return actionsSheet
.AsParallel()
Expand All @@ -94,7 +85,7 @@ public List<uint> GetNonRepeatedActionsByName(string name, Jobs job, ActionTypes
&& a.ClassJobCategory.Value.Name.ToString().Contains(job.ToString()))
|| job == Jobs.ANY)
)
.Select(a => a.RowId)
.Select(a => (int)a.RowId)
.OrderBy(id => id)
.ToList();
}
Expand Down
16 changes: 8 additions & 8 deletions OpenerCreator/Helpers/LoadedActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace OpenerCreator.Helpers;
internal class LoadedActions
{
private readonly HashSet<int> wrongActionsIndex = [];
private List<uint> actions = [];
public string Name = ""; // needs to be public for ImGui refs
private List<int> actions = []; // int instead of uint until c# has tagged unions
public string Name = ""; // needs to be public for ImGui refs


internal bool IsWrongActionAt(int i)
Expand All @@ -31,12 +31,12 @@ internal int ActionsCount()
return actions.Count;
}

internal uint GetActionAt(int i)
internal int GetActionAt(int i)
{
return actions[i];
}

internal void AddAction(uint action)
internal void AddAction(int action)
{
actions.Add(action);
}
Expand All @@ -46,12 +46,12 @@ internal void RemoveActionAt(int i)
actions.RemoveAt(i);
}

internal void InsertActionAt(int i, uint action)
internal void InsertActionAt(int i, int action)
{
actions.Insert(i, action);
}

internal List<uint> GetActionsByRef()
internal List<int> GetActionsByRef()
{
return actions;
}
Expand All @@ -61,7 +61,7 @@ internal void ClearActions()
actions.Clear();
}

internal void AddActionsByRef(List<uint> l)
internal void AddActionsByRef(List<int> l)
{
actions = l;
}
Expand All @@ -73,6 +73,6 @@ internal bool HasName()

public bool HasTrueNorth()
{
return actions.Contains(PvEActions.TrueNorthId);
return actions.Contains((int)PvEActions.TrueNorthId);
}
}
10 changes: 5 additions & 5 deletions OpenerCreator/Hooks/OnUsedActionHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class UsedActionHook : IDisposable
private const int MaxItemCount = 50;

private readonly ExcelSheet<LuminaAction>? sheet = OpenerCreator.DataManager.GetExcelSheet<LuminaAction>();
private readonly List<uint> used = new(MaxItemCount);
private readonly List<int> used = new(MaxItemCount);
private readonly Hook<UsedActionDelegate>? usedActionHook;
private bool ignoreTrueNorth;

Expand Down Expand Up @@ -82,8 +82,8 @@ private void DetourUsedAction(
var player = OpenerCreator.ClientState.LocalPlayer;
if (player == null || sourceId != player.EntityId) return;

var actionId = (uint)Marshal.ReadInt32(effectHeader, 0x8);
var action = sheet!.GetRow(actionId);
var actionId = Marshal.ReadInt32(effectHeader, 0x8);
var action = sheet!.GetRow((uint)actionId);
var isActionTrueNorth = actionId == PvEActions.TrueNorthId;
var analyseWhenTrueNorth = !(ignoreTrueNorth && isActionTrueNorth); //nand
if (action != null && PvEActions.IsPvEAction(action) && analyseWhenTrueNorth)
Expand All @@ -98,7 +98,7 @@ private void DetourUsedAction(
var loadedLength = OpenerManager.Instance.Loaded.Count;
var index = loadedLength - nActions;
var intendedAction = OpenerManager.Instance.Loaded[index];
var intendedName = PvEActions.Instance.GetActionName(intendedAction);
var intendedName = PvEActions.Instance.GetActionName((uint)intendedAction);
if (OpenerCreator.Config.StopAtFirstMistake &&
!OpenerManager.Instance.AreActionsEqual(intendedAction, intendedName, actionId)
)
Expand All @@ -107,7 +107,7 @@ private void DetourUsedAction(
var f = new Feedback();
f.AddMessage(
Feedback.MessageType.Error,
$"Difference in action {index + 1}: Substituted {intendedName} for {PvEActions.Instance.GetActionName(actionId)}"
$"Difference in action {index + 1}: Substituted {intendedName} for {PvEActions.Instance.GetActionName((uint)actionId)}"
);
provideFeedback(f);
StopRecording();
Expand Down
46 changes: 24 additions & 22 deletions OpenerCreator/Managers/OpenerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ public class OpenerManager(IActionManager actions)
{
private static OpenerManager? SingletonInstance;
private static readonly object LockObject = new();
private readonly Dictionary<Jobs, Dictionary<string, List<uint>>> defaultOpeners = new();
private readonly Dictionary<Jobs, Dictionary<string, List<uint>>> openers = new();
private readonly Dictionary<Jobs, Dictionary<string, List<int>>> defaultOpeners = new();
private readonly Dictionary<Jobs, Dictionary<string, List<int>>> openers = new();

private OpenerManager(IActionManager actions, ValueTuple _) : this(actions)
{
Expand All @@ -23,7 +23,7 @@ private OpenerManager(IActionManager actions, ValueTuple _) : this(actions)
"openers.json"));
}

public List<uint> Loaded { get; set; } = [];
public List<int> Loaded { get; set; } = [];
private string OpenersFile { get; init; } = "empty";

public static OpenerManager Instance
Expand All @@ -42,28 +42,28 @@ public static OpenerManager Instance
}
}

public void AddOpener(string name, Jobs job, IEnumerable<uint> actions)
public void AddOpener(string name, Jobs job, IEnumerable<int> opener)
{
if (!openers.TryGetValue(job, out var value))
{
value = new Dictionary<string, List<uint>>();
value = new Dictionary<string, List<int>>();
openers[job] = value;
}

value[name] = [..actions];
value[name] = [..opener];
}

public List<Tuple<Jobs, List<string>>> GetDefaultNames()
{
return defaultOpeners.Select(x => Tuple.Create(x.Key, x.Value.Keys.ToList())).ToList();
}

public List<uint> GetDefaultOpener(string name, Jobs job)
public List<int> GetDefaultOpener(string name, Jobs job)
{
return [..defaultOpeners[job][name]];
}

public List<uint> GetOpener(string name, Jobs job)
public List<int> GetOpener(string name, Jobs job)
{
return [..openers[job][name]];
}
Expand All @@ -82,7 +82,7 @@ public void DeleteOpener(string name, Jobs job)
}
}

public void Compare(List<uint> used, Action<Feedback> provideFeedback, Action<int> wrongAction)
public void Compare(List<int> used, Action<Feedback> provideFeedback, Action<int> wrongAction)
{
var feedback = new Feedback();
used = used.Take(Loaded.Count).ToList();
Expand All @@ -106,7 +106,7 @@ public void Compare(List<uint> used, Action<Feedback> provideFeedback, Action<in
{
error = true;
feedback.AddMessage(Feedback.MessageType.Error,
$"Difference in action {i + 1}: Substituted {intended} for {actions.GetActionName(actual)}");
$"Difference in action {i + 1}: Substituted {intended} for {actions.GetActionName((uint)actual)}");
wrongAction(openerIndex);

if (ShouldShift(openerIndex, size, used[i])) shift++;
Expand All @@ -126,40 +126,42 @@ public void Compare(List<uint> used, Action<Feedback> provideFeedback, Action<in
}

private bool AreActionsEqual(
IReadOnlyList<uint> used, int openerIndex, int usedIndex, out string intended, out uint actual)
IReadOnlyList<int> used, int openerIndex, int usedIndex, out string intended, out int actualId)
{
var intendedId = Loaded[openerIndex];
intended = actions.GetActionName(intendedId);
actual = used[usedIndex];
intended = actions.GetActionName((uint)intendedId);
actualId = used[usedIndex];

return AreActionsEqual(intendedId, intended, actual);
return AreActionsEqual(intendedId, intended, actualId);
}

public bool AreActionsEqual(uint intendedId, string intendedName, uint actualId)
public bool AreActionsEqual(int intendedId, string intendedName, int actualId)
{
if (intendedId < 0)
return GroupOfActions.DefaultGroups().First(g => g.HasId(intendedId)).IsMember((uint)actualId);
return intendedId == actualId ||
intendedId == IActionManager.CatchAllActionId ||
actions.SameActionsByName(intendedName, actualId);
actions.SameActionsByName(intendedName, (uint)actualId);
}

private bool ShouldShift(int openerIndex, int size, uint usedValue)
private bool ShouldShift(int openerIndex, int size, int usedValue)
{
var nextIntended = actions.GetActionName(Loaded[openerIndex]);
var nextIntended = actions.GetActionName((uint)Loaded[openerIndex]);
return openerIndex + 1 < size &&
(Loaded[openerIndex + 1] == usedValue || actions.SameActionsByName(nextIntended, usedValue));
(Loaded[openerIndex + 1] == usedValue || actions.SameActionsByName(nextIntended, (uint)usedValue));
}

private static Dictionary<Jobs, Dictionary<string, List<uint>>> LoadOpeners(string path)
private static Dictionary<Jobs, Dictionary<string, List<int>>> LoadOpeners(string path)
{
try
{
var jsonData = File.ReadAllText(path);
return JsonSerializer.Deserialize<Dictionary<Jobs, Dictionary<string, List<uint>>>>(jsonData)!;
return JsonSerializer.Deserialize<Dictionary<Jobs, Dictionary<string, List<int>>>>(jsonData)!;
}
catch (Exception e)
{
OpenerCreator.PluginLog.Error("Failed to load Openers", e);
return new Dictionary<Jobs, Dictionary<string, List<uint>>>();
return new Dictionary<Jobs, Dictionary<string, List<int>>>();
}
}

Expand Down
12 changes: 12 additions & 0 deletions OpenerCreator/OpenerCreator.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<Platforms>x64</Platforms>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<Import Project="Dalamud.Plugin.Bootstrap.targets"/>

<PropertyGroup>
Expand All @@ -13,6 +24,7 @@
<IsPackable>false</IsPackable>
</PropertyGroup>


<ItemGroup>
<Reference Include="FFXIVClientStructs">
<HintPath>$(DalamudLibPath)FFXIVClientStructs.dll</HintPath>
Expand Down
Loading