• R/O
  • SSH

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisión88b99ea5632e5ec30de61a3c2bbe3ac5c5ecf61b (tree)
Tiempo2022-03-08 23:19:49
AutorLéonard <hobbax3@gmai...>
CommiterLéonard

Log Message

Merged with 3.1-alpha-211205-2031.

Cambiar Resumen

Diferencia incremental

diff -r b66aef2a070a -r 88b99ea5632e src/cl_commands.cpp
--- a/src/cl_commands.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/cl_commands.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -432,7 +432,7 @@
432432 CLIENT_MOVE_COMMAND_s moveCMD = clientcommand_CreateMoveCommand( );
433433
434434 // [AK] If we don't want to send backup commands, send only this one and that's it.
435- if (( sv_smoothplayers == 0 ) || ( cl_backupcommands == 0 ))
435+ if ( cl_backupcommands == 0 )
436436 {
437437 CLIENT_GetLocalBuffer( )->ByteStream.WriteByte( CLC_CLIENTMOVE );
438438 clientcommand_WriteMoveCommandToBuffer( moveCMD );
diff -r b66aef2a070a -r 88b99ea5632e src/cl_main.cpp
--- a/src/cl_main.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/cl_main.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -3496,7 +3496,7 @@
34963496 const BYTE oldPlayerClass = pPlayer->CurrentPlayerClass;
34973497
34983498 // Set up the player class.
3499- pPlayer->CurrentPlayerClass = playerClass;
3499+ pPlayer->CurrentPlayerClass = clamp<int>( playerClass, 0, PlayerClasses.Size() -1 );
35003500 pPlayer->cls = PlayerClasses[pPlayer->CurrentPlayerClass].Type;
35013501
35023502 if ( isMorphed )
@@ -5798,7 +5798,7 @@
57985798 UCVarValue Value;
57995799
58005800 // Read in the gameskill setting, and set gameskill to this setting.
5801- Value.Int = pByteStream->ReadByte();
5801+ Value.Int = clamp<int>( pByteStream->ReadByte(), 0, AllSkills.Size() - 1);
58025802 gameskill.ForceSet( Value, CVAR_Int );
58035803
58045804 // Do the same for botskill.
diff -r b66aef2a070a -r 88b99ea5632e src/g_shared/st_hud.cpp
--- a/src/g_shared/st_hud.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/g_shared/st_hud.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -543,7 +543,7 @@
543543 ULONG ulTimeLeft = MIN( g_lRespawnDelay, 1 + ( g_lRespawnGametic - level.time ) / TICRATE );
544544
545545 bottomString += "\n" TEXTCOLOR_GREEN;
546- bottomString.AppendFormat( "Ready to respawn in %d second%s", ulTimeLeft, ulTimeLeft != 1 ? "s" : "" );
546+ bottomString.AppendFormat( "Ready to respawn in %lu second%s", ulTimeLeft, ulTimeLeft != 1 ? "s" : "" );
547547 }
548548 }
549549
diff -r b66aef2a070a -r 88b99ea5632e src/gamemode.cpp
--- a/src/gamemode.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/gamemode.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -1123,6 +1123,7 @@
11231123 return true;
11241124
11251125 const GAMEEVENT_e DamageEvent = bBeforeArmor ? GAMEEVENT_ACTOR_ARMORDAMAGED : GAMEEVENT_ACTOR_DAMAGED;
1126+ const int originalDamage = damage;
11261127
11271128 // [AK] We somehow need to pass all the actor pointers into the script itself. A simple way
11281129 // to do this is temporarily spawn a temporary actor and change its actor pointers to the target,
@@ -1141,7 +1142,8 @@
11411142 temp->Destroy( );
11421143
11431144 // [AK] If the new damage is zero, that means the target shouldn't take damage in P_DamageMobj.
1144- return ( damage != 0 );
1145+ // Allow P_DamageMobj to execute anyways if the original damage was zero (i.e. NODAMAGE flag).
1146+ return ( originalDamage == 0 || damage != 0 );
11451147 }
11461148
11471149 //*****************************************************************************
@@ -1445,6 +1447,10 @@
14451447 case GAMELIMIT_WAVES:
14461448 wavelimit.ForceSet( Val, CVAR_Int );
14471449 break;
1450+
1451+ default:
1452+ I_Error( "GAMEMODE_SetLimit: Unhandled GameLimit\n." );
1453+ break;
14481454 }
14491455 }
14501456
diff -r b66aef2a070a -r 88b99ea5632e src/p_acs.cpp
--- a/src/p_acs.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/p_acs.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -9510,7 +9510,7 @@
95109510 int capacity, offset, a, c;
95119511 if (CharArrayParms(capacity, offset, a, Stack, sp, pcd == PCD_PRINTMAPCHRANGE))
95129512 {
9513- while (capacity-- && (c = activeBehavior->GetArrayVal (a, offset)) != '\0')
9513+ while (capacity-- && (c = activeBehavior->GetArrayVal (*activeBehavior->MapVars[a], offset)) != '\0')
95149514 {
95159515 work += (char)c;
95169516 offset++;
diff -r b66aef2a070a -r 88b99ea5632e src/p_setup.cpp
--- a/src/p_setup.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/p_setup.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -4670,6 +4670,11 @@
46704670 // a "map" map change during possessions hold countdown to a CTF/ST map, the counter would stay
46714671 // on the screen of the clients after the map change.
46724672 {
4673+ // [AK] In case we changed levels in the middle of a duel's win sequence, just start a new duel
4674+ // so the loser still gets sent to spectators.
4675+ if (( DUEL_GetState( ) == DS_WINSEQUENCE ) && ( DUEL_GetStartNextDuelOnLevelLoad( ) == false ))
4676+ DUEL_SetStartNextDuelOnLevelLoad( true );
4677+
46734678 DUEL_SetState( DS_WAITINGFORPLAYERS );
46744679 LASTMANSTANDING_SetState( LMSS_WAITINGFORPLAYERS );
46754680 POSSESSION_SetState( PSNS_WAITINGFORPLAYERS );
@@ -4680,6 +4685,16 @@
46804685 // [BB] We have to reset the state though when this is a new game.
46814686 if ( ( SURVIVAL_GetState( ) == SURVS_COUNTDOWN ) || ( gameaction == ga_newgame ) )
46824687 SURVIVAL_SetState( SURVS_WAITINGFORPLAYERS );
4688+
4689+ // [AK] If we still advanced to the next map when the mission failed, then either the countdown
4690+ // if there's still people playing, or reset the state entirely.
4691+ if ( SURVIVAL_GetState( ) == SURVS_MISSIONFAILED )
4692+ {
4693+ if ( SERVER_CalcNumNonSpectatingPlayers( MAXPLAYERS ) < 1 )
4694+ SURVIVAL_SetState( SURVS_WAITINGFORPLAYERS );
4695+ else
4696+ SURVIVAL_StartCountdown(( sv_survivalcountdowntime > 0 ? sv_survivalcountdowntime : 20 ) * TICRATE - 1 );
4697+ }
46834698 }
46844699
46854700 if ( NETWORK_InClientMode() == false )
diff -r b66aef2a070a -r 88b99ea5632e src/sv_commands.cpp
--- a/src/sv_commands.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/sv_commands.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -3380,9 +3380,17 @@
33803380 if ( pActor == NULL )
33813381 return;
33823382
3383- // [AK] If the actor is a player, don't tell clients to play the sound while we're backtracing their movement.
3383+ // [AK] There's a few sounds that we shouldn't play if it originated from a player who we're backtracing.
33843384 if (( pActor->player ) && ( SERVER_IsBacktracingPlayer( pActor->player - players )))
3385- return;
3385+ {
3386+ static const char *pszRestrictedSounds[7] = { "*grunt", "*land", "*falling", "*jump", "*dive", "*surface", "*gasp" };
3387+
3388+ for ( unsigned int i = 0; i < 7; i++ )
3389+ {
3390+ if ( stricmp( pszSound, pszRestrictedSounds[i] ) == 0 )
3391+ return;
3392+ }
3393+ }
33863394
33873395 // [BB] If the actor doesn't have a NetID, we have to instruct the clients differently how to play the sound.
33883396 if ( pActor->NetID == -1 )
diff -r b66aef2a070a -r 88b99ea5632e src/sv_main.cpp
--- a/src/sv_main.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/sv_main.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -172,7 +172,7 @@
172172 static bool server_InfoCheat( BYTESTREAM_s* pByteStream );
173173 static bool server_CheckLogin( const ULONG ulClient );
174174 static void server_PrintWithIP( FString message, const NETADDRESS_s &address );
175-static void server_PerformBacktrace( ULONG ulClient );
175+static void server_PerformBacktrace( ULONG ulClient, ULONG ulNumLateMoveCMDs );
176176 static bool server_ShouldPerformBacktrace( ULONG ulClient );
177177 static void server_FixZFromBacktrace( APlayerPawn *pmo, fixed_t oldFloorZ );
178178
@@ -2038,6 +2038,10 @@
20382038 // should be able to go back is the gametic they connected with.
20392039 g_aClients[lClient].lLastServerGametic = gametic;
20402040
2041+ // [AK] Clear any recent command gametics from the client.
2042+ g_aClients[lClient].recentMoveCMDs.clear();
2043+ g_aClients[lClient].recentSelectCMDs.clear();
2044+
20412045 // [AK] Reset the client's tic buffer.
20422046 SERVER_ResetClientTicBuffer( lClient );
20432047
@@ -5200,56 +5204,61 @@
52005204 const ULONG ulClientTic = cmd->getClientTic( );
52015205 const bool bIsMoveCMD = cmd->isMoveCmd( );
52025206
5203- // [AK] Ignore commands that arrived too late or are duplicates of commands we already processed,
5204- // neither of which we can account for anymore. This way, we aren't processing the same commands
5205- // again, or that happened too far into the past.
5206- if (( ulClientTic != 0 ) && ( ulClientTic <= g_aClients[g_lCurrentClient].ulClientGameTic ))
5207- {
5208- delete cmd;
5209- return false;
5207+ // [AK] Ignore commands that are duplicates of commands we already received and/or processed.
5208+ // This way, we won't process the exact same commands multiple times.
5209+ if ( ulClientTic != 0 )
5210+ {
5211+ RingBuffer<ULONG, MAX_RECENT_COMMANDS> *recentCMDs;
5212+
5213+ // [AK] Move commands and weapon select commands each have their own ring buffers, since
5214+ // a movement and weapon select commands with the same gametic can co-exist.
5215+ recentCMDs = bIsMoveCMD ? &g_aClients[g_lCurrentClient].recentMoveCMDs : &g_aClients[g_lCurrentClient].recentSelectCMDs;
5216+
5217+ for ( unsigned int i = 0; i < MAX_RECENT_COMMANDS; i++ )
5218+ {
5219+ if ( recentCMDs->getOldestEntry( i ) == ulClientTic )
5220+ {
5221+ delete cmd;
5222+ return false;
5223+ }
5224+ }
5225+
5226+ // [AK] Save this gametic into the ring buffer for later use.
5227+ recentCMDs->put( ulClientTic );
52105228 }
52115229
52125230 if ( sv_useticbuffer )
52135231 {
52145232 if ( ulClientTic != 0 )
52155233 {
5216- if ( sv_smoothplayers )
5234+ // [AK] It's possible that we were extrapolating this player's movement. If that's the case,
5235+ // then we're going to store any incoming commands into a separate buffer until we receive
5236+ // as many of them as we emulated during extrapolation. Once that happens, we'll use them to
5237+ // backtrace the player's actual movement.
5238+ if (( sv_smoothplayers ) && ( g_aClients[g_lCurrentClient].ulExtrapolatedTics > 0 ))
52175239 {
5218- // [AK] It's possible this was a command that arrived late and we already extrapolated
5219- // the player's movement at this tic. In this case, we'll store these commands into a
5220- // separate buffer so we can backtrace the player's actual movement.
5221- if (( g_aClients[g_lCurrentClient].LastMoveCMD != NULL ) && ( g_aClients[g_lCurrentClient].ulExtrapolatedTics > 0 ))
5240+ ULONG ulNumLateMoveCMDs = 0;
5241+
5242+ // [AK] Only count how many movement commands are in the buffer, weapon select command don't matter.
5243+ for ( unsigned int i = 0; i < g_aClients[g_lCurrentClient].LateMoveCMDs.Size( ); i++ )
52225244 {
5223- // [AK] We want to try filling this buffer only when the client is suffering from a ping
5224- // spike, not when they're experiencing packet loss.
5225- if ( ulClientTic <= g_aClients[g_lCurrentClient].ulClientGameTic + g_aClients[g_lCurrentClient].ulExtrapolatedTics )
5226- buffer = &g_aClients[g_lCurrentClient].LateMoveCMDs;
5245+ if ( g_aClients[g_lCurrentClient].LateMoveCMDs[i]->isMoveCmd( ))
5246+ ulNumLateMoveCMDs++;
52275247 }
5248+
5249+ if ( ulNumLateMoveCMDs < g_aClients[g_lCurrentClient].ulExtrapolatedTics )
5250+ buffer = &g_aClients[g_lCurrentClient].LateMoveCMDs;
52285251 }
52295252
52305253 for ( unsigned int i = 0; i < buffer->Size( ); i++ )
52315254 {
52325255 ULONG ulBufferClientTic = (*buffer)[i]->getClientTic( );
52335256
5234- if ( ulBufferClientTic != 0 )
5257+ // [AK] Reorganize the commands in case they arrived in the wrong order.
5258+ if (( ulBufferClientTic != 0 ) && ( ulClientTic < ulBufferClientTic ))
52355259 {
5236- // [AK] Double-check to make sure we don't already have this command stored anywhere in the buffer.
5237- // If it's not a late command, we also need to make sure there aren't any newer move commands already
5238- // in the tic buffer. If any of these conditions fail, we have to ignore this command.
5239- // Movement and weapon select commands with the same gametic can co-exist in the tic buffer, as
5240- // they're not the same command, but two movement or weapon select commands cannot.
5241- if (( ulBufferClientTic == ulClientTic ) && ( bIsMoveCMD == (*buffer)[i]->isMoveCmd( )))
5242- {
5243- delete cmd;
5244- return false;
5245- }
5246-
5247- // [AK] Reorganize the commands in case they arrived in the wrong order.
5248- if ( ulClientTic < ulBufferClientTic )
5249- {
5250- buffer->Insert( i, cmd );
5251- return false;
5252- }
5260+ buffer->Insert( i, cmd );
5261+ return false;
52535262 }
52545263 }
52555264 }
@@ -5386,8 +5395,8 @@
53865395
53875396 // [AK] If we have enough late commands in the buffer, process them all immediately, so as long
53885397 // as they hadn't morphed or unmorphed at any point during extrapolation.
5389- if (( ulNumLateMoveCMDs > 0 ) && ( ulNumMoveCMDs > 0 || ulNumLateMoveCMDs == pClient->ulExtrapolatedTics ) && ( pClient->OldData != NULL ))
5390- server_PerformBacktrace( ulClient );
5398+ if (( pClient->OldData != NULL ) && ( pClient->ulExtrapolatedTics > 0 ) && ( pClient->ulExtrapolatedTics == ulNumLateMoveCMDs ))
5399+ server_PerformBacktrace( ulClient, ulNumLateMoveCMDs );
53915400
53925401 // [AK] If there are no movement commands left in the client's tic buffer then we'll keep processing
53935402 // the last movement command we received from them, but we won't extrapolate more than we should.
@@ -5407,15 +5416,6 @@
54075416
54085417 pClient->LastMoveCMD->process( ulClient );
54095418 }
5410-
5411- // [AK] Reset the client's extrapolation data if necessary.
5412- if (( ulNumMoveCMDs > 0 ) && ( pClient->ulExtrapolatedTics > 0 ))
5413- {
5414- if ( sv_smoothplayers_debuginfo )
5415- Printf( "%d: resetting extrapolation data for %s.\n", gametic, players[ulClient].userinfo.GetName( ));
5416-
5417- SERVER_ResetClientExtrapolation( ulClient );
5418- }
54195419 }
54205420 else if ( pClient->ulExtrapolatedTics > 0 )
54215421 {
@@ -5467,14 +5467,7 @@
54675467
54685468 // [AK] Clear all stored commands in the tic buffer.
54695469 for ( unsigned int i = 0; i < g_aClients[ulClient].MoveCMDs.Size( ); i++ )
5470- {
5471- // [AK] Set the client's gametic to the last command in their tic buffer that has a non-zero
5472- // gametic. This way, any old and therefore invalid backup commands will be rejected.
5473- if ( g_aClients[ulClient].MoveCMDs[i]->getClientTic( ) != 0 )
5474- g_aClients[ulClient].ulClientGameTic = g_aClients[ulClient].MoveCMDs[i]->getClientTic( );
5475-
54765470 delete g_aClients[ulClient].MoveCMDs[i];
5477- }
54785471
54795472 g_aClients[ulClient].MoveCMDs.Clear( );
54805473
@@ -5504,12 +5497,9 @@
55045497 // to the last late command we received from them and update their gametic.
55055498 if ( bUpdatedLastMoveCMD == false )
55065499 {
5507- ULONG ulNewClientGametic = g_aClients[ulClient].LastMoveCMD->getClientTic( ) + g_aClients[ulClient].ulExtrapolatedTics;
5508-
55095500 delete g_aClients[ulClient].LastMoveCMD;
55105501 g_aClients[ulClient].LastMoveCMD = static_cast<ClientMoveCommand *>( g_aClients[ulClient].LateMoveCMDs[i] );
55115502
5512- g_aClients[ulClient].LastMoveCMD->setClientTic( ulNewClientGametic );
55135503 bUpdatedLastMoveCMD = true;
55145504 continue;
55155505 }
@@ -7447,7 +7437,7 @@
74477437
74487438 //*****************************************************************************
74497439 //
7450-static void server_PerformBacktrace( ULONG ulClient )
7440+static void server_PerformBacktrace( ULONG ulClient, ULONG ulNumLateMoveCMDs )
74517441 {
74527442 CLIENT_s *pClient = &g_aClients[ulClient];
74537443 APlayerPawn *pmo = players[ulClient].mo;
@@ -7477,39 +7467,25 @@
74777467 // [AK] Check if the player hasn't moved into a spot that's blocking them or something else.
74787468 if ( P_TestMobjLocation( players[ulClient].mo ))
74797469 {
7480- ULONG ulExtrapolateStartTic = pClient->LastMoveCMD->getClientTic( );
7481- ULONG ulNumExtrapolatedTics = pClient->ulExtrapolatedTics;
7470+ ULONG ulNumProcessedMoveCMDs = 0;
74827471 fixed_t oldFloorZ = 0;
74837472
74847473 pClient->bIsBacktracing = true;
74857474 pClient->ulExtrapolatedTics = 0;
74867475
7487- // [AK] Ideally, we want to have as many late move commands in the buffer as the number of tics we
7488- // extrapolated this player for. If that's not the case, however, then we'll try "filling in the gaps"
7489- // by re-processing the command we last processed until every tic is accounted for.
7490- for ( ULONG ulTic = 1; ulTic <= ulNumExtrapolatedTics; ulTic++ )
7476+ for ( int tic = 0; tic < static_cast<int>( pClient->LateMoveCMDs.Size( )); tic++ )
74917477 {
7492- if (( pClient->LateMoveCMDs.Size( ) > 0 ) && ( pClient->LateMoveCMDs[0]->getClientTic( ) == ulExtrapolateStartTic + ulTic ))
7478+ // [AK] If this is a weapon select command, just process it and move onto the next late command.
7479+ if ( pClient->LateMoveCMDs[tic]->isMoveCmd( ) == false )
74937480 {
7494- // [AK] If this is a weapon select command, just process it and move onto the next late command.
7495- if ( pClient->LateMoveCMDs[0]->isMoveCmd( ) == false )
7496- {
7497- pClient->LateMoveCMDs[0]->process( ulClient );
7498-
7499- delete pClient->LateMoveCMDs[0];
7500- pClient->LateMoveCMDs.Delete( 0 );
7501-
7502- ulTic--;
7503- continue;
7504- }
7505-
7506- delete pClient->LastMoveCMD;
7507- pClient->LastMoveCMD = new ClientMoveCommand( *static_cast<ClientMoveCommand *>( pClient->LateMoveCMDs[0] ));
7508-
7509- delete pClient->LateMoveCMDs[0];
7510- pClient->LateMoveCMDs.Delete( 0 );
7481+ pClient->LateMoveCMDs[tic]->process( ulClient );
7482+ continue;
75117483 }
75127484
7485+ // [AK] This becomes the last movement command we received from the client.
7486+ delete pClient->LastMoveCMD;
7487+ pClient->LastMoveCMD = new ClientMoveCommand( *static_cast<ClientMoveCommand *>( pClient->LateMoveCMDs[tic] ));
7488+
75137489 pClient->LastMoveCMD->process( ulClient );
75147490
75157491 // [AK] Now we have to tick this player's body and set the proper psprite settings.
@@ -7521,7 +7497,7 @@
75217497
75227498 // [AK] Adjust the sector ceiling/floor heights for the next tic that we extrapolated the player.
75237499 // We don't have to do this on the last tic that we extrapolated the player.
7524- if ( ulTic < ulNumExtrapolatedTics )
7500+ if ( ++ulNumProcessedMoveCMDs < ulNumLateMoveCMDs )
75257501 {
75267502 unlaggedIndex = ( unlaggedIndex + 1 ) % UNLAGGEDTICS;
75277503
@@ -7546,8 +7522,6 @@
75467522 // [AK] As a final measure, fix the player's floorz/ceilingz and to ensure that they don't
75477523 // get stuck in the floor/ceiling of whatever sector they're supposed to be in.
75487524 server_FixZFromBacktrace( pmo, oldFloorZ );
7549-
7550- pClient->LastMoveCMD->setClientTic( ulExtrapolateStartTic + ulNumExtrapolatedTics );
75517525 debugMessage += "accepted";
75527526 }
75537527 else
@@ -7619,7 +7593,7 @@
76197593 {
76207594 pmo->z = pmo->floorz;
76217595 }
7622- else
7596+ else if ( oldFloorZ != pmo->floorz )
76237597 {
76247598 // [AK] Check if the player should move with the floor if it moved, similarly to PIT_FloorDrop.
76257599 if (( pmo->velz == 0 ) && (!( pmo->flags & MF_NOGRAVITY ) || ( pmo->z == oldFloorZ && !( pmo->flags & MF_NOLIFTDROP ))))
diff -r b66aef2a070a -r 88b99ea5632e src/sv_main.h
--- a/src/sv_main.h Tue Mar 08 15:18:58 2022 +0100
+++ b/src/sv_main.h Tue Mar 08 15:19:49 2022 +0100
@@ -82,6 +82,9 @@
8282 // Amount of time the client has to report his checksum of the level.
8383 #define CLIENT_CHECKSUM_WAITTIME ( 15 * TICRATE )
8484
85+// [AK] Maximum amount of gametics of recent commands from a client that we can store.
86+#define MAX_RECENT_COMMANDS 15
87+
8588 // This is for the server console, but since we normally can't include that (win32 stuff),
8689 // we can just put it here.
8790 #define UDF_NAME 0x00000001
@@ -392,6 +395,12 @@
392395 // [BB] A record of the gametics the client called protected minor commands, e.g. toggleconsole.
393396 RingBuffer<LONG, 100> minorCommandInstances;
394397
398+ // [AK] A list of gametics of the last few movement commands the client sent us.
399+ RingBuffer<ULONG, MAX_RECENT_COMMANDS> recentMoveCMDs;
400+
401+ // [AK] A list of (non-zero) gametics of the last few weapon select commands the client sent us.
402+ RingBuffer<ULONG, MAX_RECENT_COMMANDS> recentSelectCMDs;
403+
395404 // A record of the gametic the client spoke at. We store the last MAX_CHATINSTANCE_STORAGE
396405 // times the client chatted. This is used to chat spam protection.
397406 LONG lChatInstances[MAX_CHATINSTANCE_STORAGE];
diff -r b66aef2a070a -r 88b99ea5632e src/team.cpp
--- a/src/team.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/team.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -1243,7 +1243,8 @@
12431243 //
12441244 player_t *TEAM_GetCarrier( ULONG ulTeamIdx )
12451245 {
1246- if ( TEAM_CheckIfValid( ulTeamIdx ))
1246+ // [AK] Also make sure that this team's carrier is still valid.
1247+ if (( TEAM_CheckIfValid( ulTeamIdx )) && ( PLAYER_IsValidPlayerWithMo( teams[ulTeamIdx].g_pCarrier - players )))
12471248 return ( teams[ulTeamIdx].g_pCarrier );
12481249
12491250 return ( NULL );
diff -r b66aef2a070a -r 88b99ea5632e src/win32/serverconsole/serverconsole.cpp
--- a/src/win32/serverconsole/serverconsole.cpp Tue Mar 08 15:18:58 2022 +0100
+++ b/src/win32/serverconsole/serverconsole.cpp Tue Mar 08 15:19:49 2022 +0100
@@ -512,8 +512,7 @@
512512 RECT ThisWindowRect;
513513 ANIMATIONINFO AnimationInfo;
514514 NOTIFYICONDATA NotifyIconData;
515- UCVarValue Val;
516- char szString[64];
515+ FString uncolorizedHostname;
517516
518517 AnimationInfo.cbSize = sizeof( AnimationInfo );
519518 SystemParametersInfo( SPI_GETANIMATION, sizeof( AnimationInfo ), &AnimationInfo, 0 );
@@ -547,10 +546,12 @@
547546 NotifyIconData.uCallbackMessage = UWM_TRAY_TRAYID;
548547 NotifyIconData.hIcon = g_hSmallIcon;
549548
550- Val = sv_hostname.GetGenericRep( CVAR_String );
551- strncpy( szString, Val.String, 63 );
552- szString[63] = 0;
553- lstrcpy( NotifyIconData.szTip, szString );
549+ // [AK] Remove any color codes in the server name before sending it off.
550+ uncolorizedHostname = sv_hostname.GetGenericRep( CVAR_String ).String;
551+ V_ColorizeString( uncolorizedHostname );
552+ V_RemoveColorCodes( uncolorizedHostname );
553+
554+ lstrcpy( NotifyIconData.szTip, uncolorizedHostname.GetChars( ));
554555
555556 Shell_NotifyIcon( NIM_ADD, &NotifyIconData );
556557 break;