mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Strongly order network prototypes and resources. (#5293)
* Strongly order network prototypes and resources.
When a new client connects, both the uploaded prototypes and resources get sent at once. There was no ordering here, which means that prototypes could easily load before resources. This would then obviously give load errors at runtime. In practice though this seemed fine because the RSI or something would just load fine after when spawned or something.
This was then broken by ae1051e813, which made ResourceCache start caching "that RSI doesn't exist" so it never really tried again.
I originally tried to fix this by adding an API to IResourceManager that allows content to invalidate the aforementioned cache (commit 316a7e4ac10100593202ff7f53dc2992611bbd1e, for however GitHub will track that) but then realized resource uploading isn't part of content like I first thought. Lol whoops. That API might still be useful for other dynamic content use cases, but I'm not committing it for now. That fix still caused errors to be spammed if the prototype was loaded before the resources were ready.
The new fix is to just load resources before prototypes. This is done by making them both ordered relative to each other, and running resources first.
Fixes #5291
* Release notes
This commit is contained in:
committed by
GitHub
parent
c3d8080a8e
commit
3657b0a424
@@ -43,7 +43,7 @@ END TEMPLATE-->
|
||||
|
||||
### Bugfixes
|
||||
|
||||
*None yet*
|
||||
* Clients connecting to a server now always load prototype uploads after resource uploads, fixing ordering bugs that could cause various errors.
|
||||
|
||||
### Other
|
||||
|
||||
|
||||
@@ -93,8 +93,10 @@ namespace Robust.Server
|
||||
deps.Register<IServerNetConfigurationManager, ServerNetConfigurationManager>();
|
||||
deps.Register<INetConfigurationManagerInternal, ServerNetConfigurationManager>();
|
||||
deps.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
|
||||
deps.Register<GamePrototypeLoadManager>();
|
||||
deps.Register<NetworkResourceManager>();
|
||||
deps.Register<IHttpClientHolder, HttpClientHolder>();
|
||||
deps.Register<UploadedContentManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
base.Initialize();
|
||||
|
||||
_sawmill = _logManager.GetSawmill("adminbus");
|
||||
|
||||
_netManager.Connected += NetManagerOnConnected;
|
||||
}
|
||||
|
||||
public override void SendGamePrototype(string prototype)
|
||||
@@ -50,7 +48,7 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
}
|
||||
}
|
||||
|
||||
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
internal void SendToNewUser(INetChannel channel)
|
||||
{
|
||||
// Just dump all the prototypes on connect, before them missing could be an issue.
|
||||
foreach (var prototype in LoadedPrototypes)
|
||||
@@ -59,7 +57,7 @@ public sealed class GamePrototypeLoadManager : SharedPrototypeLoadManager
|
||||
{
|
||||
PrototypeData = prototype
|
||||
};
|
||||
e.Channel.SendMessage(msg);
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_serverNetManager.Connected += ServerNetManagerOnConnected;
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingEnabled, value => Enabled = value, true);
|
||||
_cfgManager.OnValueChanged(CVars.ResourceUploadingLimitMb, value => SizeLimit = value, true);
|
||||
}
|
||||
@@ -65,14 +64,14 @@ public sealed class NetworkResourceManager : SharedNetworkResourceManager
|
||||
OnResourceUploaded?.Invoke(session, msg);
|
||||
}
|
||||
|
||||
private void ServerNetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
internal void SendToNewUser(INetChannel channel)
|
||||
{
|
||||
foreach (var (path, data) in ContentRoot.GetAllFiles())
|
||||
{
|
||||
var msg = new NetworkResourceUploadMessage();
|
||||
msg.RelativePath = path;
|
||||
msg.Data = data;
|
||||
e.Channel.SendMessage(msg);
|
||||
channel.SendMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
Robust.Server/Upload/UploadedContentManager.cs
Normal file
28
Robust.Server/Upload/UploadedContentManager.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Server.Upload;
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for sending uploaded content to clients when they connect.
|
||||
/// </summary>
|
||||
internal sealed class UploadedContentManager
|
||||
{
|
||||
[Dependency] private readonly IServerNetManager _netManager = default!;
|
||||
[Dependency] private readonly GamePrototypeLoadManager _prototypeLoadManager = default!;
|
||||
[Dependency] private readonly NetworkResourceManager _networkResourceManager = default!;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_netManager.Connected += NetManagerOnConnected;
|
||||
}
|
||||
|
||||
private void NetManagerOnConnected(object? sender, NetChannelArgs e)
|
||||
{
|
||||
// This just shells out to the other managers, ensuring they are ordered properly.
|
||||
// Resources must be done before prototypes.
|
||||
// Note: both net messages sent here are on the same group and are therefore ordered.
|
||||
_networkResourceManager.SendToNewUser(e.Channel);
|
||||
_prototypeLoadManager.SendToNewUser(e.Channel);
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,7 @@ namespace Robust.Shared.Upload;
|
||||
|
||||
public sealed class NetworkResourceUploadMessage : NetMessage
|
||||
{
|
||||
public override NetDeliveryMethod DeliveryMethod => NetDeliveryMethod.ReliableUnordered;
|
||||
public override MsgGroups MsgGroup => MsgGroups.Command;
|
||||
public override MsgGroups MsgGroup => MsgGroups.String;
|
||||
|
||||
public byte[] Data { get; set; } = Array.Empty<byte>();
|
||||
public ResPath RelativePath { get; set; } = ResPath.Self;
|
||||
|
||||
Reference in New Issue
Block a user