1 // Voidwrap - A Steam API wrapper.
2
3 #define VOIDWRAP_ISEXPORTING
4 #include "voidwrap_steam.h"
5 #include "steam_api.h"
6 #include "compat.h"
7
8 static uint64_t AppID;
9 static VW_VOID_CONSTCHARPTR Callback_PrintDebug;
10
PrintDebug(const char * fmt,...)11 static void PrintDebug(const char * fmt, ...)
12 {
13 if (Callback_PrintDebug == nullptr)
14 return;
15
16 static char tmpstr[8192];
17 va_list va;
18
19 va_start(va, fmt);
20 Bvsnprintf(tmpstr, sizeof(tmpstr), fmt, va);
21 va_end(va);
22
23 Callback_PrintDebug(tmpstr);
24 }
25
SteamAPIWarningMessageHook(int nSeverity,const char * pchDebugText)26 static void SteamAPIWarningMessageHook(int nSeverity, const char * pchDebugText)
27 {
28 UNREFERENCED_PARAMETER(nSeverity);
29
30 if (Callback_PrintDebug == nullptr)
31 return;
32
33 Callback_PrintDebug(pchDebugText);
34 }
35
36 #ifdef VWDEBUG
Voidwrap_Steam_SetCallback_PrintDebug(VW_VOID_CONSTCHARPTR function)37 VOIDWRAP_API void Voidwrap_Steam_SetCallback_PrintDebug(VW_VOID_CONSTCHARPTR function)
38 {
39 Callback_PrintDebug = function;
40 }
41 #endif
42
43
44 class SteamStatsAndAchievementsHandler
45 {
46 public:
SteamStatsAndAchievementsHandler()47 SteamStatsAndAchievementsHandler()
48 : m_pSteamUserStats{SteamUserStats()}
49 { }
50
51 void SetAchievement(char const * id);
52 void SetStat(char const * id, int32_t value);
53 void ResetStats();
54
55 STEAM_CALLBACK(SteamStatsAndAchievementsHandler, OnUserStatsReceived, UserStatsReceived_t);
56 STEAM_CALLBACK(SteamStatsAndAchievementsHandler, OnUserStatsStored, UserStatsStored_t);
57
58 void Process();
59
60 private:
61 ISteamUserStats * m_pSteamUserStats;
62
63 bool m_bRequestedStats{};
64 bool m_bStatsValid{};
65
66 bool m_bStoreStats{};
67 };
68
SetAchievement(char const * id)69 void SteamStatsAndAchievementsHandler::SetAchievement(char const * id)
70 {
71 if (nullptr == m_pSteamUserStats)
72 return;
73
74 m_pSteamUserStats->SetAchievement(id);
75
76 m_bStoreStats = true;
77 }
78
SetStat(char const * id,int32_t value)79 void SteamStatsAndAchievementsHandler::SetStat(char const * id, int32_t value)
80 {
81 if (nullptr == m_pSteamUserStats)
82 return;
83
84 m_pSteamUserStats->SetStat(id, value);
85
86 m_bStoreStats = true;
87 }
88
ResetStats()89 void SteamStatsAndAchievementsHandler::ResetStats()
90 {
91 if (nullptr == m_pSteamUserStats)
92 return;
93
94 m_pSteamUserStats->ResetAllStats(true);
95 m_bStatsValid = false;
96 m_bRequestedStats = false;
97 }
98
OnUserStatsReceived(UserStatsReceived_t * pCallback)99 void SteamStatsAndAchievementsHandler::OnUserStatsReceived(UserStatsReceived_t * pCallback)
100 {
101 if (nullptr == m_pSteamUserStats || AppID != pCallback->m_nGameID)
102 return;
103
104 if (k_EResultOK == pCallback->m_eResult)
105 m_bStatsValid = true;
106 else
107 PrintDebug("RequestStats - failed, %d\n", pCallback->m_eResult);
108 }
109
OnUserStatsStored(UserStatsStored_t * pCallback)110 void SteamStatsAndAchievementsHandler::OnUserStatsStored(UserStatsStored_t * pCallback)
111 {
112 if (AppID != pCallback->m_nGameID)
113 return;
114
115 if (k_EResultInvalidParam == pCallback->m_eResult)
116 PrintDebug("StoreStats - some failed to validate\n");
117 else
118 PrintDebug("StoreStats - failed, %d\n", pCallback->m_eResult);
119 }
120
Process()121 void SteamStatsAndAchievementsHandler::Process()
122 {
123 if (nullptr == m_pSteamUserStats)
124 return;
125
126 if (!m_bRequestedStats)
127 {
128 m_bRequestedStats = m_pSteamUserStats->RequestCurrentStats();
129 return;
130 }
131
132 if (!m_bStatsValid || !m_bStoreStats)
133 return;
134
135 m_bStoreStats = !m_pSteamUserStats->StoreStats();
136 }
137
138 static SteamStatsAndAchievementsHandler * StatsAndAchievementsHandler;
139
Voidwrap_Steam_UnlockAchievement(char const * id)140 VOIDWRAP_API void Voidwrap_Steam_UnlockAchievement(char const * id)
141 {
142 if (nullptr == StatsAndAchievementsHandler)
143 return;
144
145 StatsAndAchievementsHandler->SetAchievement(id);
146 }
147
Voidwrap_Steam_SetStat(char const * id,int32_t value)148 VOIDWRAP_API void Voidwrap_Steam_SetStat(char const * id, int32_t value)
149 {
150 if (nullptr == StatsAndAchievementsHandler)
151 return;
152
153 StatsAndAchievementsHandler->SetStat(id, value);
154 }
155
Voidwrap_Steam_ResetStats()156 VOIDWRAP_API void Voidwrap_Steam_ResetStats()
157 {
158 if (nullptr == StatsAndAchievementsHandler)
159 return;
160
161 StatsAndAchievementsHandler->ResetStats();
162 }
163
164 #ifdef VWSCREENSHOT
165 class SteamScreenshotHandler
166 {
167 private:
168 STEAM_CALLBACK(SteamScreenshotHandler, screenshotRequested, ScreenshotRequested_t);
169 STEAM_CALLBACK(SteamScreenshotHandler, screenshotReady, ScreenshotReady_t);
170 };
171
172 static SteamScreenshotHandler * ScreenHandler;
173 static VW_VOID Callback_ScreenshotRequested;
174 // static VW_VOID_INT32 Callback_ScreenshotReady;
175
Voidwrap_Steam_SetCallback_ScreenshotRequested(VW_VOID function)176 VOIDWRAP_API void Voidwrap_Steam_SetCallback_ScreenshotRequested(VW_VOID function)
177 {
178 Callback_ScreenshotRequested = function;
179 }
180
181 #if 0
182 VOIDWRAP_API void Voidwrap_Steam_SetCallback_ScreenshotReady(VW_VOID_INT32 function)
183 {
184 Callback_ScreenshotReady = function;
185 }
186 #endif
187
Voidwrap_Steam_SendScreenshot(char * filepath,int32_t width,int32_t height)188 VOIDWRAP_API bool Voidwrap_Steam_SendScreenshot(char * filepath, int32_t width, int32_t height)
189 {
190 if (INVALID_SCREENSHOT_HANDLE == SteamScreenshots()->AddScreenshotToLibrary(filepath, nullptr, width, height))
191 {
192 return false;
193 }
194
195 return true;
196 }
197
screenshotRequested(ScreenshotRequested_t * pCallback)198 void SteamScreenshotHandler::screenshotRequested(ScreenshotRequested_t * pCallback)
199 {
200 if (Callback_ScreenshotRequested != nullptr)
201 {
202 PrintDebug("SteamScreenshotHandler::screenshotRequested executed.");
203 Callback_ScreenshotRequested();
204 }
205 }
206
screenshotReady(ScreenshotReady_t * pCallback)207 void SteamScreenshotHandler::screenshotReady(ScreenshotReady_t * pCallback)
208 {
209 PrintDebug("SteamScreenshotHandler::screenshotReady executed. Result: %d", pCallback->m_eResult);
210
211 #if 0
212 if (Callback_ScreenshotReady != nullptr)
213 {
214 Callback_ScreenshotReady(pCallback->m_eResult);
215 }
216 #endif
217 }
218 #endif
219
220
Voidwrap_Steam_Init()221 VOIDWRAP_API bool Voidwrap_Steam_Init()
222 {
223 if (!SteamAPI_Init())
224 {
225 SteamAPI_Shutdown();
226 return false;
227 }
228
229 SteamUtils()->SetWarningMessageHook(&SteamAPIWarningMessageHook);
230 SteamUtils()->SetOverlayNotificationPosition(k_EPositionTopRight);
231 AppID = SteamUtils()->GetAppID();
232
233 #if 0
234 PrintDebug("AppID is %llu", AppID);
235 if (SteamUtils()->IsOverlayEnabled()) { PrintDebug("Overlay is enabled."); }
236 #endif
237
238 StatsAndAchievementsHandler = new SteamStatsAndAchievementsHandler{};
239
240 #ifdef VWSCREENSHOT
241 SteamScreenshots()->HookScreenshots(true);
242 if (SteamScreenshots()->IsScreenshotsHooked()) { PrintDebug("Screenshots hooked."); }
243 ScreenHandler = new SteamScreenshotHandler();
244 #endif
245
246 SteamAPI_RunCallbacks();
247
248 return true;
249 }
250
Voidwrap_Steam_Shutdown()251 VOIDWRAP_API void Voidwrap_Steam_Shutdown()
252 {
253 SteamAPI_Shutdown();
254 }
255
Voidwrap_Steam_RunCallbacks()256 VOIDWRAP_API void Voidwrap_Steam_RunCallbacks()
257 {
258 StatsAndAchievementsHandler->Process();
259
260 SteamAPI_RunCallbacks();
261 }
262