diff --git a/interfaces/interfaces.cpp b/interfaces/interfaces.cpp index b0b072fb..fe25c8f6 100644 --- a/interfaces/interfaces.cpp +++ b/interfaces/interfaces.cpp @@ -13,18 +13,19 @@ ICvar *cvar, *g_pCVar; IEventSystem *g_pEventSystem; IProcessUtils *g_pProcessUtils; IPhysics2 *g_pPhysics2; -IPhysics2ActorManager *g_pPhysics2ActorManager; IPhysics2ResourceManager *g_pPhysics2ResourceManager; +IBaseFileSystem *g_pBaseFileSystem; IFileSystem *g_pFullFileSystem; IAsyncFileSystem *g_pAsyncFileSystem; IResourceSystem *g_pResourceSystem; -IMaterialSystem *materials, *g_pMaterialSystem; -IMaterialSystem2 *g_pMaterialSystem2; +IResourceSystemTools *g_pResourceSystemTools; +IMaterialSystem *g_pMaterialSystem; IInputSystem *g_pInputSystem; IInputStackSystem *g_pInputStackSystem; INetworkSystem *g_pNetworkSystem; +INetworkSystemUtils *g_pNetworkSystemUtils; IRenderDeviceMgr *g_pRenderDeviceMgr; -IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig; +IRenderUtils *g_pRenderUtils; ISoundSystem *g_pSoundSystem; IDebugTextureInfo *g_pMaterialSystemDebugTextureInfo; IVBAllocTracker *g_VBAllocTracker; @@ -32,9 +33,6 @@ IColorCorrectionSystem *colorcorrection; IP4 *p4; IMdlLib *mdllib; IQueuedLoader *g_pQueuedLoader; -IResourceAccessControl *g_pResourceAccessControl; -IPrecacheSystem *g_pPrecacheSystem; -IStudioRender *g_pStudioRender, *studiorender; vgui::IVGui *g_pVGui; vgui::IInput *g_pVGuiInput; vgui::IPanel *g_pVGuiPanel; @@ -43,22 +41,101 @@ vgui::ISchemeManager *g_pVGuiSchemeManager; vgui::ISystem *g_pVGuiSystem; ILocalize *g_pLocalize; vgui::ILocalize *g_pVGuiLocalize; -IMatSystemSurface *g_pMatSystemSurface; IDataCache *g_pDataCache; -IMDLCache *g_pMDLCache, *mdlcache; IAvi *g_pAVI; IBik *g_pBIK; +IQuickTime *g_pQuickTime; IDmeMakefileUtils *g_pDmeMakefileUtils; -IPhysicsCollision *g_pPhysicsCollision; ISoundEmitterSystemBase *g_pSoundEmitterSystem; +ISoundEmitterSystemBaseS1 *g_pSoundEmitterSystemS1; IMeshSystem *g_pMeshSystem; +IMeshUtils *g_pMeshUtils; IRenderDevice *g_pRenderDevice; +IRenderDeviceSetup *g_pRenderDeviceSetup; IRenderHardwareConfig *g_pRenderHardwareConfig; ISceneSystem *g_pSceneSystem; +ISceneUtils *g_pSceneUtils; IWorldRendererMgr *g_pWorldRendererMgr; IVGuiRenderSurface *g_pVGuiRenderSurface; IMatchFramework *g_pMatchFramework; -IGameUISystemMgr *g_pGameUISystemMgr; +IResourceManifestRegistry *g_pResourceManifestRegistry; +IResourceHandleUtils *g_pResourceHandleUtils; +ISchemaSystem *g_pSchemaSystem; +IResourceCompilerSystem *g_pResourceCompilerSystem; +IPostProcessingSystem *g_pPostProcessingSystem; +ISoundMixGroupSystem *g_pSoundMixGroupSystem; +ISoundOpSystemEdit *g_pSoundOpSystemEdit; +ISoundOpSystem *g_pSoundOpSystem; +IAssetSystem *g_pAssetSystem; +IAssetSystemTest *g_pAssetSystemTest; +IParticleSystemMgr *g_pParticleSystemMgr; +IVScriptManager *g_pVScriptService; +IToolScriptManager *g_pToolScriptManager; +IPropertyEditorSystem *g_pPropertyEditorSystem; +IModelProcessingSystem *g_pModelProcessingSystem; +IPanoramaUI *g_pPanoramaUI; +IToolFramework2 *g_pToolFramework2; +IMapBuilderMgr *g_pWorldRendererBuilderMgr; +IMapBuilderMgr *g_pLightingBuilderMgr; +IMapBuilderMgr *g_pPhysicsBuilderMgr; +IMapBuilderMgr *g_pVisBuilderMgr; +IMapBuilderMgr *g_pEnvironmentBuilderMgr; +IMapBuilderMgr *g_pBakedLODBuilderMgr; +IHelpSystem *g_pHelpSystem; +IToolSceneNodeFactory *g_pToolSceneNodeFactory; +IToolGameSimulationSystem *g_pToolGameSimulationSystem; +IToolGameSimulationDispatcher *g_pToolGameSimulationDispatcher; +ISchemaTestExternal_Two *g_pSchemaTestExternal_Two; +ISchemaTestExternal_One *g_pSchemaTestExternal_One; +IAnimationSystem *g_pAnimationSystem; +IAnimationSystemUtils *g_pAnimationSystemUtils; +IHammerMapLoader *g_pHammerMapLoader; +IMaterialUtils *g_pMaterialUtils; +IFontManager *g_pFontManager; +ITextLayout *g_pTextLayout; +IAssetPreviewSystem *g_pAssetPreviewSystem; +IAssetBrowserSystem *g_pAssetBrowserSystem; +IVConComm *g_pVConComm; +IConfigurationSystem *g_pConfigurationSystem; +INetworkMessages *g_pNetworkMessages; +IFlattenedSerializers *g_pFlattenedSerializers; +ISource2Client *g_pSource2Client; +ISource2ClientPrediction *g_pSource2ClientPrediction; +ISource2Server *g_pSource2Server; +ISource2ServerSerializers *g_pSource2ServerSerializers; +ISource2Host *g_pSource2Host; +ISource2GameClients *g_pSource2GameClients; +ISource2GameEntities *g_pSource2GameEntities; +IEngineServiceMgr *g_pEngineServiceMgr; +IHostStateMgr *g_pHostStateMgr; +INetworkService *g_pNetworkService; +INetworkClientService *g_pNetworkClientService; +INetworkServerService *g_pNetworkServerService; +ITextMessageMgr *g_pTextMessageMgr; +IToolService *g_pToolService; +IRenderService *g_pRenderService; +IStatsService *g_pStatsService; +IUserInfoChangeService *g_pUserInfoChangeService; +IVProfService *g_pVProfService; +IInputService *g_pInputService; +IMapListService *g_pMapListService; +IGameUIService *g_pGameUIService; +ISoundService *g_pSoundService; +IBenchmarkService *g_pBenchmarkService; +IDebugService *g_pDebugService; +IKeyValueCache *g_pKeyValueCache; +IGameResourceServiceClient *g_pGameResourceServiceClient; +IGameResourceServiceServer *g_pGameResourceServiceServer; +ISource2EngineToClient *g_pSource2EngineToClient; +ISource2EngineToServer *g_pSource2EngineToServer; +ISource2EngineToServerStringTable *g_pSource2EngineToServerStringTable; +ISource2EngineToClientStringTable *g_pSource2EngineToClientStringTable; +ISource2EngineSoundServer *g_pSource2EngineSoundServer; +ISource2EngineSoundClient *g_pSource2EngineSoundClient; + +IServerUploadGameStats *g_pServerUploadGameStats; +IScaleformUI *g_pScaleformUI; +IVR *vr; struct InterfaceGlobals_t { @@ -79,30 +156,32 @@ static const InterfaceGlobals_t g_pInterfaceGlobals[] = { EVENTSYSTEM_INTERFACE_VERSION, &g_pEventSystem }, { PROCESS_UTILS_INTERFACE_VERSION, &g_pProcessUtils }, { VPHYSICS2_INTERFACE_VERSION, &g_pPhysics2 }, - { VPHYSICS2_ACTOR_MGR_INTERFACE_VERSION, &g_pPhysics2ActorManager }, { VPHYSICS2_RESOURCE_MGR_INTERFACE_VERSION, &g_pPhysics2ResourceManager }, + { BASEFILESYSTEM_INTERFACE_VERSION, &g_pBaseFileSystem }, { FILESYSTEM_INTERFACE_VERSION, &g_pFullFileSystem }, { ASYNCFILESYSTEM_INTERFACE_VERSION, &g_pAsyncFileSystem }, { RESOURCESYSTEM_INTERFACE_VERSION, &g_pResourceSystem }, - { MATERIAL_SYSTEM_INTERFACE_VERSION, &materials }, - { MATERIAL_SYSTEM_INTERFACE_VERSION, &g_pMaterialSystem }, - { MATERIAL_SYSTEM2_INTERFACE_VERSION, &g_pMaterialSystem2 }, + { RESOURCESYSTEMTOOLS_INTERFACE_VERSION, &g_pResourceSystemTools }, + { RESOURCEMANIFESTREGISTRY_INTERFACE_VERSION, &g_pResourceManifestRegistry }, + { RESOURCEHANDLEUTILS_INTERFACE_VERSION, &g_pResourceHandleUtils }, + { SCHEMASYSTEM_INTERFACE_VERSION, &g_pSchemaSystem }, + { RESOURCECOMPILERSYSTEM_INTERFACE_VERSION, &g_pResourceCompilerSystem }, + { MATERIAL_SYSTEM2_INTERFACE_VERSION, &g_pMaterialSystem }, + { POSTPROCESSINGSYSTEM_INTERFACE_VERSION, &g_pPostProcessingSystem }, { INPUTSYSTEM_INTERFACE_VERSION, &g_pInputSystem }, { INPUTSTACKSYSTEM_INTERFACE_VERSION, &g_pInputStackSystem }, - { NETWORKSYSTEM_INTERFACE_VERSION, &g_pNetworkSystem }, { RENDER_DEVICE_MGR_INTERFACE_VERSION, &g_pRenderDeviceMgr }, - { MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, &g_pMaterialSystemHardwareConfig }, + { RENDER_UTILS_INTERFACE_VERSION, &g_pRenderUtils }, { SOUNDSYSTEM_INTERFACE_VERSION, &g_pSoundSystem }, + { SOUNDMIXGROUPSYSTEM_INTERFACE_VERSION, &g_pSoundMixGroupSystem }, + { SOUNDOPSYSTEMEDIT_INTERFACE_VERSION, &g_pSoundOpSystemEdit }, + { SOUNDOPSYSTEM_INTERFACE_VERSION, &g_pSoundOpSystem }, { DEBUG_TEXTURE_INFO_VERSION, &g_pMaterialSystemDebugTextureInfo }, { VB_ALLOC_TRACKER_INTERFACE_VERSION, &g_VBAllocTracker }, { COLORCORRECTION_INTERFACE_VERSION, &colorcorrection }, { P4_INTERFACE_VERSION, &p4 }, { MDLLIB_INTERFACE_VERSION, &mdllib }, { QUEUEDLOADER_INTERFACE_VERSION, &g_pQueuedLoader }, - { RESOURCE_ACCESS_CONTROL_INTERFACE_VERSION, &g_pResourceAccessControl }, - { PRECACHE_SYSTEM_INTERFACE_VERSION, &g_pPrecacheSystem }, - { STUDIO_RENDER_INTERFACE_VERSION, &g_pStudioRender }, - { STUDIO_RENDER_INTERFACE_VERSION, &studiorender }, { VGUI_IVGUI_INTERFACE_VERSION, &g_pVGui }, { VGUI_INPUT_INTERFACE_VERSION, &g_pVGuiInput }, { VGUI_PANEL_INTERFACE_VERSION, &g_pVGuiPanel }, @@ -111,23 +190,98 @@ static const InterfaceGlobals_t g_pInterfaceGlobals[] = { VGUI_SYSTEM_INTERFACE_VERSION, &g_pVGuiSystem }, { LOCALIZE_INTERFACE_VERSION, &g_pLocalize }, { LOCALIZE_INTERFACE_VERSION, &g_pVGuiLocalize }, - { MAT_SYSTEM_SURFACE_INTERFACE_VERSION, &g_pMatSystemSurface }, { DATACACHE_INTERFACE_VERSION, &g_pDataCache }, - { MDLCACHE_INTERFACE_VERSION, &g_pMDLCache }, - { MDLCACHE_INTERFACE_VERSION, &mdlcache }, { AVI_INTERFACE_VERSION, &g_pAVI }, { BIK_INTERFACE_VERSION, &g_pBIK }, + { QUICKTIME_INTERFACE_VERSION, &g_pQuickTime }, { DMEMAKEFILE_UTILS_INTERFACE_VERSION, &g_pDmeMakefileUtils }, - { VPHYSICS_COLLISION_INTERFACE_VERSION, &g_pPhysicsCollision }, { SOUNDEMITTERSYSTEM_INTERFACE_VERSION, &g_pSoundEmitterSystem }, + { SOUNDEMITTERSYSTEMS1_INTERFACE_VERSION, &g_pSoundEmitterSystemS1 }, { MESHSYSTEM_INTERFACE_VERSION, &g_pMeshSystem }, + { MESHUTILS_INTERFACE_VERSION, &g_pMeshUtils }, { RENDER_DEVICE_INTERFACE_VERSION, &g_pRenderDevice }, + { RENDER_DEVICE_SETUP_INTERFACE_VERSION, &g_pRenderDeviceSetup }, { RENDER_HARDWARECONFIG_INTERFACE_VERSION, &g_pRenderHardwareConfig }, { SCENESYSTEM_INTERFACE_VERSION, &g_pSceneSystem }, + { SCENEUTILS_INTERFACE_VERSION, &g_pSceneUtils }, { WORLD_RENDERER_MGR_INTERFACE_VERSION, &g_pWorldRendererMgr }, { RENDER_SYSTEM_SURFACE_INTERFACE_VERSION, &g_pVGuiRenderSurface }, + { ASSETSYSTEM_INTERFACE_VERSION, &g_pAssetSystem }, + { ASSETSYSTEMTEST_INTERFACE_VERSION, &g_pAssetSystemTest }, + { PARTICLESYSTEMMGR_INTERFACE_VERSION, &g_pParticleSystemMgr }, + { VSCRIPT_INTERFACE_VERSION, &g_pVScriptService }, + { TOOLSCRIPTMANAGER_INTERFACE_VERSION, &g_pToolScriptManager }, + { PROPERTYEDITORSYSTEM_INTERFACE_VERSION, &g_pPropertyEditorSystem }, + { MODELPROCESSINGSYSTEM_INTERFACE_VERSION, &g_pModelProcessingSystem }, { MATCHFRAMEWORK_INTERFACE_VERSION, &g_pMatchFramework }, - { GAMEUISYSTEMMGR_INTERFACE_VERSION, &g_pGameUISystemMgr } + { PANORAMAUI_INTERFACE_VERSION, &g_pPanoramaUI }, + { TOOLFRAMEWORK2_INTERFACE_VERSION, &g_pToolFramework2 }, + { WORLDRENDERERBUILDER_INTERFACE_VERSION, &g_pWorldRendererBuilderMgr }, + { LIGHTINGBUILDER_INTERFACE_VERSION, &g_pLightingBuilderMgr }, + { PHYSICSBUILDER_INTERFACE_VERSION, &g_pPhysicsBuilderMgr }, + { VISBUILDER_INTERFACE_VERSION, &g_pVisBuilderMgr }, + { ENVIRONMENTBUILDER_INTERFACE_VERSION, &g_pEnvironmentBuilderMgr }, + { BAKEDLODBUILDER_INTERFACE_VERSION, &g_pBakedLODBuilderMgr }, + { HELPSYSTEM_INTERFACE_VERSION, &g_pHelpSystem }, + { TOOLSCENENODEFACTORY_INTERFACE_VERSION, &g_pToolSceneNodeFactory }, + { TOOLGAMESIMULATIONSYSTEM_INTERFACE_VERSION, &g_pToolGameSimulationSystem }, + { TOOLGAMESIMULATIONDISPATCHER_INTERFACE_VERSION, &g_pToolGameSimulationDispatcher }, + { SCHEMATESTEXTERNALTWO_INTERFACE_VERSION, &g_pSchemaTestExternal_Two }, + { SCHEMATESTEXTERNALONE_INTERFACE_VERSION, &g_pSchemaTestExternal_One }, + { ANIMATIONSYSTEM_INTERFACE_VERSION, &g_pAnimationSystem }, + { ANIMATIONSYSTEMUTILS_INTERFACE_VERSION, &g_pAnimationSystemUtils }, + { HAMMERMAPLOADER_INTERFACE_VERSION, &g_pHammerMapLoader }, + { MATERIALUTILS_INTERFACE_VERSION, &g_pMaterialUtils }, + { FONTMANAGER_INTERFACE_VERSION, &g_pFontManager }, + { TEXTLAYOUT_INTERFACE_VERSION, &g_pTextLayout }, + { ASSETPREVIEWSYSTEM_INTERFACE_VERSION, &g_pAssetPreviewSystem }, + { ASSETBROWSERSYSTEM_INTERFACE_VERSION, &g_pAssetBrowserSystem }, + { VCONCOMM_INTERFACE_VERSION, &g_pVConComm }, + { CONFIGURATIONSYSTEM_INTERFACE_VERSION, &g_pConfigurationSystem }, + { NETWORKSYSTEM_INTERFACE_VERSION, &g_pNetworkSystem }, + { NETWORKSYSTEMUTILS_INTERFACE_VERSION, &g_pNetworkSystemUtils }, + { NETWORKMESSAGES_INTERFACE_VERSION, &g_pNetworkMessages }, + { FLATTENEDSERIALIZERS_INTERFACE_VERSION, &g_pFlattenedSerializers }, + { SOURCE2CLIENT_INTERFACE_VERSION, &g_pSource2Client }, + { SOURCE2CLIENTPREDICTION_INTERFACE_VERSION, &g_pSource2ClientPrediction }, + { SOURCE2SERVER_INTERFACE_VERSION, &g_pSource2Server }, + { SOURCE2SERVERSERIALIZERS_INTERFACE_VERSION, &g_pSource2ServerSerializers }, + { SOURCE2HOST_INTERFACE_VERSION, &g_pSource2Host }, + { SOURCE2GAMECLIENTS_INTERFACE_VERSION, &g_pSource2GameClients }, + { SOURCE2GAMEENTITIES_INTERFACE_VERSION, &g_pSource2GameEntities }, + { ENGINESERVICEMGR_INTERFACE_VERSION, &g_pEngineServiceMgr }, + { HOSTSTATEMGR_INTERFACE_VERSION, &g_pHostStateMgr }, + { NETWORKSERVICE_INTERFACE_VERSION, &g_pNetworkService }, + { NETWORKCLIENTSERVICE_INTERFACE_VERSION, &g_pNetworkClientService }, + { NETWORKSERVERSERVICE_INTERFACE_VERSION, &g_pNetworkServerService }, + { TEXTMESSAGEMGR_INTERFACE_VERSION, &g_pTextMessageMgr }, + { TOOLSERVICE_INTERFACE_VERSION, &g_pToolService }, + { RENDERSERVICE_INTERFACE_VERSION, &g_pRenderService }, + { STATSSERVICE_INTERFACE_VERSION, &g_pStatsService }, + { USERINFOCHANGESERVICE_INTERFACE_VERSION, &g_pUserInfoChangeService }, + { VPROFSERVICE_INTERFACE_VERSION, &g_pVProfService }, + { INPUTSERVICE_INTERFACE_VERSION, &g_pInputService }, + { MAPLISTSERVICE_INTERFACE_VERSION, &g_pMapListService }, + { GAMEUISERVICE_INTERFACE_VERSION, &g_pGameUIService }, + { SOUNDSERVICE_INTERFACE_VERSION, &g_pSoundService }, + { BENCHMARKSERVICE_INTERFACE_VERSION, &g_pBenchmarkService }, + { DEBUGSERVICE_INTERFACE_VERSION, &g_pDebugService }, + { KEYVALUECACHE_INTERFACE_VERSION, &g_pKeyValueCache }, + { GAMERESOURCESERVICECLIENT_INTERFACE_VERSION, &g_pGameResourceServiceClient }, + { GAMERESOURCESERVICESERVER_INTERFACE_VERSION, &g_pGameResourceServiceServer }, + { SOURCE2ENGINETOCLIENT_INTERFACE_VERSION, &g_pSource2EngineToClient }, + { SOURCE2ENGINETOSERVER_INTERFACE_VERSION, &g_pSource2EngineToServer }, + { SOURCE2ENGINETOSERVERSTRINGTABLE_INTERFACE_VERSION, &g_pSource2EngineToServerStringTable }, + { SOURCE2ENGINETOCLIENTSTRINGTABLE_INTERFACE_VERSION, &g_pSource2EngineToClientStringTable }, + { SOURCE2ENGINESOUNDSERVER_INTERFACE_VERSION, &g_pSource2EngineSoundServer }, + { SOURCE2ENGINESOUNDCLIENT_INTERFACE_VERSION, &g_pSource2EngineSoundClient }, + /* + .data:4C0E39A8 dd offset aVphysics2_inte ; "VPhysics2_Interface_001" + .data:4C0E39B0 dd offset aVphysics2_hand ; "VPhysics2_Handle_Interface_001" + */ + { SERVERUPLOADGAMESTATS_INTERFACE_VERSION, &g_pServerUploadGameStats }, + { SCALEFORMUI_INTERFACE_VERSION, &g_pScaleformUI }, + { VR_INTERFACE_VERSION, vr } }; static const int NUM_INTERFACES = sizeof(g_pInterfaceGlobals) / sizeof(InterfaceGlobals_t); @@ -143,7 +297,8 @@ void ConnectInterfaces(CreateInterfaceFn *pFactoryList, int nFactoryCount) { if (s_nRegistrationCount < 0) { - Error("APPSYSTEM: In ConnectInterfaces(), s_nRegistrationCount is %d!\n", s_nRegistrationCount); + //Error("APPSYSTEM: In ConnectInterfaces(), s_nRegistrationCount is %d!\n", s_nRegistrationCount); + Plat_ExitProcess(1); s_nConnectionCount++; return; } diff --git a/interfaces/interfaces.vcxproj b/interfaces/interfaces.vcxproj index 1e911219..b17abd03 100644 --- a/interfaces/interfaces.vcxproj +++ b/interfaces/interfaces.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -18,9 +18,11 @@ StaticLibrary + v120 StaticLibrary + v120 diff --git a/lib/public/interfaces.lib b/lib/public/interfaces.lib index 87e4b4c2..6e0bb88f 100644 Binary files a/lib/public/interfaces.lib and b/lib/public/interfaces.lib differ diff --git a/lib/public/tier0.lib b/lib/public/tier0.lib index 33663051..899b2f31 100644 Binary files a/lib/public/tier0.lib and b/lib/public/tier0.lib differ diff --git a/lib/public/tier1.lib b/lib/public/tier1.lib index c89270db..bc1a7896 100644 Binary files a/lib/public/tier1.lib and b/lib/public/tier1.lib differ diff --git a/lib/public/vstdlib.lib b/lib/public/vstdlib.lib index 465e8934..2c734317 100644 Binary files a/lib/public/vstdlib.lib and b/lib/public/vstdlib.lib differ diff --git a/public/appframework/IAppSystem.h b/public/appframework/IAppSystem.h index fc0a3c9a..e9e3e1f1 100644 --- a/public/appframework/IAppSystem.h +++ b/public/appframework/IAppSystem.h @@ -52,6 +52,11 @@ enum AppSystemTier_t APP_SYSTEM_TIER_OTHER, }; +enum BuildType_t +{ + kBuildTypeRelease = 2 +}; + abstract_class IAppSystem { @@ -67,6 +72,7 @@ public: // Init, shutdown virtual InitReturnVal_t Init() = 0; virtual void Shutdown() = 0; + virtual void PreShutdown() = 0; // Returns all dependent libraries virtual const AppSystemInfo_t* GetDependencies() = 0; @@ -79,6 +85,8 @@ public: // Returns whether or not the app system is a singleton virtual bool IsSingleton() = 0; + + virtual BuildType_t GetBuildType() = 0; }; diff --git a/public/eiface.h b/public/eiface.h index 0823b89c..15bb4343 100644 --- a/public/eiface.h +++ b/public/eiface.h @@ -23,23 +23,18 @@ #include "bitvec.h" #include "engine/iserverplugin.h" #include "tier1/bitbuf.h" +#include "tier1/utlstring.h" +#include //----------------------------------------------------------------------------- // forward declarations //----------------------------------------------------------------------------- -class SendTable; class ServerClass; -class IMoveHelper; -struct Ray_t; class CGameTrace; typedef CGameTrace trace_t; struct typedescription_t; class CSaveRestoreData; struct datamap_t; -class SendTable; -class ServerClass; -class IMoveHelper; -struct Ray_t; struct studiohdr_t; class CBaseEntity; class CRestore; @@ -49,7 +44,6 @@ struct vcollide_t; class IRecipientFilter; class CBaseEntity; class ITraceFilter; -struct client_textmessage_t; class INetChannelInfo; class ISpatialPartition; class IScratchPad3D; @@ -61,6 +55,28 @@ class ISPSharedMemory; class CGamestatsData; class CEngineHltvInfo_t; class INetworkStringTable; +class CResourceManifestPrerequisite; +class CEntityLump; +class IPVS; +class IHLTVDirector; +struct SpawnGroupDesc_t; +class IClassnameForMapClassCallback; +struct Entity2Networkable_t; +class CCreateGameServerLoadInfo; +class INavListener; +class CNavData; +struct EconItemInfo_t; +struct EconControlPointInfo_t; +class CEntityHandle; +struct RenderDeviceInfo_t; +struct RenderMultisampleType_t; +struct GameSessionConfiguration_t; +struct StringTableDef_t; +struct HostStateLoopModeType_t; +class ILoopModePrerequisiteRegistry; +struct URLArgument_t; +struct vis_info_t; +class IHLTVServer; namespace google { @@ -70,7 +86,11 @@ namespace google } } -typedef struct player_info_s player_info_t; +typedef uint32 SpawnGroupHandle_t; +typedef uint32 SwapChainHandle_t; + +// This is really an enum included in a proto-generated header. Not sure if we want to include that here. +typedef int ENetworkDisconnectionReason; //----------------------------------------------------------------------------- // defines @@ -82,7 +102,7 @@ typedef struct player_info_s player_info_t; #define DLLEXPORT /* */ #endif -#define INTERFACEVERSION_VENGINESERVER "VEngineServer024" +#define INTERFACEVERSION_VENGINESERVER "Source2EngineToServer001" struct bbox_t { @@ -121,12 +141,34 @@ struct CEntityIndex int _index; }; +//----------------------------------------------------------------------------- +// Purpose: Interface the engine exposes to the game DLL and client DLL +//----------------------------------------------------------------------------- +abstract_class ISource2Engine : public IAppSystem +{ + // Is the game paused? + virtual bool IsPaused() = 0; + + // What is the game timescale multiplied with the host_timescale? + virtual float GetTimescale( void ) const = 0; + + virtual void *FindOrCreateWorldSession( const char *, CResourceManifestPrerequisite * ) = 0; + + virtual void UpdateAddonSearchPaths( bool, bool, const char* ) = 0; + + virtual CEntityLump *GetEntityLumpForTemplate( const char *, bool, const char *, const char * ) = 0; + + virtual uint32 GetStatsAppID() const = 0; +}; + //----------------------------------------------------------------------------- // Purpose: Interface the engine exposes to the game DLL //----------------------------------------------------------------------------- -abstract_class IVEngineServer +abstract_class IVEngineServer2 : public ISource2Engine { public: + virtual CreateInterfaceFn GetGameServerFactory() = 0; + // Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" ) virtual void ChangeLevel( const char *s1, const char *s2 ) = 0; @@ -142,200 +184,29 @@ public: // Is server only accepting local connections? virtual bool IsServerLocalOnly( void ) = 0; - // Is in Hammer editing mode? - virtual int IsInEditMode( void ) = 0; - - // get arbitrary launch options - virtual KeyValues* GetLaunchOptions( void ) = 0; - // Add to the server/client lookup/precache table, the specified string is given a unique index // NOTE: The indices for PrecacheModel are 1 based // a 0 returned from those methods indicates the model or sound was not correctly precached // However, generic and decal are 0 based // If preload is specified, the file is loaded into the server/client's cache memory before level startup, otherwise // it'll only load when actually used (which can cause a disk i/o hitch if it occurs during play of a level). - virtual int PrecacheModel( const char *s, bool preload = false ) = 0; - virtual int PrecacheSentenceFile( const char *s, bool preload = false ) = 0; virtual int PrecacheDecal( const char *name, bool preload = false ) = 0; + virtual bool IsDecalPrecached( const char *s ) const = 0; + virtual int GetPrecachedDecalIndex ( const char *s ) const = 0; + virtual int PrecacheGeneric( const char *s, bool preload = false ) = 0; - - // Check's if the name is precached, but doesn't actually precache the name if not... - virtual bool IsModelPrecached( char const *s ) const = 0; - virtual bool IsDecalPrecached( char const *s ) const = 0; virtual bool IsGenericPrecached( char const *s ) const = 0; - - // Note that sounds are precached using the IEngineSound interface - - // Special purpose PVS checking - // Get the cluster # for the specified position - virtual int GetClusterForOrigin( const Vector &org ) = 0; - // Get the PVS bits for a specified cluster and copy the bits into outputpvs. Returns the number of bytes needed to pack the PVS - virtual int GetPVSForCluster( int cluster, int outputpvslength, unsigned char *outputpvs ) = 0; - // Check whether the specified origin is inside the specified PVS - virtual bool CheckOriginInPVS( const Vector &org, const unsigned char *checkpvs, int checkpvssize ) = 0; - // Check whether the specified worldspace bounding box is inside the specified PVS - virtual bool CheckBoxInPVS( const Vector &mins, const Vector &maxs, const unsigned char *checkpvs, int checkpvssize ) = 0; - + // Returns the server assigned userid for this player. Useful for logging frags, etc. // returns -1 if the edict couldn't be found in the list of players. virtual int GetPlayerUserId( CPlayerSlot clientSlot ) = 0; virtual const char *GetPlayerNetworkIDString( CPlayerSlot clientSlot ) = 0; - virtual bool IsUserIDInUse( int userID ) = 0; // TERROR: used for transitioning - virtual int GetLoadingProgressForUserID( int userID ) = 0; // TERROR: used for transitioning - - // Return the current number of used edict slots - virtual int GetEntityCount( void ) = 0; - - // Return the maximum number of used edict slots - virtual int GetMaxEntityCount( void ) = 0; - - // Return the number of free edict slots - virtual int GetFreeEntityCount( void ) = 0; - // Get stats info interface for a client netchannel virtual INetChannelInfo* GetPlayerNetInfo( CEntityIndex playerIndex ) = 0; - // Allocate space for string and return index/offset of string in global string list - // If iForceEdictIndex is not -1, then it will return the edict with that index. If that edict index - // is already used, it'll return null. - virtual edict_t *CreateEdict( int iForceEdictIndex = -1 ) = 0; - // Remove the specified edict and place back into the free edict list - virtual void RemoveEdict( edict_t *e ) = 0; + virtual bool IsUserIDInUse( int userID ) = 0; // TERROR: used for transitioning + virtual int GetLoadingProgressForUserID( int userID ) = 0; // TERROR: used for transitioning - // Memory allocation for entity class data - virtual void *PvAllocEntPrivateData( long cb ) = 0; - virtual void FreeEntPrivateData( void *pEntity ) = 0; - - // Save/restore uses a special memory allocator (which zeroes newly allocated memory, etc.) - virtual void *SaveAllocMemory( size_t num, size_t size ) = 0; - virtual void SaveFreeMemory( void *pSaveMem ) = 0; - - // Emit an ambient sound associated with the specified entity - virtual void EmitAmbientSound( CEntityIndex entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay = 0.0f ) = 0; - - // Fade out the client's volume level toward silence (or fadePercent) - virtual void FadeClientVolume( CEntityIndex playerIndex, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds ) = 0; - - // Sentences / sentence groups - virtual int SentenceGroupPick( int groupIndex, char *name, int nameBufLen ) = 0; - virtual int SentenceGroupPickSequential( int groupIndex, char *name, int nameBufLen, int sentenceIndex, int reset ) = 0; - virtual int SentenceIndexFromName( const char *pSentenceName ) = 0; - virtual const char *SentenceNameFromIndex( int sentenceIndex ) = 0; - virtual int SentenceGroupIndexFromName( const char *pGroupName ) = 0; - virtual const char *SentenceGroupNameFromIndex( int groupIndex ) = 0; - virtual float SentenceLength( int sentenceIndex ) = 0; - - // Issue a command to the command parser as if it was typed at the server console. - virtual void ServerCommand( const char *str ) = 0; - // Execute any commands currently in the command parser immediately (instead of once per frame) - virtual void ServerExecute( void ) = 0; - // Issue the specified command to the specified client (mimics that client typing the command at the console). - virtual void ClientCommand( CEntityIndex playerIndex, const char *szFmt, ... ) FMTFUNCTION( 3, 4 ) = 0; - - // Set the lightstyle to the specified value and network the change to any connected clients. Note that val must not - // change place in memory (use MAKE_STRING) for anything that's not compiled into your mod. - virtual void LightStyle( int style, const char *val ) = 0; - - // Project a static decal onto the specified entity / model (for level placed decals in the .bsp) - virtual void StaticDecal( const Vector &originInEntitySpace, int decalIndex, CEntityIndex entityIndex, int modelIndex, bool lowpriority ) = 0; - - // Given the current PVS(or PAS) and origin, determine which players should hear/receive the message - virtual void Message_DetermineMulticastRecipients( bool usepas, const Vector& origin, CPlayerBitVec& playerbits ) = 0; - - virtual void SendUserMessage( IRecipientFilter &filter, int message, const google::protobuf::Message &msg ) = 0; - - // Print szMsg to the client console. - virtual void ClientPrintf( CEntityIndex playerIndex, const char *szMsg ) = 0; - - // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) - // Prints the formatted string to the notification area of the screen ( down the right hand edge - // numbered lines starting at position 0 - virtual void Con_NPrintf( int pos, const char *fmt, ... ) = 0; - // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) - // Similar to Con_NPrintf, but allows specifying custom text color and duration information - virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... ) = 0; - - // Change a specified player's "view entity" (i.e., use the view entity position/orientation for rendering the client view) - virtual void SetView( CEntityIndex playerIndex, CEntityIndex viewEntIndex ) = 0; - - // Set the player's crosshair angle - virtual void CrosshairAngle( CEntityIndex playerIndex, float pitch, float yaw ) = 0; - - // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) - virtual void GetGameDir( char *szGetGameDir, int maxlength ) = 0; - - // Used by AI node graph code to determine if .bsp and .ain files are out of date - virtual int CompareFileTime( const char *filename1, const char *filename2, int *iCompare ) = 0; - - // Locks/unlocks the network string tables (.e.g, when adding bots to server, this needs to happen). - // Be sure to reset the lock after executing your code!!! - virtual bool LockNetworkStringTables( bool lock ) = 0; - - // Create a bot with the given name. Player index is -1 if fake client can't be created - virtual CEntityIndex CreateFakeClient( const char *netname ) = 0; - - // Get a convar keyvalue for s specified client - virtual const char *GetClientConVarValue( CEntityIndex clientIndex, const char *name ) = 0; - - // Parse a token from a file - virtual const char *ParseFile( const char *data, char *token, int maxlen ) = 0; - // Copies a file - virtual bool CopyFile( const char *source, const char *destination ) = 0; - - // Reset the pvs, pvssize is the size in bytes of the buffer pointed to by pvs. - // This should be called right before any calls to AddOriginToPVS - virtual void ResetPVS( byte *pvs, int pvssize ) = 0; - // Merge the pvs bits into the current accumulated pvs based on the specified origin ( not that each pvs origin has an 8 world unit fudge factor ) - virtual void AddOriginToPVS( const Vector &origin ) = 0; - - // Mark a specified area portal as open/closed. - // Use SetAreaPortalStates if you want to set a bunch of them at a time. - virtual void SetAreaPortalState( int portalNumber, int isOpen ) = 0; - - // Queue a temp entity for transmission - virtual void PlaybackTempEntity( IRecipientFilter& filter, float delay, const void *pSender, const SendTable *pST, int classID ) = 0; - // Given a node number and the specified PVS, return with the node is in the PVS - virtual int CheckHeadnodeVisible( int nodenum, const byte *pvs, int vissize ) = 0; - // Using area bits, cheeck whether area1 flows into area2 and vice versa (depends on area portal state) - virtual int CheckAreasConnected( int area1, int area2 ) = 0; - // Given an origin, determine which area index the origin is within - virtual int GetArea( const Vector &origin ) = 0; - // Get area portal bit set - virtual void GetAreaBits( int area, unsigned char *bits, int buflen ) = 0; - // Given a view origin (which tells us the area to start looking in) and a portal key, - // fill in the plane that leads out of this area (it points into whatever area it leads to). - virtual bool GetAreaPortalPlane( Vector const &vViewOrigin, int portalKey, VPlane *pPlane ) = 0; - - // Save/restore wrapper - FIXME: At some point we should move this to it's own interface - virtual bool LoadGameState( char const *pMapName, bool createPlayers ) = 0; - virtual void LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName ) = 0; - virtual void ClearSaveDir() = 0; - - // Get the pristine map entity lump string. (e.g., used by CS to reload the map entities when restarting a round.) - virtual const char* GetMapEntitiesString() = 0; - - // Text message system -- lookup the text message of the specified name - virtual client_textmessage_t *TextMessageGet( const char *pName ) = 0; - - // Print a message to the server log file - virtual void LogPrint( const char *msg ) = 0; - virtual bool IsLogEnabled() = 0; - // Builds PVS information for an entity - virtual void BuildEntityClusterList( CEntityIndex edictIndex, PVSInfo_t *pPVSInfo ) = 0; - - // A solid entity moved, update spatial partition - virtual void SolidMoved( CEntityIndex solidEntIndex, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin, bool testSurroundingBoundsOnly ) = 0; - // A trigger entity moved, update spatial partition - virtual void TriggerMoved( CEntityIndex triggerEntIndex, bool testSurroundingBoundsOnly ) = 0; - - // Create/destroy a custom spatial partition - virtual ISpatialPartition *CreateSpatialPartition( const Vector& worldmin, const Vector& worldmax ) = 0; - virtual void DestroySpatialPartition( ISpatialPartition * ) = 0; - - // Draw the brush geometry in the map into the scratch pad. - // Flags is currently unused. - virtual void DrawMapToScratchPad( IScratchPad3D *pPad, unsigned long iFlags ) = 0; - // This returns which entities, to the best of the server's knowledge, the client currently knows about. // This is really which entities were in the snapshot that this client last acked. // This returns a bit vector with one bit for each entity. @@ -345,147 +216,147 @@ public: // Also, this will return NULL if the client doesn't exist or if this client hasn't acked any frames yet. // // iClientIndex is the CLIENT index, so if you use pPlayer->entindex(), subtract 1. - virtual const CBitVec* GetEntityTransmitBitsForClient( int iClientIndex ) = 0; + virtual const CBitVec* GetEntityTransmitBitsForClient( CEntityIndex iClientIndex ) = 0; - // Is the game paused? - virtual bool IsPaused() = 0; + // Given the current PVS(or PAS) and origin, determine which players should hear/receive the message + virtual void Message_DetermineMulticastRecipients( bool usepas, const Vector& origin, CPlayerBitVec& playerbits ) = 0; + + // Issue a command to the command parser as if it was typed at the server console. + virtual void ServerCommand( const char *str ) = 0; + // Issue the specified command to the specified client (mimics that client typing the command at the console). + virtual void ClientCommand( CEntityIndex playerIndex, const char *szFmt, ... ) FMTFUNCTION( 3, 4 ) = 0; + + // Set the lightstyle to the specified value and network the change to any connected clients. Note that val must not + // change place in memory (use MAKE_STRING) for anything that's not compiled into your mod. + virtual void LightStyle( int style, const char *val ) = 0; - // What is the game timescale multiplied with the host_timescale? - virtual float GetTimescale( void ) const = 0; + // Project a static decal onto the specified entity / model (for level placed decals in the .bsp) + virtual void StaticDecal( const Vector &originInEntitySpace, int decalIndex, CEntityIndex entityIndex, int modelIndex, bool lowpriority ) = 0; + + // Print szMsg to the client console. + virtual void ClientPrintf( CEntityIndex playerIndex, const char *szMsg ) = 0; + + // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) + // Prints the formatted string to the notification area of the screen ( down the right hand edge + // numbered lines starting at position 0 + virtual void Con_NPrintf( int pos, const char *fmt, ... ) = 0; + // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) + // Similar to Con_NPrintf, but allows specifying custom text color and duration information + virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... ) = 0; + + virtual bool IsLowViolence() = 0; + virtual bool SetHLTVChatBan( int tvslot, bool bBanned ) = 0; + virtual bool IsAnyClientLowViolence() = 0; + + // Change a specified player's "view entity" (i.e., use the view entity position/orientation for rendering the client view) + virtual void SetView( CEntityIndex playerIndex, CEntityIndex viewEntIndex ) = 0; + + // Locks/unlocks the network string tables (.e.g, when adding bots to server, this needs to happen). + // Be sure to reset the lock after executing your code!!! + virtual bool LockNetworkStringTables( bool lock ) = 0; + + // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) + virtual void GetGameDir( char *szGetGameDir, int maxlength ) = 0; + + // Create a bot with the given name. Player index is -1 if fake client can't be created + virtual CEntityIndex CreateFakeClient( const char *netname ) = 0; + + // Get a convar keyvalue for s specified client + virtual const char *GetClientConVarValue( CEntityIndex clientIndex, const char *name ) = 0; + + // Print a message to the server log file + virtual void LogPrint( const char *msg ) = 0; + virtual bool IsLogEnabled() = 0; + + virtual bool IsSplitScreenPlayer( CEntityIndex ent_num ) = 0; + virtual edict_t *GetSplitScreenPlayerAttachToEdict( CEntityIndex ent_num ) = 0; + virtual int GetNumSplitScreenUsersAttachedToEdict( CEntityIndex ent_num ) = 0; + virtual edict_t *GetSplitScreenPlayerForEdict( CEntityIndex ent_num, int nSlot ) = 0; + + // Ret types might be all wrong for these. Haven't researched yet. + virtual bool IsSpawnGroupLoadedOnClient( CEntityIndex ent_num, SpawnGroupHandle_t spawnGroup ) const = 0; + virtual void UnloadSpawnGroup( SpawnGroupHandle_t spawnGroup, /*ESpawnGroupUnloadOption*/ int) = 0; + virtual void LoadSpawnGroup( const SpawnGroupDesc_t & ) = 0; + virtual void SetSpawnGroupDescription( SpawnGroupHandle_t spawnGroup, const char *pszDescription ) = 0; + virtual bool IsSpawnGroupLoaded( SpawnGroupHandle_t spawnGroup ) const = 0; + virtual bool IsSpawnGroupLoading( SpawnGroupHandle_t spawnGroup ) const = 0; + virtual void MakeSpawnGroupActive( SpawnGroupHandle_t spawnGroup ) = 0; + virtual void SynchronouslySpawnGroup( SpawnGroupHandle_t spawnGroup ) = 0; + virtual void SynchronizeAndBlockUntilLoaded( SpawnGroupHandle_t spawnGroup ) = 0; + + virtual void SetTimescale( float flTimescale ) = 0; + virtual CEntityIndex GetViewEntity( CEntityIndex ent ) = 0; + + // Is the engine in Commentary mode? + virtual int IsInCommentaryMode( void ) = 0; + + virtual uint32 GetAppID() = 0; + + // Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet. + virtual const CSteamID *GetClientSteamID( CEntityIndex clientIndex ) = 0; - // Marks the filename for consistency checking. This should be called after precaching the file. - virtual void ForceExactFile( const char *s ) = 0; virtual void ForceModelBounds( const char *s, const Vector &mins, const Vector &maxs ) = 0; - virtual void ClearSaveDirAfterClientLoad() = 0; - - // Sets a USERINFO client ConVar for a fakeclient - virtual void SetFakeClientConVarValue( CEntityIndex clientIndex, const char *cvar, const char *value ) = 0; // Marks the material (vmt file) for consistency checking. If the client and server have different // contents for the file, the client's vmt can only use the VertexLitGeneric shader, and can only // contain $baseTexture and $bumpmap vars. virtual void ForceSimpleMaterial( const char *s ) = 0; - - // Is the engine in Commentary mode? - virtual int IsInCommentaryMode( void ) = 0; - - // Is the engine running a background map? - virtual bool IsLevelMainMenuBackground( void ) = 0; - - // Mark some area portals as open/closed. It's more efficient to use this - // than a bunch of individual SetAreaPortalState calls. - virtual void SetAreaPortalStates( const int *portalNumbers, const int *isOpen, int nPortals ) = 0; - - // Called when relevant edict state flags change. - virtual void NotifyEdictFlagsChange( CEntityIndex iEdict ) = 0; - virtual CSharedEdictChangeInfo* GetSharedEdictChangeInfo() = 0; - - // Tells the engine we can immdiately re-use all edict indices - // even though we may not have waited enough time - virtual void AllowImmediateEdictReuse( ) = 0; - - // Returns true if the engine is an internal build. i.e. is using the internal bugreporter. - virtual bool IsInternalBuild( void ) = 0; - - virtual IChangeInfoAccessor *GetChangeAccessor( CEntityIndex edictIndex ) = 0; - - // Name of most recently load .sav file - virtual char const *GetMostRecentlyLoadedFileName() = 0; - virtual char const *GetSaveFileName() = 0; - - // Cleans up the cluster list - virtual void CleanUpEntityClusterList( PVSInfo_t *pPVSInfo ) = 0; - - virtual void SetAchievementMgr( IAchievementMgr *pAchievementMgr ) =0; - virtual IAchievementMgr *GetAchievementMgr() = 0; - - virtual int GetAppID() = 0; + // Marks the filename for consistency checking. This should be called after precaching the file. + virtual void ForceExactFile( const char *s ) = 0; - virtual bool IsLowViolence() = 0; - - virtual bool IsAnyClientLowViolence() = 0; - - // Call this to find out the value of a cvar on the client. - // - // It is an asynchronous query, and it will call IServerGameDLL::OnQueryCvarValueFinished when - // the value comes in from the client. - // - // Store the return value if you want to match this specific query to the OnQueryCvarValueFinished call. - // Returns InvalidQueryCvarCookie if the entity is invalid. - virtual QueryCvarCookie_t StartQueryCvarValue( CEntityIndex clientIndex, const char *pName ) = 0; - - virtual void InsertServerCommand( const char *str ) = 0; - - // Fill in the player info structure for the specified player index (name, model, etc.) - virtual bool GetPlayerInfo( CEntityIndex ent_num, player_info_t *pinfo ) = 0; - - // Returns true if this client has been fully authenticated by Steam - virtual bool IsClientFullyAuthenticated( CEntityIndex clientIndex ) = 0; - - // This makes the host run 1 tick per frame instead of checking the system timer to see how many ticks to run in a certain frame. - // i.e. it does the same thing timedemo does. - virtual void SetDedicatedServerBenchmarkMode( bool bBenchmarkMode ) = 0; - - virtual bool IsSplitScreenPlayer( CEntityIndex ent_num ) = 0; - virtual edict_t *GetSplitScreenPlayerAttachToEdict( CEntityIndex ent_num ) = 0; - virtual int GetNumSplitScreenUsersAttachedToEdict( CEntityIndex ent_num ) = 0; - virtual edict_t *GetSplitScreenPlayerForEdict( CEntityIndex ent_num, int nSlot ) = 0; - - // Used by Foundry to hook into the loadgame process and override the entities that are getting loaded. - virtual bool IsOverrideLoadGameEntsOn() = 0; - - // Used by Foundry when it changes an entity (and possibly its class) but preserves its serial number. - virtual void ForceFlushEntity( CEntityIndex iEntity ) = 0; - - //Finds or Creates a shared memory space, the returned pointer will automatically be AddRef()ed - virtual ISPSharedMemory *GetSinglePlayerSharedMemorySpace( const char *szName, int ent_num = MAX_EDICTS ) = 0; - - // Allocate hunk memory - virtual void *AllocLevelStaticData( size_t bytes ) = 0; - - // Gets a list of all clusters' bounds. Returns total number of clusters. - virtual int GetClusterCount() = 0; - virtual int GetAllClusterBounds( bbox_t *pBBoxList, int maxBBox ) = 0; - - virtual bool IsCreatingReslist() = 0; - virtual bool IsCreatingXboxReslist() = 0; - virtual bool IsDedicatedServerForXbox() = 0; - - virtual void Pause( bool bPause, bool bForce = false ) = 0; - - virtual void SetTimescale( float flTimescale ) = 0; - // Methods to set/get a gamestats data container so client & server running in same process can send combined data virtual void SetGamestatsData( CGamestatsData *pGamestatsData ) = 0; virtual CGamestatsData *GetGamestatsData() = 0; - - // Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet. - virtual const CSteamID *GetClientSteamID( CEntityIndex clientIndex ) = 0; - - // Returns the SteamID of the game server - virtual const CSteamID *GetGameServerSteamID() = 0; - - // Update the 360 pacifier/spinner - virtual void RefreshScreenIfNecessary() = 0; - - // Tells the engine to allocate paint surfaces - virtual bool HasPaintMap() = 0; - virtual void PaintSurface( const model_t *model, const Vector& position, const Color& color, float radius ) = 0; - virtual void TracePaintSurface( const model_t *model, const Vector& position, float radius, CUtlVector& surfColor ) = 0; - virtual void RemoveAllPaint() = 0; - + + // Send a client command keyvalues + // keyvalues are deleted inside the function + virtual void ClientCommandKeyValues( CEntityIndex client, KeyValues *pCommand ) = 0; + + // This makes the host run 1 tick per frame instead of checking the system timer to see how many ticks to run in a certain frame. + // i.e. it does the same thing timedemo does. + virtual void SetDedicatedServerBenchmarkMode( bool bBenchmarkMode ) = 0; + + // Returns true if this client has been fully authenticated by Steam + virtual bool IsClientFullyAuthenticated( CPlayerSlot slot ) = 0; + + virtual CGlobalVars *GetServerGlobals() = 0; + + // Sets a USERINFO client ConVar for a fakeclient + virtual void SetFakeClientConVarValue( CEntityIndex clientIndex, const char *cvar, const char *value ) = 0; + + virtual CSharedEdictChangeInfo* GetSharedEdictChangeInfo() = 0; + + virtual void SetAchievementMgr( IAchievementMgr *pAchievementMgr ) =0; + virtual IAchievementMgr *GetAchievementMgr() = 0; + + // Fill in the player info structure for the specified player index (name, model, etc.) + virtual bool GetPlayerInfo( CEntityIndex ent_num, google::protobuf::Message &info ) = 0; + + // Validate session + virtual void HostValidateSession() = 0; + // Returns the XUID of the specified player. It'll be NULL if the player hasn't connected yet. virtual uint64 GetClientXUID( CEntityIndex clientIndex ) = 0; - virtual bool IsActiveApp() = 0; - virtual void DisconnectClient( CEntityIndex clientIndex, /* ENetworkDisconnectionReason */ int reason ) = 0; + //Finds or Creates a shared memory space, the returned pointer will automatically be AddRef()ed + virtual ISPSharedMemory *GetSinglePlayerSharedMemorySpace( const char *szName, int ent_num = MAX_EDICTS ) = 0; + + virtual void *GetPVSForSpawnGroup( SpawnGroupHandle_t spawnGroup ) = 0; + virtual SpawnGroupHandle_t FindSpawnGroupByName( const char *szName ) = 0; + + // Returns the SteamID of the game server + virtual const CSteamID *GetGameServerSteamID() = 0; virtual int GetServerVersion( void ) = 0; - virtual bool SetHLTVChatBan( int, bool ) = 0; - virtual bool IsClientLowViolence( CEntityIndex clientIndex ) = 0; + + virtual void DisconnectClient( CEntityIndex clientIndex, /* ENetworkDisconnectionReason */ int reason ) = 0; + + virtual void GetAllSpawnGroupsWithPVS( CUtlVector *spawnGroups, CUtlVector *pOut ) = 0; + + virtual void P2PGroupChanged() = 0; }; abstract_class IServerGCLobby @@ -495,133 +366,105 @@ public: virtual bool SteamIDAllowedToConnect( const CSteamID &steamId ) const = 0; virtual void UpdateServerDetails( void ) = 0; virtual bool ShouldHibernate() = 0; + virtual bool SteamIDAllowedToP2PConnect( const CSteamID &steamId ) const = 0; }; -#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL006" +#define INTERFACEVERSION_SERVERGAMEDLL "Source2Server001" //----------------------------------------------------------------------------- // Purpose: These are the interfaces that the game .dll exposes to the engine //----------------------------------------------------------------------------- -abstract_class IServerGameDLL +abstract_class ISource2Server : public IAppSystem { public: - // Initialize the game (one-time call when the DLL is first loaded ) - // Return false if there is an error during startup. - virtual bool DLLInit( CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, - CGlobalVars *pGlobals) = 0; - - // This is called when a new game is started. (restart, map) - virtual bool GameInit( void ) = 0; - - virtual void PreChangeLevel( const char *pMapName ) = 0; - - // Called any time a new level is started (after GameInit() also on level transitions within a game) - virtual bool LevelInit( char const *pMapName, - char const *pMapEntities, char const *pOldLevel, - char const *pLandmarkName, bool loadGame, bool background ) = 0; - - // The server is about to activate - virtual void ServerActivate( void ) = 0; - + virtual void SetGlobals( CGlobalVars *pVars ) = 0; + + // Let the game .dll allocate it's own network/shared string tables + virtual void GameCreateNetworkStringTables( void ) = 0; + + virtual void WriteSignonMessages( bf_write &bf ) = 0; + + virtual void EnumSaveRestoreMapClasses( const void *, unsigned long, IClassnameForMapClassCallback * ) = 0; + + virtual void PreWorldUpdate( bool simulating ) = 0; + + virtual CUtlVector &GetEntity2Networkables( void ) const = 0; + virtual bool GetEntity2Networkable( CEntityIndex index, Entity2Networkable_t &out ) = 0; + + virtual void ClearInstancedBaselineFromServerClasses( void ) = 0; + + virtual void GetLevelsFromSaveFile( const char *pszFileName, CUtlVector &out, bool ) = 0; + virtual void ClearSaveDirectory( void ) = 0; + + virtual void *GetEntityInfo() = 0; + + // Called to apply lobby settings to a dedicated server + virtual void ApplyGameSettings( KeyValues *pKV ) = 0; + // The server should run physics/think on all edicts - virtual void GameFrame( bool simulating ) = 0; + // One of these bools is 'simulating'... probably + virtual void GameFrame( bool, bool, bool ) = 0; + + virtual void PreSaveGameLoaded( char const *pSaveName, bool bCurrentlyInGame ) = 0; - // Called once per simulation frame on the final tick - virtual void PreClientUpdate( bool simulating ) = 0; - - // Called when a level is shutdown (including changing levels) - virtual void LevelShutdown( void ) = 0; - // This is called when a game ends (server disconnect, death, restart, load) - // NOT on level transitions within a game - virtual void GameShutdown( void ) = 0; - - // Called once during DLL shutdown - virtual void DLLShutdown( void ) = 0; - - // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - // Right now this is only requested at server startup time so it can't be changed on the fly, etc. - virtual float GetTickInterval( void ) const = 0; + // Returns true if the game DLL wants the server not to be made public. + // Used by commentary system to hide multiplayer commentary servers from the master. + virtual bool ShouldHideFromMasterServer( bool ) = 0; + + virtual void GetMatchmakingTags( char *buf, size_t bufSize ) = 0; + virtual void ServerHibernationUpdate( bool bHibernating ) = 0; + + virtual IServerGCLobby *GetServerGCLobby() = 0; + + virtual void GetMatchmakingGameData( char *buf, size_t bufSize ) = 0; + + // return true to disconnect client due to timeout (used to do stricter timeouts when the game is sure the client isn't loading a map) + virtual bool ShouldTimeoutClient( int nUserID, float flTimeSinceLastReceived ) = 0; + + virtual void Status( void (*inputFunc) (const char *fmt, ...) ) = 0; + + virtual int GetServerGameDLLFlags( void ) const = 0; + + // Get the list of cvars that require tags to show differently in the server browser + virtual void GetTaggedConVarList( KeyValues *pCvarTagList ) = 0; + // Give the list of datatable classes to the engine. The engine matches class names from here with // edict_t::classname to figure out how to encode a class's data for networking virtual ServerClass* GetAllServerClasses( void ) = 0; - - // Returns string describing current .dll. e.g., TeamFortress 2, Half-Life 2. - // Hey, it's more descriptive than just the name of the game directory - virtual const char *GetGameDescription( void ) = 0; - - virtual const char *GetAddonName(void) const = 0; - // Let the game .dll allocate it's own network/shared string tables - virtual void CreateNetworkStringTables( void ) = 0; + virtual const char *GetLoadedMapName( void ) const = 0; - // Save/restore system hooks - virtual CSaveRestoreData *SaveInit( int size ) = 0; - virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveGlobalState( CSaveRestoreData * ) = 0; - virtual void RestoreGlobalState( CSaveRestoreData * ) = 0; - virtual void PreSave( CSaveRestoreData * ) = 0; - virtual void Save( CSaveRestoreData * ) = 0; - virtual void GetSaveComment( char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false ) = 0; - virtual void WriteSaveHeaders( CSaveRestoreData * ) = 0; - virtual void ReadRestoreHeaders( CSaveRestoreData * ) = 0; - virtual void Restore( CSaveRestoreData *, bool ) = 0; - virtual bool IsRestoring() = 0; - virtual bool SupportsSaveRestore() = 0; - - // Returns the number of entities moved across the transition - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) = 0; - // Build the list of maps adjacent to the current map - virtual void BuildAdjacentMapList( void ) = 0; - - // Hand over the StandardSendProxies in the game DLL's module. - virtual CStandardSendProxies* GetStandardSendProxies() = 0; - - // Called once during startup, after the game .dll has been loaded and after the client .dll has also been loaded - virtual void PostInit() = 0; - // Called once per frame even when no level is loaded... - virtual void Think( bool finalTick ) = 0; - -#ifdef _XBOX - virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) = 0; -#endif - - virtual void PreSaveGameLoaded( char const *pSaveName, bool bCurrentlyInGame ) = 0; - - virtual void InvalidateMdlCache() = 0; - - // * This function is new with version 6 of the interface. - // - // This is called when a query from IServerPluginHelpers::StartQueryCvarValue is finished. - // iCookie is the value returned by IServerPluginHelpers::StartQueryCvarValue. - // Added with version 2 of the interface. - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, CEntityIndex playerIndex, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) = 0; - - // Called after tools are initialized (i.e. when Foundry is initialized so we can get IServerFoundry). - virtual void PostToolsInit() = 0; + virtual bool IsPaused( void ) const = 0; + + virtual bool GetNavMeshData( CNavData *pOut ) = 0; + virtual void SetNavMeshData( const CNavData &data ) = 0; + virtual void RegisterNavListener( INavListener *pListener ) = 0; + virtual void UnregisterNavListener( INavListener *pListener ) = 0; + virtual void *GetSpawnDebugInterface( void ) = 0; + virtual void GetAnimationActivityList( CUtlVector &out ) = 0; + virtual void GetAnimationEventList( CUtlVector &out ) = 0; + virtual void FilterPlayerCounts( int *, int *, int * ) = 0; // Called after the steam API has been activated post-level startup virtual void GameServerSteamAPIActivated( void ) = 0; - // - virtual void GetMatchmakingTags( char *buf, size_t bufSize ) = 0; - - virtual void SetServerHibernation( bool bHibernating ) = 0; - - virtual void GetMatchmakingGameData( char *buf, size_t bufSize ) = 0; - - // return true to disconnect client due to timeout (used to do stricter timeouts when the game is sure the client isn't loading a map) - virtual bool ShouldTimeoutClient( int nUserID, float flTimeSinceLastReceived ) = 0; - - virtual IServerGCLobby *GetServerGCLobby() = 0; virtual void GameServerSteamAPIShutdown( void ) = 0; - - virtual void Status( void (*inputFunc) (const char *fmt, ...) ) = 0; - - virtual int GetServerGameDLLFlags( void ) = 0; + + virtual void OnHostNameChanged( const char *pszNewHostname ) = 0; + virtual void PreFatalShutdown( void ) const = 0; + virtual void UpdateWhenNotInGame( float ) = 0; + virtual void GetEconItemNamesForModel( const char *pszModel, bool, bool, CUtlVector &out ) = 0; + virtual void GetEconItemNamesForCharacter( const char *pszCharacter, bool, bool, CUtlVector &out ) = 0; + virtual void GetInfoForEconItems( const char *, const char *, CUtlVector &out ) = 0; + virtual void GetDefaultScaleForModel( const char *pszModel ) = 0; + virtual void GetDefaultScaleForCharacter( const char *pszCharacter ) = 0; + virtual void GetDefaultControlPointAutoUpdates( const char *, CUtlVector &out ) = 0; + virtual void GetCharacterNameForModel( const char *pszCharacter, char *pszOut, int size ) = 0; + virtual void GetDefaultModelNameForCharacter( const char *pszCharacter, char *pszOut, int size ) = 0; + virtual void GetCharacterList( CUtlVector &out ) = 0; + virtual void GetDefaultChoreoDirForModel( const char *pszModel, char *pszOut, int size ) = 0; + virtual void OnStreamEntitiesFromFileCompleted( CUtlVector &handles ) = 0; }; //----------------------------------------------------------------------------- @@ -631,90 +474,163 @@ public: //----------------------------------------------------------------------------- #define VENGINE_SERVER_RANDOM_INTERFACE_VERSION "VEngineRandom001" -#define INTERFACEVERSION_SERVERGAMEENTS "ServerGameEnts001" +#define INTERFACEVERSION_SERVERGAMEENTS "Source2GameEntities001" //----------------------------------------------------------------------------- // Purpose: Interface to get at server entities //----------------------------------------------------------------------------- -abstract_class IServerGameEnts +abstract_class ISource2GameEntities : public IAppSystem { public: - virtual ~IServerGameEnts() {} - - // The engine wants to mark two entities as touching - virtual void MarkEntitiesAsTouching( edict_t *e1, edict_t *e2 ) = 0; - - // Frees the entity attached to this edict - virtual void FreeContainingEntity( edict_t * ) = 0; - - // This allows the engine to get at edicts in a CGameTrace. - virtual edict_t* BaseEntityToEdict( CBaseEntity *pEnt ) = 0; - virtual CBaseEntity* EdictToBaseEntity( edict_t *pEdict ) = 0; - + virtual ~ISource2GameEntities() {} + // This sets a bit in pInfo for each edict in the list that wants to be transmitted to the // client specified in pInfo. // // This is also where an entity can force other entities to be transmitted if it refers to them // with ehandles. - virtual void ProcessCheckTransmit( int, CCheckTransmitInfo **pInfos, CBitVec &, const uint16 *, int ) = 0; - + virtual void CheckTransmit( CCheckTransmitInfo **pInfo, int, CBitVec<16384> &, const Entity2Networkable_t **pNetworkables, + const uint16 *pEntityIndicies, int nEntities ) = 0; + // TERROR: Perform any PVS cleanup before a full update virtual void PrepareForFullUpdate( CEntityIndex entIndex ) = 0; + // Frees the entity attached to this edict + virtual void FreeContainingEntity( CEntityIndex entIndex ) = 0; + + virtual void GetWorldspaceCenter( CEntityIndex entIndex, Vector *pOut ) const = 0; + virtual bool ShouldClientReceiveStringTableUserData( const INetworkStringTable *pStringTable, int iIndex, const CCheckTransmitInfo *pTransmitInfo ) = 0; + + virtual void ResetChangeAccessorsSerialNumbersToZero() = 0; }; -#define INTERFACEVERSION_SERVERGAMECLIENTS "ServerGameClients004" +#define INTERFACEVERSION_SERVERCONFIG "Source2ServerConfig001" + +abstract_class ISource2ServerConfig : public IAppSystem +{ +public: +#if 0 + virtual void AllocateScratchRenderTargets( SwapChainHandle_t *, const RenderDeviceInfo_t &, RenderMultisampleType_t ) = 0; + + virtual int GetDesiredRenderingPipeline( void ) = 0; + + virtual bool InstantReplayShouldSkipMessage( /* EBaseEntityMessages */ int message ) const = 0; + virtual bool InstantReplayShouldIgnoreMessage( /* EBaseEntityMessages */ int message ) const = 0; + + virtual const char *GetEncryptionKey() = 0; + + virtual CBaseEntity *FindProceduralEntity( const char *szClassname ) = 0; + + virtual void SetupGameSessionConfiguration( KeyValues *pKV, GameSessionConfiguration_t *pConfig ) = 0; + virtual void InitGameSession( const GameSessionConfiguration_t &config ) = 0; + virtual void ShutdownGameSession( void ) = 0; + + virtual const char *GetModName( void ) = 0; + + virtual bool ShouldPreserveEntityForRespawn( const char *szClassname ) = 0; + + virtual void LoopPostInitAllGameSystems( const GameSessionConfiguration_t &, ILoopModePrerequisiteRegistry * ) = 0; + + virtual void RegisterGameActivities( void ) = 0; + + virtual void ExecuteURL( const char *szURL ) = 0; + + virtual void GetBugReportLaunchURLParameters( KeyValues *pKV ) = 0; + + virtual void GetStringTableDefs( CUtlVector &defs ) = 0; + + virtual bool IsUserMessage( int id ) const = 0; + + virtual KeyValues *GetCurrentGameSessionConfigKeyValues() = 0; +#endif + // Returns string describing current .dll. e.g., TeamFortress 2, Half-Life 2. + // Hey, it's more descriptive than just the name of the game directory + virtual const char *GetGameDescription( void ) = 0; + + // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) + // Right now this is only requested at server startup time so it can't be changed on the fly, etc. + virtual float GetTickInterval( void ) const = 0; + + // Get server maxplayers and lower bound for same + virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const = 0; + + // Returns max splitscreen slot count ( 1 == no splits, 2 for 2-player split screen ) + virtual int GetMaxSplitscreenPlayers( void ) = 0; + + // Return # of human slots, -1 if can't determine or don't care (engine will assume it's == maxplayers ) + virtual int GetMaxHumanPlayers() = 0; + + virtual bool ShouldNotifyLocalClientConnectionStateChanges() = 0; + + virtual bool AllowPlayerToTakeOverBots() = 0; + + virtual void OnClientFullyConnect( CEntityIndex index ) = 0; + + virtual void GetHostStateLoopModeInfo( HostStateLoopModeType_t, CUtlString &, KeyValues ** ) = 0; + + virtual bool AllowDedicatedServers( EUniverse universe ) const = 0; + + virtual void GetConVarPrefixesToResetToDefaults( CUtlString &prefixes ) const = 0; + +#if 0 + virtual void ExecuteURL( int, const URLArgument_t * ) = 0; +#endif +}; + +#define INTERFACEVERSION_SERVERGAMECLIENTS "Source2GameClients001" //----------------------------------------------------------------------------- // Purpose: Player / Client related functions //----------------------------------------------------------------------------- -abstract_class IServerGameClients +abstract_class ISource2GameClients { public: - // Get server maxplayers and lower bound for same - virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const = 0; - // Client is connecting to server ( return false to reject the connection ) // You can specify a rejection message by writing it into reject - virtual bool ClientConnect( CEntityIndex index, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0; + virtual bool ClientConnect( CEntityIndex index, uint64 xuid, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0; + + virtual void OnClientConnected( CEntityIndex index, int userId, const char *pszName, uint64 xuid, const char *pszNetworkID, + const char *pszAddress, bool bFakePlayer ) = 0; + + // Client is connected and should be put in the game + virtual void ClientPutInServer( CEntityIndex index, char const *playername, bool bFakePlayer ) = 0; // Client is going active // If bLoadGame is true, don't spawn the player because its state is already setup. virtual void ClientActive( CEntityIndex index, bool bLoadGame ) = 0; - virtual void ClientFullyConnect( CEntityIndex index ) = 0; + virtual void ClientFullyConnect( CEntityIndex index, CPlayerSlot slot ) = 0; // Client is disconnecting from server - virtual void ClientDisconnect( CEntityIndex index, /* ENetworkDisconnectionReason */ int reason ) = 0; - - // Client is connected and should be put in the game - virtual void ClientPutInServer( CEntityIndex index, char const *playername ) = 0; + virtual void ClientDisconnect( CEntityIndex index, int userId, ENetworkDisconnectionReason reason, const char *pszName, + uint64 xuid, const char *pszNetworkID ) = 0; + + // Sets the client index for the client who typed the command into his/her console + virtual void SetCommandClient( CPlayerSlot slot) = 0; // The client has typed a command at the console virtual void ClientCommand( CEntityIndex index, const CCommand &args ) = 0; - // Sets the client index for the client who typed the command into his/her console - virtual void SetCommandClient( int index ) = 0; - // A player changed one/several replicated cvars (name etc) virtual void ClientSettingsChanged( CEntityIndex index ) = 0; // Determine PVS origin and set PVS for the player/viewentity - virtual void ClientSetupVisibility( CEntityIndex viewentIndex, CEntityIndex clientindex, unsigned char *pvs, int pvssize ) = 0; + virtual void ClientSetupVisibility( CEntityIndex viewentIndex, CEntityIndex clientindex, vis_info_t *visinfo ) = 0; // A block of CUserCmds has arrived from the user, decode them and buffer for execution during player simulation virtual float ProcessUsercmds( CEntityIndex index, bf_read *buf, int numcmds, int totalcmds, int dropped_packets, bool ignore, bool paused ) = 0; - - // For players, looks up the CPlayerState structure corresponding to the player - virtual CPlayerState *GetPlayerState( CEntityIndex index ) = 0; + + // Let the game .dll do stuff after messages have been sent to all of the clients once the server frame is complete + virtual void PostClientMessagesSent_DEPRECIATED( void ) = 0; + + virtual bool IsPlayerAlive( CEntityIndex index ) = 0; + + virtual int GetPlayerScore( CEntityIndex index ) = 0; // Get the ear position for a specified client virtual void ClientEarPosition( CEntityIndex index, Vector *pEarOrigin ) = 0; - // returns number of delay ticks if player is in Replay mode (0 = no delay) - virtual int GetReplayDelay( CEntityIndex index, int& entity ) = 0; - // Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) // can be added here virtual void GetBugReportInfo( char *buf, int buflen ) = 0; @@ -724,89 +640,26 @@ public: // A user has had their network id setup and validated virtual void NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) = 0; - - // Returns max splitscreen slot count ( 1 == no splits, 2 for 2-player split screen ) - virtual int GetMaxSplitscreenPlayers() = 0; // 68 - - // Return # of human slots, -1 if can't determine or don't care (engine will assume it's == maxplayers ) - virtual int GetMaxHumanPlayers() = 0; + + // The client has submitted a keyvalues command + virtual void ClientCommandKeyValues( edict_t *pEntity, KeyValues *pKeyValues ) = 0; virtual bool ClientCanPause( CEntityIndex index ) = 0; virtual void HLTVClientFullyConnect( int index, const CSteamID &steamID ) = 0; - virtual bool DispatchClientMessage( CEntityIndex index, int msg_type, int size, const uint8 *pData ) = 0; - virtual bool CanHLTVClientConnect( int index, const CSteamID &steamID, int *pRejectReason ) = 0; + + virtual void StartHLTVServer( CEntityIndex index ) = 0; + + virtual void SendHLTVStatusMessage( IHLTVServer *, bool, bool, const char *, int, int, int ) = 0; + + virtual IHLTVDirector *GetHLTVDirector( void ) = 0; }; -#define INTERFACEVERSION_UPLOADGAMESTATS "ServerUploadGameStats001" - -abstract_class IUploadGameStats -{ -public: - // Note that this call will block the server until the upload is completed, so use only at levelshutdown if at all. - virtual bool UploadGameStats( - char const *mapname, // Game map name - unsigned int blobversion, // Version of the binary blob data - unsigned int blobsize, // Size in bytes of blob data - const void *pvBlobData ) = 0; // Pointer to the blob data. - - // Call when created to init the CSER connection - virtual void InitConnection( void ) = 0; - - // Call periodically to poll steam for a CSER connection - virtual void UpdateConnection( void ) = 0; - - // If user has disabled stats tracking, do nothing - virtual bool IsGameStatsLoggingEnabled() = 0; - - // Gets a non-personally identifiable unique ID for this steam user, used for tracking total gameplay time across - // multiple stats sessions, but isn't trackable back to their Steam account or id. - // Buffer should be 16 bytes, ID will come back as a hexadecimal string version of a GUID - virtual void GetPseudoUniqueId( char *buf, size_t bufsize ) = 0; - - // For determining general % of users running using cyber cafe accounts... - virtual bool IsCyberCafeUser( void ) = 0; - - // Only works in single player - virtual bool IsHDREnabled( void ) = 0; -}; - -#define INTERFACEVERSION_PLUGINHELPERSCHECK "PluginHelpersCheck001" - -//----------------------------------------------------------------------------- -// Purpose: allows the game dll to control which plugin functions can be run -//----------------------------------------------------------------------------- -abstract_class IPluginHelpersCheck -{ -public: - virtual bool CreateMessage( const char *plugin, edict_t *pEntity, DIALOG_TYPE type, KeyValues *data ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface exposed from the client .dll back to the engine for specifying shared .dll IAppSystems (e.g., ISoundEmitterSystem) -//----------------------------------------------------------------------------- -abstract_class IServerDLLSharedAppSystems -{ -public: - virtual int Count() = 0; - virtual char const *GetDllName( int idx ) = 0; - virtual char const *GetInterfaceName( int idx ) = 0; -}; - -#define SERVER_DLL_SHARED_APPSYSTEMS "VServerDllSharedAppSystems001" - -#define INTERFACEVERSION_SERVERGAMETAGS "ServerGameTags001" - -//----------------------------------------------------------------------------- -// Purpose: querying the game dll for Server cvar tags -//----------------------------------------------------------------------------- -abstract_class IServerGameTags -{ -public: - // Get the list of cvars that require tags to show differently in the server browser - virtual void GetTaggedConVarList( KeyValues *pCvarTagList ) = 0; -}; +typedef IVEngineServer2 IVEngineServer; +typedef ISource2Server IServerGameDLL; +typedef ISource2GameEntities IServerGameEnts; +typedef ISource2GameClients IServerGameClients; #endif // EIFACE_H diff --git a/public/filesystem.h b/public/filesystem.h index edd55272..6b0ce3ec 100644 --- a/public/filesystem.h +++ b/public/filesystem.h @@ -22,6 +22,7 @@ #include "tier1/utlstring.h" //#include "tier1/functors.h" #include "tier1/checksum_crc.h" +#include "tier1/utldelegate.h" #include "tier1/utlqueue.h" #include "appframework/IAppSystem.h" #include "tier2/tier2.h" @@ -33,6 +34,9 @@ class CUtlBuffer; class KeyValues; class IFileList; +struct SearchPathStateHandle_t; +class ILowLevelFileIO; +class CSteamID; typedef void * FileHandle_t; typedef int FileFindHandle_t; @@ -229,6 +233,18 @@ enum SearchPathAdd_t PATH_ADD_TO_TAIL_ATINDEX, // First path searched }; +// ?????? +enum SearchPathPriority_t +{ + PRIORITY_UNKNOWN, +}; + +// ?????? +enum GetSearchPathTypes_t +{ + +}; + enum FilesystemOpenExFlags_t { FSOPEN_UNBUFFERED = (1 << 0), @@ -391,8 +407,6 @@ public: // This is the minimal interface that can be implemented to provide access to // a named set of files. -#define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011" - abstract_class IBaseFileSystem { public: @@ -424,6 +438,7 @@ public: virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0; virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) = 0; virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) = 0; + virtual bool CopyAFile( const char *pFileName, const char *pPath, const char *pDestination, bool bDontOverwrite = false ) = 0; }; @@ -458,8 +473,12 @@ public: // override is cleared and the current .bsp is searched for an embedded PAK file // and this file becomes the highest priority search path ( i.e., it's looked at first // even before the mod's file system path ). - virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0; + virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType = PATH_ADD_TO_TAIL, SearchPathPriority_t priority = PRIORITY_UNKNOWN ) = 0; virtual bool RemoveSearchPath( const char *pPath, const char *pathID = 0 ) = 0; + + virtual SearchPathStateHandle_t *SaveSearchPathState( const char *pszName ) const = 0; + virtual void RestoreSearchPathState( SearchPathStateHandle_t *pState ) = 0; + virtual void DestroySearchPathState( SearchPathStateHandle_t *pState ) = 0; // Remove all search paths (including write path?) virtual void RemoveAllSearchPaths( void ) = 0; @@ -472,12 +491,15 @@ public: // If there are currently no search paths with the specified path ID, then it will still // remember it in case you add search paths with this path ID. virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) = 0; + + virtual bool IsFileInReadOnlySearchPath ( const char *pPathID, const char *pFileName ) = 0; + virtual void SetSearchPathReadOnly( const char *pPathID, const char *, bool bReadOnly ) = 0; // converts a partial path into a full path virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) = 0; // Returns the search path, each path is separated by ;s. Returns the length of the string returned - virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) = 0; + virtual int GetSearchPath( const char *pathID, GetSearchPathTypes_t pathType, char *pPath, int nMaxLen ) = 0; //-------------------------------------------------------- // File manipulation operations @@ -551,7 +573,7 @@ public: // Returns true on success ( based on current list of search paths, otherwise false if // it can't be resolved ) - virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) = 0; + virtual bool FullPathToRelativePath( const char *pFullpath, const char *pPathID, char *pRelative, int maxlen ) = 0; // Gets the current working directory virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) = 0; @@ -643,7 +665,7 @@ public: // Start of new functions after Lost Coast release (7/05) //-------------------------------------------------------- - virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) = 0; + virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0 ) = 0; // Extended version of read provides more context to allow for more optimal reading virtual int ReadEx( void* pOutput, int sizeDest, int size, FileHandle_t file ) = 0; @@ -658,9 +680,6 @@ public: virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() = 0; #endif - virtual void SetupPreloadData() = 0; - virtual void DiscardPreloadData() = 0; - // Fixme, we could do these via a string embedded into the compiled data, etc... enum KeyValuesPreloadType_t { @@ -679,6 +698,7 @@ public: virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0; // Async read functions with memory blame FSAsyncStatus_t AsyncReadCreditAlloc( const FileAsyncRequest_t &request, const char *pszFile, int line, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultipleCreditAlloc( &request, 1, pszFile, line, phControl ); } + virtual FSAsyncStatus_t AsyncWriteUGCFile( const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, CUtlDelegate callback, FSAsyncControl_t *phControl = NULL ) = 0; virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *phControls = NULL ) = 0; virtual FSAsyncStatus_t AsyncDirectoryScan( const char* pSearchSpec, bool recurseFolders, void* pContext, FSAsyncScanAddFunc_t pfnAdd, FSAsyncScanCompleteFunc_t pfnDone, FSAsyncControl_t *pControl = NULL ) = 0; @@ -700,12 +720,6 @@ public: //-------------------------------------------------------- // //-------------------------------------------------------- - virtual void BeginMapAccess() = 0; - virtual void EndMapAccess() = 0; - - // Returns true on success, otherwise false if it can't be resolved - virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0; - virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0; virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0; @@ -776,14 +790,21 @@ public: virtual FSDirtyDiskReportFunc_t GetDirtyDiskReportFunc() = 0; - virtual void AddVPKFile( char const *pszName, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0; - virtual void RemoveVPKFile( char const *pszName ) = 0; - virtual void GetVPKFileNames( CUtlVector &destVector ) = 0; - virtual void RemoveAllMapSearchPaths() = 0; + virtual void AddVPKFile( const char *pszName, const char *, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0; + virtual void RemoveVPKFile( const char *pszName, const char * ) = 0; + virtual bool IsVPKFileLoaded( const char *pszName ) = 0; + virtual void EnableAutoVPKFileLoading( bool ) = 0; + virtual void GetAutoVPKFileLoading( void ) = 0; + virtual void AddUGCVPKFile( uint64 ugcId, const char *, SearchPathAdd_t ) = 0; + virtual void RemoveUGCVPKFile( uint64 ugcId, const char * ) = 0; + virtual bool IsUGCVPKFileLoaded( uint64 ugcId ) = 0; + virtual void ParseUGCHandleFromFilename( const char *, char ** )const = 0; + virtual void CreateFilenameForUGCFile( char *, int, uint64 ugcId, const char *, char ) const = 0; + virtual void GetUGCInfo( uint64 ugcId, char **, int *, CSteamID * ) = 0; + virtual void OpenUGCFile( uint64 ugcId ) = 0; + virtual void SyncDvdDevCache() = 0; - virtual bool GetStringFromKVPool( CRC32_t poolKey, unsigned int key, char *pOutBuff, int buflen ) = 0; - virtual bool DiscoverDLC( int iController ) = 0; virtual int IsAnyDLCPresent( bool *pbDLCSearchPathMounted = NULL ) = 0; virtual bool GetAnyDLCInfo( int iDLC, unsigned int *pLicenseMask, wchar_t *pTitleBuff, int nOutTitleSize ) = 0; @@ -796,7 +817,21 @@ public: // will be issued whenever the indicated # of seconds go by without an i/o request. Passing // 0.0 will turn off the functionality. virtual void SetIODelayAlarm( float flThreshhold ) = 0; - + + virtual ILowLevelFileIO *GetLowLevelFileIO( void ) = 0; + virtual void SetLowLevelFileIO( ILowLevelFileIO * ) = 0; + + virtual void AddXLSPUpdateSearchPath( const void *, int ) = 0; + + virtual void DumpFileSystemStats( int, const char * ) = 0; + + virtual void DeleteDirectory( const char *pFileName, const char *pathID = 0 ) = 0; + + virtual bool IsPathInvalidForFilesystem( const char *pFileName ) = 0; + + virtual void GetAvailableDrives( CUtlVector &drives ) = 0; + + virtual const char *ReadLine( FileHandle_t file, bool bStripNewline = true ) = 0; }; //----------------------------------------------------------------------------- diff --git a/public/filesystem_passthru.h b/public/filesystem_passthru.h index 56638eb4..d4175673 100644 --- a/public/filesystem_passthru.h +++ b/public/filesystem_passthru.h @@ -56,6 +56,8 @@ public: virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pBaseFileSystemPassThru->ReadFile( pFileName, pPath, buf, nMaxBytes, nStartingByte, pfnAlloc ); } virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) { return m_pBaseFileSystemPassThru->WriteFile( pFileName, pPath, buf ); } virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) { return m_pBaseFileSystemPassThru->UnzipFile( pFileName, pPath, pDestination ); } + virtual bool CopyAFile( const char *pFileName, const char *pPath, const char *pDestination, bool bDontOverwrite ) + { return m_pBaseFileSystemPassThru->CopyAFile( pFileName, pPath, pDestination, bDontOverwrite ); } protected: IBaseFileSystem *m_pBaseFileSystemPassThru; @@ -92,14 +94,20 @@ public: virtual void *QueryInterface( const char *pInterfaceName ) { return m_pFileSystemPassThru->QueryInterface( pInterfaceName ); } virtual InitReturnVal_t Init() { return m_pFileSystemPassThru->Init(); } virtual void Shutdown() { m_pFileSystemPassThru->Shutdown(); } + virtual void PreShutdown() { m_pFileSystemPassThru->PreShutdown(); } virtual const AppSystemInfo_t* GetDependencies() { return m_pFileSystemPassThru->GetDependencies(); } virtual AppSystemTier_t GetTier() { return m_pFileSystemPassThru->GetTier(); } virtual void Reconnect( CreateInterfaceFn factory, const char *pInterfaceName ) { m_pFileSystemPassThru->Reconnect( factory, pInterfaceName ); } virtual bool IsSingleton() { return m_pFileSystemPassThru->IsSingleton(); } + virtual BuildType_t GetBuildType() { return m_pFileSystemPassThru->GetBuildType(); } virtual void RemoveAllSearchPaths( void ) { m_pFileSystemPassThru->RemoveAllSearchPaths(); } - virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType ) { m_pFileSystemPassThru->AddSearchPath( pPath, pathID, addType ); } + virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType, SearchPathPriority_t priority ) + { m_pFileSystemPassThru->AddSearchPath( pPath, pathID, addType, priority ); } virtual bool RemoveSearchPath( const char *pPath, const char *pathID ) { return m_pFileSystemPassThru->RemoveSearchPath( pPath, pathID ); } + virtual SearchPathStateHandle_t *SaveSearchPathState( const char *pszName ) const { return m_pFileSystemPassThru->SaveSearchPathState( pszName ); } + virtual void RestoreSearchPathState( SearchPathStateHandle_t *pState ) { m_pFileSystemPassThru->RestoreSearchPathState( pState ); } + virtual void DestroySearchPathState( SearchPathStateHandle_t *pState ) { m_pFileSystemPassThru->DestroySearchPathState( pState ); } virtual void RemoveFile( char const* pRelativePath, const char *pathID ) { m_pFileSystemPassThru->RemoveFile( pRelativePath, pathID ); } virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID ) { return m_pFileSystemPassThru->RenameFile( pOldPath, pNewPath, pathID ); } virtual void CreateDirHierarchy( const char *path, const char *pathID ) { m_pFileSystemPassThru->CreateDirHierarchy( path, pathID ); } @@ -125,7 +133,7 @@ public: virtual bool FindIsDirectory( FileFindHandle_t handle ) { return m_pFileSystemPassThru->FindIsDirectory( handle ); } virtual void FindClose( FileFindHandle_t handle ) { m_pFileSystemPassThru->FindClose( handle ); } virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) { return m_pFileSystemPassThru->GetLocalPath( pFileName, pLocalPath, localPathBufferSize ); } - virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) { return m_pFileSystemPassThru->FullPathToRelativePath( pFullpath, pRelative, maxlen ); } + virtual bool FullPathToRelativePath( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePath( pFullPath, pPathId, pRelative, nMaxLen ); } virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) { return m_pFileSystemPassThru->GetCurrentDirectory( pDirectory, maxlen ); } virtual void PrintOpenedFiles( void ) { m_pFileSystemPassThru->PrintOpenedFiles(); } virtual void PrintSearchPaths( void ) { m_pFileSystemPassThru->PrintSearchPaths(); } @@ -134,6 +142,7 @@ public: virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ){ m_pFileSystemPassThru->AddLoggingFunc( pfnLogFunc ); } virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) { m_pFileSystemPassThru->RemoveLoggingFunc( logFunc ); } virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultiple( pRequests, nRequests, pControls ); } + virtual FSAsyncStatus_t AsyncWriteUGCFile( const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, CUtlDelegate callback, FSAsyncControl_t *phControl = NULL ) { return m_pFileSystemPassThru->AsyncWriteUGCFile( pFileName, pSrc, nSrcBytes, bFreeMemory, callback, phControl ); } virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultipleCreditAlloc( pRequests, nRequests, pszFile, line, pControls ); } virtual FSAsyncStatus_t AsyncDirectoryScan( const char* pSearchSpec, bool recurseFolders, void* pContext, FSAsyncScanAddFunc_t pfnAdd, FSAsyncScanCompleteFunc_t pfnDone, FSAsyncControl_t *pControl = NULL ) { return m_pFileSystemPassThru->AsyncDirectoryScan( pSearchSpec, recurseFolders, pContext, pfnAdd, pfnDone, pControl ); } virtual FSAsyncStatus_t AsyncFinish(FSAsyncControl_t hControl, bool wait) { return m_pFileSystemPassThru->AsyncFinish( hControl, wait ); } @@ -172,6 +181,8 @@ public: const char *pPathID ) { m_pFileSystemPassThru->FindFileAbsoluteList( output, pWildCard, pPathID ); } virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) { m_pFileSystemPassThru->MarkPathIDByRequestOnly( pPathID, bRequestOnly ); } + virtual bool IsFileInReadOnlySearchPath ( const char *pPathID, const char *pFileName ) { return m_pFileSystemPassThru->IsFileInReadOnlySearchPath( pPathID, pFileName ); } + virtual void SetSearchPathReadOnly( const char *pPathID, const char *pUnknown, bool bReadOnly ) { m_pFileSystemPassThru->SetSearchPathReadOnly( pPathID, pUnknown, bReadOnly ); } virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppend( pFileName, pSrc, nSrcBytes, bFreeMemory, pControl); } virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWrite( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); } virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWriteFile( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); } @@ -182,9 +193,9 @@ public: virtual bool AsyncSuspend() { return m_pFileSystemPassThru->AsyncSuspend(); } virtual bool AsyncResume() { return m_pFileSystemPassThru->AsyncResume(); } virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) { return m_pFileSystemPassThru->RelativePathToFullPath( pFileName, pPathID, pLocalPath, localPathBufferSize, pathFilter, pPathType ); } - virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPath( pathID, bGetPackFiles, pPath, nMaxLen ); } + virtual int GetSearchPath( const char *pathID, GetSearchPathTypes_t type, char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPath( pathID, type, pPath, nMaxLen ); } - virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) { return m_pFileSystemPassThru->OpenEx( pFileName, pOptions, flags, pathID, ppszResolvedFilename );} + virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0 ) { return m_pFileSystemPassThru->OpenEx( pFileName, pOptions, flags, pathID );} virtual int ReadEx( void* pOutput, int destSize, int size, FileHandle_t file ) { return m_pFileSystemPassThru->ReadEx( pOutput, destSize, size, file ); } virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate, bool bOptimalAlloc, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadFileEx( pFileName, pPath, ppBuf, bNullTerminate, bOptimalAlloc, nMaxBytes, nStartingByte, pfnAlloc ); } @@ -194,8 +205,6 @@ public: virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() { return m_pFileSystemPassThru->RetrieveBlockingFileAccessInfo(); } #endif - virtual void SetupPreloadData() {} - virtual void DiscardPreloadData() {} // If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup. // Otherwise, it'll just fall through to the regular KeyValues loading routines @@ -208,11 +217,7 @@ public: virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize, unsigned nOffset ) { return m_pFileSystemPassThru->AllocOptimalReadBuffer( hFile, nOffset, nSize ); } virtual void FreeOptimalReadBuffer( void *p ) { m_pFileSystemPassThru->FreeOptimalReadBuffer( p ); } - virtual void BeginMapAccess() { m_pFileSystemPassThru->BeginMapAccess(); } - virtual void EndMapAccess() { m_pFileSystemPassThru->EndMapAccess(); } - virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadToBuffer( hFile, buf, nMaxBytes, pfnAlloc ); } - virtual bool FullPathToRelativePathEx( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePathEx( pFullPath, pPathId, pRelative, nMaxLen ); } virtual int GetPathIndex( const FileNameHandle_t &handle ) { return m_pFileSystemPassThru->GetPathIndex( handle ); } virtual long GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); } @@ -245,16 +250,21 @@ public: virtual FSDirtyDiskReportFunc_t GetDirtyDiskReportFunc() { return m_pFileSystemPassThru->GetDirtyDiskReportFunc(); } - virtual void AddVPKFile( char const *pPkName, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) { m_pFileSystemPassThru->AddVPKFile( pPkName, addType ); } - virtual void RemoveVPKFile( char const *pPkName ) { m_pFileSystemPassThru->RemoveVPKFile( pPkName ); } - virtual void GetVPKFileNames( CUtlVector &destVector ) { m_pFileSystemPassThru->GetVPKFileNames( destVector ); } - - virtual void RemoveAllMapSearchPaths( void ) { m_pFileSystemPassThru->RemoveAllMapSearchPaths(); } - + virtual void AddVPKFile( char const *pPkName, const char *pUnknown, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) { m_pFileSystemPassThru->AddVPKFile( pPkName, pUnknown, addType ); } + virtual void RemoveVPKFile( char const *pPkName, const char *pUnknown ) { m_pFileSystemPassThru->RemoveVPKFile( pPkName, pUnknown ); } + virtual bool IsVPKFileLoaded( const char *pszName ) { return m_pFileSystemPassThru->IsVPKFileLoaded( pszName ); } + virtual void EnableAutoVPKFileLoading( bool unk ) { m_pFileSystemPassThru->EnableAutoVPKFileLoading( unk ); } + virtual void GetAutoVPKFileLoading( void ) { m_pFileSystemPassThru->GetAutoVPKFileLoading(); } + virtual void AddUGCVPKFile( uint64 ugcId, const char *unk1, SearchPathAdd_t unk2 ) { m_pFileSystemPassThru->AddUGCVPKFile( ugcId, unk1, unk2 ); } + virtual void RemoveUGCVPKFile( uint64 ugcId, const char *unk1 ) { m_pFileSystemPassThru->RemoveUGCVPKFile( ugcId, unk1 ); } + virtual bool IsUGCVPKFileLoaded( uint64 ugcId ) { return m_pFileSystemPassThru->IsUGCVPKFileLoaded( ugcId ); } + virtual void ParseUGCHandleFromFilename( const char *unk1, char **unk2 ) const { m_pFileSystemPassThru->ParseUGCHandleFromFilename( unk1, unk2 ); } + virtual void CreateFilenameForUGCFile( char *unk1, int unk2, uint64 ugcId, const char *unk3, char unk4 ) const { m_pFileSystemPassThru->CreateFilenameForUGCFile( unk1, unk2, ugcId, unk3, unk4 ); } + virtual void GetUGCInfo( uint64 ugcId, char **unk1, int *unk2, CSteamID *unk3 ) { m_pFileSystemPassThru->GetUGCInfo( ugcId, unk1, unk2, unk3 ); } + virtual void OpenUGCFile( uint64 ugcId ) { m_pFileSystemPassThru->OpenUGCFile( ugcId ); } + virtual void SyncDvdDevCache( void ) { m_pFileSystemPassThru->SyncDvdDevCache(); } - virtual bool GetStringFromKVPool( CRC32_t poolKey, unsigned int key, char *pOutBuff, int buflen ) { return m_pFileSystemPassThru->GetStringFromKVPool( poolKey, key, pOutBuff, buflen ); } - virtual bool DiscoverDLC( int iController ) { return m_pFileSystemPassThru->DiscoverDLC( iController ); } virtual int IsAnyDLCPresent( bool *pbDLCSearchPathMounted = NULL ) { return m_pFileSystemPassThru->IsAnyDLCPresent( pbDLCSearchPathMounted ); } virtual bool GetAnyDLCInfo( int iDLC, unsigned int *pLicenseMask, wchar_t *pTitleBuff, int nOutTitleSize ) { return m_pFileSystemPassThru->GetAnyDLCInfo( iDLC, pLicenseMask, pTitleBuff, nOutTitleSize ); } @@ -264,6 +274,14 @@ public: virtual bool IsSpecificDLCPresent( unsigned int nDLCPackage ) { return m_pFileSystemPassThru->IsSpecificDLCPresent( nDLCPackage ); } virtual void SetIODelayAlarm( float flThreshhold ) { m_pFileSystemPassThru->SetIODelayAlarm( flThreshhold ); } + virtual ILowLevelFileIO *GetLowLevelFileIO( void ) { return m_pFileSystemPassThru->GetLowLevelFileIO(); } + virtual void SetLowLevelFileIO( ILowLevelFileIO *pIO ) { m_pFileSystemPassThru->SetLowLevelFileIO( pIO ); } + virtual void AddXLSPUpdateSearchPath( const void *unk1, int unk2 ) { m_pFileSystemPassThru->AddXLSPUpdateSearchPath( unk1, unk2 ); } + virtual void DumpFileSystemStats( int unk1, const char *unk2 ) { m_pFileSystemPassThru->DumpFileSystemStats( unk1, unk2 ); } + virtual void DeleteDirectory( const char *pFileName, const char *pathID = 0 ) { m_pFileSystemPassThru->DeleteDirectory( pFileName, pathID ); } + virtual bool IsPathInvalidForFilesystem( const char *pFileName ) { return m_pFileSystemPassThru->IsPathInvalidForFilesystem( pFileName ); } + virtual void GetAvailableDrives( CUtlVector &drives ) { m_pFileSystemPassThru->GetAvailableDrives( drives ); } + virtual const char *ReadLine( FileHandle_t file, bool bStripNewline = true ) { return m_pFileSystemPassThru->ReadLine( file, bStripNewline ); } protected: IFileSystem *m_pFileSystemPassThru; }; diff --git a/public/icvar.h b/public/icvar.h index 3fdc75e8..2d4d9e76 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -19,6 +19,9 @@ class ConCommandBase; class ConCommand; class ConVar; class Color; +class IConVarListener; +class CConVarDetail; +struct ConVarSnapshot_t; //----------------------------------------------------------------------------- @@ -166,6 +169,15 @@ protected: virtual ICVarIteratorInternal *FactoryInternalIterator( void ) = 0; friend class Iterator; + + virtual void InstallConVarListener( IConVarListener *pListener ) = 0; + virtual void RemoveConVarListener( IConVarListener *pListener ) = 0; + virtual void GetConVarDetails( CUtlVector &out ) = 0; + + virtual void ResetConVarsToDefaultValues( const char *pszPrefix ) = 0; + virtual ConVarSnapshot_t *TakeConVarSnapshot( void ) = 0; + virtual void ResetConVarsToSnapshot( ConVarSnapshot_t *pSnapshot ) = 0; + virtual void DestroyConVarSnapshot( ConVarSnapshot_t *pSnaoshot ) = 0; }; inline ICvar::Iterator::Iterator(ICvar *icvar) diff --git a/public/interfaces/interfaces.h b/public/interfaces/interfaces.h index 27136351..e8bddfa8 100644 --- a/public/interfaces/interfaces.h +++ b/public/interfaces/interfaces.h @@ -48,47 +48,121 @@ class ICvar; class IProcessUtils; class ILocalize; class IPhysics2; -class IPhysics2ActorManager; class IPhysics2ResourceManager; class IEventSystem; class IAsyncFileSystem; class IColorCorrectionSystem; class IDebugTextureInfo; +class IBaseFileSystem; class IFileSystem; class IRenderHardwareConfig; class IInputSystem; class IInputStackSystem; class IMaterialSystem; -class IMaterialSystem2; -class IMaterialSystemHardwareConfig; class IMdlLib; class INetworkSystem; +class INetworkSystemUtils; class IP4; class IQueuedLoader; -class IResourceAccessControl; -class IPrecacheSystem; class IRenderDevice; +class IRenderDeviceSetup; class IRenderDeviceMgr; +class IRenderUtils; class IResourceSystem; +class IResourceSystemTools; class IVBAllocTracker; class IXboxInstaller; class IMatchFramework; class ISoundSystem; -class IStudioRender; class IMatSystemSurface; class IGameUISystemMgr; class IDataCache; -class IMDLCache; class IAvi; class IBik; +class IQuickTime; class IDmeMakefileUtils; -class IPhysicsCollision; class ISoundEmitterSystemBase; +class ISoundEmitterSystemBaseS1; class IMeshSystem; +class IMeshUtils; class IWorldRendererMgr; class ISceneSystem; +class ISceneUtils; class IVGuiRenderSurface; +class IResourceManifestRegistry; +class IResourceHandleUtils; +class ISchemaSystem; +class IResourceCompilerSystem; +class IPostProcessingSystem; +class ISoundMixGroupSystem; +class ISoundOpSystemEdit; +class ISoundOpSystem; +class IAssetSystem; +class IAssetSystemTest; +class IParticleSystemMgr; +class IVScriptManager; +class IToolScriptManager; +class IPropertyEditorSystem; +class IModelProcessingSystem; +class IPanoramaUI; +class IToolFramework2; +class IMapBuilderMgr; +class IHelpSystem; +class IToolSceneNodeFactory; +class IToolGameSimulationSystem; +class IToolGameSimulationDispatcher; +class ISchemaTestExternal_Two; +class ISchemaTestExternal_One; +class IAnimationSystem; +class IAnimationSystemUtils; +class IHammerMapLoader; +class IMaterialUtils; +class IFontManager; +class ITextLayout; +class IAssetPreviewSystem; +class IAssetBrowserSystem; +class IVConComm; +class IConfigurationSystem; +class INetworkMessages; +class IFlattenedSerializers; +class ISource2Client; +class ISource2ClientPrediction; +class ISource2Server; +class ISource2ServerSerializers; +class ISource2Host; +class ISource2GameClients; +class ISource2GameEntities; +class IEngineServiceMgr; +class IHostStateMgr; +class INetworkService; +class INetworkClientService; +class INetworkServerService; +class ITextMessageMgr; +class IToolService; +class IRenderService; +class IStatsService; +class IUserInfoChangeService; +class IVProfService; +class IInputService; +class IMapListService; +class IGameUIService; +class ISoundService; +class IBenchmarkService; +class IDebugService; +class IKeyValueCache; +class IGameResourceServiceClient; +class IGameResourceServiceServer; +class ISource2EngineToClient; +class ISource2EngineToServer; +class ISource2EngineToServerStringTable; +class ISource2EngineToClientStringTable; +class ISource2EngineSoundServer; +class ISource2EngineSoundClient; + +class IServerUploadGameStats; +class IScaleformUI; +class IVR; namespace vgui { @@ -113,13 +187,10 @@ DECLARE_TIER1_INTERFACE( ICvar, g_pCVar ) #define PROCESS_UTILS_INTERFACE_VERSION "VProcessUtils002" DECLARE_TIER1_INTERFACE( IProcessUtils, g_pProcessUtils ); -#define VPHYSICS2_INTERFACE_VERSION "Physics2 Interface v0.3" +#define VPHYSICS2_INTERFACE_VERSION "Physics2 Interface Old v0.5" DECLARE_TIER1_INTERFACE( IPhysics2, g_pPhysics2 ); -#define VPHYSICS2_ACTOR_MGR_INTERFACE_VERSION "Physics2 Interface ActorMgr v0.1" -DECLARE_TIER1_INTERFACE( IPhysics2ActorManager, g_pPhysics2ActorManager ); - -#define VPHYSICS2_RESOURCE_MGR_INTERFACE_VERSION "Physics2 Interface ResourceMgr v0.1" +#define VPHYSICS2_RESOURCE_MGR_INTERFACE_VERSION "VPhysX Interface ResourceMgr v0.1" DECLARE_TIER1_INTERFACE( IPhysics2ResourceManager, g_pPhysics2ResourceManager ); #define EVENTSYSTEM_INTERFACE_VERSION "EventSystem001" @@ -132,21 +203,41 @@ DECLARE_TIER3_INTERFACE( vgui::ILocalize, g_pVGuiLocalize ); #define RENDER_DEVICE_MGR_INTERFACE_VERSION "RenderDeviceMgr001" DECLARE_TIER2_INTERFACE( IRenderDeviceMgr, g_pRenderDeviceMgr ); +#define RENDER_UTILS_INTERFACE_VERSION "RenderUtils_001" +DECLARE_TIER2_INTERFACE( IRenderUtils, g_pRenderUtils ); + +#define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011" +DECLARE_TIER2_INTERFACE( IBaseFileSystem, g_pBaseFileSystem ); + #define FILESYSTEM_INTERFACE_VERSION "VFileSystem017" DECLARE_TIER2_INTERFACE( IFileSystem, g_pFullFileSystem ); #define ASYNCFILESYSTEM_INTERFACE_VERSION "VNewAsyncFileSystem001" DECLARE_TIER2_INTERFACE( IAsyncFileSystem, g_pAsyncFileSystem ); -#define RESOURCESYSTEM_INTERFACE_VERSION "ResourceSystem004" +#define RESOURCESYSTEM_INTERFACE_VERSION "ResourceSystem009" DECLARE_TIER2_INTERFACE( IResourceSystem, g_pResourceSystem ); -#define MATERIAL_SYSTEM_INTERFACE_VERSION "VMaterialSystem080" -DECLARE_TIER2_INTERFACE( IMaterialSystem, materials ); -DECLARE_TIER2_INTERFACE( IMaterialSystem, g_pMaterialSystem ); +#define RESOURCESYSTEMTOOLS_INTERFACE_VERSION "ResourceSystemTools001" +DECLARE_TIER2_INTERFACE( IResourceSystemTools, g_pResourceSystemTools ); + +#define RESOURCEMANIFESTREGISTRY_INTERFACE_VERSION "ResourceManifestRegistry001" +DECLARE_TIER2_INTERFACE( IResourceManifestRegistry, g_pResourceManifestRegistry ); + +#define RESOURCEHANDLEUTILS_INTERFACE_VERSION "ResourceHandleUtils001" +DECLARE_TIER2_INTERFACE( IResourceHandleUtils, g_pResourceHandleUtils ); + +#define SCHEMASYSTEM_INTERFACE_VERSION "SchemaSystem_001" +DECLARE_TIER2_INTERFACE( ISchemaSystem, g_pSchemaSystem ); + +#define RESOURCECOMPILERSYSTEM_INTERFACE_VERSION "ResourceCompilerSystem001" +DECLARE_TIER2_INTERFACE( IResourceCompilerSystem, g_pResourceCompilerSystem ); + +#define POSTPROCESSINGSYSTEM_INTERFACE_VERSION "PostProcessingSystem_001" +DECLARE_TIER2_INTERFACE( IPostProcessingSystem, g_pPostProcessingSystem ); #define MATERIAL_SYSTEM2_INTERFACE_VERSION "VMaterialSystem2_001" -DECLARE_TIER2_INTERFACE( IMaterialSystem2, g_pMaterialSystem2 ); +DECLARE_TIER2_INTERFACE( IMaterialSystem, g_pMaterialSystem ); #define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001" DECLARE_TIER2_INTERFACE( IInputSystem, g_pInputSystem ); @@ -154,11 +245,14 @@ DECLARE_TIER2_INTERFACE( IInputSystem, g_pInputSystem ); #define INPUTSTACKSYSTEM_INTERFACE_VERSION "InputStackSystemVersion001" DECLARE_TIER2_INTERFACE( IInputStackSystem, g_pInputStackSystem ); -#define NETWORKSYSTEM_INTERFACE_VERSION "NetworkSystemVersion002" +#define NETWORKSYSTEM_INTERFACE_VERSION "NetworkSystemVersion001" DECLARE_TIER2_INTERFACE( INetworkSystem, g_pNetworkSystem ); -#define MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION "MaterialSystemHardwareConfig013" -DECLARE_TIER2_INTERFACE( IMaterialSystemHardwareConfig, g_pMaterialSystemHardwareConfig ); +#define NETWORKSYSTEMUTILS_INTERFACE_VERSION "NetworkSystemUtilsVersion001" +DECLARE_TIER2_INTERFACE( INetworkSystemUtils, g_pNetworkSystemUtils ); + +#define NETWORKMESSAGES_INTERFACE_VERSION "NetworkMessagesVersion001" +DECLARE_TIER2_INTERFACE( INetworkMessages, g_pNetworkMessages ); #define DEBUG_TEXTURE_INFO_VERSION "DebugTextureInfo001" DECLARE_TIER2_INTERFACE( IDebugTextureInfo, g_pMaterialSystemDebugTextureInfo ); @@ -169,7 +263,7 @@ DECLARE_TIER2_INTERFACE( IVBAllocTracker, g_VBAllocTracker ); #define COLORCORRECTION_INTERFACE_VERSION "COLORCORRECTION_VERSION_1" DECLARE_TIER2_INTERFACE( IColorCorrectionSystem, colorcorrection ); -#define P4_INTERFACE_VERSION "VP4002" +#define P4_INTERFACE_VERSION "VP4003" DECLARE_TIER2_INTERFACE( IP4, p4 ); #define MDLLIB_INTERFACE_VERSION "VMDLLIB001" @@ -178,12 +272,6 @@ DECLARE_TIER2_INTERFACE( IMdlLib, mdllib ); #define QUEUEDLOADER_INTERFACE_VERSION "QueuedLoaderVersion001" DECLARE_TIER2_INTERFACE( IQueuedLoader, g_pQueuedLoader ); -#define RESOURCE_ACCESS_CONTROL_INTERFACE_VERSION "VResourceAccessControl001" -DECLARE_TIER2_INTERFACE( IResourceAccessControl, g_pResourceAccessControl ); - -#define PRECACHE_SYSTEM_INTERFACE_VERSION "VPrecacheSystem001" -DECLARE_TIER2_INTERFACE( IPrecacheSystem, g_pPrecacheSystem ); - #if defined( _X360 ) #define XBOXINSTALLER_INTERFACE_VERSION "XboxInstallerVersion001" DECLARE_TIER2_INTERFACE( IXboxInstaller, g_pXboxInstaller ); @@ -192,40 +280,249 @@ DECLARE_TIER2_INTERFACE( IXboxInstaller, g_pXboxInstaller ); #define MATCHFRAMEWORK_INTERFACE_VERSION "MATCHFRAMEWORK_001" DECLARE_TIER2_INTERFACE( IMatchFramework, g_pMatchFramework ); -#define GAMEUISYSTEMMGR_INTERFACE_VERSION "GameUISystemMgr001" -DECLARE_TIER3_INTERFACE( IGameUISystemMgr, g_pGameUISystemMgr ); - //----------------------------------------------------------------------------- // Not exactly a global, but we're going to keep track of these here anyways // NOTE: Appframework deals with connecting these bad boys. See materialsystem2app.cpp //----------------------------------------------------------------------------- -#define RENDER_DEVICE_INTERFACE_VERSION "RenderDevice001" -DECLARE_TIER2_INTERFACE( IRenderDevice, g_pRenderDevice ); +#define RENDER_DEVICE_INTERFACE_VERSION "RenderDevice002" +DECLARE_TIER2_INTERFACE(IRenderDevice, g_pRenderDevice); -#define RENDER_HARDWARECONFIG_INTERFACE_VERSION "RenderHardwareConfig001" +#define RENDER_DEVICE_SETUP_INTERFACE_VERSION "VRenderDeviceSetupV001" +DECLARE_TIER2_INTERFACE( IRenderDeviceSetup, g_pRenderDeviceSetup ); + +#define RENDER_HARDWARECONFIG_INTERFACE_VERSION "RenderHardwareConfig002" DECLARE_TIER2_INTERFACE( IRenderHardwareConfig, g_pRenderHardwareConfig ); #define SOUNDSYSTEM_INTERFACE_VERSION "SoundSystem001" DECLARE_TIER2_INTERFACE( ISoundSystem, g_pSoundSystem ); +#define SOUNDMIXGROUPSYSTEM_INTERFACE_VERSION "SoundMixGroupSystem001" +DECLARE_TIER2_INTERFACE( ISoundMixGroupSystem, g_pSoundMixGroupSystem); + +#define SOUNDOPSYSTEMEDIT_INTERFACE_VERSION "SoundOpSystemEdit001" +DECLARE_TIER2_INTERFACE( ISoundOpSystemEdit, g_pSoundOpSystemEdit ); + +#define SOUNDOPSYSTEM_INTERFACE_VERSION "SoundOpSystem001" +DECLARE_TIER2_INTERFACE( ISoundOpSystem, g_pSoundOpSystem ); + #define MESHSYSTEM_INTERFACE_VERSION "MeshSystem001" DECLARE_TIER3_INTERFACE( IMeshSystem, g_pMeshSystem ); -#define STUDIO_RENDER_INTERFACE_VERSION "VStudioRender026" -DECLARE_TIER3_INTERFACE( IStudioRender, g_pStudioRender ); -DECLARE_TIER3_INTERFACE( IStudioRender, studiorender ); - -#define MAT_SYSTEM_SURFACE_INTERFACE_VERSION "MatSystemSurface006" -DECLARE_TIER3_INTERFACE( IMatSystemSurface, g_pMatSystemSurface ); +#define MESHUTILS_INTERFACE_VERSION "MeshUtils001" +DECLARE_TIER3_INTERFACE( IMeshUtils, g_pMeshUtils ); #define RENDER_SYSTEM_SURFACE_INTERFACE_VERSION "RenderSystemSurface001" DECLARE_TIER3_INTERFACE( IVGuiRenderSurface, g_pVGuiRenderSurface ); -#define SCENESYSTEM_INTERFACE_VERSION "SceneSystem_001" +#define ASSETSYSTEM_INTERFACE_VERSION "AssetSystem001" +DECLARE_TIER3_INTERFACE( IAssetSystem, g_pAssetSystem ); + +#define ASSETSYSTEMTEST_INTERFACE_VERSION "AssetSystemTest001" +DECLARE_TIER3_INTERFACE( IAssetSystemTest, g_pAssetSystemTest ); + +#define PARTICLESYSTEMMGR_INTERFACE_VERSION "ParticleSystemMgr002" +DECLARE_TIER3_INTERFACE( IParticleSystemMgr, g_pParticleSystemMgr ); + +#define VSCRIPT_INTERFACE_VERSION "VScriptManager010" +DECLARE_TIER3_INTERFACE( IVScriptManager, g_pVScriptService ); + +#define TOOLSCRIPTMANAGER_INTERFACE_VERSION "ToolScriptManager001" +DECLARE_TIER3_INTERFACE( IToolScriptManager, g_pToolScriptManager ); + +#define PROPERTYEDITORSYSTEM_INTERFACE_VERSION "PropertyEditorSystem_001" +DECLARE_TIER3_INTERFACE( IPropertyEditorSystem, g_pPropertyEditorSystem ); + +#define MODELPROCESSINGSYSTEM_INTERFACE_VERSION "ModelProcessingSystem001" +DECLARE_TIER3_INTERFACE( IModelProcessingSystem, g_pModelProcessingSystem ); + +#define PANORAMAUI_INTERFACE_VERSION "PanoramaUI001" +DECLARE_TIER3_INTERFACE( IPanoramaUI, g_pPanoramaUI ); + +#define TOOLFRAMEWORK2_INTERFACE_VERSION "ToolFramework2_001" +DECLARE_TIER3_INTERFACE( IToolFramework2, g_pToolFramework2 ); + +#define WORLDRENDERERBUILDER_INTERFACE_VERSION "WorldRendererBuilderMgr001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pWorldRendererBuilderMgr ); + +#define LIGHTINGBUILDER_INTERFACE_VERSION "LightingBuilderMgr001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pLightingBuilderMgr ); + +#define PHYSICSBUILDER_INTERFACE_VERSION "PhysicsBuilderMgr001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pPhysicsBuilderMgr ); + +#define VISBUILDER_INTERFACE_VERSION "VisBuilder_001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pVisBuilderMgr ); + +#define ENVIRONMENTBUILDER_INTERFACE_VERSION "EnvironmentMapBuilder_001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pEnvironmentBuilderMgr ); + +#define BAKEDLODBUILDER_INTERFACE_VERSION "BakedLODBuilderMgr001" +DECLARE_TIER3_INTERFACE( IMapBuilderMgr, g_pBakedLODBuilderMgr ); + +#define HELPSYSTEM_INTERFACE_VERSION "HelpSystem_001" +DECLARE_TIER3_INTERFACE( IHelpSystem, g_pHelpSystem ); + +#define TOOLSCENENODEFACTORY_INTERFACE_VERSION "ToolSceneNodeFactory_001" +DECLARE_TIER3_INTERFACE( IToolSceneNodeFactory, g_pToolSceneNodeFactory ); + +#define TOOLGAMESIMULATIONSYSTEM_INTERFACE_VERSION "ToolGameSimulationSystem_001" +DECLARE_TIER3_INTERFACE( IToolGameSimulationSystem, g_pToolGameSimulationSystem ); + +#define TOOLGAMESIMULATIONDISPATCHER_INTERFACE_VERSION "ToolGameSimulationDispatcher_001" +DECLARE_TIER3_INTERFACE( IToolGameSimulationDispatcher, g_pToolGameSimulationDispatcher ); + +#define SCHEMATESTEXTERNALTWO_INTERFACE_VERSION "SchemaTestExternal_Two_001" +DECLARE_TIER3_INTERFACE( ISchemaTestExternal_Two, g_pSchemaTestExternal_Two ); + +#define SCHEMATESTEXTERNALONE_INTERFACE_VERSION "SchemaTestExternal_One_001" +DECLARE_TIER3_INTERFACE( ISchemaTestExternal_One, g_pSchemaTestExternal_One ); + +#define ANIMATIONSYSTEM_INTERFACE_VERSION "AnimationSystem_001" +DECLARE_TIER3_INTERFACE( IAnimationSystem, g_pAnimationSystem ); + +#define ANIMATIONSYSTEMUTILS_INTERFACE_VERSION "AnimationSystemUtils_001" +DECLARE_TIER3_INTERFACE( IAnimationSystemUtils, g_pAnimationSystemUtils ); + +#define HAMMERMAPLOADER_INTERFACE_VERSION "HammerMapLoader001" +DECLARE_TIER3_INTERFACE( IHammerMapLoader, g_pHammerMapLoader ); + +#define MATERIALUTILS_INTERFACE_VERSION "MaterialUtils_001" +DECLARE_TIER3_INTERFACE( IMaterialUtils, g_pMaterialUtils ); + +#define FONTMANAGER_INTERFACE_VERSION "FontManager_001" +DECLARE_TIER3_INTERFACE( IFontManager, g_pFontManager ); + +#define TEXTLAYOUT_INTERFACE_VERSION "TextLayout_001" +DECLARE_TIER3_INTERFACE( ITextLayout, g_pTextLayout ); + +#define ASSETPREVIEWSYSTEM_INTERFACE_VERSION "AssetPreviewSystem_001" +DECLARE_TIER3_INTERFACE( IAssetPreviewSystem, g_pAssetPreviewSystem ); + +#define ASSETBROWSERSYSTEM_INTERFACE_VERSION "AssetBrowserSystem_001" +DECLARE_TIER3_INTERFACE( IAssetBrowserSystem, g_pAssetBrowserSystem ); + +#define VCONCOMM_INTERFACE_VERSION "VConComm001" +DECLARE_TIER3_INTERFACE( IVConComm, g_pVConComm ); + +#define CONFIGURATIONSYSTEM_INTERFACE_VERSION "ConfigurationSystem_001" +DECLARE_TIER3_INTERFACE( IConfigurationSystem, g_pConfigurationSystem ); + +#define FLATTENEDSERIALIZERS_INTERFACE_VERSION "FlattenedSerializersVersion001" +DECLARE_TIER3_INTERFACE( IFlattenedSerializers, g_pFlattenedSerializers ); + +#define SOURCE2CLIENT_INTERFACE_VERSION "Source2Client001" +DECLARE_TIER3_INTERFACE( ISource2Client, g_pSource2Client ); + +#define SOURCE2CLIENTPREDICTION_INTERFACE_VERSION "Source2ClientPrediction001" +DECLARE_TIER3_INTERFACE( ISource2ClientPrediction, g_pSource2ClientPrediction ); + +#define SOURCE2SERVER_INTERFACE_VERSION "Source2Server001" +DECLARE_TIER3_INTERFACE( ISource2Server, g_pSource2Server ); + +#define SOURCE2SERVERSERIALIZERS_INTERFACE_VERSION "Source2ServerSerializers001" +DECLARE_TIER3_INTERFACE( ISource2ServerSerializers, g_pSource2ServerSerializers ); + +#define SOURCE2HOST_INTERFACE_VERSION "Source2Host001" +DECLARE_TIER3_INTERFACE( ISource2Host, g_pSource2Host ); + +#define SOURCE2GAMECLIENTS_INTERFACE_VERSION "Source2GameClients001" +DECLARE_TIER3_INTERFACE( ISource2GameClients, g_pSource2GameClients ); + +#define SOURCE2GAMEENTITIES_INTERFACE_VERSION "Source2GameEntities001" +DECLARE_TIER3_INTERFACE( ISource2GameEntities, g_pSource2GameEntities ); + +#define ENGINESERVICEMGR_INTERFACE_VERSION "EngineServiceMgr001" +DECLARE_TIER3_INTERFACE( IEngineServiceMgr, g_pEngineServiceMgr ); + +#define HOSTSTATEMGR_INTERFACE_VERSION "HostStateMgr001" +DECLARE_TIER3_INTERFACE( IHostStateMgr, g_pHostStateMgr ); + +#define NETWORKSERVICE_INTERFACE_VERSION "NetworkService_001" +DECLARE_TIER3_INTERFACE( INetworkService, g_pNetworkService ); + +#define NETWORKCLIENTSERVICE_INTERFACE_VERSION "NetworkClientService_001" +DECLARE_TIER3_INTERFACE( INetworkClientService, g_pNetworkClientService ); + +#define NETWORKSERVERSERVICE_INTERFACE_VERSION "NetworkServerService_001" +DECLARE_TIER3_INTERFACE( INetworkServerService, g_pNetworkServerService ); + +#define TEXTMESSAGEMGR_INTERFACE_VERSION "TextMessageMgr_001" +DECLARE_TIER3_INTERFACE( ITextMessageMgr, g_pTextMessageMgr ); + +#define TOOLSERVICE_INTERFACE_VERSION "ToolService_001" +DECLARE_TIER3_INTERFACE(IToolService, g_pToolService); + +#define RENDERSERVICE_INTERFACE_VERSION "RenderService_001" +DECLARE_TIER3_INTERFACE( IRenderService, g_pRenderService ); + +#define STATSSERVICE_INTERFACE_VERSION "StatsService_001" +DECLARE_TIER3_INTERFACE( IStatsService, g_pStatsService ); + +#define USERINFOCHANGESERVICE_INTERFACE_VERSION "UserInfoChangeService_001" +DECLARE_TIER3_INTERFACE( IUserInfoChangeService, g_pUserInfoChangeService ); + +#define VPROFSERVICE_INTERFACE_VERSION "VProfService_001" +DECLARE_TIER3_INTERFACE( IVProfService, g_pVProfService ); + +#define INPUTSERVICE_INTERFACE_VERSION "InputService_001" +DECLARE_TIER3_INTERFACE( IInputService, g_pInputService ); + +#define MAPLISTSERVICE_INTERFACE_VERSION "MapListService_001" +DECLARE_TIER3_INTERFACE( IMapListService, g_pMapListService ); + +#define GAMEUISERVICE_INTERFACE_VERSION "GameUIService_001" +DECLARE_TIER3_INTERFACE( IGameUIService, g_pGameUIService ); + +#define SOUNDSERVICE_INTERFACE_VERSION "SoundService_001" +DECLARE_TIER3_INTERFACE( ISoundService, g_pSoundService ); + +#define BENCHMARKSERVICE_INTERFACE_VERSION "BenchmarkService001" +DECLARE_TIER3_INTERFACE( IBenchmarkService, g_pBenchmarkService ); + +#define DEBUGSERVICE_INTERFACE_VERSION "VDebugService_001" +DECLARE_TIER3_INTERFACE( IDebugService, g_pDebugService ); + +#define KEYVALUECACHE_INTERFACE_VERSION "KeyValueCache001" +DECLARE_TIER3_INTERFACE( IKeyValueCache, g_pKeyValueCache ); + +#define GAMERESOURCESERVICECLIENT_INTERFACE_VERSION "GameResourceServiceClientV001" +DECLARE_TIER3_INTERFACE( IGameResourceServiceClient, g_pGameResourceServiceClient ); + +#define GAMERESOURCESERVICESERVER_INTERFACE_VERSION "GameResourceServiceServerV001" +DECLARE_TIER3_INTERFACE( IGameResourceServiceServer, g_pGameResourceServiceServer ); + +#define SOURCE2ENGINETOCLIENT_INTERFACE_VERSION "Source2EngineToClient001" +DECLARE_TIER3_INTERFACE( ISource2EngineToClient, g_pSource2EngineToClient ); + +#define SOURCE2ENGINETOSERVER_INTERFACE_VERSION "Source2EngineToServer001" +DECLARE_TIER3_INTERFACE( ISource2EngineToServer, g_pSource2EngineToServer ); + +#define SOURCE2ENGINETOSERVERSTRINGTABLE_INTERFACE_VERSION "Source2EngineToServerStringTable001" +DECLARE_TIER3_INTERFACE( ISource2EngineToServerStringTable, g_pSource2EngineToServerStringTable ); + +#define SOURCE2ENGINETOCLIENTSTRINGTABLE_INTERFACE_VERSION "Source2EngineToClientStringTable001" +DECLARE_TIER3_INTERFACE( ISource2EngineToClientStringTable, g_pSource2EngineToClientStringTable ); + +#define SOURCE2ENGINESOUNDSERVER_INTERFACE_VERSION "Source2EngineSoundServer001" +DECLARE_TIER3_INTERFACE( ISource2EngineSoundServer, g_pSource2EngineSoundServer ); + +#define SOURCE2ENGINESOUNDCLIENT_INTERFACE_VERSION "Source2EngineSoundClient001" +DECLARE_TIER3_INTERFACE( ISource2EngineSoundClient, g_pSource2EngineSoundClient ); + +#define SCALEFORMUI_INTERFACE_VERSION "ScaleformUI001" +DECLARE_TIER3_INTERFACE( IScaleformUI, g_pScaleformUI ); + +#define SERVERUPLOADGAMESTATS_INTERFACE_VERSION "ServerUploadGameStats001" +DECLARE_TIER3_INTERFACE( IServerUploadGameStats, g_pServerUploadGameStats ); + +#define SCENESYSTEM_INTERFACE_VERSION "SceneSystem_002" DECLARE_TIER3_INTERFACE( ISceneSystem, g_pSceneSystem ); -#define VGUI_SURFACE_INTERFACE_VERSION "VGUI_Surface031" +#define SCENEUTILS_INTERFACE_VERSION "SceneUtils_001" +DECLARE_TIER3_INTERFACE( ISceneUtils, g_pSceneUtils ); + +#define VGUI_SURFACE_INTERFACE_VERSION "VGUI_Surface032" DECLARE_TIER3_INTERFACE( vgui::ISurface, g_pVGuiSurface ); #define SCHEME_SURFACE_INTERFACE_VERSION "SchemeSurface001" @@ -236,7 +533,7 @@ DECLARE_TIER3_INTERFACE( vgui::IInput, g_pVGuiInput ); #define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008" DECLARE_TIER3_INTERFACE( vgui::IVGui, g_pVGui ); -#define VGUI_PANEL_INTERFACE_VERSION "VGUI_Panel009" +#define VGUI_PANEL_INTERFACE_VERSION "VGUI_Panel010" DECLARE_TIER3_INTERFACE( vgui::IPanel, g_pVGuiPanel ); #define VGUI_SCHEME_INTERFACE_VERSION "VGUI_Scheme010" @@ -248,28 +545,30 @@ DECLARE_TIER3_INTERFACE( vgui::ISystem, g_pVGuiSystem ); #define DATACACHE_INTERFACE_VERSION "VDataCache003" DECLARE_TIER3_INTERFACE( IDataCache, g_pDataCache ); // FIXME: Should IDataCache be in tier2? -#define MDLCACHE_INTERFACE_VERSION "MDLCache004" -DECLARE_TIER3_INTERFACE( IMDLCache, g_pMDLCache ); -DECLARE_TIER3_INTERFACE( IMDLCache, mdlcache ); - #define AVI_INTERFACE_VERSION "VAvi001" DECLARE_TIER3_INTERFACE( IAvi, g_pAVI ); #define BIK_INTERFACE_VERSION "VBik001" DECLARE_TIER3_INTERFACE( IBik, g_pBIK ); +#define QUICKTIME_INTERFACE_VERSION "IQuickTime001" +DECLARE_TIER3_INTERFACE( IQuickTime, g_pQuickTime ); + #define DMEMAKEFILE_UTILS_INTERFACE_VERSION "VDmeMakeFileUtils001" DECLARE_TIER3_INTERFACE( IDmeMakefileUtils, g_pDmeMakefileUtils ); -#define VPHYSICS_COLLISION_INTERFACE_VERSION "VPhysicsCollision007" -DECLARE_TIER3_INTERFACE( IPhysicsCollision, g_pPhysicsCollision ); - #define SOUNDEMITTERSYSTEM_INTERFACE_VERSION "VSoundEmitter003" DECLARE_TIER3_INTERFACE( ISoundEmitterSystemBase, g_pSoundEmitterSystem ); +#define SOUNDEMITTERSYSTEMS1_INTERFACE_VERSION "VSoundEmitterS1_001" +DECLARE_TIER3_INTERFACE( ISoundEmitterSystemBaseS1, g_pSoundEmitterSystemS1 ); + #define WORLD_RENDERER_MGR_INTERFACE_VERSION "WorldRendererMgr001" DECLARE_TIER3_INTERFACE( IWorldRendererMgr, g_pWorldRendererMgr ); +#define VR_INTERFACE_VERSION "VR_001" +DECLARE_TIER3_INTERFACE(IVR, vr); + //----------------------------------------------------------------------------- // Fills out global DLL exported interface pointers //----------------------------------------------------------------------------- diff --git a/public/tier0/basetypes.h b/public/tier0/basetypes.h index 4cd5fa4c..c0d25072 100644 --- a/public/tier0/basetypes.h +++ b/public/tier0/basetypes.h @@ -113,6 +113,37 @@ FORCEINLINE float fpmax( float a, float b ) #ifdef __cplusplus +// This is the preferred clamp operator. Using the clamp macro can lead to +// unexpected side-effects or more expensive code. Even the clamp (all +// lower-case) function can generate more expensive code because of the +// mixed types involved. +template< class T > +T Clamp( T const &val, T const &minVal, T const &maxVal ) +{ + if( val < minVal ) + return minVal; + else if( val > maxVal ) + return maxVal; + else + return val; +} + +// This is the preferred Min operator. Using the MIN macro can lead to unexpected +// side-effects or more expensive code. +template< class T > +T Min( T const &val1, T const &val2 ) +{ + return val1 < val2 ? val1 : val2; +} + +// This is the preferred Max operator. Using the MAX macro can lead to unexpected +// side-effects or more expensive code. +template< class T > +T Max( T const &val1, T const &val2 ) +{ + return val1 > val2 ? val1 : val2; +} + template< class T, class Y > inline T clamp( T const &val, Y const &minVal, Y const &maxVal ) { diff --git a/public/tier0/dbg.h b/public/tier0/dbg.h index 5ebccbc2..a8f910c0 100644 --- a/public/tier0/dbg.h +++ b/public/tier0/dbg.h @@ -82,8 +82,6 @@ class Color; // DebuggerBreak(); //----------------------------------------------------------------------------- -PLATFORM_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line ); - PLATFORM_INTERFACE bool SetupWin32ConsoleIO(); // Returns true if they want to break in the debugger. @@ -96,11 +94,6 @@ PLATFORM_INTERFACE bool SetupWin32ConsoleIO(); { \ LoggingResponse_t ret = Log_Assert( "%s (%d) : %s\n", __TFILE__, __LINE__, _msg ); \ _executeExp; \ - if ( ret == LR_DEBUGGER ) \ - { \ - if ( _bFatal ) \ - _ExitOnFatalAssert( __TFILE__, __LINE__ ); \ - } \ } \ } while (0) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 701a06ab..3884114c 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -91,16 +91,14 @@ void ConVar_PublishToVXConsole(); //----------------------------------------------------------------------------- // Called when a ConCommand needs to execute //----------------------------------------------------------------------------- -typedef void ( *FnCommandCallbackV1_t )( void ); -typedef void ( *FnCommandCallback_t )( const CCommandContext &context, const CCommand &command ); - -#define COMMAND_COMPLETION_MAXITEMS 64 -#define COMMAND_COMPLETION_ITEM_LENGTH 64 +typedef void ( *FnCommandCallbackV1_t )( const CCommandContext &context ); +typedef void ( *FnCommandCallbackV2_t )( const CCommandContext &context, const CCommand &command ); +typedef void ( *FnCommandCallback_t )( const CCommand &command ); //----------------------------------------------------------------------------- // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings //----------------------------------------------------------------------------- -typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); +typedef int(*FnCommandCompletionCallback)( const char *partial, CUtlVector< CUtlString > &commands ); //----------------------------------------------------------------------------- @@ -109,13 +107,7 @@ typedef int ( *FnCommandCompletionCallback )( const char *partial, char command class ICommandCallback { public: - virtual void CommandCallback( const CCommand &command ) = 0; -}; - -class ICommandCallback2 -{ -public: - virtual void CommandCallback( const CCommandContext &context, const CCommand &command ) = 0; + virtual void CommandCallback(const CCommandContext &context, const CCommand &command) = 0; }; class ICommandCompletionCallback @@ -183,6 +175,8 @@ protected: char *CopyString( const char *from ); private: + int m_Unknown; + // Next ConVar in chain // Prior to register, it points to the next convar in the DLL. // Once registered, though, m_pNext is reset to point to the next @@ -198,6 +192,7 @@ private: // ConVar flags int m_nFlags; + int m_nFlags2; protected: // ConVars add themselves to this list for the executable. @@ -300,14 +295,10 @@ friend class CCvar; public: typedef ConCommandBase BaseClass; - ConCommand( const char *pName, FnCommandCallbackV1_t callback, - const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); - ConCommand( const char *pName, ICommandCallback2 *pCallback, - const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); virtual ~ConCommand( void ); @@ -329,25 +320,34 @@ private: // Those fields will not exist in the version of this class that is instanced // in mod code. - // Call this function when executing the command union { FnCommandCallbackV1_t m_fnCommandCallbackV1; - FnCommandCallback_t m_fnCommandCallback; - ICommandCallback *m_pCommandCallback; - ICommandCallback2 *m_pCommandCallback2; - }; - - union - { + FnCommandCallbackV2_t m_fnCommandCallbackV2; FnCommandCompletionCallback m_fnCompletionCallback; ICommandCompletionCallback *m_pCommandCompletionCallback; }; bool m_bHasCompletionCallback : 1; - bool m_bUsingCommandCallbackInterface : 1; - bool m_bUsingOldCommandCallback : 1; - bool m_bUsingCommandCallbackInterface2 : 1; + bool m_bUsingCommandCompletionInterface : 1; + + struct ConCommandCB + { + // Call this function when executing the command + union + { + FnCommandCallback_t m_fnCommandCallback; + FnCommandCallbackV2_t m_fnCommandCallbackV2; + ICommandCallback *m_pCommandCallback; + }; + + bool m_bUsingCommandCallbackInterface : 1; + bool m_bUsingOldCommandCallback : 1; + bool m_bUsingV2CommandCallback : 1; + }; + CUtlVector m_Callbacks; + + ConCommand *m_pParent; }; @@ -957,9 +957,9 @@ private: // Purpose: Utility macros to quicky generate a simple console command //----------------------------------------------------------------------------- #define CON_COMMAND( name, description ) \ - static void name( const CCommandContext &context, const CCommand &args ); \ + static void name( const CCommand &args ); \ static ConCommand name##_command( #name, name, description ); \ - static void name( const CCommandContext &context, const CCommand &args ) + static void name( const CCommand &args ) #ifdef CLIENT_DLL #define CON_COMMAND_SHARED( name, description ) \ diff --git a/public/tier1/iconvar.h b/public/tier1/iconvar.h index 2048032d..4f4d0215 100644 --- a/public/tier1/iconvar.h +++ b/public/tier1/iconvar.h @@ -80,7 +80,7 @@ class CCommand; #define FCVAR_ACCESSIBLE_FROM_THREADS (1<<25) // used as a debugging tool necessary to check material system thread convars #define FCVAR_VCONSOLE_SET_FOCUS (1<<31) -// #define FCVAR_AVAILABLE (1<<26) +#define FCVAR_LINKED_CONCOMMAND (1<<26) // #define FCVAR_AVAILABLE (1<<27) #define FCVAR_MATERIAL_THREAD_MASK ( FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD ) @@ -115,6 +115,8 @@ public: virtual bool IsFlagSet( int nFlag ) const = 0; virtual int GetSplitScreenPlayerSlot() const = 0; + + virtual void AddFlags( int flags ) = 0; }; diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h index 29358ada..e77d7ca3 100644 --- a/public/tier1/strtools.h +++ b/public/tier1/strtools.h @@ -227,6 +227,8 @@ typedef char * va_list; #define INCORRECT_PATH_SEPARATOR_S "\\" #endif +int V_vsnprintf( char *pDest, int maxLenInCharacters, const char *pFormat, va_list params ); +template int V_vsprintf_safe( char (&pDest)[maxLenInCharacters], const char *pFormat, va_list params ) { return V_vsnprintf( pDest, maxLenInCharacters, pFormat, params ); } int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params ); // Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes ) diff --git a/public/tier1/utlbinaryblock.h b/public/tier1/utlbinaryblock.h new file mode 100644 index 00000000..93c6e680 --- /dev/null +++ b/public/tier1/utlbinaryblock.h @@ -0,0 +1,107 @@ +//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef UTLBINARYBLOCK_H +#define UTLBINARYBLOCK_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlmemory.h" +#include "tier1/strtools.h" +#include "limits.h" + +//----------------------------------------------------------------------------- +// Base class, containing simple memory management +//----------------------------------------------------------------------------- +class CUtlBinaryBlock +{ +public: + CUtlBinaryBlock( int growSize = 0, int initSize = 0 ); + + // NOTE: nInitialLength indicates how much of the buffer starts full + CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ); + CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ); + CUtlBinaryBlock( const CUtlBinaryBlock& src ); + + void Get( void *pValue, int nMaxLen ) const; + void Set( const void *pValue, int nLen ); + const void *Get( ) const; + void *Get( ); + + unsigned char& operator[]( int i ); + const unsigned char& operator[]( int i ) const; + + int Length() const; + void SetLength( int nLength ); // Undefined memory will result + bool IsEmpty() const; + void Clear(); + void Purge(); + + bool IsReadOnly() const; + + CUtlBinaryBlock &operator=( const CUtlBinaryBlock &src ); + + // Test for equality + bool operator==( const CUtlBinaryBlock &src ) const; + +private: + CUtlMemory m_Memory; + int m_nActualLength; +}; + + +//----------------------------------------------------------------------------- +// class inlines +//----------------------------------------------------------------------------- +inline const void *CUtlBinaryBlock::Get( ) const +{ + return m_Memory.Base(); +} + +inline void *CUtlBinaryBlock::Get( ) +{ + return m_Memory.Base(); +} + +inline int CUtlBinaryBlock::Length() const +{ + return m_nActualLength; +} + +inline unsigned char& CUtlBinaryBlock::operator[]( int i ) +{ + return m_Memory[i]; +} + +inline const unsigned char& CUtlBinaryBlock::operator[]( int i ) const +{ + return m_Memory[i]; +} + +inline bool CUtlBinaryBlock::IsReadOnly() const +{ + return m_Memory.IsReadOnly(); +} + +inline bool CUtlBinaryBlock::IsEmpty() const +{ + return Length() == 0; +} + +inline void CUtlBinaryBlock::Clear() +{ + SetLength( 0 ); +} + +inline void CUtlBinaryBlock::Purge() +{ + SetLength( 0 ); + m_Memory.Purge(); +} + +#endif // UTLBINARYBLOCK_H + diff --git a/public/tier1/utldelegate.h b/public/tier1/utldelegate.h new file mode 100644 index 00000000..04c5dad2 --- /dev/null +++ b/public/tier1/utldelegate.h @@ -0,0 +1,97 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A header describing use of the delegate system. It's hiding +// the highly complex implementation details of the delegate system +// +// $NoKeywords: $ +// +//===========================================================================// + +#ifndef UTLDELEGATE_H +#define UTLDELEGATE_H + +#ifdef _WIN32 +#pragma once +#endif + + +//----------------------------------------------------------------------------- +// The delegate system: A method of invoking methods, whether they are +// member methods of classes, static methods of classes, or free functions, +// dealing with all the nastiness in differences between how the calls have +// to happen yet works in a highly optimal fashion. For details, see +// +// http://www.codeproject.com/cpp/FastDelegate.asp +// +// The delegate design pattern is described here +// +// http://en.wikipedia.org/wiki/Delegation_(programming) +//----------------------------------------------------------------------------- + +#ifdef UTLDELEGATE_USAGE_DEMONSTRATION + +//----------------------------------------------------------------------------- +// Here, we show how to use this system (the ifdef UTLDELEGATE_USAGE_DEMONSTRATION is used to get syntax coloring). +//----------------------------------------------------------------------------- + +// First, define the functions you wish to call. +int Test1( char *pString, float x ); +class CTestClass +{ +public: + void Test2(); + static float Test3( int x ); +}; + +void Test() +{ + CTestClass testClass; + + // CUtlDelegate is a class that can be used to invoke methods of classes + // or static functions in a highly efficient manner. + + // There are a couple ways to hook up a delegate. One is in a constructor + // Note that the template parameter of CUtlFastDelegate looks like the + // function type: first, you have the return type, then ( parameter list ) + CUtlDelegate< int ( char *, float ) > delegate1( &Test1 ); + + // Another way is to use the UtlMakeDelegate method, allowing you to + // define the delegate later. Note that UtlMakeDelegate does *not* do a heap allocation + CUtlDelegate< void () > delegate2; + delegate2 = UtlMakeDelegate( &testClass, &CTestClass::Test2 ); + + // A third method is to use the Bind() method of CUtlFastDelegate + // Note that you do not pass in the class pointer for static functions + CUtlDelegate< float ( int ) > delegate3; + delegate3.Bind( &CTestClass::Test3 ); + + // Use the () operator to invoke the function calls. + int x = delegate1( "hello", 1.0f ); + delegate2(); + float y = delegate3( 5 ); + + // Use the Clear() method to unbind a delegate. + delegate1.Clear(); + + // You can use operator! or IsEmpty() to see if a delegate is bound + if ( !delegate1.IsEmpty() ) + { + delegate1( "hello2" ); + } + + // Delegates maintain an internal non-templatized representation of the + // functions they are bound to called CUtlAbstractDelegate. These are + // useful when keeping a list of untyped delegates or when passing + // delegates across interface boundaries. + const CUtlAbstractDelegate &abstractDelegate3 = delegate3.GetAbstractDelegate(); + CUtlDelegate< float ( int ) > delegate4; + delegate4.SetAbstractDelegate( abstractDelegate3 ); + delegate4( 10 ); +} + +#endif // UTLDELEGATE_USAGE_DEMONSTRATION + +// Looking in this file may cause blindness. +#include "tier1/utldelegateimpl.h" + +#endif // UTLDELEGATE_H diff --git a/public/tier1/utldelegateimpl.h b/public/tier1/utldelegateimpl.h new file mode 100644 index 00000000..cf9809d8 --- /dev/null +++ b/public/tier1/utldelegateimpl.h @@ -0,0 +1,2656 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * UtlMakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.Clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::IsEmpty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added CUtlAbstractDelegate, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .Clear(), ==0 as equivalent to .IsEmpty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.IsEmpty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: IsEmpty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. +// 22-Jul-10 xxx * Reformatted + renamed to match valve coding standards +// * Added UtlMakeDelegate for static functions + +#ifndef UTLDELEGATEIMPL_H +#define UTLDELEGATEIMPL_H +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 + // At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace detail // we'll hide the implementation details in a nested namespace. +{ + +// implicit_cast< > +// I believe this was originally going to be in the C++ standard but +// was left out by accident. It's even milder than static_cast. +// I use it instead of static_cast<> to emphasize that I'm not doing +// anything nasty. +// Usage is identical to static_cast<> +template +inline OutputClass implicit_cast(InputClass input) +{ + return input; +} + +// horrible_cast< > +// This is truly evil. It completely subverts C++'s type system, allowing you +// to cast from any class to any other class. Technically, using a union +// to perform the cast is undefined behaviour (even in C). But we can see if +// it is OK by checking that the union is the same size as each of its members. +// horrible_cast<> should only be used for compiler-specific workarounds. +// Usage is identical to reinterpret_cast<>. + +// This union is declared outside the horrible_cast because BCC 5.5.1 +// can't inline a function with a nested class, and gives a warning. +template +union horrible_union +{ + OutputClass out; + InputClass in; +}; + +template +inline OutputClass horrible_cast(const InputClass input) +{ + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) + && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; +} + +//////////////////////////////////////////////////////////////////////////////// +// Workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Backwards compatibility: This macro used to be necessary in the virtual inheritance +// case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + +// Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + +// DefaultVoid - a workaround for 'void' templates in VC6. +// +// (1) VC6 and earlier do not allow 'void' as a default template argument. +// (2) They also doesn't allow you to return 'void' from a function. +// +// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use +// when we'd like to use 'void'. We convert it into 'void' and back +// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. +// Workaround for (2): On VC6, the code for calling a void function is +// identical to the code for calling a non-void function in which the +// return value is never used, provided the return value is returned +// in the EAX register, rather than on the stack. +// This is true for most fundamental types such as int, enum, void *. +// Const void * is the safest option since it doesn't participate +// in any automatic conversions. But on a 16-bit compiler it might +// cause extra code to be generated, so we disable it for all compilers +// except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 +// VC6 workaround +typedef const void * DefaultVoid; +#else +// On any other compiler, just use a normal void. +typedef void DefaultVoid; +#endif + +// Translate from 'DefaultVoid' to 'void'. +// Everything else is unchanged +template +struct DefaultVoidToVoid { typedef T type; }; + +template <> +struct DefaultVoidToVoid { typedef void type; }; + +// Translate from 'void' into 'DefaultVoid' +// Everything else is unchanged +template +struct VoidToDefaultVoid { typedef T type; }; + +template <> +struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1: +// +// Conversion of member function pointer to a standard form +// +//////////////////////////////////////////////////////////////////////////////// + +// GenericClass is a fake class, ONLY used to provide a type. +// It is vitally important that it is never defined, so that the compiler doesn't +// think it can optimize the invocation. For example, Borland generates simpler +// code if it knows the class only uses single inheritance. + +// Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + +// The size of a single inheritance member function pointer. +const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + +// SimplifyMemFunc< >::Convert() +// +// A template function that converts an arbitrary member function pointer into the +// simplest possible form of member function pointer, using a supplied 'this' pointer. +// According to the standard, this can be done legally with reinterpret_cast<>. +// For (non-standard) compilers which use member function pointers which vary in size +// depending on the class, we need to use knowledge of the internal structure of a +// member function pointer, as used by the compiler. Template specialization is used +// to distinguish between the sizes. Because some compilers don't support partial +// template specialisation, I use full specialisation of a wrapper struct. + +// general case -- don't know how to convert it. Force a compile failure +template +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N-100]; + return 0; + } +}; + +// For compilers where all member func ptrs are the same size, everything goes here. +// For non-standard compilers, only single_inheritance classes go here. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 1b: +// +// Workarounds for Microsoft and Intel +// +//////////////////////////////////////////////////////////////////////////////// + + +// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), +// need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) +// at the start of each function for extra safety, but VC6 seems to ICE +// intermittently if you do this inside a template. + +// __multiple_inheritance classes go here +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +template<> +struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union + { + XFuncType func; + struct + { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } +}; + +// virtual inheritance is a real nuisance. It's inefficient and complicated. +// On MSVC and Intel, there isn't enough information in the pointer itself to +// enable conversion to a closure pointer. Earlier versions of this code didn't +// work for all cases, and generated a compile-time error instead. +// But a very clever hack invented by John M. Dlugosz solves this problem. +// My code is somewhat different to his: I have no asm code, and I make no +// assumptions about the calling convention that is used. + +// In VC++ and ICL, a virtual_inheritance member pointer +// is internally defined as: +struct MicrosoftVirtualMFP +{ + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance +}; +// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the +// m_codeptr member is *always* called, regardless of the values of the other +// members. (This is *not* true for other compilers, eg GCC, which obtain the +// function address from the vtable if a virtual function is being called). +// Dlugosz's trick is to make the codeptr point to a probe function which +// returns the 'this' pointer that was used. + +// Define a generic class that uses virtual inheritance. +// It has a trival member function that returns the value of the 'this' pointer. +struct GenericVirtualClass : virtual public GenericClass +{ + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } +}; + +// __virtual_inheritance classes go here +#ifdef _MSC_VER +#pragma warning( disable : 4121 ) +#endif + +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { + union + { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union + { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind)==sizeof(u.s) + && sizeof(function_to_bind)==sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } +}; +#ifdef _MSC_VER +#pragma warning( default : 4121 ) +#endif + +#if (_MSC_VER <1300) + +// Nasty hack for Microsoft Visual C++ 6.0 +// unknown_inheritance classes go here +// There is a compiler bug in MSVC6 which generates incorrect code in this case!! +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } +}; + + +#else + +// Nasty hack for Microsoft and Intel (IA32 and Itanium) +// unknown_inheritance classes go here +// This is probably the ugliest bit of code I've ever written. Look at the casts! +// There is a compiler bug in MSVC6 which prevents it from using this code. +template <> +struct SimplifyMemFunc +{ + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) + { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union + { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct + { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType)==sizeof(u.s)? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) + { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp ); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; +}; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 2: +// +// Define the delegate storage, and cope with static functions +// +//////////////////////////////////////////////////////////////////////////////// + +// CUtlAbstractDelegate -- an opaque structure which can hold an arbitary delegate. +// It knows nothing about the calling convention or number of arguments used by +// the function pointed to. +// It supplies comparison operators so that it can be stored in STL collections. +// It cannot be set to anything other than null, nor invoked directly: +// it must be converted to a specific delegate. + +// Implementation: +// There are two possible implementations: the Safe method and the Evil method. +// CUtlAbstractDelegate - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// A static function pointer is stored inside the class. +// Here are the valid values: +// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ +// | 0 | 0 | 0 | Empty | +// | !=0 |(dontcare)| Invoker | Static function| +// | 0 | !=0 | !=0* | Method call | +// +--------------------+----------+------------+----------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// When stored stored inside a specific delegate, the 'dontcare' entries are replaced +// with a reference to the delegate itself. This complicates the = and == operators +// for the delegate class. + +// CUtlAbstractDelegate - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. In this case the CUtlAbstractDelegate implementation is simple: +// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ +// | 0 | 0 | Empty | +// | !=0 | !=0* | Static function or method call| +// +----------+------------+-------------------------------+ +// * For Metrowerks, this can be 0. (first virtual function in a +// single_inheritance class). +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + +class CUtlAbstractDelegate +{ +protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void (*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void Clear() + { + m_pthis=0; m_pFunction=0; m_pStaticFunction=0; + } +#else + CUtlAbstractDelegate() : m_pthis(0), m_pFunction(0) {}; + void Clear() { m_pthis=0; m_pFunction=0; } +#endif +public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual (const CUtlAbstractDelegate &x) const + { + // We have to cope with the static function pointers as a special case + if (m_pFunction!=x.m_pFunction) + return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction!=x.m_pStaticFunction) + return false; + if (m_pStaticFunction!=0) + return m_pthis==x.m_pthis; + else + return true; + } +#else // Evil Method + inline bool IsEqual (const CUtlAbstractDelegate &x) const + { + return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const CUtlAbstractDelegate &right) const + { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis !=right.m_pthis) + return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { + return m_pthis==0 && m_pFunction==0; + } + inline bool IsEmpty() const // Is it bound to anything? + { + return m_pthis==0 && m_pFunction==0; + } +public: + CUtlAbstractDelegate & operator = (const CUtlAbstractDelegate &right) + { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const CUtlAbstractDelegate &right) + { + return IsLess(right); + } + inline bool operator >(const CUtlAbstractDelegate &right) + { + return right.IsLess(*this); + } + CUtlAbstractDelegate (const CUtlAbstractDelegate &right) : + m_pFunction(right.m_pFunction), m_pthis(right.m_pthis) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction (right.m_pStaticFunction) +#endif + {} + + // Only use this if you really know what you're doing. + // It's used in cases where I've cached off a delegate previously + void UnsafeThisPointerSlam( void *pThis ) + { + m_pthis = (detail::GenericClass*)( pThis ); + } + + void *UnsafeGetThisPtr() + { + return m_pthis; + } + +protected: + void SetMementoFrom(const CUtlAbstractDelegate &right) + { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } +}; + + +// ClosurePtr<> +// +// A private wrapper class that adds function signatures to CUtlAbstractDelegate. +// It's the class that does most of the actual work. +// The signatures are specified by: +// GenericMemFunc: must be a type of GenericClass member function pointer. +// StaticFuncPtr: must be a type of function pointer with the same signature +// as GenericMemFunc. +// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 +// where it never returns void (returns DefaultVoid instead). + +// An outer class, FastDelegateN<>, handles the invoking and creates the +// necessary typedefs. +// This class does everything else. + +namespace detail +{ + +template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> +class ClosurePtr : public CUtlAbstractDelegate +{ +public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) + { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) + { + m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) + { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + +// There are a few ways of dealing with static function pointers. +// There's a standard-compliant, but tricky method. +// There's also a straightforward hack, that won't work on DOS compilers using the +// medium memory model. It's so evil that I can't recommend it, but I've +// implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + +// ClosurePtr<> - Safe version +// +// This implementation is standard-compliant, but a bit tricky. +// I store the function pointer inside the class, and the delegate then +// points to itself. Whenever the delegate is copied, these self-references +// must be transformed, and this complicates the = and == operators. +public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &x) + { + SetMementoFrom(x); + if (m_pStaticFunction!=0) + { + // transform self references... + m_pthis=reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind ) + { + if (function_to_bind==0) + { // cope with assignment to 0 + m_pFunction=0; + } + else + { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction=reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const + { + return reinterpret_cast(m_pStaticFunction); + } +#else + +// ClosurePtr<> - Evil version +// +// For compilers where data pointers are at least as big as code pointers, it is +// possible to store the function pointer in the this pointer, using another +// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and +// speeds up comparison and assignment. If C++ provided direct language support +// for delegates, they would produce asm code that was almost identical to this. +// Note that the Sun C++ and MSVC documentation explicitly state that they +// support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom (DerivedClass *pParent, const CUtlAbstractDelegate &right) + { + pParent; + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) + { + if (function_to_bind==0) + { // cope with assignment to 0 + m_pFunction=0; + } + else + { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *)==sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: +// m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long +// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const + { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr)==sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr) + { + if (funcptr==0) return IsEmpty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr==reinterpret_cast(GetStaticFunction()); + } +}; + + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 3: +// +// Wrapper classes to ensure type safety +// +//////////////////////////////////////////////////////////////////////////////// + + +// Once we have the member function conversion templates, it's easy to make the +// wrapper classes. So that they will work with as many compilers as possible, +// the classes are of the form +// FastDelegate3 +// They can cope with any combination of parameters. The max number of parameters +// allowed is 8, but it is trivial to increase this limit. +// Note that we need to treat const member functions seperately. +// All this class does is to enforce type safety, and invoke the delegate with +// the correct list of parameters. + +// Because of the weird rule about the class of derived member function pointers, +// you sometimes need to apply a downcast to the 'this' pointer. +// This is the reason for the use of "implicit_cast(pthis)" in the code below. +// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, +// without this trick you'd need to write: +// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); +// but with the trick you can write +// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + +// RetType is the type the compiler uses in compiling the template. For VC6, +// it cannot be void. DesiredRetType is the real type which is returned from +// all of the functions. It can be void. + +// Implicit conversion to "bool" is achieved using the safe_bool idiom, +// using member data pointers (MDP). This allows "if (dg)..." syntax +// Because some compilers (eg codeplay) don't have a unique value for a zero +// MDP, an extra padding member is added to the SafeBool struct. +// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so +// in that case the static function constructor is not made explicit; this +// allows "if (dg==0) ..." to compile. + +//N=0 +template +class FastDelegate0 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(); + typedef RetType (*UnvoidStaticFunctionPtr)(); + typedef RetType (detail::GenericClass::*GenericMemFn)(); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate0 type; + + // Construction and comparison functions + FastDelegate0() { Clear(); } + FastDelegate0(const FastDelegate0 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate0 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate0 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate0 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate0 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate0 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate0(Y *pthis, DesiredRetType (X::* function_to_bind)() ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)()) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate0(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)() const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate0(DesiredRetType (*function_to_bind)() ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)() ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)()) + { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() () const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction() const + { + return (*(m_Closure.GetStaticFunction()))(); + } +}; + +//N=1 +template +class FastDelegate1 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; + + // Construction and comparison functions + FastDelegate1() { Clear(); } + FastDelegate1(const FastDelegate1 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate1 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate1 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate1 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate1 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate1 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType (*function_to_bind)(Param1 p1) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1)) + { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const + { + return (*(m_Closure.GetStaticFunction()))(p1); + } +}; + +//N=2 +template +class FastDelegate2 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate2 type; + + // Construction and comparison functions + FastDelegate2() { Clear(); } + FastDelegate2(const FastDelegate2 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate2 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate2 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate2 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate2 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate2 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2)) + { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2); + } +}; + +//N=3 +template +class FastDelegate3 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; + + // Construction and comparison functions + FastDelegate3() { Clear(); } + FastDelegate3(const FastDelegate3 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate3 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate3 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate3 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate3 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate3 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) + { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); + } +}; + +//N=4 +template +class FastDelegate4 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; + + // Construction and comparison functions + FastDelegate4() { Clear(); } + FastDelegate4(const FastDelegate4 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate4 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate4 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate4 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate4 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate4 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) + { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); + } +}; + +//N=5 +template +class FastDelegate5 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; + + // Construction and comparison functions + FastDelegate5() { Clear(); } + FastDelegate5(const FastDelegate5 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate5 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate5 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate5 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate5 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate5 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) + { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); + } +}; + +//N=6 +template +class FastDelegate6 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { Clear(); } + FastDelegate6(const FastDelegate6 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate6 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate6 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate6 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate6 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate6 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) + { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); + } +}; + +//N=7 +template +class FastDelegate7 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { Clear(); } + FastDelegate7(const FastDelegate7 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate7 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate7 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate7 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate7 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate7 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) + { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); + } +}; + +//N=8 +template +class FastDelegate8 +{ +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { Clear(); } + FastDelegate8(const FastDelegate8 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate8 &x) + { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate8 &x) const + { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate8 &x) const + { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate8 &x) const + { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate8 &x) const + { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) + { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void Bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) + { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) + { + Bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) ) + { + Bind(function_to_bind); + } + inline void Bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) + { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); + } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct + { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const + { + return IsEmpty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) + { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) + { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const + { // Is it bound to anything? + return !m_Closure; + } + inline bool IsEmpty() const + { + return !m_Closure; + } + void Clear() { m_Closure.Clear();} + // Conversion to and from the CUtlAbstractDelegate storage class + const CUtlAbstractDelegate & GetAbstractDelegate() { return m_Closure; } + void SetAbstractDelegate(const CUtlAbstractDelegate &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const + { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); + } +}; + + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 4: +// +// CUtlDelegate<> class (Original author: Jody Hagins) +// Allows boost::function style syntax like: +// CUtlDelegate< double (int, long) > +// instead of: +// FastDelegate2< int, long, double > +// +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +// Declare CUtlDelegate as a class template. It will be specialized +// later for all number of arguments. +template +class CUtlDelegate; + +//N=0 +// Specialization to allow use of +// CUtlDelegate< R ( ) > +// instead of +// FastDelegate0 < R > +template +class CUtlDelegate< R ( ) > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=1 +// Specialization to allow use of +// CUtlDelegate< R ( Param1 ) > +// instead of +// FastDelegate1 < Param1, R > +template +class CUtlDelegate< R ( Param1 ) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > +{ + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=2 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2 ) > +// instead of +// FastDelegate2 < Param1, Param2, R > +template +class CUtlDelegate< R ( Param1, Param2 ) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > +{ + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=3 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3 ) > +// instead of +// FastDelegate3 < Param1, Param2, Param3, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3 ) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=4 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) > +// instead of +// FastDelegate4 < Param1, Param2, Param3, Param4, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3, Param4 ) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=5 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > +// instead of +// FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=6 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > +// instead of +// FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=7 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > +// instead of +// FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + +//N=8 +// Specialization to allow use of +// CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > +// instead of +// FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +template +class CUtlDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef CUtlDelegate SelfType; + + // Mimic the base class constructors. + CUtlDelegate() : BaseType() { } + + template < class X, class Y > + CUtlDelegate(Y * pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(pthis, function_to_bind) + { } + + template < class X, class Y > + CUtlDelegate(const Y *pthis, R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const) + : BaseType(pthis, function_to_bind) + { } + + CUtlDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 )) + : BaseType(function_to_bind) + { } + + void operator = (const BaseType &x) + { + *static_cast(this) = x; + } +}; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Fast Delegates, part 5: +// +// UtlMakeDelegate() helper function +// +// UtlMakeDelegate(&x, &X::func) returns a fastdelegate of the type +// necessary for calling x.func() with the correct number of arguments. +// This makes it possible to eliminate many typedefs from user code. +// +//////////////////////////////////////////////////////////////////////////////// + +// Also declare overloads of a UtlMakeDelegate() global function to +// reduce the need for typedefs. +// We need seperate overloads for const and non-const member functions. +// Also, because of the weird rule about the class of derived member function pointers, +// implicit downcasts may need to be applied later to the 'this' pointer. +// That's why two classes (X and Y) appear in the definitions. Y must be implicitly +// castable to X. + +// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. +// GCC 3.2 and later won't compile this unless it's preceded by 'typename', +// but VC6 doesn't allow 'typename' in this context. +// So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + + +//N=0 +template +CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)()) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate(Y* x, RetType (X::*func)() const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( ) >(x, func); +} + +template < class RetType > +CUtlDelegate< FASTDLGT_RETTYPE ( ) > UtlMakeDelegate( RetType (*func)()) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( ) >( func ); +} + +//N=1 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >(x, func); +} + +template < class Param1, class RetType > +CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) > UtlMakeDelegate( RetType (*func)(Param1 p1)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1 ) >( func ); +} + + +//N=2 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2 ) >(func); +} + +//N=3 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) > UtlMakeDelegate( RetType (*func)(Param1 p1, Param2 p2, Param3 p3)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3 ) >(func); +} + +//N=4 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4 ) >(func); +} + +//N=5 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5 ) >(func); +} + +//N=6 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6 ) >(func); +} + +//N=7 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) >(func); +} + +//N=8 +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(x, func); +} + +template +CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > UtlMakeDelegate(RetType (*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) +{ + return CUtlDelegate< FASTDLGT_RETTYPE ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) >(func); +} + + +// clean up after ourselves... +#undef FASTDLGT_RETTYPE + +#endif // !defined(UTLDELEGATEIMPL_H) + diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h index 386f469f..79a6e8ac 100644 --- a/public/tier1/utlstring.h +++ b/public/tier1/utlstring.h @@ -1,4 +1,4 @@ -//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // @@ -15,96 +15,30 @@ #include "tier1/strtools.h" #include "limits.h" - -//----------------------------------------------------------------------------- -// Base class, containing simple memory management -//----------------------------------------------------------------------------- -class CUtlBinaryBlock +#if defined( OSX ) +inline wchar_t *wcsdup(const wchar_t *pString) { -public: - CUtlBinaryBlock( int growSize = 0, int initSize = 0 ); + wchar_t *pMemory; - // NOTE: nInitialLength indicates how much of the buffer starts full - CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ); - CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ); - CUtlBinaryBlock( const CUtlBinaryBlock& src ); + if (!pString) + return NULL; - void Get( void *pValue, int nMaxLen ) const; - void Set( const void *pValue, int nLen ); - const void *Get( ) const; - void *Get( ); + size_t len = (wcslen(pString) + 1); + if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL) + { + return wcscpy( pMemory, pString ); + } - unsigned char& operator[]( int i ); - const unsigned char& operator[]( int i ) const; - - int Length() const; - void SetLength( int nLength ); // Undefined memory will result - bool IsEmpty() const; - void Clear(); - void Purge(); - - bool IsReadOnly() const; - - CUtlBinaryBlock &operator=( const CUtlBinaryBlock &src ); - - // Test for equality - bool operator==( const CUtlBinaryBlock &src ) const; - -private: - CUtlMemory m_Memory; - int m_nActualLength; -}; - - -//----------------------------------------------------------------------------- -// class inlines -//----------------------------------------------------------------------------- -inline const void *CUtlBinaryBlock::Get( ) const -{ - return m_Memory.Base(); + return NULL; } -inline void *CUtlBinaryBlock::Get( ) +inline size_t strnlen(const char *s, size_t n) { - return m_Memory.Base(); -} - -inline int CUtlBinaryBlock::Length() const -{ - return m_nActualLength; -} - -inline unsigned char& CUtlBinaryBlock::operator[]( int i ) -{ - return m_Memory[i]; -} - -inline const unsigned char& CUtlBinaryBlock::operator[]( int i ) const -{ - return m_Memory[i]; -} - -inline bool CUtlBinaryBlock::IsReadOnly() const -{ - return m_Memory.IsReadOnly(); -} - -inline bool CUtlBinaryBlock::IsEmpty() const -{ - return Length() == 0; -} - -inline void CUtlBinaryBlock::Clear() -{ - SetLength( 0 ); -} - -inline void CUtlBinaryBlock::Purge() -{ - SetLength( 0 ); - m_Memory.Purge(); + const char *p = (const char *)memchr(s, 0, n); + return (p ? p - s : n); } +#endif //----------------------------------------------------------------------------- // Simple string class. @@ -112,49 +46,100 @@ inline void CUtlBinaryBlock::Purge() //----------------------------------------------------------------------------- class CUtlString { +public: + typedef enum + { + PATTERN_NONE = 0x00000000, + PATTERN_DIRECTORY = 0x00000001 + } TUtlStringPattern; + public: CUtlString(); CUtlString( const char *pString ); + CUtlString( const char *pString, int length ); CUtlString( const CUtlString& string ); - // Attaches the string to external memory. Useful for avoiding a copy - CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ); - CUtlString( const void* pMemory, int nSizeInBytes ); +#ifdef MOVE_CONSTRUCTOR_SUPPORT + // Support moving of CUtlString objects. Long live C++11 + // This move constructor will get called when appropriate, such as when + // returning objects from functions, or otherwise copying from temporaries + // which are about to be destroyed. It can also be explicitly invoked with + // std::move(). + // Move constructor: + CUtlString( CUtlString&& rhs ) + { + // Move the string pointer from the source to this -- be sure to + // zero out the source to avoid double frees. + m_pString = rhs.m_pString; + rhs.m_pString = 0; + } + // Move assignment operator: + CUtlString& operator=( CUtlString&& rhs ) + { + // Move the string pointer from the source to this -- be sure to + // zero out the source to avoid double frees. + m_pString = rhs.m_pString; + rhs.m_pString = 0; + return *this; + } +#endif + + ~CUtlString(); const char *Get( ) const; void Set( const char *pValue ); - - // Set directly and don't look for a null terminator in pValue. - void SetDirect( const char *pValue, int nChars ); - - // Converts to c-strings operator const char*() const; + // Set directly and don't look for a null terminator in pValue. + // nChars does not include the nul and this will only copy + // at most nChars (even if pValue is longer). If nChars + // is >strlen(pValue) it will copy past the end, don't do it + // Does nothing if pValue == String() + void SetDirect( const char *pValue, int nChars ); + // for compatibility switching items from UtlSymbol const char *String() const { return Get(); } // Returns strlen int Length() const; + // IsEmpty() is more efficient than Length() == 0 bool IsEmpty() const; // Sets the length (used to serialize into the buffer ) // Note: If nLen != 0, then this adds an extra byte for a null-terminator. void SetLength( int nLen ); - char *Get(); + char *GetForModify(); void Clear(); void Purge(); + // Case Change + void ToLower(); + void ToUpper(); + void Append( const char *pAddition, int nChars ); + + void Append( const char *pchAddition ); + void Append( const char chAddition ) { char temp[2] = { chAddition, 0 }; Append( temp ); } // Strips the trailing slash void StripTrailingSlash(); + void FixSlashes( char cSeparator = CORRECT_PATH_SEPARATOR ); + + // Trim whitespace + void TrimLeft( char cTarget ); + void TrimLeft( const char *szTargets = "\t\r\n " ); + void TrimRight( char cTarget ); + void TrimRight( const char *szTargets = "\t\r\n " ); + void Trim( char cTarget ); + void Trim( const char *szTargets = "\t\r\n " ); + + bool IsEqual_CaseSensitive( const char *src ) const; + bool IsEqual_CaseInsensitive( const char *src ) const; CUtlString &operator=( const CUtlString &src ); CUtlString &operator=( const char *src ); // Test for equality bool operator==( const CUtlString &src ) const; - bool operator==( const char *src ) const; bool operator!=( const CUtlString &src ) const { return !operator==( src ); } - bool operator!=( const char *src ) const { return !operator==( src ); } CUtlString &operator+=( const CUtlString &rhs ); CUtlString &operator+=( const char *rhs ); @@ -162,32 +147,57 @@ public: CUtlString &operator+=( int rhs ); CUtlString &operator+=( double rhs ); - CUtlString operator+( const char *pOther ); - CUtlString operator+( int rhs ); + CUtlString operator+( const char *pOther ) const; + CUtlString operator+( const CUtlString &other ) const; + CUtlString operator+( int rhs ) const; - int Format( const char *pFormat, ... ); + bool MatchesPattern( const CUtlString &Pattern, int nFlags = 0 ) const; // case SENSITIVE, use * for wildcard in pattern string - // Take a piece out of the string. + char operator[]( int i ) const; + + int Format( const char *pFormat, ... ) FMTFUNCTION( 2, 3 ); + int FormatV( const char *pFormat, va_list marker ); + + // Defining AltArgumentType_t hints that associative container classes should + // also implement Find/Insert/Remove functions that take const char* params. + typedef const char *AltArgumentType_t; + + // Get a copy of part of the string. // If you only specify nStart, it'll go from nStart to the end. // You can use negative numbers and it'll wrap around to the start. - CUtlString Slice( int32 nStart=0, int32 nEnd=INT_MAX ); + CUtlString Slice( int32 nStart=0, int32 nEnd=INT_MAX ) const; - // Grab a substring starting from the left or the right side. - CUtlString Left( int32 nChars ); - CUtlString Right( int32 nChars ); + // Get a substring starting from the left or the right side. + CUtlString Left( int32 nChars ) const; + CUtlString Right( int32 nChars ) const; - // Replace all instances of one character with another. - CUtlString Replace( char cFrom, char cTo ); + // Get a string with all instances of one character replaced with another. + CUtlString Replace( char cFrom, char cTo ) const; - // Calls right through to V_MakeAbsolutePath. - CUtlString AbsPath( const char *pStartingDir=NULL ); + // Replace all instances of specified string with another. + CUtlString Replace( const char *pszFrom, const char *pszTo ) const; + + // Get this string as an absolute path (calls right through to V_MakeAbsolutePath). + CUtlString AbsPath( const char *pStartingDir=NULL ) const; // Gets the filename (everything except the path.. c:\a\b\c\somefile.txt -> somefile.txt). - CUtlString UnqualifiedFilename(); - - // Strips off one directory. Uses V_StripLastDir but strips the last slash also! - CUtlString DirName(); + CUtlString UnqualifiedFilename() const; + // Gets a string with one directory removed. Uses V_StripLastDir but strips the last slash also! + CUtlString DirName() const; + + // Get a string with the extension removed (with V_StripExtension). + CUtlString StripExtension() const; + + // Get a string with the filename removed (uses V_UnqualifiedFileName and also strips the last slash) + CUtlString StripFilename() const; + + // Get a string with the base filename (with V_FileBase). + CUtlString GetBaseFilename() const; + + // Get a string with the file extension (with V_FileBase). + CUtlString GetExtension() const; + // Works like V_ComposeFileName. static CUtlString PathJoin( const char *pStr1, const char *pStr2 ); @@ -195,17 +205,93 @@ public: static int __cdecl SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 ); static int __cdecl SortCaseSensitive( const CUtlString *pString1, const CUtlString *pString2 ); + // Empty string for those times when you need to return an empty string and + // either don't want to pay the construction cost, or are returning a + // const CUtlString& and cannot just return "". + static const CUtlString &GetEmptyString(); + private: - CUtlBinaryBlock m_Storage; + // INTERNALS + // AllocMemory allocates enough space for length characters plus a terminating zero. + // Previous characters are preserved, the buffer is null-terminated, but new characters + // are not touched. + void *AllocMemory( uint32 length ); + + // If m_pString is not NULL, it points to the start of the string, and the memory allocation. + char *m_pString; }; +// // If these are not defined, CUtlConstString as rhs will auto-convert +// // to const char* and do logical operations on the raw pointers. Ugh. +// inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; } +// inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; } +// inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; } + +inline bool operator==( const char *pString, const CUtlString &utlString ) +{ + return utlString.IsEqual_CaseSensitive( pString ); +} + +inline bool operator!=( const char *pString, const CUtlString &utlString ) +{ + return !utlString.IsEqual_CaseSensitive( pString ); +} + +inline bool operator==( const CUtlString &utlString, const char *pString ) +{ + return utlString.IsEqual_CaseSensitive( pString ); +} + +inline bool operator!=( const CUtlString &utlString, const char *pString ) +{ + return !utlString.IsEqual_CaseSensitive( pString ); +} + + //----------------------------------------------------------------------------- // Inline methods //----------------------------------------------------------------------------- +inline CUtlString::CUtlString() +: m_pString( NULL ) +{ +} + +inline CUtlString::CUtlString( const char *pString ) +: m_pString( NULL ) +{ + Set( pString ); +} + +inline CUtlString::CUtlString( const char *pString, int length ) +: m_pString( NULL ) +{ + SetDirect( pString, length ); +} + +inline CUtlString::CUtlString( const CUtlString& string ) +: m_pString( NULL ) +{ + Set( string.Get() ); +} + +inline CUtlString::~CUtlString() +{ + Purge(); +} + +inline int CUtlString::Length() const +{ + if (m_pString) + { + return V_strlen( m_pString ); + } + return 0; +} + inline bool CUtlString::IsEmpty() const { - return Length() == 0; + return !m_pString || m_pString[0] == 0; } inline int __cdecl CUtlString::SortCaseInsensitive( const CUtlString *pString1, const CUtlString *pString2 ) @@ -218,5 +304,151 @@ inline int __cdecl CUtlString::SortCaseSensitive( const CUtlString *pString1, co return V_strcmp( pString1->String(), pString2->String() ); } +// Converts to c-strings +inline CUtlString::operator const char*() const +{ + return Get(); +} + + + +//----------------------------------------------------------------------------- +// Purpose: Implementation of low-level string functionality for character types. +//----------------------------------------------------------------------------- + +template < typename T > +class StringFuncs +{ +public: + static T *Duplicate( const T *pValue ); + // Note that this function takes a character count, and does not guarantee null-termination. + static void Copy( T *out_pOut, const T *pIn, int iLengthInChars ); + static int Compare( const T *pLhs, const T *pRhs ); + static int CaselessCompare( const T *pLhs, const T *pRhs ); + static int Length( const T *pValue ); + static const T *FindChar( const T *pStr, const T cSearch ); + static const T *EmptyString(); + static const T *NullDebugString(); +}; + +template < > +class StringFuncs +{ +public: + static char *Duplicate( const char *pValue ) { return strdup( pValue ); } + // Note that this function takes a character count, and does not guarantee null-termination. + static void Copy( char *out_pOut, const char *pIn, int iLengthInChars ) { strncpy( out_pOut, pIn, iLengthInChars ); } + static int Compare( const char *pLhs, const char *pRhs ) { return strcmp( pLhs, pRhs ); } + static int CaselessCompare( const char *pLhs, const char *pRhs ) { return Q_strcasecmp( pLhs, pRhs ); } + static int Length( const char *pValue ) { return (int)strlen( pValue ); } + static const char *FindChar( const char *pStr, const char cSearch ) { return strchr( pStr, cSearch ); } + static const char *EmptyString() { return ""; } + static const char *NullDebugString() { return "(null)"; } +}; + +template < > +class StringFuncs +{ +public: + static wchar_t *Duplicate( const wchar_t *pValue ) { return wcsdup( pValue ); } + // Note that this function takes a character count, and does not guarantee null-termination. + static void Copy( wchar_t *out_pOut, const wchar_t *pIn, int iLengthInChars ) { wcsncpy( out_pOut, pIn, iLengthInChars ); } + static int Compare( const wchar_t *pLhs, const wchar_t *pRhs ) { return wcscmp( pLhs, pRhs ); } + static int CaselessCompare( const wchar_t *pLhs, const wchar_t *pRhs ); // no implementation? + static int Length( const wchar_t *pValue ) { return (int)wcslen( pValue ); } + static const wchar_t *FindChar( const wchar_t *pStr, const wchar_t cSearch ) { return wcschr( pStr, cSearch ); } + static const wchar_t *EmptyString() { return L""; } + static const wchar_t *NullDebugString() { return L"(null)"; } +}; + +//----------------------------------------------------------------------------- +// Dirt-basic auto-release string class. Not intended for manipulation, +// can be stored in a container or forwarded as a functor parameter. +// Note the benefit over CUtlString: sizeof(CUtlConstString) == sizeof(char*). +// Also note: null char* pointers are treated identically to empty strings. +//----------------------------------------------------------------------------- + +template < typename T = char > +class CUtlConstStringBase +{ +public: + CUtlConstStringBase() : m_pString( NULL ) {} + explicit CUtlConstStringBase( const T *pString ) : m_pString( NULL ) { Set( pString ); } + CUtlConstStringBase( const CUtlConstStringBase& src ) : m_pString( NULL ) { Set( src.m_pString ); } + ~CUtlConstStringBase() { Set( NULL ); } + + void Set( const T *pValue ); + void Clear() { Set( NULL ); } + + const T *Get() const { return m_pString ? m_pString : StringFuncs::EmptyString(); } + operator const T*() const { return m_pString ? m_pString : StringFuncs::EmptyString(); } + + bool IsEmpty() const { return m_pString == NULL; } // Note: empty strings are never stored by Set + + int Compare( const T *rhs ) const; + + // Logical ops + bool operator<( const T *rhs ) const { return Compare( rhs ) < 0; } + bool operator==( const T *rhs ) const { return Compare( rhs ) == 0; } + bool operator!=( const T *rhs ) const { return Compare( rhs ) != 0; } + bool operator<( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) < 0; } + bool operator==( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) == 0; } + bool operator!=( const CUtlConstStringBase &rhs ) const { return Compare( rhs.m_pString ) != 0; } + + // If these are not defined, CUtlConstString as rhs will auto-convert + // to const char* and do logical operations on the raw pointers. Ugh. + inline friend bool operator<( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) > 0; } + inline friend bool operator==( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) == 0; } + inline friend bool operator!=( const T *lhs, const CUtlConstStringBase &rhs ) { return rhs.Compare( lhs ) != 0; } + + CUtlConstStringBase &operator=( const T *src ) { Set( src ); return *this; } + CUtlConstStringBase &operator=( const CUtlConstStringBase &src ) { Set( src.m_pString ); return *this; } + + // Defining AltArgumentType_t is a hint to containers that they should + // implement Find/Insert/Remove functions that take const char* params. + typedef const T *AltArgumentType_t; + +protected: + const T *m_pString; +}; + +template < typename T > +void CUtlConstStringBase::Set( const T *pValue ) +{ + if ( pValue != m_pString ) + { + free( ( void* ) m_pString ); + m_pString = pValue && pValue[0] ? StringFuncs::Duplicate( pValue ) : NULL; + } +} + +template < typename T > +int CUtlConstStringBase::Compare( const T *rhs ) const +{ + // Empty or null RHS? + if ( !rhs || !rhs[0] ) + return m_pString ? 1 : 0; + + // Empty *this, non-empty RHS? + if ( !m_pString ) + return -1; + + // Neither empty + return StringFuncs::Compare( m_pString, rhs ); +} + +typedef CUtlConstStringBase CUtlConstString; +typedef CUtlConstStringBase CUtlConstWideString; + +//----------------------------------------------------------------------------- +// Helper functor objects. +//----------------------------------------------------------------------------- + +template < typename T > struct UTLConstStringCaselessStringLessFunctor { bool operator()( const CUtlConstStringBase& a, const char *b ) const { return StringFuncs::CaselessCompare( a.Get(), b ) < 0; } }; +template < typename T > struct UTLConstStringCaselessStringEqualFunctor { bool operator()( const CUtlConstStringBase& a, const char *b ) const { return StringFuncs::CaselessCompare( a.Get(), b ) == 0; } }; + +// Helper function for CUtlMaps with a CUtlString key +inline bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs ) { return V_strcmp( lhs.Get(), rhs.Get() ) < 0; } +inline bool UtlStringCaseInsensitiveLessFunc( const CUtlString &lhs, const CUtlString &rhs ) { return V_stricmp( lhs.Get(), rhs.Get() ) < 0; } #endif // UTLSTRING_H diff --git a/public/tier1/utlvector.h b/public/tier1/utlvector.h index f397038a..e89986b6 100644 --- a/public/tier1/utlvector.h +++ b/public/tier1/utlvector.h @@ -160,21 +160,9 @@ protected: void ShiftElementsRight( int elem, int num = 1 ); void ShiftElementsLeft( int elem, int num = 1 ); - CAllocator m_Memory; int m_Size; + CAllocator m_Memory; -#ifndef _X360 - // For easier access to the elements through the debugger - // it's in release builds so this can be used in libraries correctly - T *m_pElements; - - inline void ResetDbgInfo() - { - m_pElements = Base(); - } -#else - inline void ResetDbgInfo() {} -#endif }; @@ -531,14 +519,12 @@ template< typename T, class A > inline CUtlVector::CUtlVector( int growSize, int initSize ) : m_Memory(growSize, initSize), m_Size(0) { - ResetDbgInfo(); } template< typename T, class A > inline CUtlVector::CUtlVector( T* pMemory, int allocationCount, int numElements ) : m_Memory(pMemory, allocationCount), m_Size(numElements) { - ResetDbgInfo(); } template< typename T, class A > @@ -663,7 +649,6 @@ void CUtlVector::GrowVector( int num ) } m_Size += num; - ResetDbgInfo(); } @@ -710,7 +695,6 @@ void CUtlVector::EnsureCapacity( int num ) { MEM_ALLOC_CREDIT_CLASS(); m_Memory.EnsureCapacity(num); - ResetDbgInfo(); } @@ -1116,7 +1100,6 @@ inline void CUtlVector::Purge() { RemoveAll(); m_Memory.Purge(); - ResetDbgInfo(); } diff --git a/public/vscript/ivscript.h b/public/vscript/ivscript.h index 53823237..4c1a1645 100644 --- a/public/vscript/ivscript.h +++ b/public/vscript/ivscript.h @@ -123,12 +123,6 @@ struct CCommandContext; // //----------------------------------------------------------------------------- -#define VSCRIPT_INTERFACE_VERSION "VScriptManager010" - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - class IScriptVM; enum ScriptLanguage_t diff --git a/public/vstdlib/ieventsystem.h b/public/vstdlib/ieventsystem.h new file mode 100644 index 00000000..324964ec --- /dev/null +++ b/public/vstdlib/ieventsystem.h @@ -0,0 +1,16 @@ +#include +#include + +class IEventQueue; + +abstract_class IEventSystem : public IAppSystem +{ +public: + virtual IEventQueue *CreateEventQueue() = 0; + virtual void DestroyEventQueue( IEventQueue *pQueue ) = 0; + virtual void RunEvents( IEventQueue *pQueue ) = 0; + virtual int RegisterEvent( const char *pszName ) = 0; + virtual void FireEvent( int eventId, IEventQueue *pQueue, const void *pListener, CFunctorData *pData ) = 0; + virtual void RegisterListener( int eventId, IEventQueue *pQueue, CFunctorCallback *pCallback ) = 0; + virtual void UnregisterListener( int eventId, IEventQueue *pQueue, CFunctorCallback *pCallback ) = 0; +}; \ No newline at end of file diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 12cd39ad..6439483f 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -1,3 +1,4 @@ + //===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: @@ -103,7 +104,10 @@ ConCommandBase::ConCommandBase( void ) m_pszHelpString = NULL; m_nFlags = 0; + m_nFlags2 = 0; m_pNext = NULL; + + m_Unknown = 0; } //----------------------------------------------------------------------------- @@ -501,43 +505,26 @@ int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const //----------------------------------------------------------------------------- // Default console command autocompletion function //----------------------------------------------------------------------------- -int DefaultCompletionFunc( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) +int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &commands ) { return 0; } -//----------------------------------------------------------------------------- -// Purpose: Constructs a console command -//----------------------------------------------------------------------------- -//ConCommand::ConCommand() -//{ -// m_bIsNewConCommand = true; -//} - -ConCommand::ConCommand( const char *pName, FnCommandCallbackV1_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) -{ - // Set the callback - m_fnCommandCallbackV1 = callback; - m_bUsingOldCommandCallback = true; - m_bUsingCommandCallbackInterface = false; - m_bUsingCommandCallbackInterface2 = false; - m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - m_bHasCompletionCallback = completionFunc != 0 ? true : false; - - // Setup the rest - BaseClass::Create( pName, pHelpString, flags ); -} - ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { // Set the callback - m_fnCommandCallback = callback; - m_bUsingOldCommandCallback = false; + ConCommandCB cb; + cb.m_fnCommandCallback = callback; + cb.m_bUsingOldCommandCallback = false; + cb.m_bUsingCommandCallbackInterface = false; + m_Callbacks.AddToTail(cb); + m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; m_bHasCompletionCallback = completionFunc != 0 ? true : false; - m_bUsingCommandCallbackInterface = false; - m_bUsingCommandCallbackInterface2 = false; + m_bUsingCommandCompletionInterface = false; + + m_pParent = this; // Setup the rest BaseClass::Create( pName, pHelpString, flags ); @@ -546,26 +533,17 @@ ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const c ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) { // Set the callback - m_pCommandCallback = pCallback; - m_bUsingOldCommandCallback = false; + ConCommandCB cb; + cb.m_pCommandCallback = pCallback; + cb.m_bUsingOldCommandCallback = false; + cb.m_bUsingCommandCallbackInterface = true; + m_Callbacks.AddToTail(cb); + m_pCommandCompletionCallback = pCompletionCallback; m_bHasCompletionCallback = ( pCompletionCallback != 0 ); - m_bUsingCommandCallbackInterface = true; - m_bUsingCommandCallbackInterface2 = false; + m_bUsingCommandCompletionInterface = true; - // Setup the rest - BaseClass::Create( pName, pHelpString, flags ); -} - -ConCommand::ConCommand( const char *pName, ICommandCallback2 *pCallback, const char *pHelpString /*= 0*/, int flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) -{ - // Set the callback - m_pCommandCallback2 = pCallback; - m_bUsingOldCommandCallback = false; - m_pCommandCompletionCallback = pCompletionCallback; - m_bHasCompletionCallback = ( pCompletionCallback != 0 ); - m_bUsingCommandCallbackInterface = false; - m_bUsingCommandCallbackInterface2 = true; + m_pParent = this; // Setup the rest BaseClass::Create( pName, pHelpString, flags ); @@ -593,41 +571,44 @@ bool ConCommand::IsCommand( void ) const //----------------------------------------------------------------------------- void ConCommand::Dispatch( const CCommandContext &context, const CCommand &command ) { - if ( m_bUsingOldCommandCallback ) + FOR_EACH_VEC(m_Callbacks, i) { - if ( m_fnCommandCallbackV1 ) + ConCommandCB cb = m_Callbacks[i]; + if (cb.m_bUsingOldCommandCallback) { - ( *m_fnCommandCallbackV1 )(); - return; + if (m_fnCommandCallbackV1) + { + (*m_fnCommandCallbackV1)(context); + return; + } } - } - else if ( m_bUsingCommandCallbackInterface ) - { - if ( m_pCommandCallback ) + else if (cb.m_bUsingCommandCallbackInterface) { - m_pCommandCallback->CommandCallback( command ); - return; + if (cb.m_pCommandCallback) + { + cb.m_pCommandCallback->CommandCallback(context, command); + return; + } } - } - else if (m_bUsingCommandCallbackInterface2 ) - { - if ( m_pCommandCallback2 ) + else if (cb.m_bUsingV2CommandCallback) { - m_pCommandCallback2->CommandCallback( context, command ); - return; + if (cb.m_bUsingV2CommandCallback) + { + cb.m_fnCommandCallbackV2(context, command); + } } - } - else - { - if ( m_fnCommandCallback ) + else { - ( *m_fnCommandCallback )( context, command ); - return; - } - } + if (cb.m_fnCommandCallback) + { + (*cb.m_fnCommandCallback)(command); + return; + } + } - // Command without callback!!! - AssertMsg( 0, ( "Encountered ConCommand without a callback!\n" ) ); + // Command without callback!!! + AssertMsg(0, ("Encountered ConCommand without a callback!\n")); + } } @@ -636,7 +617,7 @@ void ConCommand::Dispatch( const CCommandContext &context, const CCommand &comma //----------------------------------------------------------------------------- int ConCommand::AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ) { - if ( m_bUsingCommandCallbackInterface ) + if (m_bUsingCommandCompletionInterface) { if ( !m_pCommandCompletionCallback ) return 0; @@ -647,14 +628,7 @@ int ConCommand::AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString if ( !m_fnCompletionCallback ) return 0; - char rgpchCommands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ]; - int iret = ( m_fnCompletionCallback )( partial, rgpchCommands ); - for ( int i = 0 ; i < iret; ++i ) - { - CUtlString str = rgpchCommands[ i ]; - commands.AddToTail( str ); - } - return iret; + return m_fnCompletionCallback( partial, commands ); } diff --git a/tier1/stringpool.cpp b/tier1/stringpool.cpp index 7aecdb83..699f5cb2 100644 --- a/tier1/stringpool.cpp +++ b/tier1/stringpool.cpp @@ -321,7 +321,7 @@ void CCountedStringPool::SpewStrings() Msg("\n%d total counted strings.", m_Elements.Count()); } -#ifdef _DEBUG +#ifdef _DEBUG1111 CON_COMMAND( test_stringpool, "Tests the class CStringPool" ) { CStringPool pool; diff --git a/tier1/strtools.cpp b/tier1/strtools.cpp index 87cf7138..cdb7ac07 100644 --- a/tier1/strtools.cpp +++ b/tier1/strtools.cpp @@ -1541,8 +1541,8 @@ void V_AppendSlash( char *pStr, int strSize ) int len = V_strlen( pStr ); if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) ) { - if ( len+1 >= strSize ) - Error( "V_AppendSlash: ran out of space on %s.", pStr ); + //if ( len+1 >= strSize ) + //Error( "V_AppendSlash: ran out of space on %s.", pStr ); pStr[len] = CORRECT_PATH_SEPARATOR; pStr[len+1] = 0; @@ -1566,8 +1566,8 @@ void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char * } else { - if ( !_getcwd( pOut, outLen ) ) - Error( "V_MakeAbsolutePath: _getcwd failed." ); + //if ( !_getcwd( pOut, outLen ) ) + //Error( "V_MakeAbsolutePath: _getcwd failed." ); if ( pStartingDir ) { @@ -1581,8 +1581,8 @@ void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char * V_strncat( pOut, pPath, outLen, COPY_ALL_CHARACTERS ); } - if ( !V_RemoveDotSlashes( pOut ) ) - Error( "V_MakeAbsolutePath: tried to \"..\" past the root." ); + //if ( !V_RemoveDotSlashes( pOut ) ) + //Error( "V_MakeAbsolutePath: tried to \"..\" past the root." ); V_FixSlashes( pOut ); } diff --git a/tier1/tier1.vcxproj b/tier1/tier1.vcxproj index b992757b..5730765f 100644 --- a/tier1/tier1.vcxproj +++ b/tier1/tier1.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -18,9 +18,11 @@ StaticLibrary + v120 StaticLibrary + v120 @@ -143,6 +145,7 @@ Level3 + /Zo %(AdditionalOptions) diff --git a/tier1/utlbufferutil.cpp b/tier1/utlbufferutil.cpp index a608ad91..c1391dc4 100644 --- a/tier1/utlbufferutil.cpp +++ b/tier1/utlbufferutil.cpp @@ -22,6 +22,7 @@ #include #include #include +#include "tier1/utlbinaryblock.h" #include "tier1/utlstring.h" #include "tier1/strtools.h" #include "tier1/characterset.h" @@ -552,7 +553,7 @@ bool Unserialize( CUtlBuffer &buf, CUtlString &dest ) { int nLen = buf.PeekDelimitedStringLength( s_pConv ); dest.SetLength( nLen - 1 ); // -1 because the length returned includes space for \0 - buf.GetDelimitedString( s_pConv, dest.Get(), nLen ); + buf.GetDelimitedString( s_pConv, dest.GetForModify(), nLen ); return buf.IsValid(); } diff --git a/tier1/utlstring.cpp b/tier1/utlstring.cpp index a34e6638..300766b9 100644 --- a/tier1/utlstring.cpp +++ b/tier1/utlstring.cpp @@ -1,274 +1,269 @@ -//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. ======= +//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= +#define __STDC_LIMIT_MACROS +#include + #include "tier1/utlstring.h" #include "tier1/strtools.h" +#include - -//----------------------------------------------------------------------------- -// Base class, containing simple memory management -//----------------------------------------------------------------------------- -CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize ) : m_Memory( growSize, initSize ) -{ - m_nActualLength = 0; -} - -CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes ) -{ - m_nActualLength = nInitialLength; -} - -CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes ) -{ - m_nActualLength = nSizeInBytes; -} - -CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src ) -{ - Set( src.Get(), src.Length() ); -} - -void CUtlBinaryBlock::Get( void *pValue, int nLen ) const -{ - Assert( nLen > 0 ); - if ( m_nActualLength < nLen ) - { - nLen = m_nActualLength; - } - - if ( nLen > 0 ) - { - memcpy( pValue, m_Memory.Base(), nLen ); - } -} - -void CUtlBinaryBlock::SetLength( int nLength ) -{ - Assert( !m_Memory.IsReadOnly() ); - - m_nActualLength = nLength; - if ( nLength > m_Memory.NumAllocated() ) - { - int nOverFlow = nLength - m_Memory.NumAllocated(); - m_Memory.Grow( nOverFlow ); - - // If the reallocation failed, clamp length - if ( nLength > m_Memory.NumAllocated() ) - { - m_nActualLength = m_Memory.NumAllocated(); - } - } - -#ifdef _DEBUG - if ( m_Memory.NumAllocated() > m_nActualLength ) - { - memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength ); - } -#endif -} - -void CUtlBinaryBlock::Set( const void *pValue, int nLen ) -{ - Assert( !m_Memory.IsReadOnly() ); - - if ( !pValue ) - { - nLen = 0; - } - - SetLength( nLen ); - - if ( m_nActualLength ) - { - if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen || - ( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) ) - { - memcpy( m_Memory.Base(), pValue, m_nActualLength ); - } - else - { - memmove( m_Memory.Base(), pValue, m_nActualLength ); - } - } -} - - -CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src ) -{ - Assert( !m_Memory.IsReadOnly() ); - Set( src.Get(), src.Length() ); - return *this; -} - - -bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const -{ - if ( src.Length() != Length() ) - return false; - - return !memcmp( src.Get(), Get(), Length() ); -} - +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Simple string class. //----------------------------------------------------------------------------- -CUtlString::CUtlString() + +//----------------------------------------------------------------------------- +// Either allocates or reallocates memory to the length +// +// Allocated space for length characters. It automatically adds space for the +// nul and the cached length at the start of the memory block. Will adjust +// m_pString and explicitly set the nul at the end before returning. +void *CUtlString::AllocMemory( uint32 length ) { + void *pMemoryBlock; + if ( m_pString ) + { + pMemoryBlock = realloc( m_pString, length + 1 ); + } + else + { + pMemoryBlock = malloc( length + 1 ); + } + m_pString = (char*)pMemoryBlock; + m_pString[ length ] = 0; + + return pMemoryBlock; } -CUtlString::CUtlString( const char *pString ) +//----------------------------------------------------------------------------- +void CUtlString::SetDirect( const char *pValue, int nChars ) { - Set( pString ); + if ( pValue && nChars > 0 ) + { + if ( pValue == m_pString ) + { + AssertMsg( nChars == Q_strlen(m_pString), "CUtlString::SetDirect does not support resizing strings in place." ); + return; // Do nothing. Realloc in AllocMemory might move pValue's location resulting in a bad memcpy. + } + + Assert( nChars <= Min( strnlen(pValue, nChars) + 1, nChars ) ); + AllocMemory( nChars ); + Q_memcpy( m_pString, pValue, nChars ); + } + else + { + Purge(); + } + } -CUtlString::CUtlString( const CUtlString& string ) -{ - Set( string.Get() ); -} - -// Attaches the string to external memory. Useful for avoiding a copy -CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength ) -{ -} - -CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes ) -{ -} void CUtlString::Set( const char *pValue ) { - Assert( !m_Storage.IsReadOnly() ); - int nLen = pValue ? Q_strlen(pValue) + 1 : 0; - m_Storage.Set( pValue, nLen ); -} - -// Returns strlen -int CUtlString::Length() const -{ - return m_Storage.Length() ? m_Storage.Length() - 1 : 0; + int length = pValue ? V_strlen( pValue ) : 0; + SetDirect( pValue, length ); } // Sets the length (used to serialize into the buffer ) void CUtlString::SetLength( int nLen ) { - Assert( !m_Storage.IsReadOnly() ); - - // Add 1 to account for the NULL - m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 ); + if ( nLen > 0 ) + { +#ifdef _DEBUG + int prevLen = m_pString ? Length() : 0; +#endif + AllocMemory( nLen ); +#ifdef _DEBUG + if ( nLen > prevLen ) + { + V_memset( m_pString + prevLen, 0xEB, nLen - prevLen ); + } +#endif + } + else + { + Purge(); + } } const char *CUtlString::Get( ) const { - if ( m_Storage.Length() == 0 ) + if (!m_pString) { return ""; } - - return reinterpret_cast< const char* >( m_Storage.Get() ); + return m_pString; } -// Converts to c-strings -CUtlString::operator const char*() const +char *CUtlString::GetForModify() { - return Get(); -} - -char *CUtlString::Get() -{ - Assert( !m_Storage.IsReadOnly() ); - - if ( m_Storage.Length() == 0 ) + if ( !m_pString ) { // In general, we optimise away small mallocs for empty strings // but if you ask for the non-const bytes, they must be writable // so we can't return "" here, like we do for the const version - jd - m_Storage.SetLength( 1 ); - m_Storage[ 0 ] = '\0'; + void *pMemoryBlock = malloc( 1 ); + m_pString = (char *)pMemoryBlock; + *m_pString = 0; } - return reinterpret_cast< char* >( m_Storage.Get() ); + return m_pString; +} + +char CUtlString::operator[]( int i ) const +{ + if ( !m_pString ) + return '\0'; + + if ( i >= Length() ) + { + return '\0'; + } + + return m_pString[i]; +} + +void CUtlString::Clear() +{ + Purge(); +} + +void CUtlString::Purge() +{ + free( m_pString ); + m_pString = NULL; +} + +bool CUtlString::IsEqual_CaseSensitive( const char *src ) const +{ + if ( !src ) + { + return (Length() == 0); + } + return ( V_strcmp( Get(), src ) == 0 ); +} + +bool CUtlString::IsEqual_CaseInsensitive( const char *src ) const +{ + if ( !src ) + { + return (Length() == 0); + } + return ( V_stricmp( Get(), src ) == 0 ); +} + + +void CUtlString::ToLower() +{ + if ( !m_pString ) + { + return; + } + + V_strlower( m_pString ); +} + +void CUtlString::ToUpper() +{ + if ( !m_pString ) + { + return; + } + + V_strupr( m_pString ); } CUtlString &CUtlString::operator=( const CUtlString &src ) { - Assert( !m_Storage.IsReadOnly() ); - m_Storage = src.m_Storage; + SetDirect( src.Get(), src.Length() ); return *this; } CUtlString &CUtlString::operator=( const char *src ) { - Assert( !m_Storage.IsReadOnly() ); Set( src ); return *this; } bool CUtlString::operator==( const CUtlString &src ) const { - return m_Storage == src.m_Storage; -} + if ( IsEmpty() ) + { + if ( src.IsEmpty() ) + { + return true; + } -bool CUtlString::operator==( const char *src ) const -{ - return ( strcmp( Get(), src ) == 0 ); + return false; + } + else + { + if ( src.IsEmpty() ) + { + return false; + } + + return Q_strcmp( m_pString, src.m_pString ) == 0; + } } CUtlString &CUtlString::operator+=( const CUtlString &rhs ) { - Assert( !m_Storage.IsReadOnly() ); - const int lhsLength( Length() ); const int rhsLength( rhs.Length() ); + + if (!rhsLength) + { + return *this; + } + const int requestedLength( lhsLength + rhsLength ); - SetLength( requestedLength ); - const int allocatedLength( Length() ); - const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); - memcpy( Get() + lhsLength, rhs.Get(), copyLength ); - m_Storage[ allocatedLength ] = '\0'; + AllocMemory( requestedLength ); + Q_memcpy( m_pString + lhsLength, rhs.m_pString, rhsLength ); return *this; } CUtlString &CUtlString::operator+=( const char *rhs ) { - Assert( !m_Storage.IsReadOnly() ); - const int lhsLength( Length() ); - const int rhsLength( Q_strlen( rhs ) ); + const int rhsLength( V_strlen( rhs ) ); const int requestedLength( lhsLength + rhsLength ); - SetLength( requestedLength ); - const int allocatedLength( Length() ); - const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); - memcpy( Get() + lhsLength, rhs, copyLength ); - m_Storage[ allocatedLength ] = '\0'; + if (!requestedLength) + { + return *this; + } + + AllocMemory( requestedLength ); + Q_memcpy( m_pString + lhsLength, rhs, rhsLength ); return *this; } CUtlString &CUtlString::operator+=( char c ) { - Assert( !m_Storage.IsReadOnly() ); + const int lhsLength( Length() ); + + AllocMemory( lhsLength + 1 ); + m_pString[ lhsLength ] = c; - int nLength = Length(); - SetLength( nLength + 1 ); - m_Storage[ nLength ] = c; - m_Storage[ nLength+1 ] = '\0'; return *this; } CUtlString &CUtlString::operator+=( int rhs ) { - Assert( !m_Storage.IsReadOnly() ); Assert( sizeof( rhs ) == 4 ); char tmpBuf[ 12 ]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ] - Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs ); + V_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs ); tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; return operator+=( tmpBuf ); @@ -276,42 +271,114 @@ CUtlString &CUtlString::operator+=( int rhs ) CUtlString &CUtlString::operator+=( double rhs ) { - Assert( !m_Storage.IsReadOnly() ); - char tmpBuf[ 256 ]; // How big can doubles be??? Dunno. - Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs ); + V_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs ); tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; return operator+=( tmpBuf ); } +bool CUtlString::MatchesPattern( const CUtlString &Pattern, int nFlags ) const +{ + const char *pszSource = String(); + const char *pszPattern = Pattern.String(); + bool bExact = true; + + while( 1 ) + { + if ( ( *pszPattern ) == 0 ) + { + return ( (*pszSource ) == 0 ); + } + + if ( ( *pszPattern ) == '*' ) + { + pszPattern++; + + if ( ( *pszPattern ) == 0 ) + { + return true; + } + + bExact = false; + continue; + } + + int nLength = 0; + + while( ( *pszPattern ) != '*' && ( *pszPattern ) != 0 ) + { + nLength++; + pszPattern++; + } + + while( 1 ) + { + const char *pszStartPattern = pszPattern - nLength; + const char *pszSearch = pszSource; + + for( int i = 0; i < nLength; i++, pszSearch++, pszStartPattern++ ) + { + if ( ( *pszSearch ) == 0 ) + { + return false; + } + + if ( ( *pszSearch ) != ( *pszStartPattern ) ) + { + break; + } + } + + if ( pszSearch - pszSource == nLength ) + { + break; + } + + if ( bExact == true ) + { + return false; + } + + if ( ( nFlags & PATTERN_DIRECTORY ) != 0 ) + { + if ( ( *pszPattern ) != '/' && ( *pszSource ) == '/' ) + { + return false; + } + } + + pszSource++; + } + + pszSource += nLength; + } +} + + int CUtlString::Format( const char *pFormat, ... ) { - Assert( !m_Storage.IsReadOnly() ); - - char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer - va_list marker; va_start( marker, pFormat ); -#ifdef _WIN32 - int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); -#elif defined _LINUX || defined __APPLE__ - int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); -#else -#error "define vsnprintf type." -#endif + int len = FormatV( pFormat, marker ); va_end( marker ); - // Len < 0 represents an overflow - if( len < 0 ) - { - len = sizeof( tmpBuf ) - 1; - tmpBuf[sizeof( tmpBuf ) - 1] = 0; - } + return len; +} +//-------------------------------------------------------------------------------------------------- +// This can be called from functions that take varargs. +//-------------------------------------------------------------------------------------------------- + +int CUtlString::FormatV( const char *pFormat, va_list marker ) +{ + char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer + + //va_start( marker, pFormat ); + int len = V_vsprintf_safe( tmpBuf, pFormat, marker ); + //va_end( marker ); Set( tmpBuf ); - return len; } @@ -324,11 +391,377 @@ void CUtlString::StripTrailingSlash() return; int nLastChar = Length() - 1; - char c = m_Storage[ nLastChar ]; + char c = m_pString[ nLastChar ]; if ( c == '\\' || c == '/' ) { - m_Storage[ nLastChar ] = 0; - m_Storage.SetLength( m_Storage.Length() - 1 ); + SetLength( nLastChar ); } } +void CUtlString::FixSlashes( char cSeparator/*=CORRECT_PATH_SEPARATOR*/ ) +{ + if ( m_pString ) + { + V_FixSlashes( m_pString, cSeparator ); + } +} + +//----------------------------------------------------------------------------- +// Trim functions +//----------------------------------------------------------------------------- +void CUtlString::TrimLeft( char cTarget ) +{ + int nIndex = 0; + + if ( IsEmpty() ) + { + return; + } + + while( m_pString[nIndex] == cTarget ) + { + ++nIndex; + } + + // We have some whitespace to remove + if ( nIndex > 0 ) + { + memcpy( m_pString, &m_pString[nIndex], Length() - nIndex ); + SetLength( Length() - nIndex ); + } +} + + +void CUtlString::TrimLeft( const char *szTargets ) +{ + int i; + + if ( IsEmpty() ) + { + return; + } + + for( i = 0; m_pString[i] != 0; i++ ) + { + bool bWhitespace = false; + + for( int j = 0; szTargets[j] != 0; j++ ) + { + if ( m_pString[i] == szTargets[j] ) + { + bWhitespace = true; + break; + } + } + + if ( !bWhitespace ) + { + break; + } + } + + // We have some whitespace to remove + if ( i > 0 ) + { + memcpy( m_pString, &m_pString[i], Length() - i ); + SetLength( Length() - i ); + } +} + + +void CUtlString::TrimRight( char cTarget ) +{ + const int nLastCharIndex = Length() - 1; + int nIndex = nLastCharIndex; + + while ( nIndex >= 0 && m_pString[nIndex] == cTarget ) + { + --nIndex; + } + + // We have some whitespace to remove + if ( nIndex < nLastCharIndex ) + { + m_pString[nIndex + 1] = 0; + SetLength( nIndex + 2 ); + } +} + + +void CUtlString::TrimRight( const char *szTargets ) +{ + const int nLastCharIndex = Length() - 1; + int i; + + for( i = nLastCharIndex; i > 0; i-- ) + { + bool bWhitespace = false; + + for( int j = 0; szTargets[j] != 0; j++ ) + { + if ( m_pString[i] == szTargets[j] ) + { + bWhitespace = true; + break; + } + } + + if ( !bWhitespace ) + { + break; + } + } + + // We have some whitespace to remove + if ( i < nLastCharIndex ) + { + m_pString[i + 1] = 0; + SetLength( i + 2 ); + } +} + + +void CUtlString::Trim( char cTarget ) +{ + TrimLeft( cTarget ); + TrimRight( cTarget ); +} + + +void CUtlString::Trim( const char *szTargets ) +{ + TrimLeft( szTargets ); + TrimRight( szTargets ); +} + + +CUtlString CUtlString::Slice( int32 nStart, int32 nEnd ) const +{ + int length = Length(); + if ( length == 0 ) + { + return CUtlString(); + } + + if ( nStart < 0 ) + nStart = length - (-nStart % length); + else if ( nStart >= length ) + nStart = length; + + if ( nEnd == INT32_MAX ) + nEnd = length; + else if ( nEnd < 0 ) + nEnd = length - (-nEnd % length); + else if ( nEnd >= length ) + nEnd = length; + + if ( nStart >= nEnd ) + return CUtlString(); + + const char *pIn = String(); + + CUtlString ret; + ret.SetDirect( pIn + nStart, nEnd - nStart ); + return ret; +} + +// Grab a substring starting from the left or the right side. +CUtlString CUtlString::Left( int32 nChars ) const +{ + return Slice( 0, nChars ); +} + +CUtlString CUtlString::Right( int32 nChars ) const +{ + return Slice( -nChars ); +} + +CUtlString CUtlString::Replace( char cFrom, char cTo ) const +{ + if (!m_pString) + { + return CUtlString(); + } + + CUtlString ret = *this; + int len = ret.Length(); + for ( int i=0; i < len; i++ ) + { + if ( ret.m_pString[i] == cFrom ) + ret.m_pString[i] = cTo; + } + + return ret; +} + +CUtlString CUtlString::Replace( const char *pszFrom, const char *pszTo ) const +{ + Assert( pszTo ); // Can be 0 length, but not null + Assert( pszFrom && *pszFrom ); // Must be valid and have one character. + + + const char *pos = V_strstr( String(), pszFrom ); + if ( !pos ) + { + return *this; + } + + const char *pFirstFound = pos; + + // count number of search string + int nSearchCount = 0; + int nSearchLength = V_strlen( pszFrom ); + while ( pos ) + { + nSearchCount++; + int nSrcOffset = ( pos - String() ) + nSearchLength; + pos = V_strstr( String() + nSrcOffset, pszFrom ); + } + + // allocate the new string + int nReplaceLength = V_strlen( pszTo ); + int nAllocOffset = nSearchCount * ( nReplaceLength - nSearchLength ); + size_t srcLength = Length(); + CUtlString strDest; + size_t destLength = srcLength + nAllocOffset; + strDest.SetLength( destLength ); + + // find and replace the search string + pos = pFirstFound; + int nDestOffset = 0; + int nSrcOffset = 0; + while ( pos ) + { + // Found an instance + int nCurrentSearchOffset = pos - String(); + int nCopyLength = nCurrentSearchOffset - nSrcOffset; + V_strncpy( strDest.GetForModify() + nDestOffset, String() + nSrcOffset, nCopyLength + 1 ); + nDestOffset += nCopyLength; + V_strncpy( strDest.GetForModify() + nDestOffset, pszTo, nReplaceLength + 1 ); + nDestOffset += nReplaceLength; + + nSrcOffset = nCurrentSearchOffset + nSearchLength; + pos = V_strstr( String() + nSrcOffset, pszFrom ); + } + + // making sure that the left over string from the source is the same size as the left over dest buffer + Assert( destLength - nDestOffset == srcLength - nSrcOffset ); + if ( destLength - nDestOffset > 0 ) + { + V_strncpy( strDest.GetForModify() + nDestOffset, String() + nSrcOffset, destLength - nDestOffset + 1 ); + } + + return strDest; +} + +CUtlString CUtlString::AbsPath( const char *pStartingDir ) const +{ + char szNew[MAX_PATH]; + V_MakeAbsolutePath( szNew, sizeof( szNew ), this->String(), pStartingDir ); + return CUtlString( szNew ); +} + +CUtlString CUtlString::UnqualifiedFilename() const +{ + const char *pFilename = V_UnqualifiedFileName( this->String() ); + return CUtlString( pFilename ); +} + +CUtlString CUtlString::DirName() const +{ + CUtlString ret( this->String() ); + V_StripLastDir( (char*)ret.Get(), ret.Length() + 1 ); + V_StripTrailingSlash( (char*)ret.Get() ); + return ret; +} + +CUtlString CUtlString::StripExtension() const +{ + char szTemp[MAX_PATH]; + V_StripExtension( String(), szTemp, sizeof( szTemp ) ); + return CUtlString( szTemp ); +} + +CUtlString CUtlString::StripFilename() const +{ + const char *pFilename = V_UnqualifiedFileName( Get() ); // NOTE: returns 'Get()' on failure, never NULL + int nCharsToCopy = pFilename - Get(); + CUtlString result; + result.SetDirect( Get(), nCharsToCopy ); + result.StripTrailingSlash(); + return result; +} + +CUtlString CUtlString::GetBaseFilename() const +{ + char szTemp[MAX_PATH]; + V_FileBase( String(), szTemp, sizeof( szTemp ) ); + return CUtlString( szTemp ); +} + +CUtlString CUtlString::GetExtension() const +{ + char szTemp[MAX_PATH]; + V_ExtractFileExtension( String(), szTemp, sizeof( szTemp ) ); + return CUtlString( szTemp ); +} + + +CUtlString CUtlString::PathJoin( const char *pStr1, const char *pStr2 ) +{ + char szPath[MAX_PATH]; + V_ComposeFileName( pStr1, pStr2, szPath, sizeof( szPath ) ); + return CUtlString( szPath ); +} + +CUtlString CUtlString::operator+( const char *pOther ) const +{ + CUtlString s = *this; + s += pOther; + return s; +} + +CUtlString CUtlString::operator+( const CUtlString &other ) const +{ + CUtlString s = *this; + s += other; + return s; +} + +CUtlString CUtlString::operator+( int rhs ) const +{ + CUtlString ret = *this; + ret += rhs; + return ret; +} + +//----------------------------------------------------------------------------- +// Purpose: concatenate the provided string to our current content +//----------------------------------------------------------------------------- +void CUtlString::Append( const char *pchAddition ) +{ + (*this) += pchAddition; +} + +void CUtlString::Append( const char *pchAddition, int nChars ) +{ + nChars = Min( nChars, V_strlen( pchAddition ) ); + + const int lhsLength( Length() ); + const int rhsLength( nChars ); + const int requestedLength( lhsLength + rhsLength ); + + AllocMemory( requestedLength ); + const int allocatedLength( requestedLength ); + const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); + memcpy( GetForModify() + lhsLength, pchAddition, copyLength ); + m_pString[ allocatedLength ] = '\0'; +} + +// Shared static empty string. +const CUtlString &CUtlString::GetEmptyString() +{ + static const CUtlString s_emptyString; + + return s_emptyString; +}