Split logic_script_client and Mapbase user messages into their own files

This commit is contained in:
Blixibon 2020-12-26 00:02:43 -06:00
parent 55cbdf49aa
commit 5529127d68
6 changed files with 256 additions and 225 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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()

View File

@ -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
}

View File

@ -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
}

View File

@ -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