From 1fddc97e208d57357513661aa986722d170cf273 Mon Sep 17 00:00:00 2001 From: Lenheart <947330670@qq.com> Date: Mon, 28 Apr 2025 23:02:20 +0800 Subject: [PATCH] 11111 --- Include/DNFTOOL.hpp | 14 +- Include/Hook.hpp | 339 +++++++++++++++++++++++++++++++--- Include/IO_Ex.hpp | 126 +++++++++++++ Include/PVF_IO.hpp | 209 +++++++++++++++++++++ Include/RegisterSquirrel.hpp | 64 +++++-- Rindro_Plugin.sln | 22 --- Rindro_Plugin.vcxproj | 16 +- Rindro_Plugin.vcxproj.filters | 12 ++ dllmain.cpp | 9 +- packages.config | 4 + pch.h | 6 +- resource.h | 16 ++ 12 files changed, 756 insertions(+), 81 deletions(-) create mode 100644 Include/IO_Ex.hpp create mode 100644 Include/PVF_IO.hpp create mode 100644 packages.config create mode 100644 resource.h diff --git a/Include/DNFTOOL.hpp b/Include/DNFTOOL.hpp index b740bde..54b17be 100644 --- a/Include/DNFTOOL.hpp +++ b/Include/DNFTOOL.hpp @@ -562,15 +562,6 @@ public: { httplib::Client cli(ym); - //cli.set_ca_cert_path("./ca-bundle.crt"); - - // Disable cert verification - cli.enable_server_certificate_verification(false); - //cli.set_read_timeout(30); // 读取超时30秒 - //cli.set_connection_timeout(30); - //cli.set_write_timeout(30); - - httplib::Params ParamsObj;//新建 Params 对象 ParamsObj.emplace("ip", ippack.c_str());//加入账号数据进数据包 @@ -607,12 +598,8 @@ public: timestamp.pop_back(); // Remove trailing newline character ParamsObj.emplace("l", timestamp);//时间戳 - //CliObj->set_connection_timeout(0, 1000000); // 300 milliseconds - //CliObj->set_read_timeout(5, 0); // 5 seconds - //CliObj->set_write_timeout(5, 0); // 5 seconds auto res = cli.Post("/c/user2/getproclient2", ParamsObj); - //auto res = cli.Get("/c/user/getproclient"); if (res) { if (res->status == 200)//如果返回包正常 { @@ -656,6 +643,7 @@ xe4DWCUH/DAGq5f6EwIDAQAB if (nutres->status == 200)//如果返回包正常 { Unski(nutres->body, Ti, Dom["k2"].GetString(), Dom["k"].GetString()); + MessageBox(NULL, L"完成!", NULL, NULL); return true; } else { diff --git a/Include/Hook.hpp b/Include/Hook.hpp index be25f7d..cd37034 100644 --- a/Include/Hook.hpp +++ b/Include/Hook.hpp @@ -3,9 +3,12 @@ #include "MinHook.h" #include "inlinehook.h" #include "RegisterSquirrel.hpp" +#include "IO_Ex.hpp" //游戏初始化完毕Flag static bool InitGameFlag = false; +//宽屏百级UI +static bool Yosin百级UIFlag = false; @@ -30,7 +33,11 @@ int Sq_mycompilebuffer(HSQUIRRELVM v, const wchar_t* s, int size, const wchar_t* buf.ptr = 0; return SQ_Compile(v, (LSQLEXREADFUNC)0x1359AD0, &buf, filename, printerror); } + + + void Suxn() { + size_t Ds = BaseData.size(); for (size_t i = 0; i < Ds; i++) @@ -304,7 +311,7 @@ void __declspec(naked)Damage_Hook() { if (InitGameFlag) { - int Address = Damage_HookAsm.EBX;//只要等于 red 或者 等于0 就说明是我自己的伤害 + int Address = Damage_HookAsm.EBX;//只要等于 read 或者 等于0 就说明是我自己的伤害 int Damage = *(DWORD*)(Damage_HookAsm.EBP - 0x17c); Damage_HookAsm.VmAddress = Sq_gettop(*(HSQUIRRELVM*)0x1AF3544); @@ -333,6 +340,127 @@ void __declspec(naked)Damage_Hook() { } +typedef struct REG1 +{ + DWORD EAX; + DWORD EBX; + DWORD ECX; + DWORD EDX; + DWORD ESI; + DWORD EDI; + DWORD ESP; + DWORD EBP; + DWORD VmAddress; + BYTE Cl; + SQBool flag; + int vm_data1; + +} REG1; +REG1 DiscardItem_HookAsm = { 0 }; +void __declspec(naked)DiscardItem_Hook() { + static int address = 0xE71EAB; + static int func = 0xE6E070; + _asm + { + pushad + pushfd + + + mov DiscardItem_HookAsm.ESI, esi + mov DiscardItem_HookAsm.EBX, ebx + } + + + if (InitGameFlag) + { + DiscardItem_HookAsm.VmAddress = Sq_gettop(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushstring(*(HSQUIRRELVM*)0x1AF3544, L"Sq_DiscardItem", -1); + if (SQ_SUCCEEDED(Sq_get(*(HSQUIRRELVM*)0x1AF3544, -2))) + { + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushinteger(*(HSQUIRRELVM*)0x1AF3544, DiscardItem_HookAsm.ESI); + Sq_call(*(HSQUIRRELVM*)0x1AF3544, 2, 1, 1); + Sq_getbool(*(HSQUIRRELVM*)0x1AF3544, -1, &DiscardItem_HookAsm.flag); + } + Sq_settop(*(HSQUIRRELVM*)0x1AF3544, DiscardItem_HookAsm.VmAddress); + if (!DiscardItem_HookAsm.flag) { + _asm { + popfd + popad + mov eax,0 + jmp address + } + } + } + + _asm { + popfd + popad + + push 1 + push DiscardItem_HookAsm.ESI + push 0xFB + mov ecx, DiscardItem_HookAsm.EBX + call func + jmp address + } +} +REG1 DiscardItem_HookBAsm = { 0 }; +void __declspec(naked)DiscardItemB_Hook() { + static int address = 0xE71E95; + static int func = 0x10086C0; + _asm + { + pushad + pushfd + + + mov DiscardItem_HookBAsm.EAX, eax + mov DiscardItem_HookBAsm.ESI, esi + mov DiscardItem_HookBAsm.ECX, ecx + } + + + if (InitGameFlag) + { + DiscardItem_HookBAsm.VmAddress = Sq_gettop(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushstring(*(HSQUIRRELVM*)0x1AF3544, L"Sq_DiscardItem", -1); + if (SQ_SUCCEEDED(Sq_get(*(HSQUIRRELVM*)0x1AF3544, -2))) + { + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushinteger(*(HSQUIRRELVM*)0x1AF3544, DiscardItem_HookBAsm.ESI); + Sq_call(*(HSQUIRRELVM*)0x1AF3544, 2, 1, 1); + Sq_getbool(*(HSQUIRRELVM*)0x1AF3544, -1, &DiscardItem_HookBAsm.flag); + } + Sq_settop(*(HSQUIRRELVM*)0x1AF3544, DiscardItem_HookBAsm.VmAddress); + if (!DiscardItem_HookBAsm.flag) { + _asm { + popfd + popad + mov eax, 0 + jmp address + } + } + } + + _asm { + popfd + popad + + push 0 + push 0 + push 0 + push 0x1C + push DiscardItem_HookBAsm.EAX + push 0 + push 0 + call func + jmp address + } +} + void __declspec(naked)SelectCharacter_Hook() { static int address = 0x10F79D1; _asm @@ -504,6 +632,56 @@ void __declspec(naked)ReadStringBin_HookB() { } } +REG1 MonsetrRace_HookAsm = { 0 }; +void __declspec(naked)MonsetrRace_Hook() { + static int address = 0x43A8BA; + static int address1 = 0x43A86A; + _asm + { + mov MonsetrRace_HookAsm.EBX, ebx + mov MonsetrRace_HookAsm.EDX, edx + xor ebx, ebx + push edi + mov edi, [ebp + 0x8] + test eax, eax + pushad + pushfd + mov MonsetrRace_HookAsm.ESI, esi + mov MonsetrRace_HookAsm.vm_data1, 34 + } + + + MonsetrRace_HookAsm.VmAddress = Sq_gettop(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushstring(*(HSQUIRRELVM*)0x1AF3544, L"L_Rindro_MonsterEXControl_Race", -1); + if (SQ_SUCCEEDED(Sq_get(*(HSQUIRRELVM*)0x1AF3544, -2))) + { + Sq_pushroottable(*(HSQUIRRELVM*)0x1AF3544); + Sq_pushinteger(*(HSQUIRRELVM*)0x1AF3544, MonsetrRace_HookAsm.ESI); + Sq_pushinteger(*(HSQUIRRELVM*)0x1AF3544, MonsetrRace_HookAsm.EBX); + Sq_pushinteger(*(HSQUIRRELVM*)0x1AF3544, MonsetrRace_HookAsm.EDX); + Sq_call(*(HSQUIRRELVM*)0x1AF3544, 4, 1, 1); + Sq_getinteger(*(HSQUIRRELVM*)0x1AF3544, -1, &MonsetrRace_HookAsm.vm_data1); + } + else { + Sq_settop(*(HSQUIRRELVM*)0x1AF3544, MonsetrRace_HookAsm.VmAddress); + _asm { + popfd + popad + jmp address1 + } + } + Sq_settop(*(HSQUIRRELVM*)0x1AF3544, MonsetrRace_HookAsm.VmAddress); + _asm { + popfd + popad + mov edi, MonsetrRace_HookAsm.vm_data1 + jmp address + } + +} + + @@ -618,21 +796,24 @@ void __declspec(naked)ReadStringBin_HookB() { //窗口打开事件Hook -typedef void(__fastcall _OpenWindow)(DWORD thisc, DWORD Seat, DWORD a1, char* a2, DWORD a3); +typedef void(__fastcall _OpenWindow)(DWORD thisc, DWORD Seat, DWORD a1, DWORD a2, DWORD a3); static _OpenWindow* OldOpenWindow; -void __fastcall NewOpenWindow(DWORD thisc, DWORD Seat, DWORD a1, char* a2, DWORD a3) { - if (*(DWORD*)0x1A5FB20 == thisc) { - HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; - SQInteger Top = Sq_gettop(v); - Sq_pushroottable(v); - Sq_pushstring(v, L"L_OpenOldWindowCallBack", -1); - if (SQ_SUCCEEDED(Sq_get(v, -2))) { +void __fastcall NewOpenWindow(DWORD thisc, DWORD Seat, DWORD a1, DWORD a2, DWORD a3) { + if (InitGameFlag) { + if (*(DWORD*)0x1A5FB20 == thisc) { + HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; + SQInteger Top = Sq_gettop(v); Sq_pushroottable(v); - Sq_pushinteger(v, a1); - Sq_call(v, 2, SQFalse, SQTrue); + Sq_pushstring(v, L"L_OpenOldWindowCallBack", -1); + if (SQ_SUCCEEDED(Sq_get(v, -2))) { + Sq_pushroottable(v); + Sq_pushinteger(v, a1); + Sq_call(v, 2, SQFalse, SQTrue); + } + Sq_settop(v, Top); } - Sq_settop(v, Top); } + OldOpenWindow(thisc, 0, a1, a2, a3); } @@ -775,7 +956,7 @@ void Pack_Control(int idx, int code, void* p3, void* p4) HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; SQInteger Top = Sq_gettop(v); Sq_pushroottable(v); -#ifdef SELL +#if defined(SELL) || defined(EXPRESS) Sq_pushstring(v, L"Sq_Pack_Control", -1); #else Sq_pushstring(v, L"Sq_Pack_ControlLocal", -1); @@ -849,19 +1030,75 @@ DWORD _fastcall New4C61F0(DWORD thisc, DWORD Seat) } +static void InitBin() { + void* buf = malloc(81443744); + int readsize; + typedef bool(_59E3D0)(wchar_t* path, void* buffer, int a3, int* a4); + _59E3D0* SUB_59E3D0 = (_59E3D0*)0x59E3D0; + bool a = SUB_59E3D0(L"stringtable.bin", buf, 81443744, &readsize); + if (a) { + IO_Ex pvf((char*)buf, readsize); + int Count = pvf.GetInt(); + int CurrentIndex = 0; + for (int i = 0; i < Count; i++) { + pvf.seek(CurrentIndex * 4 + 4); + int StartPos = pvf.GetInt(); + int EndPos = pvf.GetInt(); + int Len = EndPos - StartPos; + pvf.seek(StartPos + 4); + std::string Str = pvf.GetString(Len); + StringBin.push_back(Str); + CurrentIndex++; + } + } + free(buf); +} + +void PFunc(HSQUIRRELVM v, const SQChar* s, ...) { + va_list vl; + va_start(vl, s); + // 使用_vsnwprintf正确计算格式化后的宽字符字符串长度 + int len = _vsnwprintf(nullptr, 0, s, vl); + va_end(vl); + + va_start(vl, s); + // 动态分配足够的内存空间,注意长度计算需要考虑宽字符的字节数(通常一个宽字符占2字节或更多,取决于平台和编码) + wchar_t* buffer = new wchar_t[len + 1]; + // 将格式化后的宽字符字符串拼接到动态分配的内存中 + _vsnwprintf(buffer, len + 1, s, vl); + va_end(vl); + + std::wofstream outFile("test.txt", std::ios::out | std::ios::app | std::ios::binary); // 以二进制模式打开文件用于追加写入 + if (outFile) { + outFile << buffer << std::endl; // 将宽字符字符串写入文件,并添加换行符 + outFile.close(); // 关闭文件流 + std::wcout << L"宽字符字符串已成功追加写入文件。" << std::endl; + } + else { + std::wcerr << L"无法打开文件进行追加写入。" << std::endl; + } + + std::wcout << buffer << std::endl; // 使用std::wcout输出宽字符字符串 + delete[] buffer; +} //HookNut函数注册 typedef void(__cdecl _Register_Nut)(); static _Register_Nut* Register_Nut_Old; void __cdecl H_Register_Nut() { + InitBin(); + Register_Nut_Old(); + static bool Init = false; if (!Init) { Init = true; + //sq_setprintfunc(*(HSQUIRRELVM*)0x1AF3544, PFunc); R_Register_Nut(); + std::string BaseFile = "YosinBaseC"; std::string Base = R"( FFI_FIRST_ABI <- 0; @@ -927,7 +1164,9 @@ getroottable().LenheartBaseFuncTab <- {}; getroottable().LenheartFuncTab <- {}; getroottable().Rindro_Scr_Width <- L_sq_RA(0x4D848E); getroottable().Rindro_Scr_High <- L_sq_RA(0x4D8495); + )"; + //是否为本地 FILE* file = fopen("sqr/DofileList.nut", "rb"); if (file) @@ -952,8 +1191,9 @@ getroottable().Rindro_Scr_High <- L_sq_RA(0x4D8495); delete[]filename; delete[]str; - + #ifndef SELL//本地模式要加在整体脚本 +#ifndef EXPRESS//本地模式要加在整体脚本 Sq_pushroottable(v); Sq_pushstring(v, L"dofile", -1); if (SQ_SUCCEEDED(Sq_get(v, -2))) { @@ -963,6 +1203,8 @@ getroottable().Rindro_Scr_High <- L_sq_RA(0x4D8495); } Sq_pop(v, 2); #endif // !SELL +#endif // !SELL + } } @@ -987,7 +1229,7 @@ void _fastcall H_Register_DrawCode(DWORD thisc, int Seat, int a3, int a4, int a5 delete[]clone; - if (GameStr.find("商城") != std::string::npos) { + if (GameStr.find("将帐号金库中的物品存入金库中") != std::string::npos) { std::cout << GameStr << std::endl; } @@ -1662,8 +1904,49 @@ int _fastcall New4017F0(int thisc, void* a2, char* str, int a3) { return Old4017F0(thisc, a2, str,a3); } + + +//怪物头像绘制HOOK +typedef int(__fastcall _43A1B0)(DWORD thisc, DWORD Seat, int Xpos , int Ypos); +static _43A1B0* Old43A1B0; +int __fastcall New43A1B0(DWORD thisc, DWORD Seat, int Xpos, int Ypos) { + + SQBool Flag = true; + HSQUIRRELVM v = *(HSQUIRRELVM*)0x1AF3544; + SQInteger Top = Sq_gettop(v); + Sq_pushroottable(v); + Sq_pushstring(v, L"L_Rindro_MonsterEXControl_Face", -1); + if (SQ_SUCCEEDED(Sq_get(v, -2))) { + Sq_pushroottable(v); + Sq_pushinteger(v, *(DWORD*)(thisc + 8)); + Sq_pushinteger(v, Xpos); + Sq_pushinteger(v, Ypos); + Sq_call(v, 4, SQTrue, SQTrue); + Sq_getbool(v, -1, &Flag); + } + Sq_settop(v, Top); + + if(Flag)return Old43A1B0(thisc, Seat, Xpos, Ypos); + return 0; +} + void RegisterHook() { +#ifdef EXPRESS + InitGameFlag = true; + MH_Initialize(); + + //Hook收包 + MH_CreateHook((void*)0x721EA0, &H_Register_Pack, reinterpret_cast(&Lpfn_Init)); + MH_EnableHook((void*)0x721EA0); + + //HookNut函数注册 + MH_CreateHook((void*)0x67B910, &H_Register_Nut, reinterpret_cast(&Register_Nut_Old)); + MH_EnableHook((void*)0x67B910); + + return; +#endif // EXPRESS + //InlineHook/// //玩家菜单选项HOOK 有回调 @@ -1678,12 +1961,20 @@ void RegisterHook() { //伤害HOOK inlinehook DamageHook(0xE5A2DE, (int)&Damage_Hook); DamageHook.Motify_address(); + //丢弃道具的HOOK + inlinehook DiscardItemHook(0xE71E9C, (int)&DiscardItem_Hook); + DiscardItemHook.Motify_address(); + inlinehook DiscardItemHookB(0xE71E83, (int)&DiscardItemB_Hook); + DiscardItemHookB.Motify_address(); + //怪物种族绘制HOOK + inlinehook MonsetrRaceHook(0x43A862, (int)&MonsetrRace_Hook); + MonsetrRaceHook.Motify_address(); - //读取StringBin文件 - inlinehook ReadStringBinHookA(0x119F2F8, (int)&ReadStringBin_HookA); - ReadStringBinHookA.Motify_address(); - inlinehook ReadStringBinHookB(0x119F2C0, (int)&ReadStringBin_HookB); - ReadStringBinHookB.Motify_address(); + ////读取StringBin文件 + //inlinehook ReadStringBinHookA(0x119F2F8, (int)&ReadStringBin_HookA); + //ReadStringBinHookA.Motify_address(); + //inlinehook ReadStringBinHookB(0x119F2C0, (int)&ReadStringBin_HookB); + //ReadStringBinHookB.Motify_address(); @@ -1761,8 +2052,8 @@ void RegisterHook() { //Hook发包相关 //HOOK发包类型 - //MH_CreateHook((void*)0x1127D60, &NewSendPacksType, reinterpret_cast(&_OldSendPackType)); - //MH_EnableHook((void*)0x1127D60); + MH_CreateHook((void*)0x1127D60, &NewSendPacksType, reinterpret_cast(&_OldSendPackType)); + MH_EnableHook((void*)0x1127D60); //MH_CreateHook((void*)0x1128550, &NewSendPacksByte, reinterpret_cast(&_OldSendPackByte)); //MH_EnableHook((void*)0x1128550); //MH_CreateHook((void*)0x1128580, &NewSendPacksWord, reinterpret_cast(&_OldSendPackWord)); @@ -1789,6 +2080,7 @@ void RegisterHook() { //如果加载了百级UI FILE* file = fopen("ImagePacks2/!HUD_Yosin百级UI.NPK", "rb"); if (file) { + Yosin百级UIFlag = true; //BUFF图标 显示 inlinehook BuffIconHook(0x04C8C14, (int)&BuffIcon_Hook); BuffIconHook.Motify_address(); @@ -1857,6 +2149,9 @@ void RegisterHook() { //MH_CreateHook((void*)0x11D43A0, &New11D43A0, reinterpret_cast(&Old11D43A0)); //MH_EnableHook((void*)0x11D43A0); + //怪物头像绘制 Hook + MH_CreateHook((void*)0x43A1B0, &New43A1B0, reinterpret_cast(&Old43A1B0)); + MH_EnableHook((void*)0x43A1B0); //他人信息Hook 数值 MH_CreateHook((void*)0xFA42D0, &NewFA42D0, reinterpret_cast(&OldFA42D0)); diff --git a/Include/IO_Ex.hpp b/Include/IO_Ex.hpp new file mode 100644 index 0000000..2f99c5c --- /dev/null +++ b/Include/IO_Ex.hpp @@ -0,0 +1,126 @@ +#pragma once +#include +#include +#include +#include +#include +using namespace std; + +// 定义宏用于注册获取不同类型值的函数 +#define REGISTER_GET_FUNCTION(Type, FunctionName) \ + Type Get##FunctionName() { \ + char buffer[sizeof(Type)]; \ + read(buffer, sizeof(Type)); \ + Type result; \ + std::memcpy(&result, buffer, sizeof(Type)); \ + return result; \ + } +class IO_Ex +{ + +public: + //原始数据 + char* _Data; + //最大长度 + int _MaxLen = 0; + //当前位置 + int _CurPos = 0; + //上一次读取的实际大小 + int _LastReadSize = 0; + +public: + IO_Ex(char* data,int len) { + _Data = data; + _MaxLen = len; + } + ~IO_Ex(); + +public: + int tellg() { + return _CurPos; + } + void read(char* ptr, int size) { + if ((size + _CurPos) > _MaxLen) { + size = _MaxLen - _CurPos; + } + memcpy(ptr, _Data + _CurPos, size); + _CurPos += size; + _LastReadSize = size; + } + int gcount() { + return _LastReadSize; + } + void seek(int _jidx) { + _CurPos = _jidx; + } + +public: + unsigned int charPtrToInt(const char* bytes) { + unsigned int result; + std::memcpy(&result, bytes, sizeof(int)); + return result; + } + + void CrcDecode(const int Length, const int crc32) { + int num = 0x81A79011; + for (int i = 0; i < Length; i += 4) + { + int Pos = tellg(); + char buffer[4]; + read(buffer, 4); + unsigned int anInt = charPtrToInt(buffer); + unsigned int val = (anInt ^ num ^ crc32); + unsigned int jiemi = (val >> 6) | ((val << (32 - 6)) & 0xFFFFFFFF); + _Data[Pos] = ((jiemi >> 0) & 0xFF);; + _Data[Pos + 1] = ((jiemi >> 8) & 0xFF); + _Data[Pos + 2] = ((jiemi >> 16) & 0xFF); + _Data[Pos + 3] = ((jiemi >> 24) & 0xFF); + } + } + + std::string tolower(std::string str) { + for (size_t i = 0; i < str.length(); ++i) { + str[i] = std::tolower(str[i]); + } + return str; + } + + std::vector split(const std::string& str, const std::string& delimiter) { + std::vector tokens; + size_t pos = 0; + size_t found; + while ((found = str.find(delimiter, pos)) != std::string::npos) { + tokens.push_back(str.substr(pos, found - pos)); + pos = found + delimiter.length(); + } + tokens.push_back(str.substr(pos)); + return tokens; + } + + +public: + REGISTER_GET_FUNCTION(int, Int); + REGISTER_GET_FUNCTION(short, Short); + REGISTER_GET_FUNCTION(unsigned short, UShort); + + std::string GetString(const int size) { + char* buffer = new char[size]; + read(buffer, size); + if (gcount() != size) { + std::cerr << "未能成功读取指定字节数的数据!" << std::endl; + delete[] buffer; + return ""; + } + std::string result(buffer, size); + delete[] buffer; + return result; + } + +private: + +}; + + +IO_Ex::~IO_Ex() +{ +} \ No newline at end of file diff --git a/Include/PVF_IO.hpp b/Include/PVF_IO.hpp new file mode 100644 index 0000000..83c0b78 --- /dev/null +++ b/Include/PVF_IO.hpp @@ -0,0 +1,209 @@ +#pragma once +#include "IO_Ex.hpp" +#include +#include +#include +#include "squirrel.h" +#include "sqstdaux.h" +#include "sqstdblob.h" +#include "sqstdio.h" +#include "sqstdmath.h" +#include "sqstdstring.h" +#include "sqstdsystem.h" + +class PVF_IO : public IO_Ex +{ + struct PvfFileInfo + { + int ROffset; + int Cr32; + int Length; + bool DecodeFlag = false; + }; +private: + int StartPos = 0; + std::mapFileInfo; + std::mapBinStringM; + std::mapLoadStringM; + +public: + // 构造函数 + PVF_IO(const char* defaultFilename = "Script.pvf") : IO_Ex(defaultFilename) {} + + // 析构函数,在对象销毁时,基类(fstream)的析构函数会自动被调用,一般不需要额外特殊处理 + ~PVF_IO() {} + + // 显式删除拷贝构造函数,禁止拷贝操作 + PVF_IO(const PVF_IO&) = delete; + + // 也可以考虑同时删除拷贝赋值运算符,保持一致的语义,避免误用 + PVF_IO& operator=(const PVF_IO&) = delete; + + + +public: + void Init() { + //读取头建立树 + InitHeader(); + + //读取bin文件 + InitBin(); + + //读取LoadString + InitLoadString(); + } + + void InitHeader() { + //读取UUID的长度 + int UUID_LENGTH = GetInt(); + //UUID 读 1 - 36位 构造 UTF8 string + std::string UUID = GetString(UUID_LENGTH); + //版本号 + int Version = GetInt(); + // 文件路径数据的大小 + int AlignedIndexHeaderSize = GetInt(); + // 解密密钥 + int IndexHeaderCrc = GetInt(); + // 文件数量 + int IndexSize = GetInt(); + + //文件起始位置 + int FristPos = tellg(); + + //std::cout << "UUID_LENGTH: " << UUID_LENGTH << std::endl; + //std::cout << "UUID: " << UUID << std::endl; + //std::cout << "Version: " << Version << std::endl; + //std::cout << "AlignedIndexHeaderSize: " << AlignedIndexHeaderSize << std::endl; + //std::cout << "IndexHeaderCrc: " << IndexHeaderCrc << std::endl; + //std::cout << "IndexSize: " << IndexSize << std::endl; + + CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc); + + int CurrPos = 0; + StartPos = AlignedIndexHeaderSize + 56; + + //建立pvf文件索引表 + for (size_t i = 0; i < IndexSize; i++) + { + seek(FristPos + CurrPos); + int FileNumber = GetInt(); + int FilePathLength = GetInt(); + std::string FileName = tolower(GetString(FilePathLength)); + int FileLength = GetInt(); + int Cre32 = GetInt(); + int RelativeOffset = GetInt(); + if (FileLength > 0) { + int RealFileLength = (FileLength + 3) & 4294967292; + PvfFileInfo Info; + Info.ROffset = RelativeOffset; + Info.Cr32 = Cre32; + Info.Length = RealFileLength; + Info.DecodeFlag = false; + FileInfo[FileName] = Info; + } + CurrPos += 20; + CurrPos += FilePathLength; + } + } + + void InitBin() { + if (FileInfo.count("stringtable.bin") == 0) { + std::cout << "bin文件不存在" << std::endl; + return; + } + PvfFileInfo BinInfo = FileInfo["stringtable.bin"]; + seek(StartPos + BinInfo.ROffset); + CrcDecode(BinInfo.Length, BinInfo.Cr32); + seek(StartPos + BinInfo.ROffset); + + int FileHPos = tellg(); + int Count = GetInt(); + int CurrentIndex = 0; + + for (int i = 0; i < Count; i++) { + seek(FileHPos + CurrentIndex * 4 + 4); + int StartPos = GetInt(); + int EndPos = GetInt(); + int Len = EndPos - StartPos; + seek(FileHPos + StartPos + 4); + std::string Str = GetString(Len); + BinStringM[CurrentIndex] = Str; + CurrentIndex++; + } + } + + void InitLoadString() { + if (FileInfo.count("n_string.lst") == 0) { + std::cout << "LoadString文件不存在" << std::endl; + return; + } + PvfFileInfo Info = FileInfo["n_string.lst"]; + seek(StartPos + Info.ROffset); + CrcDecode(Info.Length, Info.Cr32); + seek(StartPos + Info.ROffset); + + int FileHPos = tellg(); + int Flag = GetShort(); + int i = 2; + while (i < Info.Length) + { + if ((Info.Length - i) >= 10) { + seek(FileHPos + i + 6); + int FindKey = GetInt(); + std::string Key = GetBinString(FindKey); + if (Key.length() > 0) { + PvfFileInfo* FileInfo = GetFileInfo(Key); + if (FileInfo == nullptr)continue; + + seek(StartPos + FileInfo->ROffset); + CrcDecode(FileInfo->Length, FileInfo->Cr32); + seek(StartPos + FileInfo->ROffset); + + std::string Str = GetString(FileInfo->Length); + std::vector StrArr = split(Str, "\r\n"); + for (auto it = StrArr.begin(); it != StrArr.end(); ++it) { + std::string strobj = *it; + if (strobj.find(">") != std::string::npos) { + std::vector strobjarr = split(strobj, ">"); + if (strobjarr.size() > 1) + LoadStringM[strobjarr[0]] = strobjarr[1]; + } + } + } + } + else break; + i += 10; + } + } + + +public: + std::string GetBinString(int Key) { + if (BinStringM.count(Key))return BinStringM[Key]; + return ""; + } + std::string GetLoadString(std::string Key) { + if (LoadStringM.count(Key))return LoadStringM[Key]; + return ""; + } + PvfFileInfo* GetFileInfo(std::string path) { + path = tolower(path); + if (FileInfo.count(path))return &FileInfo[path]; + return nullptr; + } + void LoadFileToBlob(HSQUIRRELVM v ,std::string path, SQUserPointer blobp) { + path = tolower(path); + if (FileInfo.count(path)) { + seek(StartPos + FileInfo[path].ROffset); + if (FileInfo[path].DecodeFlag == false) { + CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32); + seek(StartPos + FileInfo[path].ROffset); + FileInfo[path].DecodeFlag = true; + } + read((char*)blobp, FileInfo[path].Length); + return; + } + sq_pushnull(v); + return; + } +}; \ No newline at end of file diff --git a/Include/RegisterSquirrel.hpp b/Include/RegisterSquirrel.hpp index 6a9e874..4556c78 100644 --- a/Include/RegisterSquirrel.hpp +++ b/Include/RegisterSquirrel.hpp @@ -70,7 +70,7 @@ static SQInteger sq_StringBinById(HSQUIRRELVM v) Sq_pushstring(v, cfg, -1); delete[]cfg; - + return 1; } @@ -97,7 +97,8 @@ static SQInteger sq_LongLongOperation(HSQUIRRELVM v) std::string RetString = ""; if (Type == "+") { RetString = std::to_string(value1 + value2); - }else if(Type == "-") { + } + else if (Type == "-") { RetString = std::to_string(value1 - value2); } else if (Type == "*") { @@ -123,7 +124,7 @@ static SQInteger sq_LongLongOperation(HSQUIRRELVM v) RetString = std::to_string(value1 / 1000000000.0) + "G"; } else { - RetString = std::to_string(value1 / 1000000000000.0) + "T"; + RetString = std::to_string(value1 / 1000000000000.0) + "T"; } } @@ -1065,7 +1066,7 @@ static SQInteger sq_GetWindowById(HSQUIRRELVM v) { Sq_getinteger(v, 2, &Idx); int WindowAddress = GetWindowByIdx(Idx); Sq_pushinteger(v, WindowAddress); - + return 1; } //选择大地图区域 @@ -1228,6 +1229,8 @@ static SQInteger sq_DrawItem(HSQUIRRELVM v) //获取SQR的对象转换为原始对象地址 typedef int(_cdecl __GetSqrObject)(HSQUIRRELVM a1, int a2); +typedef int(_cdecl __PushDnfobject)(HSQUIRRELVM a1, wchar_t* Type, DWORD ObjectAddress, DWORD S); +static __PushDnfobject* PushDnfobject = (__PushDnfobject*)0x11809C0; static __GetSqrObject* GetSqrObject = (__GetSqrObject*)0x5c1420; static __GetSqrObject* GetExeObject = (__GetSqrObject*)0x5c13A0; //获取对象地址 @@ -1237,6 +1240,18 @@ static SQInteger GetObjectAddress(HSQUIRRELVM v) Sq_pushinteger(v, objAddress); return 1; } +//对象地址转换为Sqr对象 +static SQInteger ObjectAddressToSqrObject(HSQUIRRELVM v) +{ + int objAddress; + Sq_getinteger(v, 2, &objAddress); + const SQChar* Type; + Sq_getstring(v, 3, &Type); + int Flag; + Sq_getinteger(v, 4, &Flag); + PushDnfobject(v, (wchar_t*)Type, objAddress, 0); + return 1; +} //获取对象名称 static SQInteger GetObjectName(HSQUIRRELVM v) { @@ -1249,6 +1264,18 @@ static SQInteger GetObjectName(HSQUIRRELVM v) delete[]name; return 1; } +//设置对象名称 +static SQInteger DeleteObjectName(HSQUIRRELVM v) +{ + int objAddress = GetSqrObject(v, 2); + wchar_t* objNameAddress = *(wchar_t**)(objAddress + 0x258); + // 遍历字符串直到遇到宽字符空终止符 + for (wchar_t* p = objNameAddress; *p != L'\0'; ++p) { + // 将每个字符替换为空格 + *p = L' '; + } + return 0; +} //获取对象名称 static SQInteger GetObjectNameByAddress(HSQUIRRELVM v) { @@ -1514,17 +1541,17 @@ static SQInteger GetObjectIsCharacter(HSQUIRRELVM v) return 1; } -typedef int(__fastcall* _GetObjectAttribute)(DWORD thisc, int Seat, int Type); +typedef int(__fastcall* _GetObjectAttribute)(DWORD thisc, int Seat, int Type); typedef int(__fastcall* _FloatDecode)(int Address); static _GetObjectAttribute GetObjectAttributeFunc = (_GetObjectAttribute)0xD07390; static _FloatDecode FloatDecode = (_FloatDecode)0x5B0090; //获取对象属性 static SQInteger GetObjectAttribute(HSQUIRRELVM v) { - int objAddress ,Type; + int objAddress, Type; Sq_getinteger(v, 2, &objAddress); Sq_getinteger(v, 3, &Type); - int Ret = GetObjectAttributeFunc(objAddress,0, Type); + int Ret = GetObjectAttributeFunc(objAddress, 0, Type); Ret = FloatDecode(Ret); Sq_pushinteger(v, Ret); return 1; @@ -1603,25 +1630,25 @@ static SQInteger SetCharacterAttribute(HSQUIRRELVM v) //获取城镇编号 static SQInteger GetTownIndex(HSQUIRRELVM v) { - Sq_pushinteger(v, DNFTOOL::GetHook(0x1A5E258, "0xAC+0xD4+",0)); + Sq_pushinteger(v, DNFTOOL::GetHook(0x1A5E258, "0xAC+0xD4+", 0)); return 1; } //获取城镇区域编号 static SQInteger GetRegionIndex(HSQUIRRELVM v) { - Sq_pushinteger(v, *(int*)(DNFTOOL::GetHook(0x1A5E258, "0xAC+0xD8+",0))); + Sq_pushinteger(v, *(int*)(DNFTOOL::GetHook(0x1A5E258, "0xAC+0xD8+", 0))); return 1; } //获取城镇X坐标 static SQInteger GetTownXpos(HSQUIRRELVM v) { - Sq_pushinteger(v, DNFTOOL::GetHook(0x1AB7CE0, "0x2BC+",0)); + Sq_pushinteger(v, DNFTOOL::GetHook(0x1AB7CE0, "0x2BC+", 0)); return 1; } //获取城镇Y坐标 static SQInteger GetTownYpos(HSQUIRRELVM v) { - Sq_pushinteger(v, DNFTOOL::GetHook(0x1AB7CE0, "0x2C0+",0)); + Sq_pushinteger(v, DNFTOOL::GetHook(0x1AB7CE0, "0x2C0+", 0)); return 1; } //获取疲劳值 @@ -2074,7 +2101,7 @@ static SQInteger LReadAddress(HSQUIRRELVM v) Sq_getinteger(v, 2, &Address); Sq_getstring(v, 3, &offset); - int Value = DNFTOOL::GetHook(Address, DNFTOOL::wchar_tTochar((wchar_t*)offset),0); + int Value = DNFTOOL::GetHook(Address, DNFTOOL::wchar_tTochar((wchar_t*)offset), 0); Sq_pushinteger(v, Value); return 1; } @@ -2743,7 +2770,7 @@ static SQInteger sq_Test(HSQUIRRELVM v) sq_getstring(v, 2, &Path); char* a = new char[1024]; //wchar_t* path = L"region/region.lst"; - SUB_11A2030(0x1D17638,0, (int)Path,(int)a, 0x100000, 0x19DAF4); + SUB_11A2030(0x1D17638, 0, (int)Path, (int)a, 0x100000, 0x19DAF4); //std::cout << a << std::endl; return 0; @@ -2967,6 +2994,7 @@ static SQInteger L_Str_Ptr(HSQUIRRELVM v) Sq_pushuserpointer(v, (void*)str); return 1; } + static SQInteger New_Point(HSQUIRRELVM v) { SQInteger Len; @@ -3111,7 +3139,7 @@ static SQInteger ConvertWideChar(HSQUIRRELVM v) if (CONTAINS_STRING(fromEncoding, "big5")) { - char* csa = DNFTOOL::wchar_tTochar((wchar_t*) Str); + char* csa = DNFTOOL::wchar_tTochar((wchar_t*)Str); wchar_t* name = DNFTOOL::BIG5ToUnicode(csa); char* str = DNFTOOL::UnicodeToUtf8(name); wchar_t* realname = DNFTOOL::charTowchar_t(str); @@ -3123,7 +3151,7 @@ static SQInteger ConvertWideChar(HSQUIRRELVM v) delete[]realname; } else if (CONTAINS_STRING(fromEncoding, "unicode")) { - char* str = DNFTOOL::UnicodeToUtf8((wchar_t*)Str); + char* str = DNFTOOL::UnicodeToUtf8((wchar_t*)Str); wchar_t* name = DNFTOOL::charTowchar_t(str); free(str); Sq_pushstring(v, name, -1); @@ -3168,7 +3196,7 @@ static SQInteger OutPutTable(HSQUIRRELVM v) void R_Register_Nut() { RegisterMyNutApi(L"L_sq_Test", sq_Test);//zlib解压 - + RegisterMyNutApi(L"Sq_OutPutTable", OutPutTable); RegisterMyNutApi(L"Sq_HookFunc", L_HookFunc); @@ -3220,10 +3248,12 @@ void R_Register_Nut() { RegisterMyNutApi(L"L_Sq_GetImg", sq_GetImg);//通过Item编号获取图标Img RegisterMyNutApi(L"L_Sq_DrawItem", sq_DrawItem);//绘制Item - + RegisterMyNutApi(L"L_Sq_GetObjectAddress", GetObjectAddress);//获取对象地址 + RegisterMyNutApi(L"L_Sq_ObjectAddressToSqrObject", ObjectAddressToSqrObject);//对象地址转换为Sqr对象 RegisterMyNutApi(L"L_Sq_GetRidingObjectAddress", GetRidingObjectAddress);//获取骑乘对象地址 RegisterMyNutApi(L"L_Sq_GetObjectName", GetObjectName);//获取对象名字 + RegisterMyNutApi(L"L_Sq_DeleteObjectName", DeleteObjectName);//设置对象名字 RegisterMyNutApi(L"L_Sq_GetObjectNameByAddress", GetObjectNameByAddress);//获取对象名字 RegisterMyNutApi(L"L_Sq_GetObjectInfo", GetObjectInfo);//获取对象信息 RegisterMyNutApi(L"L_Sq_GetObjectDeInfo", GetObjectDeInfo);//获取对象加密信息 diff --git a/Rindro_Plugin.sln b/Rindro_Plugin.sln index 974102b..7ff4d81 100644 --- a/Rindro_Plugin.sln +++ b/Rindro_Plugin.sln @@ -11,8 +11,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squirrel", "F:\nut\SQUIRREL EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sqstdlib", "F:\nut\SQUIRREL2\sqstdlib\sqstdlib.vcxproj", "{5B802548-C7C1-4993-B338-472AF8B11730}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ffi", "F:\zhuomian\Libffi-master\Libffi-master\build\ffi.vcxproj", "{E76C4B11-4165-3C69-89CE-954037C7BB5B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -107,26 +105,6 @@ Global {5B802548-C7C1-4993-B338-472AF8B11730}.Template|x64.Build.0 = Template|Win32 {5B802548-C7C1-4993-B338-472AF8B11730}.Template|x86.ActiveCfg = Template|Win32 {5B802548-C7C1-4993-B338-472AF8B11730}.Template|x86.Build.0 = Template|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Debug|x64.ActiveCfg = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Debug|x64.Build.0 = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Debug|x86.ActiveCfg = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Debug|x86.Build.0 = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.MinSizeRel|x64.Build.0 = MinSizeRel|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.MinSizeRel|x86.Build.0 = MinSizeRel|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Release|x64.ActiveCfg = Release|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Release|x64.Build.0 = Release|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Release|x86.ActiveCfg = Release|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Release|x86.Build.0 = Release|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Template|x64.ActiveCfg = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Template|x64.Build.0 = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Template|x86.ActiveCfg = Debug|Win32 - {E76C4B11-4165-3C69-89CE-954037C7BB5B}.Template|x86.Build.0 = Debug|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Rindro_Plugin.vcxproj b/Rindro_Plugin.vcxproj index a7f7b46..9518e4e 100644 --- a/Rindro_Plugin.vcxproj +++ b/Rindro_Plugin.vcxproj @@ -158,8 +158,11 @@ + + + @@ -182,11 +185,18 @@ {055a88b6-e28d-4155-a0db-b2b60dd6c7ae} - - {e76c4b11-4165-3c69-89ce-954037c7bb5b} - + + + + + + + 杩欏彴璁$畻鏈轰笂缂哄皯姝ら」鐩紩鐢ㄧ殑 NuGet 绋嬪簭鍖呫備娇鐢ㄢ淣uGet 绋嬪簭鍖呰繕鍘熲濆彲涓嬭浇杩欎簺绋嬪簭鍖呫傛湁鍏虫洿澶氫俊鎭紝璇峰弬瑙 http://go.microsoft.com/fwlink/?LinkID=322105銆傜己灏戠殑鏂囦欢鏄 {0}銆 + + + \ No newline at end of file diff --git a/Rindro_Plugin.vcxproj.filters b/Rindro_Plugin.vcxproj.filters index d883059..7ae9fc1 100644 --- a/Rindro_Plugin.vcxproj.filters +++ b/Rindro_Plugin.vcxproj.filters @@ -42,6 +42,15 @@ 澶存枃浠 + + 澶存枃浠 + + + 澶存枃浠 + + + 澶存枃浠 + @@ -57,4 +66,7 @@ 婧愭枃浠 + + + \ No newline at end of file diff --git a/dllmain.cpp b/dllmain.cpp index fab65c7..e1a170c 100644 --- a/dllmain.cpp +++ b/dllmain.cpp @@ -42,8 +42,10 @@ void LenheartThread() } } + //鍒濆鍖栧叆鍙 void Init() { + //鏄惁鍔犺浇鐧剧骇UI FILE* file = fopen("ImagePacks2/!HUD_Yosin鐧剧骇UI.NPK", "rb"); if (file) @@ -51,12 +53,13 @@ void Init() { HookHudUi(); fclose(file); } + //鏄惁寮鍚帶鍒跺彴 FILE* file2 = fopen("ip.txt", "rb"); if (file2) { AllocConsole(); - SetConsoleTitleA("Rindro_Console"); + SetConsoleTitle(L"Rindro_Console"); SetConsoleOutputCP(65001); freopen(("CONOUT$"), ("w"), stdout); freopen(("CONOUT$"), ("w"), stderr); @@ -78,9 +81,13 @@ void Init() { //娉ㄥ唽HOOK RegisterHook(); +#ifdef SELL //澶氱嚎绋嬮獙璇 DWORD threadID; HANDLE Thand = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LenheartThread, NULL, 0, &threadID); +#endif + + } diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..aaeb062 --- /dev/null +++ b/packages.config @@ -0,0 +1,4 @@ +锘 + + + \ No newline at end of file diff --git a/pch.h b/pch.h index 6c0da29..7db7ee5 100644 --- a/pch.h +++ b/pch.h @@ -24,9 +24,9 @@ - -//# define SELL "鍞嚭妯″紡" -#define INVERSION "24081701" +//# define EXPRESS "瀛︿範鐗" +# define SELL "鍞嚭妯″紡" +#define INVERSION "24112901" diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..e83c5c2 --- /dev/null +++ b/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ 生成的包含文件。 +// 供 Rindro_Plugin.rc 使用 +// +#define IDR_X1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif