-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathsteam_client.cpp
126 lines (106 loc) · 3.38 KB
/
steam_client.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "steam_internal.h"
#include "steam_client.h"
#include "steam_call_result.h"
#include "steam_friends.h"
#include "steam_user.h"
#include "steam_ugc.h"
#include "steam_utils.h"
#include "steamworks/public/steam/isteamclient.h"
#include "steamworks/public/steam/isteamuserstats.h"
#define FUNC(name) SteamAPI_ISteamClient_##name
#define US_FUNC(name) SteamAPI_ISteamUserStats_##name
namespace steam {
struct Client::Ifaces {
Ifaces(ISteamClient* client, HSteamPipe pipeHandle, HSteamUser userHandle)
: userStats(FUNC(GetISteamUserStats)(client, userHandle, pipeHandle, STEAMUSERSTATS_INTERFACE_VERSION)),
friends(FUNC(GetISteamFriends)(client, userHandle, pipeHandle, STEAMFRIENDS_INTERFACE_VERSION)),
user(FUNC(GetISteamUser)(client, userHandle, pipeHandle, STEAMUSER_INTERFACE_VERSION)),
ugc(FUNC(GetISteamUGC)(client, userHandle, pipeHandle, STEAMUGC_INTERFACE_VERSION)),
utils(FUNC(GetISteamUtils)(client, pipeHandle, STEAMUTILS_INTERFACE_VERSION)) {
}
ISteamUserStats* userStats;
Friends friends;
User user;
UGC ugc;
Utils utils;
};
struct Client::Impl {
ISteamClient* client;
HSteamPipe pipeHandle;
HSteamUser userHandle;
CallResult<NumberOfCurrentPlayers_t> nocp;
};
static Client* s_instance = nullptr;
bool Client::isAvailable() {
return !!s_instance;
}
#define IFACE_INSTANCE(name, funcName) \
name& name::instance() { \
return Client::instance().funcName(); \
}
IFACE_INSTANCE(Friends, friends)
IFACE_INSTANCE(User, user)
IFACE_INSTANCE(UGC, ugc)
IFACE_INSTANCE(Utils, utils)
#undef IFACE_INSTANCE
Client& Client::instance() {
CHECK(s_instance && "Steam client not available");
return *s_instance;
}
Client::Client() {
CHECK(!s_instance && "At most one steam::Client class can be alive at a time");
s_instance = this;
// TODO: handle errors, use Expected<>
auto client = ::SteamClient();
auto pipeHandle = FUNC(CreateSteamPipe)(client);
auto userHandle = FUNC(ConnectToGlobalUser)(client, pipeHandle);
impl.reset(new Impl{client, pipeHandle, userHandle});
ifaces.reset(new Ifaces{client, pipeHandle, userHandle});
}
Client::~Client() {
ifaces.reset();
FUNC(ReleaseUser)(impl->client, impl->pipeHandle, impl->userHandle);
FUNC(BReleaseSteamPipe)(impl->client, impl->pipeHandle);
s_instance = nullptr;
}
Friends& Client::friends() {
return ifaces->friends;
}
User& Client::user() {
return ifaces->user;
}
Utils& Client::utils() {
return ifaces->utils;
}
UGC& Client::ugc() {
return ifaces->ugc;
}
optional<int> Client::numberOfCurrentPlayers() {
optional<int> out;
if (!impl->nocp)
impl->nocp = US_FUNC(GetNumberOfCurrentPlayers)(ifaces->userStats);
else {
impl->nocp.update();
if (!impl->nocp.isPending()) {
if (impl->nocp.isCompleted()) {
out = impl->nocp.result().m_cPlayers;
}
// TODO: handle errors
impl->nocp.clear();
}
}
return out;
}
string Client::info() {
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"STEAM: App id: %u\n"
"STEAM: User id: %llu\n"
"STEAM: User name: %s\n",
utils().appId(),
user().id().value,
friends().name().c_str());
return buffer;
}
}
#undef FUNC