-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathdllmain.cpp
298 lines (271 loc) · 16 KB
/
dllmain.cpp
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#include <fstream>
#include <queue>
#include <functional>
#include <random>
#include <iostream>
#include <cmath>
#include <windows.h>
#include <Shlwapi.h>
#include <safetyhook.hpp>
#include "json/json.hpp"
#include "sol/sol.hpp"
#include "loader.h"
#include "ghidra_export.h"
#include "util.h"
#include <thread>
#include "game_utils.h"
#include "lua_core.h"
#include "lua_core_ffi.h"
#include "lua_register.h"
#include "lua_thread.h"
#include "hook_monster.h"
#include "hook_animals.h"
#include "hook_camera.h"
#include "hook_hit.h"
#include "hook_shlp.h"
#include "hook_frame.h"
#include "general.h"
#include <future>
using namespace loader;
SafetyHookInline g_hook_time;
#pragma region Basic data processing program
static void MassageCommand() {
void* MassagePlot = *(undefined**)MH::World::Message;
if (MassagePlot != nullptr) {
string Massage = offsetPtr<char>(MassagePlot, 0xC0);
string::size_type idx;
//执行实时命令
idx = Massage.find("luac:");
if (idx != string::npos) {
string command = Massage.substr(Massage.find("luac:") + 5);
framework_logger->info("执行游戏内发出的Lua实时指令: {}", command);
int err = 0;
err = luaL_dostring(LuaCore::Lc, command.c_str());
if (err != 0)
{
int type = lua_type(LuaCore::Lc, -1);
if (type == 4) {
string error = lua_tostring(LuaCore::Lc, -1);
LuaCore::LuaErrorRecord(error);
}
}
*offsetPtr<char>(MassagePlot, 0xC0) = *"";
}
//重载虚拟机
idx = Massage.find("reload ");
if (idx != string::npos) {
string luae = Massage.substr(Massage.find("reload ") + 7);
std::map<string, LuaCore::LuaScriptData>::iterator it;
it = LuaCore::LuaScript.find(luae);
if (it != LuaCore::LuaScript.end()) {
framework_logger->info("重载脚本{}的Lua虚拟机", luae);
// 注销hook函数
hook_general::clearLuaHook(LuaCore::LuaScript[luae].L);
lua_close(LuaCore::LuaScript[luae].L);
LuaCore::LuaScript[luae].L = luaL_newstate();
luaL_openlibs(LuaCore::LuaScript[luae].L);
registerFunc(LuaCore::LuaScript[luae].L, luae);
lua_thread::Registe(LuaCore::LuaScript[luae].L);
hook_monster::Registe(LuaCore::LuaScript[luae].L);
hook_animals::Registe(LuaCore::LuaScript[luae].L);
hook_camera::Registe(LuaCore::LuaScript[luae].L);
hook_hit::Registe(LuaCore::LuaScript[luae].L);
hook_frame::Registe(LuaCore::LuaScript[luae].L);
hook_shlp::Registe(LuaCore::LuaScript[luae].L);
hook_general::Registe(LuaCore::LuaScript[luae].L);
LuaCore::reloadTime = time(nullptr);;
if (LuaCore::Lua_Run(LuaCore::LuaScript[luae].L, luae) != 1) {
engine_logger->warn("脚本{}重载后出现异常,已停止该脚本继续运行", luae);
LuaCore::LuaScript[luae].start = false;
}
else {
engine_logger->info("脚本{}已完成重载操作,代码运行正常", luae);
string message = "脚本" + luae + "已完成重载操作";
MH::Chat::ShowGameMessage(*(undefined**)MH::Chat::MainPtr, (undefined*)&utils::string_To_UTF8(message)[0], -1, -1, 0);
LuaCore::LuaScript[luae].start = true;
LuaCore::run("on_init", LuaCore::LuaScript[luae].L);
}
}
*offsetPtr<char>(MassagePlot, 0xC0) = *"";
}
}
}
//数据更新程序
static void updata() {
//地图更新时清理数据
void* TimePlot = utils::GetPlot(*(undefined**)MH::Player::PlayerBasePlot, { 0x50, 0x7D20 });
if (TimePlot != nullptr && Chronoscope::NowTime > *offsetPtr<float>(TimePlot, 0xC24)) {
framework_logger->info("游戏内发生场景变换,更新框架缓存数据");
//清除计时器数据
Chronoscope::ChronoscopeList.clear();
//清除按键数据
Keyboard::TempData::t_KeyCount.clear();
Keyboard::TempData::t_KeyDown.clear();
//清除Xbox手柄数据
XboxPad::TempData::t_KeyCount.clear();
XboxPad::TempData::t_KeyDown.clear();
//钩子数据
hook_frame::SpeedList.clear();
engine_logger->info("运行脚本on_switch_scenes场景切换代码");
LuaCore::run("on_switch_scenes");
}
//更新计时器
Chronoscope::chronoscope();
//更新手柄数据
XboxPad::Updata();
//执行玩家消息指令
MassageCommand();
}
#pragma endregion
// 自定义的异常处理程序
LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo) {
if (exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
exceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO) {
// 在崩溃时记录日志
LuaCore::logger.saveLogToFile();
}
// 继续崩溃处理流程
return EXCEPTION_CONTINUE_SEARCH;
}
static void InitLogger() {
engine_logger->set_level(spdlog::level::info);
engine_logger->flush_on(spdlog::level::trace);
framework_logger->set_level(spdlog::level::info);
framework_logger->flush_on(spdlog::level::trace);
lua_logger->set_level(spdlog::level::info);
lua_logger->flush_on(spdlog::level::trace);
error_logger->set_level(spdlog::level::info);
error_logger->flush_on(spdlog::level::trace);
memory_logger->set_level(spdlog::level::info);
memory_logger->flush_on(spdlog::level::trace);
SetUnhandledExceptionFilter(ExceptionHandler);
}
void LoadLuaFiles() {
framework_logger->info("加载Lua文件");
LuaCore::Lua_Load("Lua\\", LuaCore::LuaFiles);
framework_logger->info("创建并运行实时脚本环境");
LuaCore::Lc = luaL_newstate();
}
void ApplyDelayedHooks() {
for (string file_name : LuaCore::LuaFiles) {
if (LuaCore::LuaScript[file_name].start && LuaCore::LuaScript[file_name].L != nullptr) {
lua_State* L = LuaCore::LuaScript[file_name].L;
lua_thread::Registe(L);
hook_monster::Registe(L);
hook_animals::Registe(L);
hook_camera::Registe(L);
hook_hit::Registe(L);
hook_frame::Registe(L);
hook_shlp::Registe(L);
hook_general::Registe(L);
}
}
framework_logger->info("开始执行创建各功能钩子代码");
hook_monster::Hook();
hook_animals::Hook();
hook_camera::Hook();
hook_hit::Hook();
hook_shlp::Hook();
hook_frame::Hook();
}
void ApplyTimeHooks() {
framework_logger->info("创建on_time钩子");
g_hook_time = safetyhook::create_inline(MH::World::MapClockLocal, reinterpret_cast<void*>(
+[](float* clock, float clock2) {
// 更新基础数据
updata();
// 运行 Lua 虚拟机
LuaCore::run("on_time");
return g_hook_time.call<int>(clock, clock2);
}));
}
void RegFuncs() {
luaL_openlibs(LuaCore::Lc);
registerFunc(LuaCore::Lc, "内置");
for (string file_name : LuaCore::LuaFiles) {
if (LuaCore::LuaScript[file_name].start && LuaCore::LuaScript[file_name].L != nullptr) {
lua_State* L = LuaCore::LuaScript[file_name].L;
luaL_openlibs(L);
engine_logger->info("为 {} 脚本注册引擎初始化函数", file_name);
registerFunc(L, file_name);
}
}
}
void RunLuaFiles() {
for (string file_name : LuaCore::LuaFiles) {
lua_State* L = LuaCore::LuaScript[file_name].L;
if (LuaCore::Lua_Run(L, file_name) != 1) {
engine_logger->warn("脚本{}运行过程中出现异常,已停止该脚本继续运行", file_name);
LuaCore::LuaScript[file_name].start = false;
}
}
}
void RunOnInit() {
engine_logger->info("运行脚本on_init初始化代码");
LuaCore::run("on_init");
}
__declspec(dllexport) extern bool Load()
{
LoadLuaFiles();
ApplyDelayedHooks();
RegFuncs();
RunLuaFiles();
RunOnInit();
ApplyTimeHooks();
return true;
}
/// <summary>
/// 添加 Dll 扫描目录
/// </summary>
/// <returns></returns>
BOOL AddDllSearchPath()
{
TCHAR currentPath[MAX_PATH];
TCHAR luaLibPath[MAX_PATH];
// 获取进程文件路径
DWORD dwResult = GetModuleFileName(NULL, currentPath, MAX_PATH);
if (dwResult == 0 || dwResult == MAX_PATH)
{
return FALSE;
}
// 去掉文件名部分
PathRemoveFileSpec(currentPath);
// 添加子目录
PathCombine(luaLibPath, currentPath, TEXT("Lua\\lib"));
// 添加DLL搜索路径
if (!SetDllDirectory(luaLibPath))
{
return FALSE;
}
return TRUE;
}
void mainThread() {
// 先延迟2秒加载,以便其他组件注册完毕
// TODO: 更高效的注册方法
LoadLuaFiles();
ApplyDelayedHooks();
std::this_thread::sleep_for(std::chrono::seconds(2));
RegFuncs();
RunLuaFiles();
RunOnInit();
ApplyTimeHooks();
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH: {
DisableThreadLibraryCalls(hModule);
if (!AddDllSearchPath()) { LOG(ERR) << "LuaEngine 错误:添加动态库扫描目录失败,已忽略。"; };
InitLogger();
// TODO: 在新线程中处理组件注册消息,以及完成模块初始化
std::thread tmain(mainThread);
tmain.detach();
break;
}
}
return TRUE;
}