achievements
[carveJwlIkooP6JGAAIwe30JlM.git] / steam.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 * All trademarks are property of their respective owners
4 */
5
6 #ifndef STEAM_H
7 #define STEAM_H
8
9 #include "vg/vg_steam.h"
10 #include "vg/vg_steam_utils.h"
11 #include "vg/vg_steam_networking.h"
12 #include "vg/vg_steam_auth.h"
13 #include "vg/vg_steam_http.h"
14 #include "vg/vg_steam_friends.h"
15 #include "vg/vg_steam_user_stats.h"
16
17 /*
18 * We only want to use steamworks if building for the networked version,
19 * theres not much point otherwise. We mainly want steamworks for setting
20 * achievements etc.. so that includes our own server too.
21 *
22 * This file also wraps the functions and interfaces that we want to use to
23 * make them a bit easier to read, since they are the flat API they have very
24 * long names. in non-networked builds they will return default errors or do
25 * nothing.
26 */
27
28 static char steam_username_at_startup[128];
29
30 static void recv_steam_warning( int severity, const char *msg )
31 {
32 if( severity == 0 )
33 vg_low( "%s\n", msg );
34 else
35 vg_info( "%s\n", msg );
36 }
37
38 static int steam_ready = 0,
39 steam_stats_ready = 0;
40
41 static void *hSteamNetworkingSockets,
42 *hSteamUser;
43
44 static ISteamUserStats *hSteamUserStats;
45 static HSteamPipe hSteamClientPipe;
46
47 static const char *steam_achievement_names[] =
48 {
49 "ALBERT", "MARC",
50 "ROUTE_MPY", "ROUTE_MPG", "ROUTE_MPB", "ROUTE_MPR",
51 "ROUTE_TO", "ROUTE_TC"
52 };
53
54 static void steam_store_achievements(void)
55 {
56 SteamAPI_ISteamUserStats_StoreStats( hSteamUserStats );
57 }
58
59 static void steam_set_achievement( const char *name )
60 {
61 if( steam_ready && steam_stats_ready )
62 {
63 if( SteamAPI_ISteamUserStats_SetAchievement( hSteamUserStats, name ) )
64 {
65 vg_success( "Achievement set! '%s'\n", name );
66 }
67 else
68 {
69 vg_warn( "Failed to set achievement: %s\n", name );
70 }
71 }
72 else
73 {
74 vg_warn( "Failed to set achievement (steam not ready): %s\n", name );
75 }
76 }
77
78 static void steam_clear_achievement( const char *name )
79 {
80 if( steam_ready && steam_stats_ready )
81 {
82 if( SteamAPI_ISteamUserStats_ClearAchievement( hSteamUserStats, name ) )
83 {
84 vg_info( "Achievement cleared: '%s'\n", name );
85 }
86 else
87 {
88 vg_warn( "Failed to clear achievement: %s\n", name );
89 }
90 }
91 else
92 {
93 vg_warn( "Failed to clear achievement (steam not ready): %s\n", name );
94 }
95 }
96
97
98 static int steam_list_achievements( int argc, char const *argv[] )
99 {
100 vg_info( "Achievements: \n" );
101
102 if( steam_ready && steam_stats_ready )
103 {
104 for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
105 {
106 int set = 0;
107 const char *name = steam_achievement_names[i];
108
109 if( SteamAPI_ISteamUserStats_GetAchievement(
110 hSteamUserStats, name, &set ) )
111 {
112 vg_info( " %s %s\n", (set? "[YES]": "[ ]"), name );
113 }
114 else
115 {
116 vg_warn( " Error while fetching achievement status '%s'\n", name );
117 }
118 }
119 }
120 else
121 {
122 vg_warn( " Steam is not initialized, no results\n" );
123 }
124
125 return 0;
126 }
127
128 static int steam_clear_all_achievements( int argc, char const *argv[] )
129 {
130 if( steam_ready && steam_stats_ready )
131 {
132 for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
133 {
134 steam_clear_achievement( steam_achievement_names[i] );
135 }
136
137 steam_store_achievements();
138 }
139 else
140 {
141 vg_warn( "steam is not initialized, cannot clear\n" );
142 }
143
144 return 0;
145 }
146
147 static int steam_set_achievemnt_test( int argc, char const *argv[] )
148 {
149 if( argc < 2 )
150 return 0;
151
152 if( strcmp( argv[0], "monkey_island" ) )
153 return 0;
154
155 steam_set_achievement( argv[1] );
156 steam_store_achievements();
157
158 return 0;
159 }
160
161 static void steam_on_recieve_current_stats( CallbackMsg_t *msg )
162 {
163 UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_pubParam;
164
165 if( rec->m_eResult == k_EResultOK )
166 {
167 vg_info( "Recieved stats for: %lu (user: %lu)\n", rec->m_nGameID,
168 rec->m_steamIDUser );
169 steam_stats_ready = 1;
170 }
171 else
172 {
173 vg_error( "Error recieveing stats for user (%u)\n", rec->m_eResult );
174 }
175 }
176
177 static int steam_init(void)
178 {
179 const char *username = NULL;
180
181 #ifdef SR_NETWORKED
182 vg_info( "Initializing steamworks\n" );
183
184 if( !SteamAPI_Init() )
185 {
186 printf("\n");
187 vg_error( "Steamworks failed to initialize\n" );
188 return 1;
189 }
190
191 steam_ready = 1;
192
193 SteamAPI_ManualDispatch_Init();
194
195 /* Connect interfaces */
196 hSteamClientPipe = SteamAPI_GetHSteamPipe();
197 hSteamNetworkingSockets = SteamAPI_SteamNetworkingSockets_SteamAPI();
198 hSteamUser = SteamAPI_SteamUser();
199
200 ISteamUtils *utils = SteamAPI_SteamUtils();
201 SteamAPI_ISteamUtils_SetWarningMessageHook( utils, recv_steam_warning );
202
203 printf("\n");
204 vg_success( "\nSteamworks API running\n" );
205
206 ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
207 username = SteamAPI_ISteamFriends_GetPersonaName( hSteamFriends );
208
209 /*
210 * Request stats
211 * --------------------------------------------------------
212 */
213 hSteamUserStats = SteamAPI_SteamUserStats();
214
215 steam_register_callback( k_iUserStatsReceived,
216 steam_on_recieve_current_stats );
217
218 if( !SteamAPI_ISteamUserStats_RequestCurrentStats( hSteamUserStats ) )
219 vg_warn( "No Steam Logon: Cannot request stats\n" );
220
221
222 vg_function_push( (struct vg_cmd)
223 {
224 .name = "ach_list",
225 .function = steam_list_achievements
226 });
227
228 vg_function_push( (struct vg_cmd)
229 {
230 .name = "ach_clear_all",
231 .function = steam_clear_all_achievements
232 });
233
234 vg_function_push( (struct vg_cmd)
235 {
236 .name = "ach_set",
237 .function = steam_set_achievemnt_test
238 });
239
240 #endif
241
242 /* TODO: On username update callback */
243 str_utf8_collapse( username, steam_username_at_startup,
244 vg_list_size(steam_username_at_startup) );
245
246 return 1;
247 }
248
249 static void steam_update(void)
250 {
251 if( steam_ready )
252 steamworks_event_loop( hSteamClientPipe );
253 }
254
255 static void steam_end(void *nothing)
256 {
257 if( steam_ready )
258 {
259 vg_info( "Shutting down\n..." );
260 SteamAPI_Shutdown();
261 }
262 }
263
264 #endif /* STEAM_H */