mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 11:40:52 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec234b620c | ||
|
|
cb12772f28 | ||
|
|
fdd593cdd1 | ||
|
|
133301ea57 | ||
|
|
62b4714f1f | ||
|
|
1d0404953f | ||
|
|
d0da13f895 | ||
|
|
ff23f98b26 | ||
|
|
ccfef2a786 | ||
|
|
62ce9724fc | ||
|
|
3bbe0e7f44 | ||
|
|
addd8b5bdd |
@@ -57,7 +57,7 @@
|
||||
<PackageVersion Include="SharpZstd.Interop" Version="1.5.2-beta2" />
|
||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.7" />
|
||||
<PackageVersion Include="SpaceWizards.HttpListener" Version="0.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.1.1" />
|
||||
<PackageVersion Include="SpaceWizards.NFluidsynth" Version="0.2.2" />
|
||||
<PackageVersion Include="SpaceWizards.SharpFont" Version="1.0.2" />
|
||||
<PackageVersion Include="SpaceWizards.Sodium" Version="0.2.1" />
|
||||
<PackageVersion Include="TerraFX.Interop.Windows" Version="10.0.26100.1" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project>
|
||||
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
<!-- This file automatically reset by Tools/version.py -->
|
||||
|
||||
|
||||
@@ -71,6 +71,6 @@
|
||||
</PropertyGroup>
|
||||
<Exec
|
||||
Condition="'$(_RobustUseExternalMSBuild)' == 'true'"
|
||||
Command=""$(DOTNET_HOST_PATH)" msbuild /nodereuse:false $(MSBuildProjectFile) /t:CompileRobustXaml /p:_RobustForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false"/>
|
||||
Command=""$(DOTNET_HOST_PATH)" msbuild /nodereuse:false $(MSBuildProjectFile) /t:CompileRobustXaml /p:_RobustForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false /p:IntermediateOutputPath="$(IntermediateOutputPath.TrimEnd('\'))/""/>
|
||||
</Target>
|
||||
</Project>
|
||||
|
||||
@@ -54,6 +54,31 @@ END TEMPLATE-->
|
||||
*None yet*
|
||||
|
||||
|
||||
## 255.1.2
|
||||
|
||||
|
||||
## 255.1.1
|
||||
|
||||
|
||||
## 255.1.0
|
||||
|
||||
### New features
|
||||
|
||||
* The client localisation manager now supports hot-reloading ftl files.
|
||||
* TransformSystem can now raise `GridUidChangedEvent` and `MapUidChangedEvent` when a entity's grid or map changes. This event is only raised if the `ExtraTransformEvents` metadata flag is enabled.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed a server crash due to a `NullReferenceException` in PVS system when a player's local entity is also one of their view subscriptions.
|
||||
* Fix CompileRobustXamlTask for benchmarks.
|
||||
* .ftl files will now hot reload.
|
||||
* Fix placementmanager sometimes not clearing.
|
||||
|
||||
### Other
|
||||
|
||||
* Container events are now documented.
|
||||
|
||||
|
||||
## 255.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
@@ -6,7 +6,7 @@ using Xilium.CefGlue;
|
||||
|
||||
namespace Robust.Client.WebView.Cef
|
||||
{
|
||||
public static class Program
|
||||
internal static class Program
|
||||
{
|
||||
// This was supposed to be the main entry for the subprocess program... It doesn't work.
|
||||
public static int Main(string[] args)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Robust.Client.Console;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -24,6 +25,7 @@ namespace Robust.Client.WebView.Cef
|
||||
|
||||
[Dependency] private readonly IDependencyCollection _dependencyCollection = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IGameControllerInternal _gameController = default!;
|
||||
[Dependency] private readonly IResourceManagerInternal _resourceManager = default!;
|
||||
[Dependency] private readonly IClientConsoleHost _consoleHost = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
@@ -61,7 +63,10 @@ namespace Robust.Client.WebView.Cef
|
||||
|
||||
var cachePath = "";
|
||||
if (_resourceManager.UserData is WritableDirProvider userData)
|
||||
cachePath = userData.GetFullPath(new ResPath("/cef_cache"));
|
||||
{
|
||||
var rootDir = UserDataDir.GetRootUserDataDir(_gameController);
|
||||
cachePath = Path.Combine(rootDir, "cef_cache", "0");
|
||||
}
|
||||
|
||||
var settings = new CefSettings()
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics.Clyde;
|
||||
using Robust.Client.HWId;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Localization;
|
||||
using Robust.Client.Map;
|
||||
using Robust.Client.Placement;
|
||||
using Robust.Client.Player;
|
||||
@@ -36,6 +37,7 @@ using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics;
|
||||
@@ -104,6 +106,8 @@ namespace Robust.Client
|
||||
deps.Register<IGamePrototypeLoadManager, GamePrototypeLoadManager>();
|
||||
deps.Register<NetworkResourceManager>();
|
||||
deps.Register<IReloadManager, ReloadManager>();
|
||||
deps.Register<ILocalizationManager, ClientLocalizationManager>();
|
||||
deps.Register<ILocalizationManagerInternal, ClientLocalizationManager>();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@ using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Exceptions;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
@@ -94,6 +95,7 @@ namespace Robust.Client
|
||||
[Dependency] private readonly IReplayRecordingManagerInternal _replayRecording = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly IReloadManager _reload = default!;
|
||||
[Dependency] private readonly ILocalizationManager _loc = default!;
|
||||
|
||||
private IWebViewManagerHook? _webViewHook;
|
||||
|
||||
@@ -180,6 +182,7 @@ namespace Robust.Client
|
||||
_serializer.Initialize();
|
||||
_inputManager.Initialize();
|
||||
_console.Initialize();
|
||||
_loc.Initialize();
|
||||
|
||||
// Make sure this is done before we try to load prototypes,
|
||||
// avoid any possibility of race conditions causing the check to not finish
|
||||
@@ -384,7 +387,7 @@ namespace Robust.Client
|
||||
|
||||
_prof.Initialize();
|
||||
|
||||
_resManager.Initialize(Options.LoadConfigAndUserData ? userDataDir : null);
|
||||
_resManager.Initialize(Options.LoadConfigAndUserData ? userDataDir : null, hideUserDataDir: true);
|
||||
|
||||
var mountOptions = _commandLineArgs != null
|
||||
? MountOptions.Merge(_commandLineArgs.MountOptions, Options.MountOptions)
|
||||
|
||||
33
Robust.Client/Localization/ClientLocalizationManager.cs
Normal file
33
Robust.Client/Localization/ClientLocalizationManager.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.Localization;
|
||||
|
||||
internal sealed class ClientLocalizationManager : LocalizationManager, ILocalizationManagerInternal
|
||||
{
|
||||
[Dependency] private readonly IReloadManager _reload = default!;
|
||||
|
||||
void ILocalizationManager.Initialize() => Initialize();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_reload.Register(LocaleDirPath, "*.ftl");
|
||||
|
||||
_reload.OnChanged += OnReload;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles Fluent hot reloading via LocalizationManager.ReloadLocalizations()
|
||||
/// </summary>
|
||||
private void OnReload(ResPath args)
|
||||
{
|
||||
if (args.Extension != "ftl")
|
||||
return;
|
||||
|
||||
ReloadLocalizations();
|
||||
}
|
||||
}
|
||||
@@ -356,6 +356,12 @@ namespace Robust.Client.Placement
|
||||
public event EventHandler? PlacementChanged;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearWithoutDeactivation();
|
||||
IsActive = false;
|
||||
}
|
||||
|
||||
private void ClearWithoutDeactivation()
|
||||
{
|
||||
PlacementChanged?.Invoke(this, EventArgs.Empty);
|
||||
Hijack = null;
|
||||
@@ -365,7 +371,6 @@ namespace Robust.Client.Placement
|
||||
CurrentMode = null;
|
||||
DeactivateSpecialPlacement();
|
||||
_placenextframe = false;
|
||||
IsActive = false;
|
||||
Eraser = false;
|
||||
EraserRect = null;
|
||||
PlacementOffset = Vector2i.Zero;
|
||||
@@ -480,7 +485,7 @@ namespace Robust.Client.Placement
|
||||
|
||||
public void BeginHijackedPlacing(PlacementInformation info, PlacementHijack? hijack = null)
|
||||
{
|
||||
Clear();
|
||||
ClearWithoutDeactivation();
|
||||
|
||||
CurrentPermission = info;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared;
|
||||
@@ -26,7 +25,6 @@ internal sealed class ReloadManager : IReloadManager
|
||||
private readonly TimeSpan _reloadDelay = TimeSpan.FromMilliseconds(10);
|
||||
private CancellationTokenSource _reloadToken = new();
|
||||
private readonly HashSet<ResPath> _reloadQueue = new();
|
||||
private List<FileSystemWatcher> _watchers = new();
|
||||
|
||||
public event Action<ResPath>? OnChanged;
|
||||
|
||||
@@ -69,6 +67,11 @@ internal sealed class ReloadManager : IReloadManager
|
||||
_reloadQueue.Clear();
|
||||
}
|
||||
|
||||
public void Register(ResPath directory, string filter)
|
||||
{
|
||||
Register(directory.ToString(), filter);
|
||||
}
|
||||
|
||||
public void Register(string directory, string filter)
|
||||
{
|
||||
if (!_cfg.GetCVar(CVars.ResPrototypeReloadWatch))
|
||||
@@ -90,7 +93,6 @@ internal sealed class ReloadManager : IReloadManager
|
||||
NotifyFilter = NotifyFilters.LastWrite
|
||||
};
|
||||
|
||||
_watchers.Add(watcher);
|
||||
|
||||
watcher.Changed += OnWatch;
|
||||
|
||||
@@ -100,7 +102,7 @@ internal sealed class ReloadManager : IReloadManager
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.Error($"Watching resources in path {path} threw an exception:\n{ex}");
|
||||
_sawmill.Error($"Watching resources in path {path} threw an exception:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ namespace Robust.Server
|
||||
: null;
|
||||
|
||||
// Set up the VFS
|
||||
_resources.Initialize(dataDir);
|
||||
_resources.Initialize(dataDir, hideUserDataDir: false);
|
||||
|
||||
var mountOptions = _commandLineArgs != null
|
||||
? MountOptions.Merge(_commandLineArgs.MountOptions, Options.MountOptions) : Options.MountOptions;
|
||||
@@ -331,6 +331,7 @@ namespace Robust.Server
|
||||
// TODO: solve this properly.
|
||||
_serializer.Initialize();
|
||||
|
||||
_loc.Initialize();
|
||||
_loc.AddLoadedToStringSerializer(_stringSerializer);
|
||||
|
||||
//IoCManager.Resolve<IMapLoader>().LoadedMapData +=
|
||||
|
||||
@@ -14,6 +14,19 @@ public sealed class PointLightSystem : SharedPointLightSystem
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PointLightComponent, ComponentGetState>(OnLightGetState);
|
||||
SubscribeLocalEvent<PointLightComponent, ComponentStartup>(OnLightStartup);
|
||||
SubscribeLocalEvent<PointLightComponent, ComponentShutdown>(OnLightShutdown);
|
||||
SubscribeLocalEvent<PointLightComponent, MetaFlagRemoveAttemptEvent>(OnFlagRemoveAttempt);
|
||||
}
|
||||
|
||||
private void OnLightShutdown(Entity<PointLightComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
UpdatePriority(ent.Owner, ent.Comp, MetaData(ent.Owner));
|
||||
}
|
||||
|
||||
private void OnFlagRemoveAttempt(Entity<PointLightComponent> ent, ref MetaFlagRemoveAttemptEvent args)
|
||||
{
|
||||
if (IsHighPriority(ent.Comp))
|
||||
args.ToRemove &= ~MetaDataFlags.PvsPriority;
|
||||
}
|
||||
|
||||
private void OnLightStartup(EntityUid uid, PointLightComponent component, ComponentStartup args)
|
||||
@@ -21,10 +34,14 @@ public sealed class PointLightSystem : SharedPointLightSystem
|
||||
UpdatePriority(uid, component, MetaData(uid));
|
||||
}
|
||||
|
||||
private bool IsHighPriority(SharedPointLightComponent comp)
|
||||
{
|
||||
return comp is {Enabled: true, CastShadows: true, Radius: > 7, LifeStage: <= ComponentLifeStage.Running};
|
||||
}
|
||||
|
||||
protected override void UpdatePriority(EntityUid uid, SharedPointLightComponent comp, MetaDataComponent meta)
|
||||
{
|
||||
var isHighPriority = comp.Enabled && comp.CastShadows && (comp.Radius > 7);
|
||||
_metadata.SetFlag((uid, meta), MetaDataFlags.PvsPriority, isHighPriority);
|
||||
_metadata.SetFlag((uid, meta), MetaDataFlags.PvsPriority, IsHighPriority(comp));
|
||||
}
|
||||
|
||||
private void OnLightGetState(EntityUid uid, PointLightComponent component, ref ComponentGetState args)
|
||||
|
||||
@@ -9,12 +9,30 @@ public sealed class ServerOccluderSystem : OccluderSystem
|
||||
{
|
||||
[Dependency] private readonly MetaDataSystem _metadata = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<OccluderComponent, MetaFlagRemoveAttemptEvent>(OnFlagRemoveAttempt);
|
||||
}
|
||||
|
||||
private void OnFlagRemoveAttempt(Entity<OccluderComponent> ent, ref MetaFlagRemoveAttemptEvent args)
|
||||
{
|
||||
if (ent.Comp is {Enabled: true, LifeStage: <= ComponentLifeStage.Running})
|
||||
args.ToRemove &= ~MetaDataFlags.PvsPriority;
|
||||
}
|
||||
|
||||
protected override void OnCompStartup(EntityUid uid, OccluderComponent component, ComponentStartup args)
|
||||
{
|
||||
base.OnCompStartup(uid, component, args);
|
||||
_metadata.SetFlag(uid, MetaDataFlags.PvsPriority, component.Enabled);
|
||||
}
|
||||
|
||||
protected override void OnCompRemoved(EntityUid uid, OccluderComponent component, ComponentRemove args)
|
||||
{
|
||||
base.OnCompRemoved(uid, component, args);
|
||||
_metadata.SetFlag(uid, MetaDataFlags.PvsPriority, false);
|
||||
}
|
||||
|
||||
public override void SetEnabled(EntityUid uid, bool enabled, OccluderComponent? comp = null, MetaDataComponent? meta = null)
|
||||
{
|
||||
if (!Resolve(uid, ref comp, false))
|
||||
|
||||
@@ -166,11 +166,11 @@ internal sealed partial class PvsSystem
|
||||
var session = pvsSession.Session;
|
||||
if (session.Status != SessionStatus.InGame)
|
||||
{
|
||||
pvsSession.Viewers = Array.Empty<Entity<TransformComponent, EyeComponent?>>();
|
||||
pvsSession.Viewers = Array.Empty<Entity<TransformComponent, EyeComponent?>>();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fast path
|
||||
// The majority of players will have no view subscriptions
|
||||
if (session.ViewSubscriptions.Count == 0)
|
||||
{
|
||||
if (session.AttachedEntity is not {} attached)
|
||||
@@ -184,15 +184,21 @@ internal sealed partial class PvsSystem
|
||||
return;
|
||||
}
|
||||
|
||||
var count = session.ViewSubscriptions.Count;
|
||||
var i = 0;
|
||||
if (session.AttachedEntity is { } local)
|
||||
{
|
||||
Array.Resize(ref pvsSession.Viewers, session.ViewSubscriptions.Count + 1);
|
||||
if (!session.ViewSubscriptions.Contains(local))
|
||||
count += 1;
|
||||
|
||||
Array.Resize(ref pvsSession.Viewers, count);
|
||||
|
||||
// Attached entity is always the first viewer, to prioritize it and help reduce pop-in for the "main" eye.
|
||||
pvsSession.Viewers[i++] = (local, Transform(local), _eyeQuery.CompOrNull(local));
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Resize(ref pvsSession.Viewers, session.ViewSubscriptions.Count);
|
||||
Array.Resize(ref pvsSession.Viewers, count);
|
||||
}
|
||||
|
||||
foreach (var ent in session.ViewSubscriptions)
|
||||
@@ -200,6 +206,8 @@ internal sealed partial class PvsSystem
|
||||
if (ent != session.AttachedEntity)
|
||||
pvsSession.Viewers[i++] = (ent, Transform(ent), _eyeQuery.CompOrNull(ent));
|
||||
}
|
||||
|
||||
DebugTools.AssertEqual(i, pvsSession.Viewers.Length);
|
||||
}
|
||||
|
||||
private void ProcessVisibleChunks()
|
||||
|
||||
8
Robust.Server/Localization/ServerLocalizationManager.cs
Normal file
8
Robust.Server/Localization/ServerLocalizationManager.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Robust.Server.Localization;
|
||||
|
||||
internal sealed class ServerLocalizationManager : LocalizationManager, ILocalizationManager
|
||||
{
|
||||
void ILocalizationManager.Initialize() => Initialize();
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Robust.Server.Console;
|
||||
using Robust.Server.DataMetrics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Localization;
|
||||
using Robust.Server.Placement;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Prototypes;
|
||||
@@ -21,6 +22,7 @@ using Robust.Shared.Console;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
@@ -97,7 +99,9 @@ namespace Robust.Server
|
||||
deps.Register<NetworkResourceManager>();
|
||||
deps.Register<IHttpClientHolder, HttpClientHolder>();
|
||||
deps.Register<UploadedContentManager>();
|
||||
deps.Register<IHWId, DummyHWId>();
|
||||
deps.Register<IHWId, DummyHWId>();
|
||||
deps.Register<ILocalizationManager, ServerLocalizationManager>();
|
||||
deps.Register<ILocalizationManagerInternal, ServerLocalizationManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ public abstract class ContainerAttemptEventBase : CancellableEntityEventArgs
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the container when attempting to insert an entity.
|
||||
/// </summary>
|
||||
public sealed class ContainerIsInsertingAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -23,7 +26,7 @@ public sealed class ContainerIsInsertingAttemptEvent : ContainerAttemptEventBase
|
||||
/// I.e., could the entity be inserted if the container doesn't contain anything else?
|
||||
/// </summary>
|
||||
public bool AssumeEmpty { get; set; }
|
||||
|
||||
|
||||
public ContainerIsInsertingAttemptEvent(BaseContainer container, EntityUid entityUid, bool assumeEmpty)
|
||||
: base(container, entityUid)
|
||||
{
|
||||
@@ -31,6 +34,9 @@ public sealed class ContainerIsInsertingAttemptEvent : ContainerAttemptEventBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the entity being inserted into the container.
|
||||
/// </summary>
|
||||
public sealed class ContainerGettingInsertedAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -46,6 +52,9 @@ public sealed class ContainerGettingInsertedAttemptEvent : ContainerAttemptEvent
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the container when attempting to remove an entity.
|
||||
/// </summary>
|
||||
public sealed class ContainerIsRemovingAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerIsRemovingAttemptEvent(BaseContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
@@ -53,6 +62,9 @@ public sealed class ContainerIsRemovingAttemptEvent : ContainerAttemptEventBase
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on the entity being removed from the container.
|
||||
/// </summary>
|
||||
public sealed class ContainerGettingRemovedAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerGettingRemovedAttemptEvent(BaseContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
|
||||
@@ -60,9 +60,7 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
internal string GetPath(ResPath relPath)
|
||||
{
|
||||
return Path.GetFullPath(Path.Combine(_directory.FullName, relPath.ToRelativeSystemPath()))
|
||||
// Sanitise platform-specific path and standardize it for engine use.
|
||||
.Replace(Path.DirectorySeparatorChar, '/');
|
||||
return PathHelpers.SafeGetResourcePath(_directory.FullName, relPath);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -14,7 +14,11 @@ namespace Robust.Shared.ContentPack
|
||||
/// The directory to use for user data.
|
||||
/// If null, a virtual temporary file system is used instead.
|
||||
/// </param>
|
||||
void Initialize(string? userData);
|
||||
/// <param name="hideUserDataDir">
|
||||
/// If true, <see cref="IWritableDirProvider.RootDir"/> will be hidden on
|
||||
/// <see cref="IResourceManager.UserData"/>.
|
||||
/// </param>
|
||||
void Initialize(string? userData, bool hideUserDataDir);
|
||||
|
||||
/// <summary>
|
||||
/// Mounts a single stream as a content file. Useful for unit testing.
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
/// <summary>
|
||||
/// The root path of this provider.
|
||||
/// Can be null if it's a virtual provider.
|
||||
/// Can be null if it's a virtual provider or the path is protected (e.g. on the client).
|
||||
/// </summary>
|
||||
string? RootDir { get; }
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.ContentPack
|
||||
{
|
||||
@@ -63,5 +64,27 @@ namespace Robust.Shared.ContentPack
|
||||
!OperatingSystem.IsWindows()
|
||||
&& !OperatingSystem.IsMacOS();
|
||||
|
||||
|
||||
internal static string SafeGetResourcePath(string baseDir, ResPath path)
|
||||
{
|
||||
var relSysPath = path.ToRelativeSystemPath();
|
||||
if (relSysPath.Contains("\\..") || relSysPath.Contains("/.."))
|
||||
{
|
||||
// Hard cap on any exploit smuggling a .. in there.
|
||||
// Since that could allow leaving sandbox.
|
||||
throw new InvalidOperationException($"This branch should never be reached. Path: {path}");
|
||||
}
|
||||
|
||||
var retPath = Path.GetFullPath(Path.Join(baseDir, relSysPath));
|
||||
// better safe than sorry check
|
||||
if (!retPath.StartsWith(baseDir))
|
||||
{
|
||||
// Allow path to match if it's just missing the directory separator at the end.
|
||||
if (retPath != baseDir.TrimEnd(Path.DirectorySeparatorChar))
|
||||
throw new InvalidOperationException($"This branch should never be reached. Path: {path}");
|
||||
}
|
||||
|
||||
return retPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ namespace Robust.Shared.ContentPack
|
||||
public IWritableDirProvider UserData { get; private set; } = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Initialize(string? userData)
|
||||
public virtual void Initialize(string? userData, bool hideRootDir)
|
||||
{
|
||||
Sawmill = _logManager.GetSawmill("res");
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
UserData = new WritableDirProvider(Directory.CreateDirectory(userData));
|
||||
UserData = new WritableDirProvider(Directory.CreateDirectory(userData), hideRootDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -379,6 +379,10 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
var rootDir = loader.GetPath(new ResPath(@"/"));
|
||||
|
||||
// TODO: GET RID OF THIS.
|
||||
// This code shouldn't be passing OS disk paths through ResPath.
|
||||
rootDir = rootDir.Replace(Path.DirectorySeparatorChar, '/');
|
||||
|
||||
yield return new ResPath(rootDir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,22 @@ namespace Robust.Shared.ContentPack
|
||||
/// <inheritdoc />
|
||||
internal sealed class WritableDirProvider : IWritableDirProvider
|
||||
{
|
||||
/// <inheritdoc />
|
||||
private readonly bool _hideRootDir;
|
||||
|
||||
public string RootDir { get; }
|
||||
|
||||
string? IWritableDirProvider.RootDir => _hideRootDir ? null : RootDir;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance of <see cref="WritableDirProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="rootDir">Root file system directory to allow writing.</param>
|
||||
public WritableDirProvider(DirectoryInfo rootDir)
|
||||
/// <param name="hideRootDir">If true, <see cref="IWritableDirProvider.RootDir"/> is reported as null.</param>
|
||||
public WritableDirProvider(DirectoryInfo rootDir, bool hideRootDir)
|
||||
{
|
||||
// FullName does not have a trailing separator, and we MUST have a separator.
|
||||
RootDir = rootDir.FullName + Path.DirectorySeparatorChar.ToString();
|
||||
_hideRootDir = hideRootDir;
|
||||
}
|
||||
|
||||
#region File Access
|
||||
@@ -119,7 +124,7 @@ namespace Robust.Shared.ContentPack
|
||||
throw new FileNotFoundException();
|
||||
|
||||
var dirInfo = new DirectoryInfo(GetFullPath(path));
|
||||
return new WritableDirProvider(dirInfo);
|
||||
return new WritableDirProvider(dirInfo, _hideRootDir);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -180,20 +185,7 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
path = path.Clean();
|
||||
|
||||
return GetFullPath(RootDir, path);
|
||||
}
|
||||
|
||||
private static string GetFullPath(string root, ResPath path)
|
||||
{
|
||||
var relPath = path.ToRelativeSystemPath();
|
||||
if (relPath.Contains("\\..") || relPath.Contains("/.."))
|
||||
{
|
||||
// Hard cap on any exploit smuggling a .. in there.
|
||||
// Since that could allow leaving sandbox.
|
||||
throw new InvalidOperationException($"This branch should never be reached. Path: {path}");
|
||||
}
|
||||
|
||||
return Path.GetFullPath(Path.Combine(root, relPath));
|
||||
return PathHelpers.SafeGetResourcePath(RootDir, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +238,11 @@ namespace Robust.Shared.GameObjects
|
||||
/// a grid or map.
|
||||
/// </summary>
|
||||
PvsPriority = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// If set, transform system will raise events directed at this entity whenever the GridUid or MapUid are modified.
|
||||
/// </summary>
|
||||
ExtraTransformEvents = 1 << 5,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -402,32 +402,6 @@ namespace Robust.Shared.GameObjects
|
||||
_entMan.EntitySysManager.GetEntitySystem<SharedTransformSystem>().AttachToGridOrMap(Owner, this);
|
||||
}
|
||||
|
||||
internal void UpdateChildMapIdsRecursive(
|
||||
MapId newMapId,
|
||||
EntityUid? newUid,
|
||||
bool mapPaused,
|
||||
EntityQuery<TransformComponent> xformQuery,
|
||||
EntityQuery<MetaDataComponent> metaQuery,
|
||||
MetaDataSystem system)
|
||||
{
|
||||
foreach (var child in _children)
|
||||
{
|
||||
//Set Paused state
|
||||
var metaData = metaQuery.GetComponent(child);
|
||||
system.SetEntityPaused(child, mapPaused, metaData);
|
||||
|
||||
var concrete = xformQuery.GetComponent(child);
|
||||
|
||||
concrete.MapUid = newUid;
|
||||
concrete.MapID = newMapId;
|
||||
|
||||
if (concrete.ChildCount != 0)
|
||||
{
|
||||
concrete.UpdateChildMapIdsRecursive(newMapId, newUid, mapPaused, xformQuery, metaQuery, system);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use TransformSystem.SetParent() instead")]
|
||||
public void AttachParent(EntityUid parent)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Robust.Shared.GameObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed at an entity when <see cref="TransformComponent.GridUid"/> is modified.
|
||||
/// This event is only raised if the entity has the <see cref="MetaDataFlags.ExtraTransformEvents"/> flag set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Event handlers should not modify positions or delete the entity, because the move event that triggered this event
|
||||
/// is still being processed. This may also mean that the entity's current position/parent has not yet been updated,
|
||||
/// and that positional entity queries are not reliable.
|
||||
/// </remarks>
|
||||
[ByRefEvent]
|
||||
public readonly record struct GridUidChangedEvent(
|
||||
Entity<TransformComponent, MetaDataComponent> Entity,
|
||||
EntityUid? OldGrid)
|
||||
{
|
||||
public EntityUid? NewGrid => Entity.Comp1.GridUid;
|
||||
public EntityUid Uid => Entity.Owner;
|
||||
public TransformComponent Transform => Entity.Comp1;
|
||||
public MetaDataComponent Meta => Entity.Comp2;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Robust.Shared.GameObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed at an entity when <see cref="TransformComponent.MapUid"/> is modified.
|
||||
/// This event is only raised if the entity has the <see cref="MetaDataFlags.ExtraTransformEvents"/> flag set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Event handlers should not modify positions or delete the entity, because the move event that triggered this event
|
||||
/// is still being processed. This may also mean that the entity's current position/parent has not yet been updated,
|
||||
/// and that positional entity queries are not reliable.
|
||||
/// </remarks>
|
||||
[ByRefEvent]
|
||||
public readonly record struct MapUidChangedEvent(
|
||||
Entity<TransformComponent, MetaDataComponent> Entity,
|
||||
EntityUid? OldMap,
|
||||
MapId OldMapId)
|
||||
{
|
||||
public EntityUid? NewMap => Entity.Comp1.MapUid;
|
||||
public MapId? NewMapId => Entity.Comp1.MapID;
|
||||
public EntityUid Uid => Entity.Owner;
|
||||
public TransformComponent Transform => Entity.Comp1;
|
||||
public MetaDataComponent Meta => Entity.Comp2;
|
||||
}
|
||||
@@ -159,6 +159,8 @@ public abstract class MetaDataSystem : EntitySystem
|
||||
if (toRemove == 0x0)
|
||||
return;
|
||||
|
||||
// TODO PERF
|
||||
// does this need to be a broadcast event?
|
||||
var ev = new MetaFlagRemoveAttemptEvent(toRemove);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ public abstract partial class SharedTransformSystem
|
||||
xform._localPosition = tilePos + newGrid.TileSizeHalfVector;
|
||||
xform._localRotation += rotation;
|
||||
|
||||
SetGridId(uid, xform, newGridUid, XformQuery);
|
||||
var meta = MetaData(uid);
|
||||
SetGridId((uid, xform, meta), newGridUid);
|
||||
RaiseMoveEvent((uid, xform, meta), oldGridUid, oldPos, oldRot, oldMap);
|
||||
|
||||
DebugTools.Assert(XformQuery.GetComponent(oldGridUid).MapID == XformQuery.GetComponent(newGridUid).MapID);
|
||||
@@ -354,32 +354,49 @@ public abstract partial class SharedTransformSystem
|
||||
|
||||
#region GridId
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="GridId"/> for the transformcomponent without updating its children. Does not Dirty it.
|
||||
/// </summary>
|
||||
internal void SetGridIdNoRecursive(EntityUid uid, TransformComponent xform, EntityUid? gridUid)
|
||||
/// <inheritdoc cref="SetGridId(Entity{TransformComponent,MetaDataComponent},EntityUid?)"/>
|
||||
public void SetGridId(EntityUid uid, TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent>? xformQuery = null)
|
||||
{
|
||||
DebugTools.Assert(gridUid == uid || !HasComp<MapGridComponent>(uid));
|
||||
if (xform._gridUid == gridUid)
|
||||
return;
|
||||
|
||||
DebugTools.Assert(gridUid == null || HasComp<MapGridComponent>(gridUid));
|
||||
xform._gridUid = gridUid;
|
||||
SetGridId((uid, xform, MetaData(uid)), gridId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="GridId"/> for the transformcomponent. Does not Dirty it.
|
||||
/// Sets <see cref="TransformComponent.GridUid"/> for the entity and any children. Note that this does not dirty
|
||||
/// the component, as this is implicitly networked via the transform hierarchy.
|
||||
/// </summary>
|
||||
public void SetGridId(EntityUid uid, TransformComponent xform, EntityUid? gridId, EntityQuery<TransformComponent>? xformQuery = null)
|
||||
public void SetGridId(Entity<TransformComponent, MetaDataComponent?> ent, EntityUid? gridId)
|
||||
{
|
||||
if (!xform._gridInitialized || xform._gridUid == gridId || xform.GridUid == uid)
|
||||
if (!ent.Comp1._gridInitialized || ent.Comp1._gridUid == gridId || ent.Comp1.GridUid == ent.Owner)
|
||||
return;
|
||||
|
||||
DebugTools.Assert(!HasComp<MapGridComponent>(uid) || gridId == uid);
|
||||
xform._gridUid = gridId;
|
||||
foreach (var child in xform._children)
|
||||
DebugTools.Assert(!HasComp<MapGridComponent>(ent.Owner) || gridId == ent.Owner);
|
||||
|
||||
// ReSharper disable once ReturnValueOfPureMethodIsNotUsed
|
||||
_metaQuery.ResolveInternal(ent.Owner, ref ent.Comp2);
|
||||
if ((ent.Comp2!.Flags & MetaDataFlags.ExtraTransformEvents) != 0)
|
||||
{
|
||||
SetGridId(child, XformQuery.GetComponent(child), gridId);
|
||||
#if DEBUG
|
||||
var childCount = ent.Comp1.ChildCount;
|
||||
var oldParent = ent.Comp1.ParentUid;
|
||||
#endif
|
||||
|
||||
var ev = new GridUidChangedEvent((ent.Owner, ent.Comp1, ent.Comp2), ent.Comp1._gridUid);
|
||||
ent.Comp1._gridUid = gridId;
|
||||
RaiseLocalEvent(ent, ref ev);
|
||||
|
||||
#if DEBUG
|
||||
// Lets check content didn't do anything silly with the event.
|
||||
DebugTools.AssertEqual(ent.Comp1._gridUid, gridId);
|
||||
DebugTools.AssertEqual(ent.Comp1.ChildCount, childCount);
|
||||
DebugTools.AssertEqual(ent.Comp1.ParentUid, oldParent);
|
||||
#endif
|
||||
}
|
||||
|
||||
ent.Comp1._gridUid = gridId;
|
||||
|
||||
foreach (var child in ent.Comp1._children)
|
||||
{
|
||||
SetGridId((child, XformQuery.GetComponent(child), null), gridId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,7 +587,10 @@ public abstract partial class SharedTransformSystem
|
||||
|
||||
if (newParent != null)
|
||||
{
|
||||
ChangeMapId(uid, xform, meta, newParent.MapID);
|
||||
// TODO PERF
|
||||
// if both map & grid id change, we should simultaneously update both.
|
||||
|
||||
ChangeMapId(entity, newParent.MapID);
|
||||
|
||||
if (!xform._gridInitialized)
|
||||
InitializeGridUid(uid, xform);
|
||||
@@ -578,16 +598,19 @@ public abstract partial class SharedTransformSystem
|
||||
{
|
||||
if (!newParent._gridInitialized)
|
||||
InitializeGridUid(value.EntityId, newParent);
|
||||
SetGridId(uid, xform, newParent.GridUid);
|
||||
SetGridId(entity!, newParent.GridUid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeMapId(uid, xform, meta, MapId.Nullspace);
|
||||
// TODO PERF
|
||||
// if both map & grid id change, we should simultaneously update both.
|
||||
|
||||
ChangeMapId(entity, MapId.Nullspace);
|
||||
if (!xform._gridInitialized)
|
||||
InitializeGridUid(uid, xform);
|
||||
else
|
||||
SetGridId(uid, xform, null, XformQuery);
|
||||
SetGridId(entity!, null);
|
||||
}
|
||||
|
||||
if (xform.Initialized)
|
||||
@@ -623,20 +646,54 @@ public abstract partial class SharedTransformSystem
|
||||
SetCoordinates((uid, xform, _metaQuery.GetComponent(uid)), value, rotation, unanchor, newParent, oldParent);
|
||||
}
|
||||
|
||||
private void ChangeMapId(EntityUid uid, TransformComponent xform, MetaDataComponent meta, MapId newMapId)
|
||||
private void ChangeMapId(Entity<TransformComponent, MetaDataComponent> ent, MapId newMapId)
|
||||
{
|
||||
if (newMapId == xform.MapID)
|
||||
if (newMapId == ent.Comp1.MapID)
|
||||
return;
|
||||
|
||||
EntityUid? newUid = newMapId == MapId.Nullspace ? null : _map.GetMap(newMapId);
|
||||
|
||||
//Set Paused state
|
||||
EntityUid? newMap = newMapId == MapId.Nullspace ? null : _map.GetMap(newMapId);
|
||||
var mapPaused = _map.IsPaused(newMapId);
|
||||
_metaData.SetEntityPaused(uid, mapPaused, meta);
|
||||
|
||||
xform.MapUid = newUid;
|
||||
xform.MapID = newMapId;
|
||||
xform.UpdateChildMapIdsRecursive(newMapId, newUid, mapPaused, XformQuery, _metaQuery, _metaData);
|
||||
ChangeMapIdRecursive(ent, newMap, newMapId, mapPaused);
|
||||
}
|
||||
|
||||
private void ChangeMapIdRecursive(
|
||||
Entity<TransformComponent, MetaDataComponent> ent,
|
||||
EntityUid? newMap,
|
||||
MapId newMapId,
|
||||
bool paused)
|
||||
{
|
||||
_metaData.SetEntityPaused(ent.Owner, paused, ent.Comp2);
|
||||
|
||||
if ((ent.Comp2.Flags & MetaDataFlags.ExtraTransformEvents) != 0)
|
||||
{
|
||||
#if DEBUG
|
||||
var childCount = ent.Comp1.ChildCount;
|
||||
var oldParent = ent.Comp1.ParentUid;
|
||||
#endif
|
||||
|
||||
var ev = new MapUidChangedEvent(ent, ent.Comp1.MapUid, ent.Comp1.MapID);
|
||||
ent.Comp1.MapUid = newMap;
|
||||
ent.Comp1.MapID = newMapId;
|
||||
RaiseLocalEvent(ent.Owner, ref ev);
|
||||
|
||||
#if DEBUG
|
||||
// Lets check content didn't do anything silly with the event.
|
||||
DebugTools.AssertEqual(ent.Comp1.MapUid, newMap);
|
||||
DebugTools.AssertEqual(ent.Comp1.MapID, newMapId);
|
||||
DebugTools.AssertEqual(ent.Comp1.ChildCount, childCount);
|
||||
DebugTools.AssertEqual(ent.Comp1.ParentUid, oldParent);
|
||||
#endif
|
||||
}
|
||||
|
||||
ent.Comp1.MapUid = newMap;
|
||||
ent.Comp1.MapID = newMapId;
|
||||
|
||||
foreach (var uid in ent.Comp1._children)
|
||||
{
|
||||
var child = new Entity<TransformComponent, MetaDataComponent>(uid, Transform(uid), MetaData(uid));
|
||||
ChangeMapIdRecursive(child, newMap, newMapId, paused);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -1501,9 +1558,10 @@ public abstract partial class SharedTransformSystem
|
||||
private void OnGridAdd(EntityUid uid, TransformComponent component, GridAddEvent args)
|
||||
{
|
||||
// Added to existing map so need to update all children too.
|
||||
if (LifeStage(uid) > EntityLifeStage.Initialized)
|
||||
var meta = MetaData(uid);
|
||||
if (meta.EntityLifeStage > EntityLifeStage.Initialized)
|
||||
{
|
||||
SetGridId(uid, component, uid, XformQuery);
|
||||
SetGridId((uid, component, meta), uid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,13 @@ namespace Robust.Shared.Localization
|
||||
/// Gets localization data for an entity prototype.
|
||||
/// </summary>
|
||||
EntityLocData GetEntityData(string prototypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="LocalizationManager"/>.
|
||||
/// </summary>
|
||||
void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal interface ILocalizationManagerInternal : ILocalizationManager
|
||||
|
||||
@@ -12,7 +12,7 @@ using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Robust.Shared.Localization
|
||||
{
|
||||
internal sealed partial class LocalizationManager
|
||||
internal abstract partial class LocalizationManager
|
||||
{
|
||||
// Concurrent dict so that multiple threads "reading" .Name won't cause a concurrent write issue
|
||||
// when the cache gets populated.
|
||||
@@ -134,7 +134,7 @@ namespace Robust.Shared.Localization
|
||||
.Select(x => GetString(x.Suffix!));
|
||||
suffix = string.Join(", ", suffixes);
|
||||
}
|
||||
|
||||
|
||||
return new EntityLocData(
|
||||
name ?? "",
|
||||
desc ?? "",
|
||||
|
||||
@@ -12,7 +12,7 @@ using Robust.Shared.Maths;
|
||||
|
||||
namespace Robust.Shared.Localization
|
||||
{
|
||||
internal sealed partial class LocalizationManager
|
||||
internal abstract partial class LocalizationManager
|
||||
{
|
||||
private static readonly Regex RegexWordMatch = new Regex(@"\w+");
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Localization
|
||||
{
|
||||
internal sealed partial class LocalizationManager : ILocalizationManagerInternal, IPostInjectInit
|
||||
internal abstract partial class LocalizationManager : ILocalizationManagerInternal
|
||||
{
|
||||
private static readonly ResPath LocaleDirPath = new("/Locale");
|
||||
protected static readonly ResPath LocaleDirPath = new("/Locale");
|
||||
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly IResourceManager _res = default!;
|
||||
@@ -40,7 +40,9 @@ namespace Robust.Shared.Localization
|
||||
private (CultureInfo, FluentBundle)? _defaultCulture;
|
||||
private (CultureInfo, FluentBundle)[] _fallbackCultures = Array.Empty<(CultureInfo, FluentBundle)>();
|
||||
|
||||
void IPostInjectInit.PostInject()
|
||||
void ILocalizationManager.Initialize() => Initialize();
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
_logSawmill = _log.GetSawmill("loc");
|
||||
_prototype.PrototypesReloaded += OnPrototypesReloaded;
|
||||
|
||||
@@ -9,15 +9,13 @@ namespace Robust.Shared
|
||||
public static void Setup(IConfigurationManager cfg)
|
||||
{
|
||||
// Disabled on non-release since I don't want this to start creating files in Steam's bin directory.
|
||||
#if RELEASE
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if !RELEASE
|
||||
if (!cfg.GetCVar(CVars.SysProfileOpt))
|
||||
return;
|
||||
|
||||
ProfileOptimization.SetProfileRoot(PathHelpers.GetExecutableDirectory());
|
||||
ProfileOptimization.StartProfile("profile_opt");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ namespace Robust.Shared
|
||||
deps.Register<IDynamicTypeFactory, DynamicTypeFactory>();
|
||||
deps.Register<IDynamicTypeFactoryInternal, DynamicTypeFactory>();
|
||||
deps.Register<IEntitySystemManager, EntitySystemManager>();
|
||||
deps.Register<ILocalizationManager, LocalizationManager>();
|
||||
deps.Register<ILocalizationManagerInternal, LocalizationManager>();
|
||||
deps.Register<ILogManager, LogManager>();
|
||||
deps.Register<IModLoader, ModLoader>();
|
||||
deps.Register<IModLoaderInternal, ModLoader>();
|
||||
|
||||
@@ -17,6 +17,11 @@ internal interface IReloadManager
|
||||
/// </summary>
|
||||
internal void Register(string directory, string filter);
|
||||
|
||||
/// <summary>
|
||||
/// Registers the specified directory as a <see cref="ResPath"/> and specified file extension to subscribe to.
|
||||
/// </summary>
|
||||
internal void Register(ResPath directory, string filter);
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using Robust.Server.Containers;
|
||||
using Robust.Server.Debugging;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Localization;
|
||||
using Robust.Server.Physics;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.Prototypes;
|
||||
@@ -192,7 +193,7 @@ namespace Robust.UnitTesting.Server
|
||||
container.Register<INetConfigurationManagerInternal, ServerNetConfigurationManager>();
|
||||
container.Register<IDynamicTypeFactory, DynamicTypeFactory>();
|
||||
container.Register<IDynamicTypeFactoryInternal, DynamicTypeFactory>();
|
||||
container.Register<ILocalizationManager, LocalizationManager>();
|
||||
container.Register<ILocalizationManager, ServerLocalizationManager>();
|
||||
container.Register<IModLoader, TestingModLoader>();
|
||||
container.Register<IModLoaderInternal, TestingModLoader>();
|
||||
container.Register<ProfManager, ProfManager>();
|
||||
|
||||
@@ -31,6 +31,7 @@ term1 = 2
|
||||
res.MountString("/Locale/en-US/a.ftl", DuplicateTerm);
|
||||
|
||||
var loc = IoCManager.Resolve<ILocalizationManager>();
|
||||
loc.Initialize();
|
||||
|
||||
var spyLog = (SpyLogManager) IoCManager.Resolve<ILogManager>();
|
||||
var culture = new CultureInfo("en-US", false);
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace Robust.UnitTesting.Shared.Localization
|
||||
|
||||
var loc = IoCManager.Resolve<ILocalizationManager>();
|
||||
var culture = new CultureInfo("en-US", false);
|
||||
loc.Initialize();
|
||||
loc.LoadCulture(culture);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Robust.UnitTesting.Shared.Resources
|
||||
_testDir = Directory.CreateDirectory(_testDirPath);
|
||||
var subDir = Path.Combine(_testDirPath, "writable");
|
||||
|
||||
_dirProvider = new WritableDirProvider(Directory.CreateDirectory(subDir));
|
||||
_dirProvider = new WritableDirProvider(Directory.CreateDirectory(subDir), hideRootDir: false);
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
|
||||
Reference in New Issue
Block a user