diff --git a/update_tool/api_link.asm b/update_tool/api_link.asm index af93081..7ebcc81 100644 --- a/update_tool/api_link.asm +++ b/update_tool/api_link.asm @@ -16,10 +16,15 @@ section .text -global GetThisPointer, GetGameDir -global _GetThisPointer, _GetGameDir +global GetThisPointer, GetGameDir, ServerCommand +global _GetThisPointer, _GetGameDir, _ServerCommand +global _GetICvar extern _LoadFunction +_GetICvar + mov eax, [icvar] + ret + GetThisPointer: _GetThisPointer: mov eax, GLOBAL_POINTER @@ -44,21 +49,42 @@ _GetGameDir: pop ebp ret - + +ServerCommand +_ServerCommand: + push ebp + mov ebp, esp + + mov ecx, [engine] ;get this pointer + mov edx, [ecx] ;get the vtable + push dword [ebp+8] ;push string + %ifdef LINUX + push ecx ;push this pointer + %endif + call dword [edx+144] ;call IVEngineServer::ServerCommand + %ifdef LINUX + add esp, 8 ;correct stack + %endif + + pop ebp + ret + thisLoadFunction: push ebp mov ebp, esp + push edi + ;get factory %ifdef LINUX - mov eax, [ebp+12] + mov edi, [ebp+12] %else - mov eax, [ebp+8] + mov edi, [ebp+8] %endif push dword 0 ;NULL push dword VENGINESERVER ;iface name - call eax ;call factory + call edi ;call factory add esp, 8 ;correct stack test eax, eax ;do we have a valid pointer? @@ -66,11 +92,24 @@ thisLoadFunction: mov [engine], eax ;store the engine pointer + push dword 0 ;NULL + push dword VENGINECVAR ;iface name + call edi ;call factory + add esp, 8 ;correct stack + + test eax, eax ;do we have a valid pointer? + jz .end ;no, bail out + + mov [icvar], eax ;store the icvar pointer + call _LoadFunction .end: ;We never load, never ever ever! xor eax, eax + + pop edi + pop ebp %ifdef LINUX ret @@ -84,6 +123,7 @@ thisUnloadFunction: section .data INTERFACE_NAME DB "ISERVERPLUGINCALLBACKS001", 0 VENGINESERVER DB "VEngineServer021", 0 + VENGINECVAR DB "VEngineCvar003", 0 VIRTUAL_TABLE DD thisLoadFunction DD thisUnloadFunction @@ -94,3 +134,4 @@ section .data temp_ret DD 0 temp_ptr DD temp_ret engine DD 0 + icvar DD 0 \ No newline at end of file diff --git a/update_tool/msvc8/update_tool.vcproj b/update_tool/msvc8/update_tool.vcproj index dc09f92..f1c905c 100644 --- a/update_tool/msvc8/update_tool.vcproj +++ b/update_tool/msvc8/update_tool.vcproj @@ -24,7 +24,7 @@ > #include -extern "C" void GetGameDir(char *buffer, int maxlength); -extern "C" void *GetThisPointer(); - #if defined _MSC_VER #define SEPCHAR "\\" #define MMPATH "addons\\metamod\\bin" @@ -17,9 +14,17 @@ extern "C" void *GetThisPointer(); #include #endif +#include + +extern "C" void GetGameDir(char *buffer, int maxlength); +extern "C" void *GetThisPointer(); +extern "C" void ServerCommand(const char *command); +extern "C" ICvar *GetICvar(); + size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); bool s_isspace(char c); bool RenameFile(const char *old, const char *newf); +bool RemoveFile(const char *file); /* This will be called by the thunk */ #if defined _MSC_VER @@ -28,6 +33,13 @@ extern "C" void LoadFunction() extern "C" void _LoadFunction() #endif { + ICvar *pCvar = GetICvar(); + if (pCvar->FindVar("metamod_version") != NULL) + { + /* Already exists, bail out */ + return; + } + char gamedir[260]; char mmpath[260]; @@ -141,6 +153,8 @@ extern "C" void _LoadFunction() char input[1024]; char backup[1024]; + + bool bWroteOutput = false; while (!feof(fp) && fgets(input, sizeof(input), fp) != NULL) { @@ -199,10 +213,11 @@ extern "C" void _LoadFunction() op = NULL; break; /* Nothing more to do! */ } else { - fputs("\t\t\tGameBin\t\t\t|gameinfo_path|", op); + fputs("\t\t\tGameBin\t\t\t", op); fputs(mmpath, op); fputs("\n", op); ps = Parse_None; + bWroteOutput = true; } } } @@ -222,6 +237,13 @@ extern "C" void _LoadFunction() fclose(op); fclose(fp); + /* If we didn't change anything, abort here */ + if (!bWroteOutput) + { + RemoveFile(new_path); + return; + } + /* Move the old file to a backup name */ char backup_name[260]; UTIL_Format(backup_name, sizeof(backup_name), "%s" SEPCHAR "gameinfo.backup.txt", gamedir); @@ -242,10 +264,17 @@ extern "C" void _LoadFunction() RenameFile(backup_name, old_path); return; } + RemoveFile(new_path); + + Error("Server is restarting to load Metamod:Source"); +} + +bool RemoveFile(const char *file) +{ #if defined _MSC_VER - _unlink(new_path); + return (_unlink(file) == 0); #else - unlink(new_path); + return (unlink(file) == 0); #endif }