From eb56fcbe02f35ed4f418a7dc53cd9eb0ad95a504 Mon Sep 17 00:00:00 2001 From: BobTheBob <32057864+BobTheBob9@users.noreply.github.com> Date: Mon, 2 Aug 2021 03:20:10 +0100 Subject: add dynamic keyvalue building, client serverbrowser stuff --- .../NorthstarDedicatedTest.vcxproj | 4 + .../NorthstarDedicatedTest.vcxproj.filters | 12 +++ NorthstarDedicatedTest/convar.cpp | 4 +- NorthstarDedicatedTest/convar.h | 2 +- NorthstarDedicatedTest/dllmain.cpp | 2 + NorthstarDedicatedTest/filesystem.cpp | 16 +++- NorthstarDedicatedTest/keyvalues.cpp | 96 +++++++++++++++++++ NorthstarDedicatedTest/keyvalues.h | 1 + NorthstarDedicatedTest/modmanager.cpp | 54 +++++++++-- NorthstarDedicatedTest/modmanager.h | 9 +- NorthstarDedicatedTest/scriptmodmenu.cpp | 13 ++- NorthstarDedicatedTest/scriptserverbrowser.cpp | 103 +++++++++++++++++++++ NorthstarDedicatedTest/scriptserverbrowser.h | 4 + NorthstarDedicatedTest/scriptsrson.cpp | 1 - NorthstarDedicatedTest/serverauthentication.cpp | 32 ++++--- NorthstarDedicatedTest/serverauthentication.h | 2 +- NorthstarDedicatedTest/squirrel.cpp | 5 + NorthstarDedicatedTest/squirrel.h | 4 + 18 files changed, 330 insertions(+), 34 deletions(-) create mode 100644 NorthstarDedicatedTest/keyvalues.cpp create mode 100644 NorthstarDedicatedTest/keyvalues.h create mode 100644 NorthstarDedicatedTest/scriptserverbrowser.cpp create mode 100644 NorthstarDedicatedTest/scriptserverbrowser.h (limited to 'NorthstarDedicatedTest') diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj index 203edbb3..4e3a5bc0 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj @@ -303,11 +303,13 @@ + + @@ -325,6 +327,7 @@ + @@ -334,6 +337,7 @@ Create + diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters index 71bae5bc..cb78dff1 100644 --- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters +++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters @@ -537,6 +537,12 @@ Header Files\Client + + Header Files\Client + + + Header Files\Shared\Mods\Compiled + @@ -596,6 +602,12 @@ Source Files\Client + + Source Files\Client + + + Source Files\Shared\Mods\Compiled + diff --git a/NorthstarDedicatedTest/convar.cpp b/NorthstarDedicatedTest/convar.cpp index 3bb95a95..156301b6 100644 --- a/NorthstarDedicatedTest/convar.cpp +++ b/NorthstarDedicatedTest/convar.cpp @@ -3,7 +3,7 @@ #include // should this be in modmanager? -std::set g_CustomConvars; // this is used in modloading code to determine whether we've registered a mod convar already +std::unordered_map g_CustomConvars; // this is used in modloading code to determine whether we've registered a mod convar already typedef void(*ConVarConstructorType)(ConVar* newVar, const char* name, const char* defaultValue, int flags, const char* helpString); ConVarConstructorType conVarConstructor; @@ -16,7 +16,7 @@ ConVar* RegisterConVar(const char* name, const char* defaultValue, int flags, co ConVar* newVar = new ConVar; conVarConstructor(newVar, name, defaultValue, flags, helpString); - g_CustomConvars.insert(name); + g_CustomConvars.insert(std::make_pair(name, newVar)); return newVar; } diff --git a/NorthstarDedicatedTest/convar.h b/NorthstarDedicatedTest/convar.h index adfd585f..f2e35188 100644 --- a/NorthstarDedicatedTest/convar.h +++ b/NorthstarDedicatedTest/convar.h @@ -103,4 +103,4 @@ public: ConVar* RegisterConVar(const char* name, const char* defaultValue, int flags, const char* helpString); void InitialiseConVars(HMODULE baseAddress); -extern std::set g_CustomConvars; \ No newline at end of file +extern std::unordered_map g_CustomConvars; \ No newline at end of file diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp index b0040598..4e347d05 100644 --- a/NorthstarDedicatedTest/dllmain.cpp +++ b/NorthstarDedicatedTest/dllmain.cpp @@ -10,6 +10,7 @@ #include "filesystem.h" #include "serverauthentication.h" #include "scriptmodmenu.h" +#include "scriptserverbrowser.h" bool initialised = false; @@ -56,6 +57,7 @@ void InitialiseNorthstar() AddDllLoadCallback("client.dll", InitialiseSourceConsole); AddDllLoadCallback("client.dll", InitialiseScriptModMenu); + AddDllLoadCallback("client.dll", InitialiseScriptServerBrowser); } AddDllLoadCallback("server.dll", InitialiseServerSquirrel); diff --git a/NorthstarDedicatedTest/filesystem.cpp b/NorthstarDedicatedTest/filesystem.cpp index 323b8756..15b8b4dd 100644 --- a/NorthstarDedicatedTest/filesystem.cpp +++ b/NorthstarDedicatedTest/filesystem.cpp @@ -88,12 +88,13 @@ void SetNewModSearchPaths(Mod* mod) } -bool TryReplaceFile(char* path) +bool TryReplaceFile(char* path, bool shouldCompile) { if (readingOriginalFile) return false; - (*g_ModManager).CompileAssetsForFile(path); + if (shouldCompile) + (*g_ModManager).CompileAssetsForFile(path); // idk how efficient the lexically normal check is // can't just set all /s in path to \, since some paths aren't in writeable memory @@ -111,7 +112,9 @@ FileHandle_t ReadFileFromVPKHook(VPKData* vpkInfo, __int64* b, char* filename) { // move this to a convar at some point when we can read them in native //spdlog::info("ReadFileFromVPKHook {} {}", filename, vpkInfo->path); - if (TryReplaceFile(filename)) + + // there is literally never any reason to compile here, since we'll always compile in ReadFileFromFilesystemHook in the same codepath this is called + if (TryReplaceFile(filename, false)) { *b = -1; return b; @@ -125,7 +128,7 @@ bool ReadFromCacheHook(IFileSystem* filesystem, char* path, void* result) // move this to a convar at some point when we can read them in native //spdlog::info("ReadFromCacheHook {}", path); - if (TryReplaceFile(path)) + if (TryReplaceFile(path, true)) return false; return readFromCache(filesystem, path, result); @@ -146,6 +149,9 @@ void AddSearchPathHook(IFileSystem* fileSystem, const char* pPath, const char* p FileHandle_t ReadFileFromFilesystemHook(IFileSystem* filesystem, const char* pPath, const char* pOptions, int64_t a4, uint32_t a5) { // this isn't super efficient, but it's necessary, since calling addsearchpath in readfilefromvpk doesn't work, possibly refactor later - TryReplaceFile((char*)pPath); + // it also might be possible to hook functions that are called later, idk look into callstack for ReadFileFromVPK + if (!readingOriginalFile) + TryReplaceFile((char*)pPath, true); + return readFileFromFilesystem(filesystem, pPath, pOptions, a4, a5); } \ No newline at end of file diff --git a/NorthstarDedicatedTest/keyvalues.cpp b/NorthstarDedicatedTest/keyvalues.cpp new file mode 100644 index 00000000..b2c278c6 --- /dev/null +++ b/NorthstarDedicatedTest/keyvalues.cpp @@ -0,0 +1,96 @@ +#include "pch.h" +#include "keyvalues.h" +#include "modmanager.h" +#include "filesystem.h" + +#include + +void ModManager::TryBuildKeyValues(const char* filename) +{ + spdlog::info("Building KeyValues for file {}", filename); + + std::string normalisedPath = fs::path(filename).lexically_normal().string(); + fs::path compiledPath = COMPILED_ASSETS_PATH / filename; + fs::path compiledDir = compiledPath.parent_path(); + fs::create_directories(compiledDir); + + fs::path kvPath(filename); + std::string ogFilePath = "mod_original_"; + ogFilePath += kvPath.filename().string(); + + std::string newKvs = "// AUTOGENERATED: MOD PATCH KV\n"; + + int patchNum = 0; + + // copy over patch kv files, and add #includes to new file, last mods' patches should be applied first + for (int i = m_loadedMods.size() - 1; i > -1; i--) + { + size_t fileHash = std::hash{}(normalisedPath); + for (int j = 0; j < m_loadedMods[i]->KeyValuesHash.size(); j++) + { + if (fileHash == m_loadedMods[i]->KeyValuesHash[j]) + { + // should result in smth along the lines of #include "mod_patch_5_mp_weapon_car.txt" + + std::string patchFilePath = "mod_patch_"; + patchFilePath += std::to_string(patchNum++); + patchFilePath += "_"; + patchFilePath += kvPath.filename().string(); + + newKvs += "#base \""; + newKvs += patchFilePath; + newKvs += "\"\n"; + + fs::remove(compiledDir / patchFilePath); + + fs::copy_file(m_loadedMods[i]->ModDirectory / "keyvalues" / filename, compiledDir / patchFilePath); + } + } + } + + newKvs += "#base \""; + newKvs += ogFilePath; + newKvs += "\"\n"; + + // load original file, so we can parse out the name of the root obj (e.g. WeaponData for weapons) + std::string originalFile = ReadVPKOriginalFile(filename); + char rootName[64]; + memset(rootName, 0, sizeof(rootName)); + + // iterate over all lines that aren't empty, and don't start with #s or //s, first one should be the name of the root obj + int i = 0; + while (!(originalFile[i] >= 65 && originalFile[i] <= 122)) + { + // if we hit a comment or # thing, iterate until end of line + if (originalFile[i] == '/' || originalFile[i] == '#') + while (originalFile[i] != '\n') + i++; + + i++; + } + + int j = 0; + for (int j = 0; originalFile[i] >= 65 && originalFile[i] <= 122; j++) + rootName[j] = originalFile[i++]; + + // empty kv, all the other stuff gets #base'd or #include'd + newKvs += rootName; + newKvs += "\n{\n}\n"; + + std::ofstream originalFileWriteStream(compiledDir / ogFilePath); + originalFileWriteStream << originalFile; + originalFileWriteStream.close(); + + std::ofstream writeStream(compiledPath); + writeStream << newKvs; + writeStream.close(); + + ModOverrideFile* overrideFile = new ModOverrideFile; + overrideFile->owningMod = nullptr; + overrideFile->path = normalisedPath; + + if (m_modFiles.find(normalisedPath) == m_modFiles.end()) + m_modFiles.insert(std::make_pair(normalisedPath, overrideFile)); + else + m_modFiles[normalisedPath] = overrideFile; +} \ No newline at end of file diff --git a/NorthstarDedicatedTest/keyvalues.h b/NorthstarDedicatedTest/keyvalues.h new file mode 100644 index 00000000..7b9637ef --- /dev/null +++ b/NorthstarDedicatedTest/keyvalues.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp index ae1ad98a..faca09c4 100644 --- a/NorthstarDedicatedTest/modmanager.cpp +++ b/NorthstarDedicatedTest/modmanager.cpp @@ -173,10 +173,7 @@ ModManager::ModManager() void ModManager::LoadMods() { - // this needs better support for reloads - - // do we need to dealloc individual entries in m_loadedMods? idk, rework - m_loadedMods.clear(); + UnloadMods(); std::vector modDirs; @@ -228,6 +225,11 @@ void ModManager::LoadMods() for (Mod* mod : m_loadedMods) { + mod->KeyValuesHash.clear(); + + if (!mod->Enabled) + continue; + // register convars // for reloads, this is sorta barebones, when we have a good findconvar method, we could probably reset flags and stuff on preexisting convars // potentially it might also be good to unregister convars if they get removed on a reload, but unsure if necessary @@ -240,11 +242,27 @@ void ModManager::LoadMods() for (fs::directory_entry file : fs::directory_iterator(mod->ModDirectory / "vpk")) if (fs::is_regular_file(file) && file.path().extension() == "vpk") mod->Vpks.push_back(file.path().string()); + + if (fs::exists(mod->ModDirectory / "keyvalues")) + { + for (fs::directory_entry file : fs::recursive_directory_iterator(mod->ModDirectory / "keyvalues")) + { + if (fs::is_regular_file(file) && !file.path().extension().compare(".txt")) + { + std::string kvStr = file.path().lexically_relative(mod->ModDirectory / "keyvalues").lexically_normal().string(); + mod->KeyValuesHash.push_back(std::hash{}(kvStr)); + mod->KeyValues.push_back(kvStr); + } + } + } } // in a seperate loop because we register mod files in reverse order, since mods loaded later should have their files prioritised for (int i = m_loadedMods.size() - 1; i > -1; i--) { + if (!m_loadedMods[i]->Enabled) + continue; + if (fs::exists(m_loadedMods[i]->ModDirectory / MOD_OVERRIDE_DIR)) { for (fs::directory_entry file : fs::recursive_directory_iterator(m_loadedMods[i]->ModDirectory / MOD_OVERRIDE_DIR)) @@ -253,7 +271,6 @@ void ModManager::LoadMods() if (file.is_regular_file() && m_modFiles.find(path.string()) == m_modFiles.end()) { - // super temp because it relies hard on load order ModOverrideFile* modFile = new ModOverrideFile; modFile->owningMod = m_loadedMods[i]; modFile->path = path; @@ -264,13 +281,38 @@ void ModManager::LoadMods() } } +void ModManager::UnloadMods() +{ + // clean up stuff from mods before we unload + + // remove all built kvs + for (Mod* mod : m_loadedMods) + for (std::string kvPaths : mod->KeyValues) + fs::remove(COMPILED_ASSETS_PATH / fs::path(kvPaths).lexically_relative(mod->ModDirectory)); + + // do we need to dealloc individual entries in m_loadedMods? idk, rework + m_loadedMods.clear(); +} + void ModManager::CompileAssetsForFile(const char* filename) { fs::path path(filename); if (!path.filename().compare("scripts.rson")) BuildScriptsRson(); - + else if (!strcmp((filename + strlen(filename)) - 3, "txt")) // check if it's a .txt + { + // check if we should build keyvalues, depending on whether any of our mods have patch kvs for this file + for (Mod* mod : m_loadedMods) + { + size_t fileHash = std::hash{}(fs::path(filename).lexically_normal().string()); + if (std::find(mod->KeyValuesHash.begin(), mod->KeyValuesHash.end(), fileHash) != mod->KeyValuesHash.end()) + { + TryBuildKeyValues(filename); + return; + } + } + } } void ReloadModsCommand(const CCommand& args) diff --git a/NorthstarDedicatedTest/modmanager.h b/NorthstarDedicatedTest/modmanager.h index 6146de0a..ad5e74ff 100644 --- a/NorthstarDedicatedTest/modmanager.h +++ b/NorthstarDedicatedTest/modmanager.h @@ -1,4 +1,5 @@ #pragma once +#include "convar.h" #include #include #include @@ -45,7 +46,9 @@ public: class Mod { public: + // runtime stuff fs::path ModDirectory; + bool Enabled = true; // mod.json stuff: @@ -71,7 +74,8 @@ public: // other files: std::vector Vpks; - //std::vector KeyValues; + std::vector KeyValues; + std::vector KeyValuesHash; // size_t because we hash these filesnames: faster than string comp // other stuff @@ -92,16 +96,17 @@ class ModManager { public: std::vector m_loadedMods; - //std::vector m_modFiles; std::unordered_map m_modFiles; public: ModManager(); void LoadMods(); + void UnloadMods(); void CompileAssetsForFile(const char* filename); // compile asset type stuff, these are done in files under Mods/Compiled/ void BuildScriptsRson(); + void TryBuildKeyValues(const char* filename); }; void InitialiseModManager(HMODULE baseAddress); diff --git a/NorthstarDedicatedTest/scriptmodmenu.cpp b/NorthstarDedicatedTest/scriptmodmenu.cpp index f65b3a8c..cb19e48f 100644 --- a/NorthstarDedicatedTest/scriptmodmenu.cpp +++ b/NorthstarDedicatedTest/scriptmodmenu.cpp @@ -113,12 +113,21 @@ SQInteger SQ_GetModConvars(void* sqvm) return 1; // return empty array } +// void NSReloadMods() +SQInteger SQ_ReloadMods(void* sqvm) +{ + g_ModManager->LoadMods(); + return 0; +} + void InitialiseScriptModMenu(HMODULE baseAddress) { g_UISquirrelManager->AddFuncRegistration("array", "NSGetModNames", "", "Returns the names of all loaded mods", SQ_GetModNames); - g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDescriptionByModName", "asset modName", "Returns a given mod's description", SQ_GetModDescription); + g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDescriptionByModName", "string modName", "Returns a given mod's description", SQ_GetModDescription); g_UISquirrelManager->AddFuncRegistration("string", "NSGetModVersionByModName", "string modName", "Returns a given mod's version", SQ_GetModVersion); - g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDownloadLinkByModName", "string modName", "Returns a given mod's download link", SQ_GetModVersion); + g_UISquirrelManager->AddFuncRegistration("string", "NSGetModDownloadLinkByModName", "string modName", "Returns a given mod's download link", SQ_GetModDownloadLink); g_UISquirrelManager->AddFuncRegistration("int", "NSGetModLoadPriority", "string modName", "Returns a given mod's load priority", SQ_GetModLoadPriority); g_UISquirrelManager->AddFuncRegistration("array", "NSGetModConvarsByModName", "string modName", "Returns the names of all a given mod's cvars", SQ_GetModConvars); + + g_UISquirrelManager->AddFuncRegistration("void", "NSReloadMods", "", "Reloads mods", SQ_ReloadMods); } \ No newline at end of file diff --git a/NorthstarDedicatedTest/scriptserverbrowser.cpp b/NorthstarDedicatedTest/scriptserverbrowser.cpp new file mode 100644 index 00000000..2f1c95a4 --- /dev/null +++ b/NorthstarDedicatedTest/scriptserverbrowser.cpp @@ -0,0 +1,103 @@ +#include "pch.h" +#include "scriptserverbrowser.h" +#include "squirrel.h" + +// functions for viewing server browser + +// bool function NSPollServerPage( int page ) +SQInteger SQ_PollServerPage(void* sqvm) +{ + SQInteger page = ClientSq_getinteger(sqvm, 1); + + ClientSq_pushbool(sqvm, true); + return 1; +} + +// int function NSGetNumServersOnPage( int page ) +SQInteger SQ_GetNumServersOnPage(void* sqvm) +{ + SQInteger page = ClientSq_getinteger(sqvm, 1); + + ClientSq_pushinteger(sqvm, 1); + return 1; +} + +// string function NSGetServerName( int page, int serverIndex ) +SQInteger SQ_GetServerName(void* sqvm) +{ + SQInteger page = ClientSq_getinteger(sqvm, 1); + SQInteger serverIndex = ClientSq_getinteger(sqvm, 2); + + ClientSq_pushstring(sqvm, "cool", -1); + return 1; +} + +// string function NSGetServerMap( int page, int serverIndex ) +SQInteger SQ_GetServerMap(void* sqvm) +{ + SQInteger page = ClientSq_getinteger(sqvm, 1); + SQInteger serverIndex = ClientSq_getinteger(sqvm, 2); + + ClientSq_pushstring(sqvm, "mp_thaw", -1); + return 1; +} + +// string function NSGetServerMode( int page, int serverIndex ) +SQInteger SQ_GetServerMode(void* sqvm) +{ + SQInteger page = ClientSq_getinteger(sqvm, 1); + SQInteger serverIndex = ClientSq_getinteger(sqvm, 2); + + ClientSq_pushstring(sqvm, "ffa", -1); + return 1; +} + +// string function NSGetServerID( int page, int serverIndex ) +SQInteger SQ_GetServerID(void* sqvm) +{ + + return 0; +} + +// void function NSResetRecievedServers() +SQInteger SQ_ResetRecievedServers(void* sqvm) +{ + return 0; +} + + +// functions for authenticating with servers + +// void function NSTryAuthWithServer( string serverId ) +SQInteger SQ_TryAuthWithServer(void* sqvm) +{ + return 0; +} + +// int function NSWasAuthSuccessful() +SQInteger SQ_WasAuthSuccessful(void* sqvm) +{ + return 0; +} + +// string function NSTryGetAuthedServerAddress() +SQInteger SQ_TryGetAuthedServerAddress(void* sqvm) +{ + return 0; +} + +// string function NSTryGetAuthedServerToken() +SQInteger SQ_TryGetAuthedServerToken(void* sqvm) +{ + return 0; +} + +void InitialiseScriptServerBrowser(HMODULE baseAddress) +{ + g_UISquirrelManager->AddFuncRegistration("bool", "NSPollServerPage", "int page", "", SQ_PollServerPage); + g_UISquirrelManager->AddFuncRegistration("int", "NSGetNumServersOnPage", "int page", "", SQ_GetNumServersOnPage); + g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerName", "int page, int serverIndex", "", SQ_GetServerName); + g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMap", "int page, int serverIndex", "", SQ_GetServerMap); + g_UISquirrelManager->AddFuncRegistration("string", "NSGetServerMode", "int page, int serverIndex", "", SQ_GetServerMode); + g_UISquirrelManager->AddFuncRegistration("void", "NSResetRecievedServers", "", "", SQ_ResetRecievedServers); +} \ No newline at end of file diff --git a/NorthstarDedicatedTest/scriptserverbrowser.h b/NorthstarDedicatedTest/scriptserverbrowser.h new file mode 100644 index 00000000..55776de0 --- /dev/null +++ b/NorthstarDedicatedTest/scriptserverbrowser.h @@ -0,0 +1,4 @@ +#pragma once +#include + +void InitialiseScriptServerBrowser(HMODULE baseAddress); \ No newline at end of file diff --git a/NorthstarDedicatedTest/scriptsrson.cpp b/NorthstarDedicatedTest/scriptsrson.cpp index 9c590280..bc49ed26 100644 --- a/NorthstarDedicatedTest/scriptsrson.cpp +++ b/NorthstarDedicatedTest/scriptsrson.cpp @@ -4,7 +4,6 @@ #include "filesystem.h" #include "squirrel.h" -#include #include void ModManager::BuildScriptsRson() diff --git a/NorthstarDedicatedTest/serverauthentication.cpp b/NorthstarDedicatedTest/serverauthentication.cpp index d6f3b2b2..ffc21a8b 100644 --- a/NorthstarDedicatedTest/serverauthentication.cpp +++ b/NorthstarDedicatedTest/serverauthentication.cpp @@ -7,7 +7,7 @@ // hook types -typedef void*(*CBaseServer__ConnectClientType)(void* server, void* a2, void* a3, uint32_t a4, uint32_t a5, int32_t a6, void* a7, void* a8, char* serverFilter, void* a10, char a11, void* a12, char a13, char a14, void* a15, uint32_t a16, uint32_t a17); +typedef void*(*CBaseServer__ConnectClientType)(void* server, void* a2, void* a3, uint32_t a4, uint32_t a5, int32_t a6, void* a7, void* a8, char* serverFilter, void* a10, char a11, void* a12, char a13, char a14, int64_t uid, uint32_t a16, uint32_t a17); CBaseServer__ConnectClientType CBaseServer__ConnectClient; typedef char(*CBaseClient__ConnectType)(void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, int a7); @@ -34,16 +34,19 @@ void ServerAuthenticationManager::AddPlayerAuth(char* authToken, char* uid, char } -bool ServerAuthenticationManager::AuthenticatePlayer(void* player, char* authToken) +bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, char* authToken) { - // straight up just given up + std::string strUid = std::to_string(uid); + if (!m_authData.empty() && m_authData.count(authToken)) { // use stored auth data AuthData* authData = m_authData[authToken]; - + if (strcmp(strUid.c_str(), authData->uid)) // connecting client's uid is different from auth's uid + return false; + // uuid - strcpy((char*)player + 0xF500, authData->uid); + strcpy((char*)player + 0xF500, strUid.c_str()); // copy pdata into buffer memcpy((char*)player + 0x4FA, authData->pdata, authData->pdataSize); @@ -56,14 +59,13 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, char* authTok if (!CVar_ns_auth_allow_insecure->m_nValue) // no auth data and insecure connections aren't allowed, so dc the client return false; - // insecure connections are allowed, try reading from disk, using authtoken as uid - + // insecure connections are allowed, try reading from disk // uuid - strcpy((char*)player + 0xF500, authToken); + strcpy((char*)player + 0xF500, strUid.c_str()); // try reading pdata file for player std::string pdataPath = "playerdata/playerdata_"; - pdataPath += authToken; + pdataPath += strUid; pdataPath += ".pdata"; std::fstream pdataStream(pdataPath, std::ios_base::in); @@ -120,16 +122,18 @@ void ServerAuthenticationManager::WritePersistentData(void* player) // auth hooks -// store this in a var so we can use it in CBaseClient::Connect -// this is fine because serverfilter ptr won't decay by the time we use this, just don't use it outside of cbaseclient::connect +// store these in vars so we can use them in CBaseClient::Connect +// this is fine because ptrs won't decay by the time we use this, just don't use it outside of cbaseclient::connect char* nextPlayerToken; +int64_t nextPlayerUid; -void* CBaseServer__ConnectClientHook(void* server, void* a2, void* a3, uint32_t a4, uint32_t a5, int32_t a6, void* a7, void* a8, char* serverFilter, void* a10, char a11, void* a12, char a13, char a14, void* a15, uint32_t a16, uint32_t a17) +void* CBaseServer__ConnectClientHook(void* server, void* a2, void* a3, uint32_t a4, uint32_t a5, int32_t a6, void* a7, void* a8, char* serverFilter, void* a10, char a11, void* a12, char a13, char a14, int64_t uid, uint32_t a16, uint32_t a17) { // auth tokens are sent with serverfilter, can't be accessed from player struct to my knowledge, so have to do this here nextPlayerToken = serverFilter; + nextPlayerUid = uid; - return CBaseServer__ConnectClient(server, a2, a3, a4, a5, a6, a7, a8, serverFilter, a10, a11, a12, a13, a14, a15, a16, a17); + return CBaseServer__ConnectClient(server, a2, a3, a4, a5, a6, a7, a8, serverFilter, a10, a11, a12, a13, a14, uid, a16, a17); } char CBaseClient__ConnectHook(void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, int a7) @@ -139,7 +143,7 @@ char CBaseClient__ConnectHook(void* self, char* name, __int64 netchan_ptr_arg, c char ret = CBaseClient__Connect(self, name, netchan_ptr_arg, b_fake_player_arg, a5, Buffer, a7); if (strlen(name) >= 64) // fix for name overflow bug CBaseClient__Disconnect(self, 1, "Invalid name"); - else if (!g_ServerAuthenticationManager->AuthenticatePlayer(self, nextPlayerToken)) + else if (!g_ServerAuthenticationManager->AuthenticatePlayer(self, nextPlayerUid, nextPlayerToken)) CBaseClient__Disconnect(self, 1, "Authentication Failed"); return ret; diff --git a/NorthstarDedicatedTest/serverauthentication.h b/NorthstarDedicatedTest/serverauthentication.h index 4301b78e..c28c882b 100644 --- a/NorthstarDedicatedTest/serverauthentication.h +++ b/NorthstarDedicatedTest/serverauthentication.h @@ -18,7 +18,7 @@ public: public: void AddPlayerAuth(char* authToken, char* uid, char* pdata, size_t pdataSize); - bool AuthenticatePlayer(void* player, char* authToken); + bool AuthenticatePlayer(void* player, int64_t uid, char* authToken); bool RemovePlayerAuthData(void* player); void WritePersistentData(void* player); }; diff --git a/NorthstarDedicatedTest/squirrel.cpp b/NorthstarDedicatedTest/squirrel.cpp index 17758282..46e4708a 100644 --- a/NorthstarDedicatedTest/squirrel.cpp +++ b/NorthstarDedicatedTest/squirrel.cpp @@ -66,6 +66,9 @@ sq_pushintegerType ServerSq_pushinteger; sq_pushfloatType ClientSq_pushfloat; sq_pushfloatType ServerSq_pushfloat; +sq_pushboolType ClientSq_pushbool; +sq_pushboolType ServerSq_pushbool; + // sq stack get funcs sq_getstringType ClientSq_getstring; @@ -118,6 +121,7 @@ void InitialiseClientSquirrel(HMODULE baseAddress) ClientSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440); ClientSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0); ClientSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800); + ClientSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710); ClientSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60C0); ClientSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60E0); @@ -147,6 +151,7 @@ void InitialiseServerSquirrel(HMODULE baseAddress) ServerSq_pushstring = (sq_pushstringType)((char*)baseAddress + 0x3440); ServerSq_pushinteger = (sq_pushintegerType)((char*)baseAddress + 0x36A0); ServerSq_pushfloat = (sq_pushfloatType)((char*)baseAddress + 0x3800); + ServerSq_pushbool = (sq_pushboolType)((char*)baseAddress + 0x3710); ServerSq_getstring = (sq_getstringType)((char*)baseAddress + 0x60A0); ServerSq_getinteger = (sq_getintegerType)((char*)baseAddress + 0x60C0); diff --git a/NorthstarDedicatedTest/squirrel.h b/NorthstarDedicatedTest/squirrel.h index b094dbaf..66abcd76 100644 --- a/NorthstarDedicatedTest/squirrel.h +++ b/NorthstarDedicatedTest/squirrel.h @@ -96,6 +96,10 @@ typedef void(*sq_pushfloatType)(void* sqvm, SQFloat f); extern sq_pushfloatType ClientSq_pushfloat; extern sq_pushfloatType ServerSq_pushfloat; +typedef void(*sq_pushboolType)(void* sqvm, SQBool b); +extern sq_pushboolType ClientSq_pushbool; +extern sq_pushboolType ServerSq_pushbool; + // sq stack get funcs typedef const SQChar*(*sq_getstringType)(void* sqvm, SQInteger stackpos); -- cgit v1.2.3