You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.5 KiB
277 lines
7.5 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
#include "cbase.h"
|
|
|
|
#include "cs_app_lifetime_gamestats.h"
|
|
#include "steamworks_gamestats.h"
|
|
#include "steam/isteamutils.h"
|
|
#include "csgo_serialnumbersequence.h"
|
|
|
|
#include "gametypes.h"
|
|
#include "matchmaking/imatchframework.h"
|
|
|
|
#include "cs_gamerules.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
extern IGameTypes *g_pGameTypes;
|
|
|
|
ConVar cl_debug_client_gamestats( "cl_debug_client_gamestats", "1" );
|
|
|
|
static CS_App_Lifetime_Gamestats g_CSAppLifetimeGamestats;
|
|
CS_App_Lifetime_Gamestats* CSAppLifetimeGameStats() { return &g_CSAppLifetimeGamestats; }
|
|
|
|
uint16 CS_App_Lifetime_Gamestats::m_unEventCount = 0;
|
|
|
|
const char* g_szValidUIEvents [] =
|
|
{
|
|
"ServerBrowserLAN",
|
|
"ServerBrowserFriends",
|
|
"ServerBrowserJoinFriend",
|
|
"ServerBrowserUnknownJoinType",
|
|
"ServerBrowserFavorites",
|
|
"ServerBrowserHistory",
|
|
"ServerBrowserSpectator",
|
|
"ServerBrowserInternet",
|
|
"ServerBrowserUnknownPageType",
|
|
"ServerBrowserJoinByIP",
|
|
"HLTVConnectRelay",
|
|
"CommunityQuickPlay",
|
|
"ConnectStringOnCommandline",
|
|
"PurchaseEventRequired",
|
|
"PurchaseEventMinutesPlayed",
|
|
"PurchaseEventNoMinutesPlayed",
|
|
"PurchaseEventStash",
|
|
"InventoryEquipMainMenu",
|
|
"InventoryEquipConnectedActive",
|
|
"InventoryEquipConnectedInactive",
|
|
"CrateUnlockMainMenu",
|
|
"CrateUnlockConnected",
|
|
"WeaponInspectMainMenuDefault",
|
|
"WeaponInspectMainMenuPainted",
|
|
"WeaponInspectConnectedDefault",
|
|
"WeaponInspectConnectedPainted",
|
|
"WorkshopWeaponPreview",
|
|
"MatchDownloadAttempt",
|
|
"WatchLiveMatch",
|
|
"WatchDownloadedMatch",
|
|
"WatchGOTVTheater",
|
|
"WatchTwitchStream",
|
|
"WeaponInspectExternalItem",
|
|
"ViewedOffers",
|
|
"BorrowedMusicKit",
|
|
"ViewOnMarket",
|
|
"InsufficientLevel",
|
|
"PartyBrowserRefreshEmpty",
|
|
"PartyBrowserRefreshResults",
|
|
"PartyBrowserJoin",
|
|
"FriendJoin",
|
|
"SoloSearch",
|
|
"WatchEmbeddedStreamExternally",
|
|
"PartyBrowserJoinNearby",
|
|
"SwitchedToHRTFEnabled",
|
|
"SwitchedToHRTFDisabled",
|
|
"PartyBrowserJoinInvited",
|
|
};
|
|
|
|
ConVar steamworks_sessionid_lifetime_client( "steamworks_sessionid_lifetime_client", "0", FCVAR_HIDDEN, "The full client session ID for the new steamworks gamestats." );
|
|
|
|
|
|
CS_App_Lifetime_Gamestats::CS_App_Lifetime_Gamestats() :
|
|
BaseClass( "CS_App_Lifetime_Gamestats", "steamworks_sessionid_lifetime_client" ),
|
|
m_GameJoinRequested( this, &CS_App_Lifetime_Gamestats::OnGameJoinRequested )
|
|
{
|
|
}
|
|
|
|
|
|
bool CS_App_Lifetime_Gamestats::Init()
|
|
{
|
|
if ( !BaseClass::Init() )
|
|
return false;
|
|
|
|
StartSession();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::Shutdown()
|
|
{
|
|
WriteStats();
|
|
EndSession();
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::WriteStats( void )
|
|
{
|
|
// Refresh the interface in case steam has unloaded
|
|
m_SteamWorksInterface = GetInterface();
|
|
|
|
if ( !m_SteamWorksInterface )
|
|
{
|
|
DevMsg( "WARNING: Attempted to send a steamworks gamestats row when the steamworks interface was not available!" );
|
|
}
|
|
else
|
|
{
|
|
WriteUIEvents();
|
|
WriteGameJoins();
|
|
}
|
|
}
|
|
|
|
EResult CS_App_Lifetime_Gamestats::WriteUIEvents()
|
|
{
|
|
FOR_EACH_VEC( m_vecUIEvents, i )
|
|
{
|
|
uint64 iTableID = 0;
|
|
m_SteamWorksInterface->AddNewRow( &iTableID, m_SessionID, "CSGOUIEvent" );
|
|
if ( !iTableID )
|
|
return k_EResultFail;
|
|
|
|
UIEvent_t *pData = &m_vecUIEvents[i];
|
|
|
|
WriteStringToTable( pData->strEventID.Access(), iTableID, "EventID" );
|
|
WriteIntToTable( pData->unCount, iTableID, "EventCount" );
|
|
WriteIntToTable( pData->unTime, iTableID, "TimeSubmitted" );
|
|
|
|
if ( cl_debug_client_gamestats.GetBool() )
|
|
{
|
|
Msg( "Steamworks gamestats: %s adding UI data %s id=%d time=%d\n", Name(), pData->strEventID.Get(), pData->unCount, pData->unTime );
|
|
}
|
|
|
|
EResult res = m_SteamWorksInterface->CommitRow( iTableID );
|
|
if ( res != k_EResultOK )
|
|
{
|
|
char pzMessage[MAX_PATH] = {0};
|
|
V_snprintf( pzMessage, ARRAYSIZE(pzMessage), "Failed To Submit table %s", "CSUIEvent" );
|
|
Assert( pzMessage );
|
|
return res;
|
|
}
|
|
}
|
|
m_vecUIEvents.RemoveAll();
|
|
return k_EResultOK;
|
|
}
|
|
|
|
EResult CS_App_Lifetime_Gamestats::WriteGameJoins()
|
|
{
|
|
FOR_EACH_VEC( m_vecGameJoins, i )
|
|
{
|
|
uint64 iTableID = 0;
|
|
m_SteamWorksInterface->AddNewRow( &iTableID, m_SessionID, "CSGOGameJoin" );
|
|
if ( !iTableID )
|
|
return k_EResultFail;
|
|
|
|
uint64 ullGameSessionID = m_vecGameJoins[i].ullSessionID;
|
|
uint16 unGameType = (uint16)m_vecGameJoins[i].unGameType;
|
|
uint16 unGameMode = (uint16)m_vecGameJoins[i].unGameMode;
|
|
bool bValveOfficial = m_vecGameJoins[i].bIsValveOfficial;
|
|
|
|
WriteInt64ToTable( ullGameSessionID, iTableID, "GameSessionID" );
|
|
WriteIntToTable( unGameType, iTableID, "GameTypeID" );
|
|
WriteIntToTable( unGameMode, iTableID, "GameModeID" );
|
|
WriteIntToTable( bValveOfficial, iTableID, "IsValveOfficial" );
|
|
|
|
if ( cl_debug_client_gamestats.GetBool() )
|
|
{
|
|
Msg( "Steamworks gamestats: %s adding game session %llu", Name(), ullGameSessionID );
|
|
}
|
|
|
|
EResult res = m_SteamWorksInterface->CommitRow( iTableID );
|
|
if ( res != k_EResultOK )
|
|
{
|
|
char pzMessage[MAX_PATH] = {0};
|
|
V_snprintf( pzMessage, ARRAYSIZE(pzMessage), "Failed To Submit table %s", "CSGOGameJoin" );
|
|
Assert( pzMessage );
|
|
return res;
|
|
}
|
|
}
|
|
m_vecGameJoins.RemoveAll();
|
|
return k_EResultOK;
|
|
}
|
|
|
|
static bool BHelperCheckSafeUserCmdString( char const *ipconnect )
|
|
{
|
|
bool bConnectValid = true;
|
|
while ( *ipconnect )
|
|
{
|
|
if ( ( ( *ipconnect >= '0' ) && ( *ipconnect <= '9' ) ) ||
|
|
( ( *ipconnect >= 'a' ) && ( *ipconnect <= 'z' ) ) ||
|
|
( ( *ipconnect >= 'A' ) && ( *ipconnect <= 'Z' ) ) ||
|
|
( *ipconnect == '_' ) || ( *ipconnect == '-' ) || ( *ipconnect == '.' ) ||
|
|
( *ipconnect == ':' ) || ( *ipconnect == '?' ) || ( *ipconnect == '%' ) ||
|
|
( *ipconnect == '/' ) || ( *ipconnect == '=' ) || ( *ipconnect == ' ' ) ||
|
|
( *ipconnect == '[' ) || ( *ipconnect == ']' ) || ( *ipconnect == '@' ) ||
|
|
( *ipconnect == '"' ) || ( *ipconnect == '\'' ) || ( *ipconnect == '#' ) ||
|
|
( *ipconnect == '(' ) || ( *ipconnect == ')' ) || ( *ipconnect == '!' ) ||
|
|
( *ipconnect == '\\' ) || ( *ipconnect == '$' )
|
|
)
|
|
++ipconnect;
|
|
else
|
|
{
|
|
bConnectValid = false;
|
|
break;
|
|
}
|
|
}
|
|
return bConnectValid;
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::OnGameJoinRequested( GameRichPresenceJoinRequested_t *pCallback )
|
|
{
|
|
/* Removed for partner depot */
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::RecordUIEvent( const char* szEventName )
|
|
{
|
|
if ( m_unEventCount == (uint16)-1 )
|
|
return;
|
|
|
|
bool bFound = false;
|
|
for ( int i = 0; i < ARRAYSIZE( g_szValidUIEvents ); ++i )
|
|
{
|
|
if ( V_strcmp( g_szValidUIEvents[i], szEventName) == 0 )
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Only record whitelisted events
|
|
if ( !bFound )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Assert( V_strlen( szEventName ) < UI_EVENT_NAME_MAX );
|
|
|
|
uint16 idx = m_vecUIEvents.AddToTail();
|
|
m_vecUIEvents[idx].unCount = ++m_unEventCount;
|
|
CRTime now;
|
|
m_vecUIEvents[idx].unTime = now.GetRTime32();
|
|
m_vecUIEvents[idx].strEventID.Set( szEventName );
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::AddSessionIDsToTable( int iTableID )
|
|
{
|
|
// Our client side session.
|
|
WriteInt64ToTable( m_SessionID, iTableID, "SessionID" );
|
|
}
|
|
|
|
void CS_App_Lifetime_Gamestats::RecordGameJoin( uint64 ullSessionID )
|
|
{
|
|
GameJoins_t gameJoinInfo;
|
|
gameJoinInfo.ullSessionID = ullSessionID;
|
|
gameJoinInfo.unGameMode = g_pGameTypes->GetCurrentGameMode();
|
|
gameJoinInfo.unGameType = g_pGameTypes->GetCurrentGameType();
|
|
gameJoinInfo.bIsValveOfficial = CSGameRules() && CSGameRules()->IsValveDS();
|
|
|
|
if ( m_vecGameJoins.Find( gameJoinInfo ) == m_vecGameJoins.InvalidIndex() )
|
|
{
|
|
m_vecGameJoins.AddToTail( gameJoinInfo );
|
|
}
|
|
else
|
|
{
|
|
Assert( 0 ); // Attempting double add-- would cause PK violation.
|
|
}
|
|
}
|