From b8744a9ab83a172c83c303e28916e4b480568a34 Mon Sep 17 00:00:00 2001 From: rexx <67599507+r-ex@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:45:58 +0100 Subject: [PATCH 1/3] create sv_language cvar currently unused, will be implemented in #103 --- r5dev/common/callback.cpp | 50 +++++++++++++++++++++++++++++++++++++++ r5dev/common/callback.h | 1 + r5dev/common/global.cpp | 4 ++++ r5dev/common/global.h | 1 + 4 files changed, 56 insertions(+) diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index 2e80a016..87229496 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -991,6 +991,56 @@ void RCON_Disconnect_f(const CCommand& args) } #endif // !DEDICATED +#ifndef CLIENT_DLL + +static const char* s_LanguageNames[] = { + "english", + "french", + "german", + "italian", + "japanese", + "polish", + "russian", + "spanish", + "schinese", + "tchinese", + "korean" +}; + +static bool IsValidTextLanguage(const char* pLocaleName) +{ + for (int i = 0; i < SDK_ARRAYSIZE(s_LanguageNames); ++i) + { + if (strcmp(pLocaleName, s_LanguageNames[i]) == NULL) + return true; + } + + return false; +} + +void SV_LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetCommandName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (IsValidTextLanguage(pNewString)) + return; + + // if new text isn't valid but the old value is, reset the value + if (IsValidTextLanguage(pOldString)) + { + pConVarRef->SetValue(pOldString); + return; + } + else // this shouldn't really happen, but if neither the old nor new values are valid, set to english + pConVarRef->SetValue("english"); + + } +} + +#endif + /* ===================== RCON_PasswordChanged_f diff --git a/r5dev/common/callback.h b/r5dev/common/callback.h index 9d42da2e..096c2a67 100644 --- a/r5dev/common/callback.h +++ b/r5dev/common/callback.h @@ -53,6 +53,7 @@ void RCON_Disconnect_f(const CCommand& args); #endif // !DEDICATED void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); #ifndef CLIENT_DLL +void SV_LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue); void SQVM_ServerScript_f(const CCommand& args); diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 094fcd33..1a6cd382 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -89,6 +89,8 @@ ConVar* navmesh_draw_poly_bounds = nullptr; ConVar* navmesh_draw_poly_bounds_inner = nullptr; #endif // !DEDICATED +ConVar* sv_language = nullptr; + ConVar* sv_showconnecting = nullptr; ConVar* sv_globalBanlist = nullptr; ConVar* sv_pylonVisibility = nullptr; @@ -308,6 +310,8 @@ void ConVar_StaticInit(void) navmesh_draw_poly_bounds = ConVar::StaticCreate("navmesh_draw_poly_bounds" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the bounds of the NavMesh polys.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); navmesh_draw_poly_bounds_inner = ConVar::StaticCreate("navmesh_draw_poly_bounds_inner" , "0" , FCVAR_DEVELOPMENTONLY, "Draws the inner bounds of the NavMesh polys (requires navmesh_draw_poly_bounds).", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); #endif // !DEDICATED + + sv_language = ConVar::StaticCreate("sv_language", "english", FCVAR_RELEASE, "Language of the server. Sent to MasterServer for localising error messages", false, 0.f, false, 0.f, SV_LanguageChanged_f, nullptr); sv_showconnecting = ConVar::StaticCreate("sv_showconnecting" , "1", FCVAR_RELEASE, "Logs information about the connecting client to the console.", false, 0.f, false, 0.f, nullptr, nullptr); sv_globalBanlist = ConVar::StaticCreate("sv_globalBanlist" , "1", FCVAR_RELEASE, "Determines whether or not to use the global banned list.", false, 0.f, false, 0.f, nullptr, "0 = Disable, 1 = Enable."); sv_pylonVisibility = ConVar::StaticCreate("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visibility to the Pylon master server.", false, 0.f, false, 0.f, nullptr, "0 = Offline, 1 = Hidden, 2 = Public."); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 13a5e660..95d32c8f 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -79,6 +79,7 @@ extern ConVar* navmesh_draw_polys; extern ConVar* navmesh_draw_poly_bounds; extern ConVar* navmesh_draw_poly_bounds_inner; #endif // DEDICATED +extern ConVar* sv_language; extern ConVar* sv_showconnecting; extern ConVar* sv_globalBanlist; extern ConVar* sv_pylonVisibility; From 010c0d0c209efe0eeca2e59f033ceffea23c74ea Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:43:22 +0200 Subject: [PATCH 2/3] Improve manifest script - Add configuration support for each depot - Add configurable vendor for each depot - Add size field for each depot (used for installer's progress callback) - Compute depot package checksum on the spot - Take manifest version input as string instead (used as tags) --- r5dev/resource/script/bld_man.py | 106 ++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 24 deletions(-) diff --git a/r5dev/resource/script/bld_man.py b/r5dev/resource/script/bld_man.py index 4b4de6f9..9a5cabf5 100644 --- a/r5dev/resource/script/bld_man.py +++ b/r5dev/resource/script/bld_man.py @@ -8,16 +8,20 @@ import hashlib # Compute the SHA-256 checksum of a file #------------------------------------------------------------------------------ def ComputeChecksum(filePath, blockSize=65536): - checksum = hashlib.sha256() + sha256 = hashlib.sha256() with open(filePath, "rb") as file: for block in iter(lambda: file.read(blockSize), b""): - checksum.update(block) - return checksum.hexdigest() + sha256.update(block) + + checksum = sha256.hexdigest() + print(f"*** computed checksum for '{filePath}': {checksum}") + + return checksum #------------------------------------------------------------------------------ # Compute checksums for all files in a directory #------------------------------------------------------------------------------ -def RecursiveComputeChecksum(directoryPath): +def RecursiveComputeChecksum(directoryPath, settings): checksums = {} scriptPath = os.path.abspath(__file__) @@ -32,42 +36,96 @@ def RecursiveComputeChecksum(directoryPath): continue checksum = ComputeChecksum(filePath) - checksums[normalizedPath] = checksum + checksums[normalizedPath] = { + "checksum": checksum, + "restart": False + } + + # Check if the file should be updated/installed during a restart + if settings and "restart" in settings: + restart_files = settings["restart"] + for file in restart_files: + if file in checksums: + checksums[file]["restart"] = True return checksums + +#------------------------------------------------------------------------------ +# Gets the settings for this depot +#------------------------------------------------------------------------------ +def GetDepotSettings(depotName): + settingsPath = os.path.join('devops', f'{depotName}.json') + print(f"{settingsPath}") + if not os.path.isfile(settingsPath): + settingsPath = os.path.join('devops', 'default.json') + if not os.path.isfile(settingsPath): + return None + + f = open(settingsPath) + if f.closed: + print(f"{settingsPath} = closed") + return None + + return json.load(f) + + #------------------------------------------------------------------------------ # Save the checksums to a manifest file #------------------------------------------------------------------------------ -def CreateManifest(version, depot, checksums, outManifestFile): +def CreateManifest(version, currentDirectory, outManifestFile): + depotList = [name for name in os.listdir(currentDirectory) if os.path.isdir(os.path.join(currentDirectory, name))] + manifest = { "version": version, - "depots": { - depot: { - "checksum": 0, - "optional": False, - "assets": checksums - } - } + "depot": {} } + + i = 0 + for depot in depotList: + fileName = f"{depot}.zip" + + # Each depot must have a release package !!! + zipFilePath = os.path.join(currentDirectory, 'release', fileName) + + print(f"{zipFilePath}") + if not os.path.isfile(zipFilePath): + continue + + # Each depot must have a configuration !!! + settings = GetDepotSettings(depot) + if not settings: + continue + + print(f"*** processing depot '{depot}'...") + + checksum = ComputeChecksum(zipFilePath) + size = os.path.getsize(zipFilePath) + + depotData = { + "name": fileName, + "size": size, + "checksum": checksum, + "optional": False, + "vendor": settings["vendor"], + "assets": RecursiveComputeChecksum(os.path.join(currentDirectory, depot), settings) + } + + manifest["depot"][i] = depotData + i+=1 + with open(outManifestFile, "w") as jsonFile: json.dump(manifest, jsonFile, indent=4) #------------------------------------------------------------------------------ if __name__ == "__main__": - if len(sys.argv) != 3: - print("Usage: bld_man.py ") + if len(sys.argv) != 2: + print(f"Usage: bld_man.py ") sys.exit(1) - try: - version = int(sys.argv[1]) - depot = sys.argv[2] - except ValueError: - print("Version must be an integer") - sys.exit(1) + version = sys.argv[1] - workingDirectory = os.getcwd() + currentDirectory = os.path.dirname(os.path.abspath(__file__)) outManifestFile = "manifest_patch.json" - checksums = RecursiveComputeChecksum(workingDirectory) - CreateManifest(version, depot, checksums, outManifestFile) + CreateManifest(version, currentDirectory, outManifestFile) From b967a11ffd79b946fd3c9f5bc3a824a817873f0c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 3 Aug 2023 16:56:27 +0200 Subject: [PATCH 3/3] Make switching source directories easier Engine src dir can now be switched with 1 var in CMake. --- CMakeLists.txt | 8 +++++--- r5dev/cmake/Configure.cmake | 2 -- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 263b21c3..50b8e39a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,11 @@ cmake_minimum_required( VERSION 3.16 ) project( r5sdk ) -include( "r5dev/cmake/Configure.cmake" ) -include( "r5dev/cmake/Macros.cmake" ) -include( "r5dev/cmake/Options.cmake" ) +set( ENGINE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/r5dev" CACHE PATH "Engine source directory" ) + +include( "${ENGINE_SOURCE_DIR}/cmake/Configure.cmake" ) +include( "${ENGINE_SOURCE_DIR}/cmake/Macros.cmake" ) +include( "${ENGINE_SOURCE_DIR}/cmake/Options.cmake" ) initial_setup() setup_build_configurations() diff --git a/r5dev/cmake/Configure.cmake b/r5dev/cmake/Configure.cmake index c75eac30..b6ff37a9 100644 --- a/r5dev/cmake/Configure.cmake +++ b/r5dev/cmake/Configure.cmake @@ -5,9 +5,7 @@ macro( initial_setup ) set( CMAKE_CXX_STANDARD 17 ) set( CMAKE_CXX_STANDARD_REQUIRED True ) - set( ENGINE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/r5dev" CACHE PATH "Engine source directory" ) set( THIRDPARTY_SOURCE_DIR "${ENGINE_SOURCE_DIR}/thirdparty" CACHE PATH "Thirdparty source directory" ) - set( BUILD_OUTPUT_DIR "game" CACHE PATH "Build output directory" ) set( GLOBAL_PCH