diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17120c593..af299ed07 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -262,7 +262,7 @@ jobs: steps: - name: Install tools - run: brew install coreutils pkg-config sdl2 + run: brew install coreutils sdl2 # pkg-config - uses: actions/checkout@v4 with: @@ -305,7 +305,7 @@ jobs: # 7z a -r quake3e-linux-armv7.zip ./linux-armv7/* - name: Create latest build - uses: marvinpinto/action-automatic-releases@latest + uses: czietz/action-automatic-releases@latest with: repo_token: ${{ secrets.GITHUB_TOKEN }} automatic_release_tag: "latest" diff --git a/code/server/server.h b/code/server/server.h index d05ad1811..174423182 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -351,11 +351,12 @@ void SV_GetChallenge( const netadr_t *from ); void SV_InitChallenger( void ); void SV_DirectConnect( const netadr_t *from ); +void SV_PrintClientStateChange( const client_t *cl, clientState_t newState ); void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ); void SV_UserinfoChanged( client_t *cl, qboolean updateUserinfo, qboolean runFilter ); -void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ); +void SV_ClientEnterWorld( client_t *client ); void SV_FreeClient( client_t *client ); void SV_DropClient( client_t *drop, const char *reason ); diff --git a/code/server/sv_ccmds.c b/code/server/sv_ccmds.c index 8c06b65b5..ab8a6494d 100644 --- a/code/server/sv_ccmds.c +++ b/code/server/sv_ccmds.c @@ -291,13 +291,13 @@ static void SV_MapRestart_f( void ) { // generate a new serverid // TTimo - don't update restartedserverId there, otherwise we won't deal correctly with multiple map_restart sv.serverId = com_frameTime; - Cvar_Set( "sv_serverid", va("%i", sv.serverId ) ); + Cvar_SetIntegerValue( "sv_serverid", sv.serverId ); // if a map_restart occurs while a client is changing maps, we need // to give them the correct time so that when they finish loading // they don't violate the backwards time check in cl_cgame.c - for (i=0 ; iinteger ; i++) { - if (svs.clients[i].state == CS_PRIMED) { + for ( i = 0; i < sv_maxclients->integer; i++ ) { + if ( svs.clients[i].state == CS_PRIMED ) { svs.clients[i].oldServerTime = sv.restartTime; } } @@ -351,13 +351,8 @@ static void SV_MapRestart_f( void ) { continue; } - if ( client->state == CS_ACTIVE ) - SV_ClientEnterWorld( client, &client->lastUsercmd ); - else { - // If we don't reset client->lastUsercmd and are restarting during map load, - // the client will hang because we'll use the last Usercmd from the previous map, - // which is wrong obviously. - SV_ClientEnterWorld( client, NULL ); + if ( client->state == CS_ACTIVE ) { + SV_ClientEnterWorld( client ); } } diff --git a/code/server/sv_client.c b/code/server/sv_client.c index 6e4619000..42b47ec86 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -424,6 +424,39 @@ static const char *SV_FindCountry( const char *tld ) { } +static const char *SV_GetStateName( clientState_t state ) { + switch ( state ) { + case CS_FREE: return "CS_FREE"; + case CS_ZOMBIE: return "CS_ZOMBIE"; + case CS_CONNECTED: return "CS_CONNECTED"; + case CS_PRIMED: return "CS_PRIMED"; + case CS_ACTIVE: return "CS_ACTIVE"; + default: return "CS_UNKNOWN"; + } +} + + +void SV_PrintClientStateChange( const client_t *cl, clientState_t newState ) { + + if ( cl->state == newState ) { + return; + } + +#ifndef _DEBUG + if ( com_developer->integer == 0 ) { + return; + } +#endif // !_DEBUG + + if ( cl->name[0] != '\0' ) { + Com_Printf( "Going from %s to %s for %s\n", SV_GetStateName( cl->state ), SV_GetStateName( newState ), cl->name ); + } else { + Com_Printf( "Going from %s to %s for client %d\n", SV_GetStateName( cl->state ), SV_GetStateName( newState ), cl - svs.clients ); + } + +} + + /* ================== SV_DirectConnect @@ -772,7 +805,7 @@ void SV_DirectConnect( const netadr_t *from ) { NET_OutOfBandPrint( NS_SERVER, from, "connectResponse %d", challenge ); } - Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name ); + SV_PrintClientStateChange( newcl, CS_CONNECTED ); newcl->state = CS_CONNECTED; newcl->lastSnapshotTime = svs.time - 9999; // generate a snapshot immediately @@ -826,7 +859,7 @@ or crashing -- SV_FinalMessage() will handle that ===================== */ void SV_DropClient( client_t *drop, const char *reason ) { - char name[ MAX_NAME_LENGTH ]; + char name[ sizeof( drop->name ) ]; qboolean isBot; int i; @@ -870,7 +903,8 @@ void SV_DropClient( client_t *drop, const char *reason ) { // bots shouldn't go zombie, as there's no real net connection. drop->state = CS_FREE; } else { - Com_DPrintf( "Going to CS_ZOMBIE for %s\n", name ); + Q_strncpyz( drop->name, name, sizeof( name ) ); + SV_PrintClientStateChange( drop, CS_ZOMBIE ); drop->state = CS_ZOMBIE; // become free in a few seconds } @@ -990,9 +1024,8 @@ static void SV_SendClientGameState( client_t *client ) { Com_DPrintf( "SV_SendClientGameState() for %s\n", client->name ); - if ( client->state != CS_PRIMED ) { - Com_DPrintf( "Going from CS_CONNECTED to CS_PRIMED for %s\n", client->name ); - } + SV_PrintClientStateChange( client, CS_PRIMED ); + client->state = CS_PRIMED; client->pureAuthentic = qfalse; @@ -1006,6 +1039,10 @@ static void SV_SendClientGameState( client_t *client ) { // gamestate message was not just sent, forcing a retransmit client->gamestateMessageNum = client->netchan.outgoingSequence; + // accept usercmds starting from current server time only + Com_Memset( &client->lastUsercmd, 0x0, sizeof( client->lastUsercmd ) ); + client->lastUsercmd.serverTime = sv.time - 1; + MSG_Init( &msg, msgBuffer, MAX_MSGLEN ); // NOTE, MRE: all server->client messages now acknowledge @@ -1072,11 +1109,12 @@ static void SV_SendClientGameState( client_t *client ) { SV_ClientEnterWorld ================== */ -void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) { +void SV_ClientEnterWorld( client_t *client ) { int clientNum; sharedEntity_t *ent; - Com_DPrintf( "Going from CS_PRIMED to CS_ACTIVE for %s\n", client->name ); + SV_PrintClientStateChange( client, CS_ACTIVE ); + client->state = CS_ACTIVE; // resend all configstrings using the cs commands since these are @@ -1092,13 +1130,8 @@ void SV_ClientEnterWorld( client_t *client, usercmd_t *cmd ) { client->deltaMessage = client->netchan.outgoingSequence - (PACKET_BACKUP + 1); // force delta reset client->lastSnapshotTime = svs.time - 9999; // generate a snapshot immediately - if(cmd) - memcpy(&client->lastUsercmd, cmd, sizeof(client->lastUsercmd)); - else - memset(&client->lastUsercmd, '\0', sizeof(client->lastUsercmd)); - // call the game begin function - VM_Call( gvm, 1, GAME_CLIENT_BEGIN, client - svs.clients ); + VM_Call( gvm, 1, GAME_CLIENT_BEGIN, clientNum ); } @@ -2095,7 +2128,7 @@ static void SV_UserMove( client_t *cl, msg_t *msg, qboolean delta ) { } return; } - SV_ClientEnterWorld( cl, &cmds[0] ); + SV_ClientEnterWorld( cl ); // the moves can be processed normally } diff --git a/code/server/sv_main.c b/code/server/sv_main.c index efccf5f64..1c737430e 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -1117,7 +1117,7 @@ static void SV_CheckTimeouts( void ) { if ( cl->state == CS_ZOMBIE && cl->lastPacketTime - zombiepoint < 0 ) { // using the client id cause the cl->name is empty at this point - Com_DPrintf( "Going from CS_ZOMBIE to CS_FREE for client %d\n", i ); + SV_PrintClientStateChange( cl, CS_FREE ); cl->state = CS_FREE; // can now be reused continue; }