refactor how mods are created, add new callback

This commit is contained in:
ChrisMiuchiz 2019-11-03 22:06:07 -05:00
parent 3eba6f4ec5
commit 5c0ce6c139
7 changed files with 86 additions and 45 deletions

View File

@ -2,6 +2,7 @@
#define DLL_H #define DLL_H
#include <iostream> #include <iostream>
#include <windows.h> #include <windows.h>
#include "GenericMod.h"
class DLL class DLL
{ {
@ -10,14 +11,11 @@ class DLL
HMODULE handle; HMODULE handle;
FARPROC ModPreInitialize; FARPROC ModPreInitialize;
FARPROC ModInitialize;
FARPROC ModMajorVersion; FARPROC ModMajorVersion;
FARPROC ModMinorVersion; FARPROC ModMinorVersion;
FARPROC MakeMod;
// Callbacks GenericMod* mod;
FARPROC HandleChat;
FARPROC HandleP2PRequest;
FARPROC HandleCheckInventoryFull;
DLL(std::string fileName); DLL(std::string fileName);
HMODULE Load(); HMODULE Load();

View File

@ -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

View File

@ -1,10 +1,8 @@
extern "C" int ChatHandler(wchar_t* msg) { extern "C" int ChatHandler(void* msg) {
for (DLL* dll: modDLLs) { for (DLL* dll: modDLLs) {
if (dll->HandleChat) { if (dll->mod->OnChat(msg)) {
if ( ((int(*)(wchar_t*))dll->HandleChat)(msg) ){ return 1;
return 1; }
}
}
} }
return 0; return 0;
} }
@ -12,37 +10,40 @@ extern "C" int ChatHandler(wchar_t* msg) {
GETTER_VAR(void*, ASMChatHandler_jmpback); GETTER_VAR(void*, ASMChatHandler_jmpback);
GETTER_VAR(void*, ASMChatHandler_bail); GETTER_VAR(void*, ASMChatHandler_bail);
void ASMChatHandler() { void ASMChatHandler() {
asm(".intel_syntax \n" asm(".intel_syntax \n"
PUSH_ALL 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? // Did the handler return true?
"test al, al \n" "test al, al \n"
"jnz bail \n" "jnz bail \n"
POP_ALL POP_ALL
// original code // original code
"mov qword ptr [rbp+0x88], 7 \n" "mov [rsp+0x48], rax \n"
"mov [rbp+0x80], r12 \n" "mov r8, [rbx+0x10] \n"
"mov [rbp+0x70], r12w \n" "cmp qword ptr [rbx+0x18], 8 \n"
"jb 1f \n"
"mov rbx, [rbx] \n"
"1: \n"
DEREF_JMP(ASMChatHandler_jmpback) DEREF_JMP(ASMChatHandler_jmpback)
"bail: \n" "bail: \n"
POP_ALL POP_ALL
DEREF_JMP(ASMChatHandler_bail) DEREF_JMP(ASMChatHandler_bail)
); );
} }
void SetupChatHandler() { void SetupChatHandler() {
WriteFarJMP(Offset(base, 0x97198), (void*)&ASMChatHandler); WriteFarJMP(Offset(base, 0x97175), (void*)&ASMChatHandler);
ASMChatHandler_jmpback = Offset(base, 0x971B0); ASMChatHandler_jmpback = Offset(base, 0x97188);
ASMChatHandler_bail = Offset(base, 0x9777A); ASMChatHandler_bail = Offset(base, 0x9777A);
} }

View File

@ -1,9 +1,7 @@
extern "C" int CheckInventoryFullHandler(void* player, void* item) { extern "C" int CheckInventoryFullHandler(void* player, void* item) {
for (DLL* dll: modDLLs) { for (DLL* dll: modDLLs) {
if (dll->HandleCheckInventoryFull) { if ( int result = dll->mod->OnCheckInventoryFull(player, item) ){
if ( int result = ((int(*)(void*, void*))dll->HandleCheckInventoryFull)(player, item) ){ return result;
return result;
}
} }
} }
return 0; return 0;

View File

@ -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);
}

View File

@ -1,9 +1,7 @@
extern "C" int P2PRequestHandler(long long steamID) { extern "C" int P2PRequestHandler(long long steamID) {
for (DLL* dll: modDLLs) { for (DLL* dll: modDLLs) {
if (dll->HandleP2PRequest) { if (int result = dll->mod->OnP2PRequest(steamID)) {
if ( int result = ((int(*)(long long))dll->HandleP2PRequest)(steamID) ){ return result;
return result;
}
} }
} }
return 0; return 0;

View File

@ -27,11 +27,13 @@ GETTER_VAR(void*, initterm_e); // A pointer to that function
#include "callbacks/ChatHandler.h" #include "callbacks/ChatHandler.h"
#include "callbacks/P2PRequestHandler.h" #include "callbacks/P2PRequestHandler.h"
#include "callbacks/CheckInventoryFullHandler.h" #include "callbacks/CheckInventoryFullHandler.h"
#include "callbacks/GameTickHandler.h"
void SetupHandlers() { void SetupHandlers() {
SetupChatHandler(); SetupChatHandler();
SetupP2PRequestHandler(); SetupP2PRequestHandler();
SetupCheckInventoryFullHandler(); SetupCheckInventoryFullHandler();
SetupGameTickHandler();
} }
@ -74,10 +76,7 @@ extern "C" void StartMods() {
MUST_IMPORT(dll, ModMajorVersion); MUST_IMPORT(dll, ModMajorVersion);
MUST_IMPORT(dll, ModMinorVersion); MUST_IMPORT(dll, ModMinorVersion);
MUST_IMPORT(dll, ModPreInitialize); MUST_IMPORT(dll, ModPreInitialize);
IMPORT(dll, ModInitialize); MUST_IMPORT(dll, MakeMod);
IMPORT(dll, HandleChat);
IMPORT(dll, HandleP2PRequest);
IMPORT(dll, HandleCheckInventoryFull);
} }
// Ensure version compatibility // Ensure version compatibility
@ -100,12 +99,11 @@ extern "C" void StartMods() {
// Run Initialization routines on all mods // Run Initialization routines on all mods
for (DLL* dll: modDLLs) { for (DLL* dll: modDLLs) {
((void(*)())dll->ModPreInitialize)(); ((void(*)())dll->ModPreInitialize)();
dll->mod = ((GenericMod*(*)())dll->MakeMod)();
} }
for (DLL* dll: modDLLs) { for (DLL* dll: modDLLs) {
if (dll->ModInitialize) { dll->mod->Initialize();
((void(*)())dll->ModInitialize)();
}
} }
if (hSelf) PrintLoadedMods(); if (hSelf) PrintLoadedMods();