Simple entity for the Source Engine to log and send gameplay statistics.
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======== | |
// | |
// Purpose: Simple entity to log and send gameplay statistics | |
// | |
//============================================================================= | |
#include "cbase.h" | |
#include "vstdlib/jobthread.h" | |
#include "curl/curl.h" | |
#include "steam\steam_api.h" | |
#include "view_shared.h" | |
#include <time.h> | |
#include "GameEventListener.h" | |
// memdbgon must be the last include file in a .cpp file!!! | |
#include "tier0/memdbgon.h" | |
#define ENDPOINT "http://example.com/collector.php?collect" | |
ConVar stats_enabled( "stats_enabled", "-1", FCVAR_ARCHIVE); | |
class CStatisticsCollector : public CLogicalEntity, public CGameEventListener | |
{ | |
public: | |
DECLARE_CLASS( CStatisticsCollector, CLogicalEntity ); | |
DECLARE_DATADESC(); | |
CStatisticsCollector() | |
{ | |
ListenForGameEvent("player_hurt"); | |
} | |
void FireGameEvent( IGameEvent* e ); | |
void Init(); | |
void GameEvent(); | |
void SendStatistic( const tchar *m_event ); | |
void InputSendStatistic( inputdata_t &inputData ); | |
void cURLThread(const tchar *m_event); | |
}; | |
LINK_ENTITY_TO_CLASS( statistics_collector, CStatisticsCollector ); | |
BEGIN_DATADESC( CStatisticsCollector ) | |
DEFINE_INPUTFUNC( FIELD_STRING, "Event", InputSendStatistic ) | |
END_DATADESC() | |
void CStatisticsCollector::FireGameEvent( IGameEvent* e ) | |
{ | |
CBasePlayer *player = UTIL_GetLocalPlayer(); | |
if ( Q_strcmp( "player_hurt", e->GetName() ) && player->GetHealth() == 0 ) | |
{ | |
// The player has unfortunately passed away | |
this->SendStatistic("player_death"); | |
} | |
} | |
void CStatisticsCollector::cURLThread(const char *m_event) | |
{ | |
DevMsg("Statistics Collectior: Sending event '%s'\n", m_event); | |
CBasePlayer *player = UTIL_GetLocalPlayer(); | |
const Vector player_pos = player->GetAbsOrigin(); | |
uint32 steam_id; | |
ISteamUser* steam_user = steamapicontext->SteamUser(); | |
if(steam_user->BLoggedOn()) | |
{ | |
steam_id = steam_user->GetSteamID().GetAccountID(); | |
} | |
else | |
{ | |
// Just in case someone isn't logged in. Yarr, pirate Steam | |
steam_id = 0; | |
} | |
time_t aclock; | |
time( &aclock ); | |
struct tm *newtime = localtime( &aclock ); | |
char timeString[128]; | |
Q_strncpy( timeString, asctime( newtime ), sizeof( timeString ) ); | |
// Get rid of the \n. | |
char *pEnd = strstr( timeString, "\n" ); | |
if ( pEnd ) | |
{ | |
*pEnd = 0; | |
} | |
char full_url[512]; | |
Q_snprintf(full_url, 512, "%s&e=%s&s=%i&p=%.2f,%.2f,%.2f&h=%i&d=%s&m=%s", | |
ENDPOINT, m_event, steam_id, player_pos.x, player_pos.y, player_pos.z, player->GetHealth(), timeString, gpGlobals->mapname.ToCStr() | |
); | |
CBaseCombatWeapon *weapon = player->GetActiveWeapon(); | |
if(weapon) | |
{ | |
Q_snprintf(full_url, 512, "%s&w=%s", full_url, weapon->GetClassname()); | |
} | |
DevMsg("Statistics Collectior: GET %s\n", full_url); | |
CURL *curl; | |
curl = curl_easy_init(); | |
curl_easy_setopt(curl, CURLOPT_URL, full_url); | |
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); | |
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); | |
curl_easy_perform(curl); | |
curl_easy_cleanup(curl); | |
DevMsg("Statistics Collectior: Event sent.\n"); | |
} | |
void CStatisticsCollector::SendStatistic( const char *m_event ) | |
{ | |
if(stats_enabled.GetInt() > 0) | |
{ | |
DevMsg("Statistics Collectior: cURL thread queued.\n"); | |
ThreadExecute(this, &CStatisticsCollector::cURLThread, m_event); | |
} | |
else | |
{ | |
DevMsg("Statistics Collectior: Events disabled, ignoring.\n"); | |
} | |
} | |
void CStatisticsCollector::InputSendStatistic( inputdata_t &inputData ) | |
{ | |
this->SendStatistic(inputData.value.String()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment