Misc replay related changes (#13250)

This commit is contained in:
Leon Friedrich
2023-01-08 07:04:09 +13:00
committed by GitHub
parent a9adab88e5
commit f1cb0ca37a
11 changed files with 93 additions and 9 deletions

View File

@@ -40,6 +40,7 @@ public sealed class ChatUIController : UIController
[Dependency] private readonly IClientNetManager _net = default!; [Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IPlayerManager _player = default!; [Dependency] private readonly IPlayerManager _player = default!;
[Dependency] private readonly IStateManager _state = default!; [Dependency] private readonly IStateManager _state = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[UISystemDependency] private readonly ExamineSystem? _examine = default; [UISystemDependency] private readonly ExamineSystem? _examine = default;
[UISystemDependency] private readonly GhostSystem? _ghost = default; [UISystemDependency] private readonly GhostSystem? _ghost = default;
@@ -122,7 +123,7 @@ public sealed class ChatUIController : UIController
/// </summary> /// </summary>
private readonly Dictionary<ChatChannel, int> _unreadMessages = new(); private readonly Dictionary<ChatChannel, int> _unreadMessages = new();
public readonly List<ChatMessage> History = new(); public readonly List<(GameTick, ChatMessage)> History = new();
// Maintains which channels a client should be able to filter (for showing in the chatbox) // Maintains which channels a client should be able to filter (for showing in the chatbox)
// and select (for attempting to send on). // and select (for attempting to send on).
@@ -639,12 +640,12 @@ public sealed class ChatUIController : UIController
private void OnChatMessage(MsgChatMessage message) => ProcessChatMessage(message.Message); private void OnChatMessage(MsgChatMessage message) => ProcessChatMessage(message.Message);
public void ProcessChatMessage(ChatMessage msg) public void ProcessChatMessage(ChatMessage msg, bool speechBubble = true)
{ {
// Log all incoming chat to repopulate when filter is un-toggled // Log all incoming chat to repopulate when filter is un-toggled
if (!msg.HideChat) if (!msg.HideChat)
{ {
History.Add(msg); History.Add((_timing.CurTick, msg));
MessageAdded?.Invoke(msg); MessageAdded?.Invoke(msg);
if (!msg.Read) if (!msg.Read)
@@ -660,7 +661,7 @@ public sealed class ChatUIController : UIController
} }
// Local messages that have an entity attached get a speech bubble. // Local messages that have an entity attached get a speech bubble.
if (msg.SenderEntity == default) if (!speechBubble || msg.SenderEntity == default)
return; return;
switch (msg.Channel) switch (msg.Channel)
@@ -711,6 +712,14 @@ public sealed class ChatUIController : UIController
_typingIndicator?.ClientChangedChatText(); _typingIndicator?.ClientChangedChatText();
} }
public void Repopulate()
{
foreach (var chat in _chats)
{
chat.Repopulate();
}
}
private readonly record struct SpeechBubbleData(string Message, SpeechBubble.SpeechType Type); private readonly record struct SpeechBubbleData(string Message, SpeechBubble.SpeechType Type);
private sealed class SpeechBubbleQueueData private sealed class SpeechBubbleQueueData

View File

@@ -71,13 +71,23 @@ public partial class ChatBox : UIWidget
UpdateSelectedChannel(); UpdateSelectedChannel();
} }
public void Repopulate()
{
Contents.Clear();
foreach (var message in _controller.History)
{
OnMessageAdded(message.Item2);
}
}
private void OnChannelFilter(ChatChannel channel, bool active) private void OnChannelFilter(ChatChannel channel, bool active)
{ {
Contents.Clear(); Contents.Clear();
foreach (var message in _controller.History) foreach (var message in _controller.History)
{ {
OnMessageAdded(message); OnMessageAdded(message.Item2);
} }
if (active) if (active)

View File

@@ -3,6 +3,8 @@ using Content.Shared.Administration;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Replays;
using Robust.Shared.Serialization.Markdown.Mapping;
namespace Content.Server.Administration; namespace Content.Server.Administration;
@@ -11,6 +13,7 @@ namespace Content.Server.Administration;
/// </summary> /// </summary>
public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
{ {
[Dependency] private readonly IReplayRecordingManager _replay = default!;
[Dependency] private readonly IServerNetManager _netManager = default!; [Dependency] private readonly IServerNetManager _netManager = default!;
[Dependency] private readonly IAdminManager _adminManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!;
@@ -18,11 +21,22 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
[Dependency] private readonly ILocalizationManager _localizationManager = default!; [Dependency] private readonly ILocalizationManager _localizationManager = default!;
private readonly List<string> _loadedPrototypes = new(); private readonly List<string> _loadedPrototypes = new();
public IReadOnlyList<string> LoadedPrototypes => _loadedPrototypes;
public void Initialize() public void Initialize()
{ {
_netManager.RegisterNetMessage<GamePrototypeLoadMessage>(ClientLoadsPrototype); _netManager.RegisterNetMessage<GamePrototypeLoadMessage>(ClientLoadsPrototype);
_netManager.Connected += NetManagerOnConnected; _netManager.Connected += NetManagerOnConnected;
_replay.OnRecordingStarted += OnStartReplayRecording;
}
private void OnStartReplayRecording((MappingDataNode, List<object>) initReplayData)
{
// replays will need information about currently loaded prototypes
foreach (var prototype in _loadedPrototypes)
{
initReplayData.Item2.Add(new ReplayPrototypeUploadMsg { PrototypeData = prototype });
}
} }
public void SendGamePrototype(string prototype) public void SendGamePrototype(string prototype)
@@ -47,6 +61,9 @@ public sealed class GamePrototypeLoadManager : IGamePrototypeLoadManager
private void LoadPrototypeData(string prototypeData) private void LoadPrototypeData(string prototypeData)
{ {
_loadedPrototypes.Add(prototypeData); _loadedPrototypes.Add(prototypeData);
_replay.QueueReplayMessage(new ReplayPrototypeUploadMsg { PrototypeData = prototypeData });
var msg = new GamePrototypeLoadMessage var msg = new GamePrototypeLoadMessage
{ {
PrototypeData = prototypeData PrototypeData = prototypeData

View File

@@ -5,6 +5,8 @@ using Content.Shared.CCVar;
using Robust.Server.Player; using Robust.Server.Player;
using Robust.Shared.Configuration; using Robust.Shared.Configuration;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Replays;
using Robust.Shared.Serialization.Markdown.Mapping;
namespace Content.Server.Administration; namespace Content.Server.Administration;
@@ -15,6 +17,7 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
[Dependency] private readonly IServerNetManager _serverNetManager = default!; [Dependency] private readonly IServerNetManager _serverNetManager = default!;
[Dependency] private readonly IConfigurationManager _cfgManager = default!; [Dependency] private readonly IConfigurationManager _cfgManager = default!;
[Dependency] private readonly IServerDbManager _serverDb = default!; [Dependency] private readonly IServerDbManager _serverDb = default!;
[Dependency] private readonly IReplayRecordingManager _replay = default!;
[ViewVariables] public bool Enabled { get; private set; } = true; [ViewVariables] public bool Enabled { get; private set; } = true;
[ViewVariables] public float SizeLimit { get; private set; } = 0f; [ViewVariables] public float SizeLimit { get; private set; } = 0f;
@@ -30,6 +33,16 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
_cfgManager.OnValueChanged(CCVars.ResourceUploadingStoreEnabled, value => StoreUploaded = value, true); _cfgManager.OnValueChanged(CCVars.ResourceUploadingStoreEnabled, value => StoreUploaded = value, true);
AutoDelete(_cfgManager.GetCVar(CCVars.ResourceUploadingStoreDeletionDays)); AutoDelete(_cfgManager.GetCVar(CCVars.ResourceUploadingStoreDeletionDays));
_replay.OnRecordingStarted += OnStartReplayRecording;
}
private void OnStartReplayRecording((MappingDataNode, List<object>) initReplayData)
{
// replays will need information about currently loaded extra resources
foreach (var (path, data) in ContentRoot.GetAllFiles())
{
initReplayData.Item2.Add(new ReplayResourceUploadMsg { RelativePath = path, Data = data });
}
} }
/// <summary> /// <summary>
@@ -63,6 +76,8 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
channel.SendMessage(msg); channel.SendMessage(msg);
} }
_replay.QueueReplayMessage(new ReplayResourceUploadMsg { RelativePath = msg.RelativePath, Data = msg.Data });
if (!StoreUploaded) if (!StoreUploaded)
return; return;

View File

@@ -20,6 +20,7 @@ public sealed class SpraySystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly VaporSystem _vaporSystem = default!; [Dependency] private readonly VaporSystem _vaporSystem = default!;
@@ -118,7 +119,7 @@ public sealed class SpraySystem : EntitySystem
_vaporSystem.Start(vaporComponent, vaporXform, impulseDirection, component.SprayVelocity, target, component.SprayAliveTime, args.User); _vaporSystem.Start(vaporComponent, vaporXform, impulseDirection, component.SprayVelocity, target, component.SprayAliveTime, args.User);
} }
SoundSystem.Play(component.SpraySound.GetSound(), Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.125f)); _audio.PlayPvs(component.SpraySound, uid, component.SpraySound.Params.WithVariation(0.125f));
RaiseLocalEvent(uid, RaiseLocalEvent(uid,
new RefreshItemCooldownEvent(curTime, curTime + TimeSpan.FromSeconds(component.CooldownTime)), true); new RefreshItemCooldownEvent(curTime, curTime + TimeSpan.FromSeconds(component.CooldownTime)), true);

View File

@@ -1,3 +1,6 @@
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Administration; namespace Content.Shared.Administration;
public interface IGamePrototypeLoadManager public interface IGamePrototypeLoadManager
@@ -5,3 +8,12 @@ public interface IGamePrototypeLoadManager
public void Initialize(); public void Initialize();
public void SendGamePrototype(string prototype); public void SendGamePrototype(string prototype);
} }
// TODO REPLAYS
// Figure out a way to just directly save NetMessage objects to replays. This just uses IRobustSerializer as a crutch.
[Serializable, NetSerializable]
public sealed class ReplayPrototypeUploadMsg
{
public string PrototypeData = default!;
}

