Skip to content

Commit

Permalink
MacroMate, reworked macro copying, extra copying settings
Browse files Browse the repository at this point in the history
  • Loading branch information
WorkingRobot committed Jul 27, 2024
1 parent f2d0373 commit 9537173
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 84 deletions.
7 changes: 7 additions & 0 deletions Craftimizer/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public enum CopyType
OpenWindow, // useful for big macros
CopyToMacro, // (add option for down or right) (max macro count; open copy-paste window if too much)
CopyToClipboard,
CopyToMacroMate
}

public CopyType Type { get; set; } = CopyType.OpenWindow;
Expand All @@ -137,6 +138,10 @@ public enum CopyType
public int StartMacroIdx { get; set; } = 1;
public int MaxMacroCount { get; set; } = 5;

// CopyToMacroMate
public string MacroMateName { get; set; } = "Craftimizer";
public string MacroMateParent { get; set; } = string.Empty;

// Add /nextmacro [down]
public bool UseNextMacro { get; set; }

Expand All @@ -156,6 +161,8 @@ public enum CopyType

// For SND; Cannot use CopyToMacro
public bool CombineMacro { get; set; }

public bool ShowCopiedMessage { get; set; } = true;
}

[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
Expand Down
2 changes: 2 additions & 0 deletions Craftimizer/Plugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public sealed class Plugin : IDalamudPlugin
public Hooks Hooks { get; }
public Chat Chat { get; }
public CommunityMacros CommunityMacros { get; }
public Ipc Ipc { get; }
public AttributeCommandManager AttributeCommandManager { get; }

public Plugin(IDalamudPluginInterface pluginInterface)
Expand All @@ -44,6 +45,7 @@ public Plugin(IDalamudPluginInterface pluginInterface)
Hooks = new();
Chat = new();
CommunityMacros = new();
Ipc = new();
AttributeCommandManager = new();

var assembly = Assembly.GetExecutingAssembly();
Expand Down
1 change: 1 addition & 0 deletions Craftimizer/Service.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public sealed class Service
public static WindowSystem WindowSystem => Plugin.WindowSystem;
public static Chat Chat => Plugin.Chat;
public static CommunityMacros CommunityMacros => Plugin.CommunityMacros;
public static Ipc Ipc => Plugin.Ipc;
#pragma warning restore CS8618

internal static void Initialize(Plugin plugin, IDalamudPluginInterface iface)
Expand Down
69 changes: 69 additions & 0 deletions Craftimizer/Utils/Ipc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Craftimizer.Plugin;
using Dalamud.Plugin;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using DotNext.Reflection;
using DotNext.Collections.Generic;

namespace Craftimizer.Utils;

public sealed class Ipc
{
[AttributeUsage(AttributeTargets.Property)]
private sealed class IPCCallAttribute(string? name) : Attribute
{
public string? Name { get; } = name;
}

public Ipc()
{
foreach (var prop in typeof(Ipc).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (prop.GetCustomAttribute<IPCCallAttribute>() is not { } attr)
continue;

if (prop.GetMethod is not { } getMethod)
throw new InvalidOperationException("Property must have a getter");

if (getMethod.GetCustomAttribute<CompilerGeneratedAttribute>() is null)
throw new InvalidOperationException("Property must have an auto getter");

var type = prop.PropertyType;

if (!typeof(Delegate).IsAssignableFrom(type))
throw new InvalidOperationException("Property type must be a delegate");

if (type.GetMethod("Invoke") is not { } typeMethod)
throw new InvalidOperationException("Delegate type has no Invoke");

var returnsVoid = typeMethod.ReturnType == typeof(void);

var propSubscriber = typeof(IDalamudPluginInterface).GetMethod("GetIpcSubscriber", typeMethod.GetParameters().Length + 1, [typeof(string)]);
if (propSubscriber is null)
throw new InvalidOperationException("GetIpcSubscriber method not found");

var callGateSubscriber = propSubscriber.MakeGenericMethod([.. typeMethod.GetParameterTypes(), returnsVoid ? typeof(int) : typeMethod.ReturnType]).Invoke(Service.PluginInterface, [attr.Name ?? prop.Name]);

if (callGateSubscriber is null)
throw new InvalidOperationException("CallGateSubscriber is null");

var invokeFunc = callGateSubscriber.GetType().GetMethod(returnsVoid ? "InvokeAction" : "InvokeFunc");
if (invokeFunc is null)
throw new InvalidOperationException("Subscriber Invoke method not found");

prop.SetValue(this, Delegate.CreateDelegate(type, callGateSubscriber, invokeFunc));

Log.Debug($"Bound {prop.Name} IPC to {type}");
}
}

[IPCCall("MacroMate.IsAvailable")]
public Func<bool> MacroMateIsAvailable { get; private set; } = null!;

[IPCCall("MacroMate.CreateOrUpdateMacro")]
public Func<string, string, string?, uint?, bool> MacroMateCreateMacro { get; private set; } = null!;

[IPCCall("MacroMate.ValidateGroupPath")]
public Func<string, (bool, string?)> MacroMateValidateGroupPath { get; private set; } = null!;
}
183 changes: 130 additions & 53 deletions Craftimizer/Utils/MacroCopy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,57 +30,72 @@ public static void Copy(IReadOnlyList<ActionType> actions)
return;
}

