From e33b566f88339de72d59a6dedc05d9680b4e1361 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:17:49 +0200 Subject: [PATCH 01/25] Split server and client into separate libs Work in progress; does not compile! Moved script registration function to static gamedll libs instead, and used a pointer callback approach for calling them to avoid duplicate symbols during linkage. --- r5dev/core/CMakeLists.txt | 31 ++++- r5dev/game/CMakeLists.txt | 54 +++++++-- r5dev/game/shared/r1/weapon_bolt.h | 2 + r5dev/game/shared/shared_classnames.h | 6 +- r5dev/game/shared/vscript_shared.cpp | 114 ++++++++++++++++-- r5dev/game/shared/vscript_shared.h | 30 +++-- .../languages/squirrel_re/vsquirrel.cpp | 17 ++- .../vscript/languages/squirrel_re/vsquirrel.h | 4 + r5dev/vscript/vscript.cpp | 92 -------------- r5dev/vscript/vscript.h | 4 - 10 files changed, 215 insertions(+), 139 deletions(-) diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index 21871024..06d0847f 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required( VERSION 3.16 ) + macro( add_sdk_project PROJECT_NAME ) add_module( "shared_lib" ${PROJECT_NAME} "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) @@ -79,7 +80,6 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "localize" "vscript" - "game" ) if( NOT ${PROJECT_NAME} STREQUAL "dedicated" ) @@ -99,29 +99,48 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "engine" "d3d11.lib" ) + else() target_link_libraries( ${PROJECT_NAME} PRIVATE - "engine_ds" "materialsystem_nodx" # Needs the No-DirectX version for patching. + "engine_ds" ) endif() +# Determine the compiler definitions and link libraries per project. if( ${PROJECT_NAME} STREQUAL "gamesdk" ) end_sources() + +target_link_libraries( ${PROJECT_NAME} PRIVATE + "server_static" + "client_static" +) target_compile_definitions( ${PROJECT_NAME} PRIVATE "GAMESDK" ) + elseif( ${PROJECT_NAME} STREQUAL "dedicated" ) end_sources() -target_compile_definitions( ${PROJECT_NAME} PRIVATE - "DEDICATED" - "MATERIALSYSTEM_NODX" # Needs the No-DirectX version for patching. + +target_link_libraries( ${PROJECT_NAME} PRIVATE + "server_static" ) +target_compile_definitions( ${PROJECT_NAME} PRIVATE + "MATERIALSYSTEM_NODX" + "SERVER_DLL" + "DEDICATED" +) + elseif( ${PROJECT_NAME} STREQUAL "client" ) end_sources( "${BUILD_OUTPUT_DIR}/bin/x64_retail/" ) + +target_link_libraries( ${PROJECT_NAME} PRIVATE + "client_static" +) target_compile_definitions( ${PROJECT_NAME} PRIVATE "CLIENT_DLL" ) + endif() target_link_options( ${PROJECT_NAME} PRIVATE @@ -161,4 +180,4 @@ endmacro() add_sdk_project( "gamesdk" ) add_sdk_project( "dedicated" ) -#add_sdk_project( "client" ) +add_sdk_project( "client" ) diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index c620400e..8722dde6 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required( VERSION 3.16 ) -add_module( "lib" "game" "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) + +macro( add_game_project PROJECT_NAME ) +add_module( "lib" ${PROJECT_NAME} "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() @@ -33,6 +35,7 @@ add_sources( SOURCE_GROUP "Shared/Weapon" "shared/r1/weapon_bolt.h" ) +if( NOT ${PROJECT_NAME} STREQUAL "client_static" ) add_sources( SOURCE_GROUP "Server" "server/ai_network.cpp" "server/ai_network.h" @@ -63,6 +66,15 @@ add_sources( SOURCE_GROUP "Server" "server/playerlocaldata.h" ) +add_sources( SOURCE_GROUP "Public" + "${ENGINE_SOURCE_DIR}/public/iserverentity.h" + "${ENGINE_SOURCE_DIR}/public/iservernetworkable.h" + "${ENGINE_SOURCE_DIR}/public/iserverunknown.h" +) + +endif() + +if( NOT ${PROJECT_NAME} STREQUAL "server_static" ) add_sources( SOURCE_GROUP "Client" "client/c_baseentity.cpp" "client/c_baseentity.h" @@ -80,16 +92,6 @@ add_sources( SOURCE_GROUP "Client" ) add_sources( SOURCE_GROUP "Public" - "${ENGINE_SOURCE_DIR}/public/basehandle.h" - "${ENGINE_SOURCE_DIR}/public/edict.h" - "${ENGINE_SOURCE_DIR}/public/eiface.h" - "${ENGINE_SOURCE_DIR}/public/globalvars_base.h" - "${ENGINE_SOURCE_DIR}/public/ihandleentity.h" - - "${ENGINE_SOURCE_DIR}/public/iserverentity.h" - "${ENGINE_SOURCE_DIR}/public/iservernetworkable.h" - "${ENGINE_SOURCE_DIR}/public/iserverunknown.h" - "${ENGINE_SOURCE_DIR}/public/icliententity.h" "${ENGINE_SOURCE_DIR}/public/icliententitylist.h" "${ENGINE_SOURCE_DIR}/public/iclientnetworkable.h" @@ -97,14 +99,40 @@ add_sources( SOURCE_GROUP "Public" "${ENGINE_SOURCE_DIR}/public/iclientthinkable.h" "${ENGINE_SOURCE_DIR}/public/iclientunknown.h" - "${ENGINE_SOURCE_DIR}/public/game/shared/weapon_types.h" - "${ENGINE_SOURCE_DIR}/public/game/shared/in_buttons.h" "${ENGINE_SOURCE_DIR}/public/game/client/iinput.h" ) +endif() + +add_sources( SOURCE_GROUP "Public" + "${ENGINE_SOURCE_DIR}/public/basehandle.h" + "${ENGINE_SOURCE_DIR}/public/edict.h" + "${ENGINE_SOURCE_DIR}/public/eiface.h" + "${ENGINE_SOURCE_DIR}/public/globalvars_base.h" + "${ENGINE_SOURCE_DIR}/public/ihandleentity.h" + + "${ENGINE_SOURCE_DIR}/public/game/shared/weapon_types.h" + "${ENGINE_SOURCE_DIR}/public/game/shared/in_buttons.h" +) + end_sources() +if( ${PROJECT_NAME} STREQUAL "server_static" ) +target_compile_definitions( ${PROJECT_NAME} PRIVATE + "SERVER_DLL" +) +elseif( ${PROJECT_NAME} STREQUAL "client_static" ) +target_compile_definitions( ${PROJECT_NAME} PRIVATE + "CLIENT_DLL" +) +endif() + target_include_directories( ${PROJECT_NAME} PRIVATE "${ENGINE_SOURCE_DIR}/tier0/" "${ENGINE_SOURCE_DIR}/tier1/" ) + +endmacro() + +add_game_project( "server_static" ) +add_game_project( "client_static" ) diff --git a/r5dev/game/shared/r1/weapon_bolt.h b/r5dev/game/shared/r1/weapon_bolt.h index 080aa3c1..777d2c5d 100644 --- a/r5dev/game/shared/r1/weapon_bolt.h +++ b/r5dev/game/shared/r1/weapon_bolt.h @@ -1,5 +1,7 @@ #ifndef GAME_WEAPON_BOLT_H #define GAME_WEAPON_BOLT_H + +#include #ifndef CLIENT_DLL #include #include diff --git a/r5dev/game/shared/shared_classnames.h b/r5dev/game/shared/shared_classnames.h index 264ece3f..f584e1af 100644 --- a/r5dev/game/shared/shared_classnames.h +++ b/r5dev/game/shared/shared_classnames.h @@ -13,12 +13,12 @@ // Hacky macros to allow shared code to work without even worse macro-izing #if defined( CLIENT_DLL ) -/* // TODO: Uncomment if required for client. + // Uncomment if required for client. #define CBaseEntity C_BaseEntity #define CBaseCombatCharacter C_BaseCombatCharacter #define CBaseAnimating C_BaseAnimating -#define CBasePlayer C_BasePlayer -*/ +#define CPlayer C_Player + #endif diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 4afdd7a2..4ae72687 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -6,7 +6,7 @@ // // Create functions here under the target VM namespace. If the function has to // be registered for 2 or more VM's, put them under the 'SHARED' namespace. -// Ifdef them out for 'DEDICATED' / 'CLIENT_DLL' if the target VM's do not +// Ifdef them out for 'SERVER_DLL' / 'CLIENT_DLL' if the target VM's do not // include 'SERVER' / 'CLIENT'. // //=============================================================================// @@ -22,9 +22,9 @@ #ifndef CLIENT_DLL #include "networksystem/bansystem.h" #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL #include "networksystem/listmanager.h" -#endif // !DEDICATED +#endif // !SERVER_DLL #include "vscript_shared.h" #include "vscript/languages/squirrel_re/include/sqvm.h" @@ -193,7 +193,7 @@ namespace VScriptCode return SQ_OK; } -#ifndef DEDICATED + //----------------------------------------------------------------------------- // Purpose: checks whether this SDK build is a client dll //----------------------------------------------------------------------------- @@ -207,7 +207,6 @@ namespace VScriptCode sq_pushbool(v, bClientOnly); return SQ_OK; } -#endif // !DEDICATED } #ifndef CLIENT_DLL namespace SERVER @@ -240,7 +239,7 @@ namespace VScriptCode } } #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL namespace CLIENT { } @@ -622,5 +621,104 @@ namespace VScriptCode return SQ_OK; } } -#endif // !DEDICATED -} \ No newline at end of file +#endif // !SERVER_DLL +} + +#ifndef CLIENT_DLL +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in SERVER context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterServerFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native SERVER test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); + + s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::SERVER::GetNumHumanPlayers); + s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::SERVER::GetNumFakeClients); + + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); + + s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string, string", &VScriptCode::SHARED::KickPlayerByName); + s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::KickPlayerById); + + s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); + s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::BanPlayerById); + + s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string, string", &VScriptCode::SHARED::UnbanPlayer); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); + + s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::SERVER::IsDedicated); +} +#endif // !CLIENT_DLL + +#ifndef SERVER_DLL +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in CLIENT context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterClientFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native CLIENT test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); + + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); + s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); +} + +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in UI context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterUIFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native UI test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); + + s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::UI::RefreshServerCount); + + // Functions for retrieving server browser data + s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerName); + s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerDescription); + s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerMap); + s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerPlaylist); + s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerCurrentPlayers); + s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerMaxPlayers); + s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::UI::GetServerCount); + + // Misc main menu functions + s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::UI::GetPromoData); + + // Functions for creating servers + s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::UI::CreateServer); + s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::SHARED::IsServerActive); + + // Functions for connecting to servers + s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::UI::ConnectToServer); + s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::UI::ConnectToListedServer); + s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::UI::ConnectToHiddenServer); + + s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::UI::GetHiddenServerName); + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); + +#ifndef CLIENT_DLL // UI 'admin' functions controlling server code + s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::SHARED::KickPlayerByName); + s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::KickPlayerById); + + s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); + s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::BanPlayerById); + + s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::SHARED::UnbanPlayer); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); +#endif // !CLIENT_DLL + + s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); +} +#endif diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index 1f90db3d..c9bc30f8 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -1,6 +1,7 @@ #ifndef VSCRIPT_SHARED_H #define VSCRIPT_SHARED_H #include "vscript/languages/squirrel_re/include/squirrel.h" +#include "vscript/languages/squirrel_re/vsquirrel.h" inline CMemory p_Script_Remote_BeginRegisteringFunctions; inline void*(*Script_Remote_BeginRegisteringFunctions)(void); @@ -11,9 +12,9 @@ inline void*(*RestoreRemoteChecksumsFromSaveGame)(void* a1, void* a2); #ifndef CLIENT_DLL inline uint32_t* g_nServerRemoteChecksum = nullptr; #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL inline uint32_t* g_nClientRemoteChecksum = nullptr; -#endif // !DEDICATED +#endif // !SERVER_DLL namespace VScriptCode { @@ -24,9 +25,9 @@ namespace VScriptCode SQRESULT GetAvailableMaps(HSQUIRRELVM v); SQRESULT GetAvailablePlaylists(HSQUIRRELVM v); SQRESULT ShutdownHostGame(HSQUIRRELVM v); -#ifndef DEDICATED +#ifndef SERVER_DLL SQRESULT IsClientDLL(HSQUIRRELVM v); -#endif // !DEDICATED +#endif // !SERVER_DLL SQRESULT IsServerActive(HSQUIRRELVM v); #ifndef CLIENT_DLL SQRESULT KickPlayerByName(HSQUIRRELVM v); @@ -44,7 +45,7 @@ namespace VScriptCode SQRESULT IsDedicated(HSQUIRRELVM v); } #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL namespace CLIENT { } @@ -65,9 +66,18 @@ namespace VScriptCode SQRESULT GetHiddenServerName(HSQUIRRELVM v); SQRESULT ConnectToServer(HSQUIRRELVM v); } -#endif // !DEDICATED +#endif // !SERVER_DLL } +#ifndef CLIENT_DLL +void Script_RegisterServerFunctions(CSquirrelVM* s); +#endif // !CLIENT_DLL + +#ifndef SERVER_DLL +void Script_RegisterClientFunctions(CSquirrelVM* s); +void Script_RegisterUIFunctions(CSquirrelVM* s); +#endif // !SERVER_DLL + /////////////////////////////////////////////////////////////////////////////// class VScriptShared : public IDetour { @@ -78,9 +88,9 @@ class VScriptShared : public IDetour #ifndef CLIENT_DLL LogVarAdr("g_nServerRemoteChecksum", reinterpret_cast(g_nServerRemoteChecksum)); #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL LogVarAdr("g_nClientRemoteChecksum", reinterpret_cast(g_nClientRemoteChecksum)); -#endif // !DEDICATED +#endif // !SERVER_DLL } virtual void GetFun(void) const { @@ -95,9 +105,9 @@ class VScriptShared : public IDetour #ifndef CLIENT_DLL g_nServerRemoteChecksum = p_RestoreRemoteChecksumsFromSaveGame.Offset(0x1C0).FindPatternSelf("48 8D 15", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); #endif // !CLIENT_DLL -#ifndef DEDICATED +#ifndef SERVER_DLL g_nClientRemoteChecksum = p_Script_Remote_BeginRegisteringFunctions.Offset(0x0).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast(); -#endif // !DEDICATED +#endif // !SERVER_DLL } virtual void GetCon(void) const { } virtual void Attach(void) const { } diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index b37f42fd..76d069ac 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -8,6 +8,11 @@ #include "pluginsystem/modsystem.h" #include "vsquirrel.h" +// Callbacks for registering abstracted script functions. +void(*ServerScriptRegister_Callback)(CSquirrelVM* s) = nullptr; +void(*ClientScriptRegister_Callback)(CSquirrelVM* s) = nullptr; +void(*UiScriptRegister_Callback)(CSquirrelVM* s) = nullptr; + //--------------------------------------------------------------------------------- // Purpose: Initialises a Squirrel VM instance // Output : True on success, false on failure @@ -27,17 +32,23 @@ SQBool CSquirrelVM::Init(CSquirrelVM* s, SQCONTEXT context, SQFloat curTime) #ifndef CLIENT_DLL case SQCONTEXT::SERVER: g_pServerScript = s; - Script_RegisterServerFunctions(s); + if (ServerScriptRegister_Callback) + ServerScriptRegister_Callback(s); + break; #endif #ifndef DEDICATED case SQCONTEXT::CLIENT: g_pClientScript = s; - Script_RegisterClientFunctions(s); + if (ClientScriptRegister_Callback) + ClientScriptRegister_Callback(s); + break; case SQCONTEXT::UI: g_pUIScript = s; - Script_RegisterUIFunctions(s); + if (UiScriptRegister_Callback) + UiScriptRegister_Callback(s); + break; #endif } diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index 627a0c25..2ef9c871 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -43,6 +43,10 @@ private: }; #pragma pack(pop) +extern void(*ServerScriptRegister_Callback)(CSquirrelVM* s); +extern void(*ClientScriptRegister_Callback)(CSquirrelVM* s); +extern void(*UiScriptRegister_Callback)(CSquirrelVM* s); + inline CMemory p_CSquirrelVM_Init; inline bool(*v_CSquirrelVM_Init)(CSquirrelVM* s, SQCONTEXT context, SQFloat curtime); diff --git a/r5dev/vscript/vscript.cpp b/r5dev/vscript/vscript.cpp index 7fc4d8fe..1a6e11ba 100644 --- a/r5dev/vscript/vscript.cpp +++ b/r5dev/vscript/vscript.cpp @@ -12,98 +12,6 @@ #include "game/shared/vscript_shared.h" #include "pluginsystem/modsystem.h" -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in SERVER context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterServerFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native SERVER test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::SERVER::GetNumHumanPlayers); - s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::SERVER::GetNumFakeClients); - - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string, string", &VScriptCode::SHARED::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::KickPlayerById); - - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string, string", &VScriptCode::SHARED::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); - - s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::SERVER::IsDedicated); -} - -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in CLIENT context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterClientFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native CLIENT test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); -} - -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in UI context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterUIFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native UI test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::UI::RefreshServerCount); - - // Functions for retrieving server browser data - s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerName); - s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerDescription); - s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerMap); - s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerPlaylist); - s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerCurrentPlayers); - s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerMaxPlayers); - s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::UI::GetServerCount); - - // Misc main menu functions - s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::UI::GetPromoData); - - // Functions for creating servers - s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::UI::CreateServer); - s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::SHARED::IsServerActive); - - // Functions for connecting to servers - s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::UI::ConnectToServer); - s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::UI::ConnectToListedServer); - s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::UI::ConnectToHiddenServer); - - s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::UI::GetHiddenServerName); - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::SHARED::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::KickPlayerById); - - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::SHARED::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); -} - //--------------------------------------------------------------------------------- // Purpose: Returns the script VM pointer by context // Input : context - diff --git a/r5dev/vscript/vscript.h b/r5dev/vscript/vscript.h index 3eb436fe..3861280c 100644 --- a/r5dev/vscript/vscript.h +++ b/r5dev/vscript/vscript.h @@ -34,10 +34,6 @@ inline SQBool(*v_Script_PrecompileClientScripts)(CSquirrelVM* vm); inline CMemory p_Script_SetClientCompiler; inline void(*v_Script_SetClientPrecompiler)(SQCONTEXT ctx, RSON::Node_t* rson); -void Script_RegisterServerFunctions(CSquirrelVM* s); -void Script_RegisterClientFunctions(CSquirrelVM* s); -void Script_RegisterUIFunctions(CSquirrelVM* s); - CSquirrelVM* Script_GetScriptHandle(const SQCONTEXT context); RSON::Node_t* Script_LoadScriptList(const SQChar* rsonfile); SQBool Script_LoadScriptFile(HSQUIRRELVM v, const SQChar* path, const SQChar* name, SQInteger flags); From 3637af34f61d772d5871e3d8762127e6bd70d0aa Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:18:04 +0200 Subject: [PATCH 02/25] Initialize the script register callbacks --- r5dev/core/init.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 43d9d923..85f506b6 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -193,6 +193,16 @@ void Systems_Init() DevMsg(eDLL_T::NONE, "\n"); ConVar_StaticInit(); + + // Script context registration callbacks. +#ifndef CLIENT_DLL + ServerScriptRegister_Callback = Script_RegisterServerFunctions; +#endif // !CLIENT_DLL + +#ifndef SERVER_DLL + ClientScriptRegister_Callback = Script_RegisterClientFunctions; + UiScriptRegister_Callback = Script_RegisterUIFunctions; +#endif // !SERVER_DLL } ////////////////////////////////////////////////////////////////////////// From 95ee7ddec6aaca7f5352ad7e218096d3e720ab3f Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:18:36 +0200 Subject: [PATCH 03/25] Move DLL projects to root of Solution Explorer --- r5dev/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/r5dev/CMakeLists.txt b/r5dev/CMakeLists.txt index 23305830..e72e3de1 100644 --- a/r5dev/CMakeLists.txt +++ b/r5dev/CMakeLists.txt @@ -65,4 +65,6 @@ add_subdirectory( pluginsdk ) set( FOLDER_CONTEXT "Game" ) add_subdirectory( vscript ) add_subdirectory( game ) + +set( FOLDER_CONTEXT "/" ) add_subdirectory( core ) From 6e223d1730d89744d278549efc43e307f23cac5b Mon Sep 17 00:00:00 2001 From: Amos Date: Tue, 18 Jul 2023 21:05:29 +0200 Subject: [PATCH 04/25] Make shared code separate The work is partial, and does not compile. --- r5dev/core/CMakeLists.txt | 1 + r5dev/game/CMakeLists.txt | 17 +- r5dev/game/client/vscript_client.cpp | 470 ++++++++++++++++++++++++ r5dev/game/client/vscript_client.h | 0 r5dev/game/server/vscript_server.cpp | 75 ++++ r5dev/game/server/vscript_server.h | 0 r5dev/game/shared/vscript_shared.cpp | 515 +-------------------------- r5dev/game/shared/vscript_shared.h | 8 +- 8 files changed, 566 insertions(+), 520 deletions(-) create mode 100644 r5dev/game/client/vscript_client.cpp create mode 100644 r5dev/game/client/vscript_client.h create mode 100644 r5dev/game/server/vscript_server.cpp create mode 100644 r5dev/game/server/vscript_server.h diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index 06d0847f..9daa6bc3 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -80,6 +80,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "localize" "vscript" + "game_shared_static" ) if( NOT ${PROJECT_NAME} STREQUAL "dedicated" ) diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index 8722dde6..cf902931 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -5,6 +5,8 @@ add_module( "lib" ${PROJECT_NAME} "vpc" ${FOLDER_CONTEXT} TRUE TRUE ) start_sources() +if( ${PROJECT_NAME} STREQUAL "game_shared_static" ) + add_sources( SOURCE_GROUP "Shared" "shared/ai_utility_shared.cpp" "shared/ai_utility_shared.h" @@ -35,7 +37,10 @@ add_sources( SOURCE_GROUP "Shared/Weapon" "shared/r1/weapon_bolt.h" ) -if( NOT ${PROJECT_NAME} STREQUAL "client_static" ) +endif() + +if( ${PROJECT_NAME} STREQUAL "server_static" ) + add_sources( SOURCE_GROUP "Server" "server/ai_network.cpp" "server/ai_network.h" @@ -64,6 +69,8 @@ add_sources( SOURCE_GROUP "Server" "server/player.cpp" "server/player.h" "server/playerlocaldata.h" + "server/vscript_server.cpp" + "server/vscript_server.h" ) add_sources( SOURCE_GROUP "Public" @@ -74,7 +81,8 @@ add_sources( SOURCE_GROUP "Public" endif() -if( NOT ${PROJECT_NAME} STREQUAL "server_static" ) +if( ${PROJECT_NAME} STREQUAL "client_static" ) + add_sources( SOURCE_GROUP "Client" "client/c_baseentity.cpp" "client/c_baseentity.h" @@ -89,6 +97,8 @@ add_sources( SOURCE_GROUP "Client" "client/spritemodel.cpp" "client/viewrender.cpp" "client/viewrender.h" + "client/vscript_client.cpp" + "client/vscript_client.h" ) add_sources( SOURCE_GROUP "Public" @@ -118,6 +128,7 @@ add_sources( SOURCE_GROUP "Public" end_sources() if( ${PROJECT_NAME} STREQUAL "server_static" ) + target_compile_definitions( ${PROJECT_NAME} PRIVATE "SERVER_DLL" ) @@ -125,6 +136,7 @@ elseif( ${PROJECT_NAME} STREQUAL "client_static" ) target_compile_definitions( ${PROJECT_NAME} PRIVATE "CLIENT_DLL" ) + endif() target_include_directories( ${PROJECT_NAME} PRIVATE @@ -136,3 +148,4 @@ endmacro() add_game_project( "server_static" ) add_game_project( "client_static" ) +add_game_project( "game_shared_static" ) diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp new file mode 100644 index 00000000..d29d06d9 --- /dev/null +++ b/r5dev/game/client/vscript_client.cpp @@ -0,0 +1,470 @@ +//=============================================================================// +// +// Purpose: Expose native code to VScript API +// +//----------------------------------------------------------------------------- +// +// See 'game/shared/vscript_shared.cpp' for more details. +// +//=============================================================================// + +#include "core/stdafx.h" +#include "vpc/keyvalues.h" +#include "engine/cmodel_bsp.h" +#include "engine/host_state.h" +#include "networksystem/pylon.h" +#include "networksystem/listmanager.h" +#include "game/shared/vscript_shared.h" +#include "vscript/languages/squirrel_re/include/sqvm.h" + +namespace VScriptCode +{ + namespace Client + { + } + namespace Ui + { + //----------------------------------------------------------------------------- + // Purpose: refreshes the server list + //----------------------------------------------------------------------------- + SQRESULT RefreshServerCount(HSQUIRRELVM v) + { + string serverMessage; // Refresh list. + size_t iCount = g_pServerListManager->RefreshServerList(serverMessage); + + sq_pushinteger(v, static_cast(iCount)); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current name from serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerName(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& serverName = g_pServerListManager->m_vServerList[iServer].m_svHostName; + sq_pushstring(v, serverName.c_str(), -1); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current description from serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerDescription(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& serverDescription = g_pServerListManager->m_vServerList[iServer].m_svDescription; + sq_pushstring(v, serverDescription.c_str(), -1); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current map via serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerMap(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& svServerMapName = g_pServerListManager->m_vServerList[iServer].m_svHostMap; + sq_pushstring(v, svServerMapName.c_str(), -1); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current playlist via serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerPlaylist(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& serverPlaylist = g_pServerListManager->m_vServerList[iServer].m_svPlaylist; + sq_pushstring(v, serverPlaylist.c_str(), -1); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current player count via serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& playerCount = g_pServerListManager->m_vServerList[iServer].m_svPlayerCount.c_str(); + sq_pushinteger(v, strtol(playerCount.c_str(), NULL, NULL)); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get server's current player count via serverlist index + //----------------------------------------------------------------------------- + SQRESULT GetServerMaxPlayers(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const string& maxPlayers = g_pServerListManager->m_vServerList[iServer].m_svMaxPlayers; + sq_pushinteger(v, strtol(maxPlayers.c_str(), NULL, NULL)); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get current server count from pylon + //----------------------------------------------------------------------------- + SQRESULT GetServerCount(HSQUIRRELVM v) + { + size_t iCount = g_pServerListManager->m_vServerList.size(); + sq_pushinteger(v, static_cast(iCount)); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get promo data for serverbrowser panels + //----------------------------------------------------------------------------- + SQRESULT GetPromoData(HSQUIRRELVM v) + { + enum class R5RPromoData : SQInteger + { + PromoLargeTitle, + PromoLargeDesc, + PromoLeftTitle, + PromoLeftDesc, + PromoRightTitle, + PromoRightDesc + }; + + R5RPromoData ePromoIndex = static_cast(sq_getinteger(v, 1)); + const char* pszPromoKey; + + switch (ePromoIndex) + { + case R5RPromoData::PromoLargeTitle: + { + pszPromoKey = "#PROMO_LARGE_TITLE"; + break; + } + case R5RPromoData::PromoLargeDesc: + { + pszPromoKey = "#PROMO_LARGE_DESCRIPTION"; + break; + } + case R5RPromoData::PromoLeftTitle: + { + pszPromoKey = "#PROMO_LEFT_TITLE"; + break; + } + case R5RPromoData::PromoLeftDesc: + { + pszPromoKey = "#PROMO_LEFT_DESCRIPTION"; + break; + } + case R5RPromoData::PromoRightTitle: + { + pszPromoKey = "#PROMO_RIGHT_TITLE"; + break; + } + case R5RPromoData::PromoRightDesc: + { + pszPromoKey = "#PROMO_RIGHT_DESCRIPTION"; + break; + } + default: + { + pszPromoKey = "#PROMO_SDK_ERROR"; + break; + } + } + + sq_pushstring(v, pszPromoKey, -1); + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: create server via native serverbrowser entries + // TODO: return a boolean on failure instead of raising an error, so we could + // determine from scripts whether or not to spin a local server, or connect + // to a dedicated server (for disconnecting and loading the lobby, for example) + //----------------------------------------------------------------------------- + SQRESULT CreateServer(HSQUIRRELVM v) + { +#ifndef CLIENT_DLL + SQChar* serverName = sq_getstring(v, 1); + SQChar* serverDescription = sq_getstring(v, 2); + SQChar* serverMapName = sq_getstring(v, 3); + SQChar* serverPlaylist = sq_getstring(v, 4); + EServerVisibility_t eServerVisibility = static_cast(sq_getinteger(v, 5)); + + if (!VALID_CHARSTAR(serverName) || + !VALID_CHARSTAR(serverMapName) || + !VALID_CHARSTAR(serverPlaylist)) + { + return SQ_OK; + } + + // Adjust browser settings. + std::lock_guard l(g_pServerListManager->m_Mutex); + + g_pServerListManager->m_Server.m_svHostName = serverName; + g_pServerListManager->m_Server.m_svDescription = serverDescription; + g_pServerListManager->m_Server.m_svHostMap = serverMapName; + g_pServerListManager->m_Server.m_svPlaylist = serverPlaylist; + g_pServerListManager->m_ServerVisibility = eServerVisibility; + + // Launch server. + g_pServerListManager->LaunchServer(); + + return SQ_OK; +#else + v_SQVM_RaiseError(v, "\"%s\" is not supported for client builds.\n", "CreateServer"); + return SQ_ERROR; +#endif + } + + //----------------------------------------------------------------------------- + // Purpose: connect to server from native server browser entries + //----------------------------------------------------------------------------- + SQRESULT ConnectToServer(HSQUIRRELVM v) + { + SQChar* ipAddress = sq_getstring(v, 1); + SQChar* cryptoKey = sq_getstring(v, 2); + + if (!VALID_CHARSTAR(ipAddress) || VALID_CHARSTAR(cryptoKey)) + return SQ_OK; + + DevMsg(eDLL_T::UI, "Connecting to server with ip address '%s' and encryption key '%s'\n", ipAddress, cryptoKey); + g_pServerListManager->ConnectToServer(ipAddress, cryptoKey); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: set netchannel encryption key and connect to server + //----------------------------------------------------------------------------- + SQRESULT ConnectToListedServer(HSQUIRRELVM v) + { + std::lock_guard l(g_pServerListManager->m_Mutex); + + SQInteger iServer = sq_getinteger(v, 1); + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return SQ_ERROR; + } + + const NetGameServer_t& gameServer = g_pServerListManager->m_vServerList[iServer]; + + g_pServerListManager->ConnectToServer(gameServer.m_svIpAddress, gameServer.m_svGamePort, + gameServer.m_svEncryptionKey); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: request token from pylon and join server with result. + //----------------------------------------------------------------------------- + SQRESULT ConnectToHiddenServer(HSQUIRRELVM v) + { + SQChar* privateToken = sq_getstring(v, 1); + + if (!VALID_CHARSTAR(privateToken)) + return SQ_OK; + + string hiddenServerRequestMessage; + NetGameServer_t netListing; + + bool result = g_pMasterServer->GetServerByToken(netListing, hiddenServerRequestMessage, privateToken); // Send token connect request. + if (result) + { + g_pServerListManager->ConnectToServer(netListing.m_svIpAddress, netListing.m_svGamePort, netListing.m_svEncryptionKey); + } + else + { + Warning(eDLL_T::UI, "Failed to connect to private server: %s\n", hiddenServerRequestMessage.c_str()); + } + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get response from private server request + //----------------------------------------------------------------------------- + SQRESULT GetHiddenServerName(HSQUIRRELVM v) + { + SQChar* privateToken = sq_getstring(v, 1); + + if (!VALID_CHARSTAR(privateToken)) + return SQ_OK; + + string hiddenServerRequestMessage; + NetGameServer_t serverListing; + + bool result = g_pMasterServer->GetServerByToken(serverListing, hiddenServerRequestMessage, privateToken); // Send token connect request. + if (!result) + { + if (hiddenServerRequestMessage.empty()) + { + sq_pushstring(v, "Request failed", -1); + } + else + { + hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str()); + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + + return SQ_OK; + } + + if (serverListing.m_svHostName.empty()) + { + if (hiddenServerRequestMessage.empty()) + { + hiddenServerRequestMessage = Format("Server listing empty"); + } + else + { + hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str()); + } + + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + else + { + hiddenServerRequestMessage = Format("Found server: %s", serverListing.m_svHostName.c_str()); + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + + return SQ_OK; + } + } +} + +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in CLIENT context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterClientFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native CLIENT test function", "void", "", &VScriptCode::Shared::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::Shared::ShutdownHostGame); + s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Shared::IsClientDLL); +} + +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in UI context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterUIFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native UI test function", "void", "", &VScriptCode::Shared::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + + s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::Ui::RefreshServerCount); + + // Functions for retrieving server browser data + s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerName); + s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerDescription); + s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerMap); + s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerPlaylist); + s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Ui::GetServerCurrentPlayers); + s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Ui::GetServerMaxPlayers); + s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::Ui::GetServerCount); + + // Misc main menu functions + s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::Ui::GetPromoData); + + // Functions for creating servers + s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::Ui::CreateServer); + s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::Shared::IsServerActive); + + // Functions for connecting to servers + s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::Ui::ConnectToServer); + s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::Ui::ConnectToListedServer); + s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::Ui::ConnectToHiddenServer); + + s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::Ui::GetHiddenServerName); + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); + +#ifndef CLIENT_DLL // UI 'admin' functions controlling server code + s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::SHARED::KickPlayerByName); + s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::KickPlayerById); + + s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); + s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::BanPlayerById); + + s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::SHARED::UnbanPlayer); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); +#endif // !CLIENT_DLL + + s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Shared::IsClientDLL); +} diff --git a/r5dev/game/client/vscript_client.h b/r5dev/game/client/vscript_client.h new file mode 100644 index 00000000..e69de29b diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp new file mode 100644 index 00000000..563741f4 --- /dev/null +++ b/r5dev/game/server/vscript_server.cpp @@ -0,0 +1,75 @@ +//=============================================================================// +// +// Purpose: Expose native code to VScript API +// +//----------------------------------------------------------------------------- +// +// See 'game/shared/vscript_shared.cpp' for more details. +// +//=============================================================================// + +#include "core/stdafx.h" +#include "engine/server/server.h" +#include "game/shared/vscript_shared.h" +#include "vscript/languages/squirrel_re/include/sqvm.h" + +namespace VScriptCode +{ + namespace Server + { + //----------------------------------------------------------------------------- + // Purpose: gets the number of real players on this server + //----------------------------------------------------------------------------- + SQRESULT GetNumHumanPlayers(HSQUIRRELVM v) + { + sq_pushinteger(v, g_pServer->GetNumHumanPlayers()); + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: gets the number of fake players on this server + //----------------------------------------------------------------------------- + SQRESULT GetNumFakeClients(HSQUIRRELVM v) + { + sq_pushinteger(v, g_pServer->GetNumFakeClients()); + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: checks whether this SDK build is a dedicated server + //----------------------------------------------------------------------------- + SQRESULT IsDedicated(HSQUIRRELVM v) + { + sq_pushbool(v, ::IsDedicated()); + return SQ_OK; + } + } +} + +//--------------------------------------------------------------------------------- +// Purpose: registers script functions in SERVER context +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterServerFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native SERVER test function", "void", "", &VScriptCode::Shared::SDKNativeTest); + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + + s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::Server::GetNumHumanPlayers); + s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::Server::GetNumFakeClients); + + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); + + s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string, string", &VScriptCode::Shared::KickPlayerByName); + s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::Shared::KickPlayerById); + + s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::Shared::BanPlayerByName); + s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::Shared::BanPlayerById); + + s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string, string", &VScriptCode::Shared::UnbanPlayer); + + s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::Shared::ShutdownHostGame); + + s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::Server::IsDedicated); +} diff --git a/r5dev/game/server/vscript_server.h b/r5dev/game/server/vscript_server.h new file mode 100644 index 00000000..e69de29b diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 4ae72687..0e951046 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -30,7 +30,7 @@ namespace VScriptCode { - namespace SHARED + namespace Shared { //----------------------------------------------------------------------------- // Purpose: SDK test and example body @@ -208,517 +208,4 @@ namespace VScriptCode return SQ_OK; } } -#ifndef CLIENT_DLL - namespace SERVER - { - //----------------------------------------------------------------------------- - // Purpose: gets the number of real players on this server - //----------------------------------------------------------------------------- - SQRESULT GetNumHumanPlayers(HSQUIRRELVM v) - { - sq_pushinteger(v, g_pServer->GetNumHumanPlayers()); - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: gets the number of fake players on this server - //----------------------------------------------------------------------------- - SQRESULT GetNumFakeClients(HSQUIRRELVM v) - { - sq_pushinteger(v, g_pServer->GetNumFakeClients()); - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: checks whether this SDK build is a dedicated server - //----------------------------------------------------------------------------- - SQRESULT IsDedicated(HSQUIRRELVM v) - { - sq_pushbool(v, ::IsDedicated()); - return SQ_OK; - } - } -#endif // !CLIENT_DLL -#ifndef SERVER_DLL - namespace CLIENT - { - } - namespace UI - { - //----------------------------------------------------------------------------- - // Purpose: refreshes the server list - //----------------------------------------------------------------------------- - SQRESULT RefreshServerCount(HSQUIRRELVM v) - { - string serverMessage; // Refresh list. - size_t iCount = g_pServerListManager->RefreshServerList(serverMessage); - - sq_pushinteger(v, static_cast(iCount)); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current name from serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerName(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& serverName = g_pServerListManager->m_vServerList[iServer].m_svHostName; - sq_pushstring(v, serverName.c_str(), -1); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current description from serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerDescription(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& serverDescription = g_pServerListManager->m_vServerList[iServer].m_svDescription; - sq_pushstring(v, serverDescription.c_str(), -1); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current map via serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerMap(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& svServerMapName = g_pServerListManager->m_vServerList[iServer].m_svHostMap; - sq_pushstring(v, svServerMapName.c_str(), -1); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current playlist via serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerPlaylist(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& serverPlaylist = g_pServerListManager->m_vServerList[iServer].m_svPlaylist; - sq_pushstring(v, serverPlaylist.c_str(), -1); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current player count via serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& playerCount = g_pServerListManager->m_vServerList[iServer].m_svPlayerCount.c_str(); - sq_pushinteger(v, strtol(playerCount.c_str(), NULL, NULL)); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get server's current player count via serverlist index - //----------------------------------------------------------------------------- - SQRESULT GetServerMaxPlayers(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const string& maxPlayers = g_pServerListManager->m_vServerList[iServer].m_svMaxPlayers; - sq_pushinteger(v, strtol(maxPlayers.c_str(), NULL, NULL)); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get current server count from pylon - //----------------------------------------------------------------------------- - SQRESULT GetServerCount(HSQUIRRELVM v) - { - size_t iCount = g_pServerListManager->m_vServerList.size(); - sq_pushinteger(v, static_cast(iCount)); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get promo data for serverbrowser panels - //----------------------------------------------------------------------------- - SQRESULT GetPromoData(HSQUIRRELVM v) - { - enum class R5RPromoData : SQInteger - { - PromoLargeTitle, - PromoLargeDesc, - PromoLeftTitle, - PromoLeftDesc, - PromoRightTitle, - PromoRightDesc - }; - - R5RPromoData ePromoIndex = static_cast(sq_getinteger(v, 1)); - const char* pszPromoKey; - - switch (ePromoIndex) - { - case R5RPromoData::PromoLargeTitle: - { - pszPromoKey = "#PROMO_LARGE_TITLE"; - break; - } - case R5RPromoData::PromoLargeDesc: - { - pszPromoKey = "#PROMO_LARGE_DESCRIPTION"; - break; - } - case R5RPromoData::PromoLeftTitle: - { - pszPromoKey = "#PROMO_LEFT_TITLE"; - break; - } - case R5RPromoData::PromoLeftDesc: - { - pszPromoKey = "#PROMO_LEFT_DESCRIPTION"; - break; - } - case R5RPromoData::PromoRightTitle: - { - pszPromoKey = "#PROMO_RIGHT_TITLE"; - break; - } - case R5RPromoData::PromoRightDesc: - { - pszPromoKey = "#PROMO_RIGHT_DESCRIPTION"; - break; - } - default: - { - pszPromoKey = "#PROMO_SDK_ERROR"; - break; - } - } - - sq_pushstring(v, pszPromoKey, -1); - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: create server via native serverbrowser entries - // TODO: return a boolean on failure instead of raising an error, so we could - // determine from scripts whether or not to spin a local server, or connect - // to a dedicated server (for disconnecting and loading the lobby, for example) - //----------------------------------------------------------------------------- - SQRESULT CreateServer(HSQUIRRELVM v) - { -#ifndef CLIENT_DLL - SQChar* serverName = sq_getstring(v, 1); - SQChar* serverDescription = sq_getstring(v, 2); - SQChar* serverMapName = sq_getstring(v, 3); - SQChar* serverPlaylist = sq_getstring(v, 4); - EServerVisibility_t eServerVisibility = static_cast(sq_getinteger(v, 5)); - - if (!VALID_CHARSTAR(serverName) || - !VALID_CHARSTAR(serverMapName) || - !VALID_CHARSTAR(serverPlaylist)) - { - return SQ_OK; - } - - // Adjust browser settings. - std::lock_guard l(g_pServerListManager->m_Mutex); - - g_pServerListManager->m_Server.m_svHostName = serverName; - g_pServerListManager->m_Server.m_svDescription = serverDescription; - g_pServerListManager->m_Server.m_svHostMap = serverMapName; - g_pServerListManager->m_Server.m_svPlaylist = serverPlaylist; - g_pServerListManager->m_ServerVisibility = eServerVisibility; - - // Launch server. - g_pServerListManager->LaunchServer(); - - return SQ_OK; -#else - v_SQVM_RaiseError(v, "\"%s\" is not supported for client builds.\n", "CreateServer"); - return SQ_ERROR; -#endif - } - - //----------------------------------------------------------------------------- - // Purpose: connect to server from native server browser entries - //----------------------------------------------------------------------------- - SQRESULT ConnectToServer(HSQUIRRELVM v) - { - SQChar* ipAddress = sq_getstring(v, 1); - SQChar* cryptoKey = sq_getstring(v, 2); - - if (!VALID_CHARSTAR(ipAddress) || VALID_CHARSTAR(cryptoKey)) - return SQ_OK; - - DevMsg(eDLL_T::UI, "Connecting to server with ip address '%s' and encryption key '%s'\n", ipAddress, cryptoKey); - g_pServerListManager->ConnectToServer(ipAddress, cryptoKey); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: set netchannel encryption key and connect to server - //----------------------------------------------------------------------------- - SQRESULT ConnectToListedServer(HSQUIRRELVM v) - { - std::lock_guard l(g_pServerListManager->m_Mutex); - - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - - if (iServer >= iCount) - { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); - return SQ_ERROR; - } - - const NetGameServer_t& gameServer = g_pServerListManager->m_vServerList[iServer]; - - g_pServerListManager->ConnectToServer(gameServer.m_svIpAddress, gameServer.m_svGamePort, - gameServer.m_svEncryptionKey); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: request token from pylon and join server with result. - //----------------------------------------------------------------------------- - SQRESULT ConnectToHiddenServer(HSQUIRRELVM v) - { - SQChar* privateToken = sq_getstring(v, 1); - - if (!VALID_CHARSTAR(privateToken)) - return SQ_OK; - - string hiddenServerRequestMessage; - NetGameServer_t netListing; - - bool result = g_pMasterServer->GetServerByToken(netListing, hiddenServerRequestMessage, privateToken); // Send token connect request. - if (result) - { - g_pServerListManager->ConnectToServer(netListing.m_svIpAddress, netListing.m_svGamePort, netListing.m_svEncryptionKey); - } - else - { - Warning(eDLL_T::UI, "Failed to connect to private server: %s\n", hiddenServerRequestMessage.c_str()); - } - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: get response from private server request - //----------------------------------------------------------------------------- - SQRESULT GetHiddenServerName(HSQUIRRELVM v) - { - SQChar* privateToken = sq_getstring(v, 1); - - if (!VALID_CHARSTAR(privateToken)) - return SQ_OK; - - string hiddenServerRequestMessage; - NetGameServer_t serverListing; - - bool result = g_pMasterServer->GetServerByToken(serverListing, hiddenServerRequestMessage, privateToken); // Send token connect request. - if (!result) - { - if (hiddenServerRequestMessage.empty()) - { - sq_pushstring(v, "Request failed", -1); - } - else - { - hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str()); - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - - return SQ_OK; - } - - if (serverListing.m_svHostName.empty()) - { - if (hiddenServerRequestMessage.empty()) - { - hiddenServerRequestMessage = Format("Server listing empty"); - } - else - { - hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str()); - } - - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - else - { - hiddenServerRequestMessage = Format("Found server: %s", serverListing.m_svHostName.c_str()); - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - - return SQ_OK; - } - } -#endif // !SERVER_DLL } - -#ifndef CLIENT_DLL -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in SERVER context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterServerFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native SERVER test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::SERVER::GetNumHumanPlayers); - s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::SERVER::GetNumFakeClients); - - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string, string", &VScriptCode::SHARED::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::KickPlayerById); - - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::SHARED::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string, string", &VScriptCode::SHARED::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); - - s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::SERVER::IsDedicated); -} -#endif // !CLIENT_DLL - -#ifndef SERVER_DLL -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in CLIENT context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterClientFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native CLIENT test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); -} - -//--------------------------------------------------------------------------------- -// Purpose: registers script functions in UI context -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterUIFunctions(CSquirrelVM* s) -{ - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native UI test function", "void", "", &VScriptCode::SHARED::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::SHARED::GetSDKVersion); - - s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::UI::RefreshServerCount); - - // Functions for retrieving server browser data - s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerName); - s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerDescription); - s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerMap); - s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::UI::GetServerPlaylist); - s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerCurrentPlayers); - s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::UI::GetServerMaxPlayers); - s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::UI::GetServerCount); - - // Misc main menu functions - s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::UI::GetPromoData); - - // Functions for creating servers - s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::UI::CreateServer); - s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::SHARED::IsServerActive); - - // Functions for connecting to servers - s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::UI::ConnectToServer); - s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::UI::ConnectToListedServer); - s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::UI::ConnectToHiddenServer); - - s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::UI::GetHiddenServerName); - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::SHARED::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::SHARED::GetAvailablePlaylists); - -#ifndef CLIENT_DLL // UI 'admin' functions controlling server code - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::SHARED::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::KickPlayerById); - - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::SHARED::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); -#endif // !CLIENT_DLL - - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::SHARED::IsClientDLL); -} -#endif diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index c9bc30f8..2abb9ccf 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -18,7 +18,7 @@ inline uint32_t* g_nClientRemoteChecksum = nullptr; namespace VScriptCode { - namespace SHARED + namespace Shared { SQRESULT SDKNativeTest(HSQUIRRELVM v); SQRESULT GetSDKVersion(HSQUIRRELVM v); @@ -38,7 +38,7 @@ namespace VScriptCode #endif // !CLIENT_DLL } #ifndef CLIENT_DLL - namespace SERVER + namespace Server { SQRESULT GetNumHumanPlayers(HSQUIRRELVM v); SQRESULT GetNumFakeClients(HSQUIRRELVM v); @@ -46,10 +46,10 @@ namespace VScriptCode } #endif // !CLIENT_DLL #ifndef SERVER_DLL - namespace CLIENT + namespace Client { } - namespace UI + namespace Ui { SQRESULT RefreshServerCount(HSQUIRRELVM v); SQRESULT GetServerName(HSQUIRRELVM v); From d5f35349a8f8349e5003fb4ea9b56b59c0ff9d0a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:12:56 +0200 Subject: [PATCH 05/25] Decouple script function registration Nicely decouple them. Everything server and client are now grouped as they should. The Ui namespace has been merged with Client. --- r5dev/core/init.cpp | 8 + r5dev/engine/client/cl_main.h | 7 + r5dev/game/client/vscript_client.cpp | 240 +++++++----------- r5dev/game/client/vscript_client.h | 35 +++ r5dev/game/server/vscript_server.cpp | 185 +++++++++++++- r5dev/game/server/vscript_server.h | 29 +++ r5dev/game/shared/vscript_shared.cpp | 145 +---------- r5dev/game/shared/vscript_shared.h | 64 +---- .../languages/squirrel_re/vsquirrel.cpp | 24 +- .../vscript/languages/squirrel_re/vsquirrel.h | 3 + 10 files changed, 374 insertions(+), 366 deletions(-) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 85f506b6..9fe4a11c 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -122,11 +122,13 @@ #include "game/server/gameinterface.h" #include "game/server/movehelper_server.h" #include "game/server/physics_main.h" +#include "game/server/vscript_server.h" #endif // !CLIENT_DLL #ifndef DEDICATED #include "game/client/viewrender.h" #include "game/client/input.h" #include "game/client/movehelper_client.h" +#include "game/client/vscript_client.h" #endif // !DEDICATED #include "public/edict.h" #ifndef DEDICATED @@ -197,12 +199,18 @@ void Systems_Init() // Script context registration callbacks. #ifndef CLIENT_DLL ServerScriptRegister_Callback = Script_RegisterServerFunctions; + CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions; + AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions; #endif // !CLIENT_DLL #ifndef SERVER_DLL ClientScriptRegister_Callback = Script_RegisterClientFunctions; UiScriptRegister_Callback = Script_RegisterUIFunctions; #endif // !SERVER_DLL + +#ifdef CLIENT_DLL + g_bClientDLL = true; +#endif } ////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/engine/client/cl_main.h b/r5dev/engine/client/cl_main.h index 74278853..f7394048 100644 --- a/r5dev/engine/client/cl_main.h +++ b/r5dev/engine/client/cl_main.h @@ -15,6 +15,13 @@ inline int(*CL_ClearState)(void); inline CMemory p_CL_RunPrediction; inline void(*CL_RunPrediction)(void); +inline bool g_bClientDLL = false; + +// Returns true if this is a dedicated server. +inline bool IsClientDLL() +{ + return g_bClientDLL; +} /////////////////////////////////////////////////////////////////////////////// class VCL_Main : public IDetour diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index d29d06d9..c7ce1955 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -12,17 +12,17 @@ #include "vpc/keyvalues.h" #include "engine/cmodel_bsp.h" #include "engine/host_state.h" +#include "engine/client/cl_main.h" #include "networksystem/pylon.h" #include "networksystem/listmanager.h" #include "game/shared/vscript_shared.h" #include "vscript/languages/squirrel_re/include/sqvm.h" +#include "vscript_client.h" + namespace VScriptCode { namespace Client - { - } - namespace Ui { //----------------------------------------------------------------------------- // Purpose: refreshes the server list @@ -37,6 +37,68 @@ namespace VScriptCode return SQ_OK; } + //----------------------------------------------------------------------------- + // Purpose: get current server count from pylon + //----------------------------------------------------------------------------- + SQRESULT GetServerCount(HSQUIRRELVM v) + { + size_t iCount = g_pServerListManager->m_vServerList.size(); + sq_pushinteger(v, static_cast(iCount)); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: get response from private server request + //----------------------------------------------------------------------------- + SQRESULT GetHiddenServerName(HSQUIRRELVM v) + { + SQChar* privateToken = sq_getstring(v, 1); + + if (!VALID_CHARSTAR(privateToken)) + return SQ_OK; + + string hiddenServerRequestMessage; + NetGameServer_t serverListing; + + bool result = g_pMasterServer->GetServerByToken(serverListing, hiddenServerRequestMessage, privateToken); // Send token connect request. + if (!result) + { + if (hiddenServerRequestMessage.empty()) + { + sq_pushstring(v, "Request failed", -1); + } + else + { + hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str()); + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + + return SQ_OK; + } + + if (serverListing.m_svHostName.empty()) + { + if (hiddenServerRequestMessage.empty()) + { + hiddenServerRequestMessage = Format("Server listing empty"); + } + else + { + hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str()); + } + + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + else + { + hiddenServerRequestMessage = Format("Found server: %s", serverListing.m_svHostName.c_str()); + sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); + } + + return SQ_OK; + } + //----------------------------------------------------------------------------- // Purpose: get server's current name from serverlist index //----------------------------------------------------------------------------- @@ -169,17 +231,6 @@ namespace VScriptCode return SQ_OK; } - //----------------------------------------------------------------------------- - // Purpose: get current server count from pylon - //----------------------------------------------------------------------------- - SQRESULT GetServerCount(HSQUIRRELVM v) - { - size_t iCount = g_pServerListManager->m_vServerList.size(); - sq_pushinteger(v, static_cast(iCount)); - - return SQ_OK; - } - //----------------------------------------------------------------------------- // Purpose: get promo data for serverbrowser panels //----------------------------------------------------------------------------- @@ -241,47 +292,6 @@ namespace VScriptCode return SQ_OK; } - //----------------------------------------------------------------------------- - // Purpose: create server via native serverbrowser entries - // TODO: return a boolean on failure instead of raising an error, so we could - // determine from scripts whether or not to spin a local server, or connect - // to a dedicated server (for disconnecting and loading the lobby, for example) - //----------------------------------------------------------------------------- - SQRESULT CreateServer(HSQUIRRELVM v) - { -#ifndef CLIENT_DLL - SQChar* serverName = sq_getstring(v, 1); - SQChar* serverDescription = sq_getstring(v, 2); - SQChar* serverMapName = sq_getstring(v, 3); - SQChar* serverPlaylist = sq_getstring(v, 4); - EServerVisibility_t eServerVisibility = static_cast(sq_getinteger(v, 5)); - - if (!VALID_CHARSTAR(serverName) || - !VALID_CHARSTAR(serverMapName) || - !VALID_CHARSTAR(serverPlaylist)) - { - return SQ_OK; - } - - // Adjust browser settings. - std::lock_guard l(g_pServerListManager->m_Mutex); - - g_pServerListManager->m_Server.m_svHostName = serverName; - g_pServerListManager->m_Server.m_svDescription = serverDescription; - g_pServerListManager->m_Server.m_svHostMap = serverMapName; - g_pServerListManager->m_Server.m_svPlaylist = serverPlaylist; - g_pServerListManager->m_ServerVisibility = eServerVisibility; - - // Launch server. - g_pServerListManager->LaunchServer(); - - return SQ_OK; -#else - v_SQVM_RaiseError(v, "\"%s\" is not supported for client builds.\n", "CreateServer"); - return SQ_ERROR; -#endif - } - //----------------------------------------------------------------------------- // Purpose: connect to server from native server browser entries //----------------------------------------------------------------------------- @@ -350,53 +360,11 @@ namespace VScriptCode } //----------------------------------------------------------------------------- - // Purpose: get response from private server request + // Purpose: checks whether this SDK build is a client dll //----------------------------------------------------------------------------- - SQRESULT GetHiddenServerName(HSQUIRRELVM v) + SQRESULT IsClientDLL(HSQUIRRELVM v) { - SQChar* privateToken = sq_getstring(v, 1); - - if (!VALID_CHARSTAR(privateToken)) - return SQ_OK; - - string hiddenServerRequestMessage; - NetGameServer_t serverListing; - - bool result = g_pMasterServer->GetServerByToken(serverListing, hiddenServerRequestMessage, privateToken); // Send token connect request. - if (!result) - { - if (hiddenServerRequestMessage.empty()) - { - sq_pushstring(v, "Request failed", -1); - } - else - { - hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str()); - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - - return SQ_OK; - } - - if (serverListing.m_svHostName.empty()) - { - if (hiddenServerRequestMessage.empty()) - { - hiddenServerRequestMessage = Format("Server listing empty"); - } - else - { - hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str()); - } - - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - else - { - hiddenServerRequestMessage = Format("Found server: %s", serverListing.m_svHostName.c_str()); - sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1); - } - + sq_pushbool(v, ::IsClientDLL()); return SQ_OK; } } @@ -408,14 +376,8 @@ namespace VScriptCode //--------------------------------------------------------------------------------- void Script_RegisterClientFunctions(CSquirrelVM* s) { - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native CLIENT test function", "void", "", &VScriptCode::Shared::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); - - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::Shared::ShutdownHostGame); - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Shared::IsClientDLL); + Script_RegisterCommonAbstractions(s); + Script_RegisterCoreClientFunctions(s); } //--------------------------------------------------------------------------------- @@ -424,47 +386,37 @@ void Script_RegisterClientFunctions(CSquirrelVM* s) //--------------------------------------------------------------------------------- void Script_RegisterUIFunctions(CSquirrelVM* s) { - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native UI test function", "void", "", &VScriptCode::Shared::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + Script_RegisterCommonAbstractions(s); + Script_RegisterCoreClientFunctions(s); - s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::Ui::RefreshServerCount); + s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::Client::RefreshServerCount); + s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::Client::GetServerCount); // Functions for retrieving server browser data - s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerName); - s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerDescription); - s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerMap); - s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::Ui::GetServerPlaylist); - s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Ui::GetServerCurrentPlayers); - s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Ui::GetServerMaxPlayers); - s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::Ui::GetServerCount); + s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::Client::GetHiddenServerName); + s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerName); + s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerDescription); + + s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerMap); + s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerPlaylist); + s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Client::GetServerCurrentPlayers); + + s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Client::GetServerMaxPlayers); // Misc main menu functions - s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::Ui::GetPromoData); - - // Functions for creating servers - s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::Ui::CreateServer); - s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::Shared::IsServerActive); + s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::Client::GetPromoData); // Functions for connecting to servers - s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::Ui::ConnectToServer); - s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::Ui::ConnectToListedServer); - s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::Ui::ConnectToHiddenServer); - - s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::Ui::GetHiddenServerName); - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); - -#ifndef CLIENT_DLL // UI 'admin' functions controlling server code - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::SHARED::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::KickPlayerById); - - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::SHARED::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::SHARED::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::SHARED::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::SHARED::ShutdownHostGame); -#endif // !CLIENT_DLL - - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Shared::IsClientDLL); + s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::Client::ConnectToServer); + s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::Client::ConnectToListedServer); + s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::Client::ConnectToHiddenServer); +} + +//--------------------------------------------------------------------------------- +// Purpose: core client script functions +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterCoreClientFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Client::IsClientDLL); } diff --git a/r5dev/game/client/vscript_client.h b/r5dev/game/client/vscript_client.h index e69de29b..4009126e 100644 --- a/r5dev/game/client/vscript_client.h +++ b/r5dev/game/client/vscript_client.h @@ -0,0 +1,35 @@ +#ifndef VSCRIPT_CLIENT_H +#define VSCRIPT_CLIENT_H + +namespace VScriptCode +{ + namespace Client + { + SQRESULT RefreshServerCount(HSQUIRRELVM v); + SQRESULT GetServerCount(HSQUIRRELVM v); + + SQRESULT GetHiddenServerName(HSQUIRRELVM v); + SQRESULT GetServerName(HSQUIRRELVM v); + SQRESULT GetServerDescription(HSQUIRRELVM v); + + SQRESULT GetServerMap(HSQUIRRELVM v); + SQRESULT GetServerPlaylist(HSQUIRRELVM v); + + SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v); + SQRESULT GetServerMaxPlayers(HSQUIRRELVM v); + + SQRESULT GetPromoData(HSQUIRRELVM v); + + SQRESULT ConnectToListedServer(HSQUIRRELVM v); + SQRESULT ConnectToHiddenServer(HSQUIRRELVM v); + SQRESULT ConnectToServer(HSQUIRRELVM v); + + SQRESULT IsClientDLL(HSQUIRRELVM v); + } +} + +void Script_RegisterClientFunctions(CSquirrelVM* s); +void Script_RegisterUIFunctions(CSquirrelVM* s); +void Script_RegisterCoreClientFunctions(CSquirrelVM* s); + +#endif // VSCRIPT_CLIENT_H diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 563741f4..219133fe 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -13,10 +13,142 @@ #include "game/shared/vscript_shared.h" #include "vscript/languages/squirrel_re/include/sqvm.h" +#include "vscript_server.h" +#include +#include + namespace VScriptCode { namespace Server { + //----------------------------------------------------------------------------- + // Purpose: create server via native serverbrowser entries + // TODO: return a boolean on failure instead of raising an error, so we could + // determine from scripts whether or not to spin a local server, or connect + // to a dedicated server (for disconnecting and loading the lobby, for example) + //----------------------------------------------------------------------------- + SQRESULT CreateServer(HSQUIRRELVM v) + { + SQChar* serverName = sq_getstring(v, 1); + SQChar* serverDescription = sq_getstring(v, 2); + SQChar* serverMapName = sq_getstring(v, 3); + SQChar* serverPlaylist = sq_getstring(v, 4); + EServerVisibility_t eServerVisibility = static_cast(sq_getinteger(v, 5)); + + if (!VALID_CHARSTAR(serverName) || + !VALID_CHARSTAR(serverMapName) || + !VALID_CHARSTAR(serverPlaylist)) + { + return SQ_OK; + } + + // Adjust browser settings. + std::lock_guard l(g_pServerListManager->m_Mutex); + + g_pServerListManager->m_Server.m_svHostName = serverName; + g_pServerListManager->m_Server.m_svDescription = serverDescription; + g_pServerListManager->m_Server.m_svHostMap = serverMapName; + g_pServerListManager->m_Server.m_svPlaylist = serverPlaylist; + g_pServerListManager->m_ServerVisibility = eServerVisibility; + + // Launch server. + g_pServerListManager->LaunchServer(g_pServer->IsActive()); + + return SQ_OK; + + //v_SQVM_RaiseError(v, "\"%s\" is not supported on client builds.\n", "CreateServer"); + //return SQ_ERROR; + } + //----------------------------------------------------------------------------- + // Purpose: shuts the server down and disconnects all clients + //----------------------------------------------------------------------------- + SQRESULT DestroyServer(HSQUIRRELVM v) + { + if (g_pHostState->m_bActiveGame) + g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN; + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: kicks a player by given name + //----------------------------------------------------------------------------- + SQRESULT KickPlayerByName(HSQUIRRELVM v) + { + SQChar* playerName = sq_getstring(v, 1); + SQChar* reason = sq_getstring(v, 2); + + // Discard empty strings, this will use the default message instead. + if (!VALID_CHARSTAR(reason)) + reason = nullptr; + + g_pBanSystem->KickPlayerByName(playerName, reason); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: kicks a player by given handle or id + //----------------------------------------------------------------------------- + SQRESULT KickPlayerById(HSQUIRRELVM v) + { + SQChar* playerHandle = sq_getstring(v, 1); + SQChar* reason = sq_getstring(v, 2); + + // Discard empty strings, this will use the default message instead. + if (!VALID_CHARSTAR(reason)) + reason = nullptr; + + g_pBanSystem->KickPlayerById(playerHandle, reason); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: bans a player by given name + //----------------------------------------------------------------------------- + SQRESULT BanPlayerByName(HSQUIRRELVM v) + { + SQChar* playerName = sq_getstring(v, 1); + SQChar* reason = sq_getstring(v, 2); + + // Discard empty strings, this will use the default message instead. + if (!VALID_CHARSTAR(reason)) + reason = nullptr; + + g_pBanSystem->BanPlayerByName(playerName, reason); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: bans a player by given handle or id + //----------------------------------------------------------------------------- + SQRESULT BanPlayerById(HSQUIRRELVM v) + { + SQChar* playerHandle = sq_getstring(v, 1); + SQChar* reason = sq_getstring(v, 2); + + // Discard empty strings, this will use the default message instead. + if (!VALID_CHARSTAR(reason)) + reason = nullptr; + + g_pBanSystem->BanPlayerById(playerHandle, reason); + + return SQ_OK; + } + + //----------------------------------------------------------------------------- + // Purpose: unbans a player by given nucleus id or ip address + //----------------------------------------------------------------------------- + SQRESULT UnbanPlayer(HSQUIRRELVM v) + { + SQChar* szCriteria = sq_getstring(v, 1); + g_pBanSystem->UnbanPlayer(szCriteria); + + return SQ_OK; + } + //----------------------------------------------------------------------------- // Purpose: gets the number of real players on this server //----------------------------------------------------------------------------- @@ -35,6 +167,17 @@ namespace VScriptCode return SQ_OK; } + //----------------------------------------------------------------------------- + // Purpose: checks whether the server is active + //----------------------------------------------------------------------------- + SQRESULT IsServerActive(HSQUIRRELVM v) + { + bool isActive = g_pServer->IsActive(); + + sq_pushbool(v, isActive); + return SQ_OK; + } + //----------------------------------------------------------------------------- // Purpose: checks whether this SDK build is a dedicated server //----------------------------------------------------------------------------- @@ -52,24 +195,38 @@ namespace VScriptCode //--------------------------------------------------------------------------------- void Script_RegisterServerFunctions(CSquirrelVM* s) { - s->RegisterFunction("SDKNativeTest", "Script_SDKNativeTest", "Native SERVER test function", "void", "", &VScriptCode::Shared::SDKNativeTest); - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + Script_RegisterCommonAbstractions(s); + Script_RegisterCoreServerFunctions(s); + Script_RegisterAdminPanelFunctions(s); +} +//--------------------------------------------------------------------------------- +// Purpose: core server script functions +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterCoreServerFunctions(CSquirrelVM* s) +{ + s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::Server::IsServerActive); + s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::Server::IsDedicated); + + s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::Server::CreateServer); + s->RegisterFunction("DestroyServer", "Script_DestroyServer", "Shuts the local host game down", "void", "", &VScriptCode::Server::DestroyServer); +} + +//--------------------------------------------------------------------------------- +// Purpose: admin panel script functions +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterAdminPanelFunctions(CSquirrelVM* s) +{ s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::Server::GetNumHumanPlayers); s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::Server::GetNumFakeClients); - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); + s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::Server::KickPlayerByName); + s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::Server::KickPlayerById); - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string, string", &VScriptCode::Shared::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::Shared::KickPlayerById); + s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::Server::BanPlayerByName); + s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::Server::BanPlayerById); - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::Shared::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string, string", &VScriptCode::Shared::BanPlayerById); - - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string, string", &VScriptCode::Shared::UnbanPlayer); - - s->RegisterFunction("ShutdownHostGame", "Script_ShutdownHostGame", "Shuts the local host game down", "void", "", &VScriptCode::Shared::ShutdownHostGame); - - s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::Server::IsDedicated); + s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::Server::UnbanPlayer); } diff --git a/r5dev/game/server/vscript_server.h b/r5dev/game/server/vscript_server.h index e69de29b..ed82598d 100644 --- a/r5dev/game/server/vscript_server.h +++ b/r5dev/game/server/vscript_server.h @@ -0,0 +1,29 @@ +#ifndef VSCRIPT_SERVER_H +#define VSCRIPT_SERVER_H + +namespace VScriptCode +{ + namespace Server + { + SQRESULT CreateServer(HSQUIRRELVM v); + SQRESULT DestroyServer(HSQUIRRELVM v); + + SQRESULT KickPlayerByName(HSQUIRRELVM v); + SQRESULT KickPlayerById(HSQUIRRELVM v); + SQRESULT BanPlayerByName(HSQUIRRELVM v); + SQRESULT BanPlayerById(HSQUIRRELVM v); + SQRESULT UnbanPlayer(HSQUIRRELVM v); + + SQRESULT GetNumHumanPlayers(HSQUIRRELVM v); + SQRESULT GetNumFakeClients(HSQUIRRELVM v); + + SQRESULT IsServerActive(HSQUIRRELVM v); + SQRESULT IsDedicated(HSQUIRRELVM v); + } +} + +void Script_RegisterServerFunctions(CSquirrelVM* s); +void Script_RegisterCoreServerFunctions(CSquirrelVM* s); +void Script_RegisterAdminPanelFunctions(CSquirrelVM* s); + +#endif // VSCRIPT_SERVER_H diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 0e951046..25c9b167 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -13,18 +13,12 @@ #include "core/stdafx.h" #include "vpc/keyvalues.h" -#ifndef CLIENT_DLL #include "engine/server/server.h" -#endif // CLIENT_DLL #include "engine/cmodel_bsp.h" #include "engine/host_state.h" #include "networksystem/pylon.h" -#ifndef CLIENT_DLL #include "networksystem/bansystem.h" -#endif // !CLIENT_DLL -#ifndef SERVER_DLL #include "networksystem/listmanager.h" -#endif // !SERVER_DLL #include "vscript_shared.h" #include "vscript/languages/squirrel_re/include/sqvm.h" @@ -32,15 +26,6 @@ namespace VScriptCode { namespace Shared { - //----------------------------------------------------------------------------- - // Purpose: SDK test and example body - //----------------------------------------------------------------------------- - SQRESULT SDKNativeTest(HSQUIRRELVM v) - { - // Function code goes here. - return SQ_OK; - } - //----------------------------------------------------------------------------- // Purpose: expose SDK version to the VScript API //----------------------------------------------------------------------------- @@ -89,123 +74,17 @@ namespace VScriptCode return SQ_OK; } - //----------------------------------------------------------------------------- - // Purpose: checks whether the server is active - //----------------------------------------------------------------------------- - SQRESULT IsServerActive(HSQUIRRELVM v) - { - bool isActive = false; -#ifndef CLIENT_DLL - isActive = g_pServer->IsActive(); -#endif // !CLIENT_DLL - - sq_pushbool(v, isActive); - return SQ_OK; - } -#ifndef CLIENT_DLL - - //----------------------------------------------------------------------------- - // Purpose: kicks a player by given name - //----------------------------------------------------------------------------- - SQRESULT KickPlayerByName(HSQUIRRELVM v) - { - SQChar* playerName = sq_getstring(v, 1); - SQChar* reason = sq_getstring(v, 2); - - // Discard empty strings, this will use the default message instead. - if (!VALID_CHARSTAR(reason)) - reason = nullptr; - - g_pBanSystem->KickPlayerByName(playerName, reason); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: kicks a player by given handle or id - //----------------------------------------------------------------------------- - SQRESULT KickPlayerById(HSQUIRRELVM v) - { - SQChar* playerHandle = sq_getstring(v, 1); - SQChar* reason = sq_getstring(v, 2); - - // Discard empty strings, this will use the default message instead. - if (!VALID_CHARSTAR(reason)) - reason = nullptr; - - g_pBanSystem->KickPlayerById(playerHandle, reason); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: bans a player by given name - //----------------------------------------------------------------------------- - SQRESULT BanPlayerByName(HSQUIRRELVM v) - { - SQChar* playerName = sq_getstring(v, 1); - SQChar* reason = sq_getstring(v, 2); - - // Discard empty strings, this will use the default message instead. - if (!VALID_CHARSTAR(reason)) - reason = nullptr; - - g_pBanSystem->BanPlayerByName(playerName, reason); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: bans a player by given handle or id - //----------------------------------------------------------------------------- - SQRESULT BanPlayerById(HSQUIRRELVM v) - { - SQChar* playerHandle = sq_getstring(v, 1); - SQChar* reason = sq_getstring(v, 2); - - // Discard empty strings, this will use the default message instead. - if (!VALID_CHARSTAR(reason)) - reason = nullptr; - - g_pBanSystem->BanPlayerById(playerHandle, reason); - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: unbans a player by given nucleus id or ip address - //----------------------------------------------------------------------------- - SQRESULT UnbanPlayer(HSQUIRRELVM v) - { - SQChar* szCriteria = sq_getstring(v, 1); - g_pBanSystem->UnbanPlayer(szCriteria); - - return SQ_OK; - } -#endif // !CLIENT_DLL - //----------------------------------------------------------------------------- - // Purpose: shutdown local game (host only) - //----------------------------------------------------------------------------- - SQRESULT ShutdownHostGame(HSQUIRRELVM v) - { - if (g_pHostState->m_bActiveGame) - g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN; - - return SQ_OK; - } - - //----------------------------------------------------------------------------- - // Purpose: checks whether this SDK build is a client dll - //----------------------------------------------------------------------------- - SQRESULT IsClientDLL(HSQUIRRELVM v) - { -#ifdef CLIENT_DLL - constexpr SQBool bClientOnly = true; -#else - constexpr SQBool bClientOnly = false; -#endif - sq_pushbool(v, bClientOnly); - return SQ_OK; - } } } + +//--------------------------------------------------------------------------------- +// Purpose: common script abstractions +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterCommonAbstractions(CSquirrelVM* s) +{ + s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + + s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); + s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); +} diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index 2abb9ccf..fd579a22 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -9,74 +9,20 @@ inline void*(*Script_Remote_BeginRegisteringFunctions)(void); inline CMemory p_RestoreRemoteChecksumsFromSaveGame; inline void*(*RestoreRemoteChecksumsFromSaveGame)(void* a1, void* a2); -#ifndef CLIENT_DLL inline uint32_t* g_nServerRemoteChecksum = nullptr; -#endif // !CLIENT_DLL -#ifndef SERVER_DLL inline uint32_t* g_nClientRemoteChecksum = nullptr; -#endif // !SERVER_DLL namespace VScriptCode { namespace Shared { - SQRESULT SDKNativeTest(HSQUIRRELVM v); SQRESULT GetSDKVersion(HSQUIRRELVM v); SQRESULT GetAvailableMaps(HSQUIRRELVM v); SQRESULT GetAvailablePlaylists(HSQUIRRELVM v); - SQRESULT ShutdownHostGame(HSQUIRRELVM v); -#ifndef SERVER_DLL - SQRESULT IsClientDLL(HSQUIRRELVM v); -#endif // !SERVER_DLL - SQRESULT IsServerActive(HSQUIRRELVM v); -#ifndef CLIENT_DLL - SQRESULT KickPlayerByName(HSQUIRRELVM v); - SQRESULT KickPlayerById(HSQUIRRELVM v); - SQRESULT BanPlayerByName(HSQUIRRELVM v); - SQRESULT BanPlayerById(HSQUIRRELVM v); - SQRESULT UnbanPlayer(HSQUIRRELVM v); -#endif // !CLIENT_DLL } -#ifndef CLIENT_DLL - namespace Server - { - SQRESULT GetNumHumanPlayers(HSQUIRRELVM v); - SQRESULT GetNumFakeClients(HSQUIRRELVM v); - SQRESULT IsDedicated(HSQUIRRELVM v); - } -#endif // !CLIENT_DLL -#ifndef SERVER_DLL - namespace Client - { - } - namespace Ui - { - SQRESULT RefreshServerCount(HSQUIRRELVM v); - SQRESULT GetServerName(HSQUIRRELVM v); - SQRESULT GetServerDescription(HSQUIRRELVM v); - SQRESULT GetServerMap(HSQUIRRELVM v); - SQRESULT GetServerPlaylist(HSQUIRRELVM v); - SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v); - SQRESULT GetServerMaxPlayers(HSQUIRRELVM v); - SQRESULT GetServerCount(HSQUIRRELVM v); - SQRESULT GetPromoData(HSQUIRRELVM v); - SQRESULT ConnectToListedServer(HSQUIRRELVM v); - SQRESULT CreateServer(HSQUIRRELVM v); - SQRESULT ConnectToHiddenServer(HSQUIRRELVM v); - SQRESULT GetHiddenServerName(HSQUIRRELVM v); - SQRESULT ConnectToServer(HSQUIRRELVM v); - } -#endif // !SERVER_DLL } -#ifndef CLIENT_DLL -void Script_RegisterServerFunctions(CSquirrelVM* s); -#endif // !CLIENT_DLL - -#ifndef SERVER_DLL -void Script_RegisterClientFunctions(CSquirrelVM* s); -void Script_RegisterUIFunctions(CSquirrelVM* s); -#endif // !SERVER_DLL +void Script_RegisterCommonAbstractions(CSquirrelVM* s); /////////////////////////////////////////////////////////////////////////////// class VScriptShared : public IDetour @@ -85,12 +31,8 @@ class VScriptShared : public IDetour { LogFunAdr("Remote_BeginRegisteringFunctions", p_Script_Remote_BeginRegisteringFunctions.GetPtr()); LogFunAdr("RestoreRemoteChecksumsFromSaveGame", p_RestoreRemoteChecksumsFromSaveGame.GetPtr()); -#ifndef CLIENT_DLL LogVarAdr("g_nServerRemoteChecksum", reinterpret_cast(g_nServerRemoteChecksum)); -#endif // !CLIENT_DLL -#ifndef SERVER_DLL LogVarAdr("g_nClientRemoteChecksum", reinterpret_cast(g_nClientRemoteChecksum)); -#endif // !SERVER_DLL } virtual void GetFun(void) const { @@ -102,12 +44,8 @@ class VScriptShared : public IDetour } virtual void GetVar(void) const { -#ifndef CLIENT_DLL g_nServerRemoteChecksum = p_RestoreRemoteChecksumsFromSaveGame.Offset(0x1C0).FindPatternSelf("48 8D 15", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); -#endif // !CLIENT_DLL -#ifndef SERVER_DLL g_nClientRemoteChecksum = p_Script_Remote_BeginRegisteringFunctions.Offset(0x0).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast(); -#endif // !SERVER_DLL } virtual void GetCon(void) const { } virtual void Attach(void) const { } diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index 76d069ac..990141f2 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -13,6 +13,10 @@ void(*ServerScriptRegister_Callback)(CSquirrelVM* s) = nullptr; void(*ClientScriptRegister_Callback)(CSquirrelVM* s) = nullptr; void(*UiScriptRegister_Callback)(CSquirrelVM* s) = nullptr; +// Admin panel functions, NULL on client only builds. +void(*CoreServerScriptRegister_Callback)(CSquirrelVM* s) = nullptr; +void(*AdminPanelScriptRegister_Callback)(CSquirrelVM* s) = nullptr; + //--------------------------------------------------------------------------------- // Purpose: Initialises a Squirrel VM instance // Output : True on success, false on failure @@ -29,28 +33,32 @@ SQBool CSquirrelVM::Init(CSquirrelVM* s, SQCONTEXT context, SQFloat curTime) switch (context) { -#ifndef CLIENT_DLL case SQCONTEXT::SERVER: g_pServerScript = s; + if (ServerScriptRegister_Callback) ServerScriptRegister_Callback(s); break; -#endif -#ifndef DEDICATED case SQCONTEXT::CLIENT: g_pClientScript = s; + if (ClientScriptRegister_Callback) ClientScriptRegister_Callback(s); break; case SQCONTEXT::UI: g_pUIScript = s; + if (UiScriptRegister_Callback) UiScriptRegister_Callback(s); + if (CoreServerScriptRegister_Callback) + CoreServerScriptRegister_Callback(s); + if (AdminPanelScriptRegister_Callback) + AdminPanelScriptRegister_Callback(s); + break; -#endif } return true; @@ -110,21 +118,17 @@ void CSquirrelVM::SetAsCompiler(RSON::Node_t* rson) const SQCONTEXT context = GetContext(); switch (context) { -#ifndef CLIENT_DLL case SQCONTEXT::SERVER: { v_Script_SetServerPrecompiler(context, rson); break; } -#endif -#ifndef DEDICATED case SQCONTEXT::CLIENT: case SQCONTEXT::UI: { v_Script_SetClientPrecompiler(context, rson); break; } -#endif } } @@ -187,21 +191,17 @@ void CSquirrelVM::CompileModScripts() switch (GetVM()->GetContext()) { -#ifndef CLIENT_DLL case SQCONTEXT::SERVER: { v_CSquirrelVM_PrecompileServerScripts(this, GetContext(), (char**)scriptPathArray, scriptCount); break; } -#endif -#ifndef DEDICATED case SQCONTEXT::CLIENT: case SQCONTEXT::UI: { v_CSquirrelVM_PrecompileClientScripts(this, GetContext(), (char**)scriptPathArray, scriptCount); break; } -#endif } // clean up our allocated script paths diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index 2ef9c871..94fe8d8b 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -47,6 +47,9 @@ extern void(*ServerScriptRegister_Callback)(CSquirrelVM* s); extern void(*ClientScriptRegister_Callback)(CSquirrelVM* s); extern void(*UiScriptRegister_Callback)(CSquirrelVM* s); +extern void(*CoreServerScriptRegister_Callback)(CSquirrelVM* s); +extern void(*AdminPanelScriptRegister_Callback)(CSquirrelVM* s); + inline CMemory p_CSquirrelVM_Init; inline bool(*v_CSquirrelVM_Init)(CSquirrelVM* s, SQCONTEXT context, SQFloat curtime); From dccb897c278c9a9e35dd0900f94efdb5ad4d9e23 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:14:09 +0200 Subject: [PATCH 06/25] Make 'sv_usercmd_dualwield_enable' server and client Must be for server and client, as its used in shared code. --- r5dev/common/global.cpp | 7 ++++--- r5dev/common/global.h | 3 ++- r5dev/game/shared/usercmd.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index 30c0c86d..44960bfb 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -26,6 +26,8 @@ ConVar* fps_max = nullptr; ConVar* usercmd_frametime_max = nullptr; ConVar* usercmd_frametime_min = nullptr; +ConVar* usercmd_dualwield_enable = nullptr; + ConVar* staticProp_no_fade_scalar = nullptr; ConVar* staticProp_gather_size_weight = nullptr; @@ -115,7 +117,6 @@ ConVar* sv_voiceEcho = nullptr; ConVar* sv_voiceenable = nullptr; ConVar* sv_alltalk = nullptr; -ConVar* sv_usercmd_dualwield_enable = nullptr; ConVar* player_userCmdsQueueWarning = nullptr; //#ifdef DEDICATED @@ -327,8 +328,6 @@ void ConVar_StaticInit(void) sv_validatePersonaName = ConVar::StaticCreate("sv_validatePersonaName" , "1" , FCVAR_RELEASE, "Validate the client's textual persona name on connect.", true, 0.f, false, 0.f, nullptr, nullptr); sv_minPersonaNameLength = ConVar::StaticCreate("sv_minPersonaNameLength", "4" , FCVAR_RELEASE, "The minimum length of the client's textual persona name.", true, 0.f, false, 0.f, nullptr, nullptr); sv_maxPersonaNameLength = ConVar::StaticCreate("sv_maxPersonaNameLength", "16", FCVAR_RELEASE, "The maximum length of the client's textual persona name.", true, 0.f, false, 0.f, nullptr, nullptr); - - sv_usercmd_dualwield_enable = ConVar::StaticCreate("sv_usercmd_dualwield_enable", "0", FCVAR_RELEASE, "Allows setting dual wield cycle slots, and activating multiple inventory weapons from UserCmd.", false, 0.f, false, 0.f, nullptr, nullptr); #endif // !CLIENT_DLL #if !defined (GAMEDLL_S0) && !defined (GAMEDLL_S1) bhit_depth_test = ConVar::StaticCreate("bhit_depth_test", "0", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Use depth test for bullet ray trace overlay.", false, 0.f, false, 0.f, nullptr, nullptr); @@ -405,6 +404,8 @@ void ConVar_StaticInit(void) // Taken from S15: usercmd_frametime_max = ConVar::StaticCreate("usercmd_frametime_max", "0.100", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "The largest amount of simulation seconds a UserCmd can have.", false, 0.f, false, 0.f, nullptr, nullptr); usercmd_frametime_min = ConVar::StaticCreate("usercmd_frametime_min", "0.002857", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "The smallest amount of simulation seconds a UserCmd can have.", false, 0.f, false, 0.f, nullptr, nullptr); + + usercmd_dualwield_enable = ConVar::StaticCreate("usercmd_dualwield_enable", "0", FCVAR_RELEASE, "Allows setting dual wield cycle slots, and activating multiple inventory weapons from UserCmd.", false, 0.f, false, 0.f, nullptr, nullptr); //------------------------------------------------------------------------- // FILESYSTEM | fs_showWarnings = ConVar::StaticCreate("fs_showWarnings" , "0", FCVAR_DEVELOPMENTONLY, "Logs the FileSystem warnings to the console, filtered by 'fs_warning_level' ( !slower! ).", true, 0.f, true, 2.f, nullptr, "0 = log to file. 1 = 0 + log to console. 2 = 1 + log to notify."); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index 8af21e67..c61f16da 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -17,6 +17,8 @@ extern ConVar* fps_max; extern ConVar* usercmd_frametime_max; extern ConVar* usercmd_frametime_min; +extern ConVar* usercmd_dualwield_enable; + extern ConVar* staticProp_no_fade_scalar; extern ConVar* staticProp_gather_size_weight; @@ -105,7 +107,6 @@ extern ConVar* sv_voiceEcho; extern ConVar* sv_voiceenable; extern ConVar* sv_alltalk; -extern ConVar* sv_usercmd_dualwield_enable; extern ConVar* player_userCmdsQueueWarning; //#ifdef DEDICATED diff --git a/r5dev/game/shared/usercmd.cpp b/r5dev/game/shared/usercmd.cpp index a519ade2..d540ece3 100644 --- a/r5dev/game/shared/usercmd.cpp +++ b/r5dev/game/shared/usercmd.cpp @@ -52,7 +52,7 @@ int ReadUserCmd(bf_read* buf, CUserCmd* move, CUserCmd* from) // Checks are only required if cycleslot is valid; see 'CPlayer::UpdateWeaponSlots'. if (move->cycleslot != WEAPON_INVENTORY_SLOT_INVALID) { - const bool dualWieldEnabled = sv_usercmd_dualwield_enable->GetBool(); + const bool dualWieldEnabled = usercmd_dualwield_enable->GetBool(); // Client could instruct the server to switch cycle slots for inventory // weapons, however, the client could also cycle to the dual wield slots. From 6bb622314e55fe011b9ee51453a497af6acd04a3 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:16:06 +0200 Subject: [PATCH 07/25] Improve persona name validations Move all server convars out of the EbisuSDK lib, the min/max name len are now parameterized. This also makes it possible to use the code on the client if ever needed. --- r5dev/ebisusdk/EbisuSDK.cpp | 12 +++--------- r5dev/ebisusdk/EbisuSDK.h | 2 +- r5dev/engine/server/server.cpp | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/r5dev/ebisusdk/EbisuSDK.cpp b/r5dev/ebisusdk/EbisuSDK.cpp index 4f19f94c..a87115a5 100644 --- a/r5dev/ebisusdk/EbisuSDK.cpp +++ b/r5dev/ebisusdk/EbisuSDK.cpp @@ -1,5 +1,4 @@ #include "core/stdafx.h" -#include "tier1/cvar.h" #include "ebisusdk/EbisuSDK.h" #include "engine/server/sv_main.h" @@ -44,17 +43,12 @@ bool IsOriginInitialized() // Input : *pszName - // Output : true on success, false on failure //----------------------------------------------------------------------------- -bool IsValidPersonaName(const char* pszName) +bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen) { - if (!sv_validatePersonaName->GetBool()) - { - return true; - } - size_t len = strlen(pszName); - if (len < sv_minPersonaNameLength->GetInt() || - len > sv_maxPersonaNameLength->GetInt()) + if (len < nMinLen || + len > nMaxLen) { return false; } diff --git a/r5dev/ebisusdk/EbisuSDK.h b/r5dev/ebisusdk/EbisuSDK.h index 384c8a54..e1f91265 100644 --- a/r5dev/ebisusdk/EbisuSDK.h +++ b/r5dev/ebisusdk/EbisuSDK.h @@ -19,7 +19,7 @@ inline bool* g_EbisuProfileInit = nullptr; /////////////////////////////////////////////////////////////////////////////// void HEbisuSDK_Init(); bool IsOriginInitialized(); -bool IsValidPersonaName(const char* pszName); +bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen); /////////////////////////////////////////////////////////////////////////////// class VEbisuSDK : public IDetour diff --git a/r5dev/engine/server/server.cpp b/r5dev/engine/server/server.cpp index 6a355f14..2242269b 100644 --- a/r5dev/engine/server/server.cpp +++ b/r5dev/engine/server/server.cpp @@ -105,8 +105,24 @@ CClient* CServer::ConnectClient(CServer* pServer, user_creds_s* pChallenge) DevMsg(eDLL_T::SERVER, "Processing connectionless challenge for '[%s]:%i' ('%llu')\n", pszAddresBuffer, nPort, nNucleusID); + bool bValidName = false; + + if (VALID_CHARSTAR(pszPersonaName) && + V_IsValidUTF8(pszPersonaName)) + { + if (sv_validatePersonaName->GetBool() && + !IsValidPersonaName(pszPersonaName, sv_minPersonaNameLength->GetInt(), sv_maxPersonaNameLength->GetInt())) + { + bValidName = false; + } + else + { + bValidName = true; + } + } + // Only proceed connection if the client's name is valid and UTF-8 encoded. - if (!VALID_CHARSTAR(pszPersonaName) || !V_IsValidUTF8(pszPersonaName) || !IsValidPersonaName(pszPersonaName)) + if (!bValidName) { pServer->RejectConnection(pServer->m_Socket, &pChallenge->netAdr, "#Valve_Reject_Invalid_Name"); if (bEnableLogging) From 7455d4da2decc1197a39cfbba19024333907b1db Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:17:28 +0200 Subject: [PATCH 08/25] CPylon: add getters and setters for error/token fields --- r5dev/networksystem/pylon.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/r5dev/networksystem/pylon.h b/r5dev/networksystem/pylon.h index 25747802..a5dcae66 100644 --- a/r5dev/networksystem/pylon.h +++ b/r5dev/networksystem/pylon.h @@ -21,6 +21,11 @@ public: bool QueryServer(const char* endpoint, const char* request, string& outResponse, string& outMessage, CURLINFO& outStatus) const; bool KeepAlive(const NetGameServer_t& netGameServer); + inline const string& GetCurrentToken() const { return m_Token; } + inline const string& GetCurrentError() const { return m_ErrorMsg; } + + inline void SetCurrentToken(const string& token) { m_Token = token; } + inline void SetCurrentError(const string& error) { m_ErrorMsg = error; } private: string m_Token; From 6cecc3297e02bd553146d1a9b43ed523bb624303 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:19:43 +0200 Subject: [PATCH 09/25] Move KeepAlive function to HostState Only used in HostState, moved to HostState with static linkage. --- r5dev/engine/host_state.cpp | 47 +++++++++++++++++++++++++++++++++-- r5dev/networksystem/pylon.cpp | 38 ---------------------------- r5dev/networksystem/pylon.h | 1 - 3 files changed, 45 insertions(+), 41 deletions(-) diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index f8ee976f..b33c96e2 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -17,6 +17,7 @@ #include "datacache/mdlcache.h" #ifndef CLIENT_DLL #include "engine/server/sv_rcon.h" +#include "engine/server/server.h" #endif // !CLIENT_DLL #ifndef DEDICATED #include "engine/client/cl_rcon.h" @@ -53,6 +54,46 @@ #endif // !CLIENT_DLL #include "game/shared/vscript_shared.h" +#ifndef CLIENT_DLL +//----------------------------------------------------------------------------- +// Purpose: Send keep alive request to Pylon Master Server. +// Input : &netGameServer - +// Output : Returns true on success, false otherwise. +//----------------------------------------------------------------------------- +static bool HostState_KeepAlive(const NetGameServer_t& netGameServer) +{ + if (!g_pServer->IsActive() || !sv_pylonVisibility->GetBool()) // Check for active game. + { + return false; + } + + string errorMsg; + string hostToken; + + const bool result = g_pMasterServer->PostServerHost(errorMsg, hostToken, netGameServer); + if (!result) + { + if (!errorMsg.empty() && g_pMasterServer->GetCurrentError().compare(errorMsg) != NULL) + { + g_pMasterServer->SetCurrentError(errorMsg); + Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str()); + } + } + else // Attempt to log the token, if there is one. + { + if (!hostToken.empty() && g_pMasterServer->GetCurrentToken().compare(hostToken) != NULL) + { + g_pMasterServer->SetCurrentToken(hostToken); + DevMsg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n", + g_svReset, g_svGreyB, + hostToken.c_str(), g_svReset); + } + } + + return result; +} +#endif // !CLIENT_DLL + //----------------------------------------------------------------------------- // Purpose: state machine's main processing loop //----------------------------------------------------------------------------- @@ -303,7 +344,7 @@ void CHostState::Think(void) const ).count() }; - std::thread(&CPylon::KeepAlive, g_pMasterServer, netGameServer).detach(); + std::thread(&HostState_KeepAlive, netGameServer).detach(); pylonTimer.Start(); } #endif // DEDICATED @@ -370,9 +411,11 @@ void CHostState::State_NewGame(void) DevMsg(eDLL_T::ENGINE, "%s: Loading level: '%s'\n", __FUNCTION__, g_pHostState->m_levelName); LARGE_INTEGER time{}; + +#ifndef CLIENT_DLL bool bSplitScreenConnect = m_bSplitScreenConnect; m_bSplitScreenConnect = 0; -#ifndef CLIENT_DLL + if (!g_pServerGameClients) // Init Game if it ain't valid. { SV_InitGameDLL(); diff --git a/r5dev/networksystem/pylon.cpp b/r5dev/networksystem/pylon.cpp index 46ed2200..0c8b91ce 100644 --- a/r5dev/networksystem/pylon.cpp +++ b/r5dev/networksystem/pylon.cpp @@ -187,44 +187,6 @@ bool CPylon::PostServerHost(string& outMessage, string& outToken, return true; } -//----------------------------------------------------------------------------- -// Purpose: Send keep alive request to Pylon Master Server. -// Input : &netGameServer - -// Output : Returns true on success, false otherwise. -//----------------------------------------------------------------------------- -bool CPylon::KeepAlive(const NetGameServer_t& netGameServer) -{ - if (!g_pServer->IsActive() || !sv_pylonVisibility->GetBool()) // Check for active game. - { - return false; - } - - string errorMsg; - string hostToken; - - const bool result = PostServerHost(errorMsg, hostToken, netGameServer); - if (!result) - { - if (!errorMsg.empty() && m_ErrorMsg.compare(errorMsg) != NULL) - { - m_ErrorMsg = errorMsg; - Error(eDLL_T::SERVER, NO_ERROR, "%s\n", errorMsg.c_str()); - } - } - else // Attempt to log the token, if there is one. - { - if (!hostToken.empty() && m_Token.compare(hostToken) != NULL) - { - m_Token = hostToken; - DevMsg(eDLL_T::SERVER, "Published server with token: %s'%s%s%s'\n", - g_svReset, g_svGreyB, - hostToken.c_str(), g_svReset); - } - } - - return result; -} - //----------------------------------------------------------------------------- // Purpose: Checks a list of clients for their banned status. // Input : &inBannedVec - diff --git a/r5dev/networksystem/pylon.h b/r5dev/networksystem/pylon.h index a5dcae66..b7b7d1c9 100644 --- a/r5dev/networksystem/pylon.h +++ b/r5dev/networksystem/pylon.h @@ -20,7 +20,6 @@ public: bool SendRequest(const char* endpoint, const nlohmann::json& requestJson, nlohmann::json& responseJson, string& outMessage, CURLINFO& status, const char* errorText = nullptr) const; bool QueryServer(const char* endpoint, const char* request, string& outResponse, string& outMessage, CURLINFO& outStatus) const; - bool KeepAlive(const NetGameServer_t& netGameServer); inline const string& GetCurrentToken() const { return m_Token; } inline const string& GetCurrentError() const { return m_ErrorMsg; } From 54536a2652fbbd3d369a25b795892f0760235d2b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:21:58 +0200 Subject: [PATCH 10/25] Parameterize changelevel or map in CServerListManager::LaunchServer() Parameterized; whether or not to drop all clients (map = drop, changelevel = keep). --- r5dev/gameui/IBrowser.cpp | 9 ++++++--- r5dev/networksystem/listmanager.cpp | 8 ++++---- r5dev/networksystem/listmanager.h | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/r5dev/gameui/IBrowser.cpp b/r5dev/gameui/IBrowser.cpp index bcea5e16..d94829cd 100644 --- a/r5dev/gameui/IBrowser.cpp +++ b/r5dev/gameui/IBrowser.cpp @@ -559,6 +559,9 @@ void CBrowser::HostPanel(void) } ImGui::Spacing(); + + const bool bServerActive = g_pServer->IsActive(); + if (!g_pHostState->m_bActiveGame) { if (ImGui::Button("Start server", ImVec2(ImGui::GetWindowContentRegionWidth(), 32))) @@ -568,7 +571,7 @@ void CBrowser::HostPanel(void) bool bEnforceField = g_pServerListManager->m_ServerVisibility == EServerVisibility_t::OFFLINE ? true : !g_pServerListManager->m_Server.m_svHostName.empty(); if (bEnforceField && !g_pServerListManager->m_Server.m_svPlaylist.empty() && !g_pServerListManager->m_Server.m_svHostMap.empty()) { - g_pServerListManager->LaunchServer(); // Launch server. + g_pServerListManager->LaunchServer(bServerActive); // Launch server. } else { @@ -622,7 +625,7 @@ void CBrowser::HostPanel(void) { if (!g_pServerListManager->m_Server.m_svHostMap.empty()) { - g_pServerListManager->LaunchServer(); + g_pServerListManager->LaunchServer(bServerActive); } else { @@ -631,7 +634,7 @@ void CBrowser::HostPanel(void) } } - if (g_pServer->IsActive()) + if (bServerActive) { ImGui::Spacing(); ImGui::Separator(); diff --git a/r5dev/networksystem/listmanager.cpp b/r5dev/networksystem/listmanager.cpp index 7cd5a5e1..8a508990 100644 --- a/r5dev/networksystem/listmanager.cpp +++ b/r5dev/networksystem/listmanager.cpp @@ -55,13 +55,13 @@ void CServerListManager::ClearServerList(void) //----------------------------------------------------------------------------- // Purpose: Launch server with given parameters //----------------------------------------------------------------------------- -void CServerListManager::LaunchServer(void) const +void CServerListManager::LaunchServer(const bool bChangeLevel) const { if (!ThreadInMainThread()) { - g_TaskScheduler->Dispatch([this]() + g_TaskScheduler->Dispatch([this, bChangeLevel]() { - this->LaunchServer(); + this->LaunchServer(bChangeLevel); }, 0); return; } @@ -77,7 +77,7 @@ void CServerListManager::LaunchServer(void) const KeyValues::ParsePlaylists(m_Server.m_svPlaylist.c_str()); mp_gamemode->SetValue(m_Server.m_svPlaylist.c_str()); - ProcessCommand(Format("%s \"%s\"", g_pServer->IsActive() ? "changelevel" : "map", m_Server.m_svHostMap.c_str()).c_str()); + ProcessCommand(Format("%s \"%s\"", bChangeLevel ? "changelevel" : "map", m_Server.m_svHostMap.c_str()).c_str()); } //----------------------------------------------------------------------------- diff --git a/r5dev/networksystem/listmanager.h b/r5dev/networksystem/listmanager.h index 5849084e..73fc78bc 100644 --- a/r5dev/networksystem/listmanager.h +++ b/r5dev/networksystem/listmanager.h @@ -23,7 +23,7 @@ public: size_t RefreshServerList(string& svMessage); void ClearServerList(void); - void LaunchServer(void) const; + void LaunchServer(const bool bChangeLevel) const; void ConnectToServer(const string& svIp, const string& svPort, const string& svNetKey) const; void ConnectToServer(const string& svServer, const string& svNetKey) const; From 6ccf3baa5a0fd58cac939ff15e59a49b56013033 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:27:28 +0200 Subject: [PATCH 11/25] Split server/client specific game utils Split into their respective libraries, this is to avoid linker errors regarding undefined symbols. --- r5dev/game/CMakeLists.txt | 4 ++++ r5dev/game/client/util_client.cpp | 8 ++++++++ r5dev/game/client/util_client.h | 9 +++++++++ r5dev/game/server/gameinterface.cpp | 2 +- r5dev/game/server/physics_main.cpp | 4 ++-- r5dev/game/server/util_server.cpp | 25 +++++++++++++++++++++++++ r5dev/game/server/util_server.h | 12 ++++++++++++ r5dev/game/shared/util_shared.cpp | 22 ---------------------- r5dev/game/shared/util_shared.h | 8 -------- 9 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 r5dev/game/client/util_client.cpp create mode 100644 r5dev/game/client/util_client.h create mode 100644 r5dev/game/server/util_server.cpp create mode 100644 r5dev/game/server/util_server.h diff --git a/r5dev/game/CMakeLists.txt b/r5dev/game/CMakeLists.txt index cf902931..6984ca98 100644 --- a/r5dev/game/CMakeLists.txt +++ b/r5dev/game/CMakeLists.txt @@ -69,6 +69,8 @@ add_sources( SOURCE_GROUP "Server" "server/player.cpp" "server/player.h" "server/playerlocaldata.h" + "server/util_server.cpp" + "server/util_server.h" "server/vscript_server.cpp" "server/vscript_server.h" ) @@ -95,6 +97,8 @@ add_sources( SOURCE_GROUP "Client" "client/movehelper_client.cpp" "client/movehelper_client.h" "client/spritemodel.cpp" + "client/util_client.cpp" + "client/util_client.h" "client/viewrender.cpp" "client/viewrender.h" "client/vscript_client.cpp" diff --git a/r5dev/game/client/util_client.cpp b/r5dev/game/client/util_client.cpp new file mode 100644 index 00000000..1884ca3b --- /dev/null +++ b/r5dev/game/client/util_client.cpp @@ -0,0 +1,8 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#include "util_client.h" + +// Currently empty; add client specific game utils here... diff --git a/r5dev/game/client/util_client.h b/r5dev/game/client/util_client.h new file mode 100644 index 00000000..a449bf1d --- /dev/null +++ b/r5dev/game/client/util_client.h @@ -0,0 +1,9 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#ifndef UTIL_CLIENT_H +#define UTIL_CLIENT_H + +#endif // UTIL_CLIENT_H diff --git a/r5dev/game/server/gameinterface.cpp b/r5dev/game/server/gameinterface.cpp index 5fac56bc..1273ef65 100644 --- a/r5dev/game/server/gameinterface.cpp +++ b/r5dev/game/server/gameinterface.cpp @@ -16,7 +16,7 @@ #include "entitylist.h" #include "baseanimating.h" #include "game/shared/usercmd.h" -#include "game/shared/util_shared.h" +#include "game/server/util_server.h" //----------------------------------------------------------------------------- // This is called when a new game is started. (restart, map) diff --git a/r5dev/game/server/physics_main.cpp b/r5dev/game/server/physics_main.cpp index 22aae7ee..f3ee0e49 100644 --- a/r5dev/game/server/physics_main.cpp +++ b/r5dev/game/server/physics_main.cpp @@ -8,9 +8,9 @@ #include "tier1/cvar.h" #include "player.h" #include "physics_main.h" -#include "engine/server/server.h" +#include "engine/server/server.h" #include "engine/client/client.h" -#include "game/shared/util_shared.h" +#include "game/server/util_server.h" //----------------------------------------------------------------------------- // Purpose: Runs the command simulation for fake players diff --git a/r5dev/game/server/util_server.cpp b/r5dev/game/server/util_server.cpp new file mode 100644 index 00000000..63d77a4f --- /dev/null +++ b/r5dev/game/server/util_server.cpp @@ -0,0 +1,25 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#include "game/server/player.h" +#include "game/server/gameinterface.h" + +#include "util_server.h" + +//----------------------------------------------------------------------------- +// Purpose: returns the player instance by edict +//----------------------------------------------------------------------------- +CPlayer* UTIL_PlayerByIndex(int nIndex) +{ + if (nIndex < 1 || nIndex >(*g_pGlobals)->m_nMaxClients || nIndex == FL_EDICT_INVALID) + { + assert(0); + return nullptr; + } + + // !TODO: Improve this!!! + CPlayer* pPlayer = reinterpret_cast((*g_pGlobals)->m_pEdicts[nIndex + 0x7808]); + return pPlayer; +} diff --git a/r5dev/game/server/util_server.h b/r5dev/game/server/util_server.h new file mode 100644 index 00000000..14a60557 --- /dev/null +++ b/r5dev/game/server/util_server.h @@ -0,0 +1,12 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#ifndef UTIL_SERVER_H +#define UTIL_SERVER_H +#include "game/server/player.h" + +CPlayer* UTIL_PlayerByIndex(int nIndex); + +#endif // UTIL_SERVER_H diff --git a/r5dev/game/shared/util_shared.cpp b/r5dev/game/shared/util_shared.cpp index 5f2a0b66..d407caa8 100644 --- a/r5dev/game/shared/util_shared.cpp +++ b/r5dev/game/shared/util_shared.cpp @@ -5,28 +5,6 @@ //===========================================================================// #include "core/stdafx.h" #include "util_shared.h" -#ifndef CLIENT_DLL -#include "game/server/player.h" -#include "game/server/gameinterface.h" -#endif // !CLIENT_DLL - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: returns the player instance by edict -//----------------------------------------------------------------------------- -CPlayer* UTIL_PlayerByIndex(int nIndex) -{ - if (nIndex < 1 || nIndex >(*g_pGlobals)->m_nMaxClients || nIndex == FL_EDICT_INVALID) - { - assert(0); - return nullptr; - } - - // !TODO: Improve this!!! - CPlayer* pPlayer = reinterpret_cast((*g_pGlobals)->m_pEdicts[nIndex + 0x7808]); - return pPlayer; -} -#endif // CLIENT_DLL //----------------------------------------------------------------------------- // Purpose: returns the class name, script name, and edict of the entity diff --git a/r5dev/game/shared/util_shared.h b/r5dev/game/shared/util_shared.h index 1862a067..0b854aaf 100644 --- a/r5dev/game/shared/util_shared.h +++ b/r5dev/game/shared/util_shared.h @@ -5,16 +5,9 @@ //===========================================================================// #ifndef UTIL_SHARED_H #define UTIL_SHARED_H -#ifndef CLIENT_DLL -#include "game/server/player.h" -#endif #include "public/engine/IEngineTrace.h" class CTraceFilterSimple; - -#ifndef CLIENT_DLL -CPlayer* UTIL_PlayerByIndex(int nIndex); -#endif // CLIENT_DLL const char* UTIL_GetEntityScriptInfo(CBaseEntity* pEnt); inline CMemory p_UTIL_GetEntityScriptInfo; @@ -46,7 +39,6 @@ private: int m_traceType; }; - /////////////////////////////////////////////////////////////////////////////// class VUtil_Shared : public IDetour { From ad6466fa6c602e87218042fffed29972116d4c22 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:30:07 +0200 Subject: [PATCH 12/25] Add 'engine_cl' project to SDK and fix compiler errors The 'engine_cl' library defines 'CLIENT_DLL', which prunes server specific code. This is used for the 'client.dll' project. Also fixed a compile error in 'CClient::VActivatePlayer', as it used a server only cvar. Ideally, this entire file gets ifdef'd out for engine_cl, currently it doesn't matter as nothing gets compiled in. --- r5dev/core/CMakeLists.txt | 11 ++++------- r5dev/engine/CMakeLists.txt | 20 ++++++++++++-------- r5dev/engine/client/client.cpp | 25 +++++++++++++++++++++++++ r5dev/engine/client/client.h | 21 ++------------------- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index 9daa6bc3..af34a136 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -97,15 +97,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE "vgui" "rui" - "engine" "d3d11.lib" ) - -else() -target_link_libraries( ${PROJECT_NAME} PRIVATE - "materialsystem_nodx" # Needs the No-DirectX version for patching. - "engine_ds" -) endif() # Determine the compiler definitions and link libraries per project. @@ -113,6 +106,7 @@ if( ${PROJECT_NAME} STREQUAL "gamesdk" ) end_sources() target_link_libraries( ${PROJECT_NAME} PRIVATE + "engine" "server_static" "client_static" ) @@ -124,6 +118,8 @@ elseif( ${PROJECT_NAME} STREQUAL "dedicated" ) end_sources() target_link_libraries( ${PROJECT_NAME} PRIVATE + "materialsystem_nodx" # Needs the No-DirectX version for patching. + "engine_ds" "server_static" ) target_compile_definitions( ${PROJECT_NAME} PRIVATE @@ -136,6 +132,7 @@ elseif( ${PROJECT_NAME} STREQUAL "client" ) end_sources( "${BUILD_OUTPUT_DIR}/bin/x64_retail/" ) target_link_libraries( ${PROJECT_NAME} PRIVATE + "engine_cl" "client_static" ) target_compile_definitions( ${PROJECT_NAME} PRIVATE diff --git a/r5dev/engine/CMakeLists.txt b/r5dev/engine/CMakeLists.txt index 50b2be17..33c838ed 100644 --- a/r5dev/engine/CMakeLists.txt +++ b/r5dev/engine/CMakeLists.txt @@ -20,14 +20,12 @@ add_sources( SOURCE_GROUP "Collision" "traceinit.h" ) -if( ${PROJECT_NAME} STREQUAL "engine" ) +if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" ) add_sources( SOURCE_GROUP "Debug" "debugoverlay.cpp" "debugoverlay.h" ) -endif() -if( ${PROJECT_NAME} STREQUAL "engine" ) add_sources( SOURCE_GROUP "Render" "gl_matsysiface.h" "gl_model_private.h" @@ -89,7 +87,7 @@ add_sources( SOURCE_GROUP "System" "sdk_dll.h" ) -if( ${PROJECT_NAME} STREQUAL "engine" ) +if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" ) add_sources( SOURCE_GROUP "System" "sys_getmodes.cpp" "sys_getmodes.h" @@ -98,6 +96,7 @@ add_sources( SOURCE_GROUP "System" ) endif() +if( NOT ${PROJECT_NAME} STREQUAL "engine_cl" ) add_sources( SOURCE_GROUP "Server" "server/persistence.cpp" "server/persistence.h" @@ -112,6 +111,7 @@ add_sources( SOURCE_GROUP "Server" "server/datablock_sender.cpp" "server/datablock_sender.h" ) +endif() add_sources( SOURCE_GROUP "Client" "client/cdll_engine_int.cpp" @@ -129,7 +129,7 @@ add_sources( SOURCE_GROUP "Shared" "shared/shared_rcon.h" ) -if( ${PROJECT_NAME} STREQUAL "engine" ) +if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" ) add_sources( SOURCE_GROUP "Client" # Client only. "client/clientstate.cpp" "client/clientstate.h" @@ -144,9 +144,7 @@ add_sources( SOURCE_GROUP "Client" # Client only. "client/datablock_receiver.cpp" "client/datablock_receiver.h" ) -endif() -if( ${PROJECT_NAME} STREQUAL "engine" ) add_sources( SOURCE_GROUP "GameUI" "${ENGINE_SOURCE_DIR}/gameui/IBrowser.cpp" "${ENGINE_SOURCE_DIR}/gameui/IBrowser.h" @@ -218,7 +216,7 @@ add_sources( SOURCE_GROUP "Public" "${ENGINE_SOURCE_DIR}/public/gamebspfile.h" ) -if( ${PROJECT_NAME} STREQUAL "engine" ) +if( NOT ${PROJECT_NAME} STREQUAL "engine_ds" ) add_sources( SOURCE_GROUP "Public" "${ENGINE_SOURCE_DIR}/public/client_class.h" "${ENGINE_SOURCE_DIR}/public/ivrenderview.h" @@ -232,8 +230,14 @@ if( ${PROJECT_NAME} STREQUAL "engine_ds" ) target_compile_definitions( ${PROJECT_NAME} PRIVATE "DEDICATED" ) +elseif( ${PROJECT_NAME} STREQUAL "engine_cl" ) +target_compile_definitions( ${PROJECT_NAME} PRIVATE + "CLIENT_DLL" +) endif() + endmacro() add_engine_project( "engine" ) add_engine_project( "engine_ds" ) +add_engine_project( "engine_cl" ) diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp index 5b6cf072..c258a304 100644 --- a/r5dev/engine/client/client.cpp +++ b/r5dev/engine/client/client.cpp @@ -103,6 +103,7 @@ void CClient::VActivatePlayer(CClient* pClient) pClient->SetPersistenceState(PERSISTENCE::PERSISTENCE_READY); v_CClient_ActivatePlayer(pClient); +#ifndef CLIENT_DLL const CNetChan* pNetChan = pClient->GetNetChan(); if (pNetChan && sv_showconnecting->GetBool()) @@ -110,6 +111,7 @@ void CClient::VActivatePlayer(CClient* pClient) DevMsg(eDLL_T::SERVER, "Activated player #%d; channel %s(%s) ('%llu')\n", pClient->GetUserID(), pNetChan->GetName(), pNetChan->GetAddress(), pClient->GetNucleusID()); } +#endif // !CLIENT_DLL } //--------------------------------------------------------------------------------- @@ -216,3 +218,26 @@ bool CClient::VSendNetMsgEx(CClient* pClient, CNetMessage* pMsg, char bLocal, bo { return pClient->SendNetMsgEx(pMsg, bLocal, bForceReliable, bVoice); } + +void VClient::Attach(void) const +{ +#ifndef CLIENT_DLL + DetourAttach((LPVOID*)&v_CClient_Clear, &CClient::VClear); + DetourAttach((LPVOID*)&v_CClient_Connect, &CClient::VConnect); + DetourAttach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer); + DetourAttach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd); + DetourAttach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx); + //DetourAttach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot); +#endif // !CLIENT_DLL +} +void VClient::Detach(void) const +{ +#ifndef CLIENT_DLL + DetourDetach((LPVOID*)&v_CClient_Clear, &CClient::VClear); + DetourDetach((LPVOID*)&v_CClient_Connect, &CClient::VConnect); + DetourDetach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer); + DetourDetach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd); + DetourDetach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx); + //DetourDetach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot); +#endif // !CLIENT_DLL +} diff --git a/r5dev/engine/client/client.h b/r5dev/engine/client/client.h index bf36427d..21e12ebe 100644 --- a/r5dev/engine/client/client.h +++ b/r5dev/engine/client/client.h @@ -268,24 +268,7 @@ class VClient : public IDetour } virtual void GetVar(void) const { } virtual void GetCon(void) const { } - virtual void Attach(void) const - { - DetourAttach((LPVOID*)&v_CClient_Clear, &CClient::VClear); - DetourAttach((LPVOID*)&v_CClient_Connect, &CClient::VConnect); - DetourAttach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer); - DetourAttach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd); - DetourAttach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx); - //DetourAttach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot); - } - virtual void Detach(void) const - { - DetourDetach((LPVOID*)&v_CClient_Clear, &CClient::VClear); - DetourDetach((LPVOID*)&v_CClient_Connect, &CClient::VConnect); - DetourDetach((LPVOID*)&v_CClient_ActivatePlayer, &CClient::VActivatePlayer); - DetourDetach((LPVOID*)&v_CClient_ProcessStringCmd, &CClient::VProcessStringCmd); - DetourDetach((LPVOID*)&v_CClient_SendNetMsgEx, &CClient::VSendNetMsgEx); - //DetourDetach((LPVOID*)&p_CClient_SendSnapshot, &CClient::VSendSnapshot); - } + virtual void Attach(void) const; + virtual void Detach(void) const; }; /////////////////////////////////////////////////////////////////////////////// - From e67fcfd1fb378b2c67131ef56a61e71abf927f15 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:33:22 +0200 Subject: [PATCH 13/25] Remove static keyword Can't be isolated to translation unit if only std::thread's ctor references it, triggers a compiler warning (C4505) that is treated as an error. --- r5dev/engine/host_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index b33c96e2..f896730f 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -60,7 +60,7 @@ // Input : &netGameServer - // Output : Returns true on success, false otherwise. //----------------------------------------------------------------------------- -static bool HostState_KeepAlive(const NetGameServer_t& netGameServer) +bool HostState_KeepAlive(const NetGameServer_t& netGameServer) { if (!g_pServer->IsActive() || !sv_pylonVisibility->GetBool()) // Check for active game. { From f39de84d152dd0e2702b50a0669794f50f4572d6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:09:42 +0200 Subject: [PATCH 14/25] Create macro for scriptfunc definitions Create a macro to make registration easier, by reducing the parameters. --- r5dev/game/client/vscript_client.cpp | 30 ++++++++++++++-------------- r5dev/game/client/vscript_client.h | 7 ++++++- r5dev/game/server/vscript_server.cpp | 22 ++++++++++---------- r5dev/game/server/vscript_server.h | 5 +++++ r5dev/game/shared/vscript_shared.cpp | 15 +++++++++++--- r5dev/game/shared/vscript_shared.h | 11 ++++++++++ 6 files changed, 60 insertions(+), 30 deletions(-) diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index c7ce1955..8c76136b 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -27,7 +27,7 @@ namespace VScriptCode //----------------------------------------------------------------------------- // Purpose: refreshes the server list //----------------------------------------------------------------------------- - SQRESULT RefreshServerCount(HSQUIRRELVM v) + SQRESULT RefreshServerList(HSQUIRRELVM v) { string serverMessage; // Refresh list. size_t iCount = g_pServerListManager->RefreshServerList(serverMessage); @@ -389,27 +389,27 @@ void Script_RegisterUIFunctions(CSquirrelVM* s) Script_RegisterCommonAbstractions(s); Script_RegisterCoreClientFunctions(s); - s->RegisterFunction("RefreshServerList", "Script_RefreshServerList", "Refreshes the public server list and returns the count", "int", "", &VScriptCode::Client::RefreshServerCount); - s->RegisterFunction("GetServerCount", "Script_GetServerCount", "Gets the number of public servers", "int", "", &VScriptCode::Client::GetServerCount); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, RefreshServerList, "Refreshes the public server list and returns the count", "int", ""); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerCount, "Gets the number of public servers", "int", ""); // Functions for retrieving server browser data - s->RegisterFunction("GetHiddenServerName", "Script_GetHiddenServerName", "Gets hidden server name by token", "string", "string", &VScriptCode::Client::GetHiddenServerName); - s->RegisterFunction("GetServerName", "Script_GetServerName", "Gets the name of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerName); - s->RegisterFunction("GetServerDescription", "Script_GetServerDescription", "Gets the description of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerDescription); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetHiddenServerName, "Gets hidden server name by token", "string", "string"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerName, "Gets the name of the server at the specified index of the server list", "string", "int"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerDescription, "Gets the description of the server at the specified index of the server list", "string", "int"); - s->RegisterFunction("GetServerMap", "Script_GetServerMap", "Gets the map of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerMap); - s->RegisterFunction("GetServerPlaylist", "Script_GetServerPlaylist", "Gets the playlist of the server at the specified index of the server list", "string", "int", &VScriptCode::Client::GetServerPlaylist); - s->RegisterFunction("GetServerCurrentPlayers", "Script_GetServerCurrentPlayers", "Gets the current player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Client::GetServerCurrentPlayers); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerMap, "Gets the map of the server at the specified index of the server list", "string", "int"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerPlaylist, "Gets the playlist of the server at the specified index of the server list", "string", "int"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerCurrentPlayers, "Gets the current player count of the server at the specified index of the server list", "int", "int"); - s->RegisterFunction("GetServerMaxPlayers", "Script_GetServerMaxPlayers", "Gets the max player count of the server at the specified index of the server list", "int", "int", &VScriptCode::Client::GetServerMaxPlayers); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetServerMaxPlayers, "Gets the max player count of the server at the specified index of the server list", "int", "int"); // Misc main menu functions - s->RegisterFunction("GetPromoData", "Script_GetPromoData", "Gets promo data for specified slot type", "string", "int", &VScriptCode::Client::GetPromoData); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, GetPromoData, "Gets promo data for specified slot type", "string", "int"); // Functions for connecting to servers - s->RegisterFunction("ConnectToServer", "Script_ConnectToServer", "Joins server by ip address and encryption key", "void", "string, string", &VScriptCode::Client::ConnectToServer); - s->RegisterFunction("ConnectToListedServer", "Script_ConnectToListedServer", "Joins listed server by index", "void", "int", &VScriptCode::Client::ConnectToListedServer); - s->RegisterFunction("ConnectToHiddenServer", "Script_ConnectToHiddenServer", "Joins hidden server by token", "void", "string", &VScriptCode::Client::ConnectToHiddenServer); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToServer, "Joins server by ip address and encryption key", "void", "string, string"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToListedServer, "Joins listed server by index", "void", "int"); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, ConnectToHiddenServer, "Joins hidden server by token", "void", "string"); } //--------------------------------------------------------------------------------- @@ -418,5 +418,5 @@ void Script_RegisterUIFunctions(CSquirrelVM* s) //--------------------------------------------------------------------------------- void Script_RegisterCoreClientFunctions(CSquirrelVM* s) { - s->RegisterFunction("IsClientDLL", "Script_IsClientDLL", "Returns whether this build is client only", "bool", "", &VScriptCode::Client::IsClientDLL); + DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", ""); } diff --git a/r5dev/game/client/vscript_client.h b/r5dev/game/client/vscript_client.h index 4009126e..a2066ba4 100644 --- a/r5dev/game/client/vscript_client.h +++ b/r5dev/game/client/vscript_client.h @@ -5,7 +5,7 @@ namespace VScriptCode { namespace Client { - SQRESULT RefreshServerCount(HSQUIRRELVM v); + SQRESULT RefreshServerList(HSQUIRRELVM v); SQRESULT GetServerCount(HSQUIRRELVM v); SQRESULT GetHiddenServerName(HSQUIRRELVM v); @@ -32,4 +32,9 @@ void Script_RegisterClientFunctions(CSquirrelVM* s); void Script_RegisterUIFunctions(CSquirrelVM* s); void Script_RegisterCoreClientFunctions(CSquirrelVM* s); +#define DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, functionName, helpString, \ + returnType, parameters) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ + helpString, returnType, parameters, VScriptCode::Client::##functionName); \ + #endif // VSCRIPT_CLIENT_H diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 219133fe..0b390dc9 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -206,11 +206,11 @@ void Script_RegisterServerFunctions(CSquirrelVM* s) //--------------------------------------------------------------------------------- void Script_RegisterCoreServerFunctions(CSquirrelVM* s) { - s->RegisterFunction("IsServerActive", "Script_IsServerActive", "Returns whether the server is active", "bool", "", &VScriptCode::Server::IsServerActive); - s->RegisterFunction("IsDedicated", "Script_IsDedicated", "Returns whether this is a dedicated server", "bool", "", &VScriptCode::Server::IsDedicated); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsServerActive, "Returns whether the server is active", "bool", ""); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsDedicated, "Returns whether this is a dedicated server", "bool", ""); - s->RegisterFunction("CreateServer", "Script_CreateServer", "Starts server with the specified settings", "void", "string, string, string, string, int", &VScriptCode::Server::CreateServer); - s->RegisterFunction("DestroyServer", "Script_DestroyServer", "Shuts the local host game down", "void", "", &VScriptCode::Server::DestroyServer); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, CreateServer, "Starts server with the specified settings", "void", "string, string, string, string, int"); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local host game down", "void", ""); } //--------------------------------------------------------------------------------- @@ -219,14 +219,14 @@ void Script_RegisterCoreServerFunctions(CSquirrelVM* s) //--------------------------------------------------------------------------------- void Script_RegisterAdminPanelFunctions(CSquirrelVM* s) { - s->RegisterFunction("GetNumHumanPlayers", "Script_GetNumHumanPlayers", "Gets the number of human players on the server", "int", "", &VScriptCode::Server::GetNumHumanPlayers); - s->RegisterFunction("GetNumFakeClients", "Script_GetNumFakeClients", "Gets the number of bot players on the server", "int", "", &VScriptCode::Server::GetNumFakeClients); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumHumanPlayers, "Gets the number of human players on the server", "int", ""); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, GetNumFakeClients, "Gets the number of bot players on the server", "int", ""); - s->RegisterFunction("KickPlayerByName", "Script_KickPlayerByName", "Kicks a player from the server by name", "void", "string", &VScriptCode::Server::KickPlayerByName); - s->RegisterFunction("KickPlayerById", "Script_KickPlayerById", "Kicks a player from the server by handle or nucleus id", "void", "string", &VScriptCode::Server::KickPlayerById); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, KickPlayerByName, "Kicks a player from the server by name", "void", "string"); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, KickPlayerById, "Kicks a player from the server by handle or nucleus id", "void", "string"); - s->RegisterFunction("BanPlayerByName", "Script_BanPlayerByName", "Bans a player from the server by name", "void", "string", &VScriptCode::Server::BanPlayerByName); - s->RegisterFunction("BanPlayerById", "Script_BanPlayerById", "Bans a player from the server by handle or nucleus id", "void", "string", &VScriptCode::Server::BanPlayerById); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, BanPlayerByName, "Bans a player from the server by name", "void", "string"); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, BanPlayerById, "Bans a player from the server by handle or nucleus id", "void", "string"); - s->RegisterFunction("UnbanPlayer", "Script_UnbanPlayer", "Unbans a player from the server by nucleus id or ip address", "void", "string", &VScriptCode::Server::UnbanPlayer); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, UnbanPlayer, "Unbans a player from the server by nucleus id or ip address", "void", "string"); } diff --git a/r5dev/game/server/vscript_server.h b/r5dev/game/server/vscript_server.h index ed82598d..fc22dc32 100644 --- a/r5dev/game/server/vscript_server.h +++ b/r5dev/game/server/vscript_server.h @@ -26,4 +26,9 @@ void Script_RegisterServerFunctions(CSquirrelVM* s); void Script_RegisterCoreServerFunctions(CSquirrelVM* s); void Script_RegisterAdminPanelFunctions(CSquirrelVM* s); +#define DEFINE_SERVER_SCRIPTFUNC_NAMED(s, functionName, helpString, \ + returnType, parameters) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ + helpString, returnType, parameters, VScriptCode::Server::##functionName); \ + #endif // VSCRIPT_SERVER_H diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 25c9b167..5c639d04 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -26,6 +26,15 @@ namespace VScriptCode { namespace Shared { + //----------------------------------------------------------------------------- + // Purpose: generic stub for unsupported functions + //----------------------------------------------------------------------------- + SQRESULT StubUnsupported(HSQUIRRELVM v) + { + v_SQVM_RaiseError(v, "This function is not supported on this builds.\n"); + return SQ_ERROR; + } + //----------------------------------------------------------------------------- // Purpose: expose SDK version to the VScript API //----------------------------------------------------------------------------- @@ -83,8 +92,8 @@ namespace VScriptCode //--------------------------------------------------------------------------------- void Script_RegisterCommonAbstractions(CSquirrelVM* s) { - s->RegisterFunction("GetSDKVersion", "Script_GetSDKVersion", "Gets the SDK version as a string", "string", "", &VScriptCode::Shared::GetSDKVersion); + DEFINE_SHARED_SCRIPTFUNC_NAMED(s, GetSDKVersion, "Gets the SDK version as a string", "string", ""); - s->RegisterFunction("GetAvailableMaps", "Script_GetAvailableMaps", "Gets an array of all available maps", "array< string >", "", &VScriptCode::Shared::GetAvailableMaps); - s->RegisterFunction("GetAvailablePlaylists", "Script_GetAvailablePlaylists", "Gets an array of all available playlists", "array< string >", "", &VScriptCode::Shared::GetAvailablePlaylists); + DEFINE_SHARED_SCRIPTFUNC_NAMED(s, GetAvailableMaps, "Gets an array of all available maps", "array< string >", ""); + DEFINE_SHARED_SCRIPTFUNC_NAMED(s, GetAvailablePlaylists, "Gets an array of all available playlists", "array< string >", ""); } diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index fd579a22..a15eea0b 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -16,6 +16,7 @@ namespace VScriptCode { namespace Shared { + SQRESULT StubUnsupported(HSQUIRRELVM v); SQRESULT GetSDKVersion(HSQUIRRELVM v); SQRESULT GetAvailableMaps(HSQUIRRELVM v); SQRESULT GetAvailablePlaylists(HSQUIRRELVM v); @@ -24,6 +25,16 @@ namespace VScriptCode void Script_RegisterCommonAbstractions(CSquirrelVM* s); +#define DEFINE_SCRIPTFUNC_STUBBED(s, functionName, returnType) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ + "Stub function; not supported on this build.", #returnType, "", \ + &VScriptCode::Shared::StubUnsupported); \ + +#define DEFINE_SHARED_SCRIPTFUNC_NAMED(s, functionName, helpString, \ + returnType, parameters) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ + helpString, returnType, parameters, VScriptCode::Shared::##functionName);\ + /////////////////////////////////////////////////////////////////////////////// class VScriptShared : public IDetour { From d860c43f79c3e1eabe59275e0a03512bc1b0c207 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 12:25:43 +0200 Subject: [PATCH 15/25] Deduplicate code Small deduplication. --- r5dev/game/client/vscript_client.cpp | 51 +++++++++++++--------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index 8c76136b..507b4523 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -20,6 +20,22 @@ #include "vscript_client.h" +//----------------------------------------------------------------------------- +// Purpose: checks if the server index is valid, raises an error if not +//----------------------------------------------------------------------------- +static SQBool Script_CheckServerIndex(HSQUIRRELVM v, SQInteger iServer) +{ + SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); + + if (iServer >= iCount) + { + v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); + return false; + } + + return true; +} + namespace VScriptCode { namespace Client @@ -105,13 +121,10 @@ namespace VScriptCode SQRESULT GetServerName(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -127,13 +140,10 @@ namespace VScriptCode SQRESULT GetServerDescription(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -149,13 +159,10 @@ namespace VScriptCode SQRESULT GetServerMap(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -171,13 +178,10 @@ namespace VScriptCode SQRESULT GetServerPlaylist(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -193,13 +197,10 @@ namespace VScriptCode SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -215,13 +216,10 @@ namespace VScriptCode SQRESULT GetServerMaxPlayers(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } @@ -315,13 +313,10 @@ namespace VScriptCode SQRESULT ConnectToListedServer(HSQUIRRELVM v) { std::lock_guard l(g_pServerListManager->m_Mutex); - SQInteger iServer = sq_getinteger(v, 1); - SQInteger iCount = static_cast(g_pServerListManager->m_vServerList.size()); - if (iServer >= iCount) + if (!Script_CheckServerIndex(v, iServer)) { - v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount); return SQ_ERROR; } From a2d30e45f9f33e0ee746e657152f123d1f2a0c45 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:53:20 +0200 Subject: [PATCH 16/25] Add asserts to detours This is to make it easy to catch detour errors. --- r5dev/thirdparty/detours/include/detours.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/r5dev/thirdparty/detours/include/detours.h b/r5dev/thirdparty/detours/include/detours.h index 4b9e2328..2f12f73c 100644 --- a/r5dev/thirdparty/detours/include/detours.h +++ b/r5dev/thirdparty/detours/include/detours.h @@ -882,9 +882,12 @@ template< LONG DetourAttach(_Inout_ T *ppPointer, _In_ T pDetour) noexcept { - return DetourAttach( + LONG result = DetourAttach( reinterpret_cast(ppPointer), reinterpret_cast(pDetour)); + + assert(result == NO_ERROR); + return result; } template< @@ -896,12 +899,15 @@ LONG DetourAttachEx(_Inout_ T *ppPointer, _Out_opt_ T *ppRealTarget, _Out_opt_ T *ppRealDetour) noexcept { - return DetourAttachEx( + LONG result = DetourAttachEx( reinterpret_cast(ppPointer), reinterpret_cast(pDetour), ppRealTrampoline, reinterpret_cast(ppRealTarget), reinterpret_cast(ppRealDetour)); + + assert(result == NO_ERROR); + return result; } template< @@ -910,9 +916,12 @@ template< LONG DetourDetach(_Inout_ T *ppPointer, _In_ T pDetour) noexcept { - return DetourDetach( + LONG result = DetourDetach( reinterpret_cast(ppPointer), reinterpret_cast(pDetour)); + + assert(result == NO_ERROR); + return result; } #endif // __cplusplus >= 201103L || _MSVC_LANG >= 201103L From ddfaea6ce28829860ac355999b37c9d08b72c3ff Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:00:36 +0200 Subject: [PATCH 17/25] Fix client.dll loading * Moved dedicated server command line parameter init to 'init.cpp'. * Registered 'SV_Main' on the client, this is engine code (lower level 'local' server wrappers). * Disabled registration of Weapon_Bolt, although this is shared game code, this particular file is only used for the SERVER at this moment. * Added the '-noserverdll' command lien parameter to instruct our loader.dll to load the client.dll instead. * Adjusted the loader and sdklauncher project to support the loading of client.dll. --- r5dev/core/CMakeLists.txt | 18 ++++++-- r5dev/core/init.cpp | 26 +++++++++--- r5dev/engine/CMakeLists.txt | 4 +- r5dev/engine/server/sv_main.cpp | 17 -------- r5dev/engine/server/sv_main.h | 23 +++++++++- r5dev/launcher/launcher.cpp | 25 ----------- r5dev/launcher/launcher.h | 1 - r5dev/loader/loader.cpp | 75 +++++++++++++++++++++------------ r5dev/sdklauncher/basepanel.cpp | 4 +- 9 files changed, 107 insertions(+), 86 deletions(-) diff --git a/r5dev/core/CMakeLists.txt b/r5dev/core/CMakeLists.txt index af34a136..75fec9ab 100644 --- a/r5dev/core/CMakeLists.txt +++ b/r5dev/core/CMakeLists.txt @@ -159,18 +159,28 @@ add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -P ${ENGINE_SOURCE_DIR}/cmake/PostBuild.cmake ) -if( NOT ${PROJECT_NAME} STREQUAL "dedicated" ) +if( ${PROJECT_NAME} STREQUAL "dedicated" ) set_target_properties( ${PROJECT_NAME} PROPERTIES - VS_DEBUGGER_COMMAND "r5apex.exe" + VS_DEBUGGER_COMMAND "r5apex_ds.exe" ) else() set_target_properties( ${PROJECT_NAME} PROPERTIES - VS_DEBUGGER_COMMAND "r5apex_ds.exe" + VS_DEBUGGER_COMMAND "r5apex.exe" +) +endif() + +if( ${PROJECT_NAME} STREQUAL "client" ) +set_target_properties( ${PROJECT_NAME} PROPERTIES + VS_DEBUGGER_COMMAND_ARGUMENTS "-wconsole -ansicolor -dev -devsdk -noserverdll" +) +else() +set_target_properties( ${PROJECT_NAME} PROPERTIES + VS_DEBUGGER_COMMAND_ARGUMENTS "-wconsole -ansicolor -dev -devsdk" + VS_DEBUGGER_WORKING_DIRECTORY "$(ProjectDir)../../../${BUILD_OUTPUT_DIR}/" ) endif() set_target_properties( ${PROJECT_NAME} PROPERTIES - VS_DEBUGGER_COMMAND_ARGUMENTS "-wconsole -ansicolor -dev -devsdk" VS_DEBUGGER_WORKING_DIRECTORY "$(ProjectDir)../../../${BUILD_OUTPUT_DIR}/" ) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 9fe4a11c..1529e28a 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -196,6 +196,23 @@ void Systems_Init() ConVar_StaticInit(); +#ifdef DEDICATED + // These command line parameters disable a bunch of things in the engine that + // the dedicated server does not need, therefore, reducing a lot of overhead. + CommandLine()->AppendParm("-collate", ""); + CommandLine()->AppendParm("-multiple", ""); + CommandLine()->AppendParm("-noorigin", ""); + CommandLine()->AppendParm("-nodiscord", ""); + CommandLine()->AppendParm("-noshaderapi", ""); + CommandLine()->AppendParm("-nobakedparticles", ""); + CommandLine()->AppendParm("-novid", ""); + CommandLine()->AppendParm("-nomenuvid", ""); + CommandLine()->AppendParm("-nosound", ""); + CommandLine()->AppendParm("-nomouse", ""); + CommandLine()->AppendParm("-nojoy", ""); + CommandLine()->AppendParm("-nosendtable", ""); +#endif // DEDICATED + // Script context registration callbacks. #ifndef CLIENT_DLL ServerScriptRegister_Callback = Script_RegisterServerFunctions; @@ -537,11 +554,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VGL_Screen); #endif // !DEDICATED -#ifndef CLIENT_DLL - // !!! SERVER DLL ONLY !!! REGISTER(HSV_Main); - // !!! END SERVER DLL ONLY !!! -#endif // !CLIENT_DLL #ifndef DEDICATED REGISTER(VGame); // REGISTER CLIENT ONLY! @@ -565,10 +578,11 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VAnimation); REGISTER(VUtil_Shared); - REGISTER(V_Weapon_Bolt); - #ifndef CLIENT_DLL + // In shared code, but weapon bolt is SERVER only. + REGISTER(V_Weapon_Bolt); + // Game/server REGISTER(VAI_Network); REGISTER(VAI_NetworkManager); diff --git a/r5dev/engine/CMakeLists.txt b/r5dev/engine/CMakeLists.txt index 33c838ed..3fc1bd82 100644 --- a/r5dev/engine/CMakeLists.txt +++ b/r5dev/engine/CMakeLists.txt @@ -102,10 +102,10 @@ add_sources( SOURCE_GROUP "Server" "server/persistence.h" "server/server.cpp" "server/server.h" - "server/sv_main.cpp" - "server/sv_main.h" "server/sv_rcon.cpp" "server/sv_rcon.h" + "server/sv_main.cpp" + "server/sv_main.h" "server/vengineserver_impl.cpp" "server/vengineserver_impl.h" "server/datablock_sender.cpp" diff --git a/r5dev/engine/server/sv_main.cpp b/r5dev/engine/server/sv_main.cpp index 36e0249f..5dcce362 100644 --- a/r5dev/engine/server/sv_main.cpp +++ b/r5dev/engine/server/sv_main.cpp @@ -192,20 +192,3 @@ void SV_BroadcastVoiceData(CClient* cl, int nBytes, char* data) pClient->SendNetMsgEx(&voiceData, false, false, true); } } - -/////////////////////////////////////////////////////////////////////////////// -void HSV_Main::Attach(void) const -{ - //DetourAttach(&v_SV_InitGameDLL, SV_InitGameDLL); - //DetourAttach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL); - //DetourAttach(&v_SV_ActivateServer, SV_ActivateServer); - DetourAttach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData); -} - -void HSV_Main::Detach(void) const -{ - //DetourDetach(&v_SV_InitGameDLL, SV_InitGameDLL); - //DetourDetach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL); - //DetourDetach(&v_SV_ActivateServer, SV_ActivateServer); - DetourDetach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData); -} diff --git a/r5dev/engine/server/sv_main.h b/r5dev/engine/server/sv_main.h index 087a6af7..12cf7f4a 100644 --- a/r5dev/engine/server/sv_main.h +++ b/r5dev/engine/server/sv_main.h @@ -39,6 +39,7 @@ inline bool IsDedicated() void SV_InitGameDLL(); void SV_ShutdownGameDLL(); bool SV_ActivateServer(); +void SV_BroadcastVoiceData(CClient* cl, int nBytes, char* data); void SV_IsClientBanned(CClient* pClient, const string& svIPAddr, const uint64_t nNucleusID, const string& svPersonaName, const int nPort); void SV_CheckForBan(const BannedVec_t* pBannedVec = nullptr); /////////////////////////////////////////////////////////////////////////////// @@ -83,7 +84,25 @@ class HSV_Main : public IDetour .FindPatternSelf("40 38 3D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); } virtual void GetCon(void) const { } - virtual void Attach(void) const; - virtual void Detach(void) const; + /////////////////////////////////////////////////////////////////////////////// + virtual void Attach(void) const + { + //DetourAttach(&v_SV_InitGameDLL, SV_InitGameDLL); + //DetourAttach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL); + //DetourAttach(&v_SV_ActivateServer, SV_ActivateServer); +#ifndef CLIENT_DLL + DetourAttach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData); +#endif // !CLIENT_DLL + } + + virtual void Detach(void) const + { + //DetourDetach(&v_SV_InitGameDLL, SV_InitGameDLL); + //DetourDetach(&v_SV_ShutdownGameDLL, SV_ShutdownGameDLL); + //DetourDetach(&v_SV_ActivateServer, SV_ActivateServer); +#ifndef CLIENT_DLL + DetourDetach(&v_SV_BroadcastVoiceData, SV_BroadcastVoiceData); +#endif // !CLIENT_DLL + } }; /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/launcher/launcher.cpp b/r5dev/launcher/launcher.cpp index 0cec2d8b..0aa38bfc 100644 --- a/r5dev/launcher/launcher.cpp +++ b/r5dev/launcher/launcher.cpp @@ -32,8 +32,6 @@ int LauncherMain(HINSTANCE hInstance) // its own -game parameter, which would supersede the one we really want if we didn't intercede here. void RemoveSpuriousGameParameters() { - AppendSDKParametersPreInit(); - // Find the last -game parameter. int nGameArgs = 0; char lastGameArg[MAX_PATH]; @@ -56,29 +54,6 @@ void RemoveSpuriousGameParameters() } #endif -// Append required command line parameters. -// This avoids having all these in the startup configuration files -// as all there are required to run the game with the game sdk. -void AppendSDKParametersPreInit() -{ - const bool bDedicated = IsDedicated(); - if (bDedicated) - { - CommandLine()->AppendParm("-collate", ""); - CommandLine()->AppendParm("-multiple", ""); - CommandLine()->AppendParm("-noorigin", ""); - CommandLine()->AppendParm("-nodiscord", ""); - CommandLine()->AppendParm("-noshaderapi", ""); - CommandLine()->AppendParm("-nobakedparticles", ""); - CommandLine()->AppendParm("-novid", ""); - CommandLine()->AppendParm("-nomenuvid", ""); - CommandLine()->AppendParm("-nosound", ""); - CommandLine()->AppendParm("-nomouse", ""); - CommandLine()->AppendParm("-nojoy", ""); - CommandLine()->AppendParm("-nosendtable", ""); - } -} - const char* ExitCodeToString(int nCode) { switch (nCode) diff --git a/r5dev/launcher/launcher.h b/r5dev/launcher/launcher.h index bb927e42..5037b532 100644 --- a/r5dev/launcher/launcher.h +++ b/r5dev/launcher/launcher.h @@ -12,7 +12,6 @@ inline CMemory p_RemoveSpuriousGameParameters; inline void*(*v_RemoveSpuriousGameParameters)(void); #endif // !GAMEDLL_S0 || !GAMEDLL_S1 -void AppendSDKParametersPreInit(); const char* ExitCodeToString(int nCode); /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/loader/loader.cpp b/r5dev/loader/loader.cpp index cabbf008..05e903cc 100644 --- a/r5dev/loader/loader.cpp +++ b/r5dev/loader/loader.cpp @@ -47,7 +47,7 @@ static int (*v_WinMain)(HINSTANCE, HINSTANCE, LPSTR, int) = nullptr; //----------------------------------------------------------------------------- // Purpose: Terminates the process with an error when called //----------------------------------------------------------------------------- -void FatalError(const char* fmt, ...) +static void FatalError(const char* fmt, ...) { va_list vArgs; va_start(vArgs, fmt); @@ -65,7 +65,7 @@ void FatalError(const char* fmt, ...) //----------------------------------------------------------------------------- // Purpose: Loads the SDK module //----------------------------------------------------------------------------- -void InitGameSDK(const LPSTR lpCmdLine) +static void InitGameSDK(const LPSTR lpCmdLine) { if (V_strstr(lpCmdLine, "-noworkerdll")) return; @@ -78,13 +78,22 @@ void InitGameSDK(const LPSTR lpCmdLine) // Prune the path. const char* pModuleName = strrchr(moduleName, '\\') + 1; + const bool bDedicated = V_stricmp(pModuleName, SERVER_GAME_DLL) == NULL; // The dedicated server has its own SDK module, // so we need to check whether we are running // the base game or the dedicated server. - if (V_stricmp(pModuleName, MAIN_GAME_DLL) == NULL) - s_SdkModule = LoadLibraryA(MAIN_WORKER_DLL); - else if (V_stricmp(pModuleName, SERVER_GAME_DLL) == NULL) + if (!bDedicated) + { + // Load the client dll if '-noserverdll' is passed, + // as this command lime parameter prevents the + // server dll from initializing in the engine. + if (V_strstr(lpCmdLine, "-noserverdll")) + s_SdkModule = LoadLibraryA(CLIENT_WORKER_DLL); + else + s_SdkModule = LoadLibraryA(MAIN_WORKER_DLL); + } + else s_SdkModule = LoadLibraryA(SERVER_WORKER_DLL); if (!s_SdkModule) @@ -103,6 +112,38 @@ int WINAPI hWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin return v_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd); } +//----------------------------------------------------------------------------- +// Purpose: hooks the entry point +//----------------------------------------------------------------------------- +static void AttachEP() +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DetourAttach(&v_WinMain, &hWinMain); + + HRESULT hr = DetourTransactionCommit(); + if (hr != NO_ERROR) // Failed to hook into the process, terminate... + { + Assert(0); + FatalError("Failed to detour process: error code = %08x\n", hr); + } +} + +//----------------------------------------------------------------------------- +// Purpose: unhooks the entry point +//----------------------------------------------------------------------------- +static void DetachEP() +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DetourDetach(&v_WinMain, &hWinMain); + + HRESULT hr = DetourTransactionCommit(); + Assert(hr != NO_ERROR); +} + //----------------------------------------------------------------------------- // Purpose: APIENTRY //----------------------------------------------------------------------------- @@ -120,36 +161,16 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) v_WinMain = CModule::GetExportedSymbol((QWORD)s_DosHeader, "WinMain") .RCast(); - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - DetourAttach(&v_WinMain, &hWinMain); - - HRESULT hr = DetourTransactionCommit(); - if (hr != NO_ERROR) // Failed to hook into the process, terminate... - { - Assert(0); - FatalError("Failed to detour process: error code = %08x\n", hr); - } - + AttachEP(); break; } case DLL_PROCESS_DETACH: { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - DetourDetach(&v_WinMain, &hWinMain); - - HRESULT hr = DetourTransactionCommit(); - - Assert(hr != NO_ERROR); - NOTE_UNUSED(hr); - if (s_SdkModule) FreeLibrary(s_SdkModule); + DetachEP(); break; } } diff --git a/r5dev/sdklauncher/basepanel.cpp b/r5dev/sdklauncher/basepanel.cpp index ba0fd082..5d8fd4f0 100644 --- a/r5dev/sdklauncher/basepanel.cpp +++ b/r5dev/sdklauncher/basepanel.cpp @@ -1187,8 +1187,8 @@ eLaunchMode CSurface::BuildParameter(string& svParameters) } case eMode::CLIENT: { - AppendParameterInternal(svParameters, "-noworkerdll"); // This prevents init of worker dll - //(this dll is always imported, but we want client.dll to do the work instead). + // Tells the loader module to only load the client dll. + AppendParameterInternal(svParameters, "-noserverdll"); // GAME ############################################################### if (this->m_DeveloperToggle->Checked()) From cb4a0374331dd635228be9718594cbb80ccd5a37 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:17:49 +0200 Subject: [PATCH 18/25] Fix typo --- r5dev/game/shared/vscript_shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 5c639d04..1cb43ac3 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -31,7 +31,7 @@ namespace VScriptCode //----------------------------------------------------------------------------- SQRESULT StubUnsupported(HSQUIRRELVM v) { - v_SQVM_RaiseError(v, "This function is not supported on this builds.\n"); + v_SQVM_RaiseError(v, "This function is not supported on this build\n"); return SQ_ERROR; } From 904352498c7809b7675bbc5d1a27487fa5bd073a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:18:04 +0200 Subject: [PATCH 19/25] Fix missing 'arguments' parameter to stub macro --- r5dev/game/shared/vscript_shared.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index a15eea0b..0591f348 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -25,14 +25,14 @@ namespace VScriptCode void Script_RegisterCommonAbstractions(CSquirrelVM* s); -#define DEFINE_SCRIPTFUNC_STUBBED(s, functionName, returnType) \ - s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ - "Stub function; not supported on this build.", #returnType, "", \ - &VScriptCode::Shared::StubUnsupported); \ +#define DEFINE_SCRIPTFUNC_STUBBED(s, functionName, returnType, parameters) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ + "Stub function; not supported on this build.", #returnType, parameters, \ + &VScriptCode::Shared::StubUnsupported); \ -#define DEFINE_SHARED_SCRIPTFUNC_NAMED(s, functionName, helpString, \ - returnType, parameters) \ - s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ +#define DEFINE_SHARED_SCRIPTFUNC_NAMED(s, functionName, helpString, \ + returnType, parameters) \ + s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ helpString, returnType, parameters, VScriptCode::Shared::##functionName);\ /////////////////////////////////////////////////////////////////////////////// From ee1fdca7a9ad1c37ba57aaec13e16f5462a593bf Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:19:34 +0200 Subject: [PATCH 20/25] Register admin panel/core server scriptfunc stubs for client.dll Stubbed to avoid compile errors. --- r5dev/core/init.cpp | 5 ++++- r5dev/game/client/vscript_client.cpp | 31 ++++++++++++++++++++++++++++ r5dev/game/client/vscript_client.h | 3 +++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 1529e28a..fbaa3b30 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -218,7 +218,10 @@ void Systems_Init() ServerScriptRegister_Callback = Script_RegisterServerFunctions; CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions; AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions; -#endif // !CLIENT_DLL +#else + CoreServerScriptRegister_Callback = Script_RegisterCoreServerStubs; + AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelStubs; +#endif// !CLIENT_DLL #ifndef SERVER_DLL ClientScriptRegister_Callback = Script_RegisterClientFunctions; diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index 507b4523..c865cb07 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -415,3 +415,34 @@ void Script_RegisterCoreClientFunctions(CSquirrelVM* s) { DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", ""); } + +//--------------------------------------------------------------------------------- +// Purpose: core server script stubs (stubbed to prevent script compile errors!!!) +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterCoreServerStubs(CSquirrelVM* s) +{ + DEFINE_SCRIPTFUNC_STUBBED(s, IsServerActive, "bool", ""); + DEFINE_SCRIPTFUNC_STUBBED(s, IsDedicated, "bool", ""); + + DEFINE_SCRIPTFUNC_STUBBED(s, CreateServer, "void", "string, string, string, string, int"); + DEFINE_SCRIPTFUNC_STUBBED(s, DestroyServer, "void", ""); +} + +//--------------------------------------------------------------------------------- +// Purpose: admin panel script stubs (stubbed to prevent script compile errors!!!) +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterAdminPanelStubs(CSquirrelVM* s) +{ + DEFINE_SCRIPTFUNC_STUBBED(s, GetNumHumanPlayers, "int", ""); + DEFINE_SCRIPTFUNC_STUBBED(s, GetNumFakeClients, "int", ""); + + DEFINE_SCRIPTFUNC_STUBBED(s, KickPlayerByName, "void", "string"); + DEFINE_SCRIPTFUNC_STUBBED(s, KickPlayerById, "void", "string"); + + DEFINE_SCRIPTFUNC_STUBBED(s, BanPlayerByName, "void", "string"); + DEFINE_SCRIPTFUNC_STUBBED(s, BanPlayerById, "void", "string"); + + DEFINE_SCRIPTFUNC_STUBBED(s, UnbanPlayer, "void", "string"); +} diff --git a/r5dev/game/client/vscript_client.h b/r5dev/game/client/vscript_client.h index a2066ba4..89f054e3 100644 --- a/r5dev/game/client/vscript_client.h +++ b/r5dev/game/client/vscript_client.h @@ -32,6 +32,9 @@ void Script_RegisterClientFunctions(CSquirrelVM* s); void Script_RegisterUIFunctions(CSquirrelVM* s); void Script_RegisterCoreClientFunctions(CSquirrelVM* s); +void Script_RegisterCoreServerStubs(CSquirrelVM* s); +void Script_RegisterAdminPanelStubs(CSquirrelVM* s); + #define DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, functionName, helpString, \ returnType, parameters) \ s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ From 193abdc18a091986003301673b900a0526c3ee6e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 17:17:38 +0200 Subject: [PATCH 21/25] Remove scriptfunc stubs Not really ideal, needs a different solution. --- r5dev/core/init.cpp | 3 --- r5dev/game/client/vscript_client.cpp | 31 ---------------------------- r5dev/game/client/vscript_client.h | 3 --- r5dev/game/shared/vscript_shared.cpp | 9 -------- r5dev/game/shared/vscript_shared.h | 6 ------ 5 files changed, 52 deletions(-) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index fbaa3b30..9c7448e1 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -218,9 +218,6 @@ void Systems_Init() ServerScriptRegister_Callback = Script_RegisterServerFunctions; CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions; AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions; -#else - CoreServerScriptRegister_Callback = Script_RegisterCoreServerStubs; - AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelStubs; #endif// !CLIENT_DLL #ifndef SERVER_DLL diff --git a/r5dev/game/client/vscript_client.cpp b/r5dev/game/client/vscript_client.cpp index c865cb07..507b4523 100644 --- a/r5dev/game/client/vscript_client.cpp +++ b/r5dev/game/client/vscript_client.cpp @@ -415,34 +415,3 @@ void Script_RegisterCoreClientFunctions(CSquirrelVM* s) { DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, IsClientDLL, "Returns whether this build is client only", "bool", ""); } - -//--------------------------------------------------------------------------------- -// Purpose: core server script stubs (stubbed to prevent script compile errors!!!) -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterCoreServerStubs(CSquirrelVM* s) -{ - DEFINE_SCRIPTFUNC_STUBBED(s, IsServerActive, "bool", ""); - DEFINE_SCRIPTFUNC_STUBBED(s, IsDedicated, "bool", ""); - - DEFINE_SCRIPTFUNC_STUBBED(s, CreateServer, "void", "string, string, string, string, int"); - DEFINE_SCRIPTFUNC_STUBBED(s, DestroyServer, "void", ""); -} - -//--------------------------------------------------------------------------------- -// Purpose: admin panel script stubs (stubbed to prevent script compile errors!!!) -// Input : *s - -//--------------------------------------------------------------------------------- -void Script_RegisterAdminPanelStubs(CSquirrelVM* s) -{ - DEFINE_SCRIPTFUNC_STUBBED(s, GetNumHumanPlayers, "int", ""); - DEFINE_SCRIPTFUNC_STUBBED(s, GetNumFakeClients, "int", ""); - - DEFINE_SCRIPTFUNC_STUBBED(s, KickPlayerByName, "void", "string"); - DEFINE_SCRIPTFUNC_STUBBED(s, KickPlayerById, "void", "string"); - - DEFINE_SCRIPTFUNC_STUBBED(s, BanPlayerByName, "void", "string"); - DEFINE_SCRIPTFUNC_STUBBED(s, BanPlayerById, "void", "string"); - - DEFINE_SCRIPTFUNC_STUBBED(s, UnbanPlayer, "void", "string"); -} diff --git a/r5dev/game/client/vscript_client.h b/r5dev/game/client/vscript_client.h index 89f054e3..a2066ba4 100644 --- a/r5dev/game/client/vscript_client.h +++ b/r5dev/game/client/vscript_client.h @@ -32,9 +32,6 @@ void Script_RegisterClientFunctions(CSquirrelVM* s); void Script_RegisterUIFunctions(CSquirrelVM* s); void Script_RegisterCoreClientFunctions(CSquirrelVM* s); -void Script_RegisterCoreServerStubs(CSquirrelVM* s); -void Script_RegisterAdminPanelStubs(CSquirrelVM* s); - #define DEFINE_CLIENT_SCRIPTFUNC_NAMED(s, functionName, helpString, \ returnType, parameters) \ s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index 1cb43ac3..d8a1a77e 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -26,15 +26,6 @@ namespace VScriptCode { namespace Shared { - //----------------------------------------------------------------------------- - // Purpose: generic stub for unsupported functions - //----------------------------------------------------------------------------- - SQRESULT StubUnsupported(HSQUIRRELVM v) - { - v_SQVM_RaiseError(v, "This function is not supported on this build\n"); - return SQ_ERROR; - } - //----------------------------------------------------------------------------- // Purpose: expose SDK version to the VScript API //----------------------------------------------------------------------------- diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index 0591f348..3a3b8e77 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -16,7 +16,6 @@ namespace VScriptCode { namespace Shared { - SQRESULT StubUnsupported(HSQUIRRELVM v); SQRESULT GetSDKVersion(HSQUIRRELVM v); SQRESULT GetAvailableMaps(HSQUIRRELVM v); SQRESULT GetAvailablePlaylists(HSQUIRRELVM v); @@ -25,11 +24,6 @@ namespace VScriptCode void Script_RegisterCommonAbstractions(CSquirrelVM* s); -#define DEFINE_SCRIPTFUNC_STUBBED(s, functionName, returnType, parameters) \ - s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ - "Stub function; not supported on this build.", #returnType, parameters, \ - &VScriptCode::Shared::StubUnsupported); \ - #define DEFINE_SHARED_SCRIPTFUNC_NAMED(s, functionName, helpString, \ returnType, parameters) \ s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \ From 6d39d99941323a37a0128c161110b1336a87cc3b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:47:25 +0200 Subject: [PATCH 22/25] Fix mistake in comment --- r5dev/engine/client/cl_main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r5dev/engine/client/cl_main.h b/r5dev/engine/client/cl_main.h index f7394048..efa44118 100644 --- a/r5dev/engine/client/cl_main.h +++ b/r5dev/engine/client/cl_main.h @@ -17,7 +17,7 @@ inline void(*CL_RunPrediction)(void); inline bool g_bClientDLL = false; -// Returns true if this is a dedicated server. +// Returns true if this is a client only build. inline bool IsClientDLL() { return g_bClientDLL; From 80fecd2cb06442a5f5b2827166ca6cb688b4cb00 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:50:07 +0200 Subject: [PATCH 23/25] Improve help string and add a note --- r5dev/game/server/vscript_server.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/r5dev/game/server/vscript_server.cpp b/r5dev/game/server/vscript_server.cpp index 0b390dc9..8d00ff06 100644 --- a/r5dev/game/server/vscript_server.cpp +++ b/r5dev/game/server/vscript_server.cpp @@ -210,12 +210,16 @@ void Script_RegisterCoreServerFunctions(CSquirrelVM* s) DEFINE_SERVER_SCRIPTFUNC_NAMED(s, IsDedicated, "Returns whether this is a dedicated server", "bool", ""); DEFINE_SERVER_SCRIPTFUNC_NAMED(s, CreateServer, "Starts server with the specified settings", "void", "string, string, string, string, int"); - DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local host game down", "void", ""); + DEFINE_SERVER_SCRIPTFUNC_NAMED(s, DestroyServer, "Shuts the local server down", "void", ""); } //--------------------------------------------------------------------------------- // Purpose: admin panel script functions // Input : *s - +// +// Ideally, these get dropped entirely in favor of remote functions. Currently, +// the s3 build only supports remote function calls from server to client/ui. +// Client/ui to server is all done through clientcommands. //--------------------------------------------------------------------------------- void Script_RegisterAdminPanelFunctions(CSquirrelVM* s) { From a0f0b7926603b4112029c674e8a0753375e06d62 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:52:00 +0200 Subject: [PATCH 24/25] Add callback for registering script constants, and added 'LISTEN_SERVER' All listen server code should be compiled out of the scripts using 'LISTEN_SERVER'. The constant must have a non-null value. --- r5dev/core/init.cpp | 42 ++++++++++++------- r5dev/game/shared/vscript_shared.cpp | 18 +++++--- r5dev/game/shared/vscript_shared.h | 1 + .../languages/squirrel_re/vsquirrel.cpp | 8 ++++ .../vscript/languages/squirrel_re/vsquirrel.h | 2 + 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 9c7448e1..6b33fd9c 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -149,6 +149,31 @@ // ///////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef DEDICATED +// These command line parameters disable a bunch of things in the engine that +// the dedicated server does not need, therefore, reducing a lot of overhead. +void InitCommandLineParameters() +{ + CommandLine()->AppendParm("-collate", ""); + CommandLine()->AppendParm("-multiple", ""); + CommandLine()->AppendParm("-noorigin", ""); + CommandLine()->AppendParm("-nodiscord", ""); + CommandLine()->AppendParm("-noshaderapi", ""); + CommandLine()->AppendParm("-nobakedparticles", ""); + CommandLine()->AppendParm("-novid", ""); + CommandLine()->AppendParm("-nomenuvid", ""); + CommandLine()->AppendParm("-nosound", ""); + CommandLine()->AppendParm("-nomouse", ""); + CommandLine()->AppendParm("-nojoy", ""); + CommandLine()->AppendParm("-nosendtable", ""); +} +#endif // DEDICATED + +void ScriptConstantRegistrationCallback(CSquirrelVM* s) +{ + Script_RegisterListenServerConstants(s); +} + void Systems_Init() { DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); @@ -197,23 +222,12 @@ void Systems_Init() ConVar_StaticInit(); #ifdef DEDICATED - // These command line parameters disable a bunch of things in the engine that - // the dedicated server does not need, therefore, reducing a lot of overhead. - CommandLine()->AppendParm("-collate", ""); - CommandLine()->AppendParm("-multiple", ""); - CommandLine()->AppendParm("-noorigin", ""); - CommandLine()->AppendParm("-nodiscord", ""); - CommandLine()->AppendParm("-noshaderapi", ""); - CommandLine()->AppendParm("-nobakedparticles", ""); - CommandLine()->AppendParm("-novid", ""); - CommandLine()->AppendParm("-nomenuvid", ""); - CommandLine()->AppendParm("-nosound", ""); - CommandLine()->AppendParm("-nomouse", ""); - CommandLine()->AppendParm("-nojoy", ""); - CommandLine()->AppendParm("-nosendtable", ""); + InitCommandLineParameters(); #endif // DEDICATED // Script context registration callbacks. + ScriptConstantRegister_Callback = ScriptConstantRegistrationCallback; + #ifndef CLIENT_DLL ServerScriptRegister_Callback = Script_RegisterServerFunctions; CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions; diff --git a/r5dev/game/shared/vscript_shared.cpp b/r5dev/game/shared/vscript_shared.cpp index d8a1a77e..493169cb 100644 --- a/r5dev/game/shared/vscript_shared.cpp +++ b/r5dev/game/shared/vscript_shared.cpp @@ -13,14 +13,10 @@ #include "core/stdafx.h" #include "vpc/keyvalues.h" -#include "engine/server/server.h" +#include "engine/client/cl_main.h" #include "engine/cmodel_bsp.h" -#include "engine/host_state.h" -#include "networksystem/pylon.h" -#include "networksystem/bansystem.h" -#include "networksystem/listmanager.h" -#include "vscript_shared.h" #include "vscript/languages/squirrel_re/include/sqvm.h" +#include "vscript_shared.h" namespace VScriptCode { @@ -88,3 +84,13 @@ void Script_RegisterCommonAbstractions(CSquirrelVM* s) DEFINE_SHARED_SCRIPTFUNC_NAMED(s, GetAvailableMaps, "Gets an array of all available maps", "array< string >", ""); DEFINE_SHARED_SCRIPTFUNC_NAMED(s, GetAvailablePlaylists, "Gets an array of all available playlists", "array< string >", ""); } + +//--------------------------------------------------------------------------------- +// Purpose: listen server constants (!!! only call on builds containing a listen server !!!) +// Input : *s - +//--------------------------------------------------------------------------------- +void Script_RegisterListenServerConstants(CSquirrelVM* s) +{ + const SQBool hasListenServer = !IsClientDLL(); + s->RegisterConstant("LISTEN_SERVER", hasListenServer); +} diff --git a/r5dev/game/shared/vscript_shared.h b/r5dev/game/shared/vscript_shared.h index 3a3b8e77..ba0224fe 100644 --- a/r5dev/game/shared/vscript_shared.h +++ b/r5dev/game/shared/vscript_shared.h @@ -23,6 +23,7 @@ namespace VScriptCode } void Script_RegisterCommonAbstractions(CSquirrelVM* s); +void Script_RegisterListenServerConstants(CSquirrelVM* s); #define DEFINE_SHARED_SCRIPTFUNC_NAMED(s, functionName, helpString, \ returnType, parameters) \ diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp index 990141f2..69b7fb70 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.cpp @@ -17,6 +17,9 @@ void(*UiScriptRegister_Callback)(CSquirrelVM* s) = nullptr; void(*CoreServerScriptRegister_Callback)(CSquirrelVM* s) = nullptr; void(*AdminPanelScriptRegister_Callback)(CSquirrelVM* s) = nullptr; +// Registering constants in scripts. +void(*ScriptConstantRegister_Callback)(CSquirrelVM* s) = nullptr; + //--------------------------------------------------------------------------------- // Purpose: Initialises a Squirrel VM instance // Output : True on success, false on failure @@ -75,6 +78,11 @@ SQBool CSquirrelVM::DestroySignalEntryListHead(CSquirrelVM* s, HSQUIRRELVM v, SQ { SQBool result = v_CSquirrelVM_DestroySignalEntryListHead(s, v, f); s->RegisterConstant("DEVELOPER", developer->GetInt()); + + // Must have one. + Assert(ScriptConstantRegister_Callback); + ScriptConstantRegister_Callback(s); + return result; } diff --git a/r5dev/vscript/languages/squirrel_re/vsquirrel.h b/r5dev/vscript/languages/squirrel_re/vsquirrel.h index 94fe8d8b..7198b64c 100644 --- a/r5dev/vscript/languages/squirrel_re/vsquirrel.h +++ b/r5dev/vscript/languages/squirrel_re/vsquirrel.h @@ -50,6 +50,8 @@ extern void(*UiScriptRegister_Callback)(CSquirrelVM* s); extern void(*CoreServerScriptRegister_Callback)(CSquirrelVM* s); extern void(*AdminPanelScriptRegister_Callback)(CSquirrelVM* s); +extern void(*ScriptConstantRegister_Callback)(CSquirrelVM* s); + inline CMemory p_CSquirrelVM_Init; inline bool(*v_CSquirrelVM_Init)(CSquirrelVM* s, SQCONTEXT context, SQFloat curtime); From 3b661c22c8fcfcb6c7b1d3d2e9596776fadf116b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:56:01 +0200 Subject: [PATCH 25/25] Fix compiler warning Fix warning 'C4189', variable 'hr' was only used in debug. The 'Assert' macro is just a stub in release. --- r5dev/loader/loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r5dev/loader/loader.cpp b/r5dev/loader/loader.cpp index 05e903cc..b24b6a26 100644 --- a/r5dev/loader/loader.cpp +++ b/r5dev/loader/loader.cpp @@ -139,9 +139,10 @@ static void DetachEP() DetourUpdateThread(GetCurrentThread()); DetourDetach(&v_WinMain, &hWinMain); - HRESULT hr = DetourTransactionCommit(); + Assert(hr != NO_ERROR); + NOTE_UNUSED(hr); } //-----------------------------------------------------------------------------