From dff851cc74cac6fe2351f12b85e2917f6dcc99f1 Mon Sep 17 00:00:00 2001 From: g-cont Date: Sun, 11 Jan 2009 00:00:00 +0300 Subject: [PATCH] 11 Jan 2009 --- client/hud/hud.h | 2 + client/hud/hud_msg.cpp | 16 +++ engine/server/server.h | 2 + engine/server/sv_game.c | 96 +++++++--------- engine/server/sv_save.c | 210 +++++++++++++++++++--------------- launch/utils.c | 19 ++- public/qfiles_ref.h | 7 +- public/svgame_api.h | 3 +- release.bat | 2 +- server/ents/baseentity.cpp | 5 +- server/ents/baselogic.cpp | 2 +- server/ents/basephys.cpp | 59 ++++++++++ server/global/dll_int.cpp | 3 +- server/global/saverestore.cpp | 14 ++- server/server.dsp | 4 + 15 files changed, 287 insertions(+), 157 deletions(-) create mode 100644 server/ents/basephys.cpp diff --git a/client/hud/hud.h b/client/hud/hud.h index 34644cd7..736af020 100644 --- a/client/hud/hud.h +++ b/client/hud/hud.h @@ -629,6 +629,8 @@ public: // user messages int _cdecl MsgFunc_Damage( const char *pszName, int iSize, void *pbuf ); int _cdecl MsgFunc_GameMode( const char *pszName, int iSize, void *pbuf ); + int _cdecl MsgFunc_RoomType( const char *pszName, int iSize, void *pbuf ); + int _cdecl MsgFunc_ScreenFade( const char *pszName, int iSize, void *pbuf ); int _cdecl MsgFunc_ServerName( const char *pszName, int iSize, void *pbuf ); int _cdecl MsgFunc_ResetHUD( const char *pszName, int iSize, void *pbuf); int _cdecl MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf ); diff --git a/client/hud/hud_msg.cpp b/client/hud/hud_msg.cpp index 7115400c..b82167ae 100644 --- a/client/hud/hud_msg.cpp +++ b/client/hud/hud_msg.cpp @@ -22,10 +22,12 @@ // CHud message handlers DECLARE_HUDMESSAGE( HUDColor ); DECLARE_HUDMESSAGE( SetFog ); +DECLARE_HUDMESSAGE( RoomType ); DECLARE_HUDMESSAGE( SetSky ); DECLARE_HUDMESSAGE( RainData ); DECLARE_HUDMESSAGE( SetBody ); DECLARE_HUDMESSAGE( SetSkin ); +DECLARE_HUDMESSAGE( ScreenFade ); DECLARE_HUDMESSAGE( WeaponAnim ); DECLARE_HUDMESSAGE( ResetHUD ); DECLARE_HUDMESSAGE( InitHUD ); @@ -51,6 +53,7 @@ int CHud :: InitMessages( void ) HOOK_MESSAGE( InitHUD ); HOOK_MESSAGE( ViewMode ); HOOK_MESSAGE( Concuss ); + HOOK_MESSAGE( RoomType ); HOOK_MESSAGE( HUDColor ); HOOK_MESSAGE( Particle ); HOOK_MESSAGE( TempEntity ); @@ -64,6 +67,7 @@ int CHud :: InitMessages( void ) HOOK_MESSAGE( AddMirror); HOOK_MESSAGE( AddScreen ); HOOK_MESSAGE( AddPortal ); + HOOK_MESSAGE( ScreenFade ); HOOK_MESSAGE( ScreenShake ); viewEntityIndex = 0; // trigger_viewset stuff @@ -389,6 +393,18 @@ int CHud::MsgFunc_ServerName( const char *pszName, int iSize, void *pbuf ) return 1; } +int CHud :: MsgFunc_RoomType( const char *pszName, int iSize, void *pbuf ) +{ + // FIXME: needs callback to sound engine + return 1; +} + +int CHud :: MsgFunc_ScreenFade( const char *pszName, int iSize, void *pbuf ) +{ + // FIXME: implement + return 1; +} + int CHud::MsgFunc_ScreenShake( const char *pszName, int iSize, void *pbuf ) { BEGIN_READ( pszName, iSize, pbuf ); diff --git a/engine/server/server.h b/engine/server/server.h index e53182d7..211f450b 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -219,6 +219,7 @@ typedef struct DLL_FUNCTIONS dllFuncs; // dll exported funcs byte *mempool; // edicts pool byte *private; // server.dll private pool + byte *temppool; // for parse, save and restore edicts // library exports table word *ordinals; @@ -384,6 +385,7 @@ void SV_CopyTraceToGlobal( trace_t *trace ); void SV_CopyTraceResult( TraceResult *out, trace_t trace ); float SV_AngleMod( float ideal, float current, float speed ); void SV_SpawnEntities( const char *mapname, script_t *entities ); +edict_t* SV_AllocPrivateData( edict_t *ent, string_t className ); string_t SV_AllocString( const char *szValue ); const char *SV_GetString( string_t iString ); diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index b9b149a8..20174c15 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -557,8 +557,11 @@ void SV_SetModel( edict_t *ent, const char *name ) break; } - Matrix3x3_FromAngles( angles, ent->v.m_pmatrix ); - Matrix3x3_Transpose( ent->v.m_pmatrix, ent->v.m_pmatrix ); + if( !sv.loadgame ) + { + Matrix3x3_FromAngles( angles, ent->v.m_pmatrix ); + Matrix3x3_Transpose( ent->v.m_pmatrix, ent->v.m_pmatrix ); + } SV_CreatePhysBody( ent ); } @@ -696,6 +699,39 @@ edict_t *SV_AllocEdict( void ) return pEdict; } +edict_t* SV_AllocPrivateData( edict_t *ent, string_t className ) +{ + const char *pszClassName; + LINK_ENTITY_FUNC SpawnEdict; + + pszClassName = STRING( className ); + if( !ent ) ent = SV_AllocEdict(); + else if( ent->free ) SV_InitEdict( ent ); // FIXME + ent->v.classname = className; + ent->v.pContainingEntity = ent; // re-link + + // allocate edict private memory (passed by dlls) + SpawnEdict = (LINK_ENTITY_FUNC)Com_GetProcAddress( svgame.hInstance, pszClassName ); + if( !SpawnEdict ) + { + // attempt to create custom entity + if( svgame.dllFuncs.pfnCreate( ent, pszClassName ) == -1 ) + { + ent->v.flags |= FL_KILLME; + MsgDev( D_ERROR, "No spawn function for %s\n", pszClassName ); + return ent; // this edict will be removed from map + } + } + else SpawnEdict( &ent->v ); + + Com_Assert( ent->pvServerData == NULL ) + + // also register classname to send for client + ent->pvServerData->s.classname = SV_ClassIndex( pszClassName ); + + return ent; +} + void SV_FreeEdicts( void ) { int i; @@ -1265,31 +1301,7 @@ pfnCreateNamedEntity */ edict_t* pfnCreateNamedEntity( string_t className ) { - edict_t *ent; - const char *pszClassName; - LINK_ENTITY_FUNC SpawnEdict; - - pszClassName = STRING( className ); - ent = pfnCreateEntity(); - ent->v.classname = className; - - // allocate edict private memory (passed by dlls) - SpawnEdict = (LINK_ENTITY_FUNC)Com_GetProcAddress( svgame.hInstance, pszClassName ); - if( !SpawnEdict ) - { - // attempt to create custom entity - if( svgame.dllFuncs.pfnCreate( ent, pszClassName ) == -1 ) - { - MsgDev( D_ERROR, "No spawn function for %s\n", pszClassName ); - return ent; // this edict needs to be alloced pvPrivateData - } - } - else SpawnEdict( &ent->v ); - - // also register classname to send for client - ent->pvServerData->s.classname = SV_ClassIndex( pszClassName ); - - return ent; + return SV_AllocPrivateData( NULL, className ); } /* @@ -2818,11 +2830,9 @@ bool SV_ParseEdict( script_t *script, edict_t *ent ) KeyValueData pkvd[256]; // per one entity int i, numpairs = 0; const char *classname = NULL; - LINK_ENTITY_FUNC SpawnEdict; - byte *tempstr; token_t token; - tempstr = Mem_AllocPool( "SV Temp Strings" ); + svgame.temppool = Mem_AllocPool( "SV Temp Strings" ); // go through all the dictionary pairs while( 1 ) @@ -2848,8 +2858,8 @@ bool SV_ParseEdict( script_t *script, edict_t *ent ) // create keyvalue strings pkvd[numpairs].szClassName = (char *)classname; // unknown at this moment - pkvd[numpairs].szKeyName = com.stralloc( tempstr, keyname, __FILE__, __LINE__ ); - pkvd[numpairs].szValue = com.stralloc( tempstr, token.string, __FILE__, __LINE__ ); + pkvd[numpairs].szKeyName = com.stralloc( svgame.temppool, keyname, __FILE__, __LINE__ ); + pkvd[numpairs].szValue = com.stralloc( svgame.temppool, token.string, __FILE__, __LINE__ ); pkvd[numpairs].fHandled = false; if( !com.strcmp( keyname, "classname" ) && classname == NULL ) @@ -2857,33 +2867,15 @@ bool SV_ParseEdict( script_t *script, edict_t *ent ) if( ++numpairs >= 256 ) break; } - // allocate edict private memory (passed by dlls) - SpawnEdict = (LINK_ENTITY_FUNC)Com_GetProcAddress( svgame.hInstance, classname ); - if( !SpawnEdict ) - { - // attempt to create custom entity - if( svgame.dllFuncs.pfnCreate( ent, classname ) == -1 ) - { - MsgDev( D_ERROR, "No spawn function for %s\n", classname ); - Mem_FreePool( &tempstr ); - return false; - } - } - else - { - ent->v.classname = MAKE_STRING( classname ); - SpawnEdict( &ent->v ); - } + ent = SV_AllocPrivateData( ent, MAKE_STRING( classname )); - // apply classname to keyvalue containers and parse fields - ent->pvServerData->s.classname = SV_ClassIndex( classname ); for( i = 0; i < numpairs; i++ ) { if( pkvd[i].fHandled ) continue; pkvd[i].szClassName = (char *)classname; svgame.dllFuncs.pfnKeyValue( ent, &pkvd[i] ); } - Mem_FreePool( &tempstr ); + Mem_FreePool( &svgame.temppool ); return true; } diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index d420ccae..2213778e 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -57,40 +57,51 @@ static TYPEDESCRIPTION gETable[] = DEFINE_FIELD( ENTITYTABLE, classname, FIELD_STRING ), }; -// TEST -uint HashString( const char *pszToken ) +// FIXME: implement _rotr into Xash::stdlib +static uint SV_HashString( const char *pszToken ) { - uint hash = 0; + uint hash = 0; while( *pszToken ) hash = _rotr( hash, 4 ) ^ *pszToken++; return hash; } -word TokenHash( const char *pszToken, const char **pTokens, uint tokenCount ) +static word SV_TokenHash( const char *pszToken ) { - word hash = (word)(HashString( pszToken ) % (uint)tokenCount ); - int i, index; + word hash; + int i, index; - for( i = 0; i < tokenCount; i++ ) + // only valid if SAVERESTOREDATA have been initialized + if( !svgame.SaveData.pTokens || !svgame.SaveData.tokenCount ) return 0; + + hash = (word)(SV_HashString( pszToken ) % (uint)svgame.SaveData.tokenCount ); + for( i = 0; i < svgame.SaveData.tokenCount; i++ ) { index = hash + i; - if( index >= tokenCount ) - index -= tokenCount; + if( index >= svgame.SaveData.tokenCount ) + index -= svgame.SaveData.tokenCount; - if( !pTokens[index] || !com.strcmp( pszToken, pTokens[index] )) + if( !svgame.SaveData.pTokens[index] || !com.strcmp( pszToken, svgame.SaveData.pTokens[index] )) { - pTokens[index] = (char *)pszToken; + svgame.SaveData.pTokens[index] = (char *)pszToken; return index; } } - - // Token hash table full!!! - // [Consider doing overflow table(s) after the main table & limiting linear hash table search] - MsgDev( D_ERROR, "CSaveRestoreBuffer :: TokenHash() is COMPLETELY FULL!" ); + + // consider doing overflow table(s) after the main table & limiting linear hash table search + MsgDev( D_ERROR, "SV_TokenHash is completely full!\n" ); return 0; } +static void SV_UpdateTokens( const TYPEDESCRIPTION *fields, int fieldCount ) +{ + int i; + + for( i = 0; i < fieldCount; i++, fields++ ) + SV_TokenHash( fields->fieldName ); +} + static void SV_AddSaveLump( wfile_t *f, const char *lumpname, void *data, size_t len, bool compress ) { if( f ) WAD_Write( f, lumpname, data, len, TYPE_BINDATA, ( compress ? CMP_ZLIB : CMP_NONE )); @@ -104,6 +115,26 @@ static void SV_SetPair( const char *name, const char *value, dkeyvalue_t *cvars, (*numpairs)++; // increase epairs } +static void SV_SaveBuffer( wfile_t *f, const char *lumpname, bool compress ) +{ + // write result into lump + SV_AddSaveLump( f, lumpname, svgame.SaveData.pBaseData, svgame.SaveData.size, compress ); + + // clear buffer after writing + Mem_Set( svgame.SaveData.pBaseData, 0, svgame.SaveData.bufferSize ); + svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; + svgame.SaveData.size = 0; // reset current bufSize +} + +static void SV_ReadBuffer( wfile_t *f, const char *lumpname ) +{ + // an older pointer will automatically free memory when calling WAD_Close + // so we don't need to care about it + svgame.SaveData.pBaseData = WAD_Read( f, lumpname, &svgame.SaveData.bufferSize, TYPE_BINDATA ); + svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; + svgame.SaveData.size = 0; // reset current bufSize +} + static void SV_SaveEngineData( wfile_t *f ) { byte *portalstate = NULL; @@ -130,22 +161,22 @@ static void SV_SaveEngineData( wfile_t *f ) static void SV_SaveServerData( wfile_t *f ) { SAVERESTOREDATA *pSaveData; - byte *savepool; + string_t hash_strings[4095]; + int i, numstrings; ENTITYTABLE *pTable; save_header_t shdr; game_header_t ghdr; - int i; // initialize local mempool - savepool = Mem_AllocPool( "Save Pool" ); + svgame.temppool = Mem_AllocPool( "Save Pool" ); // initialize SAVERESTOREDATA Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); svgame.SaveData.bufferSize = 0x80000; // reserve 512K for now - svgame.SaveData.pBaseData = Mem_Alloc( savepool, svgame.SaveData.bufferSize ); + svgame.SaveData.pBaseData = Mem_Alloc( svgame.temppool, svgame.SaveData.bufferSize ); svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; svgame.SaveData.tokenCount = 0xFFF; // assume a maximum of 4K-1 symbol table entries - svgame.SaveData.pTokens = Mem_Alloc( savepool, svgame.SaveData.tokenCount * sizeof( char* )); + svgame.SaveData.pTokens = Mem_Alloc( svgame.temppool, svgame.SaveData.tokenCount * sizeof( char* )); svgame.SaveData.time = svgame.globals->time; pSaveData = svgame.globals->pSaveData = &svgame.SaveData; @@ -165,7 +196,7 @@ static void SV_SaveServerData( wfile_t *f ) // initialize ENTITYTABLE pSaveData->tableCount = svgame.globals->numEntities; - pSaveData->pTable = Mem_Alloc( savepool, pSaveData->tableCount * sizeof( ENTITYTABLE )); + pSaveData->pTable = Mem_Alloc( svgame.temppool, pSaveData->tableCount * sizeof( ENTITYTABLE )); for( i = 0; i < svgame.globals->numEntities; i++ ) { @@ -173,7 +204,6 @@ static void SV_SaveServerData( wfile_t *f ) pTable = &pSaveData->pTable[i]; pTable->id = pent->serialnumber; - if( pent->free ) pTable->flags |= FENTTABLE_REMOVED; pTable->pent = pent; // setup some flags @@ -191,16 +221,20 @@ static void SV_SaveServerData( wfile_t *f ) svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "ADJACENCY", pList, gAdjacency, ARRAYSIZE( gAdjacency )); } + SV_SaveBuffer( f, LUMP_ADJACENCY, false ); + // write entity descriptions for( i = 0; i < svgame.globals->numEntities; i++ ) { edict_t *pent = EDICT_NUM( i ); - if( pent->free ) continue; - svgame.dllFuncs.pfnSave( pent, pSaveData ); + if( !pent->free && pent->v.classname ) + svgame.dllFuncs.pfnSave( pent, pSaveData ); pSaveData->currentIndex++; // move pointer } + SV_SaveBuffer( f, LUMP_ENTITIES, false ); + // write entity table for( i = 0; i < pSaveData->tableCount; i++ ) { @@ -209,12 +243,7 @@ static void SV_SaveServerData( wfile_t *f ) } // write result into lump - SV_AddSaveLump( f, LUMP_ENTITIES, pSaveData->pBaseData, pSaveData->size, false ); - - // clear buffer for global lump - Mem_Set( pSaveData->pBaseData, 0, pSaveData->size ); - pSaveData->pCurrentData = pSaveData->pBaseData; - pSaveData->size = 0; + SV_SaveBuffer( f, LUMP_ENTTABLE, false ); // write game header svgame.dllFuncs.pfnSaveWriteFields( pSaveData, "Game Header", &ghdr, gGameHeader, ARRAYSIZE( gGameHeader )); @@ -223,12 +252,23 @@ static void SV_SaveServerData( wfile_t *f ) svgame.dllFuncs.pfnSaveGlobalState( pSaveData ); // write result into lump - SV_AddSaveLump( f, LUMP_GLOBALS, pSaveData->pBaseData, pSaveData->size, false ); + SV_SaveBuffer( f, LUMP_GLOBALS, false ); + + // save used hash strings + for( i = numstrings = 0; i < svgame.SaveData.tokenCount; i++ ) + { + if( !svgame.SaveData.pTokens[i] ) continue; + hash_strings[numstrings] = StringTable_SetString( svgame.hStringTable, svgame.SaveData.pTokens[i] ); + numstrings++; + } + + // save hash table + SV_AddSaveLump( f, LUMP_HASHTABLE, hash_strings, numstrings * sizeof( string_t ), true ); // do cleanup operations Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); svgame.globals->pSaveData = NULL; - Mem_FreePool( &savepool ); + Mem_FreePool( &svgame.temppool ); } /* @@ -268,7 +308,7 @@ void SV_WriteSaveFile( const char *name, bool autosave ) // write lumps SV_SaveEngineData( savfile ); SV_SaveServerData( savfile ); - StringTable_Save( svgame.hStringTable, savfile ); + StringTable_Save( svgame.hStringTable, savfile ); // must be last WAD_Close( savfile ); @@ -279,29 +319,35 @@ void SV_ReadComment( wfile_t *l ) { SAVERESTOREDATA *pSaveData; game_header_t ghdr; - int i; // initialize SAVERESTOREDATA Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); - svgame.SaveData.pBaseData = WAD_Read( l, LUMP_GLOBALS, &svgame.SaveData.bufferSize, TYPE_BINDATA ); - svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; svgame.SaveData.tokenCount = 0xFFF; // assume a maximum of 4K-1 symbol table entries svgame.SaveData.pTokens = (char **)Z_Malloc( svgame.SaveData.tokenCount * sizeof( char* )); pSaveData = svgame.globals->pSaveData = &svgame.SaveData; + SV_ReadBuffer( l, LUMP_GLOBALS ); - // TEST: tokenize strings - for( i = 0; i < ARRAYSIZE( gGameHeader ); i++ ) - TokenHash( gGameHeader[i].fieldName, svgame.SaveData.pTokens, svgame.SaveData.tokenCount ); + SV_UpdateTokens( gGameHeader, ARRAYSIZE( gGameHeader )); // read game header svgame.dllFuncs.pfnSaveReadFields( pSaveData, "Game Header", &ghdr, gGameHeader, ARRAYSIZE( gGameHeader )); com.strncpy( svs.comment, ghdr.comment, CS_SIZE ); if( svgame.SaveData.pTokens ) Mem_Free( svgame.SaveData.pTokens ); - if( svgame.SaveData.pBaseData ) Mem_Free( svgame.SaveData.pBaseData ); Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); } +void SV_ReadHashTable( wfile_t *l ) +{ + string_t *in_table; + int i, hash_size; + + in_table = (string_t *)WAD_Read( l, LUMP_HASHTABLE, &hash_size, TYPE_BINDATA ); + + for( i = 0; i < hash_size / sizeof( string_t ); i++, in_table++ ) + SV_TokenHash( STRING( *in_table )); +} + void SV_ReadCvars( wfile_t *l ) { dkeyvalue_t *in; @@ -346,24 +392,19 @@ void SV_ReadAreaPortals( wfile_t *l ) void SV_ReadGlobals( wfile_t *l ) { SAVERESTOREDATA *pSaveData; - byte *restorepool; game_header_t ghdr; - int i; // initialize local mempool - // restorepool = Mem_AllocPool( "Restore Pool" ); + svgame.temppool = Mem_AllocPool( "Restore Pool" ); // initialize SAVERESTOREDATA Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); - svgame.SaveData.pBaseData = WAD_Read( l, LUMP_GLOBALS, &svgame.SaveData.bufferSize, TYPE_BINDATA ); - svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; svgame.SaveData.tokenCount = 0xFFF; // assume a maximum of 4K-1 symbol table entries - svgame.SaveData.pTokens = Mem_Alloc( svgame.mempool, svgame.SaveData.tokenCount * sizeof( char* )); + svgame.SaveData.pTokens = Mem_Alloc( svgame.temppool, svgame.SaveData.tokenCount * sizeof( char* )); pSaveData = svgame.globals->pSaveData = &svgame.SaveData; + SV_ReadBuffer( l, LUMP_GLOBALS ); - // TEST: tokenize strings - for( i = 0; i < ARRAYSIZE( gGameHeader ); i++ ) - TokenHash( gGameHeader[i].fieldName, svgame.SaveData.pTokens, svgame.SaveData.tokenCount ); + SV_ReadHashTable( l ); // read the game header svgame.dllFuncs.pfnSaveReadFields( pSaveData, "Game Header", &ghdr, gGameHeader, ARRAYSIZE( gGameHeader )); @@ -376,49 +417,50 @@ void SV_ReadGlobals( wfile_t *l ) svgame.dllFuncs.pfnRestoreGlobalState( pSaveData ); svgame.dllFuncs.pfnServerDeactivate(); - //Mem_FreePool( &restorepool ); + // leave pool unfreed, because we have partially filled hash tokens +} + +void SV_RestoreEdict( edict_t *ent ) +{ + SV_SetPhysForce( ent ); // restore forces ... + SV_SetMassCentre( ent ); // and mass force } void SV_ReadEntities( wfile_t *l ) { SAVERESTOREDATA *pSaveData; - byte *restorepool; ENTITYTABLE *pTable; LEVELLIST *pList; save_header_t shdr; int i; - // initialize local mempool - //restorepool = Mem_AllocPool( "Restore Pool" ); - // SAVERESTOREDATA partially initialized, continue filling pSaveData = svgame.globals->pSaveData = &svgame.SaveData; - svgame.SaveData.pBaseData = WAD_Read( l, LUMP_ENTITIES, &svgame.SaveData.bufferSize, TYPE_BINDATA ); - svgame.SaveData.pCurrentData = svgame.SaveData.pBaseData; - svgame.SaveData.size = 0; + SV_ReadBuffer( l, LUMP_ADJACENCY ); - // TEST: tokenize strings - for( i = 0; i < ARRAYSIZE( gSaveHeader ); i++ ) - TokenHash( gSaveHeader[i].fieldName, svgame.SaveData.pTokens, svgame.SaveData.tokenCount ); - // read save header svgame.dllFuncs.pfnSaveReadFields( pSaveData, "Save Header", &shdr, gSaveHeader, ARRAYSIZE( gSaveHeader )); - SV_ConfigString( CS_MAXCLIENTS, va("%i", Host_MaxClients())); + SV_ConfigString( CS_MAXCLIENTS, va( "%i", Host_MaxClients( ))); com.strncpy( sv.name, shdr.mapName, MAX_STRING ); svgame.globals->mapname = MAKE_STRING( sv.name ); svgame.globals->time = sv.time = shdr.time; pSaveData->connectionCount = shdr.numConnections; + // read ADJACENCY sections + for( i = 0; i < pSaveData->connectionCount; i++ ) + { + pList = &pSaveData->levelList[i]; + svgame.dllFuncs.pfnSaveReadFields( pSaveData, "ADJACENCY", pList, gAdjacency, ARRAYSIZE( gAdjacency )); + } + // initialize ENTITYTABLE pSaveData->tableCount = shdr.numEntities; - pSaveData->pTable = Mem_Alloc( svgame.mempool, pSaveData->tableCount * sizeof( ENTITYTABLE )); + pSaveData->pTable = Mem_Alloc( svgame.temppool, pSaveData->tableCount * sizeof( ENTITYTABLE )); while( svgame.globals->numEntities < shdr.numEntities ) SV_AllocEdict(); // allocate edicts - // TEST: tokenize strings - for( i = 0; i < ARRAYSIZE( gETable ); i++ ) - TokenHash( gETable[i].fieldName, svgame.SaveData.pTokens, svgame.SaveData.tokenCount ); - + SV_ReadBuffer( l, LUMP_ENTTABLE ); + // read entity table for( i = 0; i < pSaveData->tableCount; i++ ) { @@ -430,20 +472,13 @@ void SV_ReadEntities( wfile_t *l ) if( pTable->id != pent->serialnumber ) MsgDev( D_ERROR, "ETABLE id( %i ) != edict->id( %i )\n", pTable->id, pent->serialnumber ); if( pTable->flags & FENTTABLE_REMOVED ) SV_FreeEdict( pent ); + else pent = SV_AllocPrivateData( pent, pTable->classname ); pTable->pent = pent; } - // TEST: tokenize strings - for( i = 0; i < ARRAYSIZE( gAdjacency ); i++ ) - TokenHash( gAdjacency[i].fieldName, svgame.SaveData.pTokens, svgame.SaveData.tokenCount ); + SV_ReadBuffer( l, LUMP_ENTITIES ); + pSaveData->fUseLandmark = true; - // read ADJACENCY sections - for( i = 0; i < pSaveData->connectionCount; i++ ) - { - pList = &pSaveData->levelList[i]; - svgame.dllFuncs.pfnSaveReadFields( pSaveData, "ADJACENCY", pList, gAdjacency, ARRAYSIZE( gAdjacency )); - } - Com_Assert( 1 ); // and read entities ... for( i = 0; i < pSaveData->tableCount; i++ ) { @@ -451,14 +486,18 @@ void SV_ReadEntities( wfile_t *l ) pTable = &pSaveData->pTable[i]; // ignore removed edicts - if( pTable->flags & FENTTABLE_REMOVED ) continue; - svgame.dllFuncs.pfnRestore( pent, pSaveData, (pTable->flags & FENTTABLE_GLOBAL)); + if( !pent->free && pTable->classname ) + { + svgame.dllFuncs.pfnRestore( pent, pSaveData, false ); + SV_RestoreEdict( pent ); + } + pSaveData->currentIndex++; } - + // do cleanup operations Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA )); svgame.globals->pSaveData = NULL; - //Mem_FreePool( &restorepool ); + Mem_FreePool( &svgame.temppool ); } /* @@ -544,13 +583,4 @@ bool SV_GetComment( char *comment, int savenum ) WAD_Close( savfile ); return true; -} - -void SV_RestoreEdict( edict_t *ent ) -{ - // link it into the bsp tree - SV_LinkEdict( ent ); - SV_CreatePhysBody( ent ); - SV_SetPhysForce( ent ); // restore forces ... - SV_SetMassCentre( ent ); // and mass force } \ No newline at end of file diff --git a/launch/utils.c b/launch/utils.c index b1e319d8..b049fa1f 100644 --- a/launch/utils.c +++ b/launch/utils.c @@ -289,7 +289,7 @@ int StringTable_CreateNewSystem( const char *name, size_t max_strings ) { // found free slot dstring[i] = Mem_Alloc( Sys.basepool, sizeof( stringtable_t )); - dstring[i]->mempool = Mem_AllocPool( va( "StringTable_%s", name )); + dstring[i]->mempool = Mem_AllocPool( va( "StringTable_%s", name )); com.strncpy( dstring[i]->name, name, MAX_STRING ); dstring[i]->maxdatasize = max_strings * 8; dstring[i]->maxstrings = max_strings; @@ -393,13 +393,22 @@ bool StringTable_SaveSystem( int h, wfile_t *wad ) int StringTable_LoadSystem( wfile_t *wad, const char *name ) { + int datasize, table_size; int h = StringTable_CreateNewSystem( name, 0x10000 ); // 65535 unique strings - int datasize, numstrings; + char *data = (char *)W_LoadLump( wad, "stringdata", &datasize, TYPE_STRDATA ); + int *table = (int *)W_LoadLump( wad, "stringtable", &table_size, TYPE_STRDATA ); - dstring[h]->data = W_LoadLump( wad, "stringdata", &datasize, TYPE_STRDATA ); - dstring[h]->table = (int *)W_LoadLump( wad, "stringtable", &numstrings, TYPE_STRDATA ); + if(( datasize > dstring[h]->maxdatasize ) || ((table_size / sizeof( int )) > dstring[h]->maxstrings )) + Sys_Error( "Too small StringTable for loading\n" ); + +#ifndef ST_STATIC_ALLOCATE + dstring[h]->data = Mem_Realloc( dstring[handle]->mempool, dstring[handle]->data, datasize ); + dstring[h]->table = Mem_Realloc( dstring[handle]->mempool, dstring[handle]->table, table_size ); +#endif + Mem_Copy( dstring[h]->data, data, datasize ); + Mem_Copy( dstring[h]->table, table, table_size ); dstring[h]->datasize = datasize; - dstring[h]->numstrings = numstrings / sizeof(int); + dstring[h]->numstrings = table_size / sizeof( int ); return h; } diff --git a/public/qfiles_ref.h b/public/qfiles_ref.h index 80f6a9ad..a55c89ec 100644 --- a/public/qfiles_ref.h +++ b/public/qfiles_ref.h @@ -903,9 +903,12 @@ included global, and both (client & server) pent list */ #define LUMP_CFGSTRING "configstrings" #define LUMP_AREASTATE "areaportals" -#define LUMP_ENTITIES "entities" -#define LUMP_GLOBALS "global_data" +#define LUMP_ENTITIES "entities" // entvars + CBase->fields +#define LUMP_ENTTABLE "enttable" // entity transition table +#define LUMP_ADJACENCY "adjacency" // Save Header + ADJACENCY +#define LUMP_GLOBALS "global_data" // Game Header + Global State #define LUMP_GAMECVARS "latched_cvars" +#define LUMP_HASHTABLE "hashtable" // contains string_t only for used hash-values #define LUMP_SNAPSHOT "saveshot" // currently not implemented #define DENT_KEY 0 diff --git a/public/svgame_api.h b/public/svgame_api.h index 1a96e5d7..7ec1adb4 100644 --- a/public/svgame_api.h +++ b/public/svgame_api.h @@ -228,7 +228,7 @@ typedef struct } ENTITYTABLE; #define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore -#define MAX_LEVEL_CONNECTIONS 32 // These are encoded in the lower 16bits of ENTITYTABLE->flags +#define MAX_LEVEL_CONNECTIONS 16 // These are encoded in the lower 16bits of ENTITYTABLE->flags #define FENTTABLE_GLOBAL 0x10000000 #define FENTTABLE_MOVEABLE 0x20000000 @@ -300,6 +300,7 @@ typedef struct #define DEFINE_FIELD( type, name, fieldtype ) _FIELD( type, name, fieldtype, 1, 0 ) #define DEFINE_ARRAY( type, name, fieldtype, count ) _FIELD( type, name, fieldtype, count, 0 ) #define DEFINE_ENTITY_FIELD( name, fieldtype ) _FIELD( entvars_t, name, fieldtype, 1, 0 ) +#define DEFINE_ENTITY_FIELD_ARRAY( name, fieldtype, count ) _FIELD( entvars_t, name, fieldtype, count, 0 ) #define DEFINE_ENTITY_GLOBAL_FIELD( name, fieldtype ) _FIELD( entvars_t, name, fieldtype, 1, FTYPEDESC_GLOBAL ) #define DEFINE_GLOBAL_FIELD( type, name, fieldtype ) _FIELD( type, name, fieldtype, 1, FTYPEDESC_GLOBAL ) diff --git a/release.bat b/release.bat index b7416417..a0ec5f31 100644 --- a/release.bat +++ b/release.bat @@ -71,5 +71,5 @@ if exist vsound\vsound.plg del /f /q vsound\vsound.plg echo Build succeeded! echo Please wait. Xash is now loading cd D:\Xash3D\ -quake.exe -game tmpQuArK -dev 3 -log +map dm_knot +quake.exe -game tmpQuArK -dev 3 -log +map qctest :done \ No newline at end of file diff --git a/server/ents/baseentity.cpp b/server/ents/baseentity.cpp index 76d81b88..5f64d6a7 100644 --- a/server/ents/baseentity.cpp +++ b/server/ents/baseentity.cpp @@ -891,7 +891,10 @@ int CBaseEntity :: Restore( CRestore &restore ) status = restore.ReadEntVars( "ENTVARS", pev ); if( status ) status = restore.ReadFields( "BASE", this, m_SaveData, ARRAYSIZE( m_SaveData )); - if( pev->modelindex != 0 && !FStringNull( pev->model )) + // restore edict class here + SetObjectClass( m_iClassType ); + + if( pev->modelindex != 0 && !FStringNull( pev->model )) { Vector mins = pev->mins, maxs = pev->maxs; // Set model is about to destroy these diff --git a/server/ents/baselogic.cpp b/server/ents/baselogic.cpp index 56716908..ab1e6f27 100644 --- a/server/ents/baselogic.cpp +++ b/server/ents/baselogic.cpp @@ -1,6 +1,6 @@ //======================================================================= // Copyright (C) Shambler Team 2004 -// logicentity.cpp - all entities with prefix "logic_" +// logicentity.cpp - all entities with prefix "logic_" // additional entities for smart system //======================================================================= diff --git a/server/ents/basephys.cpp b/server/ents/basephys.cpp new file mode 100644 index 00000000..f5f348a9 --- /dev/null +++ b/server/ents/basephys.cpp @@ -0,0 +1,59 @@ +//======================================================================= +// Copyright (C) XashXT Group 2008 +//======================================================================= + +#include "extdll.h" +#include "utils.h" +#include "cbase.h" +#include "client.h" + +class CPhysEntity : public CBaseEntity +{ +public: + void Precache( void ) + { + UTIL_PrecacheModel( pev->model, (char *)Model() ); + } + void Spawn( void ) + { + Precache(); + + pev->movetype = MOVETYPE_PHYSIC; + pev->solid = SolidType(); + pev->owner = ENT( pev ); // g-cont. i'm forget what for needs this stuff :) + + UTIL_SetOrigin( this, pev->origin ); + UTIL_SetModel( ENT( pev ), pev->model, (char *)Model() ); + + SetObjectClass( ED_RIGIDBODY ); + } + virtual const char *Model( void ){ return NULL; } + virtual int SolidType( void ){ return SOLID_MESH; } // generic but slow + void PostActivate( void ) { } // stub +}; +LINK_ENTITY_TO_CLASS( func_physbox, CPhysEntity ); + +// some rigid bodies for Xash3D 0.56 beta +class CPhysSphere : public CPhysEntity +{ +public: + virtual const char *Model( void ){ return "models/props/nexplode.mdl"; } + virtual int SolidType( void ){ return SOLID_SPHERE; } +}; +LINK_ENTITY_TO_CLASS( misc_sphere, CPhysSphere ); + +class CPhysBarrel : public CPhysEntity +{ +public: + virtual const char *Model( void ){ return "models/props/barrel2.mdl"; } + virtual int SolidType( void ){ return SOLID_CYLINDER; } +}; +LINK_ENTITY_TO_CLASS( misc_barrel, CPhysBarrel ); + +class CPhysBox : public CPhysEntity +{ +public: + virtual const char *Model( void ){ return "models/props/box.mdl"; } + virtual int SolidType( void ){ return SOLID_BOX; } +}; +LINK_ENTITY_TO_CLASS( misc_physbox, CPhysBox ); \ No newline at end of file diff --git a/server/global/dll_int.cpp b/server/global/dll_int.cpp index 7199020e..b7d7c35f 100644 --- a/server/global/dll_int.cpp +++ b/server/global/dll_int.cpp @@ -239,11 +239,12 @@ int DispatchRestore( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity { CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent); - if ( pEntity && pSaveData ) + if( pEntity && pSaveData ) { entvars_t tmpVars; Vector oldOffset; + ALERT( at_console, "DispatchRestore( %s )\n", STRING( pent->v.classname )); CRestore restoreHelper( pSaveData ); if ( globalEntity ) { diff --git a/server/global/saverestore.cpp b/server/global/saverestore.cpp index 372fd100..81292cc4 100644 --- a/server/global/saverestore.cpp +++ b/server/global/saverestore.cpp @@ -95,7 +95,17 @@ TYPEDESCRIPTION gEntvarsDescription[] = DEFINE_ENTITY_FIELD( spawnflags, FIELD_INTEGER ), DEFINE_ENTITY_FIELD( flags, FIELD_INTEGER64 ), - +#if 0 + DEFINE_ENTITY_FIELD_ARRAY( m_pmatrix, FIELD_VECTOR, 3 ), + DEFINE_ENTITY_FIELD_ARRAY( m_pcentre, FIELD_VECTOR, 3 ), +#else + DEFINE_ENTITY_FIELD( m_pmatrix[0], FIELD_VECTOR ), + DEFINE_ENTITY_FIELD( m_pmatrix[1], FIELD_VECTOR ), + DEFINE_ENTITY_FIELD( m_pmatrix[2], FIELD_VECTOR ), + DEFINE_ENTITY_FIELD( m_pcentre[0], FIELD_VECTOR ), + DEFINE_ENTITY_FIELD( m_pcentre[1], FIELD_VECTOR ), + DEFINE_ENTITY_FIELD( m_pcentre[2], FIELD_VECTOR ), +#endif DEFINE_ENTITY_FIELD( colormap, FIELD_INTEGER ), DEFINE_ENTITY_FIELD( team, FIELD_INTEGER ), @@ -988,8 +998,6 @@ void CRestore::BufferReadHeader( HEADER *pheader ) pheader->token = ReadShort(); // Read field name token pheader->pData = BufferPointer(); // Field Data is next BufferSkipBytes( pheader->size ); // Advance to next field - - ALERT( at_console, "header.token is %i\n", pheader->token ); } diff --git a/server/server.dsp b/server/server.dsp index e49b187a..ab9ee7e3 100644 --- a/server/server.dsp +++ b/server/server.dsp @@ -185,6 +185,10 @@ SOURCE=.\ents\basepath.cpp # End Source File # Begin Source File +SOURCE=.\ents\basephys.cpp +# End Source File +# Begin Source File + SOURCE=.\ents\baserockets.cpp # End Source File # Begin Source File