summaryrefslogtreecommitdiff
path: root/engine/sv_precache.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/sv_precache.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/sv_precache.cpp')
-rw-r--r--engine/sv_precache.cpp655
1 files changed, 655 insertions, 0 deletions
diff --git a/engine/sv_precache.cpp b/engine/sv_precache.cpp
new file mode 100644
index 0000000..a66e67d
--- /dev/null
+++ b/engine/sv_precache.cpp
@@ -0,0 +1,655 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "server_pch.h"
+#include "sv_precache.h"
+#include "host.h"
+#include "tier0/icommandline.h"
+#include "MapReslistGenerator.h"
+#include "DownloadListGenerator.h"
+#include "soundchars.h"
+#ifndef SWDS
+#include "vgui_baseui_interface.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+static ConVar sv_forcepreload( "sv_forcepreload", "0", FCVAR_ARCHIVE, "Force server side preloading.");
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int SV_ModelIndex
+//-----------------------------------------------------------------------------
+int SV_ModelIndex (const char *name)
+{
+ return sv.LookupModelIndex( name );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// preload -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_FindOrAddModel(const char *name, bool preload )
+{
+ // Look for a match or an empty slot...
+ int flags = RES_FATALIFMISSING;
+ if ( preload )
+ {
+ flags |= RES_PRELOAD;
+ }
+
+ return sv.PrecacheModel( name, flags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_SoundIndex(const char *name)
+{
+ return sv.LookupSoundIndex( name );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// preload -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_FindOrAddSound(const char *name, bool preload )
+{
+ // Look for a match or an empty slot...
+ int flags = RES_FATALIFMISSING;
+ if ( preload )
+ {
+ flags |= RES_PRELOAD;
+ }
+
+ return sv.PrecacheSound( name, flags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_GenericIndex(const char *name)
+{
+ return sv.LookupGenericIndex( name );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// preload -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_FindOrAddGeneric(const char *name, bool preload )
+{
+ // Look for a match or an empty slot...
+ int flags = RES_FATALIFMISSING;
+ if ( preload )
+ {
+ flags |= RES_PRELOAD;
+ }
+
+ return sv.PrecacheGeneric( name, flags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_DecalIndex(const char *name)
+{
+ return sv.LookupDecalIndex( name );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// preload -
+// Output : int
+//-----------------------------------------------------------------------------
+int SV_FindOrAddDecal(const char *name, bool preload )
+{
+ // Look for a match or an empty slot...
+ int flags = RES_FATALIFMISSING;
+ if ( preload )
+ {
+ flags |= RES_PRELOAD;
+ }
+
+ return sv.PrecacheDecal( name, flags );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+//-----------------------------------------------------------------------------
+void SV_ForceSimpleMaterial( const char *name )
+{
+ DownloadListGenerator().ForceSimpleMaterial( name );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// &mins -
+// &maxs -
+//-----------------------------------------------------------------------------
+void SV_ForceModelBounds( const char *name, const Vector &mins, const Vector &maxs )
+{
+ DownloadListGenerator().ForceModelBounds( name, mins, maxs );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : TABLEID
+//-----------------------------------------------------------------------------
+INetworkStringTable *CGameServer::GetModelPrecacheTable( void ) const
+{
+ return m_pModelPrecacheTable;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// flags -
+// *model -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::PrecacheModel( char const *name, int flags, model_t *model /*=NULL*/ )
+{
+ if ( !m_pModelPrecacheTable )
+ return -1;
+
+ int idx = m_pModelPrecacheTable->AddString( true, name );
+ if ( idx == INVALID_STRING_INDEX )
+ {
+ return -1;
+ }
+
+ CPrecacheUserData p;
+
+ // first time, set file size & flags
+ CPrecacheUserData const *pExisting = (CPrecacheUserData const *)m_pModelPrecacheTable->GetStringUserData( idx, NULL );
+ if ( !pExisting )
+ {
+ p.flags = flags;
+ }
+ else
+ {
+ // Just or in any new flags
+ p = *pExisting;
+ p.flags |= flags;
+ }
+
+ m_pModelPrecacheTable->SetStringUserData( idx, sizeof( p ), &p );
+
+ CPrecacheItem *slot = &model_precache[ idx ];
+
+ if ( model )
+ {
+ slot->SetModel( model );
+ }
+
+ bool bLoadNow;
+ bLoadNow = ( !slot->GetModel() && ( ( flags & RES_PRELOAD ) || IsX360() ) );
+ if ( CommandLine()->FindParm( "-nopreload" ) || CommandLine()->FindParm( "-nopreloadmodels" ))
+ {
+ bLoadNow = false;
+ }
+ else if ( sv_forcepreload.GetInt() || CommandLine()->FindParm( "-preload" ) )
+ {
+ bLoadNow = true;
+ }
+
+ if ( idx != 0 )
+ {
+ if ( bLoadNow )
+ {
+ slot->SetModel( modelloader->GetModelForName( name, IModelLoader::FMODELLOADER_SERVER ) );
+#ifndef SWDS
+ EngineVGui()->UpdateProgressBar(PROGRESS_PRECACHE);
+#endif
+ MapReslistGenerator().OnModelPrecached(name);
+ }
+ else
+ {
+ modelloader->ReferenceModel( name, IModelLoader::FMODELLOADER_SERVER );
+ slot->SetModel( NULL );
+ }
+ }
+
+ return idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+// Output : model_t
+//-----------------------------------------------------------------------------
+model_t *CGameServer::GetModel( int index )
+{
+ if ( index <= 0 || !m_pModelPrecacheTable )
+ return NULL;
+
+ if ( index >= m_pModelPrecacheTable->GetNumStrings() )
+ {
+ return NULL;
+ }
+
+ CPrecacheItem *slot = &model_precache[ index ];
+ model_t *m = slot->GetModel();
+ if ( m )
+ {
+ return m;
+ }
+
+ char const *modelname = m_pModelPrecacheTable->GetString( index );
+ Assert( modelname );
+
+ if ( host_showcachemiss.GetBool() )
+ {
+ ConDMsg( "server model cache miss on %s\n", modelname );
+ }
+
+ m = modelloader->GetModelForName( modelname, IModelLoader::FMODELLOADER_SERVER );
+ slot->SetModel( m );
+
+ return m;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::LookupModelIndex( char const *name )
+{
+ if ( !m_pModelPrecacheTable )
+ return -1;
+
+ int idx = m_pModelPrecacheTable->FindStringIndex( name );
+ return ( idx == INVALID_STRING_INDEX ) ? -1 : idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : TABLEID
+//-----------------------------------------------------------------------------
+INetworkStringTable *CGameServer::GetSoundPrecacheTable( void ) const
+{
+ return m_pSoundPrecacheTable;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// flags -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::PrecacheSound( char const *name, int flags )
+{
+ if ( !m_pSoundPrecacheTable )
+ return -1;
+
+ int idx = m_pSoundPrecacheTable->AddString( true, name );
+ if ( idx == INVALID_STRING_INDEX )
+ {
+ return -1;
+ }
+
+ // mark the sound as being precached, but check first that reslist generation is enabled to save on the va() call
+ if (MapReslistGenerator().IsEnabled() && name[0])
+ {
+ MapReslistGenerator().OnResourcePrecached( va( "sound/%s", PSkipSoundChars( name ) ) );
+ }
+
+ // first time, set file size & flags
+ CPrecacheUserData p;
+ CPrecacheUserData const *pExisting = (CPrecacheUserData const *)m_pSoundPrecacheTable->GetStringUserData( idx, NULL );
+ if ( !pExisting )
+ {
+ p.flags = flags;
+ }
+ else
+ {
+ // Just or in any new flags
+ p = *pExisting;
+ p.flags |= flags;
+ }
+
+ m_pSoundPrecacheTable->SetStringUserData( idx, sizeof( p ), &p );
+
+ CPrecacheItem *slot = &sound_precache[ idx ];
+ slot->SetName( name );
+
+ return idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+// Output : char const
+//-----------------------------------------------------------------------------
+char const *CGameServer::GetSound( int index )
+{
+ if ( index <= 0 || !m_pSoundPrecacheTable )
+ {
+ return NULL;
+ }
+
+ if ( index >= m_pSoundPrecacheTable->GetNumStrings() )
+ {
+ return NULL;
+ }
+
+ CPrecacheItem *slot = &sound_precache[ index ];
+ return slot->GetName();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::LookupSoundIndex( char const *name )
+{
+ if ( !m_pSoundPrecacheTable )
+ return 0;
+
+ int idx = m_pSoundPrecacheTable->FindStringIndex( name );
+ return ( idx == INVALID_STRING_INDEX ) ? 0 : idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : TABLEID
+//-----------------------------------------------------------------------------
+INetworkStringTable *CGameServer::GetGenericPrecacheTable( void ) const
+{
+ return m_pGenericPrecacheTable;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// flags -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::PrecacheGeneric( char const *name, int flags )
+{
+ if ( !m_pGenericPrecacheTable )
+ return -1;
+
+ int idx = m_pGenericPrecacheTable->AddString( true, name );
+
+ if ( idx == INVALID_STRING_INDEX )
+ {
+ return -1;
+ }
+
+ MapReslistGenerator().OnResourcePrecached( name );
+
+ CPrecacheUserData p;
+
+ // first time, set file size & flags
+ CPrecacheUserData const *pExisting = (CPrecacheUserData const *)m_pGenericPrecacheTable->GetStringUserData( idx, NULL );
+ if ( !pExisting )
+ {
+ p.flags = flags;
+
+ }
+ else
+ {
+ // Just or in any new flags
+ p = *pExisting;
+ p.flags |= flags;
+ }
+
+ m_pGenericPrecacheTable->SetStringUserData( idx, sizeof( p ), &p );
+
+ CPrecacheItem *slot = &generic_precache[ idx ];
+ slot->SetGeneric( name );
+ return idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+// Output : char const
+//-----------------------------------------------------------------------------
+char const *CGameServer::GetGeneric( int index )
+{
+ // Bogus index
+ if ( index < 0 || !m_pGenericPrecacheTable )
+ return "";
+
+ if ( index >= m_pGenericPrecacheTable->GetNumStrings() )
+ {
+ return "";
+ }
+
+ CPrecacheItem *slot = &generic_precache[ index ];
+ return slot->GetGeneric();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::LookupGenericIndex( char const *name )
+{
+ if ( !m_pGenericPrecacheTable )
+ return 0;
+
+ int idx = m_pGenericPrecacheTable->FindStringIndex( name );
+
+ return ( idx == INVALID_STRING_INDEX ) ? 0 : idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : TABLEID
+//-----------------------------------------------------------------------------
+INetworkStringTable *CGameServer::GetDecalPrecacheTable( void ) const
+{
+ return m_pDecalPrecacheTable;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// flags -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::PrecacheDecal( char const *name, int flags )
+{
+ if ( !m_pDecalPrecacheTable )
+ return -1;
+
+ int idx = m_pDecalPrecacheTable->AddString( true, name );
+ if ( idx == INVALID_STRING_INDEX )
+ {
+ return -1;
+ }
+
+ MapReslistGenerator().OnResourcePrecached(name);
+
+ CPrecacheUserData p;
+
+ // first time, set file size & flags
+ CPrecacheUserData const *pExisting = (CPrecacheUserData const *)m_pDecalPrecacheTable->GetStringUserData( idx, NULL );
+ if ( !pExisting )
+ {
+ p.flags = flags;
+ }
+ else
+ {
+ // Just or in any new flags
+ p = *pExisting;
+ p.flags |= flags;
+ }
+
+ m_pDecalPrecacheTable->SetStringUserData( idx, sizeof( p ), &p );
+
+ CPrecacheItem *slot = &decal_precache[ idx ];
+ slot->SetDecal( name );
+ return idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *name -
+// Output : int
+//-----------------------------------------------------------------------------
+int CGameServer::LookupDecalIndex( char const *name )
+{
+ if ( !m_pDecalPrecacheTable )
+ return -1;
+
+ int idx = m_pDecalPrecacheTable->FindStringIndex( name );
+ return ( idx == INVALID_STRING_INDEX ) ? -1 : idx;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGameServer::DumpPrecacheStats( INetworkStringTable *table )
+{
+ if ( table == NULL )
+ {
+ ConMsg( "Can only dump stats when active in a level\n" );
+ return;
+ }
+
+ CPrecacheItem *items = NULL;
+ if ( table == m_pModelPrecacheTable )
+ {
+ items = model_precache;
+ }
+ else if ( table == m_pGenericPrecacheTable )
+ {
+ items = generic_precache;
+ }
+ else if ( table == m_pSoundPrecacheTable )
+ {
+ items = sound_precache;
+ }
+ else if ( table == m_pDecalPrecacheTable )
+ {
+ items = decal_precache;
+ }
+
+ if ( !items )
+ return;
+
+ int count = table->GetNumStrings();
+ int maxcount = table->GetMaxStrings();
+
+ ConMsg( "\n" );
+ ConMsg( "Precache table %s: %i of %i slots used\n", table->GetTableName(),
+ count, maxcount );
+
+ for ( int i = 0; i < count; i++ )
+ {
+ char const *name = table->GetString( i );
+ CPrecacheItem *slot = &items[ i ];
+
+ int testLength;
+ const CPrecacheUserData *p = ( const CPrecacheUserData * )table->GetStringUserData( i, &testLength );
+ ErrorIfNot( testLength == sizeof( *p ),
+ ("CGameServer::DumpPrecacheStats: invalid CPrecacheUserData length (%d)", testLength)
+ );
+
+ if ( !name || !slot || !p )
+ continue;
+
+ ConMsg( "%03i: %s (%s): ",
+ i,
+ name,
+ GetFlagString( p->flags ) );
+
+ if ( slot->GetReferenceCount() == 0 )
+ {
+ ConMsg( " never used\n" );
+ }
+ else
+ {
+ ConMsg( " %i refs, first %.2f mru %.2f\n",
+ slot->GetReferenceCount(),
+ slot->GetFirstReference(),
+ slot->GetMostRecentReference() );
+ }
+ }
+
+ ConMsg( "\n" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CON_COMMAND( sv_precacheinfo, "Show precache info." )
+{
+ if ( args.ArgC() == 2 )
+ {
+ char const *table = args[ 1 ];
+
+ bool dumped = true;
+ if ( !Q_strcasecmp( table, "generic" ) )
+ {
+ sv.DumpPrecacheStats( sv.GetGenericPrecacheTable() );
+ }
+ else if ( !Q_strcasecmp( table, "sound" ) )
+ {
+ sv.DumpPrecacheStats( sv.GetSoundPrecacheTable() );
+ }
+ else if ( !Q_strcasecmp( table, "decal" ) )
+ {
+ sv.DumpPrecacheStats( sv.GetDecalPrecacheTable() );
+ }
+ else if ( !Q_strcasecmp( table, "model" ) )
+ {
+ sv.DumpPrecacheStats( sv.GetModelPrecacheTable() );
+ }
+ else
+ {
+ dumped = false;
+ }
+
+ if ( dumped )
+ {
+ return;
+ }
+ }
+
+ // Show all data
+ sv.DumpPrecacheStats( sv.GetGenericPrecacheTable() );
+ sv.DumpPrecacheStats( sv.GetDecalPrecacheTable() );
+ sv.DumpPrecacheStats( sv.GetSoundPrecacheTable() );
+ sv.DumpPrecacheStats( sv.GetModelPrecacheTable() );
+}