generated from karashiiro/DalamudPluginProjectTemplate
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Plugin.cs
161 lines (132 loc) · 4.89 KB
/
Plugin.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System;
using Dalamud.Plugin;
using FATEAutoSync.Attributes;
using System.Runtime.InteropServices;
using Dalamud.Game;
using Dalamud.Game.Gui;
using Dalamud.Logging;
using Dalamud.Game.Command;
namespace FATEAutoSync
{
public class Plugin : IDalamudPlugin
{
public string Name => "FATE AutoSync";
private DalamudPluginInterface pluginInterface;
private Framework framework;
private SigScanner sigScanner;
private PluginCommandManager<Plugin> commandManager;
private Configuration config;
// private PluginUI ui;
// Command execution
private delegate void ProcessChatBoxDelegate(IntPtr uiModule, IntPtr message, IntPtr unused, byte a4);
private delegate IntPtr GetUIModuleDelegate(IntPtr basePtr);
private ProcessChatBoxDelegate? ProcessChatBox;
private IntPtr uiModule = IntPtr.Zero;
// Our specific stuff
private IntPtr inFateAreaPtr = IntPtr.Zero;
private bool inFateArea = false;
private bool firstRun = true;
private ChatGui chat;
public Plugin(DalamudPluginInterface pluginInterface, ChatGui chat, Framework framework, CommandManager commands, SigScanner sigScanner)
{
this.pluginInterface = pluginInterface;
this.chat = chat;
this.framework = framework;
this.sigScanner = sigScanner;
config = this.pluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
config.Initialize(this.pluginInterface);
// this.ui = new PluginUI();
// this.pluginInterface.UiBuilder.OnBuildUi += this.ui.Draw;
framework.Update += Update;
commandManager = new PluginCommandManager<Plugin>(this, commands);
InitializePointers();
}
private void Update(Dalamud.Game.Framework framework)
{
if (!this.config.enabled) return;
var wasInFateArea = inFateArea;
inFateArea = Marshal.ReadByte(inFateAreaPtr) == 1;
if (wasInFateArea != inFateArea)
{
if (inFateArea)
{
if (firstRun)
{
chat.Print("FATE Auto Sync ran for the first time in this session (/fateautosync to toggle)");
firstRun = false;
}
ExecuteCommand("/levelsync on");
}
}
}
[Command("/fateautosync")]
[HelpMessage("Toggles the plug-in on and off.")]
public void ToggleCommand(string command, string args)
{
this.config.enabled = !this.config.enabled;
chat.Print($"Toggled FATE Auto Sync {(this.config.enabled ? "on" : "off")}");
}
// Courtesy of https://github.com/UnknownX7/QoLBar
private unsafe void InitializePointers()
{
// FATE pointer (thanks to Pohky#8008)
try
{
var sig = sigScanner.ScanText("80 3D ?? ?? ?? ?? ?? 0F 84 ?? ?? ?? ?? 48 8B 42 20");
inFateAreaPtr = sig + Marshal.ReadInt32(sig, 2) + 7;
chat.Print("Retrieved 'inFateAreaPtr' successfully");
chat.Print(inFateAreaPtr.ToString("X8"));
}
catch
{
PluginLog.Error("Failed loading 'inFateAreaPtr'");
}
// for ExecuteCommand
try
{
var getUIModulePtr = sigScanner.ScanText("E8 ?? ?? ?? ?? 48 83 7F ?? 00 48 8B F0");
var easierProcessChatBoxPtr = sigScanner.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9");
var uiModulePtr = sigScanner.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 8D 54 24 ?? 48 83 C1 10 E8");
var GetUIModule = Marshal.GetDelegateForFunctionPointer<GetUIModuleDelegate>(getUIModulePtr);
uiModule = GetUIModule(*(IntPtr*)uiModulePtr);
ProcessChatBox = Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(easierProcessChatBoxPtr);
}
catch { PluginLog.Error("Failed loading 'ExecuteCommand'"); }
}
public void ExecuteCommand(string command)
{
try
{
var bytes = System.Text.Encoding.UTF8.GetBytes(command);
var mem1 = Marshal.AllocHGlobal(400);
var mem2 = Marshal.AllocHGlobal(bytes.Length + 30);
Marshal.Copy(bytes, 0, mem2, bytes.Length);
Marshal.WriteByte(mem2 + bytes.Length, 0);
Marshal.WriteInt64(mem1, mem2.ToInt64());
Marshal.WriteInt64(mem1 + 8, 64);
Marshal.WriteInt64(mem1 + 8 + 8, bytes.Length + 1);
Marshal.WriteInt64(mem1 + 8 + 8 + 8, 0);
ProcessChatBox(uiModule, mem1, IntPtr.Zero, 0);
Marshal.FreeHGlobal(mem1);
Marshal.FreeHGlobal(mem2);
}
catch (Exception err) { chat.PrintError(err.Message); }
}
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (!disposing) return;
this.commandManager.Dispose();
this.pluginInterface.SavePluginConfig(this.config);
// this.pluginInterface.UiBuilder.OnBuildUi -= this.ui.Draw;
framework.Update -= Update;
this.pluginInterface.Dispose();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}