View File

@@ -1,5 +1,6 @@
using Robust.Shared.ContentPack; using Robust.Shared.ContentPack;
using Robust.Shared.Network; using Robust.Shared.Network;
using Robust.Shared.Serialization;
using Robust.Shared.Utility; using Robust.Shared.Utility;
namespace Content.Shared.Administration; namespace Content.Shared.Administration;
@@ -38,4 +39,14 @@ public abstract class SharedNetworkResourceManager : IDisposable
// MemoryContentRoot uses a ReaderWriterLockSlim, which we need to dispose of. // MemoryContentRoot uses a ReaderWriterLockSlim, which we need to dispose of.
ContentRoot.Dispose(); ContentRoot.Dispose();
} }
// TODO REPLAYS
// Figure out a way to just directly save NetMessage objects to replays. This just uses IRobustSerializer as a crutch.
[Serializable, NetSerializable]
public sealed class ReplayResourceUploadMsg
{
public byte[] Data = default!;
public ResourcePath RelativePath = default!;
}
} }

View File

@@ -77,6 +77,9 @@ public abstract partial class SharedHandsSystem : EntitySystem
if (!TryComp(session?.AttachedEntity, out SharedHandsComponent? component)) if (!TryComp(session?.AttachedEntity, out SharedHandsComponent? component))
return; return;
if (!_actionBlocker.CanInteract(session.AttachedEntity.Value, null))
return;
if (component.ActiveHand == null || component.Hands.Count < 2) if (component.ActiveHand == null || component.Hands.Count < 2)
return; return;

