diff options
Diffstat (limited to 'mp/src/utils/serverplugin_sample/serverplugin_empty.cpp')
| -rw-r--r-- | mp/src/utils/serverplugin_sample/serverplugin_empty.cpp | 1844 |
1 files changed, 922 insertions, 922 deletions
diff --git a/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp b/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp index ff82b5f6..42e4c1d3 100644 --- a/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp +++ b/mp/src/utils/serverplugin_sample/serverplugin_empty.cpp @@ -1,922 +1,922 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-// $NoKeywords: $
-//
-//===========================================================================//
-
-#include <stdio.h>
-
-//#define GAME_DLL
-#ifdef GAME_DLL
-#include "cbase.h"
-#endif
-
-#include <stdio.h>
-#include "interface.h"
-#include "filesystem.h"
-#include "engine/iserverplugin.h"
-#include "eiface.h"
-#include "igameevents.h"
-#include "convar.h"
-#include "Color.h"
-#include "vstdlib/random.h"
-#include "engine/IEngineTrace.h"
-#include "tier2/tier2.h"
-#include "game/server/pluginvariant.h"
-#include "game/server/iplayerinfo.h"
-#include "game/server/ientityinfo.h"
-#include "game/server/igameinfo.h"
-
-//#define SAMPLE_TF2_PLUGIN
-#ifdef SAMPLE_TF2_PLUGIN
-#include "tf/tf_shareddefs.h"
-#endif
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-// Interfaces from the engine
-IVEngineServer *engine = NULL; // helper functions (messaging clients, loading content, making entities, running commands, etc)
-IGameEventManager *gameeventmanager_ = NULL; // game events interface
-#ifndef GAME_DLL
-#define gameeventmanager gameeventmanager_
-#endif
-IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players
-IEntityInfoManager *entityinfomanager = NULL; // game dll interface to interact with all entities (like IPlayerInfo)
-IGameInfoManager *gameinfomanager = NULL; // game dll interface to get data from game rules directly
-IBotManager *botmanager = NULL; // game dll interface to interact with bots
-IServerPluginHelpers *helpers = NULL; // special 3rd party plugin helpers from the engine
-IUniformRandomStream *randomStr = NULL;
-IEngineTrace *enginetrace = NULL;
-
-
-CGlobalVars *gpGlobals = NULL;
-
-// function to initialize any cvars/command in this plugin
-void Bot_RunAll( void );
-
-// useful helper func
-#ifndef GAME_DLL
-inline bool FStrEq(const char *sz1, const char *sz2)
-{
- return(Q_stricmp(sz1, sz2) == 0);
-}
-#endif
-//---------------------------------------------------------------------------------
-// Purpose: a sample 3rd party plugin class
-//---------------------------------------------------------------------------------
-class CEmptyServerPlugin: public IServerPluginCallbacks, public IGameEventListener
-{
-public:
- CEmptyServerPlugin();
- ~CEmptyServerPlugin();
-
- // IServerPluginCallbacks methods
- virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory );
- virtual void Unload( void );
- virtual void Pause( void );
- virtual void UnPause( void );
- virtual const char *GetPluginDescription( void );
- virtual void LevelInit( char const *pMapName );
- virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax );
- virtual void GameFrame( bool simulating );
- virtual void LevelShutdown( void );
- virtual void ClientActive( edict_t *pEntity );
- virtual void ClientDisconnect( edict_t *pEntity );
- virtual void ClientPutInServer( edict_t *pEntity, char const *playername );
- virtual void SetCommandClient( int index );
- virtual void ClientSettingsChanged( edict_t *pEdict );
- virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen );
- virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args );
- virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID );
- virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue );
- virtual void OnEdictAllocated( edict_t *edict );
- virtual void OnEdictFreed( const edict_t *edict );
-
- // IGameEventListener Interface
- virtual void FireGameEvent( KeyValues * event );
-
- virtual int GetCommandIndex() { return m_iClientCommandIndex; }
-private:
- int m_iClientCommandIndex;
-};
-
-
-//
-// The plugin is a static singleton that is exported as an interface
-//
-CEmptyServerPlugin g_EmtpyServerPlugin;
-EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEmptyServerPlugin, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, g_EmtpyServerPlugin );
-
-//---------------------------------------------------------------------------------
-// Purpose: constructor/destructor
-//---------------------------------------------------------------------------------
-CEmptyServerPlugin::CEmptyServerPlugin()
-{
- m_iClientCommandIndex = 0;
-}
-
-CEmptyServerPlugin::~CEmptyServerPlugin()
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when the plugin is loaded, load the interface we need from the engine
-//---------------------------------------------------------------------------------
-bool CEmptyServerPlugin::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory )
-{
- ConnectTier1Libraries( &interfaceFactory, 1 );
- ConnectTier2Libraries( &interfaceFactory, 1 );
-
- entityinfomanager = (IEntityInfoManager *)gameServerFactory(INTERFACEVERSION_ENTITYINFOMANAGER,NULL);
- if ( !entityinfomanager )
- {
- Warning( "Unable to load entityinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access entity data
- }
-
- playerinfomanager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER,NULL);
- if ( !playerinfomanager )
- {
- Warning( "Unable to load playerinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access specific player data
- }
-
- botmanager = (IBotManager *)gameServerFactory(INTERFACEVERSION_PLAYERBOTMANAGER, NULL);
- if ( !botmanager )
- {
- Warning( "Unable to load botcontroller, ignoring\n" ); // this isn't fatal, we just won't be able to access specific bot functions
- }
- gameinfomanager = (IGameInfoManager *)gameServerFactory(INTERFACEVERSION_GAMEINFOMANAGER, NULL);
- if (!gameinfomanager)
- {
- Warning( "Unable to load gameinfomanager, ignoring\n" );
- }
-
- engine = (IVEngineServer*)interfaceFactory(INTERFACEVERSION_VENGINESERVER, NULL);
- gameeventmanager = (IGameEventManager *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER,NULL);
- helpers = (IServerPluginHelpers*)interfaceFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, NULL);
- enginetrace = (IEngineTrace *)interfaceFactory(INTERFACEVERSION_ENGINETRACE_SERVER,NULL);
- randomStr = (IUniformRandomStream *)interfaceFactory(VENGINE_SERVER_RANDOM_INTERFACE_VERSION, NULL);
-
- // get the interfaces we want to use
- if( ! ( engine && gameeventmanager && g_pFullFileSystem && helpers && enginetrace && randomStr ) )
- {
- return false; // we require all these interface to function
- }
-
- if ( playerinfomanager )
- {
- gpGlobals = playerinfomanager->GetGlobalVars();
- }
-
- MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
- ConVar_Register( 0 );
- return true;
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when the plugin is unloaded (turned off)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::Unload( void )
-{
- gameeventmanager->RemoveListener( this ); // make sure we are unloaded from the event system
-
- ConVar_Unregister( );
- DisconnectTier2Libraries( );
- DisconnectTier1Libraries( );
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when the plugin is paused (i.e should stop running but isn't unloaded)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::Pause( void )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when the plugin is unpaused (i.e should start executing again)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::UnPause( void )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: the name of this plugin, returned in "plugin_print" command
-//---------------------------------------------------------------------------------
-const char *CEmptyServerPlugin::GetPluginDescription( void )
-{
- return "Emtpy-Plugin V2, Valve";
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called on level start
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::LevelInit( char const *pMapName )
-{
- Msg( "Level \"%s\" has been loaded\n", pMapName );
- gameeventmanager->AddListener( this, true );
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called on level start, when the server is ready to accept client connections
-// edictCount is the number of entities in the level, clientMax is the max client count
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called once per server frame, do recurring work here (like checking for timeouts)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::GameFrame( bool simulating )
-{
- if ( simulating )
- {
- Bot_RunAll();
- }
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called on level end (as the server is shutting down or going to a new map)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::LevelShutdown( void ) // !!!!this can get called multiple times per map change
-{
- gameeventmanager->RemoveListener( this );
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a client spawns into a server (i.e as they begin to play)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::ClientActive( edict_t *pEntity )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a client leaves a server (or is timed out)
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::ClientDisconnect( edict_t *pEntity )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called on
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::ClientPutInServer( edict_t *pEntity, char const *playername )
-{
- KeyValues *kv = new KeyValues( "msg" );
- kv->SetString( "title", "Hello" );
- kv->SetString( "msg", "Hello there" );
- kv->SetColor( "color", Color( 255, 0, 0, 255 ));
- kv->SetInt( "level", 5);
- kv->SetInt( "time", 10);
- helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this );
- kv->deleteThis();
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called on level start
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::SetCommandClient( int index )
-{
- m_iClientCommandIndex = index;
-}
-
-void ClientPrint( edict_t *pEdict, char *format, ... )
-{
- va_list argptr;
- static char string[1024];
-
- va_start (argptr, format);
- Q_vsnprintf(string, sizeof(string), format,argptr);
- va_end (argptr);
-
- engine->ClientPrintf( pEdict, string );
-}
-//---------------------------------------------------------------------------------
-// Purpose: called on level start
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::ClientSettingsChanged( edict_t *pEdict )
-{
- if ( playerinfomanager )
- {
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEdict );
-
- const char * name = engine->GetClientConVarValue( engine->IndexOfEdict(pEdict), "name" );
-
- // CAN'T use Q_stricmp here, this dll is made by 3rd parties and may not link to tier0/vstdlib
- if ( playerinfo && name && playerinfo->GetName() &&
- stricmp( name, playerinfo->GetName()) ) // playerinfo may be NULL if the MOD doesn't support access to player data
- // OR if you are accessing the player before they are fully connected
- {
- ClientPrint( pEdict, "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() );
- // this is the bad way to check this, the better option it to listen for the "player_changename" event in FireGameEvent()
- // this is here to give a real example of how to use the playerinfo interface
- }
- }
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a client joins a server
-//---------------------------------------------------------------------------------
-PLUGIN_RESULT CEmptyServerPlugin::ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen )
-{
- return PLUGIN_CONTINUE;
-}
-
-CON_COMMAND( DoAskConnect, "Server plugin example of using the ask connect dialog" )
-{
- if ( args.ArgC() < 2 )
- {
- Warning ( "DoAskConnect <server IP>\n" );
- }
- else
- {
- const char *pServerIP = args.Arg( 1 );
-
- KeyValues *kv = new KeyValues( "menu" );
- kv->SetString( "title", pServerIP ); // The IP address of the server to connect to goes in the "title" field.
- kv->SetInt( "time", 3 );
-
- for ( int i=1; i < gpGlobals->maxClients; i++ )
- {
- edict_t *pEdict = engine->PEntityOfEntIndex( i );
- if ( pEdict )
- {
- helpers->CreateMessage( pEdict, DIALOG_ASKCONNECT, kv, &g_EmtpyServerPlugin );
- }
- }
-
- kv->deleteThis();
- }
-}
-
-#ifdef SAMPLE_TF2_PLUGIN
-const char *classNames[] =
-{
- "unknown",
- "scout",
- "sniper",
- "soldier",
- "demoman",
- "medic",
- "heavy weapons guy",
- "pyro",
- "spy",
- "engineer",
-};
-
-bool TFPlayerHasCondition( int inBits, int condition )
-{
- Assert( condition >= 0 && condition < TF_COND_LAST );
-
- return ( ( inBits & (1<<condition) ) != 0 );
-}
-
-void SentryStatus( edict_t *pEntity )
-{
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- {
- Msg("couldn't get playerinfo\n");
- return;
- }
-
- Msg("Sentry Status:\n");
- pluginvariant value;
- pluginvariant emptyVariant;
- edict_t *pSentry = NULL;
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_SENTRY, value, emptyVariant))
- {
- pSentry = engine->PEntityOfEntIndex( value.Int() );
- if (!pSentry)
- {
- Warning("couldn't attain sentry gun entity\n");
- return;
- }
- }
- else
- {
- Msg("No Sentrygun built.\n");
- return;
-
- }
- IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pSentry );
- if (!entinfo)
- {
- Warning("couldn't get entinfo for sentry gun\n");
- return;
- }
-
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_SENTRY, value, emptyVariant))
- {
- if (value.Bool())
- Msg("Sentry Under Construction...\n");
- }
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_UPGRADING_SENTRY, value, emptyVariant))
- {
- if (value.Bool())
- Msg("Sentry Upgrading...\n");
- }
-
- int sentryLevel = 0;
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_LEVEL, value, emptyVariant))
- {
- sentryLevel = value.Int();
- Msg("Sentry Level: %i\n", sentryLevel );
- }
- else
- Msg("Unable to retrive sentry level\n");
-
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_PROGRESS, value, emptyVariant))
- {
- if (sentryLevel < 3)
- {
- int iMetal, iRequiredMetal;
- iRequiredMetal = value.Int() & 0xFF;
- iMetal = (value.Int()>>8) & 0xFF;
- Msg("%i / %i Metal Required for Sentry Level %i\n", iMetal, iRequiredMetal, sentryLevel+1);
- }
- else
- Msg("Sentry cannot be upgraded further.\n");
- }
-
- Msg("Health: %i\n", entinfo->GetHealth() );
-
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_KILLS, value, emptyVariant))
- Msg("Kills: %i\n", value.Int() );
- else
- Msg("Unable to retrieve sentry kills\n");
-
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_SHELLS, value, emptyVariant))
- {
- int iShells, iMaxShells;
- iMaxShells = value.Int() & 0xFF;
- iShells = (value.Int()>>8) & 0xFF;
- Msg("Shells: %i / %i\n", iShells, iMaxShells);
- }
- if (sentryLevel > 2)
- {
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_ROCKETS, value, emptyVariant))
- {
- int iRockets, iMaxRockets;
- iMaxRockets = value.Int() & 0xFF;
- iRockets = (value.Int()>>8) & 0xFF;
- Msg("Rockets: %i / %i\n", iRockets, iMaxRockets);
- }
- }
-
-}
-void DispenserStatus( edict_t *pEntity )
-{
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- {
- Msg("couldn't get playerinfo\n");
- return;
- }
-
- Msg("Dispenser Status:\n");
- pluginvariant value;
- pluginvariant emptyVariant;
- edict_t *pDispenser = NULL;
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_DISPENSER, value, emptyVariant))
- {
- pDispenser = engine->PEntityOfEntIndex( value.Int() );
- if (!pDispenser)
- {
- Warning("couldn't attain dispenser entity\n");
- return;
- }
- }
- else
- {
- Msg("No dispenser built.\n");
- return;
- }
- IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pDispenser );
- if (!entinfo)
- {
- Warning("couldn't get entinfo for dispenser\n");
- return;
- }
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_DISPENSER, value, emptyVariant))
- {
- if (value.Bool())
- Msg("Dispenser Under Construction...\n");
- }
- Msg("Health: %i\n", entinfo->GetHealth() );
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_DISPENSER_METAL, value, emptyVariant))
- Msg("Metal: %i\n", value.Int() );
-}
-void TeleporterStatus( edict_t *pEntity )
-{
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- {
- Msg("couldn't get playerinfo\n");
- return;
- }
-
- Msg("Teleporter Status:\n");
-
- pluginvariant value;
- pluginvariant emptyVariant;
- edict_t *pEntrance = NULL;
- edict_t *pExit = NULL;
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_ENTRANCE, value, emptyVariant))
- {
- pEntrance = engine->PEntityOfEntIndex( value.Int() );
- if (!pEntrance)
- {
- Warning("couldn't attain entrance entity\n");
- }
- }
- else
- {
- Msg("No Teleporter Entrance built.\n");
- }
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_EXIT, value, emptyVariant))
- {
- pExit = engine->PEntityOfEntIndex( value.Int() );
- if (!pExit)
- {
- Warning("couldn't attain exit entity\n");
- }
- }
- else
- {
- Msg("No Teleporter Entrance built.\n");
- }
- IEntityInfo *entranceInfo = entityinfomanager->GetEntityInfo( pEntrance );
- if (!entranceInfo)
- {
- Warning("couldn't get entinfo for teleporter entrance\n");
- }
- IEntityInfo *exitInfo = entityinfomanager->GetEntityInfo( pExit );
- if (!exitInfo)
- {
- Warning("couldn't get entinfo for teleporter exit\n");
- }
-
- if (pEntrance && entranceInfo)
- {
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_ENTRANCE, value, emptyVariant))
- {
- if (value.Bool())
- Msg("Entrance Under Construction...\n");
- }
- Msg("Entrance Health: %i\n", entranceInfo->GetHealth() );
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_TELEPORTER_USES, value, emptyVariant))
- Msg("Entrance Used %i Times.\n", value.Int() );
-
- }
- if (pExit && exitInfo)
- {
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_EXIT, value, emptyVariant))
- {
- if (value.Bool())
- Msg("Exit Under Construction...\n");
- }
- Msg("Exit Health: %i\n", exitInfo->GetHealth() );
- }
-}
-void ClassStatus( edict_t *pEntity )
-{
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- {
- Msg("couldn't get playerinfo\n");
- return;
- }
- int playerClassId = playerinfo->GetPlayerClassId();
-
- Msg("Player Class: %s\n", playerinfo->GetPlayerClassName());
- pluginvariant conditionValue;
- pluginvariant emptyVariant;
- if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant))
- {
- Warning("unable to retrieve conditions!\n");
- }
- if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE ))
- Msg("You are Invulnerable!\n");
- if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT ))
- Msg("You are about to Teleport.\n");
- if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED ))
- Msg("You have recently been teleported.\n");
-
- switch(playerClassId)
- {
- default:
- case TF_CLASS_MEDIC:
- break;
- case TF_CLASS_ENGINEER:
- Msg("Building Information:\n");
- SentryStatus( pEntity );
- DispenserStatus( pEntity );
- TeleporterStatus( pEntity );
- break;
- case TF_CLASS_SPY:
- {
- int disguiseClass = 0;
- pluginvariant value;
-
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_DISGUISEDAS, value, emptyVariant))
- disguiseClass = value.Int();
-
- if ( TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) )
- Msg("Disguising..\n");
- else if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) )
- Msg("Disguised as: %s\n", classNames[disguiseClass] );
-
- if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED ))
- Msg("Cloaked!\n");
- if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_CLOAKCHARGELEVEL, value, emptyVariant))
- Msg("Cloak Charge Percent: %d\n", value.Float() );
-
- break;
- }
- case TF_CLASS_DEMOMAN:
- break;
- }
-}
-const char *ctf_flagtype[] =
-{
- "ctf", //TF_FLAGTYPE_CTF = 0,
- "attack / defend", //TF_FLAGTYPE_ATTACK_DEFEND,
- "territory control", //TF_FLAGTYPE_TERRITORY_CONTROL,
- "invade", //TF_FLAGTYPE_INVADE,
- "king of the hill", //TF_FLAGTYPE_KINGOFTHEHILL,
-};
-const char *ctf_flagstatus[] =
-{
- "unknown",
- "At Home",
- "Dropped",
- "Stolen",
-};
-void FlagStatus( edict_t *pPlayer )
-{
- IPlayerInfo *pInfo = playerinfomanager->GetPlayerInfo( pPlayer );
- if (!pInfo)
- {
- Msg( "couldn't get playerinfo\n" );
- return;
- }
- IGameInfo *gameInfo = gameinfomanager->GetGameInfo();
- if (!gameInfo)
- {
- Msg( "couldn't get gameinfo\n" );
- }
-
- int gameType = gameInfo->GetInfo_GameType();
-
- if (gameType != 1)
- {
- Msg( "Game is not CTF.\n" );
- return;
- }
- Msg( "===============================\n" );
- Msg( "Capture The Flag -- Flag Status\n" );
- Msg( "===============================\n" );
- pluginvariant value, options;
-
- edict_t *pFlag = NULL;
- while ( (pFlag = entityinfomanager->FindEntityByClassname(pFlag, "item_teamflag")) != NULL )
- {
- IEntityInfo *pFlagInfo = entityinfomanager->GetEntityInfo( pFlag );
- if (!pFlagInfo)
- continue;
-
- Msg( "\nTeam %s's Flag\n", gameInfo->GetInfo_GetTeamName( pFlagInfo->GetTeamIndex() ) );
- options.SetInt(engine->IndexOfEdict(pFlag));
- if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_TYPE, value, options) )
- Msg( "Type: %s\n", ctf_flagtype[value.Int()] );
- if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_STATUS, value, options) )
- {
- Msg( "Status: %s\n", ctf_flagstatus[value.Int()] );
- //Tony; if we're carried, find out who has us.
- if (value.Int() == 3)
- {
- edict_t *pPlayer = pFlagInfo->GetOwner();
- if (pPlayer)
- {
- IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo( pPlayer );
- if (pPlayerInfo)
- Msg( "Carried by: %s\n", pPlayerInfo->GetName() );
- }
- }
- }
- }
-
-
- Msg( "===============================\n" );
-}
-#endif
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a client types in a command (only a subset of commands however, not CON_COMMAND's)
-//---------------------------------------------------------------------------------
-PLUGIN_RESULT CEmptyServerPlugin::ClientCommand( edict_t *pEntity, const CCommand &args )
-{
- const char *pcmd = args[0];
-
- if ( !pEntity || pEntity->IsFree() )
- {
- return PLUGIN_CONTINUE;
- }
-
- if ( FStrEq( pcmd, "menu" ) )
- {
- KeyValues *kv = new KeyValues( "menu" );
- kv->SetString( "title", "You've got options, hit ESC" );
- kv->SetInt( "level", 1 );
- kv->SetColor( "color", Color( 255, 0, 0, 255 ));
- kv->SetInt( "time", 20 );
- kv->SetString( "msg", "Pick an option\nOr don't." );
-
- for( int i = 1; i < 9; i++ )
- {
- char num[10], msg[10], cmd[10];
- Q_snprintf( num, sizeof(num), "%i", i );
- Q_snprintf( msg, sizeof(msg), "Option %i", i );
- Q_snprintf( cmd, sizeof(cmd), "option%i", i );
-
- KeyValues *item1 = kv->FindKey( num, true );
- item1->SetString( "msg", msg );
- item1->SetString( "command", cmd );
- }
-
- helpers->CreateMessage( pEntity, DIALOG_MENU, kv, this );
- kv->deleteThis();
- return PLUGIN_STOP; // we handled this function
- }
- else if ( FStrEq( pcmd, "rich" ) )
- {
- KeyValues *kv = new KeyValues( "menu" );
- kv->SetString( "title", "A rich message" );
- kv->SetInt( "level", 1 );
- kv->SetInt( "time", 20 );
- kv->SetString( "msg", "This is a long long long text string.\n\nIt also has line breaks." );
-
- helpers->CreateMessage( pEntity, DIALOG_TEXT, kv, this );
- kv->deleteThis();
- return PLUGIN_STOP; // we handled this function
- }
- else if ( FStrEq( pcmd, "msg" ) )
- {
- KeyValues *kv = new KeyValues( "menu" );
- kv->SetString( "title", "Just a simple hello" );
- kv->SetInt( "level", 1 );
- kv->SetInt( "time", 20 );
-
- helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this );
- kv->deleteThis();
- return PLUGIN_STOP; // we handled this function
- }
- else if ( FStrEq( pcmd, "entry" ) )
- {
- KeyValues *kv = new KeyValues( "entry" );
- kv->SetString( "title", "Stuff" );
- kv->SetString( "msg", "Enter something" );
- kv->SetString( "command", "say" ); // anything they enter into the dialog turns into a say command
- kv->SetInt( "level", 1 );
- kv->SetInt( "time", 20 );
-
- helpers->CreateMessage( pEntity, DIALOG_ENTRY, kv, this );
- kv->deleteThis();
- return PLUGIN_STOP; // we handled this function
- }
-#ifdef SAMPLE_TF2_PLUGIN
- else if ( FStrEq( pcmd, "gameinfo" ) )
- {
- IGameInfo *gameInfo = gameinfomanager->GetGameInfo();
- if (!gameInfo)
- return PLUGIN_STOP;
-
- Msg("=== Game Information ===\n");
- Msg("Game Type: %i / %s\n", gameInfo->GetInfo_GameType(), gameInfo->GetInfo_GameTypeName() );
- int teamCount = gameInfo->GetInfo_GetTeamCount();
- Msg("Num Teams: %i\n", teamCount );
-
- Msg("Player Counts:\n");
- for (int i = 0;i<teamCount;i++)
- {
- //If this failes, we can assume the rest is invalid too.
- if (!gameInfo->GetInfo_GetTeamName(i) )
- continue;
- Msg("Team: %s, Players: %i\n", gameInfo->GetInfo_GetTeamName(i), gameInfo->GetInfo_NumPlayersOnTeam(i) );
- }
- return PLUGIN_STOP;
-
- }
- // Sample to use the new CustomInfo added to TF2 for plugins
- else if ( FStrEq( pcmd, "tfcond" ) )
- {
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- return PLUGIN_STOP;
-
- pluginvariant conditionValue;
- pluginvariant emptyVariant;
- if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant))
- {
- Msg("unable to retrieve conditions!\n");
- return PLUGIN_STOP;
- }
-
- Msg("Disguising?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ? "yes" : "no" );
- Msg("Disguised?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ? "yes" : "no" );
- Msg("Stealthed?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED ) ? "yes" : "no" );
- Msg("Invulnerable?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE ) ? "yes" : "no" );
- Msg("Teleported Recently?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED ) ? "yes" : "no" );
- Msg("Selected for Teleportation?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT ) ? "yes" : "no" );
- Msg("On Fire?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_BURNING ) ? "yes" : "no" );
-
- return PLUGIN_STOP;
- }
- else if ( FStrEq( pcmd, "sentry_status" ) )
- {
- SentryStatus(pEntity);
- return PLUGIN_STOP;
- }
- else if ( FStrEq( pcmd, "class_status" ) )
- {
- ClassStatus(pEntity);
- return PLUGIN_STOP;
- }
- else if ( FStrEq( pcmd, "flag_status" ) )
- {
- FlagStatus(pEntity);
- return PLUGIN_STOP;
- }
- #ifdef GAME_DLL
- else if ( FStrEq( pcmd, "cbe_test" ) )
- {
- IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity );
- if (!playerinfo)
- return PLUGIN_STOP;
-
- CBaseEntity *pEnt = static_cast< CBaseEntity* >(entityinfomanager->GetEntity( pEntity ));
- if (pEnt)
- Msg("got a pointer to CBaseEntity..\n");
- Msg("attempting to print this entities modelname directly..\n");
-
- Msg("ModelName: %s\n", STRING(pEnt->GetModelName()) );
-
- return PLUGIN_STOP;
- }
- #endif
-#endif
-
-
- return PLUGIN_CONTINUE;
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a client is authenticated
-//---------------------------------------------------------------------------------
-PLUGIN_RESULT CEmptyServerPlugin::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID )
-{
- return PLUGIN_CONTINUE;
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when a cvar value query is finished
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue )
-{
- Msg( "Cvar query (cookie: %d, status: %d) - name: %s, value: %s\n", iCookie, eStatus, pCvarName, pCvarValue );
-}
-void CEmptyServerPlugin::OnEdictAllocated( edict_t *edict )
-{
-}
-void CEmptyServerPlugin::OnEdictFreed( const edict_t *edict )
-{
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: called when an event is fired
-//---------------------------------------------------------------------------------
-void CEmptyServerPlugin::FireGameEvent( KeyValues * event )
-{
- const char * name = event->GetName();
- Msg( "CEmptyServerPlugin::FireGameEvent: Got event \"%s\"\n", name );
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: an example of how to implement a new command
-//---------------------------------------------------------------------------------
-CON_COMMAND( empty_version, "prints the version of the empty plugin" )
-{
- Msg( "Version:2.0.0.0\n" );
-}
-
-CON_COMMAND( empty_log, "logs the version of the empty plugin" )
-{
- engine->LogPrint( "Version:2.0.0.0\n" );
-}
-
-//---------------------------------------------------------------------------------
-// Purpose: an example cvar
-//---------------------------------------------------------------------------------
-static ConVar empty_cvar("plugin_empty", "0", FCVAR_NOTIFY, "Example plugin cvar");
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#include <stdio.h> + +//#define GAME_DLL +#ifdef GAME_DLL +#include "cbase.h" +#endif + +#include <stdio.h> +#include "interface.h" +#include "filesystem.h" +#include "engine/iserverplugin.h" +#include "eiface.h" +#include "igameevents.h" +#include "convar.h" +#include "Color.h" +#include "vstdlib/random.h" +#include "engine/IEngineTrace.h" +#include "tier2/tier2.h" +#include "game/server/pluginvariant.h" +#include "game/server/iplayerinfo.h" +#include "game/server/ientityinfo.h" +#include "game/server/igameinfo.h" + +//#define SAMPLE_TF2_PLUGIN +#ifdef SAMPLE_TF2_PLUGIN +#include "tf/tf_shareddefs.h" +#endif +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +// Interfaces from the engine +IVEngineServer *engine = NULL; // helper functions (messaging clients, loading content, making entities, running commands, etc) +IGameEventManager *gameeventmanager_ = NULL; // game events interface +#ifndef GAME_DLL +#define gameeventmanager gameeventmanager_ +#endif +IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players +IEntityInfoManager *entityinfomanager = NULL; // game dll interface to interact with all entities (like IPlayerInfo) +IGameInfoManager *gameinfomanager = NULL; // game dll interface to get data from game rules directly +IBotManager *botmanager = NULL; // game dll interface to interact with bots +IServerPluginHelpers *helpers = NULL; // special 3rd party plugin helpers from the engine +IUniformRandomStream *randomStr = NULL; +IEngineTrace *enginetrace = NULL; + + +CGlobalVars *gpGlobals = NULL; + +// function to initialize any cvars/command in this plugin +void Bot_RunAll( void ); + +// useful helper func +#ifndef GAME_DLL +inline bool FStrEq(const char *sz1, const char *sz2) +{ + return(Q_stricmp(sz1, sz2) == 0); +} +#endif +//--------------------------------------------------------------------------------- +// Purpose: a sample 3rd party plugin class +//--------------------------------------------------------------------------------- +class CEmptyServerPlugin: public IServerPluginCallbacks, public IGameEventListener +{ +public: + CEmptyServerPlugin(); + ~CEmptyServerPlugin(); + + // IServerPluginCallbacks methods + virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ); + virtual void Unload( void ); + virtual void Pause( void ); + virtual void UnPause( void ); + virtual const char *GetPluginDescription( void ); + virtual void LevelInit( char const *pMapName ); + virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); + virtual void GameFrame( bool simulating ); + virtual void LevelShutdown( void ); + virtual void ClientActive( edict_t *pEntity ); + virtual void ClientDisconnect( edict_t *pEntity ); + virtual void ClientPutInServer( edict_t *pEntity, char const *playername ); + virtual void SetCommandClient( int index ); + virtual void ClientSettingsChanged( edict_t *pEdict ); + virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); + virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args ); + virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); + virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); + virtual void OnEdictAllocated( edict_t *edict ); + virtual void OnEdictFreed( const edict_t *edict ); + + // IGameEventListener Interface + virtual void FireGameEvent( KeyValues * event ); + + virtual int GetCommandIndex() { return m_iClientCommandIndex; } +private: + int m_iClientCommandIndex; +}; + + +// +// The plugin is a static singleton that is exported as an interface +// +CEmptyServerPlugin g_EmtpyServerPlugin; +EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEmptyServerPlugin, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, g_EmtpyServerPlugin ); + +//--------------------------------------------------------------------------------- +// Purpose: constructor/destructor +//--------------------------------------------------------------------------------- +CEmptyServerPlugin::CEmptyServerPlugin() +{ + m_iClientCommandIndex = 0; +} + +CEmptyServerPlugin::~CEmptyServerPlugin() +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called when the plugin is loaded, load the interface we need from the engine +//--------------------------------------------------------------------------------- +bool CEmptyServerPlugin::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ) +{ + ConnectTier1Libraries( &interfaceFactory, 1 ); + ConnectTier2Libraries( &interfaceFactory, 1 ); + + entityinfomanager = (IEntityInfoManager *)gameServerFactory(INTERFACEVERSION_ENTITYINFOMANAGER,NULL); + if ( !entityinfomanager ) + { + Warning( "Unable to load entityinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access entity data + } + + playerinfomanager = (IPlayerInfoManager *)gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER,NULL); + if ( !playerinfomanager ) + { + Warning( "Unable to load playerinfomanager, ignoring\n" ); // this isn't fatal, we just won't be able to access specific player data + } + + botmanager = (IBotManager *)gameServerFactory(INTERFACEVERSION_PLAYERBOTMANAGER, NULL); + if ( !botmanager ) + { + Warning( "Unable to load botcontroller, ignoring\n" ); // this isn't fatal, we just won't be able to access specific bot functions + } + gameinfomanager = (IGameInfoManager *)gameServerFactory(INTERFACEVERSION_GAMEINFOMANAGER, NULL); + if (!gameinfomanager) + { + Warning( "Unable to load gameinfomanager, ignoring\n" ); + } + + engine = (IVEngineServer*)interfaceFactory(INTERFACEVERSION_VENGINESERVER, NULL); + gameeventmanager = (IGameEventManager *)interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER,NULL); + helpers = (IServerPluginHelpers*)interfaceFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, NULL); + enginetrace = (IEngineTrace *)interfaceFactory(INTERFACEVERSION_ENGINETRACE_SERVER,NULL); + randomStr = (IUniformRandomStream *)interfaceFactory(VENGINE_SERVER_RANDOM_INTERFACE_VERSION, NULL); + + // get the interfaces we want to use + if( ! ( engine && gameeventmanager && g_pFullFileSystem && helpers && enginetrace && randomStr ) ) + { + return false; // we require all these interface to function + } + + if ( playerinfomanager ) + { + gpGlobals = playerinfomanager->GetGlobalVars(); + } + + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); + ConVar_Register( 0 ); + return true; +} + +//--------------------------------------------------------------------------------- +// Purpose: called when the plugin is unloaded (turned off) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::Unload( void ) +{ + gameeventmanager->RemoveListener( this ); // make sure we are unloaded from the event system + + ConVar_Unregister( ); + DisconnectTier2Libraries( ); + DisconnectTier1Libraries( ); +} + +//--------------------------------------------------------------------------------- +// Purpose: called when the plugin is paused (i.e should stop running but isn't unloaded) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::Pause( void ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called when the plugin is unpaused (i.e should start executing again) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::UnPause( void ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: the name of this plugin, returned in "plugin_print" command +//--------------------------------------------------------------------------------- +const char *CEmptyServerPlugin::GetPluginDescription( void ) +{ + return "Emtpy-Plugin V2, Valve"; +} + +//--------------------------------------------------------------------------------- +// Purpose: called on level start +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::LevelInit( char const *pMapName ) +{ + Msg( "Level \"%s\" has been loaded\n", pMapName ); + gameeventmanager->AddListener( this, true ); +} + +//--------------------------------------------------------------------------------- +// Purpose: called on level start, when the server is ready to accept client connections +// edictCount is the number of entities in the level, clientMax is the max client count +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called once per server frame, do recurring work here (like checking for timeouts) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::GameFrame( bool simulating ) +{ + if ( simulating ) + { + Bot_RunAll(); + } +} + +//--------------------------------------------------------------------------------- +// Purpose: called on level end (as the server is shutting down or going to a new map) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::LevelShutdown( void ) // !!!!this can get called multiple times per map change +{ + gameeventmanager->RemoveListener( this ); +} + +//--------------------------------------------------------------------------------- +// Purpose: called when a client spawns into a server (i.e as they begin to play) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::ClientActive( edict_t *pEntity ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called when a client leaves a server (or is timed out) +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::ClientDisconnect( edict_t *pEntity ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called on +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::ClientPutInServer( edict_t *pEntity, char const *playername ) +{ + KeyValues *kv = new KeyValues( "msg" ); + kv->SetString( "title", "Hello" ); + kv->SetString( "msg", "Hello there" ); + kv->SetColor( "color", Color( 255, 0, 0, 255 )); + kv->SetInt( "level", 5); + kv->SetInt( "time", 10); + helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this ); + kv->deleteThis(); +} + +//--------------------------------------------------------------------------------- +// Purpose: called on level start +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::SetCommandClient( int index ) +{ + m_iClientCommandIndex = index; +} + +void ClientPrint( edict_t *pEdict, char *format, ... ) +{ + va_list argptr; + static char string[1024]; + + va_start (argptr, format); + Q_vsnprintf(string, sizeof(string), format,argptr); + va_end (argptr); + + engine->ClientPrintf( pEdict, string ); +} +//--------------------------------------------------------------------------------- +// Purpose: called on level start +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::ClientSettingsChanged( edict_t *pEdict ) +{ + if ( playerinfomanager ) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEdict ); + + const char * name = engine->GetClientConVarValue( engine->IndexOfEdict(pEdict), "name" ); + + // CAN'T use Q_stricmp here, this dll is made by 3rd parties and may not link to tier0/vstdlib + if ( playerinfo && name && playerinfo->GetName() && + stricmp( name, playerinfo->GetName()) ) // playerinfo may be NULL if the MOD doesn't support access to player data + // OR if you are accessing the player before they are fully connected + { + ClientPrint( pEdict, "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() ); + // this is the bad way to check this, the better option it to listen for the "player_changename" event in FireGameEvent() + // this is here to give a real example of how to use the playerinfo interface + } + } +} + +//--------------------------------------------------------------------------------- +// Purpose: called when a client joins a server +//--------------------------------------------------------------------------------- +PLUGIN_RESULT CEmptyServerPlugin::ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) +{ + return PLUGIN_CONTINUE; +} + +CON_COMMAND( DoAskConnect, "Server plugin example of using the ask connect dialog" ) +{ + if ( args.ArgC() < 2 ) + { + Warning ( "DoAskConnect <server IP>\n" ); + } + else + { + const char *pServerIP = args.Arg( 1 ); + + KeyValues *kv = new KeyValues( "menu" ); + kv->SetString( "title", pServerIP ); // The IP address of the server to connect to goes in the "title" field. + kv->SetInt( "time", 3 ); + + for ( int i=1; i < gpGlobals->maxClients; i++ ) + { + edict_t *pEdict = engine->PEntityOfEntIndex( i ); + if ( pEdict ) + { + helpers->CreateMessage( pEdict, DIALOG_ASKCONNECT, kv, &g_EmtpyServerPlugin ); + } + } + + kv->deleteThis(); + } +} + +#ifdef SAMPLE_TF2_PLUGIN +const char *classNames[] = +{ + "unknown", + "scout", + "sniper", + "soldier", + "demoman", + "medic", + "heavy weapons guy", + "pyro", + "spy", + "engineer", +}; + +bool TFPlayerHasCondition( int inBits, int condition ) +{ + Assert( condition >= 0 && condition < TF_COND_LAST ); + + return ( ( inBits & (1<<condition) ) != 0 ); +} + +void SentryStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Sentry Status:\n"); + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pSentry = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_SENTRY, value, emptyVariant)) + { + pSentry = engine->PEntityOfEntIndex( value.Int() ); + if (!pSentry) + { + Warning("couldn't attain sentry gun entity\n"); + return; + } + } + else + { + Msg("No Sentrygun built.\n"); + return; + + } + IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pSentry ); + if (!entinfo) + { + Warning("couldn't get entinfo for sentry gun\n"); + return; + } + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_SENTRY, value, emptyVariant)) + { + if (value.Bool()) + Msg("Sentry Under Construction...\n"); + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_UPGRADING_SENTRY, value, emptyVariant)) + { + if (value.Bool()) + Msg("Sentry Upgrading...\n"); + } + + int sentryLevel = 0; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_LEVEL, value, emptyVariant)) + { + sentryLevel = value.Int(); + Msg("Sentry Level: %i\n", sentryLevel ); + } + else + Msg("Unable to retrive sentry level\n"); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_PROGRESS, value, emptyVariant)) + { + if (sentryLevel < 3) + { + int iMetal, iRequiredMetal; + iRequiredMetal = value.Int() & 0xFF; + iMetal = (value.Int()>>8) & 0xFF; + Msg("%i / %i Metal Required for Sentry Level %i\n", iMetal, iRequiredMetal, sentryLevel+1); + } + else + Msg("Sentry cannot be upgraded further.\n"); + } + + Msg("Health: %i\n", entinfo->GetHealth() ); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_KILLS, value, emptyVariant)) + Msg("Kills: %i\n", value.Int() ); + else + Msg("Unable to retrieve sentry kills\n"); + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_SHELLS, value, emptyVariant)) + { + int iShells, iMaxShells; + iMaxShells = value.Int() & 0xFF; + iShells = (value.Int()>>8) & 0xFF; + Msg("Shells: %i / %i\n", iShells, iMaxShells); + } + if (sentryLevel > 2) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SENTRY_AMMO_ROCKETS, value, emptyVariant)) + { + int iRockets, iMaxRockets; + iMaxRockets = value.Int() & 0xFF; + iRockets = (value.Int()>>8) & 0xFF; + Msg("Rockets: %i / %i\n", iRockets, iMaxRockets); + } + } + +} +void DispenserStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Dispenser Status:\n"); + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pDispenser = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_DISPENSER, value, emptyVariant)) + { + pDispenser = engine->PEntityOfEntIndex( value.Int() ); + if (!pDispenser) + { + Warning("couldn't attain dispenser entity\n"); + return; + } + } + else + { + Msg("No dispenser built.\n"); + return; + } + IEntityInfo *entinfo = entityinfomanager->GetEntityInfo( pDispenser ); + if (!entinfo) + { + Warning("couldn't get entinfo for dispenser\n"); + return; + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_DISPENSER, value, emptyVariant)) + { + if (value.Bool()) + Msg("Dispenser Under Construction...\n"); + } + Msg("Health: %i\n", entinfo->GetHealth() ); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_DISPENSER_METAL, value, emptyVariant)) + Msg("Metal: %i\n", value.Int() ); +} +void TeleporterStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + + Msg("Teleporter Status:\n"); + + pluginvariant value; + pluginvariant emptyVariant; + edict_t *pEntrance = NULL; + edict_t *pExit = NULL; + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_ENTRANCE, value, emptyVariant)) + { + pEntrance = engine->PEntityOfEntIndex( value.Int() ); + if (!pEntrance) + { + Warning("couldn't attain entrance entity\n"); + } + } + else + { + Msg("No Teleporter Entrance built.\n"); + } + if (playerinfo->GetCustomInfo(TFPLAYERINFO_ENTINDEX_TELEPORTER_EXIT, value, emptyVariant)) + { + pExit = engine->PEntityOfEntIndex( value.Int() ); + if (!pExit) + { + Warning("couldn't attain exit entity\n"); + } + } + else + { + Msg("No Teleporter Entrance built.\n"); + } + IEntityInfo *entranceInfo = entityinfomanager->GetEntityInfo( pEntrance ); + if (!entranceInfo) + { + Warning("couldn't get entinfo for teleporter entrance\n"); + } + IEntityInfo *exitInfo = entityinfomanager->GetEntityInfo( pExit ); + if (!exitInfo) + { + Warning("couldn't get entinfo for teleporter exit\n"); + } + + if (pEntrance && entranceInfo) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_ENTRANCE, value, emptyVariant)) + { + if (value.Bool()) + Msg("Entrance Under Construction...\n"); + } + Msg("Entrance Health: %i\n", entranceInfo->GetHealth() ); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_TELEPORTER_USES, value, emptyVariant)) + Msg("Entrance Used %i Times.\n", value.Int() ); + + } + if (pExit && exitInfo) + { + if (playerinfo->GetCustomInfo(TFPLAYERINFO_BUILDING_TELEPORTER_EXIT, value, emptyVariant)) + { + if (value.Bool()) + Msg("Exit Under Construction...\n"); + } + Msg("Exit Health: %i\n", exitInfo->GetHealth() ); + } +} +void ClassStatus( edict_t *pEntity ) +{ + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + { + Msg("couldn't get playerinfo\n"); + return; + } + int playerClassId = playerinfo->GetPlayerClassId(); + + Msg("Player Class: %s\n", playerinfo->GetPlayerClassName()); + pluginvariant conditionValue; + pluginvariant emptyVariant; + if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) + { + Warning("unable to retrieve conditions!\n"); + } + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE )) + Msg("You are Invulnerable!\n"); + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT )) + Msg("You are about to Teleport.\n"); + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED )) + Msg("You have recently been teleported.\n"); + + switch(playerClassId) + { + default: + case TF_CLASS_MEDIC: + break; + case TF_CLASS_ENGINEER: + Msg("Building Information:\n"); + SentryStatus( pEntity ); + DispenserStatus( pEntity ); + TeleporterStatus( pEntity ); + break; + case TF_CLASS_SPY: + { + int disguiseClass = 0; + pluginvariant value; + + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_DISGUISEDAS, value, emptyVariant)) + disguiseClass = value.Int(); + + if ( TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ) + Msg("Disguising..\n"); + else if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ) + Msg("Disguised as: %s\n", classNames[disguiseClass] ); + + if (TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED )) + Msg("Cloaked!\n"); + if (playerinfo->GetCustomInfo(TFPLAYERINFO_SPY_CLOAKCHARGELEVEL, value, emptyVariant)) + Msg("Cloak Charge Percent: %d\n", value.Float() ); + + break; + } + case TF_CLASS_DEMOMAN: + break; + } +} +const char *ctf_flagtype[] = +{ + "ctf", //TF_FLAGTYPE_CTF = 0, + "attack / defend", //TF_FLAGTYPE_ATTACK_DEFEND, + "territory control", //TF_FLAGTYPE_TERRITORY_CONTROL, + "invade", //TF_FLAGTYPE_INVADE, + "king of the hill", //TF_FLAGTYPE_KINGOFTHEHILL, +}; +const char *ctf_flagstatus[] = +{ + "unknown", + "At Home", + "Dropped", + "Stolen", +}; +void FlagStatus( edict_t *pPlayer ) +{ + IPlayerInfo *pInfo = playerinfomanager->GetPlayerInfo( pPlayer ); + if (!pInfo) + { + Msg( "couldn't get playerinfo\n" ); + return; + } + IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); + if (!gameInfo) + { + Msg( "couldn't get gameinfo\n" ); + } + + int gameType = gameInfo->GetInfo_GameType(); + + if (gameType != 1) + { + Msg( "Game is not CTF.\n" ); + return; + } + Msg( "===============================\n" ); + Msg( "Capture The Flag -- Flag Status\n" ); + Msg( "===============================\n" ); + pluginvariant value, options; + + edict_t *pFlag = NULL; + while ( (pFlag = entityinfomanager->FindEntityByClassname(pFlag, "item_teamflag")) != NULL ) + { + IEntityInfo *pFlagInfo = entityinfomanager->GetEntityInfo( pFlag ); + if (!pFlagInfo) + continue; + + Msg( "\nTeam %s's Flag\n", gameInfo->GetInfo_GetTeamName( pFlagInfo->GetTeamIndex() ) ); + options.SetInt(engine->IndexOfEdict(pFlag)); + if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_TYPE, value, options) ) + Msg( "Type: %s\n", ctf_flagtype[value.Int()] ); + if ( gameInfo->GetInfo_Custom( TFGAMEINFO_CTF_FLAG_STATUS, value, options) ) + { + Msg( "Status: %s\n", ctf_flagstatus[value.Int()] ); + //Tony; if we're carried, find out who has us. + if (value.Int() == 3) + { + edict_t *pPlayer = pFlagInfo->GetOwner(); + if (pPlayer) + { + IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo( pPlayer ); + if (pPlayerInfo) + Msg( "Carried by: %s\n", pPlayerInfo->GetName() ); + } + } + } + } + + + Msg( "===============================\n" ); +} +#endif + +//--------------------------------------------------------------------------------- +// Purpose: called when a client types in a command (only a subset of commands however, not CON_COMMAND's) +//--------------------------------------------------------------------------------- +PLUGIN_RESULT CEmptyServerPlugin::ClientCommand( edict_t *pEntity, const CCommand &args ) +{ + const char *pcmd = args[0]; + + if ( !pEntity || pEntity->IsFree() ) + { + return PLUGIN_CONTINUE; + } + + if ( FStrEq( pcmd, "menu" ) ) + { + KeyValues *kv = new KeyValues( "menu" ); + kv->SetString( "title", "You've got options, hit ESC" ); + kv->SetInt( "level", 1 ); + kv->SetColor( "color", Color( 255, 0, 0, 255 )); + kv->SetInt( "time", 20 ); + kv->SetString( "msg", "Pick an option\nOr don't." ); + + for( int i = 1; i < 9; i++ ) + { + char num[10], msg[10], cmd[10]; + Q_snprintf( num, sizeof(num), "%i", i ); + Q_snprintf( msg, sizeof(msg), "Option %i", i ); + Q_snprintf( cmd, sizeof(cmd), "option%i", i ); + + KeyValues *item1 = kv->FindKey( num, true ); + item1->SetString( "msg", msg ); + item1->SetString( "command", cmd ); + } + + helpers->CreateMessage( pEntity, DIALOG_MENU, kv, this ); + kv->deleteThis(); + return PLUGIN_STOP; // we handled this function + } + else if ( FStrEq( pcmd, "rich" ) ) + { + KeyValues *kv = new KeyValues( "menu" ); + kv->SetString( "title", "A rich message" ); + kv->SetInt( "level", 1 ); + kv->SetInt( "time", 20 ); + kv->SetString( "msg", "This is a long long long text string.\n\nIt also has line breaks." ); + + helpers->CreateMessage( pEntity, DIALOG_TEXT, kv, this ); + kv->deleteThis(); + return PLUGIN_STOP; // we handled this function + } + else if ( FStrEq( pcmd, "msg" ) ) + { + KeyValues *kv = new KeyValues( "menu" ); + kv->SetString( "title", "Just a simple hello" ); + kv->SetInt( "level", 1 ); + kv->SetInt( "time", 20 ); + + helpers->CreateMessage( pEntity, DIALOG_MSG, kv, this ); + kv->deleteThis(); + return PLUGIN_STOP; // we handled this function + } + else if ( FStrEq( pcmd, "entry" ) ) + { + KeyValues *kv = new KeyValues( "entry" ); + kv->SetString( "title", "Stuff" ); + kv->SetString( "msg", "Enter something" ); + kv->SetString( "command", "say" ); // anything they enter into the dialog turns into a say command + kv->SetInt( "level", 1 ); + kv->SetInt( "time", 20 ); + + helpers->CreateMessage( pEntity, DIALOG_ENTRY, kv, this ); + kv->deleteThis(); + return PLUGIN_STOP; // we handled this function + } +#ifdef SAMPLE_TF2_PLUGIN + else if ( FStrEq( pcmd, "gameinfo" ) ) + { + IGameInfo *gameInfo = gameinfomanager->GetGameInfo(); + if (!gameInfo) + return PLUGIN_STOP; + + Msg("=== Game Information ===\n"); + Msg("Game Type: %i / %s\n", gameInfo->GetInfo_GameType(), gameInfo->GetInfo_GameTypeName() ); + int teamCount = gameInfo->GetInfo_GetTeamCount(); + Msg("Num Teams: %i\n", teamCount ); + + Msg("Player Counts:\n"); + for (int i = 0;i<teamCount;i++) + { + //If this failes, we can assume the rest is invalid too. + if (!gameInfo->GetInfo_GetTeamName(i) ) + continue; + Msg("Team: %s, Players: %i\n", gameInfo->GetInfo_GetTeamName(i), gameInfo->GetInfo_NumPlayersOnTeam(i) ); + } + return PLUGIN_STOP; + + } + // Sample to use the new CustomInfo added to TF2 for plugins + else if ( FStrEq( pcmd, "tfcond" ) ) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + return PLUGIN_STOP; + + pluginvariant conditionValue; + pluginvariant emptyVariant; + if (!playerinfo->GetCustomInfo(TFPLAYERINFO_CONDITIONS, conditionValue, emptyVariant)) + { + Msg("unable to retrieve conditions!\n"); + return PLUGIN_STOP; + } + + Msg("Disguising?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISING ) ? "yes" : "no" ); + Msg("Disguised?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_DISGUISED ) ? "yes" : "no" ); + Msg("Stealthed?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_STEALTHED ) ? "yes" : "no" ); + Msg("Invulnerable?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_INVULNERABLE ) ? "yes" : "no" ); + Msg("Teleported Recently?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_TELEPORTED ) ? "yes" : "no" ); + Msg("Selected for Teleportation?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_SELECTED_TO_TELEPORT ) ? "yes" : "no" ); + Msg("On Fire?: %s\n", TFPlayerHasCondition(conditionValue.Int(), TF_COND_BURNING ) ? "yes" : "no" ); + + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "sentry_status" ) ) + { + SentryStatus(pEntity); + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "class_status" ) ) + { + ClassStatus(pEntity); + return PLUGIN_STOP; + } + else if ( FStrEq( pcmd, "flag_status" ) ) + { + FlagStatus(pEntity); + return PLUGIN_STOP; + } + #ifdef GAME_DLL + else if ( FStrEq( pcmd, "cbe_test" ) ) + { + IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); + if (!playerinfo) + return PLUGIN_STOP; + + CBaseEntity *pEnt = static_cast< CBaseEntity* >(entityinfomanager->GetEntity( pEntity )); + if (pEnt) + Msg("got a pointer to CBaseEntity..\n"); + Msg("attempting to print this entities modelname directly..\n"); + + Msg("ModelName: %s\n", STRING(pEnt->GetModelName()) ); + + return PLUGIN_STOP; + } + #endif +#endif + + + return PLUGIN_CONTINUE; +} + +//--------------------------------------------------------------------------------- +// Purpose: called when a client is authenticated +//--------------------------------------------------------------------------------- +PLUGIN_RESULT CEmptyServerPlugin::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) +{ + return PLUGIN_CONTINUE; +} + +//--------------------------------------------------------------------------------- +// Purpose: called when a cvar value query is finished +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) +{ + Msg( "Cvar query (cookie: %d, status: %d) - name: %s, value: %s\n", iCookie, eStatus, pCvarName, pCvarValue ); +} +void CEmptyServerPlugin::OnEdictAllocated( edict_t *edict ) +{ +} +void CEmptyServerPlugin::OnEdictFreed( const edict_t *edict ) +{ +} + +//--------------------------------------------------------------------------------- +// Purpose: called when an event is fired +//--------------------------------------------------------------------------------- +void CEmptyServerPlugin::FireGameEvent( KeyValues * event ) +{ + const char * name = event->GetName(); + Msg( "CEmptyServerPlugin::FireGameEvent: Got event \"%s\"\n", name ); +} + +//--------------------------------------------------------------------------------- +// Purpose: an example of how to implement a new command +//--------------------------------------------------------------------------------- +CON_COMMAND( empty_version, "prints the version of the empty plugin" ) +{ + Msg( "Version:2.0.0.0\n" ); +} + +CON_COMMAND( empty_log, "logs the version of the empty plugin" ) +{ + engine->LogPrint( "Version:2.0.0.0\n" ); +} + +//--------------------------------------------------------------------------------- +// Purpose: an example cvar +//--------------------------------------------------------------------------------- +static ConVar empty_cvar("plugin_empty", "0", FCVAR_NOTIFY, "Example plugin cvar"); |