2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 * All trademarks are property of their respective owners
9 #include "vg/vg_stdint.h"
11 #include "network_msg.h"
12 #include "highscores.h"
14 VG_STATIC
int network_scores_updated
= 0;
19 //#define SR_USE_LOCALHOST
21 /* Call it at start; Connects us to the gameserver */
22 VG_STATIC
void network_init(void);
24 /* Run this from main loop */
25 VG_STATIC
void network_update(void);
27 /* Call it at shutdown */
28 VG_STATIC
void network_end(void);
31 * Can buffer up a bunch of these by calling many times, they will be
32 * sent at the next connection
34 VG_STATIC
void network_submit_highscore( u32 trackid
, u16 points
, u16 time
);
37 * Game endpoints are provided with the same names to allow running without a
43 * Runtime connection stuff
45 VG_STATIC u8 steam_app_ticket
[ 1024 ];
46 VG_STATIC u32 steam_app_ticket_length
;
47 VG_STATIC
int network_name_update
= 1;
49 VG_STATIC HSteamNetConnection cremote
;
50 VG_STATIC ESteamNetworkingConnectionState cremote_state
=
51 k_ESteamNetworkingConnectionState_None
;
57 VG_STATIC
void scores_update(void);
59 VG_STATIC
void on_auth_ticket_recieved( void *result
, void *context
)
61 EncryptedAppTicketResponse_t
*response
= result
;
63 if( response
->m_eResult
== k_EResultOK
)
65 vg_info( " New app ticket ready\n" );
69 vg_warn( " Could not request new encrypted app ticket (%u)\n",
70 response
->m_eResult
);
73 if( SteamAPI_ISteamUser_GetEncryptedAppTicket( hSteamUser
,
75 vg_list_size(steam_app_ticket
),
76 &steam_app_ticket_length
))
78 vg_success( " Loaded app ticket (%u bytes)\n", steam_app_ticket_length
);
82 vg_error( " No ticket availible\n" );
83 steam_app_ticket_length
= 0;
87 VG_STATIC
void request_auth_ticket(void)
90 * TODO Check for one thats cached on the disk and load it.
91 * This might be OK though because steam seems to cache the result
94 vg_info( "Requesting new authorization ticket\n" );
96 vg_steam_async_call
*call
= vg_alloc_async_steam_api_call();
97 call
->userdata
= NULL
;
98 call
->p_handler
= on_auth_ticket_recieved
;
100 SteamAPI_ISteamUser_RequestEncryptedAppTicket( hSteamUser
, NULL
, 0 );
103 VG_STATIC
void send_auth_ticket(void)
105 u32 size
= sizeof(netmsg_auth
) + steam_app_ticket_length
;
106 netmsg_auth
*auth
= alloca(size
);
108 auth
->inetmsg_id
= k_inetmsg_auth
;
109 auth
->ticket_length
= steam_app_ticket_length
;
110 for( int i
=0; i
<steam_app_ticket_length
; i
++ )
111 auth
->ticket
[i
] = steam_app_ticket
[i
];
113 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
114 hSteamNetworkingSockets
, cremote
, auth
, size
,
115 k_nSteamNetworkingSend_Reliable
, NULL
);
118 VG_STATIC
void send_score_request(void)
120 vg_info( "Requesting scores\n" );
121 netmsg_scores_request req
;
122 req
.inetmsg_id
= k_inetmsg_scores_request
;
124 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
125 hSteamNetworkingSockets
, cremote
, &req
, sizeof(netmsg_scores_request
),
126 k_nSteamNetworkingSend_Reliable
, NULL
);
129 VG_STATIC
void send_score_update(void)
131 vg_info( "Sending scores\n" );
132 u32 size
= sizeof(netmsg_set_score
) +
133 vg_list_size(track_infos
)*sizeof(struct netmsg_score_record
);
134 netmsg_set_score
*setscore
= alloca( size
);
135 setscore
->inetmsg_id
= k_inetmsg_set_score
;
138 for( u32 i
=0; i
<vg_list_size(track_infos
); i
++ ){
139 if( track_infos
[i
].push
){
140 track_infos
[i
].push
= 0;
143 highscore_record
*user_record
= highscore_find_user_record( 0, i
);
146 vg_error( "No score set but tried to upload for track %u\n", i
);
150 highscore_record
*user_record
= &track_infos
[i
].record
;
152 setscore
->records
[count
].trackid
= i
;
153 setscore
->records
[count
].playerid
= 0;
154 setscore
->records
[count
].points
= user_record
->points
;
155 setscore
->records
[count
].time
= user_record
->time
;
161 if( count
== 0 ) return;
162 u32 send_size
= sizeof(netmsg_set_score
) +
163 count
*sizeof(struct netmsg_score_record
);
164 setscore
->record_count
= count
;
166 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
167 hSteamNetworkingSockets
, cremote
, setscore
, send_size
,
168 k_nSteamNetworkingSend_Reliable
, NULL
);
171 VG_STATIC
void send_nickname(void)
173 netmsg_set_nickname nick
;
174 nick
.inetmsg_id
= k_inetmsg_set_nickname
;
176 memset( nick
.nickname
, 0, 16 );
177 vg_strncpy( steam_username_at_startup
, nick
.nickname
, 16,
178 k_strncpy_allow_cutoff
);
180 SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
181 hSteamNetworkingSockets
, cremote
, &nick
, sizeof(netmsg_set_nickname
),
182 k_nSteamNetworkingSend_Reliable
, NULL
);
184 network_name_update
= 0;
187 VG_STATIC
void server_routine_update(void)
191 if( network_name_update
)
195 send_score_request();
198 VG_STATIC
void on_server_connect_status( CallbackMsg_t
*msg
)
200 SteamNetConnectionStatusChangedCallback_t
*info
= (void *)msg
->m_pubParam
;
201 vg_info( " Connection status changed for %lu\n", info
->m_hConn
);
202 vg_info( " %s -> %s\n",
203 string_ESteamNetworkingConnectionState(info
->m_eOldState
),
204 string_ESteamNetworkingConnectionState(info
->m_info
.m_eState
) );
206 if( info
->m_hConn
== cremote
)
208 cremote_state
= info
->m_info
.m_eState
;
209 if( info
->m_info
.m_eState
==
210 k_ESteamNetworkingConnectionState_Connected
)
212 vg_success(" Connected to remote server.. running updates\n");
213 server_routine_update();
218 vg_warn( " Recieved signal from unknown connection\n" );
222 VG_STATIC
void network_connect_gc(void)
224 /* Connect to server if not connected */
225 SteamNetworkingIPAddr remoteAddr
;
227 #ifdef SR_USE_LOCALHOST
228 SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr
, 27402 );
230 const char *server_lon1
= "46.101.34.155:27402";
231 SteamAPI_SteamNetworkingIPAddr_ParseString( &remoteAddr
, server_lon1
);
235 SteamAPI_SteamNetworkingIPAddr_ToString( &remoteAddr
, buf
, 256, 1 );
236 vg_info( "connect to: %s\n", buf
);
238 cremote
= SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
239 hSteamNetworkingSockets
, &remoteAddr
, 0, NULL
);
242 VG_STATIC
void on_inet_scoreboard( SteamNetworkingMessage_t
*msg
)
244 netmsg_scoreboard
*sb
= msg
->m_pData
;
246 u32 base_size
= sizeof(netmsg_scoreboard
)-
247 sizeof(struct netmsg_board
)*vg_list_size(track_infos
),
248 expected
= base_size
+sizeof(struct netmsg_board
)*sb
->board_count
;
250 if( msg
->m_cbSize
!= expected
){
251 vg_error( "Server scoreboard was corrupted. Size: %u != %u\n",
252 msg
->m_cbSize
, expected
);
255 if( vg_list_size(track_infos
) > sb
->board_count
)
256 vg_warn( "Server is out of date, not enough boards recieved\n");
257 else if( vg_list_size(track_infos
) < sb
->board_count
)
258 vg_warn( "Client out of date, server sent more boards than we have\n");
260 vg_success( "Recieved new scoreboards from server\n" );
262 for( int i
=0; i
< vg_min(sb
->board_count
,vg_list_size(track_infos
)); i
++){
263 scoreboard_client_data
.boards
[i
] = sb
->boards
[i
];
264 highscores_board_printf( stdout
, sb
->boards
[i
].data
, 10 );
268 /* We dont need to stay on the server currently */
269 SteamAPI_ISteamNetworkingSockets_CloseConnection(
270 hSteamNetworkingSockets
, cremote
, 0, NULL
, 1 );
272 network_scores_updated
= 1;
275 VG_STATIC
void poll_connection(void)
277 SteamNetworkingMessage_t
*messages
[32];
281 len
= SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection(
282 hSteamNetworkingSockets
, cremote
, messages
, vg_list_size(messages
));
287 for( int i
=0; i
<len
; i
++ ){
288 SteamNetworkingMessage_t
*msg
= messages
[i
];
290 if( msg
->m_cbSize
< sizeof(netmsg_blank
) ){
291 vg_warn( "Discarding message (too small: %d)\n", msg
->m_cbSize
);
295 netmsg_blank
*tmp
= msg
->m_pData
;
297 if( tmp
->inetmsg_id
== k_inetmsg_scoreboard
)
298 on_inet_scoreboard( msg
);
300 SteamAPI_SteamNetworkingMessage_t_Release( msg
);
306 * Subroutine to be connected to main game loop, runs all routines on timers
308 VG_STATIC
void network_update(void)
311 static double last_update
= 0.0;
314 if( vg
.time
> (last_update
+ 60.0) ){
315 last_update
= vg
.time
;
317 if( steam_app_ticket_length
){
318 network_connect_gc();
321 vg_low( "Not making remote connection; app ticket not gotten\n" );
325 if( vg
.time
> (last_update
+ 10.0) &&
326 (cremote_state
== k_ESteamNetworkingConnectionState_Connected
))
328 vg_warn( "Connected to server but no return... disconnecting\n" );
329 SteamAPI_ISteamNetworkingSockets_CloseConnection(
330 hSteamNetworkingSockets
, cremote
, 0, NULL
, 1 );
335 VG_STATIC
void network_init(void)
338 steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack
,
339 on_server_connect_status
);
340 request_auth_ticket();
344 VG_STATIC
void network_end(void)
346 /* TODO: Fire off any buffered highscores that need to be setn */
347 if( cremote_state
== k_ESteamNetworkingConnectionState_Connected
||
348 cremote_state
== k_ESteamNetworkingConnectionState_Connecting
)
350 SteamAPI_ISteamNetworkingSockets_CloseConnection(
351 hSteamNetworkingSockets
, cremote
, 0, NULL
, 1 );
355 #else /* SR_NETWORKED */
357 VG_STATIC
void network_init(void){}
358 VG_STATIC
void network_update(void){}
359 VG_STATIC
void network_end(void){}
361 #endif /* SR_NETWORKED */
362 #endif /* NETWORK_H */