var config = Service.Configuration.MacroCopy;
var macros = GetMacros(actions, Service.Configuration.MacroCopy);

switch (Service.Configuration.MacroCopy.Type)
{
case MacroCopyConfiguration.CopyType.OpenWindow:
Service.Plugin.OpenMacroClipboard(macros);
break;
case MacroCopyConfiguration.CopyType.CopyToMacro:
CopyToMacro(macros);
break;
case MacroCopyConfiguration.CopyType.CopyToClipboard:
CopyToClipboard(macros);
break;
case MacroCopyConfiguration.CopyType.CopyToMacroMate:
CopyToMacroMate(macros[0]);
break;
}
}

private static List<string> GetMacros(IReadOnlyList<ActionType> actions, MacroCopyConfiguration config)
{
var mustSplit = (config.Type == MacroCopyConfiguration.CopyType.CopyToMacro || !config.CombineMacro) && config.Type != MacroCopyConfiguration.CopyType.CopyToMacroMate;

var macros = new List<string>();
var s = new List<string>();

var m = new List<string>();

for (var i = 0; i < actions.Count; ++i)
{
if (config.UseMacroLock && s.Count == 0)
{
s.Add("/mlock");
}
var a = actions[i];
var isLast = i == actions.Count - 1;
var isSecondLast = i == actions.Count - 2;

s.Add(GetActionCommand(actions[i], config));

if (config.Type == MacroCopyConfiguration.CopyType.CopyToMacro || !config.CombineMacro)
if (config.UseMacroLock && m.Count == 0)
m.Add("/mlock");

m.Add(GetActionCommand(a, config));

if (mustSplit && !isLast)
{
if (i != actions.Count - 1 && (i != actions.Count - 2 || config.ForceNotification))
var endLine = GetEndCommand(macros.Count, false, config);

if (endLine != null && m.Count == MacroSize - 1)
{
if (s.Count == MacroSize - 1)
{
if (GetEndCommand(macros.Count, false, config) is { } endCommand)
s.Add(endCommand);
}
if (s.Count == MacroSize)
{
macros.Add(string.Join(Environment.NewLine, s));
s.Clear();
}
if (!isSecondLast || config.ForceNotification)
m.Add(endLine);
}
}
}
if (s.Count > 0)
{
if (s.Count < MacroSize || (config.Type != MacroCopyConfiguration.CopyType.CopyToMacro && config.CombineMacro))

if (mustSplit && m.Count == MacroSize)
{
if (GetEndCommand(macros.Count, true, config) is { } endCommand)
s.Add(endCommand);
macros.Add(string.Join(Environment.NewLine, m));
m.Clear();
}
macros.Add(string.Join(Environment.NewLine, s));
}

switch (config.Type)
if (m.Count != MacroSize && m.Count != 0)
{
case MacroCopyConfiguration.CopyType.OpenWindow:
Service.Plugin.OpenMacroClipboard(macros);
break;
case MacroCopyConfiguration.CopyType.CopyToMacro:
CopyToMacro(macros, config);
break;
case MacroCopyConfiguration.CopyType.CopyToClipboard:
CopyToClipboard(macros);
break;
if (GetEndCommand(macros.Count, true, config) is { } endLine)
m.Add(endLine);
}

if (m.Count != 0)
macros.Add(string.Join(Environment.NewLine, m));

return macros;
}

private static string GetActionCommand(ActionType action, MacroCopyConfiguration config)
Expand Down Expand Up @@ -124,22 +139,27 @@ private static string GetActionCommand(ActionType action, MacroCopyConfiguration
return null;
}

private static void CopyToMacro(List<string> macros, MacroCopyConfiguration config)
private static void CopyToMacro(List<string> macros)
{
var config = Service.Configuration.MacroCopy;

int i, macroIdx;
for (
i = 0, macroIdx = config.StartMacroIdx;
i < macros.Count && i < config.MaxMacroCount && macroIdx < 100;
i++, macroIdx += config.CopyDown ? 10 : 1)
SetMacro(macroIdx, config.SharedMacro, macros[i]);
SetMacro(macroIdx, config.SharedMacro, macros[i], i + 1);

Service.Plugin.DisplayNotification(new()
if (config.ShowCopiedMessage)
{
Content = i > 1 ? "Copied macro to User Macros." : $"Copied {i} macros to User Macros.",
MinimizedText = i > 1 ? "Copied macro" : $"Copied {i} macros",
Title = "Macro Copied",
Type = NotificationType.Success
});
Service.Plugin.DisplayNotification(new()
{
Content = i > 1 ? "Copied macro to User Macros." : $"Copied {i} macros to User Macros.",
MinimizedText = i > 1 ? "Copied macro" : $"Copied {i} macros",
Title = "Macro Copied",
Type = NotificationType.Success
});
}
if (i < macros.Count)
{
Service.Plugin.OpenMacroClipboard(macros);
Expand All @@ -154,28 +174,85 @@ private static void CopyToMacro(List<string> macros, MacroCopyConfiguration conf
}
}

