mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-04-30 00:49:34 +03:00
Merge branch 'develop' into vscript-leak-fixes
This commit is contained in:
commit
cce93d7486
5
.gitignore
vendored
5
.gitignore
vendored
@ -19,6 +19,8 @@ ipch
|
|||||||
*.idb
|
*.idb
|
||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.sln
|
*.sln
|
||||||
|
*.vcxproj.FileListAbsolute.txt
|
||||||
|
*.pdb
|
||||||
|
|
||||||
# OSX/Linux build products
|
# OSX/Linux build products
|
||||||
*.mak
|
*.mak
|
||||||
@ -49,6 +51,8 @@ client.dylib.dSYM/
|
|||||||
server.dylib
|
server.dylib
|
||||||
server.dylib.dSYM/
|
server.dylib.dSYM/
|
||||||
|
|
||||||
|
sp/game/bin
|
||||||
|
|
||||||
# files generated by running a mod
|
# files generated by running a mod
|
||||||
config.cfg
|
config.cfg
|
||||||
|
|
||||||
@ -61,6 +65,7 @@ config.cfg
|
|||||||
*.filters
|
*.filters
|
||||||
*.vpc_crc
|
*.vpc_crc
|
||||||
*.sentinel
|
*.sentinel
|
||||||
|
*.recipe
|
||||||
|
|
||||||
# Backup files
|
# Backup files
|
||||||
*.bak
|
*.bak
|
||||||
|
@ -157,6 +157,22 @@ void CColorCorrectionMgr::CommitColorCorrectionWeights()
|
|||||||
}
|
}
|
||||||
m_colorCorrectionWeights.RemoveAll();
|
m_colorCorrectionWeights.RemoveAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CColorCorrectionMgr::LevelShutdownPreEntity()
|
||||||
|
{
|
||||||
|
//Clean up the vectors when shuting down a level
|
||||||
|
//will keep dangling pointers inside of the vector causing a nullptr crash
|
||||||
|
if (g_ColorCorrectionVolumeList.Base())
|
||||||
|
{
|
||||||
|
g_ColorCorrectionVolumeList.Purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_ColorCorrectionList.Base())
|
||||||
|
{
|
||||||
|
g_ColorCorrectionList.Purge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
|
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
|
||||||
{
|
{
|
||||||
|
@ -76,6 +76,8 @@ private:
|
|||||||
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
|
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
|
||||||
|
|
||||||
void CommitColorCorrectionWeights();
|
void CommitColorCorrectionWeights();
|
||||||
|
|
||||||
|
void LevelShutdownPreEntity();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
extern IScriptManager *scriptmanager;
|
extern IScriptManager *scriptmanager;
|
||||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
extern int vscript_debugger_port;
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define VMPROFILE 1
|
// #define VMPROFILE 1
|
||||||
|
|
||||||
#ifdef VMPROFILE
|
#ifdef VMPROFILE
|
||||||
@ -682,6 +686,14 @@ bool VScriptClientInit()
|
|||||||
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
if ( vscript_debugger_port )
|
||||||
|
{
|
||||||
|
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||||
|
vscript_debugger_port = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (scriptLanguage == SL_SQUIRREL)
|
if (scriptLanguage == SL_SQUIRREL)
|
||||||
{
|
{
|
||||||
g_pScriptVM->Run( g_Script_vscript_client );
|
g_pScriptVM->Run( g_Script_vscript_client );
|
||||||
@ -770,11 +782,19 @@ public:
|
|||||||
VScriptClientTerm();
|
VScriptClientTerm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
virtual void Update( float frametime )
|
||||||
|
{
|
||||||
|
if ( g_pScriptVM )
|
||||||
|
g_pScriptVM->Frame( frametime );
|
||||||
|
}
|
||||||
|
#else
|
||||||
virtual void FrameUpdatePostEntityThink()
|
virtual void FrameUpdatePostEntityThink()
|
||||||
{
|
{
|
||||||
if ( g_pScriptVM )
|
if ( g_pScriptVM )
|
||||||
g_pScriptVM->Frame( gpGlobals->frametime );
|
g_pScriptVM->Frame( gpGlobals->frametime );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool m_bAllowEntityCreationInScripts;
|
bool m_bAllowEntityCreationInScripts;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
#include "saverestore_utlvector.h"
|
#include "saverestore_utlvector.h"
|
||||||
#include "dt_utlvector_send.h"
|
#include "dt_utlvector_send.h"
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
#include "mapbase/vscript_funcs_shared.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
@ -471,7 +475,8 @@ void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAni
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
if (eventHandler->m_ScriptScope.IsInitialized() && eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
scriptanimevent_t wrapper( event );
|
||||||
|
if (eventHandler->m_ScriptScope.IsInitialized() && !eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1261,7 +1261,8 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
if (eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
scriptanimevent_t wrapper( event );
|
||||||
|
if (!eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1299,11 +1300,11 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CBaseAnimating::ScriptHookHandleAnimEvent( animevent_t *pEvent )
|
bool CBaseAnimating::ScriptHookHandleAnimEvent( scriptanimevent_t &event )
|
||||||
{
|
{
|
||||||
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
|
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
|
||||||
{
|
{
|
||||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( reinterpret_cast<scriptanimevent_t*>(pEvent) );
|
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( &event );
|
||||||
|
|
||||||
// event
|
// event
|
||||||
ScriptVariant_t args[] = { hEvent };
|
ScriptVariant_t args[] = { hEvent };
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#include "datacache/idatacache.h"
|
#include "datacache/idatacache.h"
|
||||||
#include "tier0/threadtools.h"
|
#include "tier0/threadtools.h"
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
struct scriptanimevent_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct animevent_t;
|
struct animevent_t;
|
||||||
struct matrix3x4_t;
|
struct matrix3x4_t;
|
||||||
@ -146,7 +149,7 @@ public:
|
|||||||
virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
|
virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
|
||||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
bool ScriptHookHandleAnimEvent( animevent_t *pEvent );
|
bool ScriptHookHandleAnimEvent( scriptanimevent_t &event );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
|
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
|
||||||
|
@ -3482,13 +3482,13 @@ void CBaseCombatCharacter::AddRelationship( const char *pszRelationship, CBaseEn
|
|||||||
bool bFoundEntity = false;
|
bool bFoundEntity = false;
|
||||||
|
|
||||||
// Try to get pointer to an entity of this name
|
// Try to get pointer to an entity of this name
|
||||||
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString );
|
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString, this, pActivator );
|
||||||
while( entity )
|
while( entity )
|
||||||
{
|
{
|
||||||
// make sure you catch all entities of this name.
|
// make sure you catch all entities of this name.
|
||||||
bFoundEntity = true;
|
bFoundEntity = true;
|
||||||
AddEntityRelationship(entity, disposition, priority );
|
AddEntityRelationship(entity, disposition, priority );
|
||||||
entity = gEntList.FindEntityByName( entity, entityString );
|
entity = gEntList.FindEntityByName( entity, entityString, this, pActivator );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !bFoundEntity )
|
if( !bFoundEntity )
|
||||||
|
@ -134,6 +134,11 @@ enum LandingState_t
|
|||||||
LANDING_HOVER_DESCEND,
|
LANDING_HOVER_DESCEND,
|
||||||
LANDING_HOVER_TOUCHDOWN,
|
LANDING_HOVER_TOUCHDOWN,
|
||||||
LANDING_END_HOVER,
|
LANDING_END_HOVER,
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Strider dropoff
|
||||||
|
LANDING_STRIDER,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -295,6 +300,9 @@ private:
|
|||||||
bool IsHovering();
|
bool IsHovering();
|
||||||
void UpdateGroundRotorWashSound( float flAltitude );
|
void UpdateGroundRotorWashSound( float flAltitude );
|
||||||
void UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime );
|
void UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void DeathNotice(CBaseEntity* pVictim);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Timers
|
// Timers
|
||||||
@ -353,6 +361,12 @@ private:
|
|||||||
string_t m_sRollermineTemplate;
|
string_t m_sRollermineTemplate;
|
||||||
string_t m_sRollermineTemplateData;
|
string_t m_sRollermineTemplateData;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Template for strider carried by this dropship
|
||||||
|
string_t m_sStriderTemplate;
|
||||||
|
string_t m_sStriderTemplateData;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Cached attachment points
|
// Cached attachment points
|
||||||
int m_iMuzzleAttachment;
|
int m_iMuzzleAttachment;
|
||||||
int m_iMachineGunBaseAttachment;
|
int m_iMachineGunBaseAttachment;
|
||||||
@ -827,6 +841,11 @@ BEGIN_DATADESC( CNPC_CombineDropship )
|
|||||||
DEFINE_KEYFIELD( m_sRollermineTemplate, FIELD_STRING, "RollermineTemplate" ),
|
DEFINE_KEYFIELD( m_sRollermineTemplate, FIELD_STRING, "RollermineTemplate" ),
|
||||||
DEFINE_FIELD( m_sRollermineTemplateData, FIELD_STRING ),
|
DEFINE_FIELD( m_sRollermineTemplateData, FIELD_STRING ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD(m_sStriderTemplate, FIELD_STRING, "StriderTemplate"),
|
||||||
|
DEFINE_FIELD(m_sStriderTemplateData, FIELD_STRING),
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_ARRAY( m_sNPCTemplateData, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ),
|
DEFINE_ARRAY( m_sNPCTemplateData, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ),
|
||||||
DEFINE_KEYFIELD( m_sNPCTemplate[0], FIELD_STRING, "NPCTemplate" ),
|
DEFINE_KEYFIELD( m_sNPCTemplate[0], FIELD_STRING, "NPCTemplate" ),
|
||||||
DEFINE_KEYFIELD( m_sNPCTemplate[1], FIELD_STRING, "NPCTemplate2" ),
|
DEFINE_KEYFIELD( m_sNPCTemplate[1], FIELD_STRING, "NPCTemplate2" ),
|
||||||
@ -962,12 +981,60 @@ void CNPC_CombineDropship::Spawn( void )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CRATE_STRIDER:
|
case CRATE_STRIDER:
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_sStriderTemplate != NULL_STRING )
|
||||||
|
{
|
||||||
|
m_sStriderTemplateData = Templates_FindByTargetName( STRING( m_sStriderTemplate ) );
|
||||||
|
if (m_sStriderTemplateData == NULL_STRING)
|
||||||
|
{
|
||||||
|
Warning("npc_combinedropship %s: Strider Template %s not found!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAI_BaseNPC* pent = NULL;
|
||||||
|
CBaseEntity* pEntity = NULL;
|
||||||
|
MapEntity_ParseEntity( pEntity, STRING( m_sStriderTemplateData ), NULL);
|
||||||
|
if ( pEntity != NULL )
|
||||||
|
{
|
||||||
|
pent = ( CAI_BaseNPC* )pEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !FClassnameIs(pent, "npc_strider"))
|
||||||
|
{
|
||||||
|
Warning("npc_combinedropship %s: Strider Template %s is not a strider!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_OnSpawnNPC.Set( pEntity, pEntity, this );
|
||||||
|
|
||||||
|
pent->RemoveSpawnFlags( SF_NPC_TEMPLATE );
|
||||||
|
|
||||||
|
pent->SetOwnerEntity( this );
|
||||||
|
|
||||||
|
m_hContainer = pent;
|
||||||
|
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||||
|
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||||
|
m_hContainer->SetParent( this, 0 );
|
||||||
|
m_hContainer->SetOwnerEntity( this );
|
||||||
|
DispatchSpawn(pent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_hContainer = ( CBaseAnimating* )CreateEntityByName("npc_strider");
|
||||||
|
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||||
|
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||||
|
m_hContainer->SetParent( this, 0 );
|
||||||
|
m_hContainer->SetOwnerEntity( this );
|
||||||
|
m_hContainer->Spawn();
|
||||||
|
}
|
||||||
|
#else
|
||||||
m_hContainer = (CBaseAnimating*)CreateEntityByName( "npc_strider" );
|
m_hContainer = (CBaseAnimating*)CreateEntityByName( "npc_strider" );
|
||||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||||
m_hContainer->SetParent(this, 0);
|
m_hContainer->SetParent(this, 0);
|
||||||
m_hContainer->SetOwnerEntity(this);
|
m_hContainer->SetOwnerEntity(this);
|
||||||
m_hContainer->Spawn();
|
m_hContainer->Spawn();
|
||||||
|
#endif
|
||||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||||
#ifdef MAPBASE
|
#ifdef MAPBASE
|
||||||
m_OnSpawnNPC.Set( m_hContainer, m_hContainer, this );
|
m_OnSpawnNPC.Set( m_hContainer, m_hContainer, this );
|
||||||
@ -1201,13 +1268,24 @@ void CNPC_CombineDropship::Precache( void )
|
|||||||
void CNPC_CombineDropship::Flight( void )
|
void CNPC_CombineDropship::Flight( void )
|
||||||
{
|
{
|
||||||
// Only run the flight model in some flight states
|
// Only run the flight model in some flight states
|
||||||
|
#ifdef MAPBASE
|
||||||
bool bRunFlight = ( GetLandingState() == LANDING_NO ||
|
bool bRunFlight = ( GetLandingState() == LANDING_NO ||
|
||||||
GetLandingState() == LANDING_LEVEL_OUT ||
|
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||||
GetLandingState() == LANDING_LIFTOFF ||
|
GetLandingState() == LANDING_LIFTOFF ||
|
||||||
GetLandingState() == LANDING_SWOOPING ||
|
GetLandingState() == LANDING_SWOOPING ||
|
||||||
GetLandingState() == LANDING_DESCEND ||
|
GetLandingState() == LANDING_DESCEND ||
|
||||||
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||||
GetLandingState() == LANDING_HOVER_DESCEND );
|
GetLandingState() == LANDING_HOVER_DESCEND ||
|
||||||
|
GetLandingState() == LANDING_STRIDER );
|
||||||
|
#else
|
||||||
|
bool bRunFlight = (GetLandingState() == LANDING_NO ||
|
||||||
|
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||||
|
GetLandingState() == LANDING_LIFTOFF ||
|
||||||
|
GetLandingState() == LANDING_SWOOPING ||
|
||||||
|
GetLandingState() == LANDING_DESCEND ||
|
||||||
|
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||||
|
GetLandingState() == LANDING_HOVER_DESCEND );
|
||||||
|
#endif
|
||||||
|
|
||||||
Vector forward, right, up;
|
Vector forward, right, up;
|
||||||
GetVectors( &forward, &right, &up );
|
GetVectors( &forward, &right, &up );
|
||||||
@ -1429,8 +1507,14 @@ void CNPC_CombineDropship::Flight( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we're landing, deliberately tuck in the back end
|
// If we're landing, deliberately tuck in the back end
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||||
|
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED ||
|
||||||
|
GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||||
|
#else
|
||||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||||
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED || IsHovering() )
|
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED || IsHovering() )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
finspeed = -60;
|
finspeed = -60;
|
||||||
}
|
}
|
||||||
@ -1779,6 +1863,16 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_iszLandTarget != NULL_STRING)
|
||||||
|
{
|
||||||
|
LandCommon();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLandingState(LANDING_STRIDER);
|
||||||
|
}
|
||||||
|
#else
|
||||||
QAngle angles = GetAbsAngles();
|
QAngle angles = GetAbsAngles();
|
||||||
|
|
||||||
angles.x = 0.0;
|
angles.x = 0.0;
|
||||||
@ -1790,6 +1884,7 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
|||||||
m_hContainer->SetAbsVelocity( vec3_origin );
|
m_hContainer->SetAbsVelocity( vec3_origin );
|
||||||
|
|
||||||
m_hContainer = NULL;
|
m_hContainer = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2016,7 +2111,11 @@ void CNPC_CombineDropship::SetLandingState( LandingState_t landingState )
|
|||||||
if ( m_pDescendingWarningSound )
|
if ( m_pDescendingWarningSound )
|
||||||
{
|
{
|
||||||
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) || ( landingState == LANDING_STRIDER ) )
|
||||||
|
#else
|
||||||
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) )
|
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
controller.SoundChangeVolume( m_pDescendingWarningSound, m_bSuppressSound ? 0.0f : 1.0f, 0.3f );
|
controller.SoundChangeVolume( m_pDescendingWarningSound, m_bSuppressSound ? 0.0f : 1.0f, 0.3f );
|
||||||
}
|
}
|
||||||
@ -2112,8 +2211,15 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
|||||||
if ( flDistance < 70 && flSpeed < 100 )
|
if ( flDistance < 70 && flSpeed < 100 )
|
||||||
{
|
{
|
||||||
m_flLandingSpeed = flSpeed;
|
m_flLandingSpeed = flSpeed;
|
||||||
|
#ifdef MAPBASE
|
||||||
if( IsHovering() )
|
if ( m_iCrateType == CRATE_STRIDER )
|
||||||
|
{
|
||||||
|
SetLandingState( LANDING_STRIDER );
|
||||||
|
}
|
||||||
|
else if( IsHovering() )
|
||||||
|
#else
|
||||||
|
if ( IsHovering() )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
SetLandingState( LANDING_HOVER_DESCEND );
|
SetLandingState( LANDING_HOVER_DESCEND );
|
||||||
}
|
}
|
||||||
@ -2315,6 +2421,98 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case LANDING_STRIDER:
|
||||||
|
{
|
||||||
|
if (!m_hContainer)
|
||||||
|
{
|
||||||
|
// Strider died, get out of here
|
||||||
|
SetLandingState(LANDING_LIFTOFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orient myself to the desired direction
|
||||||
|
bool bStillOrienting = false;
|
||||||
|
Vector targetDir;
|
||||||
|
if (m_hLandTarget)
|
||||||
|
{
|
||||||
|
// We've got a land target, so match it's orientation
|
||||||
|
AngleVectors(m_hLandTarget->GetAbsAngles(), &targetDir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No land target.
|
||||||
|
targetDir = GetDesiredPosition() - GetAbsOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't unload until we're facing the way the dropoff point specifies
|
||||||
|
float flTargetYaw = UTIL_VecToYaw(targetDir);
|
||||||
|
float flDeltaYaw = UTIL_AngleDiff(flTargetYaw, GetAbsAngles().y);
|
||||||
|
if (fabs(flDeltaYaw) > 5)
|
||||||
|
{
|
||||||
|
bStillOrienting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we land on the drop point. Stop dropping if we're still turning.
|
||||||
|
Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
|
||||||
|
float flDistance = vecToTarget.Length();
|
||||||
|
float flRampedSpeed = m_flLandingSpeed * (flDistance / 70);
|
||||||
|
Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget;
|
||||||
|
|
||||||
|
#define STRIDER_LANDING_HEIGHT 540.0f
|
||||||
|
|
||||||
|
float flFactor = MIN(1.0, MAX(0.1f, (flAltitude - STRIDER_LANDING_HEIGHT) / flAltitude));
|
||||||
|
float flDescendVelocity = MIN(-75, MAX_LAND_VEL * flFactor);
|
||||||
|
|
||||||
|
vecVelocity.z = flDescendVelocity;
|
||||||
|
|
||||||
|
SetAbsVelocity(vecVelocity);
|
||||||
|
|
||||||
|
if (flAltitude < 600)
|
||||||
|
{
|
||||||
|
QAngle angles = GetLocalAngles();
|
||||||
|
|
||||||
|
// Level out quickly.
|
||||||
|
angles.x = UTIL_Approach(0.0, angles.x, 0.2);
|
||||||
|
angles.z = UTIL_Approach(0.0, angles.z, 0.2);
|
||||||
|
|
||||||
|
SetLocalAngles(angles);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// randomly move as if buffeted by ground effects
|
||||||
|
// gently flatten ship from starting pitch/yaw
|
||||||
|
m_existPitch = UTIL_Approach(0.0, m_existPitch, 1);
|
||||||
|
m_existRoll = UTIL_Approach(0.0, m_existRoll, 1);
|
||||||
|
|
||||||
|
QAngle angles = GetLocalAngles();
|
||||||
|
angles.x = m_existPitch + (sin(gpGlobals->curtime * 3.5f) * DROPSHIP_MAX_LAND_TILT);
|
||||||
|
angles.z = m_existRoll + (sin(gpGlobals->curtime * 3.75f) * DROPSHIP_MAX_LAND_TILT);
|
||||||
|
SetLocalAngles(angles);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoRotorWash();
|
||||||
|
|
||||||
|
if (!bStillOrienting && flAltitude < STRIDER_LANDING_HEIGHT)
|
||||||
|
{
|
||||||
|
QAngle angles = GetAbsAngles();
|
||||||
|
|
||||||
|
m_hContainer->SetParent(NULL, 0);
|
||||||
|
m_hContainer->SetOwnerEntity(NULL);
|
||||||
|
m_hContainer->SetAbsAngles(angles);
|
||||||
|
m_hContainer->SetAbsVelocity(vec3_origin);
|
||||||
|
|
||||||
|
m_hContainer = NULL;
|
||||||
|
|
||||||
|
m_flTimeTakeOff = gpGlobals->curtime + 3.5f;
|
||||||
|
SetLandingState(LANDING_UNLOADING);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case LANDING_UNLOADING:
|
case LANDING_UNLOADING:
|
||||||
{
|
{
|
||||||
// If we've got no specified takeoff time, we're still waiting for troops to exit. Idle.
|
// If we've got no specified takeoff time, we're still waiting for troops to exit. Idle.
|
||||||
@ -2817,7 +3015,11 @@ void CNPC_CombineDropship::UpdatePickupNavigation( void )
|
|||||||
void CNPC_CombineDropship::UpdateLandTargetNavigation( void )
|
void CNPC_CombineDropship::UpdateLandTargetNavigation( void )
|
||||||
{
|
{
|
||||||
Vector vecPickup = m_hLandTarget->WorldSpaceCenter();
|
Vector vecPickup = m_hLandTarget->WorldSpaceCenter();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
vecPickup.z += ( m_iCrateType == CRATE_STRIDER ) ? 732 : 256;
|
||||||
|
#else
|
||||||
vecPickup.z += 256;
|
vecPickup.z += 256;
|
||||||
|
#endif
|
||||||
SetDesiredPosition( vecPickup );
|
SetDesiredPosition( vecPickup );
|
||||||
|
|
||||||
//NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f );
|
//NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f );
|
||||||
@ -2850,7 +3052,11 @@ void CNPC_CombineDropship::Hunt( void )
|
|||||||
// Face our desired position.
|
// Face our desired position.
|
||||||
m_vecDesiredFaceDir = desiredDir;
|
m_vecDesiredFaceDir = desiredDir;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||||
|
#else
|
||||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || IsHovering() )
|
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || IsHovering() )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if ( m_hLandTarget )
|
if ( m_hLandTarget )
|
||||||
{
|
{
|
||||||
@ -3150,6 +3356,19 @@ void CNPC_CombineDropship::MakeTracer( const Vector &vecTracerSrc, const trace_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Need a way to tell if our strider died
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CNPC_CombineDropship::DeathNotice( CBaseEntity *pVictim )
|
||||||
|
{
|
||||||
|
if ( m_iCrateType == CRATE_STRIDER && GetLandingState() == LANDING_NO )
|
||||||
|
{
|
||||||
|
m_OnContainerShotDownBeforeDropoff.Set( 1, m_hContainer, this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_BEGIN_CUSTOM_NPC( npc_combinedropship, CNPC_CombineDropship )
|
AI_BEGIN_CUSTOM_NPC( npc_combinedropship, CNPC_CombineDropship )
|
||||||
|
|
||||||
DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE );
|
DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE );
|
||||||
|
@ -1327,6 +1327,15 @@ void CNPC_Strider::BuildScheduleTestBits()
|
|||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
int CNPC_Strider::SelectSchedule()
|
int CNPC_Strider::SelectSchedule()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if( GetMoveType() == MOVETYPE_NONE )
|
||||||
|
{
|
||||||
|
// Dropship just released me.
|
||||||
|
AddFlag(FL_FLY);
|
||||||
|
SetMoveType( MOVETYPE_STEP );
|
||||||
|
return SCHED_STRIDER_FALL_TO_GROUND;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
if( GetMoveType() != MOVETYPE_FLY )
|
if( GetMoveType() != MOVETYPE_FLY )
|
||||||
{
|
{
|
||||||
@ -5818,6 +5827,18 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
|||||||
" COND_STRIDER_SHOULD_STAND"
|
" COND_STRIDER_SHOULD_STAND"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_SCHEDULE
|
||||||
|
(
|
||||||
|
SCHED_STRIDER_FALL_TO_GROUND,
|
||||||
|
|
||||||
|
" Tasks "
|
||||||
|
" TASK_SOUND_WAKE 0"
|
||||||
|
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_STRIDER_DEPLOY"
|
||||||
|
""
|
||||||
|
" Interrupts "
|
||||||
|
)
|
||||||
|
#else
|
||||||
DEFINE_SCHEDULE
|
DEFINE_SCHEDULE
|
||||||
(
|
(
|
||||||
SCHED_STRIDER_FALL_TO_GROUND,
|
SCHED_STRIDER_FALL_TO_GROUND,
|
||||||
@ -5827,7 +5848,7 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
|||||||
""
|
""
|
||||||
" Interrupts "
|
" Interrupts "
|
||||||
)
|
)
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_END_CUSTOM_NPC()
|
AI_END_CUSTOM_NPC()
|
||||||
|
|
||||||
|
@ -2645,16 +2645,19 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
|||||||
{
|
{
|
||||||
// By default, aim for the center
|
// By default, aim for the center
|
||||||
Vector vecTarget = pTarget->WorldSpaceCenter();
|
Vector vecTarget = pTarget->WorldSpaceCenter();
|
||||||
|
const Vector vecBulletOrigin = GetBulletOrigin();
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
|
if ( m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope( m_ScriptScope ) )
|
||||||
{
|
{
|
||||||
ScriptVariant_t functionReturn;
|
ScriptVariant_t functionReturn;
|
||||||
ScriptVariant_t args[] = { GetBulletOrigin(), ToHScript( pTarget ) };
|
ScriptVariant_t args[] = { vecBulletOrigin, ToHScript( pTarget ) };
|
||||||
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
|
if ( g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ) )
|
||||||
{
|
{
|
||||||
if (functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f)
|
if ( functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f )
|
||||||
|
{
|
||||||
return *functionReturn.m_pVector;
|
return *functionReturn.m_pVector;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2682,12 +2685,12 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
|||||||
{
|
{
|
||||||
if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() )
|
if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() )
|
||||||
{
|
{
|
||||||
vecTarget = pTarget->BodyTarget( GetBulletOrigin(), false );
|
vecTarget = pTarget->BodyTarget( vecBulletOrigin, false );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Shoot zombies in the headcrab
|
// Shoot zombies in the headcrab
|
||||||
vecTarget = pTarget->HeadTarget( GetBulletOrigin() );
|
vecTarget = pTarget->HeadTarget( vecBulletOrigin );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( pTarget->Classify() == CLASS_ANTLION )
|
else if( pTarget->Classify() == CLASS_ANTLION )
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
|
|
||||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
extern int vscript_debugger_port;
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define VMPROFILE 1
|
// #define VMPROFILE 1
|
||||||
|
|
||||||
#ifdef VMPROFILE
|
#ifdef VMPROFILE
|
||||||
@ -663,6 +667,14 @@ bool VScriptServerInit()
|
|||||||
RegisterSharedScriptFunctions();
|
RegisterSharedScriptFunctions();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
if ( vscript_debugger_port )
|
||||||
|
{
|
||||||
|
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||||
|
vscript_debugger_port = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (scriptLanguage == SL_SQUIRREL)
|
if (scriptLanguage == SL_SQUIRREL)
|
||||||
{
|
{
|
||||||
g_pScriptVM->Run( g_Script_vscript_server );
|
g_pScriptVM->Run( g_Script_vscript_server );
|
||||||
|
@ -357,7 +357,8 @@ void RegisterSharedScriptConstants()
|
|||||||
ScriptRegisterConstant( g_pScriptVM, ROPE_NO_GRAVITY, "Disable gravity on this rope. (for use in rope flags)" );
|
ScriptRegisterConstant( g_pScriptVM, ROPE_NO_GRAVITY, "Disable gravity on this rope. (for use in rope flags)" );
|
||||||
ScriptRegisterConstant( g_pScriptVM, ROPE_NUMFLAGS, "The number of rope flags recognized by the game." );
|
ScriptRegisterConstant( g_pScriptVM, ROPE_NUMFLAGS, "The number of rope flags recognized by the game." );
|
||||||
|
|
||||||
ScriptRegisterConstantNamed( g_pScriptVM, Vector( ROPE_GRAVITY ), "ROPE_GRAVITY", "Default rope gravity vector." );
|
static Vector vecRopeGravity( ROPE_GRAVITY );
|
||||||
|
ScriptRegisterConstantNamed( g_pScriptVM, vecRopeGravity, "ROPE_GRAVITY", "Default rope gravity vector." );
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sounds
|
// Sounds
|
||||||
|
@ -512,7 +512,7 @@ bool CAnimEventTInstanceHelper::Get( void *p, const char *pszKey, ScriptVariant_
|
|||||||
{
|
{
|
||||||
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
||||||
|
|
||||||
animevent_t *ani = ((animevent_t *)p);
|
animevent_t *ani = &((scriptanimevent_t *)p)->event;
|
||||||
if (FStrEq( pszKey, "event" ))
|
if (FStrEq( pszKey, "event" ))
|
||||||
variant = ani->event;
|
variant = ani->event;
|
||||||
else if (FStrEq( pszKey, "options" ))
|
else if (FStrEq( pszKey, "options" ))
|
||||||
@ -535,18 +535,28 @@ bool CAnimEventTInstanceHelper::Set( void *p, const char *pszKey, ScriptVariant_
|
|||||||
{
|
{
|
||||||
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
||||||
|
|
||||||
animevent_t *ani = ((animevent_t *)p);
|
scriptanimevent_t *script_ani = ((scriptanimevent_t *)p);
|
||||||
|
animevent_t *ani = &script_ani->event;
|
||||||
if (FStrEq( pszKey, "event" ))
|
if (FStrEq( pszKey, "event" ))
|
||||||
ani->event = variant;
|
{
|
||||||
|
return variant.AssignTo( &ani->event );
|
||||||
|
}
|
||||||
else if (FStrEq( pszKey, "options" ))
|
else if (FStrEq( pszKey, "options" ))
|
||||||
ani->options = variant;
|
{
|
||||||
|
char *szOptions;
|
||||||
|
if (!variant.AssignTo( &szOptions ))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
script_ani->SetOptions( szOptions );
|
||||||
|
}
|
||||||
else if (FStrEq( pszKey, "cycle" ))
|
else if (FStrEq( pszKey, "cycle" ))
|
||||||
ani->cycle = variant;
|
return variant.AssignTo( &ani->cycle );
|
||||||
else if (FStrEq( pszKey, "eventtime" ))
|
else if (FStrEq( pszKey, "eventtime" ))
|
||||||
ani->eventtime = variant;
|
return variant.AssignTo( &ani->eventtime );
|
||||||
else if (FStrEq( pszKey, "type" ))
|
else if (FStrEq( pszKey, "type" ))
|
||||||
ani->type = variant;
|
return variant.AssignTo( &ani->type );
|
||||||
else if (FStrEq( pszKey, "source" ))
|
else if (FStrEq( pszKey, "source" ) && variant.m_type == FIELD_HSCRIPT)
|
||||||
{
|
{
|
||||||
CBaseEntity *pEnt = ToEnt( variant.m_hScript );
|
CBaseEntity *pEnt = ToEnt( variant.m_hScript );
|
||||||
if (pEnt)
|
if (pEnt)
|
||||||
|
@ -167,30 +167,47 @@ private:
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Exposes animevent_t to VScript
|
// Exposes animevent_t to VScript
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
struct scriptanimevent_t : public animevent_t
|
struct scriptanimevent_t
|
||||||
{
|
{
|
||||||
int GetEvent() { return event; }
|
friend class CAnimEventTInstanceHelper;
|
||||||
void SetEvent( int nEvent ) { event = nEvent; }
|
|
||||||
|
|
||||||
const char *GetOptions() { return options; }
|
public:
|
||||||
void SetOptions( const char *pOptions ) { options = pOptions; }
|
scriptanimevent_t( animevent_t &event ) : event( event ), options( NULL ) { }
|
||||||
|
~scriptanimevent_t( ) { delete[] options; }
|
||||||
|
|
||||||
float GetCycle() { return cycle; }
|
int GetEvent() { return event.event; }
|
||||||
void SetCycle( float flCycle ) { cycle = flCycle; }
|
void SetEvent( int nEvent ) { event.event = nEvent; }
|
||||||
|
|
||||||
float GetEventTime() { return eventtime; }
|
const char *GetOptions() { return event.options; }
|
||||||
void SetEventTime( float flEventTime ) { eventtime = flEventTime; }
|
void SetOptions( const char *pOptions )
|
||||||
|
{
|
||||||
|
size_t len = strlen( pOptions );
|
||||||
|
delete[] options;
|
||||||
|
event.options = options = new char[len + 1];
|
||||||
|
memcpy( options, pOptions, len + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
int GetType() { return type; }
|
float GetCycle() { return event.cycle; }
|
||||||
void SetType( int nType ) { eventtime = type; }
|
void SetCycle( float flCycle ) { event.cycle = flCycle; }
|
||||||
|
|
||||||
HSCRIPT GetSource() { return ToHScript( pSource ); }
|
float GetEventTime() { return event.eventtime; }
|
||||||
|
void SetEventTime( float flEventTime ) { event.eventtime = flEventTime; }
|
||||||
|
|
||||||
|
int GetType() { return event.type; }
|
||||||
|
void SetType( int nType ) { event.type = nType; }
|
||||||
|
|
||||||
|
HSCRIPT GetSource() { return ToHScript( event.pSource ); }
|
||||||
void SetSource( HSCRIPT hSource )
|
void SetSource( HSCRIPT hSource )
|
||||||
{
|
{
|
||||||
CBaseEntity *pEnt = ToEnt( hSource );
|
CBaseEntity *pEnt = ToEnt( hSource );
|
||||||
if (pEnt)
|
if (pEnt)
|
||||||
pSource = pEnt->GetBaseAnimating();
|
event.pSource = pEnt->GetBaseAnimating();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
animevent_t &event;
|
||||||
|
// storage for ScriptVariant_t string, which may be temporary
|
||||||
|
char *options;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAnimEventTInstanceHelper : public IScriptInstanceHelper
|
class CAnimEventTInstanceHelper : public IScriptInstanceHelper
|
||||||
|
@ -37,6 +37,7 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
|||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
// This is to ensure a dependency exists between the vscript library and the game DLLs
|
// This is to ensure a dependency exists between the vscript library and the game DLLs
|
||||||
extern int vscript_token;
|
extern int vscript_token;
|
||||||
|
extern int vscript_debugger_port;
|
||||||
int vscript_token_hack = vscript_token;
|
int vscript_token_hack = vscript_token;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -390,12 +391,30 @@ CON_COMMAND_F( script_debug, "Connect the vscript VM to the script debugger", FC
|
|||||||
if ( !IsCommandIssuedByServerAdmin() )
|
if ( !IsCommandIssuedByServerAdmin() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
#ifdef GAME_DLL
|
||||||
|
int port = 1212;
|
||||||
|
#else
|
||||||
|
int port = 1213;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( !g_pScriptVM )
|
if ( !g_pScriptVM )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
vscript_debugger_port = port;
|
||||||
|
CGMsg( 0, CON_GROUP_VSCRIPT, "VScript VM is not running, waiting for it to attach the debugger to port %d...\n", port );
|
||||||
|
#else
|
||||||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
g_pScriptVM->ConnectDebugger( port );
|
||||||
|
#else
|
||||||
g_pScriptVM->ConnectDebugger();
|
g_pScriptVM->ConnectDebugger();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CLIENT_DLL
|
#ifdef CLIENT_DLL
|
||||||
|
@ -321,7 +321,8 @@ enum ScriptFuncBindingFlags_t
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn );
|
union ScriptVariantTemporaryStorage_t;
|
||||||
|
typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage );
|
||||||
|
|
||||||
struct ScriptFunctionBinding_t
|
struct ScriptFunctionBinding_t
|
||||||
{
|
{
|
||||||
@ -342,11 +343,6 @@ public:
|
|||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
virtual bool Get( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
virtual bool Get( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
||||||
virtual bool Set( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
virtual bool Set( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
||||||
|
|
||||||
virtual ScriptVariant_t *Add( void *p, ScriptVariant_t &variant ) { return NULL; }
|
|
||||||
virtual ScriptVariant_t *Subtract( void *p, ScriptVariant_t &variant ) { return NULL; }
|
|
||||||
virtual ScriptVariant_t *Multiply( void *p, ScriptVariant_t &variant ) { return NULL; }
|
|
||||||
virtual ScriptVariant_t *Divide( void *p, ScriptVariant_t &variant ) { return NULL; }
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -411,13 +407,17 @@ struct ScriptVariant_t
|
|||||||
ScriptVariant_t( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; }
|
ScriptVariant_t( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; }
|
||||||
ScriptVariant_t( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; }
|
ScriptVariant_t( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; }
|
||||||
|
|
||||||
ScriptVariant_t( const Vector &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = &val; } else { m_pVector = new Vector( val ); m_flags |= SV_FREE; } }
|
ScriptVariant_t( const Vector &val ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { m_pVector = &val; }
|
||||||
ScriptVariant_t( const Vector *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = val; } else { m_pVector = new Vector( *val ); m_flags |= SV_FREE; } }
|
ScriptVariant_t( const Vector *val ) : ScriptVariant_t( *val ) { }
|
||||||
ScriptVariant_t( const char *val , bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { if ( !bCopy ) { m_pszString = val; } else { m_pszString = strdup( val ); m_flags |= SV_FREE; } }
|
|
||||||
|
ScriptVariant_t( const char *val ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { m_pszString = val; }
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
ScriptVariant_t( const QAngle &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = &val; } else { m_pAngle = new QAngle( val ); m_flags |= SV_FREE; } }
|
ScriptVariant_t( const QAngle &val ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { m_pAngle = &val; }
|
||||||
ScriptVariant_t( const QAngle *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = val; } else { m_pAngle = new QAngle( *val ); m_flags |= SV_FREE; } }
|
ScriptVariant_t( const QAngle *val ) : ScriptVariant_t( *val ) { }
|
||||||
|
|
||||||
|
ScriptVariant_t( Vector &&val ) = delete;
|
||||||
|
ScriptVariant_t( QAngle &&val ) = delete;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool IsNull() const { return (m_type == FIELD_VOID ); }
|
bool IsNull() const { return (m_type == FIELD_VOID ); }
|
||||||
@ -425,74 +425,41 @@ struct ScriptVariant_t
|
|||||||
operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; }
|
operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; }
|
||||||
operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; }
|
operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; }
|
||||||
operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; }
|
operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; }
|
||||||
operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; }
|
operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); return (m_pVector) ? *m_pVector : vec3_origin; }
|
||||||
operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; }
|
operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; }
|
||||||
operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; }
|
operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; }
|
||||||
operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; }
|
operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; }
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
operator const QAngle &() const { Assert( m_type == FIELD_VECTOR ); static QAngle vecNull(0, 0, 0); return (m_pAngle) ? *m_pAngle : vecNull; }
|
operator const QAngle &() const { Assert( m_type == FIELD_VECTOR ); return (m_pAngle) ? *m_pAngle : vec3_angle; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; }
|
void operator=( int i ) { m_type = FIELD_INTEGER; m_flags = 0; m_int = i; }
|
||||||
void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; }
|
void operator=( float f ) { m_type = FIELD_FLOAT; m_flags = 0; m_float = f; }
|
||||||
void operator=( double f ) { m_type = FIELD_FLOAT; m_float = (float)f; }
|
void operator=( double f ) { m_type = FIELD_FLOAT; m_flags = 0; m_float = (float)f; }
|
||||||
void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_pVector = &vec; }
|
void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_flags = 0; m_pVector = &vec; }
|
||||||
void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; }
|
void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_flags = 0; m_pVector = vec; }
|
||||||
void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; }
|
void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_flags = 0; m_pszString = psz; }
|
||||||
void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; }
|
void operator=( char c ) { m_type = FIELD_CHARACTER; m_flags = 0; m_char = c; }
|
||||||
void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; }
|
void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_flags = 0; m_bool = b; }
|
||||||
void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; }
|
void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_flags = 0; m_hScript = h; }
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
void operator=( const QAngle &vec ) { m_type = FIELD_VECTOR; m_pAngle = &vec; }
|
void operator=( const QAngle &ang ) { m_type = FIELD_VECTOR; m_flags = 0; m_pAngle = ∠ }
|
||||||
void operator=( const QAngle *vec ) { m_type = FIELD_VECTOR; m_pAngle = vec; }
|
void operator=( const QAngle *ang ) { m_type = FIELD_VECTOR; m_flags = 0; m_pAngle = ang; }
|
||||||
|
|
||||||
|
void operator=( Vector &&vec ) = delete;
|
||||||
|
void operator=( QAngle &&ang ) = delete;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Free() { if ( ( m_flags & SV_FREE ) && ( m_type == FIELD_HSCRIPT || m_type == FIELD_VECTOR || m_type == FIELD_CSTRING ) ) delete m_pszString; } // Generally only needed for return results
|
void Free()
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T Get()
|
|
||||||
{
|
{
|
||||||
T value;
|
// Generally only needed for return results
|
||||||
AssignTo( &value );
|
if ( ! ( m_flags & SV_FREE ) )
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool AssignTo( T *pDest )
|
|
||||||
{
|
|
||||||
ScriptDataType_t destType = ScriptDeduceType( T );
|
|
||||||
if ( destType == FIELD_TYPEUNKNOWN )
|
|
||||||
{
|
{
|
||||||
DevWarning( "Unable to convert script variant to unknown type\n" );
|
return;
|
||||||
}
|
|
||||||
if ( destType == m_type )
|
|
||||||
{
|
|
||||||
*pDest = *this;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_type != FIELD_VECTOR && m_type != FIELD_CSTRING && destType != FIELD_VECTOR && destType != FIELD_CSTRING )
|
AssertMsg( m_type == FIELD_CSTRING || m_type == FIELD_VECTOR, "Don't know how to free script variant of type %d", m_type );
|
||||||
{
|
free( (void*)m_pszString );
|
||||||
switch ( m_type )
|
|
||||||
{
|
|
||||||
case FIELD_VOID: *pDest = 0; break;
|
|
||||||
case FIELD_INTEGER: *pDest = m_int; return true;
|
|
||||||
case FIELD_FLOAT: *pDest = m_float; return true;
|
|
||||||
case FIELD_CHARACTER: *pDest = m_char; return true;
|
|
||||||
case FIELD_BOOLEAN: *pDest = m_bool; return true;
|
|
||||||
case FIELD_HSCRIPT: *pDest = m_hScript; return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DevWarning( "No free conversion of %s script variant to %s right now\n",
|
|
||||||
ScriptFieldTypeName( m_type ), ScriptFieldTypeName<T>() );
|
|
||||||
if ( destType != FIELD_VECTOR )
|
|
||||||
{
|
|
||||||
*pDest = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssignTo( float *pDest )
|
bool AssignTo( float *pDest )
|
||||||
@ -547,25 +514,38 @@ struct ScriptVariant_t
|
|||||||
|
|
||||||
bool AssignTo( ScriptVariant_t *pDest )
|
bool AssignTo( ScriptVariant_t *pDest )
|
||||||
{
|
{
|
||||||
|
pDest->Free();
|
||||||
pDest->m_type = m_type;
|
pDest->m_type = m_type;
|
||||||
if ( m_type == FIELD_VECTOR )
|
if ( m_flags & SV_FREE )
|
||||||
{
|
{
|
||||||
pDest->m_pVector = new Vector;
|
if ( m_type == FIELD_VECTOR )
|
||||||
((Vector *)(pDest->m_pVector))->Init( m_pVector->x, m_pVector->y, m_pVector->z );
|
{
|
||||||
pDest->m_flags |= SV_FREE;
|
pDest->m_pVector = (Vector*)malloc( sizeof( Vector ) );
|
||||||
}
|
pDest->EmplaceAllocedVector( *m_pVector );
|
||||||
else if ( m_type == FIELD_CSTRING )
|
m_flags |= SV_FREE;
|
||||||
{
|
}
|
||||||
pDest->m_pszString = strdup( m_pszString );
|
else if ( m_type == FIELD_CSTRING )
|
||||||
pDest->m_flags |= SV_FREE;
|
{
|
||||||
|
pDest->m_pszString = strdup( m_pszString );
|
||||||
|
pDest->m_flags |= SV_FREE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert( false );
|
||||||
|
pDest->m_int = m_int;
|
||||||
|
pDest->m_flags &= ~SV_FREE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pDest->m_int = m_int;
|
pDest->m_int = m_int;
|
||||||
|
pDest->m_flags &= ~SV_FREE;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmplaceAllocedVector( const Vector &vec );
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
int m_int;
|
int m_int;
|
||||||
@ -587,8 +567,25 @@ struct ScriptVariant_t
|
|||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "tier0/memdbgoff.h"
|
||||||
|
inline void ScriptVariant_t::EmplaceAllocedVector( const Vector &vec )
|
||||||
|
{
|
||||||
|
new ( (Vector*)m_pVector ) Vector( vec );
|
||||||
|
}
|
||||||
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
#define SCRIPT_VARIANT_NULL ScriptVariant_t()
|
#define SCRIPT_VARIANT_NULL ScriptVariant_t()
|
||||||
|
|
||||||
|
union ScriptVariantTemporaryStorage_t
|
||||||
|
{
|
||||||
|
// members must be initialized via placement-new
|
||||||
|
ScriptVariantTemporaryStorage_t() { }
|
||||||
|
|
||||||
|
// members must have trivial destructor, since no destructor will be invoked
|
||||||
|
Vector m_vec;
|
||||||
|
QAngle m_ang;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef MAPBASE_VSCRIPT
|
#ifdef MAPBASE_VSCRIPT
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
struct ScriptConstantBinding_t
|
struct ScriptConstantBinding_t
|
||||||
@ -690,7 +687,7 @@ static inline int ToConstantVariant(int value)
|
|||||||
// This is used for registering variants (particularly vectors) not tied to existing variables.
|
// This is used for registering variants (particularly vectors) not tied to existing variables.
|
||||||
// The principal difference is that m_data is initted with bCopy set to true.
|
// The principal difference is that m_data is initted with bCopy set to true.
|
||||||
#define ScriptRegisterConstantFromTemp( pVM, constant, description ) ScriptRegisterConstantFromTempNamed( pVM, constant, #constant, description )
|
#define ScriptRegisterConstantFromTemp( pVM, constant, description ) ScriptRegisterConstantFromTempNamed( pVM, constant, #constant, description )
|
||||||
#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constant, true ); pVM->RegisterConstant( &binding ); } while (0)
|
#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static const auto constantStorage = constant; static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constantStorage ); pVM->RegisterConstant( &binding ); } while (0)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@ -884,7 +881,11 @@ public:
|
|||||||
virtual bool Init() = 0;
|
virtual bool Init() = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
|
#ifdef MAPBASE_VSCRIPT
|
||||||
|
virtual bool ConnectDebugger( int port = 0 ) = 0;
|
||||||
|
#else
|
||||||
virtual bool ConnectDebugger() = 0;
|
virtual bool ConnectDebugger() = 0;
|
||||||
|
#endif
|
||||||
virtual void DisconnectDebugger() = 0;
|
virtual void DisconnectDebugger() = 0;
|
||||||
|
|
||||||
virtual ScriptLanguage_t GetLanguage() = 0;
|
virtual ScriptLanguage_t GetLanguage() = 0;
|
||||||
|
@ -326,8 +326,8 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
class CNonMemberScriptBinding##N \
|
class CNonMemberScriptBinding##N \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
{ \
|
{ \
|
||||||
Assert( nArguments == N ); \
|
Assert( nArguments == N ); \
|
||||||
Assert( pReturn ); \
|
Assert( pReturn ); \
|
||||||
Assert( !pContext ); \
|
Assert( !pContext ); \
|
||||||
@ -337,17 +337,15 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
*pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \
|
*pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \
|
||||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
return true; \
|
||||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
} \
|
||||||
return true; \
|
|
||||||
} \
|
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
class CNonMemberScriptBinding##N<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
class CNonMemberScriptBinding##N<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
{ \
|
{ \
|
||||||
Assert( nArguments == N ); \
|
Assert( nArguments == N ); \
|
||||||
Assert( !pReturn ); \
|
Assert( !pReturn ); \
|
||||||
@ -362,12 +360,52 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
|
class CNonMemberScriptBinding##N<FUNC_TYPE, Vector FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
|
{ \
|
||||||
|
Assert( nArguments == N ); \
|
||||||
|
Assert( pReturn ); \
|
||||||
|
Assert( !pContext ); \
|
||||||
|
\
|
||||||
|
if ( nArguments != N || !pReturn || pContext ) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
new ( &temporaryReturnStorage.m_vec ) Vector( ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||||
|
*pReturn = temporaryReturnStorage.m_vec; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
|
class CNonMemberScriptBinding##N<FUNC_TYPE, QAngle FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
|
{ \
|
||||||
|
Assert( nArguments == N ); \
|
||||||
|
Assert( pReturn ); \
|
||||||
|
Assert( !pContext ); \
|
||||||
|
\
|
||||||
|
if ( nArguments != N || !pReturn || pContext ) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
new ( &temporaryReturnStorage.m_ang ) QAngle( ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||||
|
*pReturn = temporaryReturnStorage.m_ang; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
class CMemberScriptBinding##N \
|
class CMemberScriptBinding##N \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
{ \
|
{ \
|
||||||
Assert( nArguments == N ); \
|
Assert( nArguments == N ); \
|
||||||
Assert( pReturn ); \
|
Assert( pReturn ); \
|
||||||
Assert( pContext ); \
|
Assert( pContext ); \
|
||||||
@ -377,17 +415,15 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
*pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
|
*pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
|
||||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
return true; \
|
||||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
} \
|
||||||
return true; \
|
|
||||||
} \
|
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
{ \
|
{ \
|
||||||
public: \
|
public: \
|
||||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
{ \
|
{ \
|
||||||
Assert( nArguments == N ); \
|
Assert( nArguments == N ); \
|
||||||
Assert( !pReturn ); \
|
Assert( !pReturn ); \
|
||||||
@ -402,6 +438,46 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
} \
|
} \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
|
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
|
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, Vector FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
|
{ \
|
||||||
|
Assert( nArguments == N ); \
|
||||||
|
Assert( pReturn ); \
|
||||||
|
Assert( pContext ); \
|
||||||
|
\
|
||||||
|
if ( nArguments != N || !pReturn || !pContext ) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
new ( &temporaryReturnStorage.m_vec ) Vector( (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||||
|
*pReturn = temporaryReturnStorage.m_vec; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
|
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, QAngle FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||||
|
{ \
|
||||||
|
Assert( nArguments == N ); \
|
||||||
|
Assert( pReturn ); \
|
||||||
|
Assert( pContext ); \
|
||||||
|
\
|
||||||
|
if ( nArguments != N || !pReturn || !pContext ) \
|
||||||
|
{ \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
new ( &temporaryReturnStorage.m_ang ) QAngle( (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||||
|
*pReturn = temporaryReturnStorage.m_ang; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||||
inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||||
{ \
|
{ \
|
||||||
@ -423,7 +499,11 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
|||||||
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//note: no memory is actually allocated in the functions that get defined,
|
||||||
|
// it merely uses placement-new for which we need to disable this
|
||||||
|
#include "tier0/memdbgoff.h"
|
||||||
FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS );
|
FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS );
|
||||||
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -2471,6 +2471,15 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail )
|
|||||||
{
|
{
|
||||||
do_fast = true;
|
do_fast = true;
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else if(!Q_stricmp(argv[i], "-ultrafast"))
|
||||||
|
{
|
||||||
|
do_fast = true;
|
||||||
|
g_bFastAmbient = true;
|
||||||
|
do_extra = false;
|
||||||
|
numbounce = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (!Q_stricmp(argv[i],"-noskyboxrecurse"))
|
else if (!Q_stricmp(argv[i],"-noskyboxrecurse"))
|
||||||
{
|
{
|
||||||
g_bNoSkyRecurse = true;
|
g_bNoSkyRecurse = true;
|
||||||
@ -2777,6 +2786,9 @@ void PrintUsage( int argc, char **argv )
|
|||||||
" -v (or -verbose): Turn on verbose output (also shows more command\n"
|
" -v (or -verbose): Turn on verbose output (also shows more command\n"
|
||||||
" -bounce # : Set max number of bounces (default: 100).\n"
|
" -bounce # : Set max number of bounces (default: 100).\n"
|
||||||
" -fast : Quick and dirty lighting.\n"
|
" -fast : Quick and dirty lighting.\n"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
" -ultrafast : Very quick and dirty lighting, same as -fast -fastambient -noextra -bounce 1\n"
|
||||||
|
#endif
|
||||||
" -fastambient : Per-leaf ambient sampling is lower quality to save compute time.\n"
|
" -fastambient : Per-leaf ambient sampling is lower quality to save compute time.\n"
|
||||||
" -final : High quality processing. equivalent to -extrasky 16.\n"
|
" -final : High quality processing. equivalent to -extrasky 16.\n"
|
||||||
" -extrasky n : trace N times as many rays for indirect light and sky ambient.\n"
|
" -extrasky n : trace N times as many rays for indirect light and sky ambient.\n"
|
||||||
|
@ -847,34 +847,40 @@ void RichText::Paint()
|
|||||||
|
|
||||||
// 3.
|
// 3.
|
||||||
// Calculate the range of text to draw all at once
|
// Calculate the range of text to draw all at once
|
||||||
int iLim = m_TextStream.Count();
|
int iLim = m_TextStream.Count() - 1;
|
||||||
|
|
||||||
|
// Stop at the next line break
|
||||||
|
if ( m_LineBreaks.IsValidIndex( lineBreakIndexIndex ) && m_LineBreaks[lineBreakIndexIndex] <= iLim )
|
||||||
|
iLim = m_LineBreaks[lineBreakIndexIndex] - 1;
|
||||||
|
|
||||||
// Stop at the next format change
|
// Stop at the next format change
|
||||||
if ( m_FormatStream.IsValidIndex(renderState.formatStreamIndex) &&
|
if ( m_FormatStream.IsValidIndex(renderState.formatStreamIndex) &&
|
||||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex < iLim &&
|
m_FormatStream[renderState.formatStreamIndex].textStreamIndex <= iLim &&
|
||||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex >= i &&
|
m_FormatStream[renderState.formatStreamIndex].textStreamIndex >= i &&
|
||||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex )
|
m_FormatStream[renderState.formatStreamIndex].textStreamIndex )
|
||||||
{
|
{
|
||||||
iLim = m_FormatStream[renderState.formatStreamIndex].textStreamIndex;
|
iLim = m_FormatStream[renderState.formatStreamIndex].textStreamIndex - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop at the next line break
|
// Stop when entering or exiting the selected range
|
||||||
if ( m_LineBreaks.IsValidIndex( lineBreakIndexIndex ) && m_LineBreaks[lineBreakIndexIndex] < iLim )
|
if ( i < selection0 && iLim >= selection0 )
|
||||||
iLim = m_LineBreaks[lineBreakIndexIndex];
|
iLim = selection0 - 1;
|
||||||
|
if ( i >= selection0 && i < selection1 && iLim >= selection1 )
|
||||||
|
iLim = selection1 - 1;
|
||||||
|
|
||||||
// Handle non-drawing characters specially
|
// Handle non-drawing characters specially
|
||||||
for ( int iT = i; iT < iLim; iT++ )
|
for ( int iT = i; iT <= iLim; iT++ )
|
||||||
{
|
{
|
||||||
if ( iswcntrl(m_TextStream[iT]) )
|
if ( iswcntrl(m_TextStream[iT]) )
|
||||||
{
|
{
|
||||||
iLim = iT;
|
iLim = iT - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4.
|
// 4.
|
||||||
// Draw the current text range
|
// Draw the current text range
|
||||||
if ( iLim <= i )
|
if ( iLim < i )
|
||||||
{
|
{
|
||||||
if ( m_TextStream[i] == '\t' )
|
if ( m_TextStream[i] == '\t' )
|
||||||
{
|
{
|
||||||
@ -887,8 +893,8 @@ void RichText::Paint()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
renderState.x += DrawString(i, iLim - 1, renderState, hFontCurrent );
|
renderState.x += DrawString(i, iLim, renderState, hFontCurrent );
|
||||||
i = iLim;
|
i = iLim + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
70
sp/src/vscript/sqdbg/include/sqdbg.h
Normal file
70
sp/src/vscript/sqdbg/include/sqdbg.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// github.com/samisalreadytaken/sqdbg
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Squirrel Debugger
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SQDBG_H
|
||||||
|
#define SQDBG_H
|
||||||
|
|
||||||
|
#include <squirrel.h>
|
||||||
|
|
||||||
|
#define SQDBG_SV_API_VER 1
|
||||||
|
|
||||||
|
#ifndef SQDBG_API
|
||||||
|
#ifdef SQDBG_DLL
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#ifdef SQDBG_DLL_EXPORT
|
||||||
|
#define SQDBG_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define SQDBG_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#ifdef SQDBG_DLL_EXPORT
|
||||||
|
#define SQDBG_API __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define SQDBG_API extern
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SQDBG_API extern
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SQDBG_API extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct SQDebugServer;
|
||||||
|
typedef SQDebugServer* HSQDEBUGSERVER;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create and attach a new debugger
|
||||||
|
// Memory is owned by the VM, it is freed when the VM dies or
|
||||||
|
// the debugger is disconnected via sqdbg_destroy_debugger()
|
||||||
|
SQDBG_API HSQDEBUGSERVER sqdbg_attach_debugger( HSQUIRRELVM vm );
|
||||||
|
|
||||||
|
// Detach and destroy the debugger attached to this VM
|
||||||
|
// Invalidates the handle returned from sqdbg_attach_debugger()
|
||||||
|
SQDBG_API void sqdbg_destroy_debugger( HSQUIRRELVM vm );
|
||||||
|
|
||||||
|
// Open specified port and allow client connections
|
||||||
|
// If port is 0, the system will choose a unique available port
|
||||||
|
// Returns 0 on success
|
||||||
|
SQDBG_API int sqdbg_listen_socket( HSQDEBUGSERVER dbg, unsigned short port );
|
||||||
|
|
||||||
|
// Process client connections and incoming messages
|
||||||
|
// Blocks on script breakpoints while a client is connected
|
||||||
|
SQDBG_API void sqdbg_frame( HSQDEBUGSERVER dbg );
|
||||||
|
|
||||||
|
// Copies the script to be able to source it to debugger clients
|
||||||
|
SQDBG_API void sqdbg_on_script_compile( HSQDEBUGSERVER dbg, const SQChar *script, SQInteger size,
|
||||||
|
const SQChar *sourcename, SQInteger sourcenamelen );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SQDBG_H
|
131
sp/src/vscript/sqdbg/sqdbg/debug.h
Normal file
131
sp/src/vscript/sqdbg/sqdbg/debug.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// github.com/samisalreadytaken/sqdbg
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SQDBG_DEBUG_H
|
||||||
|
#define SQDBG_DEBUG_H
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <crtdbg.h>
|
||||||
|
|
||||||
|
bool __IsDebuggerPresent();
|
||||||
|
const char *GetModuleBaseName();
|
||||||
|
|
||||||
|
#define DebuggerBreak() do { if ( __IsDebuggerPresent() ) __debugbreak(); } while(0)
|
||||||
|
|
||||||
|
#define Assert( x ) \
|
||||||
|
do { \
|
||||||
|
__CAT( L, __LINE__ ): \
|
||||||
|
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), #x)) ) \
|
||||||
|
{ \
|
||||||
|
if ( !__IsDebuggerPresent() ) \
|
||||||
|
goto __CAT( L, __LINE__ ); \
|
||||||
|
__debugbreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg( x, msg ) \
|
||||||
|
do { \
|
||||||
|
__CAT( L, __LINE__ ): \
|
||||||
|
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg)) ) \
|
||||||
|
{ \
|
||||||
|
if ( !__IsDebuggerPresent() ) \
|
||||||
|
goto __CAT( L, __LINE__ ); \
|
||||||
|
__debugbreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg1( x, msg, a1 ) \
|
||||||
|
do { \
|
||||||
|
__CAT( L, __LINE__ ): \
|
||||||
|
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg, a1)) ) \
|
||||||
|
{ \
|
||||||
|
if ( !__IsDebuggerPresent() ) \
|
||||||
|
goto __CAT( L, __LINE__ ); \
|
||||||
|
__debugbreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg2( x, msg, a1, a2 ) \
|
||||||
|
do { \
|
||||||
|
__CAT( L, __LINE__ ): \
|
||||||
|
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg, a1, a2)) ) \
|
||||||
|
{ \
|
||||||
|
if ( !__IsDebuggerPresent() ) \
|
||||||
|
goto __CAT( L, __LINE__ ); \
|
||||||
|
__debugbreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
|
extern "C" int printf(const char *, ...);
|
||||||
|
|
||||||
|
#define DebuggerBreak() asm("int3")
|
||||||
|
|
||||||
|
#define Assert( x ) \
|
||||||
|
do { \
|
||||||
|
if ( !(x) ) \
|
||||||
|
{ \
|
||||||
|
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, #x); \
|
||||||
|
DebuggerBreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg( x, msg ) \
|
||||||
|
do { \
|
||||||
|
if ( !(x) ) \
|
||||||
|
{ \
|
||||||
|
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, msg); \
|
||||||
|
DebuggerBreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg1( x, msg, a1 ) \
|
||||||
|
do { \
|
||||||
|
if ( !(x) ) \
|
||||||
|
{ \
|
||||||
|
::printf("Assertion failed %s:%d: ", __FILE__, __LINE__); \
|
||||||
|
::printf(msg, a1); \
|
||||||
|
::printf("\n"); \
|
||||||
|
DebuggerBreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define AssertMsg2( x, msg, a1, a2 ) \
|
||||||
|
do { \
|
||||||
|
if ( !(x) ) \
|
||||||
|
{ \
|
||||||
|
::printf("Assertion failed %s:%d: ", __FILE__, __LINE__); \
|
||||||
|
::printf(msg, a1, a2); \
|
||||||
|
::printf("\n"); \
|
||||||
|
DebuggerBreak(); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
#endif
|
||||||
|
#define Verify( x ) Assert(x)
|
||||||
|
#else
|
||||||
|
#define DebuggerBreak() ((void)0)
|
||||||
|
#define Assert( x ) ((void)0)
|
||||||
|
#define AssertMsg( x, msg ) ((void)0)
|
||||||
|
#define AssertMsg1( x, msg, a1 ) ((void)0)
|
||||||
|
#define AssertMsg2( x, msg, a1, a2 ) ((void)0)
|
||||||
|
#define Verify( x ) x
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <tier0/dbg.h>
|
||||||
|
|
||||||
|
// Misdefined for GCC in platform.h
|
||||||
|
#undef UNREACHABLE
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __assume(0); } while(0)
|
||||||
|
#else
|
||||||
|
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __builtin_unreachable(); } while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SQDBG_DEBUG_H
|
1200
sp/src/vscript/sqdbg/sqdbg/json.h
Normal file
1200
sp/src/vscript/sqdbg/sqdbg/json.h
Normal file
File diff suppressed because it is too large
Load Diff
846
sp/src/vscript/sqdbg/sqdbg/net.h
Normal file
846
sp/src/vscript/sqdbg/sqdbg/net.h
Normal file
@ -0,0 +1,846 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// github.com/samisalreadytaken/sqdbg
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SQDBG_NET_H
|
||||||
|
#define SQDBG_NET_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <WS2tcpip.h>
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#include <debugapi.h>
|
||||||
|
|
||||||
|
inline bool __IsDebuggerPresent()
|
||||||
|
{
|
||||||
|
return IsDebuggerPresent();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *GetModuleBaseName()
|
||||||
|
{
|
||||||
|
static char module[MAX_PATH];
|
||||||
|
int len = GetModuleFileNameA( NULL, module, sizeof(module) );
|
||||||
|
|
||||||
|
if ( len != 0 )
|
||||||
|
{
|
||||||
|
for ( char *pBase = module + len; pBase-- > module; )
|
||||||
|
{
|
||||||
|
if ( *pBase == '\\' )
|
||||||
|
return pBase + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma comment(lib, "Ws2_32.lib")
|
||||||
|
|
||||||
|
#undef RegisterClass
|
||||||
|
#undef SendMessage
|
||||||
|
#undef Yield
|
||||||
|
#undef CONST
|
||||||
|
#undef PURE
|
||||||
|
|
||||||
|
#undef errno
|
||||||
|
#define errno WSAGetLastError()
|
||||||
|
#define strerr(e) gai_strerror(e)
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define closesocket close
|
||||||
|
#define ioctlsocket ioctl
|
||||||
|
#define strerr(e) strerror(e)
|
||||||
|
|
||||||
|
typedef int SOCKET;
|
||||||
|
#define INVALID_SOCKET -1
|
||||||
|
#define SOCKET_ERROR -1
|
||||||
|
#define SD_BOTH SHUT_RDWR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
class CEntryCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int *count;
|
||||||
|
CEntryCounter( int *p ) : count(p) { (*count)++; }
|
||||||
|
~CEntryCounter() { (*count)--; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TRACK_ENTRIES() \
|
||||||
|
static int s_EntryCount = 0; \
|
||||||
|
CEntryCounter entrycounter( &s_EntryCount );
|
||||||
|
#else
|
||||||
|
#define TRACK_ENTRIES()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *sqdbg_malloc( unsigned int size );
|
||||||
|
void *sqdbg_realloc( void *p, unsigned int oldsize, unsigned int size );
|
||||||
|
void sqdbg_free( void *p, unsigned int size );
|
||||||
|
|
||||||
|
#ifndef SQDBG_NET_BUF_SIZE
|
||||||
|
#define SQDBG_NET_BUF_SIZE ( 16 * 1024 )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CMessagePool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int index_t;
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
struct message_t
|
||||||
|
{
|
||||||
|
index_t next;
|
||||||
|
index_t prev;
|
||||||
|
unsigned short len;
|
||||||
|
char ptr[1];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct chunk_t
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const index_t INVALID_INDEX = 0x80000000;
|
||||||
|
|
||||||
|
// Message queue is going to be less than 16 unless
|
||||||
|
// there is many variable evaluations at once or network lag
|
||||||
|
static const int MEM_CACHE_CHUNKS_ALIGN = 16;
|
||||||
|
|
||||||
|
// Most messages are going to be less than 256 bytes,
|
||||||
|
// only exceeding it on long file paths and long evaluate strings
|
||||||
|
static const int MEM_CACHE_CHUNKSIZE = 256;
|
||||||
|
|
||||||
|
message_t *Get( index_t index )
|
||||||
|
{
|
||||||
|
Assert( index != INVALID_INDEX );
|
||||||
|
|
||||||
|
int msgIdx = index & 0x0000ffff;
|
||||||
|
int chunkIdx = index >> 16;
|
||||||
|
|
||||||
|
Assert( m_Memory );
|
||||||
|
Assert( chunkIdx < m_MemChunkCount );
|
||||||
|
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
Assert( msgIdx < chunk->count );
|
||||||
|
|
||||||
|
return (message_t*)&chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_t *m_Memory;
|
||||||
|
int m_MemChunkCount;
|
||||||
|
int m_ElemCount;
|
||||||
|
|
||||||
|
index_t m_Head;
|
||||||
|
index_t m_Tail;
|
||||||
|
|
||||||
|
index_t NewMessage( char *pcsMsg, int nLength )
|
||||||
|
{
|
||||||
|
if ( !m_Memory )
|
||||||
|
{
|
||||||
|
m_Memory = (chunk_t*)sqdbg_malloc( m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
memset( (char*)m_Memory, 0, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
|
||||||
|
chunk_t *chunk = &m_Memory[0];
|
||||||
|
chunk->count = MEM_CACHE_CHUNKS_ALIGN;
|
||||||
|
chunk->ptr = (char*)sqdbg_malloc( chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
AssertOOM( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
memset( chunk->ptr, 0, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
int requiredChunks = ( sizeof(message_t) + nLength - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
int matchedChunks = 0;
|
||||||
|
int msgIdx = 0;
|
||||||
|
int chunkIdx = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
Assert( chunk->count && chunk->ptr );
|
||||||
|
|
||||||
|
message_t *msg = (message_t*)&chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
|
||||||
|
if ( msg->len == 0 )
|
||||||
|
{
|
||||||
|
if ( ++matchedChunks == requiredChunks )
|
||||||
|
{
|
||||||
|
msgIdx = msgIdx - matchedChunks + 1;
|
||||||
|
msg = (message_t*)&chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
|
||||||
|
Assert( nLength >= 0 );
|
||||||
|
Assert( nLength < ( 1 << ( sizeof(message_t::len) * 8 ) ) );
|
||||||
|
|
||||||
|
msg->next = msg->prev = INVALID_INDEX;
|
||||||
|
msg->len = (unsigned short)nLength;
|
||||||
|
memcpy( msg->ptr, pcsMsg, nLength );
|
||||||
|
|
||||||
|
return ( chunkIdx << 16 ) | msgIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchedChunks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgIdx += ( sizeof(message_t) + msg->len - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
|
||||||
|
Assert( msgIdx < 0x0000ffff );
|
||||||
|
|
||||||
|
if ( msgIdx < chunk->count )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
msgIdx = 0;
|
||||||
|
matchedChunks = 0;
|
||||||
|
|
||||||
|
if ( ++chunkIdx >= m_MemChunkCount )
|
||||||
|
{
|
||||||
|
int oldcount = m_MemChunkCount;
|
||||||
|
m_MemChunkCount += 4;
|
||||||
|
m_Memory = (chunk_t*)sqdbg_realloc( m_Memory,
|
||||||
|
oldcount * sizeof(chunk_t),
|
||||||
|
m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
memset( (char*)m_Memory + oldcount * sizeof(chunk_t),
|
||||||
|
0,
|
||||||
|
(m_MemChunkCount - oldcount) * sizeof(chunk_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count == 0 )
|
||||||
|
{
|
||||||
|
Assert( chunk->ptr == NULL );
|
||||||
|
|
||||||
|
chunk->count = ( requiredChunks + ( MEM_CACHE_CHUNKS_ALIGN - 1 ) ) & ~( MEM_CACHE_CHUNKS_ALIGN - 1 );
|
||||||
|
chunk->ptr = (char*)sqdbg_malloc( chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
AssertOOM( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
memset( chunk->ptr, 0, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( chunkIdx < 0x00007fff );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteMessage( message_t *pMsg )
|
||||||
|
{
|
||||||
|
if ( pMsg->len == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Assert( pMsg->len > 0 );
|
||||||
|
Assert( m_ElemCount > 0 );
|
||||||
|
m_ElemCount--;
|
||||||
|
|
||||||
|
int msgIdx = ( ( sizeof(message_t) + pMsg->len +
|
||||||
|
( MEM_CACHE_CHUNKSIZE - 1 ) ) & ~( MEM_CACHE_CHUNKSIZE - 1 ) ) / MEM_CACHE_CHUNKSIZE;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pMsg->next = pMsg->prev = INVALID_INDEX;
|
||||||
|
pMsg->len = 0;
|
||||||
|
pMsg->ptr[0] = 0;
|
||||||
|
|
||||||
|
pMsg = (message_t*)( (char*)pMsg + MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
while ( --msgIdx > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
CMessagePool() :
|
||||||
|
m_Memory( NULL ),
|
||||||
|
m_MemChunkCount( 4 ),
|
||||||
|
m_ElemCount( 0 ),
|
||||||
|
m_Head( INVALID_INDEX ),
|
||||||
|
m_Tail( INVALID_INDEX )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~CMessagePool()
|
||||||
|
{
|
||||||
|
if ( m_Memory )
|
||||||
|
{
|
||||||
|
for ( int chunkIdx = 0; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
for ( int msgIdx = 0; msgIdx < chunk->count; )
|
||||||
|
{
|
||||||
|
message_t *msg = (message_t*)&chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
Assert( msg->len == 0 && msg->ptr[0] == 0 );
|
||||||
|
msgIdx += ( sizeof(message_t) + msg->len - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
DeleteMessage( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
sqdbg_free( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
sqdbg_free( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( m_ElemCount == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shrink()
|
||||||
|
{
|
||||||
|
Assert( m_ElemCount == 0 );
|
||||||
|
|
||||||
|
if ( !m_Memory )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( int chunkIdx = 1; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count )
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
for ( int msgIdx = 0; msgIdx < chunk->count; )
|
||||||
|
{
|
||||||
|
message_t *msg = (message_t*)&chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
Assert( msg->len == 0 && msg->ptr[0] == 0 );
|
||||||
|
msgIdx += ( sizeof(message_t) + msg->len - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
sqdbg_free( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
|
||||||
|
chunk->count = 0;
|
||||||
|
chunk->ptr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_MemChunkCount > 4 )
|
||||||
|
{
|
||||||
|
int oldcount = m_MemChunkCount;
|
||||||
|
m_MemChunkCount = 4;
|
||||||
|
m_Memory = (chunk_t*)sqdbg_realloc( m_Memory,
|
||||||
|
oldcount * sizeof(chunk_t),
|
||||||
|
m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add( char *pcsMsg, int nLength )
|
||||||
|
{
|
||||||
|
index_t newMsg = NewMessage( pcsMsg, nLength );
|
||||||
|
|
||||||
|
m_ElemCount++;
|
||||||
|
|
||||||
|
// Add to tail
|
||||||
|
if ( m_Tail == INVALID_INDEX )
|
||||||
|
{
|
||||||
|
Assert( m_Head == INVALID_INDEX );
|
||||||
|
m_Head = m_Tail = newMsg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Get(newMsg)->prev = m_Tail;
|
||||||
|
Get(m_Tail)->next = newMsg;
|
||||||
|
m_Tail = newMsg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T, void (T::*callback)( char *ptr, int len ) >
|
||||||
|
void Service( T *ctx )
|
||||||
|
{
|
||||||
|
TRACK_ENTRIES();
|
||||||
|
|
||||||
|
index_t msg = m_Head;
|
||||||
|
|
||||||
|
while ( msg != INVALID_INDEX )
|
||||||
|
{
|
||||||
|
message_t *pMsg = Get(msg);
|
||||||
|
|
||||||
|
Assert( pMsg->len || ( pMsg->next == INVALID_INDEX && pMsg->prev == INVALID_INDEX ) );
|
||||||
|
|
||||||
|
if ( pMsg->len == 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Advance before execution
|
||||||
|
index_t next = pMsg->next;
|
||||||
|
index_t prev = pMsg->prev;
|
||||||
|
|
||||||
|
pMsg->next = INVALID_INDEX;
|
||||||
|
pMsg->prev = INVALID_INDEX;
|
||||||
|
|
||||||
|
if ( prev != INVALID_INDEX )
|
||||||
|
Get(prev)->next = next;
|
||||||
|
|
||||||
|
if ( next != INVALID_INDEX )
|
||||||
|
Get(next)->prev = prev;
|
||||||
|
|
||||||
|
if ( msg == m_Head )
|
||||||
|
{
|
||||||
|
// prev could be non-null on re-entry
|
||||||
|
//Assert( prev == INVALID_INDEX );
|
||||||
|
m_Head = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( msg == m_Tail )
|
||||||
|
{
|
||||||
|
Assert( next == INVALID_INDEX && prev == INVALID_INDEX );
|
||||||
|
m_Tail = INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
(ctx->*callback)( pMsg->ptr, pMsg->len );
|
||||||
|
|
||||||
|
Assert( Get(msg) == pMsg );
|
||||||
|
|
||||||
|
DeleteMessage( pMsg );
|
||||||
|
msg = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
index_t msg = m_Head;
|
||||||
|
|
||||||
|
while ( msg != INVALID_INDEX )
|
||||||
|
{
|
||||||
|
message_t *pMsg = Get(msg);
|
||||||
|
|
||||||
|
index_t next = pMsg->next;
|
||||||
|
index_t prev = pMsg->prev;
|
||||||
|
|
||||||
|
if ( prev != INVALID_INDEX )
|
||||||
|
Get(prev)->next = next;
|
||||||
|
|
||||||
|
if ( next != INVALID_INDEX )
|
||||||
|
Get(next)->prev = prev;
|
||||||
|
|
||||||
|
if ( msg == m_Head )
|
||||||
|
{
|
||||||
|
Assert( prev == INVALID_INDEX );
|
||||||
|
m_Head = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( msg == m_Tail )
|
||||||
|
{
|
||||||
|
Assert( next == INVALID_INDEX && prev == INVALID_INDEX );
|
||||||
|
m_Tail = INVALID_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteMessage( pMsg );
|
||||||
|
msg = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( m_Head == INVALID_INDEX && m_Tail == INVALID_INDEX );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool SocketWouldBlock()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS;
|
||||||
|
#else
|
||||||
|
return errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void CloseSocket( SOCKET *sock )
|
||||||
|
{
|
||||||
|
if ( *sock != INVALID_SOCKET )
|
||||||
|
{
|
||||||
|
shutdown( *sock, SD_BOTH );
|
||||||
|
closesocket( *sock );
|
||||||
|
*sock = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CServerSocket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SOCKET m_Socket;
|
||||||
|
SOCKET m_ServerSocket;
|
||||||
|
|
||||||
|
CMessagePool m_MessagePool;
|
||||||
|
|
||||||
|
char *m_pRecvBufPtr;
|
||||||
|
char m_pRecvBuf[ SQDBG_NET_BUF_SIZE ];
|
||||||
|
|
||||||
|
bool m_bWSAInit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const char *m_pszLastMsgFmt;
|
||||||
|
const char *m_pszLastMsg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool IsListening()
|
||||||
|
{
|
||||||
|
return m_ServerSocket != INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsClientConnected()
|
||||||
|
{
|
||||||
|
return m_Socket != INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short GetServerPort()
|
||||||
|
{
|
||||||
|
if ( m_ServerSocket != INVALID_SOCKET )
|
||||||
|
{
|
||||||
|
sockaddr_in addr;
|
||||||
|
socklen_t len = sizeof(addr);
|
||||||
|
|
||||||
|
if ( getsockname( m_ServerSocket, (sockaddr*)&addr, &len ) != SOCKET_ERROR )
|
||||||
|
return ntohs( addr.sin_port );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListenSocket( unsigned short port )
|
||||||
|
{
|
||||||
|
if ( m_ServerSocket != INVALID_SOCKET )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if ( !m_bWSAInit )
|
||||||
|
{
|
||||||
|
WSADATA wsadata;
|
||||||
|
if ( WSAStartup( MAKEWORD(2,2), &wsadata ) != 0 )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) WSA startup failed";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_bWSAInit = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_ServerSocket = socket( AF_INET, SOCK_STREAM, 0 );
|
||||||
|
|
||||||
|
if ( m_ServerSocket == INVALID_SOCKET )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to open socket";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_long iMode = 1;
|
||||||
|
#ifdef _WIN32
|
||||||
|
if ( ioctlsocket( m_ServerSocket, FIONBIO, &iMode ) == SOCKET_ERROR )
|
||||||
|
#else
|
||||||
|
int f = fcntl( m_ServerSocket, F_GETFL );
|
||||||
|
if ( f == -1 || fcntl( m_ServerSocket, F_SETFL, f | O_NONBLOCK ) == -1 )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to set socket non-blocking";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iMode = 1;
|
||||||
|
|
||||||
|
if ( setsockopt( m_ServerSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&iMode, sizeof(iMode) ) == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to set TCP nodelay";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
linger ln;
|
||||||
|
ln.l_onoff = 0;
|
||||||
|
ln.l_linger = 0;
|
||||||
|
|
||||||
|
if ( setsockopt( m_ServerSocket, SOL_SOCKET, SO_LINGER, (char*)&ln, sizeof(ln) ) == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to set don't linger";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in addr;
|
||||||
|
memset( &addr, 0, sizeof(addr) );
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons( port );
|
||||||
|
addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||||
|
|
||||||
|
if ( bind( m_ServerSocket, (sockaddr*)&addr, sizeof(addr) ) == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to bind socket on port";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( listen( m_ServerSocket, 0 ) == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
Shutdown();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to listen to socket";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Listen()
|
||||||
|
{
|
||||||
|
timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO( &rfds );
|
||||||
|
FD_SET( m_ServerSocket, &rfds );
|
||||||
|
|
||||||
|
select( 0, &rfds, NULL, NULL, &tv );
|
||||||
|
|
||||||
|
if ( !FD_ISSET( m_ServerSocket, &rfds ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FD_CLR( m_ServerSocket, &rfds );
|
||||||
|
|
||||||
|
sockaddr_in addr;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
|
||||||
|
m_Socket = accept( m_ServerSocket, (sockaddr*)&addr, &addrlen );
|
||||||
|
|
||||||
|
if ( m_Socket == INVALID_SOCKET )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
int f = fcntl( m_Socket, F_GETFL );
|
||||||
|
if ( f == -1 || fcntl( m_Socket, F_SETFL, f | O_NONBLOCK ) == -1 )
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Failed to set socket non-blocking";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_pszLastMsg = inet_ntoa( addr.sin_addr );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown()
|
||||||
|
{
|
||||||
|
CloseSocket( &m_Socket );
|
||||||
|
CloseSocket( &m_ServerSocket );
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if ( m_bWSAInit )
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
m_bWSAInit = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_MessagePool.Clear();
|
||||||
|
m_pRecvBufPtr = m_pRecvBuf;
|
||||||
|
memset( m_pRecvBuf, -1, sizeof( m_pRecvBuf ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisconnectClient()
|
||||||
|
{
|
||||||
|
CloseSocket( &m_Socket );
|
||||||
|
|
||||||
|
m_MessagePool.Clear();
|
||||||
|
m_pRecvBufPtr = m_pRecvBuf;
|
||||||
|
memset( m_pRecvBuf, -1, sizeof( m_pRecvBuf ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Send( const char *buf, int len )
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int bytesSend = send( m_Socket, buf, len, 0 );
|
||||||
|
|
||||||
|
if ( bytesSend == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
// Keep blocking
|
||||||
|
if ( SocketWouldBlock() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int err = errno;
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Network error";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( len == bytesSend )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
len -= bytesSend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Recv()
|
||||||
|
{
|
||||||
|
timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO( &rfds );
|
||||||
|
FD_SET( m_Socket, &rfds );
|
||||||
|
|
||||||
|
select( 0, &rfds, NULL, NULL, &tv );
|
||||||
|
|
||||||
|
if ( !FD_ISSET( m_Socket, &rfds ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
FD_CLR( m_Socket, &rfds );
|
||||||
|
|
||||||
|
u_long readlen = 0;
|
||||||
|
ioctlsocket( m_Socket, FIONREAD, &readlen );
|
||||||
|
|
||||||
|
int bufsize = m_pRecvBuf + sizeof(m_pRecvBuf) - m_pRecvBufPtr;
|
||||||
|
|
||||||
|
if ( bufsize <= 0 || (unsigned int)bufsize < readlen )
|
||||||
|
{
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Net message buffer is full";
|
||||||
|
m_pszLastMsg = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int bytesRecv = recv( m_Socket, m_pRecvBufPtr, bufsize, 0 );
|
||||||
|
|
||||||
|
if ( bytesRecv == SOCKET_ERROR )
|
||||||
|
{
|
||||||
|
if ( SocketWouldBlock() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
int err = errno;
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Network error";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !bytesRecv )
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSASetLastError( WSAECONNRESET );
|
||||||
|
#else
|
||||||
|
errno = ECONNRESET;
|
||||||
|
#endif
|
||||||
|
int err = errno;
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Client disconnected";
|
||||||
|
m_pszLastMsg = strerr(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pRecvBufPtr += bytesRecv;
|
||||||
|
bufsize -= bytesRecv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Header reader sets message pointer to the content start
|
||||||
|
//
|
||||||
|
template < bool (readHeader)( char **ppMsg, int *pLength ) >
|
||||||
|
bool Parse()
|
||||||
|
{
|
||||||
|
// Nothing to parse
|
||||||
|
if ( m_pRecvBufPtr == m_pRecvBuf )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
char *pMsg = m_pRecvBuf;
|
||||||
|
int nLength = sizeof(m_pRecvBuf);
|
||||||
|
|
||||||
|
while ( readHeader( &pMsg, &nLength ) )
|
||||||
|
{
|
||||||
|
char *pMsgEnd = pMsg + (unsigned int)nLength;
|
||||||
|
|
||||||
|
if ( pMsgEnd >= m_pRecvBuf + sizeof(m_pRecvBuf) )
|
||||||
|
{
|
||||||
|
DisconnectClient();
|
||||||
|
m_pszLastMsgFmt = "(sqdbg) Client disconnected";
|
||||||
|
|
||||||
|
if ( nLength == -1 )
|
||||||
|
{
|
||||||
|
m_pszLastMsg = "malformed message";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pszLastMsg = "content is too large";
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entire message wasn't received, wait for it
|
||||||
|
if ( m_pRecvBufPtr < pMsgEnd )
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_MessagePool.Add( pMsg, nLength );
|
||||||
|
|
||||||
|
// Last message
|
||||||
|
if ( m_pRecvBufPtr == pMsgEnd )
|
||||||
|
{
|
||||||
|
memset( m_pRecvBuf, 0, m_pRecvBufPtr - m_pRecvBuf );
|
||||||
|
m_pRecvBufPtr = m_pRecvBuf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next message
|
||||||
|
int shift = m_pRecvBufPtr - pMsgEnd;
|
||||||
|
memmove( m_pRecvBuf, pMsgEnd, shift );
|
||||||
|
memset( m_pRecvBuf + shift, 0, m_pRecvBufPtr - ( m_pRecvBuf + shift ) );
|
||||||
|
m_pRecvBufPtr = m_pRecvBuf + shift;
|
||||||
|
pMsg = m_pRecvBuf;
|
||||||
|
nLength = sizeof(m_pRecvBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T, void (T::*callback)( char *ptr, int len ) >
|
||||||
|
void Execute( T *ctx )
|
||||||
|
{
|
||||||
|
m_MessagePool.Service< T, callback >( ctx );
|
||||||
|
|
||||||
|
if ( m_Socket == INVALID_SOCKET && m_MessagePool.m_ElemCount == 0 )
|
||||||
|
{
|
||||||
|
m_MessagePool.Shrink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
CServerSocket() :
|
||||||
|
m_Socket( INVALID_SOCKET ),
|
||||||
|
m_ServerSocket( INVALID_SOCKET ),
|
||||||
|
m_pRecvBufPtr( m_pRecvBuf ),
|
||||||
|
m_bWSAInit( false )
|
||||||
|
{
|
||||||
|
Assert( sizeof(m_pRecvBuf) <= ( 1 << ( sizeof(CMessagePool::message_t::len) * 8 ) ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQDBG_NET_H
|
300
sp/src/vscript/sqdbg/sqdbg/protocol.h
Normal file
300
sp/src/vscript/sqdbg/sqdbg/protocol.h
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// github.com/samisalreadytaken/sqdbg
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SQDBG_DAP_H
|
||||||
|
#define SQDBG_DAP_H
|
||||||
|
|
||||||
|
#define DAP_HEADER_CONTENTLENGTH "Content-Length"
|
||||||
|
#define DAP_HEADER_END "\r\n\r\n"
|
||||||
|
#define DAP_HEADER_MAXSIZE ( STRLEN(DAP_HEADER_CONTENTLENGTH ": ") + STRLEN(DAP_HEADER_END) + FMT_UINT32_LEN )
|
||||||
|
|
||||||
|
inline void DAP_Serialise( CBuffer *buffer )
|
||||||
|
{
|
||||||
|
Assert( buffer->size() > 0 && buffer->size() < INT_MAX );
|
||||||
|
|
||||||
|
char *mem = buffer->base();
|
||||||
|
int contentSize = buffer->size() - DAP_HEADER_MAXSIZE;
|
||||||
|
int digits = countdigits( contentSize );
|
||||||
|
int padding = FMT_UINT32_LEN - digits;
|
||||||
|
|
||||||
|
int nearest = 10;
|
||||||
|
while ( contentSize >= nearest )
|
||||||
|
nearest *= 10;
|
||||||
|
|
||||||
|
contentSize += padding;
|
||||||
|
|
||||||
|
if ( contentSize >= nearest )
|
||||||
|
{
|
||||||
|
// Padding between header and content increased content size digits,
|
||||||
|
// add padding in the end to match
|
||||||
|
padding--;
|
||||||
|
digits++;
|
||||||
|
buffer->_base.Ensure( buffer->size() + 1 );
|
||||||
|
mem[buffer->_size++] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( mem, DAP_HEADER_CONTENTLENGTH ": ", STRLEN(DAP_HEADER_CONTENTLENGTH ": ") );
|
||||||
|
|
||||||
|
int idx = STRLEN(DAP_HEADER_CONTENTLENGTH ": ") + digits;
|
||||||
|
|
||||||
|
for ( int i = idx - 1; contentSize; )
|
||||||
|
{
|
||||||
|
char c = contentSize % 10;
|
||||||
|
contentSize /= 10;
|
||||||
|
mem[i--] = '0' + c;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( mem + idx, DAP_HEADER_END, STRLEN(DAP_HEADER_END) );
|
||||||
|
idx += STRLEN(DAP_HEADER_END);
|
||||||
|
memset( mem + idx, ' ', padding );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DAP_Free( CBuffer *buffer )
|
||||||
|
{
|
||||||
|
buffer->_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ParseFieldName( const char *pMemEnd, char *pStart, int *len )
|
||||||
|
{
|
||||||
|
char *c = pStart;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ( IN_RANGE_CHAR( ((unsigned char*)c)[0], 0x20, 0x7E ) )
|
||||||
|
{
|
||||||
|
if ( c + 1 >= pMemEnd )
|
||||||
|
{
|
||||||
|
*len = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( c[0] == ':' )
|
||||||
|
{
|
||||||
|
if ( c[1] == ' ' )
|
||||||
|
{
|
||||||
|
*len = c - pStart;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ParseFieldValue( const char *pMemEnd, char *pStart, int *len )
|
||||||
|
{
|
||||||
|
char *c = pStart;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ( c + 1 >= pMemEnd )
|
||||||
|
{
|
||||||
|
*len = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( c[0] == '\n' )
|
||||||
|
{
|
||||||
|
*len = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( c[0] == '\r' && c[1] == '\n' )
|
||||||
|
{
|
||||||
|
*len = c - pStart;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DAP_ReadHeader( char **ppMsg, int *pLength )
|
||||||
|
{
|
||||||
|
char *pMsg = *ppMsg;
|
||||||
|
const char *pMemEnd = pMsg + *pLength;
|
||||||
|
int nContentLength = 0;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
ParseFieldName( pMemEnd, pMsg, &len );
|
||||||
|
|
||||||
|
if ( len == 0 )
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
if ( len == -1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( len == (int)STRLEN(DAP_HEADER_CONTENTLENGTH) &&
|
||||||
|
!memcmp( pMsg, DAP_HEADER_CONTENTLENGTH, STRLEN(DAP_HEADER_CONTENTLENGTH) ) )
|
||||||
|
{
|
||||||
|
// Duplicate length field
|
||||||
|
if ( nContentLength )
|
||||||
|
goto ignore;
|
||||||
|
|
||||||
|
pMsg += len + 2;
|
||||||
|
|
||||||
|
for ( char *pStart = pMsg;; )
|
||||||
|
{
|
||||||
|
if ( pMsg >= pMemEnd )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( IN_RANGE_CHAR( *(unsigned char*)pMsg, '0', '9' ) )
|
||||||
|
{
|
||||||
|
nContentLength = nContentLength * 10 + *pMsg - '0';
|
||||||
|
pMsg++;
|
||||||
|
|
||||||
|
if ( pMsg - pStart > (int)FMT_UINT32_LEN )
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
// Strict - no whitespace allowed
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( pMsg + 1 >= pMemEnd )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( pMsg[0] == '\r' && pMsg[1] == '\n' )
|
||||||
|
{
|
||||||
|
if ( nContentLength <= 0 )
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
*pLength = nContentLength;
|
||||||
|
pMsg += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ignore unknown header fields
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ignore:
|
||||||
|
pMsg += len + 2;
|
||||||
|
|
||||||
|
ParseFieldValue( pMemEnd, pMsg, &len );
|
||||||
|
|
||||||
|
if ( len == 0 )
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
if ( len == -1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pMsg += len + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pMsg + 1 >= pMemEnd )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( pMsg[0] == '\r' && pMsg[1] == '\n' )
|
||||||
|
{
|
||||||
|
*ppMsg = pMsg + 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
// Signal that the client needs to be dropped
|
||||||
|
*pLength = -1;
|
||||||
|
*ppMsg = pMsg;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SQDBG_VALIDATE_SENT_MSG
|
||||||
|
inline void DAP_Test( CScratch< JSON_SCRATCH_CHUNK_SIZE > *scratch, CBuffer *buffer )
|
||||||
|
{
|
||||||
|
char *pMsg = buffer->base();
|
||||||
|
int nLength = buffer->size();
|
||||||
|
|
||||||
|
bool res = DAP_ReadHeader( &pMsg, &nLength );
|
||||||
|
Assert( res && nLength < buffer->size() );
|
||||||
|
|
||||||
|
if ( res )
|
||||||
|
{
|
||||||
|
json_table_t table;
|
||||||
|
JSONParser parser( scratch, pMsg, nLength, &table );
|
||||||
|
|
||||||
|
AssertMsg1( !parser.GetError(), "%s", parser.GetError() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define DAP_Test(...) (void)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _DAP_INIT_BUF( _buf ) \
|
||||||
|
CBufTmpCache _bufcache( (_buf) ); \
|
||||||
|
(_buf)->_size = DAP_HEADER_MAXSIZE; \
|
||||||
|
(void)0
|
||||||
|
|
||||||
|
#define DAP_START_REQUEST( _seq, _cmd ) \
|
||||||
|
{ \
|
||||||
|
_DAP_INIT_BUF( &m_SendBuf ); \
|
||||||
|
{ \
|
||||||
|
wjson_table_t packet( m_SendBuf ); \
|
||||||
|
packet.SetInt( "seq", _seq ); \
|
||||||
|
packet.SetString( "type", "request" ); \
|
||||||
|
packet.SetString( "command", _cmd );
|
||||||
|
|
||||||
|
#define _DAP_START_RESPONSE( _seq, _cmd, _suc ) \
|
||||||
|
if ( IsClientConnected() ) \
|
||||||
|
{ \
|
||||||
|
_DAP_INIT_BUF( &m_SendBuf ); \
|
||||||
|
{ \
|
||||||
|
wjson_table_t packet( m_SendBuf ); \
|
||||||
|
packet.SetInt( "request_seq", _seq ); \
|
||||||
|
packet.SetString( "type", "response" ); \
|
||||||
|
packet.SetString( "command", _cmd ); \
|
||||||
|
packet.SetBool( "success", _suc );
|
||||||
|
|
||||||
|
#define DAP_START_RESPONSE( _seq, _cmd ) \
|
||||||
|
_DAP_START_RESPONSE( _seq, _cmd, true );
|
||||||
|
|
||||||
|
#define DAP_ERROR_RESPONSE( _seq, _cmd ) \
|
||||||
|
_DAP_START_RESPONSE( _seq, _cmd, false );
|
||||||
|
|
||||||
|
#define DAP_ERROR_BODY( _id, _fmt ) \
|
||||||
|
wjson_table_t body = packet.SetTable( "body" ); \
|
||||||
|
wjson_table_t error = body.SetTable( "error" ); \
|
||||||
|
error.SetInt( "id", _id ); \
|
||||||
|
error.SetString( "format", _fmt ); \
|
||||||
|
|
||||||
|
#define DAP_START_EVENT( _seq, _ev ) \
|
||||||
|
{ \
|
||||||
|
_DAP_INIT_BUF( &m_SendBuf ); \
|
||||||
|
{ \
|
||||||
|
wjson_table_t packet( m_SendBuf ); \
|
||||||
|
packet.SetInt( "seq", _seq ); \
|
||||||
|
packet.SetString( "type", "event" ); \
|
||||||
|
packet.SetString( "event", _ev );
|
||||||
|
|
||||||
|
#define DAP_SET( _key, _val ) \
|
||||||
|
packet.Set( _key, _val );
|
||||||
|
|
||||||
|
#define DAP_SET_TABLE( _val ) \
|
||||||
|
wjson_table_t _val = packet.SetTable( #_val );
|
||||||
|
|
||||||
|
#define DAP_SEND() \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
DAP_Serialise( &m_SendBuf ); \
|
||||||
|
Send( m_SendBuf.base(), m_SendBuf.size() ); \
|
||||||
|
DAP_Test( &m_ReadBuf, &m_SendBuf ); \
|
||||||
|
DAP_Free( &m_SendBuf ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SQDBG_DAP_H
|
19094
sp/src/vscript/sqdbg/sqdbg/server.cpp
Normal file
19094
sp/src/vscript/sqdbg/sqdbg/server.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1481
sp/src/vscript/sqdbg/sqdbg/str.h
Normal file
1481
sp/src/vscript/sqdbg/sqdbg/str.h
Normal file
File diff suppressed because it is too large
Load Diff
624
sp/src/vscript/sqdbg/sqdbg/vec.h
Normal file
624
sp/src/vscript/sqdbg/sqdbg/vec.h
Normal file
@ -0,0 +1,624 @@
|
|||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// github.com/samisalreadytaken/sqdbg
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SQDBG_VEC_H
|
||||||
|
#define SQDBG_VEC_H
|
||||||
|
|
||||||
|
void *sqdbg_malloc( unsigned int size );
|
||||||
|
void *sqdbg_realloc( void *p, unsigned int oldsize, unsigned int size );
|
||||||
|
void sqdbg_free( void *p, unsigned int size );
|
||||||
|
|
||||||
|
class CMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
struct memory_t
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
memory_t memory;
|
||||||
|
|
||||||
|
char &operator[]( unsigned int i ) const
|
||||||
|
{
|
||||||
|
Assert( memory.size > 0 );
|
||||||
|
return *( memory.ptr + i );
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Base()
|
||||||
|
{
|
||||||
|
return memory.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Size() const
|
||||||
|
{
|
||||||
|
return memory.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free()
|
||||||
|
{
|
||||||
|
if ( memory.ptr )
|
||||||
|
{
|
||||||
|
sqdbg_free( memory.ptr, memory.size );
|
||||||
|
memory.ptr = 0;
|
||||||
|
memory.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Alloc( unsigned int count )
|
||||||
|
{
|
||||||
|
Assert( count > 0 || memory.size == 0 );
|
||||||
|
|
||||||
|
if ( count == memory.size )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int size = ( count + sizeof(void*) - 1 ) & ~( sizeof(void*) - 1 );
|
||||||
|
|
||||||
|
if ( memory.ptr )
|
||||||
|
{
|
||||||
|
memory.ptr = (char*)sqdbg_realloc( memory.ptr, memory.size, size );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memory.ptr = (char*)sqdbg_malloc( size );
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertOOM( memory.ptr, size );
|
||||||
|
|
||||||
|
if ( memory.ptr )
|
||||||
|
{
|
||||||
|
memory.size = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memory.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ensure( unsigned int newcount )
|
||||||
|
{
|
||||||
|
unsigned int oldcount = memory.size;
|
||||||
|
|
||||||
|
if ( newcount <= oldcount )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( oldcount != 0 )
|
||||||
|
{
|
||||||
|
unsigned int i = (unsigned int)0x7fffffffu;
|
||||||
|
|
||||||
|
while ( ( i >> 1 ) > newcount )
|
||||||
|
{
|
||||||
|
i >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( i > 0 );
|
||||||
|
Assert( i > oldcount );
|
||||||
|
Assert( i >= newcount );
|
||||||
|
|
||||||
|
newcount = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( newcount < 4 )
|
||||||
|
newcount = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
Alloc( newcount );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template< int MEM_CACHE_CHUNKS_ALIGN = 2048 >
|
||||||
|
class CScratch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int MEM_CACHE_CHUNKSIZE = 4;
|
||||||
|
static const int INVALID_INDEX = 0x80000000;
|
||||||
|
|
||||||
|
struct chunk_t
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
chunk_t *m_Memory;
|
||||||
|
int m_MemChunkCount;
|
||||||
|
int m_LastFreeChunk;
|
||||||
|
int m_LastFreeIndex;
|
||||||
|
|
||||||
|
char *Get( int index )
|
||||||
|
{
|
||||||
|
Assert( index != INVALID_INDEX );
|
||||||
|
|
||||||
|
int msgIdx = index & 0x0000ffff;
|
||||||
|
int chunkIdx = index >> 16;
|
||||||
|
|
||||||
|
Assert( m_Memory );
|
||||||
|
Assert( chunkIdx < m_MemChunkCount );
|
||||||
|
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
Assert( msgIdx < chunk->count );
|
||||||
|
|
||||||
|
return &chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Alloc( int size, int *index = NULL, bool sequential = true )
|
||||||
|
{
|
||||||
|
if ( !m_Memory )
|
||||||
|
{
|
||||||
|
m_MemChunkCount = 4;
|
||||||
|
m_Memory = (chunk_t*)sqdbg_malloc( m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
memset( (char*)m_Memory, 0, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
|
||||||
|
chunk_t *chunk = &m_Memory[0];
|
||||||
|
chunk->count = MEM_CACHE_CHUNKS_ALIGN;
|
||||||
|
chunk->ptr = (char*)sqdbg_malloc( chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
AssertOOM( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
memset( chunk->ptr, 0, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
int requiredChunks;
|
||||||
|
int msgIdx;
|
||||||
|
int chunkIdx;
|
||||||
|
int matchedChunks = 0;
|
||||||
|
|
||||||
|
if ( sequential )
|
||||||
|
{
|
||||||
|
requiredChunks = ( size - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
msgIdx = m_LastFreeIndex;
|
||||||
|
chunkIdx = m_LastFreeChunk;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
requiredChunks = ( size + sizeof(int) - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
msgIdx = 0;
|
||||||
|
chunkIdx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
Assert( chunk->count && chunk->ptr );
|
||||||
|
|
||||||
|
if ( sequential )
|
||||||
|
{
|
||||||
|
int remainingChunks = chunk->count - msgIdx;
|
||||||
|
|
||||||
|
if ( remainingChunks >= requiredChunks )
|
||||||
|
{
|
||||||
|
m_LastFreeIndex = msgIdx + requiredChunks;
|
||||||
|
m_LastFreeChunk = chunkIdx;
|
||||||
|
|
||||||
|
if ( index )
|
||||||
|
{
|
||||||
|
Assert( msgIdx < 0x0000ffff );
|
||||||
|
Assert( chunkIdx < 0x00007fff );
|
||||||
|
*index = ( chunkIdx << 16 ) | msgIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *ptr = &chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
Assert( *(int*)ptr >= 0 && *(int*)ptr < ( chunk->count - msgIdx ) * MEM_CACHE_CHUNKSIZE );
|
||||||
|
|
||||||
|
if ( *(int*)ptr == 0 )
|
||||||
|
{
|
||||||
|
if ( ++matchedChunks == requiredChunks )
|
||||||
|
{
|
||||||
|
msgIdx = msgIdx - matchedChunks + 1;
|
||||||
|
Assert( !index );
|
||||||
|
ptr = &chunk->ptr[ msgIdx * MEM_CACHE_CHUNKSIZE ];
|
||||||
|
*(int*)ptr = size;
|
||||||
|
return ptr + sizeof(int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchedChunks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgIdx += ( *(int*)ptr + sizeof(int) - 1 ) / MEM_CACHE_CHUNKSIZE + 1;
|
||||||
|
|
||||||
|
Assert( msgIdx < 0x0000ffff );
|
||||||
|
|
||||||
|
if ( msgIdx < chunk->count )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
matchedChunks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msgIdx = 0;
|
||||||
|
|
||||||
|
if ( ++chunkIdx >= m_MemChunkCount )
|
||||||
|
{
|
||||||
|
int oldcount = m_MemChunkCount;
|
||||||
|
m_MemChunkCount <<= 1;
|
||||||
|
m_Memory = (chunk_t*)sqdbg_realloc( m_Memory,
|
||||||
|
oldcount * sizeof(chunk_t),
|
||||||
|
m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
memset( (char*)m_Memory + oldcount * sizeof(chunk_t),
|
||||||
|
0,
|
||||||
|
(m_MemChunkCount - oldcount) * sizeof(chunk_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count == 0 )
|
||||||
|
{
|
||||||
|
Assert( chunk->ptr == NULL );
|
||||||
|
|
||||||
|
chunk->count = ( requiredChunks + ( MEM_CACHE_CHUNKS_ALIGN - 1 ) ) & ~( MEM_CACHE_CHUNKS_ALIGN - 1 );
|
||||||
|
chunk->ptr = (char*)sqdbg_malloc( chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
AssertOOM( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
memset( chunk->ptr, 0, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( chunkIdx < 0x00007fff );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free( void *ptr )
|
||||||
|
{
|
||||||
|
Assert( m_Memory );
|
||||||
|
Assert( ptr );
|
||||||
|
|
||||||
|
*(char**)&ptr -= sizeof(int);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for ( int chunkIdx = 0; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count && ptr >= chunk->ptr && ptr < chunk->ptr + chunk->count * MEM_CACHE_CHUNKSIZE )
|
||||||
|
{
|
||||||
|
Assert( *(int*)ptr >= 0 );
|
||||||
|
Assert( (char*)ptr + sizeof(int) + *(int*)ptr <= chunk->ptr + chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert( found );
|
||||||
|
|
||||||
|
(*(unsigned char**)&ptr)[ *(int*)ptr + sizeof(int) - 1 ] = 0xdd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset( (char*)ptr, 0, *(int*)ptr + sizeof(int) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free()
|
||||||
|
{
|
||||||
|
if ( !m_Memory )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( int chunkIdx = 0; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count )
|
||||||
|
{
|
||||||
|
sqdbg_free( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sqdbg_free( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
|
||||||
|
m_Memory = NULL;
|
||||||
|
m_MemChunkCount = 4;
|
||||||
|
m_LastFreeChunk = 0;
|
||||||
|
m_LastFreeIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseShrink()
|
||||||
|
{
|
||||||
|
if ( !m_Memory )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( int chunkIdx = 4; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count )
|
||||||
|
{
|
||||||
|
sqdbg_free( chunk->ptr, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
|
||||||
|
chunk->count = 0;
|
||||||
|
chunk->ptr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
for ( int chunkIdx = 0; chunkIdx < 4; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count )
|
||||||
|
{
|
||||||
|
memset( chunk->ptr, 0xdd, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( m_MemChunkCount > 8 )
|
||||||
|
{
|
||||||
|
int oldcount = m_MemChunkCount;
|
||||||
|
m_MemChunkCount = 8;
|
||||||
|
m_Memory = (chunk_t*)sqdbg_realloc( m_Memory,
|
||||||
|
oldcount * sizeof(chunk_t),
|
||||||
|
m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
AssertOOM( m_Memory, m_MemChunkCount * sizeof(chunk_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_LastFreeChunk = 0;
|
||||||
|
m_LastFreeIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Release()
|
||||||
|
{
|
||||||
|
if ( !m_Memory || ( !m_LastFreeChunk && !m_LastFreeIndex ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
for ( int chunkIdx = 0; chunkIdx < m_MemChunkCount; chunkIdx++ )
|
||||||
|
{
|
||||||
|
chunk_t *chunk = &m_Memory[ chunkIdx ];
|
||||||
|
|
||||||
|
if ( chunk->count )
|
||||||
|
{
|
||||||
|
memset( chunk->ptr, 0xdd, chunk->count * MEM_CACHE_CHUNKSIZE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_LastFreeChunk = 0;
|
||||||
|
m_LastFreeIndex = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T, bool bExternalMem = false, class CAllocator = CMemory >
|
||||||
|
class vector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef unsigned int I;
|
||||||
|
|
||||||
|
CAllocator _base;
|
||||||
|
I _size;
|
||||||
|
|
||||||
|
vector() : _base(), _size(0)
|
||||||
|
{
|
||||||
|
Assert( !bExternalMem );
|
||||||
|
}
|
||||||
|
|
||||||
|
vector( CAllocator &a ) : _base(a), _size(0)
|
||||||
|
{
|
||||||
|
Assert( bExternalMem );
|
||||||
|
}
|
||||||
|
|
||||||
|
vector( I count ) : _base(), _size(0)
|
||||||
|
{
|
||||||
|
Assert( !bExternalMem );
|
||||||
|
_base.Alloc( count * sizeof(T) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vector( const vector< T > &src ) : _base()
|
||||||
|
{
|
||||||
|
Assert( !bExternalMem );
|
||||||
|
_base.Alloc( src._base.Size() );
|
||||||
|
_size = src._size;
|
||||||
|
|
||||||
|
for ( I i = 0; i < _size; i++ )
|
||||||
|
new( &_base[ i * sizeof(T) ] ) T( (T&)src._base[ i * sizeof(T) ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
~vector()
|
||||||
|
{
|
||||||
|
Assert( (unsigned int)_size <= _base.Size() );
|
||||||
|
|
||||||
|
for ( I i = 0; i < _size; i++ )
|
||||||
|
((T&)(_base[ i * sizeof(T) ])).~T();
|
||||||
|
|
||||||
|
if ( !bExternalMem )
|
||||||
|
_base.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
T &operator[]( I i ) const
|
||||||
|
{
|
||||||
|
Assert( _size > 0 );
|
||||||
|
Assert( i >= 0 && i < _size );
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
return (T&)_base[ i * sizeof(T) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
T *base()
|
||||||
|
{
|
||||||
|
return _base.Base();
|
||||||
|
}
|
||||||
|
|
||||||
|
I size() const
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
I capacity() const
|
||||||
|
{
|
||||||
|
return _base.Size() / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
T &top() const
|
||||||
|
{
|
||||||
|
Assert( _size > 0 );
|
||||||
|
return (T&)_base[ ( _size - 1 ) * sizeof(T) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
Assert( _size > 0 );
|
||||||
|
((T&)_base[ --_size * sizeof(T) ]).~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
T &append()
|
||||||
|
{
|
||||||
|
_base.Ensure( ++_size * sizeof(T) );
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
return *( new( &_base[ ( _size - 1 ) * sizeof(T) ] ) T() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void append( const T &src )
|
||||||
|
{
|
||||||
|
_base.Ensure( ++_size * sizeof(T) );
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
new( &_base[ ( _size - 1 ) * sizeof(T) ] ) T( src );
|
||||||
|
}
|
||||||
|
|
||||||
|
T &insert( I i )
|
||||||
|
{
|
||||||
|
Assert( i >= 0 && i <= _size );
|
||||||
|
|
||||||
|
_base.Ensure( ++_size * sizeof(T) );
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
|
||||||
|
if ( i != _size - 1 )
|
||||||
|
{
|
||||||
|
memmove( &_base[ ( i + 1 ) * sizeof(T) ],
|
||||||
|
&_base[ i * sizeof(T) ],
|
||||||
|
( _size - ( i + 1 ) ) * sizeof(T) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return *( new( &_base[ i * sizeof(T) ] ) T() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove( I i )
|
||||||
|
{
|
||||||
|
Assert( _size > 0 );
|
||||||
|
Assert( i >= 0 && i < _size );
|
||||||
|
|
||||||
|
((T&)_base[ i * sizeof(T) ]).~T();
|
||||||
|
|
||||||
|
if ( i != _size - 1 )
|
||||||
|
{
|
||||||
|
memmove( &_base[ i * sizeof(T) ],
|
||||||
|
&_base[ ( i + 1 ) * sizeof(T) ],
|
||||||
|
( _size - ( i + 1 ) ) * sizeof(T) );
|
||||||
|
}
|
||||||
|
|
||||||
|
_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for ( I i = 0; i < _size; i++ )
|
||||||
|
((T&)_base[ i * sizeof(T) ]).~T();
|
||||||
|
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sort( int (*fn)(const T *, const T *) )
|
||||||
|
{
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
|
||||||
|
if ( _size > 1 )
|
||||||
|
{
|
||||||
|
qsort( _base.Base(), _size, sizeof(T), (int (*)(const void *, const void *))fn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve( I count )
|
||||||
|
{
|
||||||
|
Assert( (unsigned int)_size <= _base.Size() );
|
||||||
|
|
||||||
|
if ( count == 0 )
|
||||||
|
count = 4;
|
||||||
|
|
||||||
|
if ( (unsigned int)count == _base.Size() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( I i = count; i < _size; i++ )
|
||||||
|
((T&)_base[ i * sizeof(T) ]).~T();
|
||||||
|
|
||||||
|
_base.Alloc( count * sizeof(T) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void purge()
|
||||||
|
{
|
||||||
|
Assert( _size * sizeof(T) <= _base.Size() );
|
||||||
|
|
||||||
|
for ( I i = 0; i < _size; i++ )
|
||||||
|
((T&)_base[ i * sizeof(T) ]).~T();
|
||||||
|
|
||||||
|
_base.Free();
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMemory _base;
|
||||||
|
int _size;
|
||||||
|
int _offset;
|
||||||
|
|
||||||
|
char *base()
|
||||||
|
{
|
||||||
|
return _base.Base() + _offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() const
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int capacity() const
|
||||||
|
{
|
||||||
|
return _base.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve( int count )
|
||||||
|
{
|
||||||
|
Assert( (unsigned int)_size <= _base.Size() );
|
||||||
|
|
||||||
|
if ( (unsigned int)count == _base.Size() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
_base.Alloc( count );
|
||||||
|
}
|
||||||
|
|
||||||
|
void purge()
|
||||||
|
{
|
||||||
|
_base.Free();
|
||||||
|
_size = 0;
|
||||||
|
_offset = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBufTmpCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBuffer *buffer;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
CBufTmpCache( CBuffer *b ) :
|
||||||
|
buffer(b),
|
||||||
|
size(buffer->_size)
|
||||||
|
{
|
||||||
|
buffer->_offset += buffer->_size;
|
||||||
|
buffer->_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CBufTmpCache()
|
||||||
|
{
|
||||||
|
buffer->_offset -= size;
|
||||||
|
buffer->_size = size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQDBG_VEC_H
|
@ -17,6 +17,7 @@
|
|||||||
IScriptVM* makeSquirrelVM();
|
IScriptVM* makeSquirrelVM();
|
||||||
|
|
||||||
int vscript_token = 0;
|
int vscript_token = 0;
|
||||||
|
int vscript_debugger_port = 0;
|
||||||
|
|
||||||
class CScriptManager : public CTier1AppSystem<IScriptManager>
|
class CScriptManager : public CTier1AppSystem<IScriptManager>
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ $Configuration
|
|||||||
{
|
{
|
||||||
$Compiler
|
$Compiler
|
||||||
{
|
{
|
||||||
$AdditionalIncludeDirectories "$BASE;.\squirrel\include"
|
$AdditionalIncludeDirectories "$BASE;.\squirrel\include;.\squirrel\squirrel;.\squirrel\sqstdlib;.\sqdbg\include"
|
||||||
$PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT]
|
$PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,5 +65,21 @@ $Project "VScript"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$Folder "sqdbg"
|
||||||
|
{
|
||||||
|
$File ".\sqdbg\sqdbg\server.cpp"
|
||||||
|
{
|
||||||
|
$Configuration
|
||||||
|
{
|
||||||
|
$Compiler
|
||||||
|
{
|
||||||
|
$PreprocessorDefinitions "$BASE;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS"
|
||||||
|
$AdditionalOptions "$BASE /wd4127 /wd4146 /wd4201 /wd4244 /wd4267 /wd4456 /wd4706"
|
||||||
|
$TreatWarningsAsErrors "No"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,13 +453,11 @@ bool CScriptColorInstanceHelper::Get( void *p, const char *pszKey, ScriptVariant
|
|||||||
bool CScriptColorInstanceHelper::Set( void *p, const char *pszKey, ScriptVariant_t &variant )
|
bool CScriptColorInstanceHelper::Set( void *p, const char *pszKey, ScriptVariant_t &variant )
|
||||||
{
|
{
|
||||||
Color *pClr = ((Color *)p);
|
Color *pClr = ((Color *)p);
|
||||||
if ( strlen(pszKey) == 1 )
|
int iVal;
|
||||||
|
if ( strlen(pszKey) == 1 && variant.AssignTo( &iVal ) )
|
||||||
{
|
{
|
||||||
int iVal;
|
|
||||||
variant.AssignTo( &iVal );
|
|
||||||
switch (pszKey[0])
|
switch (pszKey[0])
|
||||||
{
|
{
|
||||||
// variant.AssignTo( &(*pClr)[0] );
|
|
||||||
case 'r':
|
case 'r':
|
||||||
(*pClr)[0] = iVal;
|
(*pClr)[0] = iVal;
|
||||||
return true;
|
return true;
|
||||||
|
@ -258,39 +258,18 @@ bool CScriptQuaternionInstanceHelper::Set( void *p, const char *pszKey, ScriptVa
|
|||||||
switch (pszKey[0])
|
switch (pszKey[0])
|
||||||
{
|
{
|
||||||
case 'x':
|
case 'x':
|
||||||
variant.AssignTo( &pQuat->x );
|
return variant.AssignTo( &pQuat->x );
|
||||||
return true;
|
|
||||||
case 'y':
|
case 'y':
|
||||||
variant.AssignTo( &pQuat->y );
|
return variant.AssignTo( &pQuat->y );
|
||||||
return true;
|
|
||||||
case 'z':
|
case 'z':
|
||||||
variant.AssignTo( &pQuat->z );
|
return variant.AssignTo( &pQuat->z );
|
||||||
return true;
|
|
||||||
case 'w':
|
case 'w':
|
||||||
variant.AssignTo( &pQuat->w );
|
return variant.AssignTo( &pQuat->w );
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptVariant_t *CScriptQuaternionInstanceHelper::Add( void *p, ScriptVariant_t &variant )
|
|
||||||
{
|
|
||||||
Quaternion *pQuat = ((Quaternion *)p);
|
|
||||||
|
|
||||||
float flAdd;
|
|
||||||
variant.AssignTo( &flAdd );
|
|
||||||
|
|
||||||
(*pQuat)[0] += flAdd;
|
|
||||||
(*pQuat)[1] += flAdd;
|
|
||||||
(*pQuat)[2] += flAdd;
|
|
||||||
(*pQuat)[3] += flAdd;
|
|
||||||
|
|
||||||
static ScriptVariant_t result;
|
|
||||||
result = (HSCRIPT)p;
|
|
||||||
return &result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -40,11 +40,6 @@ class CScriptQuaternionInstanceHelper : public IScriptInstanceHelper
|
|||||||
|
|
||||||
bool Get( void *p, const char *pszKey, ScriptVariant_t &variant );
|
bool Get( void *p, const char *pszKey, ScriptVariant_t &variant );
|
||||||
bool Set( void *p, const char *pszKey, ScriptVariant_t &variant );
|
bool Set( void *p, const char *pszKey, ScriptVariant_t &variant );
|
||||||
|
|
||||||
ScriptVariant_t *Add( void *p, ScriptVariant_t &variant );
|
|
||||||
//ScriptVariant_t *Subtract( void *p, ScriptVariant_t &variant );
|
|
||||||
//ScriptVariant_t *Multiply( void *p, ScriptVariant_t &variant );
|
|
||||||
//ScriptVariant_t *Divide( void *p, ScriptVariant_t &variant );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Quaternion *ToQuaternion( HSCRIPT hQuat ) { return HScriptToClass<Quaternion>( hQuat ); }
|
inline Quaternion *ToQuaternion( HSCRIPT hQuat ) { return HScriptToClass<Quaternion>( hQuat ); }
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include "squirrel/squirrel/squserdata.h"
|
#include "squirrel/squirrel/squserdata.h"
|
||||||
#include "squirrel/squirrel/sqclosure.h"
|
#include "squirrel/squirrel/sqclosure.h"
|
||||||
|
|
||||||
|
#include "sqdbg.h"
|
||||||
|
|
||||||
#include "tier1/utlbuffer.h"
|
#include "tier1/utlbuffer.h"
|
||||||
#include "tier1/mapbase_con_groups.h"
|
#include "tier1/mapbase_con_groups.h"
|
||||||
#include "tier1/convar.h"
|
#include "tier1/convar.h"
|
||||||
@ -113,7 +115,7 @@ public:
|
|||||||
virtual bool Init() override;
|
virtual bool Init() override;
|
||||||
virtual void Shutdown() override;
|
virtual void Shutdown() override;
|
||||||
|
|
||||||
virtual bool ConnectDebugger() override;
|
virtual bool ConnectDebugger( int port = 0 ) override;
|
||||||
virtual void DisconnectDebugger() override;
|
virtual void DisconnectDebugger() override;
|
||||||
|
|
||||||
virtual ScriptLanguage_t GetLanguage() override;
|
virtual ScriptLanguage_t GetLanguage() override;
|
||||||
@ -299,6 +301,7 @@ public:
|
|||||||
HSQOBJECT lastError_;
|
HSQOBJECT lastError_;
|
||||||
HSQOBJECT vectorClass_;
|
HSQOBJECT vectorClass_;
|
||||||
HSQOBJECT regexpClass_;
|
HSQOBJECT regexpClass_;
|
||||||
|
HSQDEBUGSERVER debugger_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char TYPETAG_VECTOR[] = "VectorTypeTag";
|
static char TYPETAG_VECTOR[] = "VectorTypeTag";
|
||||||
@ -1230,6 +1233,8 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
{
|
{
|
||||||
case OT_NULL:
|
case OT_NULL:
|
||||||
{
|
{
|
||||||
|
variant.Free();
|
||||||
|
variant.m_flags = 0;
|
||||||
// TODO: Should this be (HSCRIPT)nullptr
|
// TODO: Should this be (HSCRIPT)nullptr
|
||||||
variant.m_type = FIELD_VOID;
|
variant.m_type = FIELD_VOID;
|
||||||
return true;
|
return true;
|
||||||
@ -1241,6 +1246,7 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
variant.Free();
|
||||||
variant = (int)val;
|
variant = (int)val;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1251,6 +1257,7 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
variant.Free();
|
||||||
variant = (float)val;
|
variant = (float)val;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1261,6 +1268,7 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
variant.Free();
|
||||||
variant = val ? true : false;
|
variant = val ? true : false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1272,7 +1280,8 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char* buffer = new char[size + 1];
|
variant.Free();
|
||||||
|
char* buffer = (char*)malloc(size + 1);
|
||||||
V_memcpy(buffer, val, size);
|
V_memcpy(buffer, val, size);
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
variant = buffer;
|
variant = buffer;
|
||||||
@ -1287,7 +1296,9 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
tag == TYPETAG_VECTOR &&
|
tag == TYPETAG_VECTOR &&
|
||||||
SQ_SUCCEEDED(sq_getinstanceup(vm, idx, (SQUserPointer*)&v, TYPETAG_VECTOR)))
|
SQ_SUCCEEDED(sq_getinstanceup(vm, idx, (SQUserPointer*)&v, TYPETAG_VECTOR)))
|
||||||
{
|
{
|
||||||
variant = new Vector(*v);
|
variant.Free();
|
||||||
|
variant = (Vector*)malloc(sizeof(Vector));
|
||||||
|
variant.EmplaceAllocedVector(*v);
|
||||||
variant.m_flags |= SV_FREE;
|
variant.m_flags |= SV_FREE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1295,6 +1306,7 @@ bool getVariant(HSQUIRRELVM vm, SQInteger idx, ScriptVariant_t& variant)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
variant.Free();
|
||||||
HSQOBJECT* obj = new HSQOBJECT;
|
HSQOBJECT* obj = new HSQOBJECT;
|
||||||
sq_resetobject(obj);
|
sq_resetobject(obj);
|
||||||
sq_getstackobj(vm, idx, obj);
|
sq_getstackobj(vm, idx, obj);
|
||||||
@ -1423,37 +1435,54 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
|||||||
instance = ((ClassInstanceData*)self)->instance;
|
instance = ((ClassInstanceData*)self)->instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptVariant_t retval;
|
ScriptVariant_t script_retval;
|
||||||
|
ScriptVariantTemporaryStorage_t script_retval_storage;
|
||||||
|
|
||||||
SquirrelVM* pSquirrelVM = (SquirrelVM*)sq_getsharedforeignptr(vm);
|
SquirrelVM* pSquirrelVM = (SquirrelVM*)sq_getsharedforeignptr(vm);
|
||||||
Assert(pSquirrelVM);
|
Assert(pSquirrelVM);
|
||||||
|
|
||||||
sq_resetobject(&pSquirrelVM->lastError_);
|
sq_resetobject(&pSquirrelVM->lastError_);
|
||||||
|
|
||||||
(*pFunc->m_pfnBinding)(pFunc->m_pFunction, instance, params.Base(), nargs,
|
bool call_success = (*pFunc->m_pfnBinding)(pFunc->m_pFunction, instance, params.Base(), nargs,
|
||||||
pFunc->m_desc.m_ReturnType == FIELD_VOID ? nullptr : &retval);
|
pFunc->m_desc.m_ReturnType == FIELD_VOID ? nullptr : &script_retval, script_retval_storage);
|
||||||
|
Assert(call_success);
|
||||||
|
(void)call_success;
|
||||||
|
|
||||||
|
SQInteger sq_retval;
|
||||||
if (!sq_isnull(pSquirrelVM->lastError_))
|
if (!sq_isnull(pSquirrelVM->lastError_))
|
||||||
{
|
{
|
||||||
sq_pushobject(vm, pSquirrelVM->lastError_);
|
sq_pushobject(vm, pSquirrelVM->lastError_);
|
||||||
sq_resetobject(&pSquirrelVM->lastError_);
|
sq_resetobject(&pSquirrelVM->lastError_);
|
||||||
return sq_throwobject(vm);
|
sq_retval = sq_throwobject(vm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert(script_retval.m_type == pFunc->m_desc.m_ReturnType);
|
||||||
|
|
||||||
|
if (pFunc->m_desc.m_ReturnType != FIELD_VOID)
|
||||||
|
{
|
||||||
|
PushVariant(vm, script_retval);
|
||||||
|
sq_retval = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sq_retval = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PushVariant(vm, retval);
|
// strings never get copied here, Vector and QAngle are stored in script_retval_storage
|
||||||
|
// everything else is stored inline, so there should be no memory to free
|
||||||
if (retval.m_type == FIELD_VECTOR)
|
Assert(!(script_retval.m_flags & SV_FREE));
|
||||||
delete retval.m_pVector;
|
|
||||||
|
|
||||||
Assert( ( pFunc->m_desc.m_ReturnType != FIELD_VOID ) || !( pFunc->m_flags & SF_REFCOUNTED_RET ) );
|
Assert( ( pFunc->m_desc.m_ReturnType != FIELD_VOID ) || !( pFunc->m_flags & SF_REFCOUNTED_RET ) );
|
||||||
|
|
||||||
if ( ( pFunc->m_flags & SF_REFCOUNTED_RET ) && retval.m_hScript )
|
if ( ( pFunc->m_flags & SF_REFCOUNTED_RET ) && script_retval.m_hScript )
|
||||||
{
|
{
|
||||||
Assert( retval.m_type == FIELD_HSCRIPT );
|
Assert( script_retval.m_type == FIELD_HSCRIPT );
|
||||||
|
|
||||||
// Release the intermediary ref held from RegisterInstance
|
// Release the intermediary ref held from RegisterInstance
|
||||||
sq_release(vm, (HSQOBJECT*)retval.m_hScript);
|
sq_release(vm, (HSQOBJECT*)script_retval.m_hScript);
|
||||||
delete (HSQOBJECT*)retval.m_hScript;
|
delete (HSQOBJECT*)script_retval.m_hScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i <= nLastHScriptIdx; ++i )
|
for ( int i = 0; i <= nLastHScriptIdx; ++i )
|
||||||
@ -1462,7 +1491,7 @@ SQInteger function_stub(HSQUIRRELVM vm)
|
|||||||
delete (HSQOBJECT*)params[i].m_hScript;
|
delete (HSQOBJECT*)params[i].m_hScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pFunc->m_desc.m_ReturnType != FIELD_VOID;
|
return sq_retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1506,12 +1535,8 @@ SQInteger constructor_stub(HSQUIRRELVM vm)
|
|||||||
|
|
||||||
void* instance = pClassDesc->m_pfnConstruct();
|
void* instance = pClassDesc->m_pfnConstruct();
|
||||||
|
|
||||||
if (!sq_isnull(pSquirrelVM->lastError_))
|
// expect construction to always succeed
|
||||||
{
|
Assert(sq_isnull(pSquirrelVM->lastError_));
|
||||||
sq_pushobject(vm, pSquirrelVM->lastError_);
|
|
||||||
sq_resetobject(&pSquirrelVM->lastError_);
|
|
||||||
return sq_throwobject(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SQUserPointer p;
|
SQUserPointer p;
|
||||||
@ -1568,19 +1593,22 @@ SQInteger get_stub(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScriptVariant_t var;
|
ScriptVariant_t var;
|
||||||
|
SQInteger sq_retval = 0;
|
||||||
if (classInstanceData &&
|
if (classInstanceData &&
|
||||||
classInstanceData->instance &&
|
classInstanceData->instance &&
|
||||||
classInstanceData->desc->pHelper &&
|
classInstanceData->desc->pHelper &&
|
||||||
classInstanceData->desc->pHelper->Get(classInstanceData->instance, key, var))
|
classInstanceData->desc->pHelper->Get(classInstanceData->instance, key, var))
|
||||||
{
|
{
|
||||||
PushVariant(vm, var);
|
PushVariant(vm, var);
|
||||||
|
sq_retval = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
var.Free();
|
||||||
|
return sq_retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQInteger set_stub(HSQUIRRELVM vm)
|
SQInteger set_stub(HSQUIRRELVM vm)
|
||||||
@ -1597,122 +1625,22 @@ SQInteger set_stub(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScriptVariant_t var;
|
ScriptVariant_t var;
|
||||||
|
SQInteger sq_retval = 0;
|
||||||
getVariant( vm, -1, var );
|
getVariant( vm, -1, var );
|
||||||
|
|
||||||
if (classInstanceData &&
|
if (!(
|
||||||
|
classInstanceData &&
|
||||||
classInstanceData->instance &&
|
classInstanceData->instance &&
|
||||||
classInstanceData->desc->pHelper &&
|
classInstanceData->desc->pHelper &&
|
||||||
classInstanceData->desc->pHelper->Set(classInstanceData->instance, key, var))
|
classInstanceData->desc->pHelper->Set(classInstanceData->instance, key, var)
|
||||||
|
))
|
||||||
{
|
{
|
||||||
sq_pop(vm, 1);
|
sq_retval = sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return sqstd_throwerrorf(vm, "the index '%.50s' does not exist", key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQInteger add_stub(HSQUIRRELVM vm)
|
|
||||||
{
|
|
||||||
ClassInstanceData* classInstanceData = nullptr;
|
|
||||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
|
||||||
|
|
||||||
ScriptVariant_t var;
|
|
||||||
getVariant( vm, 1, var );
|
|
||||||
|
|
||||||
if (classInstanceData &&
|
|
||||||
classInstanceData->instance &&
|
|
||||||
classInstanceData->desc->pHelper)
|
|
||||||
{
|
|
||||||
ScriptVariant_t *result = classInstanceData->desc->pHelper->Add( classInstanceData->instance, var );
|
|
||||||
if (result != nullptr)
|
|
||||||
{
|
|
||||||
PushVariant( vm, *result );
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var.Free();
|
||||||
sq_pop(vm, 1);
|
sq_pop(vm, 1);
|
||||||
return sqstd_throwerrorf(vm, "invalid arith op +");
|
return sq_retval;
|
||||||
}
|
|
||||||
|
|
||||||
SQInteger sub_stub(HSQUIRRELVM vm)
|
|
||||||
{
|
|
||||||
ClassInstanceData* classInstanceData = nullptr;
|
|
||||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
|
||||||
|
|
||||||
ScriptVariant_t var;
|
|
||||||
getVariant( vm, 1, var );
|
|
||||||
|
|
||||||
if (classInstanceData &&
|
|
||||||
classInstanceData->instance &&
|
|
||||||
classInstanceData->desc->pHelper)
|
|
||||||
{
|
|
||||||
ScriptVariant_t *result = classInstanceData->desc->pHelper->Subtract( classInstanceData->instance, var );
|
|
||||||
if (result != nullptr)
|
|
||||||
{
|
|
||||||
PushVariant( vm, *result );
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return sqstd_throwerrorf(vm, "invalid arith op -");
|
|
||||||
}
|
|
||||||
|
|
||||||
SQInteger mul_stub(HSQUIRRELVM vm)
|
|
||||||
{
|
|
||||||
ClassInstanceData* classInstanceData = nullptr;
|
|
||||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
|
||||||
|
|
||||||
ScriptVariant_t var;
|
|
||||||
getVariant( vm, 1, var );
|
|
||||||
|
|
||||||
if (classInstanceData &&
|
|
||||||
classInstanceData->instance &&
|
|
||||||
classInstanceData->desc->pHelper )
|
|
||||||
{
|
|
||||||
ScriptVariant_t *result = classInstanceData->desc->pHelper->Add( classInstanceData->instance, var );
|
|
||||||
if (result != nullptr)
|
|
||||||
{
|
|
||||||
PushVariant( vm, *result );
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return sqstd_throwerrorf(vm, "invalid arith op *");
|
|
||||||
}
|
|
||||||
|
|
||||||
SQInteger div_stub(HSQUIRRELVM vm)
|
|
||||||
{
|
|
||||||
ClassInstanceData* classInstanceData = nullptr;
|
|
||||||
sq_getinstanceup(vm, 1, (SQUserPointer*)&classInstanceData, 0);
|
|
||||||
|
|
||||||
ScriptVariant_t var;
|
|
||||||
getVariant( vm, 1, var );
|
|
||||||
|
|
||||||
if (classInstanceData &&
|
|
||||||
classInstanceData->instance &&
|
|
||||||
classInstanceData->desc->pHelper )
|
|
||||||
{
|
|
||||||
ScriptVariant_t *result = classInstanceData->desc->pHelper->Add( classInstanceData->instance, var );
|
|
||||||
if (result != nullptr)
|
|
||||||
{
|
|
||||||
PushVariant( vm, *result );
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sq_pop(vm, 1);
|
|
||||||
return sqstd_throwerrorf(vm, "invalid arith op /");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SQInteger IsValid_stub(HSQUIRRELVM vm)
|
SQInteger IsValid_stub(HSQUIRRELVM vm)
|
||||||
@ -2120,15 +2048,37 @@ void SquirrelVM::Shutdown()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SquirrelVM::ConnectDebugger()
|
bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing );
|
||||||
|
|
||||||
|
bool SquirrelVM::ConnectDebugger( int port )
|
||||||
{
|
{
|
||||||
// TODO: Debugger support
|
if ( !debugger_ )
|
||||||
return false;
|
{
|
||||||
|
debugger_ = sqdbg_attach_debugger( vm_ );
|
||||||
|
|
||||||
|
if ( sqdbg_listen_socket( debugger_, port ) != 0 )
|
||||||
|
{
|
||||||
|
sqdbg_destroy_debugger( vm_ );
|
||||||
|
debugger_ = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sqdbg_frame( debugger_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
VScriptRunScript( "sqdbg_definitions.nut", NULL, false );
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SquirrelVM::DisconnectDebugger()
|
void SquirrelVM::DisconnectDebugger()
|
||||||
{
|
{
|
||||||
// TODO: Debugger support
|
if ( debugger_ )
|
||||||
|
{
|
||||||
|
sqdbg_destroy_debugger( vm_ );
|
||||||
|
debugger_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptLanguage_t SquirrelVM::GetLanguage()
|
ScriptLanguage_t SquirrelVM::GetLanguage()
|
||||||
@ -2148,7 +2098,10 @@ void SquirrelVM::AddSearchPath(const char* pszSearchPath)
|
|||||||
|
|
||||||
bool SquirrelVM::Frame(float simTime)
|
bool SquirrelVM::Frame(float simTime)
|
||||||
{
|
{
|
||||||
// TODO: Frame support
|
if ( debugger_ )
|
||||||
|
{
|
||||||
|
sqdbg_frame( debugger_ );
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2175,12 +2128,24 @@ HSCRIPT SquirrelVM::CompileScript(const char* pszScript, const char* pszId)
|
|||||||
{
|
{
|
||||||
SquirrelSafeCheck safeCheck(vm_);
|
SquirrelSafeCheck safeCheck(vm_);
|
||||||
|
|
||||||
Assert(vm_);
|
bool bUnnamed = ( pszId == nullptr );
|
||||||
if (pszId == nullptr) pszId = "<unnamed>";
|
if ( bUnnamed )
|
||||||
if (SQ_FAILED(sq_compilebuffer(vm_, pszScript, strlen(pszScript), pszId, SQTrue)))
|
{
|
||||||
|
pszId = "<unnamed>";
|
||||||
|
}
|
||||||
|
|
||||||
|
int nScriptLen = strlen(pszScript);
|
||||||
|
|
||||||
|
if (SQ_FAILED(sq_compilebuffer(vm_, pszScript, nScriptLen, pszId, SQTrue)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( debugger_ && !bUnnamed )
|
||||||
|
{
|
||||||
|
sqdbg_on_script_compile( debugger_, pszScript, nScriptLen, pszId, strlen(pszId) );
|
||||||
|
}
|
||||||
|
|
||||||
HSQOBJECT* obj = new HSQOBJECT;
|
HSQOBJECT* obj = new HSQOBJECT;
|
||||||
sq_resetobject(obj);
|
sq_resetobject(obj);
|
||||||
sq_getstackobj(vm_, -1, obj);
|
sq_getstackobj(vm_, -1, obj);
|
||||||
@ -2463,6 +2428,7 @@ void SquirrelVM::RegisterFunction(ScriptFunctionBinding_t* pScriptFunction)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
char typemask[64];
|
char typemask[64];
|
||||||
|
Assert(pScriptFunction->m_desc.m_Parameters.Count() < sizeof(typemask));
|
||||||
if (!CreateParamCheck(*pScriptFunction, typemask))
|
if (!CreateParamCheck(*pScriptFunction, typemask))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -2548,22 +2514,6 @@ bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc)
|
|||||||
sq_newclosure(vm_, set_stub, 0);
|
sq_newclosure(vm_, set_stub, 0);
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
sq_newslot(vm_, -3, SQFalse);
|
||||||
|
|
||||||
sq_pushstring(vm_, "_add", -1);
|
|
||||||
sq_newclosure(vm_, add_stub, 0);
|
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
|
||||||
|
|
||||||
sq_pushstring(vm_, "_sub", -1);
|
|
||||||
sq_newclosure(vm_, sub_stub, 0);
|
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
|
||||||
|
|
||||||
sq_pushstring(vm_, "_mul", -1);
|
|
||||||
sq_newclosure(vm_, mul_stub, 0);
|
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
|
||||||
|
|
||||||
sq_pushstring(vm_, "_div", -1);
|
|
||||||
sq_newclosure(vm_, div_stub, 0);
|
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
|
||||||
|
|
||||||
sq_pushstring(vm_, "IsValid", -1);
|
sq_pushstring(vm_, "IsValid", -1);
|
||||||
sq_newclosure(vm_, IsValid_stub, 0);
|
sq_newclosure(vm_, IsValid_stub, 0);
|
||||||
sq_newslot(vm_, -3, SQFalse);
|
sq_newslot(vm_, -3, SQFalse);
|
||||||
@ -2582,6 +2532,7 @@ bool SquirrelVM::RegisterClass(ScriptClassDesc_t* pClassDesc)
|
|||||||
auto& scriptFunction = pClassDesc->m_FunctionBindings[i];
|
auto& scriptFunction = pClassDesc->m_FunctionBindings[i];
|
||||||
|
|
||||||
char typemask[64];
|
char typemask[64];
|
||||||
|
Assert(scriptFunction.m_desc.m_Parameters.Count() < sizeof(typemask));
|
||||||
if (!CreateParamCheck(scriptFunction, typemask))
|
if (!CreateParamCheck(scriptFunction, typemask))
|
||||||
{
|
{
|
||||||
Warning("Unable to create param check for %s.%s\n",
|
Warning("Unable to create param check for %s.%s\n",
|
||||||
@ -3126,6 +3077,7 @@ void SquirrelVM::ReleaseValue(ScriptVariant_t& value)
|
|||||||
|
|
||||||
// Let's prevent this being called again and giving some UB
|
// Let's prevent this being called again and giving some UB
|
||||||
value.m_type = FIELD_VOID;
|
value.m_type = FIELD_VOID;
|
||||||
|
value.m_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SquirrelVM::ClearValue(HSCRIPT hScope, const char* pszKey)
|
bool SquirrelVM::ClearValue(HSCRIPT hScope, const char* pszKey)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user