forked from vera/halflife-thewastes-sdk
229 lines
4.6 KiB
C++
229 lines
4.6 KiB
C++
/***
|
|
*
|
|
* Copyright (C) 2002 The Wastes Project, All Rights Reserved.
|
|
*
|
|
* This product contains software technology licensed from Id
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
* All Rights Reserved.
|
|
*
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
* The Wastes Project. All other use, distribution, or modification is prohibited
|
|
* without written permission from The Wastes Project.
|
|
*
|
|
***/
|
|
//
|
|
// parsebsp.cpp -> parse bsp entity information client side
|
|
// some of this code was graciously accepted from DMC_Teleporters.cpp
|
|
//
|
|
#include <string.h> // memset
|
|
#include "extdll.h"
|
|
#include "entity_state.h"
|
|
#include "pm_defs.h"
|
|
#include "pm_movevars.h"
|
|
#include "hud_iface.h"
|
|
#include "com_model.h"
|
|
#include "event_api.h"
|
|
#include "com_weapons.h"
|
|
#include "event_flags.h"
|
|
#include "dmc_bspfile.h"
|
|
#include "cl_util.h"
|
|
#include "ParseBspEnt.h"
|
|
#include "ParseBsp.h"
|
|
|
|
#include <vector>
|
|
using namespace std;
|
|
|
|
CParseBsp g_ParseBsp;
|
|
|
|
CParseBsp::CParseBsp()
|
|
{
|
|
memset( m_szCurrentLevel, 0, sizeof( m_szCurrentLevel ) );
|
|
}
|
|
|
|
int CParseBsp::CheckMap()
|
|
{
|
|
if( stricmp( m_szCurrentLevel, gEngfuncs.pfnGetLevelName() ) != 0 )
|
|
{
|
|
strcpy( m_szCurrentLevel, gEngfuncs.pfnGetLevelName() );
|
|
|
|
// Right now this is kind of a strong approach to read entities
|
|
// The entire .bsp must be read for each new entity we wish to read.
|
|
ParseBsp( "worldspawn", new CBspWorldspawn() );
|
|
ParseBsp( "env_fog", new CBspEnvFog() );
|
|
ParseBsp( "env_particlesystem", new CBspEnvParticleSystem() );
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *CParseBsp::ParseEntity( char *pBuf, int &error, CBspEntity *pEnt )
|
|
{
|
|
char key[256];
|
|
char token[ 1024 ];
|
|
int n;
|
|
|
|
while (1)
|
|
{
|
|
// Parse key
|
|
pBuf = gEngfuncs.COM_ParseFile ( pBuf, token );
|
|
if ( token[0] == '}' )
|
|
break;
|
|
|
|
// Ran out of input buffer?
|
|
if ( !pBuf )
|
|
{
|
|
error = 1;
|
|
break;
|
|
}
|
|
|
|
// Store off the key
|
|
strcpy ( key, token );
|
|
|
|
// Fix heynames with trailing spaces
|
|
n = strlen( key );
|
|
while (n && key[n-1] == ' ')
|
|
{
|
|
key[n-1] = 0;
|
|
n--;
|
|
}
|
|
|
|
// Parse value
|
|
pBuf = gEngfuncs.COM_ParseFile ( pBuf, token );
|
|
|
|
// Ran out of buffer?
|
|
if (!pBuf)
|
|
{
|
|
error = 1;
|
|
break;
|
|
}
|
|
|
|
// Hit the end instead of a value?
|
|
if ( token[0] == '}' )
|
|
{
|
|
error = 1;
|
|
break;
|
|
}
|
|
|
|
if ( token[0] == '}' && token[1] == '(' )
|
|
int k = 0;
|
|
|
|
// Assign k/v pair
|
|
pEnt->SetKeyValue( key, token );
|
|
}
|
|
|
|
// Return what's left in the stream
|
|
return pBuf;
|
|
}
|
|
|
|
char *CParseBsp::LoadEntityLump( char *pszFilename )
|
|
{
|
|
FILE *fp;
|
|
int i;
|
|
dheader_t header;
|
|
int size;
|
|
lump_t *curLump;
|
|
char *buffer = NULL;
|
|
|
|
fp = fopen( pszFilename, "rb" );
|
|
if( !fp )
|
|
return NULL;
|
|
|
|
// Read in the .bsp header
|
|
if ( fread(&header, sizeof(dheader_t), 1, fp) != 1 )
|
|
{
|
|
gEngfuncs.Con_Printf("Dmc_LoadEntityLump: Could not read BSP header for map [%s].\n", pszFilename);
|
|
fclose(fp);
|
|
return NULL;
|
|
}
|
|
|
|
// Check the version
|
|
i = header.version;
|
|
if ( i != 29 && i != 30)
|
|
{
|
|
fclose(fp);
|
|
gEngfuncs.Con_Printf("Dmc_LoadEntityLump: Map [%s] has incorrect BSP version (%i should be %i).\n", pszFilename, i, BSPVERSION);
|
|
return NULL;
|
|
}
|
|
|
|
// Get entity lump
|
|
curLump = &header.lumps[ LUMP_ENTITIES ];
|
|
// and entity lump size
|
|
size = curLump->filelen;
|
|
|
|
// Jump to it
|
|
fseek( fp, curLump->fileofs, SEEK_SET );
|
|
|
|
// Allocate sufficient memmory
|
|
buffer = new char[ size + 1 ];
|
|
if ( buffer == NULL )
|
|
{
|
|
fclose(fp);
|
|
gEngfuncs.Con_Printf("Dmc_LoadEntityLump: Couldn't allocate %i bytes\n", size + 1 );
|
|
return NULL;
|
|
}
|
|
|
|
// Read in the entity lump
|
|
fread( buffer, size, 1, fp );
|
|
|
|
// Terminate the string
|
|
buffer[ size ] = '\0';
|
|
|
|
if ( fp )
|
|
{
|
|
fclose(fp);
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
void CParseBsp::LumpPass( char *pBuf, const char *pszClassname, CBspEntity *pEnt )
|
|
{
|
|
char szToken[ 1024 ];
|
|
int error = 0;
|
|
|
|
while( 1 )
|
|
{
|
|
pBuf = gEngfuncs.COM_ParseFile( pBuf, szToken );
|
|
if( pBuf == NULL )
|
|
break;
|
|
|
|
// Didn't find opening brace?
|
|
if( szToken[0] != '{' )
|
|
{
|
|
gEngfuncs.Con_Printf( "CParseBsp::ParseBsp: found %s when expecting {\n", szToken[0] );
|
|
break;
|
|
}
|
|
|
|
pBuf = ParseEntity( pBuf, error, pEnt );
|
|
if( stricmp( pszClassname, pEnt->szClassname ) == 0 )
|
|
pEnt->AddEntity();
|
|
|
|
if( error )
|
|
{
|
|
gEngfuncs.Con_Printf( "CParseBsp::ParseBsp: error parsing entities\n" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete pEnt;
|
|
}
|
|
|
|
void CParseBsp::ParseBsp( const char *pszClassname, CBspEntity *pEnt )
|
|
{
|
|
char szFilename[256];
|
|
char *pBuf;
|
|
|
|
sprintf( szFilename, "%s/%s", gEngfuncs.pfnGetGameDirectory(), m_szCurrentLevel );
|
|
|
|
pBuf = LoadEntityLump( szFilename );
|
|
if( pBuf != NULL )
|
|
{
|
|
LumpPass( pBuf, pszClassname, pEnt );
|
|
delete[] pBuf;
|
|
}
|
|
}
|
|
|
|
|