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
#include <iostream>
#include <windows.h>
#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();

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

View File

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

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) {
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;

View File

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