From 5529127d681ea1a20cdefdc88cc494a4f5f02ef5 Mon Sep 17 00:00:00 2001 From: Blixibon Date: Sat, 26 Dec 2020 00:02:43 -0600 Subject: [PATCH] Split logic_script_client and Mapbase user messages into their own files --- sp/src/game/client/client_mapbase.vpc | 2 + sp/src/game/server/server_mapbase.vpc | 2 + .../shared/mapbase/logic_script_client.cpp | 188 ++++++++++++++++++ sp/src/game/shared/mapbase/mapbase_shared.cpp | 45 ----- .../shared/mapbase/mapbase_usermessages.cpp | 64 ++++++ sp/src/game/shared/vscript_shared.cpp | 180 ----------------- 6 files changed, 256 insertions(+), 225 deletions(-) create mode 100644 sp/src/game/shared/mapbase/logic_script_client.cpp create mode 100644 sp/src/game/shared/mapbase/mapbase_usermessages.cpp diff --git a/sp/src/game/client/client_mapbase.vpc b/sp/src/game/client/client_mapbase.vpc index 3c2eb00f..243324f1 100644 --- a/sp/src/game/client/client_mapbase.vpc +++ b/sp/src/game/client/client_mapbase.vpc @@ -35,6 +35,7 @@ $Project $Folder "Mapbase" { $File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp" + $File "$SRCDIR\game\shared\mapbase\mapbase_usermessages.cpp" $File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp" $File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.cpp" @@ -50,6 +51,7 @@ $Project $File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT] $File "mapbase\c_func_clientclip.cpp" $File "mapbase\c_func_fake_worldportal.cpp" diff --git a/sp/src/game/server/server_mapbase.vpc b/sp/src/game/server/server_mapbase.vpc index 40581e0f..37146238 100644 --- a/sp/src/game/server/server_mapbase.vpc +++ b/sp/src/game/server/server_mapbase.vpc @@ -31,6 +31,7 @@ $Project $Folder "Mapbase" { $File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp" + $File "$SRCDIR\game\shared\mapbase\mapbase_usermessages.cpp" $File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp" $File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp" $File "$SRCDIR\game\shared\mapbase\MapEdit.cpp" @@ -46,6 +47,7 @@ $Project $File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT] $File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT] + $File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT] $File "mapbase\ai_grenade.cpp" $File "mapbase\ai_grenade.h" diff --git a/sp/src/game/shared/mapbase/logic_script_client.cpp b/sp/src/game/shared/mapbase/logic_script_client.cpp new file mode 100644 index 00000000..60c59351 --- /dev/null +++ b/sp/src/game/shared/mapbase/logic_script_client.cpp @@ -0,0 +1,188 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Custom client-side equivalent of logic_script. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "vscript_shared.h" +#include "tier1/fmtstr.h" + +//----------------------------------------------------------------------------- +// Purpose: An entity that acts as a container for client-side game scripts. +//----------------------------------------------------------------------------- + +#define MAX_SCRIPT_GROUP_CLIENT 8 + +class CLogicScriptClient : public CBaseEntity +{ +public: + DECLARE_CLASS( CLogicScriptClient, CBaseEntity ); + DECLARE_DATADESC(); + DECLARE_NETWORKCLASS(); + +#ifdef CLIENT_DLL + void OnDataChanged( DataUpdateType_t type ) + { + BaseClass::OnDataChanged( type ); + + if ( !m_ScriptScope.IsInitialized() ) + { + RunVScripts(); + } + } +#else + int UpdateTransmitState() { return SetTransmitState( FL_EDICT_ALWAYS ); } +#endif + + bool KeyValue( const char *szKeyName, const char *szValue ) + { + if ( FStrEq( szKeyName, "vscripts" ) ) + { + Q_strcpy( m_iszClientScripts.GetForModify(), szValue ); + } + + return BaseClass::KeyValue( szKeyName, szValue ); + } + + void RunVScripts() + { +#ifdef CLIENT_DLL + if (m_iszClientScripts == NULL_STRING) + { + CGMsg( 0, CON_GROUP_VSCRIPT, "%s has no client scripts", GetDebugName() ); + return; + } + + if (g_pScriptVM == NULL) + { + return; + } + + ValidateScriptScope(); + + // All functions we want to have call chained instead of overwritten + // by other scripts in this entities list. + static const char* sCallChainFunctions[] = + { + "OnPostSpawn", + "Precache" + }; + + ScriptLanguage_t language = g_pScriptVM->GetLanguage(); + + // Make a call chainer for each in this entities scope + for (int j = 0; j < ARRAYSIZE( sCallChainFunctions ); ++j) + { + + if (language == SL_PYTHON) + { + // UNDONE - handle call chaining in python + ; + } + else if (language == SL_SQUIRREL) + { + //TODO: For perf, this should be precompiled and the %s should be passed as a parameter + HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript( CFmtStr( "%sCallChain <- CSimpleCallChainer(\"%s\", self.GetScriptScope(), true)", sCallChainFunctions[j], sCallChainFunctions[j] ) ); + g_pScriptVM->Run( hCreateChainScript, (HSCRIPT)m_ScriptScope ); + } + } + + char szScriptsList[255]; + Q_strcpy( szScriptsList, m_iszClientScripts.Get() ); + CUtlStringList szScripts; + + V_SplitString( szScriptsList, " ", szScripts ); + + for (int i = 0; i < szScripts.Count(); i++) + { + CGMsg( 0, CON_GROUP_VSCRIPT, "%s executing script: %s\n", GetDebugName(), szScripts[i] ); + + RunScriptFile( szScripts[i], IsWorld() ); + + for (int j = 0; j < ARRAYSIZE( sCallChainFunctions ); ++j) + { + if (language == SL_PYTHON) + { + // UNDONE - handle call chaining in python + ; + } + else if (language == SL_SQUIRREL) + { + //TODO: For perf, this should be precompiled and the %s should be passed as a parameter. + HSCRIPT hRunPostScriptExecute = g_pScriptVM->CompileScript( CFmtStr( "%sCallChain.PostScriptExecute()", sCallChainFunctions[j] ) ); + g_pScriptVM->Run( hRunPostScriptExecute, (HSCRIPT)m_ScriptScope ); + } + } + } +#else + // Avoids issues from having m_iszVScripts set without actually having a script scope + ValidateScriptScope(); + + if (m_bRunOnServer) + { + BaseClass::RunVScripts(); + } +#endif + } + +#ifndef CLIENT_DLL + void InputCallScriptFunctionClient( inputdata_t &inputdata ) + { + // TODO: Support for specific players? + CBroadcastRecipientFilter filter; + filter.MakeReliable(); + + const char *pszFunction = inputdata.value.String(); + if (strlen( pszFunction ) > 64) + { + Msg("%s CallScriptFunctionClient: \"%s\" is too long at %i characters, must be 64 or less\n", GetDebugName(), pszFunction, strlen(pszFunction)); + return; + } + + UserMessageBegin( filter, "CallClientScriptFunction" ); + WRITE_STRING( pszFunction ); // function + WRITE_SHORT( entindex() ); // entity + MessageEnd(); + } +#endif + + //CNetworkArray( string_t, m_iszGroupMembers, MAX_SCRIPT_GROUP_CLIENT ); + CNetworkString( m_iszClientScripts, 128 ); + + bool m_bRunOnServer; +}; + +LINK_ENTITY_TO_CLASS( logic_script_client, CLogicScriptClient ); + +BEGIN_DATADESC( CLogicScriptClient ) + + //DEFINE_KEYFIELD( m_iszGroupMembers[0], FIELD_STRING, "Group00"), + //DEFINE_KEYFIELD( m_iszGroupMembers[1], FIELD_STRING, "Group01"), + //DEFINE_KEYFIELD( m_iszGroupMembers[2], FIELD_STRING, "Group02"), + //DEFINE_KEYFIELD( m_iszGroupMembers[3], FIELD_STRING, "Group03"), + //DEFINE_KEYFIELD( m_iszGroupMembers[4], FIELD_STRING, "Group04"), + //DEFINE_KEYFIELD( m_iszGroupMembers[5], FIELD_STRING, "Group05"), + //DEFINE_KEYFIELD( m_iszGroupMembers[6], FIELD_STRING, "Group06"), + //DEFINE_KEYFIELD( m_iszGroupMembers[7], FIELD_STRING, "Group07"), + + DEFINE_KEYFIELD( m_bRunOnServer, FIELD_BOOLEAN, "RunOnServer" ), + +#ifndef CLIENT_DLL + DEFINE_INPUTFUNC( FIELD_STRING, "CallScriptFunctionClient", InputCallScriptFunctionClient ), +#endif + +END_DATADESC() + +IMPLEMENT_NETWORKCLASS_DT( CLogicScriptClient, DT_LogicScriptClient ) + +#ifdef CLIENT_DLL + //RecvPropArray( RecvPropString( RECVINFO( m_iszGroupMembers[0] ) ), m_iszGroupMembers ), + RecvPropString( RECVINFO( m_iszClientScripts ) ), +#else + //SendPropArray( SendPropStringT( SENDINFO_ARRAY( m_iszGroupMembers ) ), m_iszGroupMembers ), + SendPropString( SENDINFO( m_iszClientScripts ) ), +#endif + +END_NETWORK_TABLE() diff --git a/sp/src/game/shared/mapbase/mapbase_shared.cpp b/sp/src/game/shared/mapbase/mapbase_shared.cpp index 3406d9c8..880e851b 100644 --- a/sp/src/game/shared/mapbase/mapbase_shared.cpp +++ b/sp/src/game/shared/mapbase/mapbase_shared.cpp @@ -618,48 +618,3 @@ BEGIN_DATADESC( CMapbaseManifestEntity ) END_DATADESC() #endif - -#ifdef CLIENT_DLL -void __MsgFunc_CallClientScriptFunction( bf_read &msg ) -{ - char szFunction[64]; - if (!msg.ReadString( szFunction, sizeof( szFunction ) )) - { - CGMsg( 0, CON_GROUP_VSCRIPT, "Unable to read function string\n" ); - } - - int idx = msg.ReadByte(); - C_BaseEntity *pEntity = CBaseEntity::Instance( idx ); - - if (pEntity) - { - if (pEntity->m_ScriptScope.IsInitialized()) - { - //CGMsg( 0, CON_GROUP_VSCRIPT, "%s calling function \"%s\"\n", pEntity->GetDebugName(), szFunction ); - pEntity->CallScriptFunction( szFunction, NULL ); - } - else - { - CGMsg( 0, CON_GROUP_VSCRIPT, "%s scope not initialized\n", pEntity->GetDebugName() ); - } - } - else - { - CGMsg( 0, CON_GROUP_VSCRIPT, "Clientside entity not found for script function (index %i)\n", idx ); - } -} - -void HookMapbaseUserMessages( void ) -{ - HOOK_MESSAGE( CallClientScriptFunction ); -} -#endif - -void RegisterMapbaseUserMessages( void ) -{ - usermessages->Register( "CallClientScriptFunction", -1 ); - -#ifdef CLIENT_DLL - HookMapbaseUserMessages(); -#endif -} diff --git a/sp/src/game/shared/mapbase/mapbase_usermessages.cpp b/sp/src/game/shared/mapbase/mapbase_usermessages.cpp new file mode 100644 index 00000000..6cbe9949 --- /dev/null +++ b/sp/src/game/shared/mapbase/mapbase_usermessages.cpp @@ -0,0 +1,64 @@ +//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============// +// +// Purpose: Mapbase-specific user messages. +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" + +#include "usermessages.h" +#ifdef CLIENT_DLL +#include "hud_macros.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef CLIENT_DLL +void __MsgFunc_CallClientScriptFunction( bf_read &msg ) +{ + char szFunction[64]; + if (!msg.ReadString( szFunction, sizeof( szFunction ) )) + { + CGMsg( 0, CON_GROUP_VSCRIPT, "Unable to read function string\n" ); + } + + int idx = msg.ReadByte(); + C_BaseEntity *pEntity = CBaseEntity::Instance( idx ); + + if (pEntity) + { + if (pEntity->m_ScriptScope.IsInitialized()) + { + //CGMsg( 0, CON_GROUP_VSCRIPT, "%s calling function \"%s\"\n", pEntity->GetDebugName(), szFunction ); + pEntity->CallScriptFunction( szFunction, NULL ); + } + else + { + CGMsg( 0, CON_GROUP_VSCRIPT, "%s scope not initialized\n", pEntity->GetDebugName() ); + } + } + else + { + CGMsg( 0, CON_GROUP_VSCRIPT, "Clientside entity not found for script function (index %i)\n", idx ); + } +} + +void HookMapbaseUserMessages( void ) +{ + // VScript + HOOK_MESSAGE( CallClientScriptFunction ); +} +#endif + +void RegisterMapbaseUserMessages( void ) +{ + // VScript + usermessages->Register( "CallClientScriptFunction", -1 ); + +#ifdef CLIENT_DLL + // TODO: Better placement? + HookMapbaseUserMessages(); +#endif +} diff --git a/sp/src/game/shared/vscript_shared.cpp b/sp/src/game/shared/vscript_shared.cpp index d844c323..ebe997a8 100644 --- a/sp/src/game/shared/vscript_shared.cpp +++ b/sp/src/game/shared/vscript_shared.cpp @@ -274,183 +274,3 @@ CON_COMMAND_SHARED( script_dump_all, "Dump the state of the VM to the console" ) } g_pScriptVM->DumpState(); } - -#ifdef MAPBASE_VSCRIPT -//----------------------------------------------------------------------------- -// Purpose: An entity that acts as a container for game scripts. -//----------------------------------------------------------------------------- - -#define MAX_SCRIPT_GROUP_CLIENT 8 - -class CLogicScriptClient : public CBaseEntity -{ -public: - DECLARE_CLASS( CLogicScriptClient, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_NETWORKCLASS(); - -#ifdef CLIENT_DLL - void OnDataChanged( DataUpdateType_t type ) - { - BaseClass::OnDataChanged( type ); - - if ( !m_ScriptScope.IsInitialized() ) - { - RunVScripts(); - } - } -#else - int UpdateTransmitState() { return SetTransmitState( FL_EDICT_ALWAYS ); } -#endif - - bool KeyValue( const char *szKeyName, const char *szValue ) - { - if ( FStrEq( szKeyName, "vscripts" ) ) - { - Q_strcpy( m_iszClientScripts.GetForModify(), szValue ); - } - - return BaseClass::KeyValue( szKeyName, szValue ); - } - - void RunVScripts() - { -#ifdef CLIENT_DLL - if (m_iszClientScripts == NULL_STRING) - { - CGMsg( 0, CON_GROUP_VSCRIPT, "%s has no client scripts", GetDebugName() ); - return; - } - - if (g_pScriptVM == NULL) - { - return; - } - - ValidateScriptScope(); - - // All functions we want to have call chained instead of overwritten - // by other scripts in this entities list. - static const char* sCallChainFunctions[] = - { - "OnPostSpawn", - "Precache" - }; - - ScriptLanguage_t language = g_pScriptVM->GetLanguage(); - - // Make a call chainer for each in this entities scope - for (int j = 0; j < ARRAYSIZE( sCallChainFunctions ); ++j) - { - - if (language == SL_PYTHON) - { - // UNDONE - handle call chaining in python - ; - } - else if (language == SL_SQUIRREL) - { - //TODO: For perf, this should be precompiled and the %s should be passed as a parameter - HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript( CFmtStr( "%sCallChain <- CSimpleCallChainer(\"%s\", self.GetScriptScope(), true)", sCallChainFunctions[j], sCallChainFunctions[j] ) ); - g_pScriptVM->Run( hCreateChainScript, (HSCRIPT)m_ScriptScope ); - } - } - - char szScriptsList[255]; - Q_strcpy( szScriptsList, m_iszClientScripts.Get() ); - CUtlStringList szScripts; - - V_SplitString( szScriptsList, " ", szScripts ); - - for (int i = 0; i < szScripts.Count(); i++) - { - CGMsg( 0, CON_GROUP_VSCRIPT, "%s executing script: %s\n", GetDebugName(), szScripts[i] ); - - RunScriptFile( szScripts[i], IsWorld() ); - - for (int j = 0; j < ARRAYSIZE( sCallChainFunctions ); ++j) - { - if (language == SL_PYTHON) - { - // UNDONE - handle call chaining in python - ; - } - else if (language == SL_SQUIRREL) - { - //TODO: For perf, this should be precompiled and the %s should be passed as a parameter. - HSCRIPT hRunPostScriptExecute = g_pScriptVM->CompileScript( CFmtStr( "%sCallChain.PostScriptExecute()", sCallChainFunctions[j] ) ); - g_pScriptVM->Run( hRunPostScriptExecute, (HSCRIPT)m_ScriptScope ); - } - } - } -#else - // Avoids issues from having m_iszVScripts set without actually having a script scope - ValidateScriptScope(); - - if (m_bRunOnServer) - { - BaseClass::RunVScripts(); - } -#endif - } - -#ifndef CLIENT_DLL - void InputCallScriptFunctionClient( inputdata_t &inputdata ) - { - // TODO: Support for specific players? - CBroadcastRecipientFilter filter; - filter.MakeReliable(); - - const char *pszFunction = inputdata.value.String(); - if (strlen( pszFunction ) > 64) - { - Msg("%s CallScriptFunctionClient: \"%s\" is too long at %i characters, must be 64 or less\n", GetDebugName(), pszFunction, strlen(pszFunction)); - return; - } - - UserMessageBegin( filter, "CallClientScriptFunction" ); - WRITE_STRING( pszFunction ); // function - WRITE_SHORT( entindex() ); // entity - MessageEnd(); - } -#endif - - //CNetworkArray( string_t, m_iszGroupMembers, MAX_SCRIPT_GROUP_CLIENT ); - CNetworkString( m_iszClientScripts, 128 ); - - bool m_bRunOnServer; -}; - -LINK_ENTITY_TO_CLASS( logic_script_client, CLogicScriptClient ); - -BEGIN_DATADESC( CLogicScriptClient ) - - //DEFINE_KEYFIELD( m_iszGroupMembers[0], FIELD_STRING, "Group00"), - //DEFINE_KEYFIELD( m_iszGroupMembers[1], FIELD_STRING, "Group01"), - //DEFINE_KEYFIELD( m_iszGroupMembers[2], FIELD_STRING, "Group02"), - //DEFINE_KEYFIELD( m_iszGroupMembers[3], FIELD_STRING, "Group03"), - //DEFINE_KEYFIELD( m_iszGroupMembers[4], FIELD_STRING, "Group04"), - //DEFINE_KEYFIELD( m_iszGroupMembers[5], FIELD_STRING, "Group05"), - //DEFINE_KEYFIELD( m_iszGroupMembers[6], FIELD_STRING, "Group06"), - //DEFINE_KEYFIELD( m_iszGroupMembers[7], FIELD_STRING, "Group07"), - - DEFINE_KEYFIELD( m_bRunOnServer, FIELD_BOOLEAN, "RunOnServer" ), - -#ifndef CLIENT_DLL - DEFINE_INPUTFUNC( FIELD_STRING, "CallScriptFunctionClient", InputCallScriptFunctionClient ), -#endif - -END_DATADESC() - -IMPLEMENT_NETWORKCLASS_DT( CLogicScriptClient, DT_LogicScriptClient ) - -#ifdef CLIENT_DLL - //RecvPropArray( RecvPropString( RECVINFO( m_iszGroupMembers[0] ) ), m_iszGroupMembers ), - RecvPropString( RECVINFO( m_iszClientScripts ) ), -#else - //SendPropArray( SendPropStringT( SENDINFO_ARRAY( m_iszGroupMembers ) ), m_iszGroupMembers ), - SendPropString( SENDINFO( m_iszClientScripts ) ), -#endif - -END_NETWORK_TABLE() -#endif