View File

@@ -32,7 +32,7 @@ namespace Content.Shared.Projectiles
} }
[NetSerializable, Serializable] [NetSerializable, Serializable]
protected sealed class ProjectileComponentState : ComponentState public sealed class ProjectileComponentState : ComponentState
{ {
public ProjectileComponentState(EntityUid shooter, bool ignoreShooter) public ProjectileComponentState(EntityUid shooter, bool ignoreShooter)
{ {
@@ -45,7 +45,7 @@ namespace Content.Shared.Projectiles
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]
protected sealed class ImpactEffectEvent : EntityEventArgs public sealed class ImpactEffectEvent : EntityEventArgs
{ {
public string Prototype; public string Prototype;
public EntityCoordinates Coordinates; public EntityCoordinates Coordinates;

View File

@@ -7,6 +7,12 @@ public abstract class SharedTimedDespawnSystem : EntitySystem
{ {
[Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly IGameTiming _timing = default!;
public override void Initialize()
{
base.Initialize();
UpdatesOutsidePrediction = true;
}
public override void Update(float frameTime) public override void Update(float frameTime)
{ {
base.Update(frameTime); base.Update(frameTime);

View File

@@ -404,7 +404,7 @@ public abstract partial class SharedGunSystem : EntitySystem
/// Used for animated effects on the client. /// Used for animated effects on the client.
/// </summary> /// </summary>
[Serializable, NetSerializable] [Serializable, NetSerializable]
protected sealed class HitscanEvent : EntityEventArgs public sealed class HitscanEvent : EntityEventArgs
{ {
public List<(EntityCoordinates coordinates, Angle angle, SpriteSpecifier Sprite, float Distance)> Sprites = new(); public List<(EntityCoordinates coordinates, Angle angle, SpriteSpecifier Sprite, float Distance)> Sprites = new();
} }