aboutsummaryrefslogtreecommitdiff
path: root/mp/src/utils/vbsp/manifest.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/utils/vbsp/manifest.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/utils/vbsp/manifest.cpp')
-rw-r--r--mp/src/utils/vbsp/manifest.cpp568
1 files changed, 568 insertions, 0 deletions
diff --git a/mp/src/utils/vbsp/manifest.cpp b/mp/src/utils/vbsp/manifest.cpp
new file mode 100644
index 00000000..44dd07b8
--- /dev/null
+++ b/mp/src/utils/vbsp/manifest.cpp
@@ -0,0 +1,568 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#include "vbsp.h"
+#include "map_shared.h"
+#include "fgdlib/fgdlib.h"
+#include "manifest.h"
+#include "windows.h"
+
+//-----------------------------------------------------------------------------
+// Purpose: default constructor
+//-----------------------------------------------------------------------------
+CManifestMap::CManifestMap( void )
+{
+ m_RelativeMapFileName[ 0 ] = 0;
+ m_bTopLevelMap = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: default constructor
+//-----------------------------------------------------------------------------
+CManifest::CManifest( void )
+{
+ m_InstancePath[ 0 ] = 0;
+ m_bIsCordoning = false;
+ m_CordoningMapEnt = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: this function will parse through the known keys for the manifest map entry
+// Input : szKey - the key name
+// szValue - the value
+// pManifestMap - the manifest map this belongs to
+// Output : ChunkFileResult_t - result of the parsing
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadManifestMapKeyCallback( const char *szKey, const char *szValue, CManifestMap *pManifestMap )
+{
+ if ( !stricmp( szKey, "Name" ) )
+ {
+ // pManifestMap->m_FriendlyName = szValue;
+ }
+ else if ( !stricmp( szKey, "File" ) )
+ {
+ strcpy( pManifestMap->m_RelativeMapFileName, szValue );
+ }
+ else if ( !stricmp( szKey, "IsPrimary" ) )
+ {
+ // pManifestMap->m_bPrimaryMap = ( atoi( szValue ) == 1 );
+ }
+ else if ( !stricmp( szKey, "IsProtected" ) )
+ {
+ // pManifestMap->m_bCanBeModified = ( atoi( szValue ) != 1 );
+ }
+ else if ( !stricmp( szKey, "TopLevel" ) )
+ {
+ pManifestMap->m_bTopLevelMap = ( atoi( szValue ) == 1 );
+ }
+
+ return ChunkFile_Ok;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: this function is responsible for setting up the manifest map about to be read in
+// Input : pFile - the chunk file being read
+// pDoc - the owning manifest document
+// Output : ChunkFileResult_t - result of the parsing
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadManifestVMFCallback( CChunkFile *pFile, CManifest *pManifest )
+{
+ CManifestMap *pManifestMap = new CManifestMap();
+
+ pManifest->m_Maps.AddToTail( pManifestMap );
+
+ ChunkFileResult_t eResult = pFile->ReadChunk( ( KeyHandler_t )LoadManifestMapKeyCallback, pManifestMap );
+
+ return( eResult );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: this function will load the VMF chunk
+// Input : pFile - the chunk file being read
+// pDoc - the owning manifest document
+// Output : ChunkFileResult_t - result of the parsing
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadManifestMapsCallback( CChunkFile *pFile, CManifest *pManifest )
+{
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "VMF", ( ChunkHandler_t )LoadManifestVMFCallback, pManifest );
+ pFile->PushHandlers(&Handlers);
+
+ ChunkFileResult_t eResult = ChunkFile_Ok;
+
+ eResult = pFile->ReadChunk();
+
+ pFile->PopHandlers();
+
+ return( eResult );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonBoxCallback( CChunkFile *pFile, Cordon_t *pCordon )
+{
+ // Add a box to this cordon.
+ pCordon->m_Boxes.AddToTail();
+ BoundBox &box = pCordon->m_Boxes.Tail();
+
+ // Fill it in with the data from the VMF.
+ return pFile->ReadChunk( (KeyHandler_t)LoadCordonBoxKeyCallback, (void *)&box );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonBoxKeyCallback( const char *szKey, const char *szValue, BoundBox *pBox )
+{
+ if (!stricmp(szKey, "mins"))
+ {
+ CChunkFile::ReadKeyValuePoint(szValue, pBox->bmins);
+ }
+ else if (!stricmp(szKey, "maxs"))
+ {
+ CChunkFile::ReadKeyValuePoint(szValue, pBox->bmaxs);
+ }
+
+ return ChunkFile_Ok;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonKeyCallback( const char *szKey, const char *szValue, Cordon_t *pCordon )
+{
+ if (!stricmp(szKey, "name"))
+ {
+ pCordon->m_szName.Set( szValue );
+ }
+ // Whether this particular cordon volume is active.
+ else if (!stricmp(szKey, "active"))
+ {
+ CChunkFile::ReadKeyValueBool(szValue, pCordon->m_bActive);
+ }
+
+ return ChunkFile_Ok;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonCallback( CChunkFile *pFile, CManifest *pManifest )
+{
+ // Add a new cordon which will be filled in by the key callback
+ pManifest->m_Cordons.AddToTail();
+ Cordon_t &cordon = pManifest->m_Cordons.Tail();
+
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "box", (ChunkHandler_t)CManifest::LoadCordonBoxCallback, (void *)&cordon );
+
+ pFile->PushHandlers(&Handlers);
+ ChunkFileResult_t eResult = pFile->ReadChunk( (KeyHandler_t)LoadCordonKeyCallback, (void *)&cordon );
+ pFile->PopHandlers();
+
+ return(eResult);
+}
+
+
+//-----------------------------------------------------------------------------------------------------------
+// Parses keys that are applicable to all cordons in the map.
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonsKeyCallback( const char *szKey, const char *szValue, CManifest *pManifest )
+{
+ // Whether the cordoning system is enabled or disabled.
+ if ( !stricmp( szKey, "active" ) )
+ {
+ CChunkFile::ReadKeyValueBool( szValue, pManifest->m_bIsCordoning );
+ }
+
+ return ChunkFile_Ok;
+}
+
+
+//-----------------------------------------------------------------------------
+// Parses the VMF chunk that pertains to all the cordons in the map:
+//
+// cordons
+// {
+// "active" "true"
+// cordon
+// {
+// "active" "true"
+// "box"
+// {
+// "mins" "-1024, -1024, -1024"
+// "maxs" "1024, 1024, 1024"
+// }
+// ...may be more boxes...
+// }
+// ...may be more cordons...
+// }
+//
+//-----------------------------------------------------------------------------
+ChunkFileResult_t CManifest::LoadCordonsCallback( CChunkFile *pFile, CManifest *pManifest )
+{
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "cordon", (ChunkHandler_t)CManifest::LoadCordonCallback, pManifest );
+
+ pFile->PushHandlers(&Handlers);
+ ChunkFileResult_t eResult = pFile->ReadChunk( (KeyHandler_t)LoadCordonsKeyCallback, pManifest );
+ pFile->PopHandlers();
+
+ return(eResult);
+}
+
+extern ChunkFileResult_t LoadSolidCallback(CChunkFile *pFile, LoadEntity_t *pLoadEntity);
+
+ChunkFileResult_t CManifest::LoadManifestCordoningPrefsCallback( CChunkFile *pFile, CManifest *pDoc )
+{
+ pDoc->m_CordoningMapEnt = &g_MainMap->entities[g_MainMap->num_entities];
+ g_MainMap->num_entities++;
+ memset( pDoc->m_CordoningMapEnt, 0, sizeof( *pDoc->m_CordoningMapEnt ) );
+ pDoc->m_CordoningMapEnt->firstbrush = g_MainMap->nummapbrushes;
+ pDoc->m_CordoningMapEnt->numbrushes = 0;
+
+ LoadEntity_t LoadEntity;
+ LoadEntity.pEntity = pDoc->m_CordoningMapEnt;
+
+ // No default flags/contents
+ LoadEntity.nBaseFlags = 0;
+ LoadEntity.nBaseContents = 0;
+
+ //
+ // Set up handlers for the subchunks that we are interested in.
+ //
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "cordons", ( ChunkHandler_t )CManifest::LoadCordonsCallback, pDoc );
+ Handlers.AddHandler("solid", (ChunkHandler_t)::LoadSolidCallback, &LoadEntity);
+ pFile->PushHandlers(&Handlers);
+
+ ChunkFileResult_t eResult = ChunkFile_Ok;
+
+ eResult = pFile->ReadChunk();
+
+ pFile->PopHandlers();
+
+ return( eResult );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: this function will create a new entity pair
+// Input : pKey - the key of the pair
+// pValue - the value of the pair
+// Output : returns a newly created epair structure
+//-----------------------------------------------------------------------------
+epair_t *CManifest::CreateEPair( char *pKey, char *pValue )
+{
+ epair_t *pEPair = new epair_t;
+
+ pEPair->key = new char[ strlen( pKey ) + 1 ];
+ pEPair->value = new char[ strlen( pValue ) + 1 ];
+
+ strcpy( pEPair->key, pKey );
+ strcpy( pEPair->value, pValue );
+
+ return pEPair;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: this function will load in all of the submaps belonging to this manifest,
+// except for the top level map, which is loaded separately.
+// Input : pMapFile - the top level map that was previously loaded
+// pszFileName - the absolute file name of the top level map file
+// Output : returns true if all submaps were loaded
+//-----------------------------------------------------------------------------
+bool CManifest::LoadSubMaps( CMapFile *pMapFile, const char *pszFileName )
+{
+ entity_t *InstanceEntity;
+ epair_t *pEPair;
+
+ InstanceEntity = &pMapFile->entities[ pMapFile->num_entities ];
+ pMapFile->num_entities++;
+ memset( InstanceEntity, 0, sizeof( *InstanceEntity ) );
+
+ InstanceEntity->origin.Init( 0.0f, 0.0f, 0.0f );
+ pEPair = CreateEPair( "classname", "worldspawn" );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+
+ for( int i = 0; i < m_Maps.Count(); i++ )
+ {
+ // if ( m_Maps[ i ]->m_bTopLevelMap == false )
+ {
+ char FileName[ MAX_PATH ];
+
+ sprintf( FileName, "%s%s", m_InstancePath, m_Maps[ i ]->m_RelativeMapFileName );
+
+ InstanceEntity = &pMapFile->entities[ pMapFile->num_entities ];
+ pMapFile->num_entities++;
+
+ memset( InstanceEntity, 0, sizeof( *InstanceEntity ) );
+ InstanceEntity->origin.Init( 0.0f, 0.0f, 0.0f );
+
+ pEPair = CreateEPair( "angles", "0 0 0" );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+
+ char temp[ 128 ];
+ sprintf( temp, "%d", GameData::NAME_FIXUP_NONE );
+
+ pEPair = CreateEPair( "fixup_style", temp );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+
+ pEPair = CreateEPair( "classname", "func_instance" );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+
+ pEPair = CreateEPair( "file", m_Maps[ i ]->m_RelativeMapFileName );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+
+ if ( m_Maps[ i ]->m_bTopLevelMap == true )
+ {
+ pEPair = CreateEPair( "toplevel", "1" );
+ pEPair->next = InstanceEntity->epairs;
+ InstanceEntity->epairs = pEPair;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+bool CManifest::LoadVMFManifestUserPrefs( const char *pszFileName )
+{
+ char UserName[ MAX_PATH ], FileName[ MAX_PATH ], UserPrefsFileName[ MAX_PATH ];
+ DWORD UserNameSize;
+
+ UserNameSize = sizeof( UserName );
+ if ( GetUserName( UserName, &UserNameSize ) == 0 )
+ {
+ strcpy( UserPrefsFileName, "default" );
+ }
+
+ sprintf( UserPrefsFileName, "\\%s.vmm_prefs", UserName );
+ V_StripExtension( pszFileName, FileName, sizeof( FileName ) );
+ strcat( FileName, UserPrefsFileName );
+
+ FILE *fp = fopen( FileName, "rb" );
+ if ( !fp )
+ {
+ return false;
+ }
+
+ CChunkFile File;
+ ChunkFileResult_t eResult = File.Open( FileName, ChunkFile_Read );
+
+ if ( eResult == ChunkFile_Ok )
+ {
+ //
+ // Set up handlers for the subchunks that we are interested in.
+ //
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "cordoning", ( ChunkHandler_t )CManifest::LoadManifestCordoningPrefsCallback, this );
+
+ // Handlers.SetErrorHandler( ( ChunkErrorHandler_t )CMapDoc::HandleLoadError, this);
+
+ File.PushHandlers(&Handlers);
+
+ while( eResult == ChunkFile_Ok )
+ {
+ eResult = File.ReadChunk();
+ }
+
+ if ( eResult == ChunkFile_EOF )
+ {
+ eResult = ChunkFile_Ok;
+ }
+
+ File.PopHandlers();
+ }
+
+ if ( eResult == ChunkFile_Ok )
+ {
+ }
+ else
+ {
+ // no pref message for now
+ // GetMainWnd()->MessageBox( File.GetErrorText( eResult ), "Error loading manifest!", MB_OK | MB_ICONEXCLAMATION );
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Loads a .VMM file.
+// Input : pszFileName - Full path of the map file to load.
+//-----------------------------------------------------------------------------
+bool CManifest::LoadVMFManifest( const char *pszFileName )
+{
+ V_StripExtension( pszFileName, m_InstancePath, sizeof( m_InstancePath ) );
+ strcat( m_InstancePath, "\\" );
+
+ CChunkFile File;
+ ChunkFileResult_t eResult = File.Open( pszFileName, ChunkFile_Read );
+ if ( eResult != ChunkFile_Ok )
+ {
+ g_MapError.ReportError( File.GetErrorText( eResult ) );
+ return false;
+ }
+
+ CChunkHandlerMap Handlers;
+ Handlers.AddHandler( "Maps", ( ChunkHandler_t )LoadManifestMapsCallback, this );
+
+ File.PushHandlers(&Handlers);
+
+ while (eResult == ChunkFile_Ok)
+ {
+ eResult = File.ReadChunk();
+ }
+
+ if (eResult == ChunkFile_EOF)
+ {
+ eResult = ChunkFile_Ok;
+ }
+
+ File.PopHandlers();
+
+ if ( eResult == ChunkFile_Ok )
+ {
+ int index = g_Maps.AddToTail( new CMapFile() );
+ g_LoadingMap = g_Maps[ index ];
+ if ( g_MainMap == NULL )
+ {
+ g_MainMap = g_LoadingMap;
+ }
+
+ LoadSubMaps( g_LoadingMap, pszFileName );
+
+ LoadVMFManifestUserPrefs( pszFileName );
+ }
+
+ return ( eResult == ChunkFile_Ok );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CManifest::CordonWorld( )
+{
+ if ( m_bIsCordoning == false )
+ {
+ return;
+ }
+
+ for ( int i = 0; i < g_MainMap->num_entities; i++ )
+ {
+ if ( i == 0 )
+ { // for world spawn, we look at brushes
+ for( int nBrushNum = 0; nBrushNum < g_MainMap->entities[ i ].numbrushes; nBrushNum++ )
+ {
+ int nIndex = g_MainMap->entities[ i ].firstbrush + nBrushNum;
+
+ bool bRemove = true;
+
+ for( int nCordon = 0; nCordon < m_Cordons.Count(); nCordon++ )
+ {
+ if ( m_Cordons[ nCordon ].m_bActive == false )
+ {
+ continue;
+ }
+
+ for( int nBox = 0; nBox < m_Cordons[ nCordon ].m_Boxes.Count(); nBox++ )
+ {
+ if ( m_Cordons[ nCordon ].m_Boxes[ nBox ].IsIntersectingBox( g_MainMap->mapbrushes[ nIndex ].mins, g_MainMap->mapbrushes[ nIndex ].maxs ) == true )
+ {
+ bRemove = false;
+ break;
+ }
+ }
+
+ if ( bRemove == false )
+ {
+ break;
+ }
+ }
+
+ if ( bRemove )
+ {
+ int nSize = ( g_MainMap->entities[ i ].numbrushes - nBrushNum - 1 ) * sizeof( g_MainMap->mapbrushes[ 0 ] );
+ memmove( &g_MainMap->mapbrushes[ nIndex ], &g_MainMap->mapbrushes[ nIndex + 1 ], nSize );
+ g_MainMap->entities[ i ].numbrushes--;
+ nBrushNum--;
+ }
+ }
+ }
+ else if ( &g_MainMap->entities[ i ] != m_CordoningMapEnt )
+ { // for all other entities, even if they include brushes, we look at origin
+ if ( g_MainMap->entities[ i ].numbrushes == 0 && g_MainMap->entities[ i ].epairs == NULL )
+ {
+ continue;
+ }
+
+ bool bRemove = true;
+
+ for( int nCordon = 0; nCordon < m_Cordons.Count(); nCordon++ )
+ {
+ if ( m_Cordons[ nCordon ].m_bActive == false )
+ {
+ continue;
+ }
+
+ for( int nBox = 0; nBox < m_Cordons[ nCordon ].m_Boxes.Count(); nBox++ )
+ {
+ if ( m_Cordons[ nCordon ].m_Boxes[ nBox ].ContainsPoint( g_MainMap->entities[ i ].origin ) == true )
+ {
+ bRemove = false;
+ break;
+ }
+ }
+
+ if ( bRemove == false )
+ {
+ break;
+ }
+ }
+
+ if ( bRemove )
+ {
+ g_MainMap->entities[ i ].numbrushes = 0;
+ g_MainMap->entities[ i ].epairs = NULL;
+ }
+ }
+ }
+
+ if ( m_CordoningMapEnt )
+ {
+ g_MainMap->MoveBrushesToWorldGeneral( m_CordoningMapEnt );
+ m_CordoningMapEnt->numbrushes = 0;
+ m_CordoningMapEnt->epairs = NULL;
+ }
+}