mirror of
https://github.com/YGGverse/hlsdk-portable.git
synced 2025-02-08 21:14:14 +00:00
Entity save fields dumper
This commit is contained in:
parent
bc2b07a240
commit
90ed3bb8d2
@ -3,7 +3,7 @@
|
||||
#include "cbase.h"
|
||||
#include "game.h"
|
||||
#include "player.h"
|
||||
|
||||
#include "saverestore.h"
|
||||
#define Ent_IsValidEdict( e ) ( e && !e->free )
|
||||
|
||||
// stop any actions with players
|
||||
@ -481,6 +481,182 @@ bool Ent_CheckModel( const char *model )
|
||||
return true;
|
||||
}
|
||||
|
||||
class CDumper: public CSave
|
||||
{
|
||||
public:
|
||||
CDumper( edict_t *cl, bool E, bool EV ) : CSave(NULL), client(cl), dumpEmpty(E), dumpEntvars(EV) {};
|
||||
/*CSave& operator CSave&()
|
||||
{
|
||||
return (CSave&)*this;
|
||||
}*/
|
||||
int WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
|
||||
int WriteEntVars( const char *pname, entvars_t *pev )
|
||||
{
|
||||
if( dumpEntvars )
|
||||
return CSave::WriteEntVars( pname, pev );
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
edict_t *client;
|
||||
bool dumpEmpty;
|
||||
bool dumpEntvars;
|
||||
};
|
||||
#ifdef __GNUC__
|
||||
extern "C" char *__cxa_demangle(const char* mangled_name,
|
||||
char* output_buffer, size_t* length,
|
||||
int* status);
|
||||
#endif
|
||||
#define PRINTARR(pat, type, add) \
|
||||
for( j = 0; j < pTest->fieldSize - 1; j++ ) \
|
||||
Ent_ClientPrintf( client, pat", ", ((type*)pOutputData)[j] add ); \
|
||||
Ent_ClientPrintf( client, pat"\n", ((type*)pOutputData)[pTest->fieldSize - 1] add);
|
||||
|
||||
int CDumper::WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if( !dumpEntvars && !strcmp( pname, "ENTVARS") )
|
||||
return 0;
|
||||
|
||||
Ent_ClientPrintf( client, "%s:\n", pname );
|
||||
|
||||
for( i = 0; i < fieldCount; i++ )
|
||||
{
|
||||
TYPEDESCRIPTION *pTest = &pFields[i];
|
||||
void *pOutputData = ( (char *)pBaseData + pTest->fieldOffset );
|
||||
|
||||
if( !dumpEmpty && FieldEmpty(pTest, pOutputData) )
|
||||
continue;
|
||||
|
||||
if( pTest->fieldSize > 1 )
|
||||
Ent_ClientPrintf( client, "%s : \n", pTest->fieldName );
|
||||
else
|
||||
Ent_ClientPrintf( client, "%s : ", pTest->fieldName );
|
||||
|
||||
switch( pTest->fieldType )
|
||||
{
|
||||
case FIELD_FLOAT:
|
||||
PRINTARR("%f",float,)
|
||||
break;
|
||||
case FIELD_TIME:
|
||||
PRINTARR("%+fs",float,-gpGlobals->time)
|
||||
break;
|
||||
case FIELD_MODELNAME:
|
||||
case FIELD_SOUNDNAME:
|
||||
case FIELD_STRING:
|
||||
for( j = 0; j < pTest->fieldSize - 1; j++ )
|
||||
if(((string_t*)pOutputData)[j])
|
||||
Ent_ClientPrintf( client, "\"%s\", ", STRING(((string_t*)pOutputData)[j]) );
|
||||
else
|
||||
Ent_ClientPrintf( client, "null, ");
|
||||
|
||||
if(((string_t*)pOutputData)[pTest->fieldSize - 1])
|
||||
Ent_ClientPrintf( client, "\"%s\"\n", STRING(((string_t*)pOutputData)[pTest->fieldSize - 1]) );
|
||||
else
|
||||
Ent_ClientPrintf( client, "null\n");
|
||||
break;
|
||||
case FIELD_CLASSPTR:
|
||||
case FIELD_EVARS:
|
||||
case FIELD_EDICT:
|
||||
case FIELD_ENTITY:
|
||||
case FIELD_EHANDLE:
|
||||
for( j = 0; j < pTest->fieldSize; j++ )
|
||||
{
|
||||
CBaseEntity *ent;
|
||||
switch( pTest->fieldType )
|
||||
{
|
||||
case FIELD_EVARS:
|
||||
ent = CBaseEntity::Instance( ( (entvars_t **)pOutputData )[j] );
|
||||
break;
|
||||
case FIELD_CLASSPTR:
|
||||
ent = ( (CBaseEntity **)pOutputData )[j];
|
||||
break;
|
||||
case FIELD_EDICT:
|
||||
ent = CBaseEntity::Instance( ( (edict_t **)pOutputData )[j] );
|
||||
break;
|
||||
case FIELD_ENTITY:
|
||||
ent = CBaseEntity::Instance( ( (EOFFSET *)pOutputData )[j] );
|
||||
break;
|
||||
case FIELD_EHANDLE:
|
||||
ent = (CBaseEntity *)( ( (EHANDLE *)pOutputData)[j] );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if( ent )
|
||||
{
|
||||
const char *classname = "";
|
||||
if( ent->pev->classname )
|
||||
classname = STRING(ent->pev->classname);
|
||||
|
||||
Ent_ClientPrintf( client, "%i %s\n", ENTINDEX(ent->edict()), classname);
|
||||
}
|
||||
else
|
||||
Ent_ClientPrintf( client, "null\n");
|
||||
|
||||
}
|
||||
break;
|
||||
case FIELD_POSITION_VECTOR:
|
||||
case FIELD_VECTOR:
|
||||
for( j = 0; j < pTest->fieldSize; j++ )
|
||||
Ent_ClientPrintf( client, "%f %f %f\n", ((float*)pOutputData)[j*3],((float*)pOutputData)[j*3+1],((float*)pOutputData)[j*3+2] );
|
||||
break;
|
||||
case FIELD_BOOLEAN:
|
||||
case FIELD_INTEGER:
|
||||
PRINTARR("%i",int,)
|
||||
break;
|
||||
case FIELD_SHORT:
|
||||
PRINTARR("%i",short,)
|
||||
break;
|
||||
case FIELD_CHARACTER:
|
||||
for( j = 0; j < pTest->fieldSize; j++ )
|
||||
{
|
||||
signed char c = ((char*)pOutputData)[j];
|
||||
if( c < 32 ) // allow bool/int types
|
||||
Ent_ClientPrintf( client, "\\%d", c);
|
||||
else
|
||||
Ent_ClientPrintf( client, "%c", c);
|
||||
if( c == 0 )
|
||||
break;
|
||||
}
|
||||
Ent_ClientPrintf( client, "\n");
|
||||
break;
|
||||
// For now, just write the address out, we're not going to change memory while doing this yet!
|
||||
case FIELD_POINTER:
|
||||
PRINTARR("%p",void*,)
|
||||
break;
|
||||
case FIELD_FUNCTION:
|
||||
for( j = 0; j < pTest->fieldSize; j++ )
|
||||
{
|
||||
const char *name = NAME_FOR_FUNCTION(((void**)pOutputData)[j]);
|
||||
#ifdef __GNUC__
|
||||
char *demangled = __cxa_demangle( name, NULL, NULL, NULL );
|
||||
if( demangled ) name = demangled;
|
||||
Ent_ClientPrintf( client, "%s\n", name );
|
||||
if( demangled ) free( demangled );
|
||||
#else
|
||||
Ent_ClientPrintf( client, "%s\n", name );
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ALERT( at_error, "Bad field type\n" );
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Ent_Dump_f(edict_t *player)
|
||||
{
|
||||
CDumper dumper( player, atoi(CMD_ARGV(2)), atoi(CMD_ARGV(3)) );
|
||||
edict_t *pent = Ent_FindSingle(player, CMD_ARGV(1));
|
||||
CBaseEntity *ent = CBaseEntity::Instance( pent );
|
||||
if( ent )
|
||||
ent->Save( dumper );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Ent_Fire_f
|
||||
@ -929,6 +1105,8 @@ ucmd_t enttoolscmds[] =
|
||||
{ "ent_fire", Ent_Fire_f },
|
||||
{ "ent_create", Ent_Create_f },
|
||||
{ "ent_getvars", Ent_GetVars_f },
|
||||
{ "ent_dump", Ent_Dump_f },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define SAVERESTORE_H
|
||||
|
||||
class CBaseEntity;
|
||||
|
||||
bool FieldEmpty( TYPEDESCRIPTION *field, void *pOutputData );
|
||||
class CSaveRestoreBuffer
|
||||
{
|
||||
public:
|
||||
@ -65,8 +65,8 @@ public:
|
||||
void WritePositionVector( const char *pname, const Vector &value ); // Offset for landmark if necessary
|
||||
void WritePositionVector( const char *pname, const float *value, int count ); // array of pos vectors
|
||||
void WriteFunction( const char *pname, void **value, int count ); // Save a function pointer
|
||||
int WriteEntVars( const char *pname, entvars_t *pev ); // Save entvars_t (entvars_t)
|
||||
int WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
|
||||
virtual int WriteEntVars( const char *pname, entvars_t *pev ); // Save entvars_t (entvars_t)
|
||||
virtual int WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount );
|
||||
|
||||
private:
|
||||
int DataEmpty( const char *pdata, int size );
|
||||
|
@ -2227,6 +2227,17 @@ int CSave::WriteEntVars( const char *pname, entvars_t *pev )
|
||||
return WriteFields( pname, pev, gEntvarsDescription, ENTVARS_COUNT );
|
||||
}
|
||||
|
||||
bool FieldEmpty( TYPEDESCRIPTION *field, void *pOutputData )
|
||||
{
|
||||
int j;
|
||||
|
||||
for( j = 0; j < field->fieldSize * gSizes[field->fieldType]; j++ )
|
||||
if( ((const char*)pOutputData)[j] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CSave::WriteFields( const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount )
|
||||
{
|
||||
int i, j, actualCount, emptyCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user