int compiled_something = 0;
-void build_server( enum compiler compiler )
-{
+/* old highscores server */
+void build_server( enum compiler compiler ){
vg_build_start( "skaterift_server", compiler );
vg_build_object( "server.c " );
vg_build_link( "-lm -lsdkencryptedappticket -lsteam_api " );
vg_build_library_dir( "-L./vg/dep/steam " );
- vg_build_bin_dependency_file( "vg/dep/steam/steamclient.so" );
+ vg_build_bin_dependency_file( "vg/dep/steam/steamclient.so" );//TODO????
vg_build_bin_dependency_file( "vg/dep/steam/libsteam_api.so" );
vg_build_bin_dependency_file( "vg/dep/steam/libsdkencryptedappticket.so" );
compiled_something = 1;
}
+/* new game server */
+void build_gameserver( enum compiler compiler ){
+ vg_build_start( "skaterift_gameserver", compiler );
+ vg_build_object( "gameserver.c" );
+
+ vg_build_link( "-lm -lsdkencryptedappticket -lsteam_api " );
+ vg_build_library_dir( "-L./vg/dep/steam " );
+
+ //vg_build_bin_dependency_file( "vg/dep/steam/steamclient.so" );?????
+ vg_build_bin_dependency_file( "vg/dep/steam/libsteam_api.so" );
+ vg_build_bin_dependency_file( "vg/dep/steam/libsdkencryptedappticket.so" );
+
+ vg_build();
+ compiled_something = 1;
+}
+
+void build_servermonitor( enum compiler compiler ){
+ vg_build_start( "skaterift_servermonitor", compiler );
+ vg_build_object( "servermonitor_client.c " );
+
+ vg_build_add_link_for_graphics();
+ vg_build_include( "-I./vg/dep " );
+ vg_build_copy_graphics_dependencies();
+
+ vg_build();
+ compiled_something = 1;
+}
+
void write_msg( vg_msg *msg, const char *path ){
FILE *fp = fopen( path, "wb" );
if( !fp ){
}
void build_shaders(void);
-void build_game( enum compiler compiler )
-{
+void build_game( enum compiler compiler ){
static int shaders_built = 0;
if( !shaders_built ){
shaders_built = 1;
time_t uid = time(NULL);
char *arg;
- while( vg_argp( argc, argv ) )
- {
+ while( vg_argp( argc, argv ) ){
if( vg_long_opt( "debug" ) || vg_opt( 'd' ) )
vg_build_mode_debug();
if( vg_long_opt( "clang-server" ) )
build_server( k_compiler_clang );
+ if( vg_long_opt( "gcc-gameserver" ) )
+ build_gameserver( k_compiler_gcc );
+
+ if( vg_long_opt( "gcc-servermonitor" ) )
+ build_servermonitor( k_compiler_gcc );
+
if( vg_long_opt( "clean" ) )
vg_build_clean();
if( vg_long_opt( "mingw" ) )
build_game( k_compiler_mingw );
- if( vg_opt('p') || vg_long_opt("run") )
- {
+ if( vg_opt('p') || vg_long_opt("run") ){
chdir( vg_compiler.build_dir );
if( vg_compiler.compiler == k_compiler_mingw )
vg_build_syscall( "wine %s.exe", vg_compiler.name );
chdir( "../../" );
}
- if( vg_long_opt( "tar" ) || vg_opt( 't' ) )
- {
+ if( vg_long_opt( "tar" ) || vg_opt( 't' ) ){
vg_build_syscall( "mkdir -p dist" );
if( compiled_something )
vg_build_syscall( "tar -chzvf dist/%s-%u.tar.gz %s",
vg_compiler.name, uid, vg_compiler.build_dir );
}
- if( vg_long_opt( "zip" ) || vg_opt( 'z' ) )
- {
+ if( vg_long_opt( "zip" ) || vg_opt( 'z' ) ){
vg_build_syscall( "mkdir -p dist" );
if( compiled_something )
vg_build_syscall( "zip -r9 dist/%s-%u.zip %s",
#define _S( NAME, VS, FS ) \
vg_build_shader( "shaders/" VS, "shaders/" FS, NULL, "shaders", NAME )
-void build_shaders(void)
-{
+void build_shaders(void){
vg_shader_set_include_dir( "shaders" );
/* Scene */
--- /dev/null
+/*
+ * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ */
+
+#define _DEFAULT_SOURCE
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+
+volatile sig_atomic_t sig_stop;
+
+static void inthandler( int signum ) {
+ sig_stop = 1;
+}
+
+#include "gameserver.h"
+#include "highscores.c"
+#include "servermonitor_server.c"
+#include "vg/vg_opt.h"
+
+static const u64 k_connection_unauthorized = 0xffffffffffffffff;
+
+static u64_steamid get_connection_authsteamid( SteamNetworkingMessage_t *msg ){
+ i64 userdata = SteamAPI_ISteamNetworkingSockets_GetConnectionUserData(
+ hSteamNetworkingSockets, msg->m_conn );
+
+ return *((u64_steamid *)&userdata);
+}
+
+static void set_connection_authsteamid(HSteamNetConnection con, u64_steamid id){
+ i64 userdata = *((i64 *)&id);
+
+ SteamAPI_ISteamNetworkingSockets_SetConnectionUserData(
+ hSteamNetworkingSockets, con, userdata );
+}
+
+static void new_client_connecting( HSteamNetConnection client ){
+ EResult accept_status = SteamAPI_ISteamNetworkingSockets_AcceptConnection(
+ hSteamNetworkingSockets, client );
+
+ if( accept_status == k_EResultOK ){
+ vg_success( "Accepted client (id: %u)\n", client );
+ SteamAPI_ISteamNetworkingSockets_SetConnectionPollGroup(
+ hSteamNetworkingSockets,
+ client, gameserver.client_group );
+
+ /* Just to be sure */
+ set_connection_authsteamid( client, -1 );
+ }
+ else{
+ vg_warn( "Error accepting client (id: %u)\n", client );
+ }
+}
+
+static void on_auth_status( CallbackMsg_t *msg ){
+ SteamNetAuthenticationStatus_t *info = (void *)msg->m_pubParam;
+ vg_info( " Authentication availibility: %s\n",
+ string_ESteamNetworkingAvailability(info->m_eAvail) );
+ vg_info( " %s\n", info->m_debugMsg );
+}
+
+static void on_connect_status( CallbackMsg_t *msg ){
+ SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
+ vg_info( " Connection status changed for %lu\n", info->m_hConn );
+
+ vg_info( " %s -> %s\n",
+ string_ESteamNetworkingConnectionState(info->m_eOldState),
+ string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
+
+ if( info->m_info.m_eState==k_ESteamNetworkingConnectionState_Connecting ){
+ new_client_connecting( info->m_hConn );
+ }
+}
+
+static void on_inet_auth( SteamNetworkingMessage_t *msg ){
+ if( gameserver.auth_mode != eServerModeAuthentication ){
+ vg_error( "Running server without authentication. "
+ "Connection %u tried to authenticate.\n", msg->m_conn );
+ return;
+ }
+
+ if( get_connection_authsteamid( msg ) != k_connection_unauthorized ){
+ vg_warn( "Already authorized this user but app ticket was sent"
+ " again (%u)\n", msg->m_conn );
+ return;
+ }
+
+ vg_low( "Attempting to verify user\n" );
+
+ if( msg->m_cbSize < sizeof(netmsg_auth) ){
+ vg_error( "Malformed auth ticket, too small (%u)\n", msg->m_conn );
+ return;
+ }
+
+ netmsg_auth *auth = msg->m_pData;
+
+ if( msg->m_cbSize < sizeof(netmsg_auth)+auth->ticket_length ||
+ auth->ticket_length > 1024 ){
+ vg_error( "Malformed auth ticket, ticket_length incorrect (%u)\n",
+ auth->ticket_length );
+ return;
+ }
+
+ u8 decrypted[1024];
+ u32 ticket_len = 1024;
+
+ int success = SteamEncryptedAppTicket_BDecryptTicket(
+ auth->ticket, auth->ticket_length, decrypted,
+ &ticket_len, gameserver.app_symmetric_key,
+ k_nSteamEncryptedAppTicketSymmetricKeyLen );
+
+ if( !success ){
+ vg_error( "Failed to decrypt users ticket (client %u)\n", msg->m_conn );
+ vg_error( " ticket length: %u\n", auth->ticket_length );
+
+ SteamAPI_ISteamNetworkingSockets_CloseConnection(
+ hSteamNetworkingSockets,
+ msg->m_conn, 0, NULL, 1 );
+ return;
+ }
+
+ if( SteamEncryptedAppTicket_GetTicketIssueTime( decrypted, ticket_len )){
+ RTime32 ctime = time(NULL),
+ tickettime = SteamEncryptedAppTicket_GetTicketIssueTime(
+ decrypted, ticket_len ),
+ expiretime = tickettime + 24*3*60*60;
+
+ if( ctime > expiretime ){
+ vg_error( "Ticket expired (client %u)\n", msg->m_conn );
+
+ /* TODO: Send expired information */
+ SteamAPI_ISteamNetworkingSockets_CloseConnection(
+ hSteamNetworkingSockets,
+ msg->m_conn, 0, NULL, 1 );
+ return;
+ }
+ }
+
+ CSteamID steamid;
+ SteamEncryptedAppTicket_GetTicketSteamID( decrypted, ticket_len, &steamid );
+ vg_success( "User is authenticated! steamid %lu (%u)\n",
+ steamid.m_unAll64Bits, msg->m_conn );
+
+ set_connection_authsteamid( msg->m_conn, steamid.m_unAll64Bits );
+}
+
+static int inet_require_auth( SteamNetworkingMessage_t *msg ){
+ if( gameserver.auth_mode == eServerModeNoAuthentication )
+ return 1;
+
+ if( get_connection_authsteamid( msg ) == k_connection_unauthorized ){
+ vg_warn( "Unauthorized request! Disconnecting client: %u\n",
+ msg->m_conn );
+
+ SteamAPI_ISteamNetworkingSockets_CloseConnection(
+ hSteamNetworkingSockets,
+ msg->m_conn, 0, NULL, 1 );
+
+ return 0;
+ }
+ else return 1;
+}
+
+static void on_inet_score_request( SteamNetworkingMessage_t *msg ){
+ if( !inet_require_auth(msg) ) return;
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, msg->m_conn,
+ &scoreboard_client_data, sizeof(netmsg_scoreboard),
+ k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+static void on_inet_set_nickname( SteamNetworkingMessage_t *msg ){
+ if(!inet_require_auth(msg)) return;
+
+ u64_steamid steamid = get_connection_authsteamid(msg);
+ netmsg_set_nickname *setnick = msg->m_pData;
+ if( msg->m_cbSize < sizeof(netmsg_set_nickname) ){
+ vg_warn( "Invalid nickname request from client: %u, steamid: %lu\n",
+ msg->m_conn, steamid );
+ return;
+ }
+
+ highscore_set_user_nickname( steamid, setnick->nickname );
+}
+
+static void on_inet_set_score( SteamNetworkingMessage_t *msg ){
+ if(!inet_require_auth(msg)) return;
+
+ u64_steamid steamid = get_connection_authsteamid(msg);
+
+ if( msg->m_cbSize < sizeof(netmsg_set_score) ){
+ vg_warn( "Invalid set score post from client: %u, steamid: %lu\n",
+ msg->m_conn, steamid );
+ return;
+ }
+
+ netmsg_set_score *info = msg->m_pData;
+
+ if( msg->m_cbSize < sizeof(netmsg_set_score) +
+ sizeof(struct netmsg_score_record)*info->record_count ){
+ vg_warn( "Malformed set score post from client: %u, steamid: %lu\n",
+ msg->m_conn, steamid );
+ return;
+ }
+
+ for( int i=0; i<info->record_count; i++ ){
+ highscore_record temp;
+ temp.trackid = info->records[i].trackid;
+ temp.datetime = time(NULL);
+ temp.playerid = steamid;
+ temp.points = info->records[i].points;
+ temp.time = info->records[i].time;
+
+ highscores_push_record( &temp );
+ }
+}
+
+static void on_inet_playerframe( SteamNetworkingMessage_t *msg ){
+ if( msg->m_cbSize < sizeof(netmsg_playerframe) ){
+ return;
+ }
+
+
+ netmsg_playerframe *info = msg->m_pData;
+ vg_info( "... @: %.2f %.2f %.2f\n",
+ //msg->m_identityPeer,
+ info->pos_temp[0], info->pos_temp[1], info->pos_temp[2] );
+}
+
+static void poll_connections(void){
+ SteamNetworkingMessage_t *messages[32];
+ int len;
+
+ while(1){
+ len = SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnPollGroup(
+ hSteamNetworkingSockets,
+ gameserver.client_group, messages, vg_list_size(messages) );
+
+ if( len <= 0 )
+ return;
+
+ for( int i=0; i<len; i++ ){
+ SteamNetworkingMessage_t *msg = messages[i];
+
+ if( msg->m_cbSize < sizeof(netmsg_blank) ){
+ vg_warn( "Discarding message (too small: %d)\n",
+ msg->m_cbSize );
+ continue;
+ }
+
+ netmsg_blank *tmp = msg->m_pData;
+
+ if( tmp->inetmsg_id == k_inetmsg_auth )
+ on_inet_auth( msg );
+ else if( tmp->inetmsg_id == k_inetmsg_scores_request )
+ on_inet_score_request( msg );
+ else if( tmp->inetmsg_id == k_inetmsg_set_nickname )
+ on_inet_set_nickname( msg );
+ else if( tmp->inetmsg_id == k_inetmsg_set_score )
+ on_inet_set_score( msg );
+ else if( tmp->inetmsg_id == k_inetmsg_playerframe )
+ on_inet_playerframe( msg );
+ else {
+ vg_warn( "Unknown inetmsg_id recieved from client. (%u)\n",
+ tmp->inetmsg_id );
+ }
+
+ SteamAPI_SteamNetworkingMessage_t_Release( msg );
+ }
+ }
+}
+
+static u64 seconds_to_server_ticks( double s ){
+ return s / 0.01;
+}
+
+static void generate_boards(void){
+ FILE *fp = fopen( "www/html/srhighscores.txt", "w" );
+
+ if( !fp ){
+ vg_error( "Can't write boards to www/html/srhighscores.txt\n" );
+ return;
+ }
+
+ for( int i=0; i<vg_list_size(track_infos); i++ ){
+ struct netmsg_board *board = &scoreboard_client_data.boards[i];
+
+ highscores_board_generate( board->data, i, 10 );
+ highscores_board_printf( fp, board->data, 10 );
+ }
+
+ fclose( fp );
+}
+
+int main( int argc, char *argv[] ){
+ signal( SIGINT, inthandler );
+ signal( SIGQUIT, inthandler );
+ signal( SIGPIPE, SIG_IGN );
+
+ char *arg;
+ while( vg_argp( argc, argv ) ){
+ if( vg_long_opt( "noauth" ) )
+ gameserver.auth_mode = eServerModeNoAuthentication;
+ }
+
+ /* TODO: Options to override, ammend, remove etc */
+
+ vg_set_mem_quota( 80*1024*1024 );
+ vg_alloc_quota();
+
+ highscores_init( 250000, 10000 );
+
+ if( !highscores_read() )
+ highscores_create_db();
+
+ steamworks_ensure_txt( "2103940" );
+
+ if( gameserver.auth_mode == eServerModeAuthentication ){
+ if( !vg_load_steam_symetric_key( "application_key",
+ gameserver.app_symmetric_key )){
+ return 0;
+ }
+ }
+ else{
+ vg_warn( "Running without user authentication.\n" );
+ }
+
+ if( !SteamGameServer_Init( 0, 27400, 27401,
+ gameserver.auth_mode, "1.0.0.0" ) ){
+ vg_error( "SteamGameServer_Init failed\n" );
+ return 0;
+ }
+
+ void *hSteamGameServer = SteamAPI_SteamGameServer();
+ SteamAPI_ISteamGameServer_LogOnAnonymous( hSteamGameServer );
+
+ SteamAPI_ManualDispatch_Init();
+ HSteamPipe hsteampipe = SteamGameServer_GetHSteamPipe();
+
+ //hSteamHTTP = SteamAPI_SteamGameServerHTTP();
+ hSteamNetworkingSockets =
+ SteamAPI_SteamGameServerNetworkingSockets_SteamAPI();
+
+ /*
+ * Server code
+ */
+
+ steam_register_callback( k_iSteamNetAuthenticationStatus, on_auth_status );
+ steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack,
+ on_connect_status );
+
+ vg_success( "Steamworks API running\n" );
+ steamworks_event_loop( hsteampipe );
+
+ /*
+ * Create a listener
+ */
+
+ HSteamListenSocket listener;
+ SteamNetworkingIPAddr localAddr;
+ SteamAPI_SteamNetworkingIPAddr_Clear( &localAddr );
+ localAddr.m_port = 27402;
+
+ listener = SteamAPI_ISteamNetworkingSockets_CreateListenSocketIP(
+ hSteamNetworkingSockets, &localAddr, 0, NULL );
+ gameserver.client_group = SteamAPI_ISteamNetworkingSockets_CreatePollGroup(
+ hSteamNetworkingSockets );
+
+ u64 server_ticks = 8000,
+ last_record_save = 8000,
+ last_scoreboard_gen = 0,
+ last_monitor_heartbeat = 0;
+
+ generate_boards();
+ monitor_start_server();
+
+ while( !sig_stop ){
+ monitor_event_loop();
+ steamworks_event_loop( hsteampipe );
+ poll_connections();
+
+ usleep(10000);
+ server_ticks ++;
+
+ if( server_ticks >
+ (last_monitor_heartbeat + seconds_to_server_ticks(10.0))){
+ last_monitor_heartbeat = server_ticks;
+ monitor_heartbeat();
+ }
+
+ if( server_ticks > last_scoreboard_gen + seconds_to_server_ticks(60.0) ){
+ last_scoreboard_gen = server_ticks;
+ generate_boards();
+ }
+
+ if( server_ticks > last_record_save + seconds_to_server_ticks(10.0*60.0)){
+ last_record_save = server_ticks;
+ highscores_serialize_all();
+ }
+ }
+
+ highscores_serialize_all();
+
+ SteamAPI_ISteamNetworkingSockets_DestroyPollGroup( hSteamNetworkingSockets,
+ gameserver.client_group );
+ SteamAPI_ISteamNetworkingSockets_CloseListenSocket(
+ hSteamNetworkingSockets, listener );
+
+ vg_info( "Shutting down\n..." );
+ SteamGameServer_Shutdown();
+
+ return 0;
+}
--- /dev/null
+#ifndef GAMESERVER_H
+#define GAMESERVER_H
+
+#define VG_SERVER
+#include "vg/vg.h"
+#include "vg/vg_steam.h"
+#include "vg/vg_steam_networking.h"
+#include "vg/vg_steam_http.h"
+#include "vg/vg_steam_auth.h"
+#include "network_msg.h"
+#include "highscores.h"
+#include <sys/socket.h>
+
+struct {
+ HSteamNetPollGroup client_group;
+ EServerMode auth_mode;
+
+ u8 app_symmetric_key[ k_nSteamEncryptedAppTicketSymmetricKeyLen ];
+
+ int monitor_fd;
+ int monitor_clients[ 4 ];
+}
+static gameserver = {
+ .auth_mode = eServerModeAuthentication
+};
+
+static ISteamNetworkingSockets *hSteamNetworkingSockets = NULL;
+
+#endif /* GAMESERVER_H */
--- /dev/null
+#ifndef MONITORINFO_H
+#define MONITORINFO_H
+
+static const char *MONITOR_SOCK_PATH = "\0skaterift.server_monitor";
+
+#endif /* MONITORINFO_H */
--- /dev/null
+VG_STATIC void scores_update(void);
+
+VG_STATIC void on_auth_ticket_recieved( void *result, void *context ){
+ EncryptedAppTicketResponse_t *response = result;
+
+ if( response->m_eResult == k_EResultOK ){
+ vg_info( " New app ticket ready\n" );
+ }
+ else{
+ vg_warn( " Could not request new encrypted app ticket (%u)\n",
+ response->m_eResult );
+ }
+
+ if( SteamAPI_ISteamUser_GetEncryptedAppTicket( hSteamUser,
+ network_client.app_symmetric_key,
+ vg_list_size(network_client.app_symmetric_key),
+ &network_client.app_key_length )){
+ vg_success( " Loaded app ticket\n" );
+ }
+ else{
+ vg_error( " No ticket availible\n" );
+ network_client.app_key_length = 0;
+ }
+}
+
+VG_STATIC void request_auth_ticket(void){
+ /*
+ * TODO Check for one thats cached on the disk and load it.
+ * This might be OK though because steam seems to cache the result
+ */
+
+ vg_info( "Requesting new authorization ticket\n" );
+
+ vg_steam_async_call *call = vg_alloc_async_steam_api_call();
+ call->userdata = NULL;
+ call->p_handler = on_auth_ticket_recieved;
+ call->id =
+ SteamAPI_ISteamUser_RequestEncryptedAppTicket( hSteamUser, NULL, 0 );
+}
+
+VG_STATIC void send_auth_ticket(void){
+ u32 size = sizeof(netmsg_auth) + network_client.app_key_length;
+ netmsg_auth *auth = alloca(size);
+
+ auth->inetmsg_id = k_inetmsg_auth;
+ auth->ticket_length = network_client.app_key_length;
+ for( int i=0; i<network_client.app_key_length; i++ )
+ auth->ticket[i] = network_client.app_symmetric_key[i];
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, network_client.remote, auth, size,
+ k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+VG_STATIC void send_score_request(void){
+ vg_info( "Requesting scores\n" );
+ netmsg_scores_request req;
+ req.inetmsg_id = k_inetmsg_scores_request;
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, network_client.remote,
+ &req, sizeof(netmsg_scores_request),
+ k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+VG_STATIC void send_score_update(void){
+ vg_info( "Sending scores\n" );
+ u32 size = sizeof(netmsg_set_score) +
+ vg_list_size(track_infos)*sizeof(struct netmsg_score_record);
+ netmsg_set_score *setscore = alloca( size );
+ setscore->inetmsg_id = k_inetmsg_set_score;
+
+ int count = 0;
+ for( u32 i=0; i<vg_list_size(track_infos); i++ ){
+ if( track_infos[i].push ){
+ track_infos[i].push = 0;
+
+#if 0
+ highscore_record *user_record = highscore_find_user_record( 0, i );
+
+ if( !user_record ){
+ vg_error( "No score set but tried to upload for track %u\n", i );
+ continue;
+ }
+#endif
+ highscore_record *user_record = &track_infos[i].record;
+
+ setscore->records[count].trackid = i;
+ setscore->records[count].playerid = 0;
+ setscore->records[count].points = user_record->points;
+ setscore->records[count].time = user_record->time;
+
+ count ++;
+ }
+ }
+
+ if( count == 0 ) return;
+ u32 send_size = sizeof(netmsg_set_score) +
+ count*sizeof(struct netmsg_score_record);
+ setscore->record_count = count;
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, network_client.remote, setscore, send_size,
+ k_nSteamNetworkingSend_Reliable, NULL );
+}
+
+VG_STATIC void send_nickname(void){
+ netmsg_set_nickname nick;
+ nick.inetmsg_id = k_inetmsg_set_nickname;
+
+ memset( nick.nickname, 0, 16 );
+ vg_strncpy( steam_username_at_startup, nick.nickname, 16,
+ k_strncpy_allow_cutoff );
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, network_client.remote,
+ &nick, sizeof(netmsg_set_nickname),
+ k_nSteamNetworkingSend_Reliable, NULL );
+
+ network_client.name_update = 0;
+}
+
+static void network_send_playerframe(void){
+ netmsg_playerframe frame;
+ frame.inetmsg_id = k_inetmsg_playerframe;
+ v3_copy( localplayer.rb.co, frame.pos_temp );
+
+ SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
+ hSteamNetworkingSockets, network_client.remote,
+ &frame, sizeof(frame),
+ k_nSteamNetworkingSend_Unreliable, NULL );
+}
+
+VG_STATIC void server_routine_update(void){
+ if( network_client.name_update )
+ send_nickname();
+
+ send_score_update();
+ send_score_request();
+}
+
+VG_STATIC void on_server_connect_status( CallbackMsg_t *msg ){
+ SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
+ vg_info( " Connection status changed for %lu\n", info->m_hConn );
+ vg_info( " %s -> %s\n",
+ string_ESteamNetworkingConnectionState(info->m_eOldState),
+ string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
+
+ if( info->m_hConn == network_client.remote ){
+ network_client.state = info->m_info.m_eState;
+ if( info->m_info.m_eState == k_ESteamNetworkingConnectionState_Connected ){
+ vg_success(" Connected to remote server.. authenticating\n");
+ send_auth_ticket();
+ }
+ }
+ else{
+ vg_warn( " Recieved signal from unknown connection\n" );
+ }
+}
+
+VG_STATIC void network_connect(void){
+ /* Connect to server if not connected */
+ SteamNetworkingIPAddr remoteAddr;
+
+#ifdef SR_USE_LOCALHOST
+ SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr, 27402 );
+#else
+ const char *server_lon1 = "46.101.34.155:27402";
+ SteamAPI_SteamNetworkingIPAddr_ParseString( &remoteAddr, server_lon1 );
+#endif
+
+ char buf[256];
+ SteamAPI_SteamNetworkingIPAddr_ToString( &remoteAddr, buf, 256, 1 );
+ vg_info( "connect to: %s\n", buf );
+
+ network_client.remote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
+ hSteamNetworkingSockets, &remoteAddr, 0, NULL );
+}
+
+VG_STATIC void on_inet_scoreboard( SteamNetworkingMessage_t *msg ){
+ netmsg_scoreboard *sb = msg->m_pData;
+
+ u32 base_size = sizeof(netmsg_scoreboard)-
+ sizeof(struct netmsg_board)*vg_list_size(track_infos),
+ expected = base_size+sizeof(struct netmsg_board)*sb->board_count;
+
+ if( msg->m_cbSize != expected ){
+ vg_error( "Server scoreboard was corrupted. Size: %u != %u\n",
+ msg->m_cbSize, expected );
+ }
+ else{
+ if( vg_list_size(track_infos) > sb->board_count )
+ vg_warn( "Server is out of date, not enough boards recieved\n");
+ else if( vg_list_size(track_infos) < sb->board_count )
+ vg_warn( "Client out of date, server sent more boards than we have\n");
+ else
+ vg_success( "Recieved new scoreboards from server\n" );
+
+ for( int i=0; i < vg_min(sb->board_count,vg_list_size(track_infos)); i++){
+ scoreboard_client_data.boards[i] = sb->boards[i];
+ highscores_board_printf( stdout, sb->boards[i].data, 10 );
+ }
+ }
+
+ /* We dont need to stay on the server currently */
+ SteamAPI_ISteamNetworkingSockets_CloseConnection(
+ hSteamNetworkingSockets, network_client.remote, 0, NULL, 1 );
+
+ network_scores_updated = 1;
+}
+
+VG_STATIC void poll_remote_connection(void){
+ SteamNetworkingMessage_t *messages[32];
+ int len;
+
+ for( int i=0; i<10; i++ ){
+ len = SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection(
+ hSteamNetworkingSockets, network_client.remote,
+ messages, vg_list_size(messages));
+
+ if( len <= 0 )
+ return;
+
+ for( int i=0; i<len; i++ ){
+ SteamNetworkingMessage_t *msg = messages[i];
+
+ if( msg->m_cbSize < sizeof(netmsg_blank) ){
+ vg_warn( "Discarding message (too small: %d)\n", msg->m_cbSize );
+ continue;
+ }
+
+ netmsg_blank *tmp = msg->m_pData;
+
+ if( tmp->inetmsg_id == k_inetmsg_scoreboard )
+ on_inet_scoreboard( msg );
+
+ SteamAPI_SteamNetworkingMessage_t_Release( msg );
+ }
+ }
+}
+
+VG_STATIC void network_update(void){
+ if( !steam_ready )
+ return;
+
+ ESteamNetworkingConnectionState state = network_client.state;
+
+ if( state == k_ESteamNetworkingConnectionState_Connected ){
+ poll_remote_connection();
+ f64 frame_delta = vg.time_real - network_client.last_frame;
+
+ if( frame_delta > 0.1 ){
+ network_client.last_frame = vg.time_real;
+ network_send_playerframe();
+ }
+ }
+ else {
+ if( (state == k_ESteamNetworkingConnectionState_Connecting) ||
+ (state == k_ESteamNetworkingConnectionState_FindingRoute) ){
+ return;
+ }
+ else {
+ f64 waited = vg.time_real - network_client.last_attempt,
+ min_wait = 1.0;
+
+ if( network_client.retries > 5 )
+ min_wait = 60.0;
+
+ if( waited < min_wait )
+ return;
+
+ network_connect();
+ network_client.retries ++;
+ network_client.last_attempt = vg.time_real;
+ }
+ }
+}
+
+VG_STATIC void network_init(void){
+ if( steam_ready ){
+ steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack,
+ on_server_connect_status );
+ request_auth_ticket();
+ }
+}
+
+VG_STATIC void network_end(void){
+ /* TODO: Send buffered highscores that were not already */
+ if( (network_client.state == k_ESteamNetworkingConnectionState_Connected) ||
+ (network_client.state == k_ESteamNetworkingConnectionState_Connecting) )
+ {
+ SteamAPI_ISteamNetworkingSockets_CloseConnection(
+ hSteamNetworkingSockets, network_client.remote, 0, NULL, 1 );
+ }
+}
*/
#ifdef SR_NETWORKED
-/*
- * Runtime connection stuff
- */
-VG_STATIC u8 steam_app_ticket[ 1024 ];
-VG_STATIC u32 steam_app_ticket_length;
-VG_STATIC int network_name_update = 1;
-
-VG_STATIC HSteamNetConnection cremote;
-VG_STATIC ESteamNetworkingConnectionState cremote_state =
- k_ESteamNetworkingConnectionState_None;
-
-/*
- * Implementation
- */
-
-VG_STATIC void scores_update(void);
-
-VG_STATIC void on_auth_ticket_recieved( void *result, void *context )
-{
- EncryptedAppTicketResponse_t *response = result;
-
- if( response->m_eResult == k_EResultOK )
- {
- vg_info( " New app ticket ready\n" );
- }
- else
- {
- vg_warn( " Could not request new encrypted app ticket (%u)\n",
- response->m_eResult );
- }
+struct {
+ u8 app_symmetric_key[ 1024 ];
+ u32 app_key_length;
+ EServerMode auth_mode;
- if( SteamAPI_ISteamUser_GetEncryptedAppTicket( hSteamUser,
- steam_app_ticket,
- vg_list_size(steam_app_ticket),
- &steam_app_ticket_length ))
- {
- vg_success( " Loaded app ticket (%u bytes)\n", steam_app_ticket_length );
- }
- else
- {
- vg_error( " No ticket availible\n" );
- steam_app_ticket_length = 0;
- }
-}
-
-VG_STATIC void request_auth_ticket(void)
-{
- /*
- * TODO Check for one thats cached on the disk and load it.
- * This might be OK though because steam seems to cache the result
- */
-
- vg_info( "Requesting new authorization ticket\n" );
-
- vg_steam_async_call *call = vg_alloc_async_steam_api_call();
- call->userdata = NULL;
- call->p_handler = on_auth_ticket_recieved;
- call->id =
- SteamAPI_ISteamUser_RequestEncryptedAppTicket( hSteamUser, NULL, 0 );
-}
-
-VG_STATIC void send_auth_ticket(void)
-{
- u32 size = sizeof(netmsg_auth) + steam_app_ticket_length;
- netmsg_auth *auth = alloca(size);
-
- auth->inetmsg_id = k_inetmsg_auth;
- auth->ticket_length = steam_app_ticket_length;
- for( int i=0; i<steam_app_ticket_length; i++ )
- auth->ticket[i] = steam_app_ticket[i];
-
- SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
- hSteamNetworkingSockets, cremote, auth, size,
- k_nSteamNetworkingSend_Reliable, NULL );
-}
-
-VG_STATIC void send_score_request(void)
-{
- vg_info( "Requesting scores\n" );
- netmsg_scores_request req;
- req.inetmsg_id = k_inetmsg_scores_request;
-
- SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
- hSteamNetworkingSockets, cremote, &req, sizeof(netmsg_scores_request),
- k_nSteamNetworkingSend_Reliable, NULL );
-}
-
-VG_STATIC void send_score_update(void)
-{
- vg_info( "Sending scores\n" );
- u32 size = sizeof(netmsg_set_score) +
- vg_list_size(track_infos)*sizeof(struct netmsg_score_record);
- netmsg_set_score *setscore = alloca( size );
- setscore->inetmsg_id = k_inetmsg_set_score;
-
- int count = 0;
- for( u32 i=0; i<vg_list_size(track_infos); i++ ){
- if( track_infos[i].push ){
- track_infos[i].push = 0;
-
-#if 0
- highscore_record *user_record = highscore_find_user_record( 0, i );
-
- if( !user_record ){
- vg_error( "No score set but tried to upload for track %u\n", i );
- continue;
- }
-#endif
- highscore_record *user_record = &track_infos[i].record;
-
- setscore->records[count].trackid = i;
- setscore->records[count].playerid = 0;
- setscore->records[count].points = user_record->points;
- setscore->records[count].time = user_record->time;
-
- count ++;
- }
- }
-
- if( count == 0 ) return;
- u32 send_size = sizeof(netmsg_set_score) +
- count*sizeof(struct netmsg_score_record);
- setscore->record_count = count;
-
- SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
- hSteamNetworkingSockets, cremote, setscore, send_size,
- k_nSteamNetworkingSend_Reliable, NULL );
-}
-
-VG_STATIC void send_nickname(void)
-{
- netmsg_set_nickname nick;
- nick.inetmsg_id = k_inetmsg_set_nickname;
-
- memset( nick.nickname, 0, 16 );
- vg_strncpy( steam_username_at_startup, nick.nickname, 16,
- k_strncpy_allow_cutoff );
-
- SteamAPI_ISteamNetworkingSockets_SendMessageToConnection(
- hSteamNetworkingSockets, cremote, &nick, sizeof(netmsg_set_nickname),
- k_nSteamNetworkingSend_Reliable, NULL );
-
- network_name_update = 0;
-}
+ int name_update;
-VG_STATIC void server_routine_update(void)
-{
- send_auth_ticket();
-
- if( network_name_update )
- send_nickname();
-
- send_score_update();
- send_score_request();
-}
-
-VG_STATIC void on_server_connect_status( CallbackMsg_t *msg )
-{
- SteamNetConnectionStatusChangedCallback_t *info = (void *)msg->m_pubParam;
- vg_info( " Connection status changed for %lu\n", info->m_hConn );
- vg_info( " %s -> %s\n",
- string_ESteamNetworkingConnectionState(info->m_eOldState),
- string_ESteamNetworkingConnectionState(info->m_info.m_eState) );
-
- if( info->m_hConn == cremote )
- {
- cremote_state = info->m_info.m_eState;
- if( info->m_info.m_eState ==
- k_ESteamNetworkingConnectionState_Connected )
- {
- vg_success(" Connected to remote server.. running updates\n");
- server_routine_update();
- }
- }
- else
- {
- vg_warn( " Recieved signal from unknown connection\n" );
- }
-}
-
-VG_STATIC void network_connect_gc(void)
-{
- /* Connect to server if not connected */
- SteamNetworkingIPAddr remoteAddr;
-
-#ifdef SR_USE_LOCALHOST
- SteamAPI_SteamNetworkingIPAddr_SetIPv6LocalHost( &remoteAddr, 27402 );
-#else
- const char *server_lon1 = "46.101.34.155:27402";
- SteamAPI_SteamNetworkingIPAddr_ParseString( &remoteAddr, server_lon1 );
-#endif
-
- char buf[256];
- SteamAPI_SteamNetworkingIPAddr_ToString( &remoteAddr, buf, 256, 1 );
- vg_info( "connect to: %s\n", buf );
-
- cremote = SteamAPI_ISteamNetworkingSockets_ConnectByIPAddress(
- hSteamNetworkingSockets, &remoteAddr, 0, NULL );
-}
-
-VG_STATIC void on_inet_scoreboard( SteamNetworkingMessage_t *msg )
-{
- netmsg_scoreboard *sb = msg->m_pData;
-
- u32 base_size = sizeof(netmsg_scoreboard)-
- sizeof(struct netmsg_board)*vg_list_size(track_infos),
- expected = base_size+sizeof(struct netmsg_board)*sb->board_count;
-
- if( msg->m_cbSize != expected ){
- vg_error( "Server scoreboard was corrupted. Size: %u != %u\n",
- msg->m_cbSize, expected );
- }
- else{
- if( vg_list_size(track_infos) > sb->board_count )
- vg_warn( "Server is out of date, not enough boards recieved\n");
- else if( vg_list_size(track_infos) < sb->board_count )
- vg_warn( "Client out of date, server sent more boards than we have\n");
- else
- vg_success( "Recieved new scoreboards from server\n" );
-
- for( int i=0; i < vg_min(sb->board_count,vg_list_size(track_infos)); i++){
- scoreboard_client_data.boards[i] = sb->boards[i];
- highscores_board_printf( stdout, sb->boards[i].data, 10 );
- }
- }
-
- /* We dont need to stay on the server currently */
- SteamAPI_ISteamNetworkingSockets_CloseConnection(
- hSteamNetworkingSockets, cremote, 0, NULL, 1 );
-
- network_scores_updated = 1;
-}
-
-VG_STATIC void poll_connection(void)
-{
- SteamNetworkingMessage_t *messages[32];
- int len;
-
- while(1){
- len = SteamAPI_ISteamNetworkingSockets_ReceiveMessagesOnConnection(
- hSteamNetworkingSockets, cremote, messages, vg_list_size(messages));
-
- if( len <= 0 )
- return;
-
- for( int i=0; i<len; i++ ){
- SteamNetworkingMessage_t *msg = messages[i];
-
- if( msg->m_cbSize < sizeof(netmsg_blank) ){
- vg_warn( "Discarding message (too small: %d)\n", msg->m_cbSize );
- continue;
- }
-
- netmsg_blank *tmp = msg->m_pData;
-
- if( tmp->inetmsg_id == k_inetmsg_scoreboard )
- on_inet_scoreboard( msg );
-
- SteamAPI_SteamNetworkingMessage_t_Release( msg );
- }
- }
-}
-
-/*
- * Subroutine to be connected to main game loop, runs all routines on timers
- */
-VG_STATIC void network_update(void)
-{
- if( steam_ready ){
- static double last_update = 0.0;
- poll_connection();
-
- if( vg.time > (last_update + 60.0) ){
- last_update = vg.time;
-
- if( steam_app_ticket_length ){
- network_connect_gc();
- }
- else{
- vg_low( "Not making remote connection; app ticket not gotten\n" );
- }
- }
-
- if( vg.time > (last_update + 10.0) &&
- (cremote_state == k_ESteamNetworkingConnectionState_Connected ))
- {
- vg_warn( "Connected to server but no return... disconnecting\n" );
- SteamAPI_ISteamNetworkingSockets_CloseConnection(
- hSteamNetworkingSockets, cremote, 0, NULL, 1 );
- }
- }
-}
-
-VG_STATIC void network_init(void)
-{
- if( steam_ready ){
- steam_register_callback( k_iSteamNetConnectionStatusChangedCallBack,
- on_server_connect_status );
- request_auth_ticket();
- }
-}
+ HSteamNetConnection remote;
+ ESteamNetworkingConnectionState state;
-VG_STATIC void network_end(void)
-{
- /* TODO: Fire off any buffered highscores that need to be setn */
- if( cremote_state == k_ESteamNetworkingConnectionState_Connected ||
- cremote_state == k_ESteamNetworkingConnectionState_Connecting )
- {
- SteamAPI_ISteamNetworkingSockets_CloseConnection(
- hSteamNetworkingSockets, cremote, 0, NULL, 1 );
- }
+ f64 last_attempt, last_frame;
+ u32 retries;
}
+static network_client = {
+ .state = k_ESteamNetworkingConnectionState_None,
+ .auth_mode = eServerModeAuthentication,
+ .name_update = 1
+};
#else /* SR_NETWORKED */
};
/* probably about 10k */
+typedef struct netmsg_playerframe netmsg_playerframe;
+enum{ k_inetmsg_playerframe = 20 };
+struct netmsg_playerframe{
+ u32 inetmsg_id;
+
+ v3f pos_temp;
+};
+
#pragma pack(pop)
#endif /* NETWORK_MSG_H */
--- /dev/null
+#ifndef SERVERMONITOR_H
+#define SERVERMONITOR_H
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef VG_RELEASE
+ #define VG_DEVWINDOW
+#endif
+
+#define VG_3D
+#define VG_GAME
+#define VG_MSG_V1_SUPPORT
+#define VG_LOG_SOURCE_INFO
+#define VG_TIMESTEP_FIXED (1.0/60.0)
+#define VG_NO_STEAM
+#define VG_NO_AUDIO
+#include "vg/vg.h"
+#include "vg/vg_lines.h"
+#include "vg/vg_imgui.h"
+#include "monitorinfo.h"
+
+int main( int argc, char *argv[] ){
+ vg_mem.use_libc_malloc = 0;
+ vg_set_mem_quota( 160*1024*1024 );
+ vg_enter( argc, argv, "Server Monitor" );
+ return 0;
+}
+
+VG_STATIC void vg_launch_opt(void){}
+
+static int sockfd = -1;
+
+static void connect_to_monitor_server(void){
+ struct sockaddr_un serv_addr;
+
+ if((sockfd = socket(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0)) < 0){
+ vg_error("Could not create socket\n");
+ sockfd = -1;
+ return;
+ }
+
+ memset( &serv_addr, 0, sizeof(serv_addr) );
+
+ serv_addr.sun_family = AF_UNIX;
+ strcpy( serv_addr.sun_path, MONITOR_SOCK_PATH );
+
+ vg_info( "Connecting...\n" );
+ if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 ){
+ vg_error("Connect Failed \n");
+ close( sockfd );
+ sockfd = -1;
+ return;
+ }
+
+ vg_success( "Connected\n" );
+}
+
+VG_STATIC void vg_preload(void){}
+
+VG_STATIC void vg_load(void){
+ vg_bake_shaders();
+ vg_console_load_autos();
+}
+
+/*
+ * UPDATE LOOP
+ * ---------------------------------------------------------------------------*/
+
+VG_STATIC void vg_pre_update(void){
+ if( sockfd == -1 ) return;
+
+ char recvBuff[1024];
+ int len = read(sockfd, recvBuff, sizeof(recvBuff)-1);
+
+ if( len > 0 ){
+ recvBuff[ len ] = 0;
+ vg_info( "%s", recvBuff );
+ }
+}
+
+VG_STATIC void vg_fixed_update(void){
+}
+
+VG_STATIC void vg_post_update(void){
+}
+
+/*
+ * RENDERING
+ * ---------------------------------------------------------------------------*/
+
+VG_STATIC void vg_framebuffer_resize( int w, int h ){
+}
+
+VG_STATIC void vg_render(void){
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glViewport( 0,0, vg.window_x, vg.window_y );
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_BLEND );
+
+ glClearColor( 0.1f, 0.1f, 0.1f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+ vg_lines_drawall();
+}
+
+VG_STATIC void vg_gui(void){
+ vg_ui.wants_mouse = 1;
+ static i32 page = 0;
+ ui_rect panel = { 0, 0, vg.window_x, vg.window_y };
+ ui_rect_pad( panel, (ui_px[]){ 8, 8 } );
+
+ const char *pages[] = { "Status", "Options" };
+ ui_tabs( panel, panel, pages, vg_list_size(pages), &page );
+
+ if( page == 0 ){
+ char buf[512];
+ snprintf( buf, 511, "%sSockfd: %d", (sockfd==-1?KRED:KGRN), sockfd );
+ ui_info( panel, buf );
+
+ if( sockfd == -1 ){
+ if( ui_button( panel, "Reconnect" ) == 1 ){
+ connect_to_monitor_server();
+ }
+ }
+ else{
+ if( ui_button( panel, "Disconnect" ) == 1 ){
+ close( sockfd );
+ sockfd = -1;
+ }
+ }
+ }
+}
+
+#endif /* SERVERMONITOR_H */
--- /dev/null
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include "monitorinfo.h"
+#include "gameserver.h"
+
+static int monitor_write_index( int index, const void *buf, size_t nbyte ){
+ int fd = gameserver.monitor_clients[ index ];
+ if( write( fd, buf, nbyte ) == -1 ){
+ gameserver.monitor_clients[ index ] = -1;
+ vg_error( "Monitor client disconnected (%d)\n", index );
+ close( fd );
+ return 0;
+ }
+ else
+ return 1;
+}
+
+static void monitor_accept_connections(void){
+ char sendbuff[1025];
+ int fd = accept( gameserver.monitor_fd, (struct sockaddr*)NULL, NULL );
+
+ if( fd == -1 )
+ return;
+
+ int index = -1;
+ for( int i=0; i<vg_list_size(gameserver.monitor_clients); i ++ ){
+ if( gameserver.monitor_clients[i] == -1 ){
+ index = i;
+ break;
+ }
+ }
+
+ vg_info( "New monitor client (fd: %d, index: %d)\n", fd, index );
+
+ if( index == -1 ){
+ snprintf( sendbuff, sizeof(sendbuff), "MONITOR_FULL\n" );
+ write( fd, sendbuff, strlen(sendbuff) );
+ close( fd );
+ return;
+ }
+
+ gameserver.monitor_clients[ index ] = fd;
+
+ time_t ticks = time( NULL );
+ snprintf( sendbuff, sizeof(sendbuff), "logged in %.24s\n", ctime(&ticks) );
+ if( monitor_write_index( index, sendbuff, strlen(sendbuff) ) )
+ vg_success( "Accepted\n" );
+}
+
+static void monitor_heartbeat(void){
+ for( int i=0; i<vg_list_size(gameserver.monitor_clients); i++ ){
+ if( gameserver.monitor_clients[i] != -1 )
+ monitor_write_index( i, NULL, 0 );
+ }
+}
+
+static void monitor_start_server(void){
+ for( int i=0; i<vg_list_size(gameserver.monitor_clients); i++ ){
+ gameserver.monitor_clients[i] = -1;
+ }
+
+ struct sockaddr_un serv_addr;
+
+ char sendbuff[1025];
+
+ gameserver.monitor_fd = socket( AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0 );
+ memset( &serv_addr, 0, sizeof(serv_addr) );
+ memset( sendbuff, 0, sizeof(sendbuff) );
+
+ serv_addr.sun_family = AF_UNIX;
+ strcpy( serv_addr.sun_path, MONITOR_SOCK_PATH );
+
+ unlink( MONITOR_SOCK_PATH );
+ bind( gameserver.monitor_fd,
+ (struct sockaddr*)&serv_addr, sizeof(serv_addr) );
+ listen( gameserver.monitor_fd, 4 );
+}
+
+static void monitor_event_loop(void){
+ monitor_accept_connections();
+}
#if 1
#define SR_NETWORKED
+#define SR_USE_LOCALHOST
#ifndef VG_RELEASE
#define VG_DEVWINDOW
#include "highscores.c"
#include "save.c"
#include "respawn.c"
+#include "network.c"
static struct player_avatar localplayer_avatar;
return 0;
}
-VG_STATIC void vg_launch_opt(void){}
+VG_STATIC void vg_launch_opt(void){
+ if( vg_long_opt( "noauth" ) ){
+ network_client.auth_mode = eServerModeNoAuthentication;
+ }
+}
VG_STATIC void vg_preload(void){
//skaterift_read_savedata();