From 5c0ce6c139cbca3a6b7c1497264eac3c2ce4588a Mon Sep 17 00:00:00 2001 From: ChrisMiuchiz Date: Sun, 3 Nov 2019 22:06:07 -0500 Subject: [PATCH] refactor how mods are created, add new callback --- CubeModLoader/DLL.h | 8 ++- CubeModLoader/GenericMod.h | 13 +++++ CubeModLoader/callbacks/ChatHandler.h | 51 ++++++++++--------- .../callbacks/CheckInventoryFullHandler.h | 6 +-- CubeModLoader/callbacks/GameTickHandler.h | 35 +++++++++++++ CubeModLoader/callbacks/P2PRequestHandler.h | 6 +-- CubeModLoader/main.cpp | 12 ++--- 7 files changed, 86 insertions(+), 45 deletions(-) create mode 100644 CubeModLoader/GenericMod.h create mode 100644 CubeModLoader/callbacks/GameTickHandler.h diff --git a/CubeModLoader/DLL.h b/CubeModLoader/DLL.h index 7027773..254ab94 100644 --- a/CubeModLoader/DLL.h +++ b/CubeModLoader/DLL.h @@ -2,6 +2,7 @@ #define DLL_H #include #include +#include "GenericMod.h" class DLL { @@ -10,14 +11,11 @@ class DLL HMODULE handle; FARPROC ModPreInitialize; - FARPROC ModInitialize; FARPROC ModMajorVersion; FARPROC ModMinorVersion; + FARPROC MakeMod; - // Callbacks - FARPROC HandleChat; - FARPROC HandleP2PRequest; - FARPROC HandleCheckInventoryFull; + GenericMod* mod; DLL(std::string fileName); HMODULE Load(); diff --git a/CubeModLoader/GenericMod.h b/CubeModLoader/GenericMod.h new file mode 100644 index 0000000..89c9147 --- /dev/null +++ b/CubeModLoader/GenericMod.h @@ -0,0 +1,13 @@ +#ifndef GENERICMOD_H +#define GENERICMOD_H + +class GenericMod { +public: + virtual void Initialize() {} + virtual int OnChat(void* msg) { return 0; } + virtual int OnCheckInventoryFull(void* player, void* item) { return 0; } + virtual int OnP2PRequest(uint64_t steamID) { return 0; } + virtual void OnGameTick(void* game) {} +}; + +#endif // GENERICMOD_H diff --git a/CubeModLoader/callbacks/ChatHandler.h b/CubeModLoader/callbacks/ChatHandler.h index 7f7823d..dd2bae3 100644 --- a/CubeModLoader/callbacks/ChatHandler.h +++ b/CubeModLoader/callbacks/ChatHandler.h @@ -1,10 +1,8 @@ -extern "C" int ChatHandler(wchar_t* msg) { +extern "C" int ChatHandler(void* msg) { for (DLL* dll: modDLLs) { - if (dll->HandleChat) { - if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){ - return 1; - } - } + if (dll->mod->OnChat(msg)) { + return 1; + } } return 0; } @@ -12,37 +10,40 @@ extern "C" int ChatHandler(wchar_t* msg) { GETTER_VAR(void*, ASMChatHandler_jmpback); GETTER_VAR(void*, ASMChatHandler_bail); void ASMChatHandler() { - asm(".intel_syntax \n" + asm(".intel_syntax \n" PUSH_ALL - "mov rcx, rbx \n" // The message + "mov rcx, rbx \n" //The (std::wstring*) message - PREPARE_STACK + PREPARE_STACK - "call ChatHandler \n" + "call ChatHandler \n" - RESTORE_STACK + RESTORE_STACK - // Did the handler return true? - "test al, al \n" - "jnz bail \n" + // Did the handler return true? + "test al, al \n" + "jnz bail \n" - POP_ALL + POP_ALL - // original code - "mov qword ptr [rbp+0x88], 7 \n" - "mov [rbp+0x80], r12 \n" - "mov [rbp+0x70], r12w \n" + // original code + "mov [rsp+0x48], rax \n" + "mov r8, [rbx+0x10] \n" + "cmp qword ptr [rbx+0x18], 8 \n" + "jb 1f \n" + "mov rbx, [rbx] \n" + "1: \n" DEREF_JMP(ASMChatHandler_jmpback) - "bail: \n" - POP_ALL + "bail: \n" + POP_ALL DEREF_JMP(ASMChatHandler_bail) - ); + ); } void SetupChatHandler() { - WriteFarJMP(Offset(base, 0x97198), (void*)&ASMChatHandler); - ASMChatHandler_jmpback = Offset(base, 0x971B0); - ASMChatHandler_bail = Offset(base, 0x9777A); + WriteFarJMP(Offset(base, 0x97175), (void*)&ASMChatHandler); + ASMChatHandler_jmpback = Offset(base, 0x97188); + ASMChatHandler_bail = Offset(base, 0x9777A); } diff --git a/CubeModLoader/callbacks/CheckInventoryFullHandler.h b/CubeModLoader/callbacks/CheckInventoryFullHandler.h index 3a00d94..eb151c0 100644 --- a/CubeModLoader/callbacks/CheckInventoryFullHandler.h +++ b/CubeModLoader/callbacks/CheckInventoryFullHandler.h @@ -1,9 +1,7 @@ extern "C" int CheckInventoryFullHandler(void* player, void* item) { for (DLL* dll: modDLLs) { - if (dll->HandleCheckInventoryFull) { - if ( int result = ((int(*)(void*, void*))dll->HandleCheckInventoryFull)(player, item) ){ - return result; - } + if ( int result = dll->mod->OnCheckInventoryFull(player, item) ){ + return result; } } return 0; diff --git a/CubeModLoader/callbacks/GameTickHandler.h b/CubeModLoader/callbacks/GameTickHandler.h new file mode 100644 index 0000000..ab45130 --- /dev/null +++ b/CubeModLoader/callbacks/GameTickHandler.h @@ -0,0 +1,35 @@ +extern "C" void GameTickHandler(void* game) { + for (DLL* dll: modDLLs) { + dll->mod->OnGameTick(game); + } +} + +GETTER_VAR(void*, ASMGameTickHandler_jmpback); +void ASMGameTickHandler() { + asm(".intel_syntax \n" + PUSH_ALL + + "mov rcx, rax \n" // cube::Game* + + PREPARE_STACK + + "call GameTickHandler \n" + + RESTORE_STACK + + POP_ALL + + // original code + "mov [rsp+0x20], ebx \n" + "xor r9d, r9d \n" + "xor r8d, r8d \n" + "xor edx, edx \n" + "lea rcx, [rbp+0xB8] \n" + + DEREF_JMP(ASMGameTickHandler_jmpback) + ); +} +void SetupGameTickHandler() { + WriteFarJMP(Offset(base, 0x136458), (void*)&ASMGameTickHandler); + ASMGameTickHandler_jmpback = Offset(base, 0x13646B); +} diff --git a/CubeModLoader/callbacks/P2PRequestHandler.h b/CubeModLoader/callbacks/P2PRequestHandler.h index e6e7e33..c423aa6 100644 --- a/CubeModLoader/callbacks/P2PRequestHandler.h +++ b/CubeModLoader/callbacks/P2PRequestHandler.h @@ -1,9 +1,7 @@ extern "C" int P2PRequestHandler(long long steamID) { for (DLL* dll: modDLLs) { - if (dll->HandleP2PRequest) { - if ( int result = ((int(*)(long long))dll->HandleP2PRequest)(steamID) ){ - return result; - } + if (int result = dll->mod->OnP2PRequest(steamID)) { + return result; } } return 0; diff --git a/CubeModLoader/main.cpp b/CubeModLoader/main.cpp index 361c0e4..501a501 100644 --- a/CubeModLoader/main.cpp +++ b/CubeModLoader/main.cpp @@ -27,11 +27,13 @@ GETTER_VAR(void*, initterm_e); // A pointer to that function #include "callbacks/ChatHandler.h" #include "callbacks/P2PRequestHandler.h" #include "callbacks/CheckInventoryFullHandler.h" +#include "callbacks/GameTickHandler.h" void SetupHandlers() { SetupChatHandler(); SetupP2PRequestHandler(); SetupCheckInventoryFullHandler(); + SetupGameTickHandler(); } @@ -74,10 +76,7 @@ extern "C" void StartMods() { MUST_IMPORT(dll, ModMajorVersion); MUST_IMPORT(dll, ModMinorVersion); MUST_IMPORT(dll, ModPreInitialize); - IMPORT(dll, ModInitialize); - IMPORT(dll, HandleChat); - IMPORT(dll, HandleP2PRequest); - IMPORT(dll, HandleCheckInventoryFull); + MUST_IMPORT(dll, MakeMod); } // Ensure version compatibility @@ -100,12 +99,11 @@ extern "C" void StartMods() { // Run Initialization routines on all mods for (DLL* dll: modDLLs) { ((void(*)())dll->ModPreInitialize)(); + dll->mod = ((GenericMod*(*)())dll->MakeMod)(); } for (DLL* dll: modDLLs) { - if (dll->ModInitialize) { - ((void(*)())dll->ModInitialize)(); - } + dll->mod->Initialize(); } if (hSelf) PrintLoadedMods();