diff --git a/Robust.Client/Replays/Loading/IReplayLoadManager.cs b/Robust.Client/Replays/Loading/IReplayLoadManager.cs index b3f97f990..58325285d 100644 --- a/Robust.Client/Replays/Loading/IReplayLoadManager.cs +++ b/Robust.Client/Replays/Loading/IReplayLoadManager.cs @@ -19,7 +19,8 @@ public interface IReplayLoadManager public MappingDataNode? LoadYamlMetadata(IWritableDirProvider dir, ResPath path); /// - /// Async task that loads up a replay for playback. + /// Async task that loads up a replay for playback. Note that this will have some side effects, such as loading + /// networked resources and prototypes. These resources are not tracked or automatically unloaded. /// /// /// This task is intended to be used with a so that the loading can happen over several frame @@ -34,7 +35,9 @@ public interface IReplayLoadManager Task LoadReplayAsync(IWritableDirProvider dir, ResPath path, LoadReplayCallback callback); /// - /// Async task that loads the initial state of a replay, including spawning & initializing all entities. + /// Async task that loads the initial state of a replay, including spawning & initializing all entities. Note that + /// this will have some side effects, such as loading networked resources and prototypes. These resources are not + /// tracked or automatically unloaded. /// /// /// This task is intended to be used with a so that the loading can happen over several frame diff --git a/Robust.Client/Upload/NetworkResourceManager.cs b/Robust.Client/Upload/NetworkResourceManager.cs index 250f0b709..c597d6670 100644 --- a/Robust.Client/Upload/NetworkResourceManager.cs +++ b/Robust.Client/Upload/NetworkResourceManager.cs @@ -1,9 +1,25 @@ +using Robust.Shared.IoC; using Robust.Shared.Upload; namespace Robust.Client.Upload; public sealed class NetworkResourceManager : SharedNetworkResourceManager { + [Dependency] private readonly IBaseClient _client = default!; + + public override void Initialize() + { + base.Initialize(); + _client.RunLevelChanged += OnLevelChanged; + } + + private void OnLevelChanged(object? sender, RunLevelChangedEventArgs e) + { + // Clear networked resources when disconnecting from a multiplayer game. + if (e.OldLevel == ClientRunLevel.InGame) + ClearResources(); + } + /// /// Callback for when the server sends a new resource. /// @@ -12,4 +28,12 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager { ContentRoot.AddOrUpdateFile(msg.RelativePath, msg.Data); } + + /// + /// Clears all the networked resources. If used while connected to a server, this will probably cause issues. + /// + public void ClearResources() + { + ContentRoot.Clear(); + } } diff --git a/Robust.Shared/ContentPack/MemoryContentRoot.cs b/Robust.Shared/ContentPack/MemoryContentRoot.cs index 745fab39a..b4478acb3 100644 --- a/Robust.Shared/ContentPack/MemoryContentRoot.cs +++ b/Robust.Shared/ContentPack/MemoryContentRoot.cs @@ -55,6 +55,22 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable } } + /// + /// Removes ALL files from this content root. + /// + public void Clear() + { + _lock.EnterWriteLock(); + try + { + _files.Clear(); + } + finally + { + _lock.ExitWriteLock(); + } + } + public bool FileExists(ResPath relPath) { _lock.EnterReadLock();