fix: lobby music volume will be changed on options change without restart (also lobby music not looped anymore) (#25530)

* fix: lobby music volume will be changed on options change without restart (also lobby music not looped anymore)

* refactor: now lobby music is part of ContentAudioSystem. Lobby playlist is used instead of single track. Client now selects next lobby soundtrack after previous finished.

* refactor: incapsulated info on current lobby track in simple record

* refactor: fixed inconsistent naming between song and soundtrack for lobbymusic

* refactor: xml-doc for LobbyPlaylistChangedEvent

* fix: inverted invalid _audio.PlayGlobal check to return only if lobby soundtrack play call failed

---------

Co-authored-by: pa.pecherskij <pa.pecherskij@interfax.ru>
This commit is contained in:
Fildrance
2024-03-02 23:40:04 +03:00
committed by GitHub
parent 4f7facbd73
commit 4c87dcd3cb
13 changed files with 402 additions and 270 deletions

View File

@@ -1,19 +1,37 @@
using System.Linq;
using Content.Server.GameTicking;
using Content.Server.GameTicking.Events;
using Content.Shared.Audio;
using Content.Shared.Audio.Events;
using Content.Shared.GameTicking;
using Robust.Server.Audio;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
namespace Content.Server.Audio;
public sealed class ContentAudioSystem : SharedContentAudioSystem
{
[ValidatePrototypeId<SoundCollectionPrototype>]
private const string LobbyMusicCollection = "LobbyMusic";
[Dependency] private readonly AudioSystem _serverAudio = default!;
[Dependency] private readonly IRobustRandom _robustRandom = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private SoundCollectionPrototype _lobbyMusicCollection = default!;
private string[]? _lobbyPlaylist;
public override void Initialize()
{
base.Initialize();
_lobbyMusicCollection = _prototypeManager.Index<SoundCollectionPrototype>(LobbyMusicCollection);
_lobbyPlaylist = ShuffleLobbyPlaylist();
SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnPlayerJoinedLobby);
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundCleanup);
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnProtoReload);
@@ -36,4 +54,33 @@ public sealed class ContentAudioSystem : SharedContentAudioSystem
// yeah it's whacky af.
_serverAudio.ReloadPresets();
}
private void OnPlayerJoinedLobby(PlayerJoinedLobbyEvent ev)
{
if (_lobbyPlaylist != null)
{
var session = ev.PlayerSession;
RaiseNetworkEvent(new LobbyPlaylistChangedEvent(_lobbyPlaylist), session);
}
}
private void OnRoundEnd(RoundEndMessageEvent ev)
{
// The lobby song is set here instead of in RestartRound,
// because ShowRoundEndScoreboard triggers the start of the music playing
// at the end of a round, and this needs to be set before RestartRound
// in order for the lobby song status display to be accurate.
_lobbyPlaylist = ShuffleLobbyPlaylist();
RaiseNetworkEvent(new LobbyPlaylistChangedEvent(_lobbyPlaylist));
}
private string[] ShuffleLobbyPlaylist()
{
var playlist = _lobbyMusicCollection.PickFiles
.Select(x => x.ToString())
.ToArray();
_robustRandom.Shuffle(playlist);
return playlist;
}
}

View File

@@ -94,7 +94,7 @@ namespace Content.Server.GameTicking
private TickerLobbyStatusEvent GetStatusMsg(ICommonSession session)
{
_playerGameStatuses.TryGetValue(session.UserId, out var status);
return new TickerLobbyStatusEvent(RunLevel != GameRunLevel.PreRoundLobby, LobbySong, LobbyBackground, status == PlayerGameStatus.ReadyToPlay, _roundStartTime, RoundPreloadTime, RoundStartTimeSpan, Paused);
return new TickerLobbyStatusEvent(RunLevel != GameRunLevel.PreRoundLobby, LobbyBackground, status == PlayerGameStatus.ReadyToPlay, _roundStartTime, RoundPreloadTime, RoundStartTimeSpan, Paused);
}
private void SendStatusToAll()

