Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Robust.Shared;
using Robust.Shared.Animations;
using Robust.Shared.ComponentTrees;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.IoC;
Expand Down Expand Up @@ -251,7 +252,7 @@ void ISerializationHooks.AfterDeserialization()
IoCManager.InjectDependencies(this);
if (!string.IsNullOrWhiteSpace(rsi))
{
var rsiPath = TextureRoot / rsi;
var rsiPath = PathHelpers.ApparentPath(rsi, TextureRoot.ToString());
if (resourceCache.TryGetResource(rsiPath, out RSIResource? resource))
_baseRsi = resource.RSI;
else
Expand Down Expand Up @@ -508,8 +509,7 @@ internal void LayerSetData(Layer layer, PrototypeLayerData layerDatum)

if (!string.IsNullOrWhiteSpace(layerDatum.RsiPath))
{
var path = TextureRoot / layerDatum.RsiPath;

var path = PathHelpers.ApparentPath(layerDatum.RsiPath, TextureRoot.ToString());
if (resourceCache.TryGetResource(path, out RSIResource? resource))
{
layer.RSI = resource.RSI;
Expand Down Expand Up @@ -559,8 +559,8 @@ internal void LayerSetData(Layer layer, PrototypeLayerData layerDatum)
}
else
{
layer.Texture =
resourceCache.GetResource<TextureResource>(TextureRoot / layerDatum.TexturePath);
var texPath = PathHelpers.ApparentPath(layerDatum.TexturePath, TextureRoot.ToString());
layer.Texture = resourceCache.GetResource<TextureResource>(texPath);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using JetBrains.Annotations;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Prototypes;
Expand Down Expand Up @@ -171,9 +172,8 @@ public Texture GetFallbackTexture()
[Pure]
public RSI.State GetState(SpriteSpecifier.Rsi rsiSpecifier)
{
if (_resourceCache.TryGetResource<RSIResource>(
TextureRoot / rsiSpecifier.RsiPath,
out var theRsi) &&
var path = PathHelpers.ApparentPath(rsiSpecifier.RsiPath, TextureRoot);
if (_resourceCache.TryGetResource<RSIResource>(path, out var theRsi) &&
theRsi.RSI.TryGetState(rsiSpecifier.RsiState, out var state))
{
return state;
Expand All @@ -185,11 +185,13 @@ public RSI.State GetState(SpriteSpecifier.Rsi rsiSpecifier)

public Texture GetTexture(SpriteSpecifier.Texture texSpecifier)
{
var path = PathHelpers.ApparentPath(texSpecifier.TexturePath, TextureRoot);
return _resourceCache
.GetResource<TextureResource>(TextureRoot / texSpecifier.TexturePath)
.GetResource<TextureResource>(path)
.Texture;
}


private void OnPrototypesReloaded(PrototypesReloadedEventArgs args)
{
if (!args.TryGetModified<EntityPrototype>(out var modified))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics.CodeAnalysis;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Utility;
using static Robust.Client.GameObjects.SpriteComponent;
Expand Down Expand Up @@ -190,7 +191,8 @@ public int AddRsiLayer(Entity<SpriteComponent?> sprite, RSI.StateId state, ResPa
if (!_query.Resolve(sprite.Owner, ref sprite.Comp))
return -1;

if (!_resourceCache.TryGetResource<RSIResource>(TextureRoot / path, out var res))
var rsiPath = PathHelpers.ApparentPath(path, TextureRoot);
if (!_resourceCache.TryGetResource<RSIResource>(rsiPath, out var res))
Log.Error($"Unable to load RSI '{path}'. Trace:\n{Environment.StackTrace}");

if (path.Extension != "rsi")
Expand All @@ -201,7 +203,8 @@ public int AddRsiLayer(Entity<SpriteComponent?> sprite, RSI.StateId state, ResPa

public int AddTextureLayer(Entity<SpriteComponent?> sprite, ResPath path, int? index = null)
{
if (_resourceCache.TryGetResource<TextureResource>(TextureRoot / path, out var texture))
var texPath = PathHelpers.ApparentPath(path, TextureRoot);
if (_resourceCache.TryGetResource<TextureResource>(texPath, out var texture))
return AddTextureLayer(sprite, texture?.Texture, index);

if (path.Extension == "rsi")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Numerics;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
Expand Down Expand Up @@ -131,7 +132,8 @@ public void LayerSetTexture(Entity<SpriteComponent?> sprite, Enum key, ResPath p

private void LayerSetTexture(Layer layer, ResPath path)
{
if (!_resourceCache.TryGetResource<TextureResource>(TextureRoot / path, out var texture))
var actualPath = PathHelpers.ApparentPath(path, TextureRoot);
if (!_resourceCache.TryGetResource<TextureResource>(actualPath, out var texture))
{
if (path.Extension == "rsi")
Log.Error($"Expected texture but got rsi '{path}', did you mean 'sprite:' instead of 'texture:'?");
Expand Down Expand Up @@ -228,7 +230,8 @@ public void LayerSetRsi(Entity<SpriteComponent?> sprite, Enum key, ResPath rsi,

public void LayerSetRsi(Layer layer, ResPath rsi, StateId? state = null)
{
if (!_resourceCache.TryGetResource<RSIResource>(TextureRoot / rsi, out var res))
var rsiPath = PathHelpers.ApparentPath(rsi, TextureRoot);
if (!_resourceCache.TryGetResource<RSIResource>(rsiPath, out var res))
Log.Error($"Unable to load RSI '{rsi}' for entity {ToPrettyString(layer.Owner)}. Trace:\n{Environment.StackTrace}");

LayerSetRsi(layer, res?.RSI, state);
Expand Down
4 changes: 3 additions & 1 deletion Robust.Client/GameObjects/EntitySystems/SpriteSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Robust.Client.Utility;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Graphics.RSI;
using Robust.Shared.IoC;
Expand Down Expand Up @@ -187,7 +188,8 @@ public Texture GetFrame(SpriteSpecifier spriteSpec, TimeSpan curTime, bool loop
switch (spriteSpec)
{
case SpriteSpecifier.Rsi rsi:
var rsiActual = _resourceCache.GetResource<RSIResource>(rsi.RsiPath).RSI;
var path = PathHelpers.ApparentPath(rsi.RsiPath, TextureRoot);
var rsiActual = _resourceCache.GetResource<RSIResource>(path).RSI;
rsiActual.TryGetState(rsi.RsiState, out var state);
var frames = state!.GetFrames(RsiDirection.South);
var delays = state.GetDelays();
Expand Down
4 changes: 2 additions & 2 deletions Robust.Client/Graphics/Texture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Texture IRsiStateLike.GetFrame(RsiDirection dir, int frame)
/// <param name="name">The "name" of this texture. This can be referred to later to aid debugging.</param>
/// <param name="loadParameters">
/// Parameters that influence the loading of textures.
/// Defaults to <see cref="Robust.Client.Graphics.TextureLoadParameters.Default"/> if <c>null</c>.
/// Defaults to <see cref="TextureLoadParameters.Default"/> if <c>null</c>.
/// </param>
/// <typeparam name="T">The type of pixels of the image. At the moment, images must be <see cref="Rgba32"/>.</typeparam>
public static Texture LoadFromImage<T>(Image<T> image, string? name = null,
Expand All @@ -101,7 +101,7 @@ public static Texture LoadFromImage<T>(Image<T> image, string? name = null,
/// <param name="name">The "name" of this texture. This can be referred to later to aid debugging.</param>
/// <param name="loadParameters">
/// Parameters that influence the loading of textures.
/// Defaults to <see cref="Robust.Client.Graphics.TextureLoadParameters.Default"/> if <c>null</c>.
/// Defaults to <see cref="TextureLoadParameters.Default"/> if <c>null</c>.
/// </param>
public static Texture LoadFromPNGStream(Stream stream, string? name = null,
TextureLoadParameters? loadParameters = null)
Expand Down
3 changes: 3 additions & 0 deletions Robust.Client/Prototypes/ClientPrototypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
using System.Collections.Generic;
using System.Diagnostics;
using Robust.Client.Timing;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Network;
using Robust.Shared.Network.Messages;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
using TerraFX.Interop.Windows;

namespace Robust.Client.Prototypes
{
Expand All @@ -33,6 +35,7 @@ public override void LoadDefaultPrototypes(Dictionary<Type, HashSet<string>>? ch
{
LoadDirectory(new("/EnginePrototypes/"), changed: changed);
LoadDirectory(_controller.Options.PrototypeDirectory, changed: changed);
LoadModularPrototypes(_controller.Options.PrototypeDirectory, changed);
ResolveResults();
}

Expand Down
24 changes: 21 additions & 3 deletions Robust.Client/ResourceManagement/ResourceCache.Preload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ private void PreloadTextures(ISawmill sawmill)
var sw = Stopwatch.StartNew();
var resList = GetTypeData<TextureResource>().Resources;

var texList = _manager.ContentFindFiles("/Textures/")
var texList = GetTextureSearchPaths()
.SelectMany(path => _manager.ContentFindFiles(path))
// Skip PNG files inside RSIs.
.Where(p => p.Extension == "png" && !p.ToString().Contains(".rsi/") && !resList.ContainsKey(p))
.Select(p => new TextureResource.LoadStepData {Path = p})
Expand Down Expand Up @@ -138,11 +139,15 @@ private void PreloadRsis(ISawmill sawmill)
var sw = Stopwatch.StartNew();
var resList = GetTypeData<RSIResource>().Resources;

var foundRsiList = _manager.ContentFindFiles("/Textures/")
var searchPaths = GetTextureSearchPaths().ToArray();

var foundRsiList = searchPaths
.SelectMany(path => _manager.ContentFindFiles(path))
.Where(p => p.ToString().EndsWith(".rsi/meta.json"))
.Select(c => c.Directory);

var foundRsicList = _manager.ContentFindFiles("/Textures/")
var foundRsicList = searchPaths
.SelectMany(path => _manager.ContentFindFiles(path))
.Where(p => p.Extension == "rsic")
.Select(c => c.WithExtension("rsi"));

Expand Down Expand Up @@ -391,6 +396,19 @@ private static bool ShouldMetaAtlas(RSIResource.LoadStepData rsi)
{
return rsi.MetaAtlas && rsi.LoadParameters == TextureLoadParameters.Default;
}

private IEnumerable<ResPath> GetTextureSearchPaths()
{
yield return new ResPath("/Textures/");

var manifest = ResourceManifestData.LoadResourceManifest(_manager);
if (manifest.ModularResources == null) yield break;
foreach (var path in manifest.ModularResources.Keys)
{

yield return new ResPath(path).ToRootedPath() / "Textures";
}
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.Markdown.Mapping;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.Markdown.Value;
using Robust.Shared.Serialization.TypeSerializers.Implementations;
using Robust.Shared.Utility;

namespace Robust.Client.Serialization;

Expand All @@ -28,7 +30,7 @@ public override ValidationNode ValidateRsi(ISerializationManager serializationMa
}

var res = dependencies.Resolve<IResourceCache>();
var rsiPath = TextureRoot / valuePathNode.Value;
var rsiPath = PathHelpers.ApparentPath(new ResPath(valuePathNode.Value), TextureRoot);
if (!res.TryGetResource(rsiPath, out RSIResource? resource))
{
return new ErrorNode(node, "Failed to load RSI");
Expand Down
28 changes: 26 additions & 2 deletions Robust.Client/Utility/ReloadManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Threading;
using Robust.Client.Graphics;
using Robust.Shared;
Expand All @@ -10,6 +12,7 @@
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Utility;
using TerraFX.Interop.Windows;
using Timer = Robust.Shared.Timing.Timer;

namespace Robust.Client.Utility;
Expand All @@ -28,6 +31,7 @@ internal sealed class ReloadManager : IReloadManager
private CancellationTokenSource _reloadToken = new();
private readonly HashSet<ResPath> _reloadQueue = new();
private List<FileSystemWatcher> _watchers = new(); // this list is never used but needed to prevent them from being garbage collected
private ResourceManifestData _manifest = ResourceManifestData.Default;

public event Action<ResPath>? OnChanged;

Expand All @@ -37,6 +41,7 @@ public void Initialize()
{
_sawmill = _logMan.GetSawmill("reload");
_clyde.OnWindowFocused += WindowFocusedChanged;
_manifest = ResourceManifestData.LoadResourceManifest(_res);
}

private void WindowFocusedChanged(WindowFocusedEventArgs args)
Expand Down Expand Up @@ -136,11 +141,30 @@ void OnWatch(object sender, FileSystemEventArgs args)
}

var file = ResPath.FromRelativeSystemPath(relPath).ToRootedPath();
if (!file.CanonPath.Contains("/../"))
_reloadQueue.Add(file);
if (file.CanonPath.Contains("/../"))
continue;
var path = ResolveModularPath(file, rootIter);
_reloadQueue.Add(path);
}
});
}
#endif
}

private ResPath ResolveModularPath(ResPath relative, string rootIter)
{
var finalPath = relative;
var rootName = new DirectoryInfo(rootIter).Name;

if (_manifest.ModularResources == null)
return relative;

foreach (var (vfsPath, diskPath) in _manifest.ModularResources)
{
if (diskPath != rootName) continue;
finalPath = new ResPath(vfsPath) / relative;
break;
}
return finalPath;
}
}
7 changes: 5 additions & 2 deletions Robust.Client/Utility/SpriteSpecifierExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.Graphics;
using Robust.Shared.IoC;
Expand All @@ -20,15 +21,17 @@ public static class SpriteSpecifierExt
[Obsolete("Use SpriteSystem.GetTexture() instead")]
public static Texture GetTexture(this SpriteSpecifier.Texture texSpecifier, IResourceCache cache)
{
var texPath = PathHelpers.ApparentPath(texSpecifier.TexturePath, SpriteSpecifierSerializer.TextureRoot);
return cache
.GetResource<TextureResource>(SpriteSpecifierSerializer.TextureRoot / texSpecifier.TexturePath)
.GetResource<TextureResource>(texPath)
.Texture;
}

[Obsolete("Use SpriteSystem.GetState() instead")]
public static RSI.State GetState(this SpriteSpecifier.Rsi rsiSpecifier, IResourceCache cache)
{
if (!cache.TryGetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / rsiSpecifier.RsiPath, out var theRsi))
var rsiPath = PathHelpers.ApparentPath(rsiSpecifier.RsiPath, SpriteSpecifierSerializer.TextureRoot);
if (!cache.TryGetResource<RSIResource>(rsiPath, out var theRsi))
{
var sys = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<SpriteSystem>();
Logger.Error("SpriteSpecifier failed to load RSI {0}", rsiSpecifier.RsiPath);
Expand Down
2 changes: 2 additions & 0 deletions Robust.Packaging/RobustClientPackaging.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Robust.Packaging.AssetProcessing;
using Robust.Shared.ContentPack;

namespace Robust.Packaging;

Expand Down Expand Up @@ -34,5 +35,6 @@ public static async Task WriteClientResources(
.ToHashSet();

await RobustSharedPackaging.DoResourceCopy(Path.Combine(contentDir, "Resources"), pass, ignoreSet, cancel: cancel);
await RobustSharedPackaging.DoModularResourceCopy(contentDir, pass, ignoreSet);
}
}
2 changes: 2 additions & 0 deletions Robust.Packaging/RobustServerPackaging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@ await RobustSharedPackaging.DoResourceCopy(
pass,
ignoreSet,
cancel: cancel);

await RobustSharedPackaging.DoModularResourceCopy(contentDir, pass, ignoreSet);
}
}
Loading
Loading