using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using Dalamud.Game.ClientState.Keys; using Dalamud.Game.Command; using Dalamud.Game.NativeWrapper; using Dalamud.Hooking; using Dalamud.Plugin; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; using InteropGenerator.Runtime; namespace WorldMapFixer; public sealed class Plugin : IDalamudPlugin, IDisposable { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void FireCallbackDelegate(nint atkUnitBase, uint valueCount, nint values, bool close); public delegate void AreaMapReceiveEventDelegate(long p1, long p2, uint p3, long p4, nint p5); private const string commandName = "/wme"; public bool alertedDebugWindow; private bool areaMapVisible; private IKeyState keyState; private nint fireCallbackAddress; private FireCallbackDelegate fireCallback; public string Name => "World Map Enhancer"; private IDalamudPluginInterface PluginInterface { get; init; } private ICommandManager CommandManager { get; init; } private Configuration Configuration { get; init; } private PluginUI PluginUi { get; init; } public Hook MouseDelegateHook { get; private set; } public long rcStartTime { get; private set; } public Plugin(IDalamudPluginInterface pluginInterface) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown DalamudApi.Initialize(pluginInterface); PluginInterface = pluginInterface; CommandManager = DalamudApi.CommandManager ?? throw new ArgumentNullException("CommandManager"); pluginInterface.Create(Array.Empty()); DalamudApi.Framework.Update += new OnUpdateDelegate(Framework_UpdateNew); Configuration = (PluginInterface.GetPluginConfig() as Configuration) ?? new Configuration(); Configuration.Initialize(PluginInterface); PluginUi = new PluginUI(Configuration); keyState = DalamudApi.KeyState; CommandManager.AddHandler("/wme", new CommandInfo(new HandlerDelegate(OnCommand)) { HelpMessage = "Configuration for the right click behaviour" }); PluginInterface.UiBuilder.Draw += DrawUI; PluginInterface.UiBuilder.OpenConfigUi += DrawConfigUI; string text = "E8 ?? ?? ?? ?? 0F B6 E8 8B 44 24 20"; fireCallbackAddress = DalamudApi.SigScanner.ScanText(text); fireCallback = (FireCallbackDelegate)Marshal.GetDelegateForFunctionPointer(fireCallbackAddress, typeof(FireCallbackDelegate)); InstallMouseHook(); } private void Framework_UpdateNew(IFramework framework) { if (Configuration != null && Configuration.Enabled && DalamudApi.ClientState != null && DalamudApi.ClientState.IsLoggedIn) { CheckForMap(); } } private void InstallMouseHook() { string text = "40 55 56 57 48 8B EC 48 83 EC 70 0F B7 C2"; nint num = DalamudApi.SigScanner.ScanText(text); if (num != IntPtr.Zero) { DalamudApi.PluginLog.Debug("Hooking!", Array.Empty()); MouseDelegateHook = DalamudApi.Hooks.HookFromAddress((IntPtr)num, (AreaMapReceiveEventDelegate)Detour, (HookBackend)0); MouseDelegateHook?.Enable(); } } private void Detour(long p1, long p2, uint p3, long p4, nint p5) { Marshal.ReadIntPtr(p5); byte b = Marshal.ReadByte(p5, 6); byte b2 = Marshal.ReadByte(p5, 7); _ = DalamudApi.KeyState[(VirtualKey)162]; if (p2 == 4 && p3 == 16 && b == 1 && b2 != 1) { ZoomOutMap(); } MouseDelegateHook.Original(p1, p2, p3, p4, p5); } public unsafe Vector4 GetMapParams() { if (areaMapVisible) { AtkUnitBase* areaMapPointer = GetAreaMapPointer(); return new Vector4(((AtkResNode)((AtkUnitBase)areaMapPointer).RootNode).X, ((AtkResNode)((AtkUnitBase)areaMapPointer).RootNode).Y, (int)((AtkResNode)((AtkUnitBase)areaMapPointer).RootNode).GetWidth(), (int)((AtkResNode)((AtkUnitBase)areaMapPointer).RootNode).GetHeight()); } return new Vector4(float.MinValue, float.MinValue, float.MinValue, float.MinValue); } public unsafe static AtkValue* CreateAtkValueArray(params object[] values) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) AtkValue* ptr = (AtkValue*)Marshal.AllocHGlobal(values.Length * Unsafe.SizeOf()); if (ptr == null) { return null; } try { for (int i = 0; i < values.Length; i++) { object obj = values[i]; if (!(obj is uint uInt)) { if (!(obj is int num)) { if (!(obj is float num2)) { if (!(obj is bool flag)) { if (!(obj is string s)) { throw new ArgumentException($"Unable to convert type {obj.GetType()} to AtkValue"); } Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type, (ValueType)8); byte[] bytes = Encoding.UTF8.GetBytes(s); nint num3 = Marshal.AllocHGlobal(bytes.Length + 1); Marshal.Copy(bytes, 0, num3, bytes.Length); Marshal.WriteByte(num3, bytes.Length, 0); Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).String, CStringPointer.op_Implicit((byte*)num3)); } else { Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type, (ValueType)2); ((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Byte = (flag ? ((byte)1) : ((byte)0)); } } else { Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type, (ValueType)7); ((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Float = num2; } } else { Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type, (ValueType)3); ((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Int = num; } } else { Unsafe.Write(&((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type, (ValueType)5); ((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).UInt = uInt; } } return ptr; } catch { return null; } } public unsafe static bool GetUnitBase(string name, out AtkUnitBase* unitBase, int index = 1) { unitBase = GetUnitBase(name, index); return unitBase != null; } public unsafe static AtkUnitBase* GetUnitBase(string name, int index = 1) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return (AtkUnitBase*)Service.GameGui.GetAddonByName(name, index).Address; } public unsafe static void GenerateCallback(AtkUnitBase* unitBase, params object[] values) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) AtkValue* ptr = CreateAtkValueArray(values); if (ptr == null) { return; } try { ((AtkUnitBase)unitBase).FireCallback((uint)values.Length, ptr, false); } finally { for (int i = 0; i < values.Length; i++) { if ((int)((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).Type == 8) { Marshal.FreeHGlobal(new IntPtr(CStringPointer.op_Implicit(((AtkValue)((byte*)ptr + (nint)i * (nint)Unsafe.SizeOf())).String))); } } Marshal.FreeHGlobal(new IntPtr(ptr)); } } private unsafe AtkUnitBase* GetAreaMapPointer() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) AtkUnitBasePtr addonByName = DalamudApi.GameGui.GetAddonByName("AreaMap", 1); if (addonByName.Address != (IntPtr)IntPtr.Zero) { AtkUnitBase* address = (AtkUnitBase*)addonByName.Address; if (((AtkUnitBase)address).RootNode != null) { DalamudApi.PluginLog.Debug("PTR: " + (long)((AtkUnitBase)address).RootNode, Array.Empty()); return address; } DalamudApi.PluginLog.Debug("Null pointer.", Array.Empty()); return null; } DalamudApi.PluginLog.Debug("Null pointer.", Array.Empty()); return null; } private unsafe void CheckForMap() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) AtkUnitBasePtr addonByName = DalamudApi.GameGui.GetAddonByName("AreaMap", 1); if (addonByName.Address == (IntPtr)IntPtr.Zero) { return; } AtkUnitBase* address = (AtkUnitBase*)addonByName.Address; if (((AtkUnitBase)address).RootNode == null) { return; } if (((AtkUnitBase)address).IsVisible) { if (!areaMapVisible) { areaMapVisible = true; } } else if (areaMapVisible) { areaMapVisible = false; } } private void Framework_Update() { if (Configuration.Enabled && DalamudApi.ClientState.IsLoggedIn) { CheckForMap(); } } public void Dispose() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown PluginUi.Dispose(); CommandManager.RemoveHandler("/wme"); DalamudApi.Framework.Update -= new OnUpdateDelegate(Framework_UpdateNew); MouseDelegateHook.Dispose(); } private void OnCommand(string command, string args) { PluginUi.SettingsVisible = true; } private void DrawUI() { PluginUi.Draw(); } private unsafe void ZoomOutMap() { AtkUnitBase* unitBase = GetUnitBase("AreaMap"); if (unitBase == null) { DalamudApi.PluginLog.Debug("Null pointer to areamap. Going away", Array.Empty()); return; } uint valueCount = 1u; AtkValue* values = CreateAtkValueArray(5); fireCallback((nint)unitBase, valueCount, (nint)values, close: false); } private void DrawConfigUI() { PluginUi.SettingsVisible = true; } }