mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-11-23 19:25:35 +08:00
implement isteamgamestats
This commit is contained in:
parent
3124997cc5
commit
d1d5416d62
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
#include "steam_gameserver.h"
|
#include "steam_gameserver.h"
|
||||||
#include "steam_gameserverstats.h"
|
#include "steam_gameserverstats.h"
|
||||||
|
#include "steam_gamestats.h"
|
||||||
#include "steam_masterserver_updater.h"
|
#include "steam_masterserver_updater.h"
|
||||||
|
|
||||||
#include "overlay/steam_overlay.h"
|
#include "overlay/steam_overlay.h"
|
||||||
@ -136,6 +137,7 @@ public:
|
|||||||
Steam_Parties *steam_parties{};
|
Steam_Parties *steam_parties{};
|
||||||
Steam_RemotePlay *steam_remoteplay{};
|
Steam_RemotePlay *steam_remoteplay{};
|
||||||
Steam_TV *steam_tv{};
|
Steam_TV *steam_tv{};
|
||||||
|
Steam_GameStats *steam_gamestats{};
|
||||||
|
|
||||||
Steam_GameServer *steam_gameserver{};
|
Steam_GameServer *steam_gameserver{};
|
||||||
Steam_Utils *steam_gameserver_utils{};
|
Steam_Utils *steam_gameserver_utils{};
|
||||||
@ -231,6 +233,9 @@ public:
|
|||||||
// user screenshots
|
// user screenshots
|
||||||
ISteamScreenshots *GetISteamScreenshots( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion );
|
ISteamScreenshots *GetISteamScreenshots( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion );
|
||||||
|
|
||||||
|
// game stats
|
||||||
|
ISteamGameStats *GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );
|
||||||
|
|
||||||
|
|
||||||
// Deprecated. Applications should use SteamAPI_RunCallbacks() or SteamGameServer_RunCallbacks() instead.
|
// Deprecated. Applications should use SteamAPI_RunCallbacks() or SteamGameServer_RunCallbacks() instead.
|
||||||
STEAM_PRIVATE_API( void RunFrame() );
|
STEAM_PRIVATE_API( void RunFrame() );
|
||||||
|
117
dll/dll/steam_gamestats.h
Normal file
117
dll/dll/steam_gamestats.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#ifndef __INCLUDED_STEAM_GAMESTATS_H__
|
||||||
|
#define __INCLUDED_STEAM_GAMESTATS_H__
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Functions for recording game play sessions and details thereof
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class Steam_GameStats :
|
||||||
|
public ISteamGameStats
|
||||||
|
{
|
||||||
|
enum class AttributeType_t
|
||||||
|
{
|
||||||
|
Int, Str, Float, Int64,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Attribute_t
|
||||||
|
{
|
||||||
|
AttributeType_t type{};
|
||||||
|
union {
|
||||||
|
int32 n_data;
|
||||||
|
std::string s_data;
|
||||||
|
float f_data;
|
||||||
|
int64 ll_data{};
|
||||||
|
};
|
||||||
|
|
||||||
|
Attribute_t();
|
||||||
|
Attribute_t(const Attribute_t &other);
|
||||||
|
Attribute_t(Attribute_t &&other);
|
||||||
|
~Attribute_t();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Row_t
|
||||||
|
{
|
||||||
|
bool committed = false;
|
||||||
|
std::map<std::string, Attribute_t> attributes{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Table_t
|
||||||
|
{
|
||||||
|
std::vector<Row_t> rows{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Session_t
|
||||||
|
{
|
||||||
|
EGameStatsAccountType nAccountType{};
|
||||||
|
RTime32 rtTimeStarted{};
|
||||||
|
RTime32 rtTimeEnded{};
|
||||||
|
int nReasonCode{};
|
||||||
|
bool ended = false;
|
||||||
|
std::map<std::string, Attribute_t> attributes{};
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, Table_t>> tables{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Settings *settings{};
|
||||||
|
class Networking *network{};
|
||||||
|
class SteamCallResults *callback_results{};
|
||||||
|
class SteamCallBacks *callbacks{};
|
||||||
|
class RunEveryRunCB *run_every_runcb{};
|
||||||
|
|
||||||
|
std::vector<Session_t> sessions{};
|
||||||
|
|
||||||
|
|
||||||
|
bool valid_stats_account_type(int8 nAccountType);
|
||||||
|
Table_t *get_or_create_session_table(Session_t &session, const char *table_name);
|
||||||
|
Attribute_t *get_or_create_session_att(const char *att_name, Session_t &session, AttributeType_t type_if_create);
|
||||||
|
Attribute_t *get_or_create_row_att(uint64 ulRowID, const char *att_name, Table_t &table, AttributeType_t type_if_create);
|
||||||
|
|
||||||
|
void steam_run_callback();
|
||||||
|
|
||||||
|
// user connect/disconnect
|
||||||
|
void network_callback_low_level(Common_Message *msg);
|
||||||
|
|
||||||
|
static void steam_gamestats_network_low_level(void *object, Common_Message *msg);
|
||||||
|
static void steam_gamestats_run_every_runcb(void *object);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Steam_GameStats(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb);
|
||||||
|
~Steam_GameStats();
|
||||||
|
|
||||||
|
SteamAPICall_t GetNewSession( int8 nAccountType, uint64 ulAccountID, int32 nAppID, RTime32 rtTimeStarted );
|
||||||
|
SteamAPICall_t EndSession( uint64 ulSessionID, RTime32 rtTimeEnded, int nReasonCode );
|
||||||
|
EResult AddSessionAttributeInt( uint64 ulSessionID, const char* pstrName, int32 nData );
|
||||||
|
EResult AddSessionAttributeString( uint64 ulSessionID, const char* pstrName, const char *pstrData );
|
||||||
|
EResult AddSessionAttributeFloat( uint64 ulSessionID, const char* pstrName, float fData );
|
||||||
|
|
||||||
|
EResult AddNewRow( uint64 *pulRowID, uint64 ulSessionID, const char *pstrTableName );
|
||||||
|
EResult CommitRow( uint64 ulRowID );
|
||||||
|
EResult CommitOutstandingRows( uint64 ulSessionID );
|
||||||
|
EResult AddRowAttributeInt( uint64 ulRowID, const char *pstrName, int32 nData );
|
||||||
|
EResult AddRowAtributeString( uint64 ulRowID, const char *pstrName, const char *pstrData );
|
||||||
|
EResult AddRowAttributeFloat( uint64 ulRowID, const char *pstrName, float fData );
|
||||||
|
|
||||||
|
EResult AddSessionAttributeInt64( uint64 ulSessionID, const char *pstrName, int64 llData );
|
||||||
|
EResult AddRowAttributeInt64( uint64 ulRowID, const char *pstrName, int64 llData );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __INCLUDED_STEAM_GAMESTATS_H__
|
@ -122,6 +122,7 @@ Steam_Client::Steam_Client()
|
|||||||
steam_parties = new Steam_Parties(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_parties = new Steam_Parties(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
steam_remoteplay = new Steam_RemotePlay(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_remoteplay = new Steam_RemotePlay(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
steam_tv = new Steam_TV(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_tv = new Steam_TV(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
|
steam_gamestats = new Steam_GameStats(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
|
|
||||||
// server
|
// server
|
||||||
PRINT_DEBUG("init gameserver");
|
PRINT_DEBUG("init gameserver");
|
||||||
@ -200,6 +201,7 @@ Steam_Client::~Steam_Client()
|
|||||||
DEL_INST(steam_parties);
|
DEL_INST(steam_parties);
|
||||||
DEL_INST(steam_remoteplay);
|
DEL_INST(steam_remoteplay);
|
||||||
DEL_INST(steam_tv);
|
DEL_INST(steam_tv);
|
||||||
|
DEL_INST(steam_gamestats);
|
||||||
|
|
||||||
DEL_INST(steam_utils);
|
DEL_INST(steam_utils);
|
||||||
DEL_INST(steam_friends);
|
DEL_INST(steam_friends);
|
||||||
|
@ -18,6 +18,19 @@
|
|||||||
#include "dll/steam_client.h"
|
#include "dll/steam_client.h"
|
||||||
|
|
||||||
|
|
||||||
|
// retrieves the ISteamGameStats interface associated with the handle
|
||||||
|
ISteamGameStats *Steam_Client::GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s", pchVersion);
|
||||||
|
if (!steam_pipes.count(hSteamPipe) || !hSteamUser) return nullptr;
|
||||||
|
|
||||||
|
if (strcmp(pchVersion, STEAMGAMESTATS_INTERFACE_VERSION) == 0) {
|
||||||
|
return reinterpret_cast<ISteamGameStats *>(static_cast<ISteamGameStats *>(steam_gamestats));
|
||||||
|
}
|
||||||
|
|
||||||
|
report_missing_impl_and_exit(pchVersion, EMU_FUNC_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
// retrieves the ISteamUser interface associated with the handle
|
// retrieves the ISteamUser interface associated with the handle
|
||||||
ISteamUser *Steam_Client::GetISteamUser( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
ISteamUser *Steam_Client::GetISteamUser( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
||||||
{
|
{
|
||||||
@ -332,6 +345,8 @@ void *Steam_Client::GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe
|
|||||||
return GetISteamGameServerStats(hSteamUser, hSteamPipe, pchVersion);
|
return GetISteamGameServerStats(hSteamUser, hSteamPipe, pchVersion);
|
||||||
} else if (strstr(pchVersion, "SteamGameServer") == pchVersion) {
|
} else if (strstr(pchVersion, "SteamGameServer") == pchVersion) {
|
||||||
return GetISteamGameServer(hSteamUser, hSteamPipe, pchVersion);
|
return GetISteamGameServer(hSteamUser, hSteamPipe, pchVersion);
|
||||||
|
} else if (strstr(pchVersion, "SteamGameStats") == pchVersion) {
|
||||||
|
return GetISteamGameStats(hSteamUser, hSteamPipe, pchVersion);
|
||||||
} else if (strstr(pchVersion, "SteamMatchMakingServers") == pchVersion) {
|
} else if (strstr(pchVersion, "SteamMatchMakingServers") == pchVersion) {
|
||||||
return GetISteamMatchmakingServers(hSteamUser, hSteamPipe, pchVersion);
|
return GetISteamMatchmakingServers(hSteamUser, hSteamPipe, pchVersion);
|
||||||
} else if (strstr(pchVersion, "SteamMatchMaking") == pchVersion) {
|
} else if (strstr(pchVersion, "SteamMatchMaking") == pchVersion) {
|
||||||
|
474
dll/steam_gamestats.cpp
Normal file
474
dll/steam_gamestats.cpp
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
There are no public docs about this interface, this implementation
|
||||||
|
is an imagination of how it might have been implemented
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dll/steam_gamestats.h"
|
||||||
|
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t::Attribute_t()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t::Attribute_t(const Attribute_t &other)
|
||||||
|
{
|
||||||
|
type = other.type;
|
||||||
|
switch (other.type)
|
||||||
|
{
|
||||||
|
case AttributeType_t::Int: n_data = other.n_data; break;
|
||||||
|
case AttributeType_t::Str: s_data = other.s_data; break;
|
||||||
|
case AttributeType_t::Float: f_data = other.f_data; break;
|
||||||
|
case AttributeType_t::Int64: ll_data = other.ll_data; break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t::Attribute_t(Attribute_t &&other)
|
||||||
|
{
|
||||||
|
type = other.type;
|
||||||
|
switch (other.type)
|
||||||
|
{
|
||||||
|
case AttributeType_t::Int: n_data = other.n_data; break;
|
||||||
|
case AttributeType_t::Str: s_data = std::move(other.s_data); break;
|
||||||
|
case AttributeType_t::Float: f_data = other.f_data; break;
|
||||||
|
case AttributeType_t::Int64: ll_data = other.ll_data; break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t::~Attribute_t()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_GameStats::steam_gamestats_network_low_level(void *object, Common_Message *msg)
|
||||||
|
{
|
||||||
|
//PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto inst = (Steam_GameStats *)object;
|
||||||
|
inst->network_callback_low_level(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_GameStats::steam_gamestats_run_every_runcb(void *object)
|
||||||
|
{
|
||||||
|
//PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto inst = (Steam_GameStats *)object;
|
||||||
|
inst->steam_run_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Steam_GameStats(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb)
|
||||||
|
{
|
||||||
|
this->settings = settings;
|
||||||
|
this->network = network;
|
||||||
|
this->callback_results = callback_results;
|
||||||
|
this->callbacks = callbacks;
|
||||||
|
this->run_every_runcb = run_every_runcb;
|
||||||
|
|
||||||
|
this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_GameStats::steam_gamestats_network_low_level, this);
|
||||||
|
this->run_every_runcb->add(&Steam_GameStats::steam_gamestats_run_every_runcb, this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::~Steam_GameStats()
|
||||||
|
{
|
||||||
|
this->network->rmCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_GameStats::steam_gamestats_network_low_level, this);
|
||||||
|
this->run_every_runcb->remove(&Steam_GameStats::steam_gamestats_run_every_runcb, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Steam_GameStats::valid_stats_account_type(int8 nAccountType)
|
||||||
|
{
|
||||||
|
switch ((EGameStatsAccountType)nAccountType) {
|
||||||
|
case EGameStatsAccountType::k_EGameStatsAccountType_Steam:
|
||||||
|
case EGameStatsAccountType::k_EGameStatsAccountType_Xbox:
|
||||||
|
case EGameStatsAccountType::k_EGameStatsAccountType_SteamGameServer:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Table_t *Steam_GameStats::get_or_create_session_table(Session_t &session, const char *table_name)
|
||||||
|
{
|
||||||
|
Table_t *table{};
|
||||||
|
{
|
||||||
|
auto table_it = std::find_if(session.tables.rbegin(), session.tables.rend(), [=](const std::pair<std::string, Table_t> &item){ return item.first == table_name; });
|
||||||
|
if (session.tables.rend() == table_it) {
|
||||||
|
session.tables.emplace_back(std::pair<std::string, Table_t>{});
|
||||||
|
table = &session.tables.back().second;
|
||||||
|
} else {
|
||||||
|
table = &table_it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t *Steam_GameStats::get_or_create_session_att(const char *att_name, Session_t &session, AttributeType_t type_if_create)
|
||||||
|
{
|
||||||
|
Attribute_t *att{};
|
||||||
|
{
|
||||||
|
auto att_itr = session.attributes.find(att_name);
|
||||||
|
if (att_itr != session.attributes.end()) {
|
||||||
|
att = &att_itr->second;
|
||||||
|
} else {
|
||||||
|
att = &session.attributes[att_name];
|
||||||
|
att->type = type_if_create;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return att;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_GameStats::Attribute_t *Steam_GameStats::get_or_create_row_att(uint64 ulRowID, const char *att_name, Table_t &table, AttributeType_t type_if_create)
|
||||||
|
{
|
||||||
|
Attribute_t *att{};
|
||||||
|
{
|
||||||
|
auto &row = table.rows[ulRowID];
|
||||||
|
auto att_itr = row.attributes.find(att_name);
|
||||||
|
if (att_itr != row.attributes.end()) {
|
||||||
|
att = &att_itr->second;
|
||||||
|
} else {
|
||||||
|
att = &row.attributes[att_name];
|
||||||
|
att->type = type_if_create;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return att;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SteamAPICall_t Steam_GameStats::GetNewSession( int8 nAccountType, uint64 ulAccountID, int32 nAppID, RTime32 rtTimeStarted )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%i, %llu, %i, %u", (int)nAccountType, ulAccountID, nAppID, rtTimeStarted);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if ((settings->get_local_steam_id().ConvertToUint64() != ulAccountID) ||
|
||||||
|
(nAppID < 0) ||
|
||||||
|
(settings->get_local_game_id().AppID() != (uint32)nAppID) ||
|
||||||
|
!valid_stats_account_type(nAccountType)) {
|
||||||
|
GameStatsSessionIssued_t data_invalid{};
|
||||||
|
data_invalid.m_bCollectingAny = false;
|
||||||
|
data_invalid.m_bCollectingDetails = false;
|
||||||
|
data_invalid.m_eResult = EResult::k_EResultInvalidParam;
|
||||||
|
data_invalid.m_ulSessionID = 0;
|
||||||
|
|
||||||
|
auto ret = callback_results->addCallResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
// the function returns SteamAPICall_t (call result), but in isteamstats.h you can see that a callback is also expected
|
||||||
|
callbacks->addCBResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Session_t new_session{};
|
||||||
|
new_session.nAccountType = (EGameStatsAccountType)nAccountType;
|
||||||
|
new_session.rtTimeStarted = rtTimeStarted;
|
||||||
|
sessions.emplace_back(new_session);
|
||||||
|
|
||||||
|
GameStatsSessionIssued_t data{};
|
||||||
|
data.m_bCollectingAny = true; // TODO is this correct?
|
||||||
|
data.m_bCollectingDetails = true; // TODO is this correct?
|
||||||
|
data.m_eResult = EResult::k_EResultOK;
|
||||||
|
data.m_ulSessionID = (uint64)sessions.size(); // I don't know if 0 is a bad value, so always send count (index + 1)
|
||||||
|
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
// the function returns SteamAPICall_t (call result), but in isteamstats.h you can see that a callback is also expected
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamAPICall_t Steam_GameStats::EndSession( uint64 ulSessionID, RTime32 rtTimeEnded, int nReasonCode )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, %u, %i", ulSessionID, rtTimeEnded, nReasonCode);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size()) {
|
||||||
|
GameStatsSessionClosed_t data_invalid{};
|
||||||
|
data_invalid.m_eResult = EResult::k_EResultInvalidParam;
|
||||||
|
data_invalid.m_ulSessionID = ulSessionID;
|
||||||
|
|
||||||
|
auto ret = callback_results->addCallResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
// the function returns SteamAPICall_t (call result), but in isteamstats.h you can see that a callback is also expected
|
||||||
|
callbacks->addCBResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) {
|
||||||
|
GameStatsSessionClosed_t data_invalid{};
|
||||||
|
data_invalid.m_eResult = EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
data_invalid.m_ulSessionID = ulSessionID;
|
||||||
|
|
||||||
|
auto ret = callback_results->addCallResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
// the function returns SteamAPICall_t (call result), but in isteamstats.h you can see that a callback is also expected
|
||||||
|
callbacks->addCBResult(data_invalid.k_iCallback, &data_invalid, sizeof(data_invalid));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.ended = true;
|
||||||
|
session.rtTimeEnded = rtTimeEnded;
|
||||||
|
session.nReasonCode = nReasonCode;
|
||||||
|
|
||||||
|
GameStatsSessionClosed_t data{};
|
||||||
|
data.m_eResult = EResult::k_EResultOK;
|
||||||
|
data.m_ulSessionID = ulSessionID;
|
||||||
|
|
||||||
|
auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
// the function returns SteamAPICall_t (call result), but in isteamstats.h you can see that a callback is also expected
|
||||||
|
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddSessionAttributeInt( uint64 ulSessionID, const char* pstrName, int32 nData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %i", ulSessionID, pstrName, nData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size() || !pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_session_att(pstrName, session, AttributeType_t::Int);
|
||||||
|
if (att->type != AttributeType_t::Int) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->n_data = nData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddSessionAttributeString( uint64 ulSessionID, const char* pstrName, const char *pstrData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', '%s'", ulSessionID, pstrName, pstrData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size() || !pstrName || !pstrData) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_session_att(pstrName, session, AttributeType_t::Str);
|
||||||
|
if (att->type != AttributeType_t::Str) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->s_data = pstrData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddSessionAttributeFloat( uint64 ulSessionID, const char* pstrName, float fData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %f", ulSessionID, pstrName, fData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size() || !pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_session_att(pstrName, session, AttributeType_t::Float);
|
||||||
|
if (att->type != AttributeType_t::Float) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->f_data = fData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddNewRow( uint64 *pulRowID, uint64 ulSessionID, const char *pstrTableName )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%p, %llu, '%s'", pulRowID, ulSessionID, pstrTableName);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size() || !pstrTableName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
auto table = get_or_create_session_table(session, pstrTableName);
|
||||||
|
table->rows.emplace_back(Row_t{});
|
||||||
|
if (pulRowID) *pulRowID = (uint64)(table->rows.size() - 1);
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::CommitRow( uint64 ulRowID )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", ulRowID);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
auto active_session = std::find_if(sessions.rbegin(), sessions.rend(), [](const Session_t &item){ return !item.ended; });
|
||||||
|
if (sessions.rend() == active_session) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
if (active_session->tables.empty()) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &table = active_session->tables.back().second;
|
||||||
|
if (ulRowID >= table.rows.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
// TODO what if it was already committed ?
|
||||||
|
auto &row = table.rows[ulRowID];
|
||||||
|
row.committed = true;
|
||||||
|
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::CommitOutstandingRows( uint64 ulSessionID )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu", ulSessionID);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
if (session.tables.size()) {
|
||||||
|
for (auto &row : session.tables.back().second.rows) {
|
||||||
|
row.committed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddRowAttributeInt( uint64 ulRowID, const char *pstrName, int32 nData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %i", ulRowID, pstrName, nData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto active_session = std::find_if(sessions.rbegin(), sessions.rend(), [](const Session_t &item){ return !item.ended; });
|
||||||
|
if (sessions.rend() == active_session) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
if (active_session->tables.empty()) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &table = active_session->tables.back().second;
|
||||||
|
if (ulRowID >= table.rows.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_row_att(ulRowID, pstrName, table, AttributeType_t::Int);
|
||||||
|
if (att->type != AttributeType_t::Int) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->n_data = nData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddRowAtributeString( uint64 ulRowID, const char *pstrName, const char *pstrData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', '%s'", ulRowID, pstrName, pstrData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pstrName || !pstrData) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto active_session = std::find_if(sessions.rbegin(), sessions.rend(), [](const Session_t &item){ return !item.ended; });
|
||||||
|
if (sessions.rend() == active_session) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &table = active_session->tables.back().second;
|
||||||
|
if (ulRowID >= table.rows.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_row_att(ulRowID, pstrName, table, AttributeType_t::Str);
|
||||||
|
if (att->type != AttributeType_t::Str) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->s_data = pstrData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddRowAttributeFloat( uint64 ulRowID, const char *pstrName, float fData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %f", ulRowID, pstrName, fData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto active_session = std::find_if(sessions.rbegin(), sessions.rend(), [](const Session_t &item){ return !item.ended; });
|
||||||
|
if (sessions.rend() == active_session) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &table = active_session->tables.back().second;
|
||||||
|
if (ulRowID >= table.rows.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_row_att(ulRowID, pstrName, table, AttributeType_t::Float);
|
||||||
|
if (att->type != AttributeType_t::Float) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->f_data = fData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddSessionAttributeInt64( uint64 ulSessionID, const char *pstrName, int64 llData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %lli", ulSessionID, pstrName, llData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (ulSessionID == 0 || ulSessionID > sessions.size() || !pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &session = sessions[ulSessionID - 1];
|
||||||
|
if (session.ended) return EResult::k_EResultExpired; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_session_att(pstrName, session, AttributeType_t::Int64);
|
||||||
|
if (att->type != AttributeType_t::Int64) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->ll_data = llData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
EResult Steam_GameStats::AddRowAttributeInt64( uint64 ulRowID, const char *pstrName, int64 llData )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%llu, '%s', %lli", ulRowID, pstrName, llData);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (!pstrName) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto active_session = std::find_if(sessions.rbegin(), sessions.rend(), [](const Session_t &item){ return !item.ended; });
|
||||||
|
if (sessions.rend() == active_session) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
auto &table = active_session->tables.back().second;
|
||||||
|
if (ulRowID >= table.rows.size()) return EResult::k_EResultInvalidParam; // TODO is this correct?
|
||||||
|
|
||||||
|
auto att = get_or_create_row_att(ulRowID, pstrName, table, AttributeType_t::Int64);
|
||||||
|
if (att->type != AttributeType_t::Int64) return EResult::k_EResultFail; // TODO is this correct?
|
||||||
|
|
||||||
|
att->ll_data = llData;
|
||||||
|
return EResult::k_EResultOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- steam callbacks
|
||||||
|
|
||||||
|
void Steam_GameStats::steam_run_callback()
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- networking callbacks
|
||||||
|
|
||||||
|
// user connect/disconnect
|
||||||
|
void Steam_GameStats::network_callback_low_level(Common_Message *msg)
|
||||||
|
{
|
||||||
|
switch (msg->low_level().type())
|
||||||
|
{
|
||||||
|
case Low_Level::CONNECT:
|
||||||
|
// nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Low_Level::DISCONNECT:
|
||||||
|
// nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
PRINT_DEBUG("unknown type %i", (int)msg->low_level().type());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
75
sdk/steam/isteamgamestats.h
Normal file
75
sdk/steam/isteamgamestats.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//====== Copyright 1996-2008, Valve Corporation, All rights reserved. =======
|
||||||
|
//
|
||||||
|
// Purpose: interface to steam for game play statistics
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#ifndef ISTEAMGAMESTATS_H
|
||||||
|
#define ISTEAMGAMESTATS_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Functions for recording game play sessions and details thereof
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class ISteamGameStats
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual SteamAPICall_t GetNewSession( int8 nAccountType, uint64 ulAccountID, int32 nAppID, RTime32 rtTimeStarted ) = 0;
|
||||||
|
virtual SteamAPICall_t EndSession( uint64 ulSessionID, RTime32 rtTimeEnded, int nReasonCode ) = 0;
|
||||||
|
virtual EResult AddSessionAttributeInt( uint64 ulSessionID, const char* pstrName, int32 nData ) = 0;
|
||||||
|
virtual EResult AddSessionAttributeString( uint64 ulSessionID, const char* pstrName, const char *pstrData ) = 0;
|
||||||
|
virtual EResult AddSessionAttributeFloat( uint64 ulSessionID, const char* pstrName, float fData ) = 0;
|
||||||
|
|
||||||
|
virtual EResult AddNewRow( uint64 *pulRowID, uint64 ulSessionID, const char *pstrTableName ) = 0;
|
||||||
|
virtual EResult CommitRow( uint64 ulRowID ) = 0;
|
||||||
|
virtual EResult CommitOutstandingRows( uint64 ulSessionID ) = 0;
|
||||||
|
virtual EResult AddRowAttributeInt( uint64 ulRowID, const char *pstrName, int32 nData ) = 0;
|
||||||
|
virtual EResult AddRowAtributeString( uint64 ulRowID, const char *pstrName, const char *pstrData ) = 0;
|
||||||
|
virtual EResult AddRowAttributeFloat( uint64 ulRowID, const char *pstrName, float fData ) = 0;
|
||||||
|
|
||||||
|
virtual EResult AddSessionAttributeInt64( uint64 ulSessionID, const char *pstrName, int64 llData ) = 0;
|
||||||
|
virtual EResult AddRowAttributeInt64( uint64 ulRowID, const char *pstrName, int64 llData ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define STEAMGAMESTATS_INTERFACE_VERSION "SteamGameStats001"
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: nAccountType for GetNewSession
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
enum EGameStatsAccountType
|
||||||
|
{
|
||||||
|
k_EGameStatsAccountType_Steam = 1, // ullAccountID is a 64-bit SteamID for a player
|
||||||
|
k_EGameStatsAccountType_Xbox = 2, // ullAccountID is a 64-bit XUID
|
||||||
|
k_EGameStatsAccountType_SteamGameServer = 3, // ullAccountID is a 64-bit SteamID for a game server
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: callback for GetNewSession() method
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct GameStatsSessionIssued_t
|
||||||
|
{
|
||||||
|
enum { k_iCallback = k_iSteamGameStatsCallbacks + 1 };
|
||||||
|
|
||||||
|
uint64 m_ulSessionID;
|
||||||
|
EResult m_eResult;
|
||||||
|
bool m_bCollectingAny;
|
||||||
|
bool m_bCollectingDetails;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: callback for EndSession() method
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct GameStatsSessionClosed_t
|
||||||
|
{
|
||||||
|
enum { k_iCallback = k_iSteamGameStatsCallbacks + 2 };
|
||||||
|
|
||||||
|
uint64 m_ulSessionID;
|
||||||
|
EResult m_eResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ISTEAMGAMESTATS_H
|
@ -193,6 +193,18 @@
|
|||||||
#include "isteamnetworkingutils.h"
|
#include "isteamnetworkingutils.h"
|
||||||
#include "isteamtv.h"
|
#include "isteamtv.h"
|
||||||
#include "steamnetworkingfakeip.h"
|
#include "steamnetworkingfakeip.h"
|
||||||
|
#include "isteamgameserver.h"
|
||||||
|
#include "isteamgameserver014.h"
|
||||||
|
#include "isteamgameserver013.h"
|
||||||
|
#include "isteamgameserver012.h"
|
||||||
|
#include "isteamgameserver011.h"
|
||||||
|
#include "isteamgameserver010.h"
|
||||||
|
#include "isteamgameserver009.h"
|
||||||
|
#include "isteamgameserver008.h"
|
||||||
|
#include "isteamgameserver005.h"
|
||||||
|
#include "isteamgameserver004.h"
|
||||||
|
#include "isteamgameserverstats.h"
|
||||||
|
#include "isteamgamestats.h"
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
|
||||||
|
@ -12,15 +12,6 @@
|
|||||||
|
|
||||||
#include "steam_api.h"
|
#include "steam_api.h"
|
||||||
#include "isteamgameserver.h"
|
#include "isteamgameserver.h"
|
||||||
#include "isteamgameserver014.h"
|
|
||||||
#include "isteamgameserver013.h"
|
|
||||||
#include "isteamgameserver012.h"
|
|
||||||
#include "isteamgameserver011.h"
|
|
||||||
#include "isteamgameserver010.h"
|
|
||||||
#include "isteamgameserver009.h"
|
|
||||||
#include "isteamgameserver008.h"
|
|
||||||
#include "isteamgameserver005.h"
|
|
||||||
#include "isteamgameserver004.h"
|
|
||||||
#include "isteamgameserverstats.h"
|
#include "isteamgameserverstats.h"
|
||||||
|
|
||||||
enum EServerMode
|
enum EServerMode
|
||||||
|
Loading…
Reference in New Issue
Block a user