private static unsafe void SetMacro(int idx, bool isShared, string macroText)
private static unsafe void SetMacro(int idx, bool isShared, string macroText, int macroIdx)
{
if (idx >= 100 || idx < 0)
throw new ArgumentOutOfRangeException(nameof(idx), "Macro index must be between 0 and 99");

var set = isShared ? 1u : 0u;

var module = RaptureMacroModule.Instance();
var macro = module->GetMacro(isShared ? 1u : 0u, (uint)idx);
var macro = module->GetMacro(set, (uint)idx);
if (macro->IsEmpty())
{
macro->Name.SetString($"Craftimizer Macro {macroIdx}");
macro->SetIcon((uint)(macroIdx > 10 ? 66161 : (66161 + macroIdx)));
}
var text = Utf8String.FromString(macroText.ReplaceLineEndings("\n"));
module->ReplaceMacroLines(macro, text);
text->Dtor();
IMemorySpace.Free(text);

RaptureHotbarModule.Instance()->ReloadMacroSlots((byte)set, (byte)idx);
}

private static void CopyToClipboard(List<string> macros)
{
ImGui.SetClipboardText(string.Join(Environment.NewLine + Environment.NewLine, macros));
Service.Plugin.DisplayNotification(new()
if (Service.Configuration.MacroCopy.ShowCopiedMessage)
{
Service.Plugin.DisplayNotification(new()
{
Content = macros.Count == 1 ? "Copied macro to clipboard." : $"Copied {macros.Count} macros to clipboard.",
MinimizedText = macros.Count == 1 ? "Copied macro" : $"Copied {macros.Count} macros",
Title = "Macro Copied",
Type = NotificationType.Success
});
}
}

private static void CopyToMacroMate(string macro)
{
if (!Service.Ipc.MacroMateIsAvailable())
{
Content = macros.Count > 1 ? "Copied macro to clipboard." : $"Copied {macros.Count} macros to clipboard.",
MinimizedText = macros.Count > 1 ? "Copied macro" : $"Copied {macros.Count} macros",
Title = "Macro Copied",
Type = NotificationType.Success
});
Service.Plugin.DisplayNotification(new()
{
Content = "Please check if it installed and enabled.",
MinimizedText = "Macro Mate is unavailable",
Title = "Macro Mate Unavailable",
Type = NotificationType.Error
});
return;
}

var parentPath = Service.Configuration.MacroCopy.MacroMateParent;
if (string.IsNullOrWhiteSpace(parentPath))
parentPath = "/";

var (isValidParent, parentError) = Service.Ipc.MacroMateValidateGroupPath(parentPath);
if (!isValidParent)
{
Service.Plugin.DisplayNotification(new()
{
Content = parentError!,
MinimizedText = parentError,
Title = "Macro Mate Invalid Parent",
Type = NotificationType.Error
});
return;
}

Service.Ipc.MacroMateCreateMacro(Service.Configuration.MacroCopy.MacroMateName, macro, parentPath, null);

if (Service.Configuration.MacroCopy.ShowCopiedMessage)
{
Service.Plugin.DisplayNotification(new()
{
Content = "Copied macro to Macro Mate.",
MinimizedText = "Copied macro",
Title = "Macro Copied",
Type = NotificationType.Success
});
}
}
}
17 changes: 10 additions & 7 deletions Craftimizer/Windows/MacroClipboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public override void Draw()
private void DrawMacro(int idx, string macro)
{
using var id = ImRaii.PushId(idx);
using var panel = ImRaii2.GroupPanel($"Macro {idx + 1}", -1, out var availWidth);
using var panel = ImRaii2.GroupPanel(Macros.Count == 1 ? "Macro" : $"Macro {idx + 1}", -1, out var availWidth);

var cursor = ImGui.GetCursorPos();

Expand All @@ -56,13 +56,16 @@ private void DrawMacro(int idx, string macro)
if (buttonClicked)
{
ImGui.SetClipboardText(macro);
Service.Plugin.DisplayNotification(new()
if (Service.Configuration.MacroCopy.ShowCopiedMessage)
{
Content = $"Macro {idx + 1} copied to clipboard.",
MinimizedText = $"Copied macro {idx + 1}",
Title = "Macro Copied",
Type = NotificationType.Success
});
Service.Plugin.DisplayNotification(new()
{
Content = Macros.Count == 1 ? "Copied macro to clipboard." : $"Copied macro {idx + 1} to clipboard.",
MinimizedText = Macros.Count == 1 ? "Copied macro" : $"Copied macro {idx + 1}",
Title = "Macro Copied",
Type = NotificationType.Success
});
}
}
}
if (buttonHovered)
Expand Down
Loading

0 comments on commit 9537173

Please sign in to comment.