halflife-thewastes-sdk/cl_dll/parsebsp.cpp
2023-09-09 03:01:15 +03:00

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