From 7ab522689236c97c418539f2b253850667698f02 Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Mon, 26 Jun 2023 15:19:51 +1200 Subject: [PATCH] Block `TickerJoinGameEvent` in replays (#17649) --- .../Replay/ContentReplayPlaybackManager.cs | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/Content.Client/Replay/ContentReplayPlaybackManager.cs b/Content.Client/Replay/ContentReplayPlaybackManager.cs index 843fcdfbd1..16cdfb79fe 100644 --- a/Content.Client/Replay/ContentReplayPlaybackManager.cs +++ b/Content.Client/Replay/ContentReplayPlaybackManager.cs @@ -1,10 +1,12 @@ using Content.Client.Administration.Managers; using Content.Client.Launcher; using Content.Client.MainMenu; +using Content.Client.Replay.Spectator; using Content.Client.Replay.UI.Loading; using Content.Client.UserInterface.Systems.Chat; using Content.Shared.Chat; using Content.Shared.GameTicking; +using Content.Shared.GameWindow; using Content.Shared.Hands; using Content.Shared.Instruments; using Content.Shared.Popups; @@ -16,6 +18,7 @@ using Content.Shared.Weapons.Ranged.Systems; using Robust.Client; using Robust.Client.Console; using Robust.Client.GameObjects; +using Robust.Client.Player; using Robust.Client.Replays.Loading; using Robust.Client.Replays.Playback; using Robust.Client.State; @@ -38,6 +41,7 @@ public sealed class ContentReplayPlaybackManager [Dependency] private readonly IReplayPlaybackManager _playback = default!; [Dependency] private readonly IClientConGroupController _conGrp = default!; [Dependency] private readonly IClientAdminManager _adminMan = default!; + [Dependency] private readonly IPlayerManager _player = default!; /// /// UI state to return to when stopping a replay or loading fails. @@ -98,36 +102,53 @@ public sealed class ContentReplayPlaybackManager private bool OnHandleReplayMessage(object message, bool skipEffects) { + // TODO REPLAYS figure out a cleaner way of doing this. This sucks. + // Maybe wrap the event in another cancellable event and raise that? + + // This is where replays filter through networked messages and can choose to ignore or give them special treatment. + // In particular, we want to avoid spamming pop-ups, sounds, and visual effect entities while fast forwarding. + // E.g., when rewinding 1 tick, we really rewind back to the last checkpoint and then fast forward. Currently, this is + // effectively an EntityEvent blacklist. + switch (message) - { - case BoundUserInterfaceMessage: - break; // TODO REPLAYS refactor BUIs - case ChatMessage chat: - // Just pass on the chat message to the UI controller, but skip speech-bubbles if we are fast-forwarding. - _uiMan.GetUIController().ProcessChatMessage(chat, speechBubble: !skipEffects); - return true; - // TODO REPLAYS figure out a cleaner way of doing this. This sucks. - // Next: we want to avoid spamming animations, sounds, and pop-ups while scrubbing or rewinding time - // (e.g., to rewind 1 tick, we really rewind ~60 and then fast forward 59). Currently, this is - // effectively an EntityEvent blacklist. But this is kinda shit and should be done differently somehow. - // The unifying aspect of these events is that they trigger pop-ups, UI changes, spawn client-side - // entities or start animations. - case RoundEndMessageEvent: - case PopupEvent: - case AudioMessage: - case PickupAnimationEvent: - case MeleeLungeEvent: - case SharedGunSystem.HitscanEvent: - case ImpactEffectEvent: - case MuzzleFlashEvent: - case DamageEffectEvent: - case InstrumentStartMidiEvent: - case InstrumentMidiEventEvent: - case InstrumentStopMidiEvent: - if (!skipEffects) - _entMan.DispatchReceivedNetworkMsg((EntityEventArgs)message); - return true; - } + { + case BoundUserInterfaceMessage: // TODO REPLAYS refactor BUIs + case RequestWindowAttentionEvent: + // Mark as handled -- the event won't get raised. + return true; + case TickerJoinGameEvent: + if (!_entMan.EntityExists(_player.LocalPlayer?.ControlledEntity)) + _entMan.System().SetSpectatorPosition(default); + return true; + } + + if (!skipEffects) + { + // Don't mark as handled -- the event get raised as a normal networked event. + return false; + } + + switch (message) + { + case ChatMessage chat: + // Pass the chat message to the UI controller, skip the speech-bubble / pop-up. + _uiMan.GetUIController().ProcessChatMessage(chat, speechBubble: false); + return true; + case RoundEndMessageEvent: + case PopupEvent: + case AudioMessage: + case PickupAnimationEvent: + case MeleeLungeEvent: + case SharedGunSystem.HitscanEvent: + case ImpactEffectEvent: + case MuzzleFlashEvent: + case DamageEffectEvent: + case InstrumentStartMidiEvent: + case InstrumentMidiEventEvent: + case InstrumentStopMidiEvent: + // Block visual effects, pop-ups, and sounds + return true; + } return false; }