View File

@@ -1,68 +0,0 @@
using Robust.Shared.Audio;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server.GameTicking
{
public sealed partial class GameTicker
{
[ValidatePrototypeId<SoundCollectionPrototype>]
private const string LobbyMusicCollection = "LobbyMusic";
[ViewVariables]
private bool _lobbyMusicInitialized = false;
[ViewVariables]
private SoundCollectionPrototype _lobbyMusicCollection = default!;
[ViewVariables]
public string? LobbySong { get; private set; }
private void InitializeLobbyMusic()
{
DebugTools.Assert(!_lobbyMusicInitialized);
_lobbyMusicCollection = _prototypeManager.Index<SoundCollectionPrototype>(LobbyMusicCollection);
// Now that the collection is set, the lobby music has been initialized and we can choose a random song.
_lobbyMusicInitialized = true;
ChooseRandomLobbySong();
}
/// <summary>
/// Sets the current lobby song, or stops it if null.
/// </summary>
/// <param name="song">The lobby song to play, or null to stop any lobby songs.</param>
public void SetLobbySong(string? song)
{
DebugTools.Assert(_lobbyMusicInitialized);
if (song == null)
{
LobbySong = null;
return;
// TODO GAMETICKER send song stop event
}
LobbySong = song;
// TODO GAMETICKER send song change event
}
/// <summary>
/// Plays a random song from the LobbyMusic sound collection.
/// </summary>
public void ChooseRandomLobbySong()
{
DebugTools.Assert(_lobbyMusicInitialized);
SetLobbySong(_robustRandom.Pick(_lobbyMusicCollection.PickFiles).ToString());
}
/// <summary>
/// Stops the current lobby song being played.
/// </summary>
public void StopLobbySong()
{
SetLobbySong(null);
}
}
}

View File

@@ -301,12 +301,6 @@ namespace Content.Server.GameTicking
RunLevel = GameRunLevel.PostRound;
// The lobby song is set here instead of in RestartRound,
// because ShowRoundEndScoreboard triggers the start of the music playing
// at the end of a round, and this needs to be set before RestartRound
// in order for the lobby song status display to be accurate.
LobbySong = _robustRandom.Pick(_lobbyMusicCollection.PickFiles).ToString();
ShowRoundEndScoreboard(text);
SendRoundEndDiscordMessage();
}
@@ -394,8 +388,17 @@ namespace Content.Server.GameTicking
var listOfPlayerInfoFinal = listOfPlayerInfo.OrderBy(pi => pi.PlayerOOCName).ToArray();
var sound = RoundEndSoundCollection == null ? null : _audio.GetSound(new SoundCollectionSpecifier(RoundEndSoundCollection));
RaiseNetworkEvent(new RoundEndMessageEvent(gamemodeTitle, roundEndText, roundDuration, RoundId,
listOfPlayerInfoFinal.Length, listOfPlayerInfoFinal, LobbySong, sound));
var roundEndMessageEvent = new RoundEndMessageEvent(
gamemodeTitle,
roundEndText,
roundDuration,
RoundId,
listOfPlayerInfoFinal.Length,
listOfPlayerInfoFinal,
sound
);
RaiseNetworkEvent(roundEndMessageEvent);
RaiseLocalEvent(roundEndMessageEvent);
_replayRoundPlayerInfo = listOfPlayerInfoFinal;
_replayRoundText = roundEndText;

View File

@@ -93,7 +93,6 @@ namespace Content.Server.GameTicking
InitializeStatusShell();
InitializeCVars();
InitializePlayer();
InitializeLobbyMusic();
InitializeLobbyBackground();
InitializeGamePreset();
DebugTools.Assert(_prototypeManager.Index<JobPrototype>(FallbackOverflowJob).Name == FallbackOverflowJobName,