# HG changeset patch # User Adam Kaminski # Date 1606535723 18000 # Fri Nov 27 22:55:23 2020 -0500 # Node ID 0c661b7b855db02ca5e2bcd21ea73fd0422146d6 # Parent a7dc9713d17d795b31169f01c7528bf3e3995c4f Fixed sound channels containing looped sounds not being synced with newly connected clients. diff -r a7dc9713d17d -r 0c661b7b855d docs/zandronum-history.txt --- a/docs/zandronum-history.txt Fri Nov 27 12:07:38 2020 -0500 +++ b/docs/zandronum-history.txt Fri Nov 27 22:55:23 2020 -0500 @@ -43,6 +43,7 @@ - - Fixed the obituary for the BFG tracer not being used if a player was killed by them. [Kaminsky] - - Fixed desaturated translations created with CreateTranslation() not syncing with clients in an online game. [Kaminsky] - - Fixed missiles with the STEPMISSILE flag disappearing in online games. [Kaminsky] +- - Fixed sound channels containing looped sounds not being synced with newly connected clients. [Kaminsky] ! - sv_forcegldefaults renamed to sv_forcevideodefaults. The old name still exists for compatibility. [Dusk] ! - r_3dfloors is now forced to be true when sv_forcevideodefaults is true. [Dusk] ! - When the wad authentication fails for a connecting client, the client only reports the missing and incompatible PWADS instead of all of them. [Pol Marcet] diff -r a7dc9713d17d -r 0c661b7b855d src/p_acs.cpp --- a/src/p_acs.cpp Fri Nov 27 12:07:38 2020 -0500 +++ b/src/p_acs.cpp Fri Nov 27 22:55:23 2020 -0500 @@ -6142,11 +6142,27 @@ { if (!looping) { - S_Sound(spot, chan, sid, vol, atten, true); // [EP] Inform the clients. + // [AK] Check if this actor isn't already looping the same sound on the server. + if (( NETWORK_GetState() != NETSTATE_SERVER ) || (( chan & CHAN_LOOP ) && !SERVER_IsChannelLooping( spot, chan & 7, sid ))) + { + S_Sound(spot, chan, sid, vol, atten, true); // [EP] Inform the clients. + + // [AK] Update the server's list of looping sound channels. + if ( NETWORK_GetState() == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( spot, chan, sid, vol, atten, false ); + } } else if (!S_IsActorPlayingSomething(spot, chan & 7, sid)) { - S_Sound(spot, chan | CHAN_LOOP, sid, vol, atten, true); // [EP] Inform the clients. + // [AK] Check if this actor isn't already looping the same sound on the server. + if (( NETWORK_GetState() != NETSTATE_SERVER ) || (!SERVER_IsChannelLooping( spot, chan & 7, sid ))) + { + S_Sound(spot, chan | CHAN_LOOP, sid, vol, atten, true); // [EP] Inform the clients. + + // [AK] Add this channel to the server's list of looping sound channels. + if ( NETWORK_GetState() == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( spot, chan, sid, vol, atten, false ); + } } } } @@ -6161,6 +6177,10 @@ if (args[0] == 0) { S_StopSound(activator, chan); + + // [AK] If we're the server, remove this channel from the list of looping channels. + if ( NETWORK_GetState() == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( activator, chan, 0, 0, 0, true ); } else { @@ -6170,6 +6190,10 @@ while ((spot = it.Next()) != NULL) { S_StopSound(spot, chan); + + // [AK] If we're the server, remove this channel from the list of looping channels. + if ( NETWORK_GetState() == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( spot, chan, 0, 0, 0, true ); } } } diff -r a7dc9713d17d -r 0c661b7b855d src/p_mobj.cpp --- a/src/p_mobj.cpp Fri Nov 27 12:07:38 2020 -0500 +++ b/src/p_mobj.cpp Fri Nov 27 22:55:23 2020 -0500 @@ -5286,6 +5286,10 @@ // Transform any playing sound into positioned, non-actor sounds. S_RelinkSound (this, NULL); + // [AK] If we're the server, clear all looping channels belonging to this actor. + if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + SERVER_ClearLoopingChannels ( this ); + Super::Destroy (); } diff -r a7dc9713d17d -r 0c661b7b855d src/p_setup.cpp --- a/src/p_setup.cpp Fri Nov 27 12:07:38 2020 -0500 +++ b/src/p_setup.cpp Fri Nov 27 22:55:23 2020 -0500 @@ -3967,6 +3967,8 @@ SERVER_ClearEditedTranslations( ); // [BB] And the stored sector links. SERVER_ClearSectorLinks( ); + // [AK] And the looping sound channels of any actors. + SERVER_ClearLoopingChannels( NULL ); } // Initial height of PointOfView will be set by player think. diff -r a7dc9713d17d -r 0c661b7b855d src/sv_main.cpp --- a/src/sv_main.cpp Fri Nov 27 12:07:38 2020 -0500 +++ b/src/sv_main.cpp Fri Nov 27 22:55:23 2020 -0500 @@ -243,6 +243,9 @@ // [BB] List of all sector links created by calls to Sector_SetLink. static TArray g_SectorLinkList; +// [AK] List of all actor sound channels containing looping sounds. +static TArray g_LoopingChannelList; + // [BB] Seperate log file to debug the tic buffer. static FILE *MoveCMDRegulatorLogFile = NULL; @@ -2649,6 +2652,10 @@ } } + // [AK] Send out any looping sounds that might be playing on an actor's sound channels. + for ( ulIdx = 0; ulIdx < g_LoopingChannelList.Size(); ulIdx++ ) + SERVERCOMMANDS_SoundActor( g_LoopingChannelList[ulIdx].Actor, g_LoopingChannelList[ulIdx].EntChannel | g_LoopingChannelList[ulIdx].ChanFlags | CHAN_LOOP, S_GetName( g_LoopingChannelList[ulIdx].SoundID ), g_LoopingChannelList[ulIdx].Volume, g_LoopingChannelList[ulIdx].DistanceScale, ulClient, SVCF_ONLYTHISCLIENT, true ); + // [BB] If the sky differs from the standard sky, let the client know about it. if ( level.info && ( ( stricmp( level.skypic1, level.info->skypic1 ) != 0 ) @@ -4013,6 +4020,74 @@ //***************************************************************************** // +void SERVER_UpdateLoopingChannels( AActor *pActor, int channel, FSoundID soundid, float fVolume, float fAttenuation, bool bRemove ) +{ + FSoundChan chan; + + chan.Actor = pActor; + chan.EntChannel = channel & 7; + chan.ChanFlags = channel & ~7; + chan.SoundID = soundid; + chan.Volume = fVolume; + chan.DistanceScale = fAttenuation; + + for ( unsigned int i = 0; i < g_LoopingChannelList.Size(); i++ ) + { + if (( g_LoopingChannelList[i].Actor == pActor ) && ( g_LoopingChannelList[i].EntChannel == ( channel & 7 ) )) + { + if (( bRemove ) || ( channel & CHAN_LOOP ) == false ) + g_LoopingChannelList.Delete( i ); + else + g_LoopingChannelList[i] = chan; + + return; + } + } + + g_LoopingChannelList.Push( chan ); +} + +//***************************************************************************** +// +bool SERVER_IsChannelLooping( AActor *pActor, int channel, int soundid ) +{ + for ( unsigned int i = 0; i < g_LoopingChannelList.Size(); i++ ) + { + if (( g_LoopingChannelList[i].Actor == pActor ) && + ( g_LoopingChannelList[i].EntChannel == channel ) && ( g_LoopingChannelList[i].SoundID == soundid )) + { + return true; + } + } + + return false; +} + +//***************************************************************************** +// +void SERVER_ClearLoopingChannels( AActor *pActor ) +{ + unsigned int i = 0; + + if ( pActor != NULL ) + { + while ( i < g_LoopingChannelList.Size() ) + { + if ( g_LoopingChannelList[i].Actor == pActor ) + { + g_LoopingChannelList.Delete( i++ ); + continue; + } + } + + return; + } + + g_LoopingChannelList.Clear( ); +} + +//***************************************************************************** +// void SERVER_ErrorCleanup( void ) { ULONG ulIdx; diff -r a7dc9713d17d -r 0c661b7b855d src/sv_main.h --- a/src/sv_main.h Fri Nov 27 12:07:38 2020 -0500 +++ b/src/sv_main.h Fri Nov 27 22:55:23 2020 -0500 @@ -505,6 +505,9 @@ void SERVER_ClearEditedTranslations( void ); void SERVER_AddSectorLink( ULONG ulSector, int iArg1, int iArg2, int iArg3 ); void SERVER_ClearSectorLinks( void ); +void SERVER_UpdateLoopingChannels( AActor *pActor, int channel, FSoundID soundid, float fVolume, float fAttenuation, bool bRemove ); +bool SERVER_IsChannelLooping( AActor *pActor, int channel, int soundid ); +void SERVER_ClearLoopingChannels( AActor *pActor ); void SERVER_ErrorCleanup( void ); void SERVER_ParsePacket( BYTESTREAM_s *pByteStream ); bool SERVER_ProcessCommand( LONG lCommand, BYTESTREAM_s *pByteStream ); diff -r a7dc9713d17d -r 0c661b7b855d src/thingdef/thingdef_codeptr.cpp --- a/src/thingdef/thingdef_codeptr.cpp Fri Nov 27 12:07:38 2020 -0500 +++ b/src/thingdef/thingdef_codeptr.cpp Fri Nov 27 22:55:23 2020 -0500 @@ -453,18 +453,36 @@ if (!looping) { + // [AK] If we're the server, we have to update the list of looping sound channels. + if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + { + // [AK] Don't loop this sound if it's already looping on this channel. + if (( channel & CHAN_LOOP ) && ( SERVER_IsChannelLooping( self, channel&7, soundid ) )) + return; + + SERVER_UpdateLoopingChannels( self, channel, soundid, volume, attenuation, false ); + } + S_Sound (self, channel, soundid, volume, attenuation, true ); // [BC] Inform the clients. } else { if (!S_IsActorPlayingSomething (self, channel&7, soundid)) { + // [AK] Don't play the sound if it's already looping on this channel on the server. + if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( SERVER_IsChannelLooping( self, channel&7, soundid ) )) + return; + S_Sound (self, channel | CHAN_LOOP, soundid, volume, attenuation); // [BC] If we're the server, tell clients to play the sound. // [Dusk] We need to respect existing sound play since this is a looped sound. + // [AK] Add this channel to the list of looping channels. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + { SERVERCOMMANDS_SoundActor( self, channel | CHAN_LOOP, S_GetName( soundid ), volume, attenuation, MAXPLAYERS, 0, true ); + SERVER_UpdateLoopingChannels( self, channel, soundid, volume, attenuation, false ); + } } } } @@ -475,6 +493,10 @@ ACTION_PARAM_INT(slot, 0); S_StopSound(self, slot); + + // [AK] If we're the server, remove this channel from the list of looping channels. + if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( self, slot, 0, 0, 0, true ); } //========================================================================== @@ -526,17 +548,35 @@ if (!looping) { + // [AK] If we're the server, we have to update the list of looping sound channels. + if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + { + // [AK] Don't loop this sound if it's already looping on this channel. + if (( channel & CHAN_LOOP ) && ( SERVER_IsChannelLooping( self, ( int(channel) - NAME_Auto ) & 7, soundid ) )) + return; + + SERVER_UpdateLoopingChannels( self, channel, soundid, 1, attenuation, false ); + } + S_Sound (self, int(channel) - NAME_Auto, soundid, 1, attenuation, true ); // [BB] Inform the clients. } else { if (!S_IsActorPlayingSomething (self, int(channel) - NAME_Auto, soundid)) { + // [AK] If we're the server, check if this sound isn't already looping on the same channel. + if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && ( SERVER_IsChannelLooping( self, ( int(channel) - NAME_Auto ) & 7, soundid ) ) ) + return; + S_Sound (self, (int(channel) - NAME_Auto) | CHAN_LOOP, soundid, 1, attenuation); // [BB] If we're the server, tell clients to play the sound, but only if they are not already playing something for this actor. + // [AK] Add this channel to the list of looping channels. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) + { SERVERCOMMANDS_SoundActor( self, (int(channel) - NAME_Auto) | CHAN_LOOP, S_GetName( soundid ), 1, attenuation, MAXPLAYERS, 0, true ); + SERVER_UpdateLoopingChannels( self, int(channel) - NAME_Auto, soundid, 1, attenuation, false ); + } } } } @@ -549,6 +589,10 @@ if (channel > NAME_Auto && channel <= NAME_SoundSlot7) { S_StopSound (self, int(channel) - NAME_Auto); + + // [AK] If we're the server, remove this channel from the list of looping channels. + if ( NETWORK_GetState() == NETSTATE_SERVER ) + SERVER_UpdateLoopingChannels( self, int(channel) - NAME_Auto, 0, 0, 0, true ); } }