Replace ResourcePath with ResPath (#3926)

This commit is contained in:
Ygg01
2023-04-19 15:37:46 +02:00
committed by GitHub
parent 8958b2123e
commit d6a3e1e286
87 changed files with 449 additions and 1179 deletions

View File

@@ -108,9 +108,7 @@ namespace Robust.Benchmarks.Serialization.Copy
copy.Potency = Seed.Potency;
copy.Ligneous = Seed.Ligneous;
copy.PlantRsi = Seed.PlantRsi == null
? null!
: new ResourcePath(Seed.PlantRsi.ToString(), Seed.PlantRsi.Separator);
copy.PlantRsi = new ResPath(Seed.PlantRsi.ToString());
copy.PlantIconState = Seed.PlantIconState;
copy.Bioluminescent = Seed.Bioluminescent;
copy.BioluminescentColor = Seed.BioluminescentColor;

View File

@@ -87,7 +87,7 @@ namespace Robust.Benchmarks.Serialization.Definitions
#endregion
#region Cosmetics
[DataField("plantRsi", required: true)] public ResourcePath PlantRsi { get; set; } = default!;
[DataField("plantRsi", required: true)] public ResPath PlantRsi { get; set; } = default!;
[DataField("plantIconState")] public string PlantIconState { get; set; } = "produce";
[DataField("bioluminescent")] public bool Bioluminescent { get; set; }
[DataField("bioluminescentColor")] public Color BioluminescentColor { get; set; } = Color.White;

View File

@@ -31,17 +31,6 @@ public class ResourcePathBench
}
return res;
}
[Benchmark]
public ResourcePath? CreateResourcePath()
{
ResourcePath? res = null;
for (var i = 0; i < N; i++)
{
res = new ResourcePath(_path);
}
return res;
}
}
#pragma warning restore CS0612

View File

@@ -60,7 +60,7 @@ namespace Robust.Client.WebView.Cef
var cachePath = "";
if (_resourceManager.UserData is WritableDirProvider userData)
cachePath = userData.GetFullPath(new ResourcePath("/cef_cache"));
cachePath = userData.GetFullPath(new ResPath("/cef_cache"));
var settings = new CefSettings()
{
@@ -171,10 +171,10 @@ namespace Robust.Client.WebView.Cef
_sawmill.Debug($"HANDLING: {request.Url}");
var resourcePath = new ResourcePath(uri.AbsolutePath);
if (_resourceManager.TryContentFileRead(resourcePath, out var stream))
var resPath = new ResPath(uri.AbsolutePath);
if (_resourceManager.TryContentFileRead(resPath, out var stream))
{
if (!_parent.TryGetResourceMimeType(resourcePath.Extension, out var mime))
if (!_parent.TryGetResourceMimeType(resPath.Extension, out var mime))
mime = "application/octet-stream";
return new RequestResultStream(stream, mime, HttpStatusCode.OK).MakeHandler();

View File

@@ -103,7 +103,7 @@ internal sealed partial class MidiManager : IMidiManager
private const string ContentCustomSoundfontDirectory = "/Audio/MidiCustom/";
private static ResourcePath CustomSoundfontDirectory = new ResourcePath("/soundfonts/");
private static ResPath CustomSoundfontDirectory = new("/soundfonts/");
private readonly ResourceLoaderCallbacks _soundfontLoaderCallbacks;
@@ -476,7 +476,7 @@ internal sealed partial class MidiManager : IMidiManager
Stream? stream;
var resourceCache = _parent._resourceManager;
var resourcePath = new ResourcePath(filename);
var resourcePath = new ResPath(filename);
if (resourcePath.IsRooted)
{

View File

@@ -468,7 +468,7 @@ namespace Robust.Client.Console.Commands
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
using var writer = _res.UserData.OpenWriteText(new ResourcePath("/guidump.txt"));
using var writer = _res.UserData.OpenWriteText(new ResPath("/guidump.txt"));
foreach (var root in _ui.AllRoots)
{
@@ -674,7 +674,7 @@ namespace Robust.Client.Console.Commands
? StringComparer.Ordinal
: StringComparer.OrdinalIgnoreCase;
var reversePathResolution = new ConcurrentDictionary<string, HashSet<ResourcePath>>(stringComparer);
var reversePathResolution = new ConcurrentDictionary<string, HashSet<ResPath>>(stringComparer);
var taskManager = _taskManager;
@@ -688,7 +688,7 @@ namespace Robust.Client.Console.Commands
throw new NotImplementedException();
}
reversePathResolution.GetOrAdd(fullPath, _ => new HashSet<ResourcePath>()).Add(path);
reversePathResolution.GetOrAdd(fullPath, _ => new HashSet<ResPath>()).Add(path);
var dir = Path.GetDirectoryName(fullPath)!;
var fileName = Path.GetFileName(fullPath);
@@ -702,7 +702,7 @@ namespace Robust.Client.Console.Commands
throw new NotImplementedException();
}
reversePathResolution.GetOrAdd(incFullPath, _ => new HashSet<ResourcePath>()).Add(path);
reversePathResolution.GetOrAdd(incFullPath, _ => new HashSet<ResPath>()).Add(path);
var incDir = Path.GetDirectoryName(incFullPath)!;
var incFileName = Path.GetFileName(incFullPath);

View File

@@ -157,7 +157,7 @@ namespace Robust.Client
ProgramShared.FinishCheckBadFileExtensions(checkBadExtensions);
_prototypeManager.Initialize();
_prototypeManager.LoadDirectory(new ResourcePath("/EnginePrototypes/"));
_prototypeManager.LoadDirectory(new("/EnginePrototypes/"));
_prototypeManager.LoadDirectory(Options.PrototypeDirectory);
_prototypeManager.ResolveResults();
_userInterfaceManager.Initialize();
@@ -387,7 +387,7 @@ namespace Robust.Client
{
foreach (var (api, prefix) in mounts)
{
_resourceCache.MountLoaderApi(api, "", new ResourcePath(prefix));
_resourceCache.MountLoaderApi(api, "", new(prefix));
}
}

View File

@@ -51,22 +51,22 @@ namespace Robust.Client
/// <summary>
/// Directory to load all assemblies from.
/// </summary>
public ResourcePath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
public ResPath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
/// <summary>
/// Directory to load all prototypes from.
/// </summary>
public ResourcePath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
public ResPath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
/// <summary>
/// Directory resource path containing window icons to load.
/// </summary>
public ResourcePath? WindowIconSet { get; init; }
public ResPath? WindowIconSet { get; init; }
/// <summary>
/// Resource path for splash image to show when the game starts up.
/// </summary>
public ResourcePath? SplashLogo { get; init; }
public ResPath? SplashLogo { get; init; }
/// <summary>
/// Whether to disable mounting the "Resources/" folder on FULL_RELEASE.

View File

@@ -18,7 +18,7 @@ namespace Robust.Client.GameObjects
public IDirectionalTextureProvider? Icon { get; private set; }
[DataField("sprite")]
private ResourcePath? rsi;
private ResPath rsi;
[DataField("state")]
private string? stateID;

View File

@@ -505,10 +505,10 @@ namespace Robust.Client.GameObjects
public int AddLayer(string texturePath, int? newIndex = null)
{
return AddLayer(new ResourcePath(texturePath), newIndex);
return AddLayer(new ResPath(texturePath), newIndex);
}
public int AddLayer(ResourcePath texturePath, int? newIndex = null)
public int AddLayer(ResPath texturePath, int? newIndex = null)
{
if (!resourceCache.TryGetResource<TextureResource>(TextureRoot / texturePath, out var texture))
{
@@ -555,7 +555,7 @@ namespace Robust.Client.GameObjects
public int AddLayer(RSI.StateId stateId, string rsiPath, int? newIndex = null)
{
return AddLayer(stateId, new ResourcePath(rsiPath), newIndex);
return AddLayer(stateId, new ResPath(rsiPath), newIndex);
}
public int AddLayerState(string stateId, string rsiPath, int? newIndex = null)
@@ -563,7 +563,7 @@ namespace Robust.Client.GameObjects
return AddLayer(new RSI.StateId(stateId), rsiPath, newIndex);
}
public int AddLayer(RSI.StateId stateId, ResourcePath rsiPath, int? newIndex = null)
public int AddLayer(RSI.StateId stateId, ResPath rsiPath, int? newIndex = null)
{
if (!resourceCache.TryGetResource<RSIResource>(TextureRoot / rsiPath, out var res))
{
@@ -573,7 +573,7 @@ namespace Robust.Client.GameObjects
return AddLayer(stateId, res?.RSI, newIndex);
}
public int AddLayerState(string stateId, ResourcePath rsiPath, int? newIndex = null)
public int AddLayerState(string stateId, ResPath rsiPath, int? newIndex = null)
{
return AddLayer(new RSI.StateId(stateId), rsiPath, newIndex);
}
@@ -899,15 +899,15 @@ namespace Robust.Client.GameObjects
public void LayerSetTexture(int layer, string texturePath)
{
LayerSetTexture(layer, new ResourcePath(texturePath));
LayerSetTexture(layer, new ResPath(texturePath));
}
public void LayerSetTexture(object layerKey, string texturePath)
{
LayerSetTexture(layerKey, new ResourcePath(texturePath));
LayerSetTexture(layerKey, new ResPath(texturePath));
}
public void LayerSetTexture(int layer, ResourcePath texturePath)
public void LayerSetTexture(int layer, ResPath texturePath)
{
if (!resourceCache.TryGetResource<TextureResource>(TextureRoot / texturePath, out var texture))
{
@@ -925,7 +925,7 @@ namespace Robust.Client.GameObjects
LayerSetTexture(layer, texture?.Texture);
}
public void LayerSetTexture(object layerKey, ResourcePath texturePath)
public void LayerSetTexture(object layerKey, ResPath texturePath)
{
if (!LayerMapTryGet(layerKey, out var layer, true))
return;
@@ -991,15 +991,15 @@ namespace Robust.Client.GameObjects
public void LayerSetState(int layer, RSI.StateId stateId, string rsiPath)
{
LayerSetState(layer, stateId, new ResourcePath(rsiPath));
LayerSetState(layer, stateId, new ResPath(rsiPath));
}
public void LayerSetState(object layerKey, RSI.StateId stateId, string rsiPath)
{
LayerSetState(layerKey, stateId, new ResourcePath(rsiPath));
LayerSetState(layerKey, stateId, new ResPath(rsiPath));
}
public void LayerSetState(int layer, RSI.StateId stateId, ResourcePath rsiPath)
public void LayerSetState(int layer, RSI.StateId stateId, ResPath rsiPath)
{
if (!resourceCache.TryGetResource<RSIResource>(TextureRoot / rsiPath, out var res))
{
@@ -1009,7 +1009,7 @@ namespace Robust.Client.GameObjects
LayerSetState(layer, stateId, res?.RSI);
}
public void LayerSetState(object layerKey, RSI.StateId stateId, ResourcePath rsiPath)
public void LayerSetState(object layerKey, RSI.StateId stateId, ResPath rsiPath)
{
if (!LayerMapTryGet(layerKey, out var layer, true))
return;
@@ -1035,15 +1035,15 @@ namespace Robust.Client.GameObjects
public void LayerSetRSI(int layer, string rsiPath)
{
LayerSetRSI(layer, new ResourcePath(rsiPath));
LayerSetRSI(layer, new ResPath(rsiPath));
}
public void LayerSetRSI(object layerKey, string rsiPath)
{
LayerSetRSI(layerKey, new ResourcePath(rsiPath));
LayerSetRSI(layerKey, new ResPath(rsiPath));
}
public void LayerSetRSI(int layer, ResourcePath rsiPath)
public void LayerSetRSI(int layer, ResPath rsiPath)
{
if (!resourceCache.TryGetResource<RSIResource>(TextureRoot / rsiPath, out var res))
{
@@ -1053,7 +1053,7 @@ namespace Robust.Client.GameObjects
LayerSetRSI(layer, res?.RSI);
}
public void LayerSetRSI(object layerKey, ResourcePath rsiPath)
public void LayerSetRSI(object layerKey, ResPath rsiPath)
{
if (!LayerMapTryGet(layerKey, out var layer, true))
return;
@@ -1678,7 +1678,7 @@ namespace Robust.Client.GameObjects
Shader = ShaderPrototype,
State = State.Name,
Visible = Visible,
RsiPath = RSI?.Path?.ToString(),
RsiPath = RSI?.Path.CanonPath,
//todo TexturePath = Textur
//todo MapKeys
};
@@ -1797,7 +1797,7 @@ namespace Robust.Client.GameObjects
}
else
{
Logger.ErrorS(LogCategory, "State '{0}' does not exist in set RSI ({1}). Trace:\n{2}", State, rsi?.Path?.ToString() ?? "null",
Logger.ErrorS(LogCategory, "State '{0}' does not exist in set RSI ({1}). Trace:\n{2}", State, rsi?.Path.CanonPath ?? "null",
Environment.StackTrace);
Texture = null;
}

View File

@@ -290,7 +290,7 @@ public sealed class AudioSystem : SharedAudioSystem
#region Play AudioStream
private bool TryGetAudio(string filename, [NotNullWhen(true)] out AudioResource? audio)
{
if (_resourceCache.TryGetResource<AudioResource>(new ResourcePath(filename), out audio))
if (_resourceCache.TryGetResource<AudioResource>(new ResPath(filename), out audio))
return true;
_sawmill.Error($"Server tried to play audio file {filename} which does not exist.");
@@ -524,7 +524,7 @@ public sealed class AudioSystem : SharedAudioSystem
/// <inheritdoc />
public override IPlayingAudioStream? Play(string filename, Filter playerFilter, EntityUid entity, bool recordReplay, AudioParams? audioParams = null)
{
if (_resourceCache.TryGetResource<AudioResource>(new ResourcePath(filename), out var audio))
if (_resourceCache.TryGetResource<AudioResource>(new ResPath(filename), out var audio))
{
return Play(audio, entity, null, audioParams);
}
@@ -555,7 +555,7 @@ public sealed class AudioSystem : SharedAudioSystem
/// <inheritdoc />
public override IPlayingAudioStream? PlayEntity(string filename, ICommonSession recipient, EntityUid uid, AudioParams? audioParams = null)
{
if (_resourceCache.TryGetResource<AudioResource>(new ResourcePath(filename), out var audio))
if (_resourceCache.TryGetResource<AudioResource>(new ResPath(filename), out var audio))
{
return Play(audio, uid, null, audioParams);
}
@@ -565,7 +565,7 @@ public sealed class AudioSystem : SharedAudioSystem
/// <inheritdoc />
public override IPlayingAudioStream? PlayEntity(string filename, EntityUid recipient, EntityUid uid, AudioParams? audioParams = null)
{
if (_resourceCache.TryGetResource<AudioResource>(new ResourcePath(filename), out var audio))
if (_resourceCache.TryGetResource<AudioResource>(new ResPath(filename), out var audio))
{
return Play(audio, uid, null, audioParams);
}

View File

@@ -33,7 +33,7 @@ namespace Robust.Client.Graphics.Clyde
private Renderer _chosenRenderer;
#pragma warning restore 414
private ResourcePath? _windowIconPath;
private ResPath _windowIconPath;
private Thread? _windowingThread;
private bool _vSync;
private WindowMode _windowMode;
@@ -96,7 +96,7 @@ namespace Robust.Client.Graphics.Clyde
var iconPath = _cfg.GetCVar(CVars.DisplayWindowIconSet);
if (!string.IsNullOrWhiteSpace(iconPath))
_windowIconPath = new ResourcePath(iconPath);
_windowIconPath = new ResPath(iconPath);
_windowingThread = Thread.CurrentThread;

View File

@@ -27,7 +27,7 @@ namespace Robust.Client.Graphics
/// The original path of this RSI or null.
/// </summary>
[ViewVariables]
public ResourcePath? Path { get; }
public ResPath Path { get; }
public State this[StateId key] => States[key];
@@ -46,7 +46,7 @@ namespace Robust.Client.Graphics
return States.TryGetValue(stateId, out state);
}
public RSI(Vector2i size, ResourcePath? path = null, int capacity = 0)
public RSI(Vector2i size, ResPath path = default, int capacity = 0)
{
Size = size;
Path = path;

View File

@@ -10,7 +10,7 @@ namespace Robust.Client.Graphics
public ParsedShader(IReadOnlyDictionary<string, ShaderUniformDefinition> uniforms,
IReadOnlyDictionary<string, ShaderVaryingDefinition> varyings,
IReadOnlyDictionary<string, ShaderConstantDefinition> constants, IList<ShaderFunctionDefinition> functions,
ShaderLightMode lightMode, ShaderBlendMode blendMode, ShaderPreset preset, ICollection<ResourcePath> includes)
ShaderLightMode lightMode, ShaderBlendMode blendMode, ShaderPreset preset, ICollection<ResPath> includes)
{
Uniforms = uniforms;
Varyings = varyings;
@@ -29,7 +29,7 @@ namespace Robust.Client.Graphics
public ShaderLightMode LightMode { get; }
public ShaderBlendMode BlendMode { get; }
public ShaderPreset Preset { get; }
public ICollection<ResourcePath> Includes { get; }
public ICollection<ResPath> Includes { get; }
}

View File

@@ -156,7 +156,7 @@ namespace Robust.Client.Graphics
_currentParser.Take(); // Quote.
var pathString = new string(pathParsing.ToArray());
var path = new ResourcePath(pathString);
var path = new ResPath(pathString);
_includes.AddLast(path);
using var stream = _resManager.ContentFileRead(path);
using var reader = new StreamReader(stream, EncodingHelpers.UTF8);

View File

@@ -19,7 +19,7 @@ namespace Robust.Client.Graphics
private readonly List<ShaderConstantDefinition> _constantsParsing = new();
private readonly List<ShaderVaryingDefinition> _varyingsParsing = new();
private readonly List<ShaderFunctionDefinition> _functionsParsing = new();
private readonly LinkedList<ResourcePath> _includes = new();
private readonly LinkedList<ResPath> _includes = new();
public static ParsedShader Parse(TextReader reader, IResourceManager resManager)
{

View File

@@ -102,7 +102,7 @@ namespace Robust.Client.Graphics
}
[DataField("kind", readOnly: true, required: true)] private string _rawKind = default!;
[DataField("path", readOnly: true)] private ResourcePath? path;
[DataField("path", readOnly: true)] private ResPath path;
[DataField("params", readOnly: true)] private Dictionary<string, string>? paramMapping;
[DataField("light_mode", readOnly: true)] private string? rawMode;
[DataField("blend_mode", readOnly: true)] private string? rawBlendMode;

View File

@@ -113,7 +113,7 @@ namespace Robust.Client.Input
Contexts.ContextChanged += OnContextChanged;
var path = new ResourcePath(KeybindsPath);
var path = new ResPath(KeybindsPath);
if (_resourceMan.UserData.Exists(path))
{
LoadKeyFile(path, true);
@@ -154,7 +154,7 @@ namespace Robust.Client.Input
mapping.Add("binds", _serialization.WriteValue(modifiedBindings, notNullableOverride: true));
mapping.Add("leaveEmpty", _serialization.WriteValue(leaveEmpty, notNullableOverride: true));
var path = new ResourcePath(KeybindsPath);
var path = new ResPath(KeybindsPath);
using var writer = _resourceMan.UserData.OpenWriteText(path);
var stream = new YamlStream {new(mapping.ToYaml())};
stream.Save(new YamlMappingFix(new Emitter(writer)), false);
@@ -474,7 +474,7 @@ namespace Robust.Client.Input
return true;
}
private void LoadKeyFile(ResourcePath file, bool userData)
private void LoadKeyFile(ResPath file, bool userData)
{
TextReader reader;
if (userData)

View File

@@ -101,7 +101,7 @@ namespace Robust.Client.Map
{
Image<Rgba32> image;
// Already know it's not null above
var path = def.Sprite!;
var path = def.Sprite!.Value;
using (var stream = _resourceCache.ContentFileRead(path))
{

View File

@@ -721,7 +721,7 @@ namespace Robust.Client.Placement
}
else
{
sc.AddLayer(new ResourcePath("/Textures/UserInterface/tilebuildoverlay.png"));
sc.AddLayer(new ResPath("/Textures/UserInterface/tilebuildoverlay.png"));
}
sc.NoRotation = noRot;
@@ -735,7 +735,7 @@ namespace Robust.Client.Placement
private void PreparePlacementTile()
{
var sc = SetupPlacementOverlayEntity();
sc.AddLayer(new ResourcePath("/Textures/UserInterface/tilebuildoverlay.png"));
sc.AddLayer(new ResPath("/Textures/UserInterface/tilebuildoverlay.png"));
IsActive = true;
}

View File

@@ -196,12 +196,12 @@ namespace Robust.Client.Placement
public TextureResource GetSprite(string key)
{
return pManager.ResourceCache.GetResource<TextureResource>(new ResourcePath("/Textures/") / key);
return pManager.ResourceCache.GetResource<TextureResource>(new ResPath("/Textures/") / key);
}
public bool TryGetSprite(string key, [NotNullWhen(true)] out TextureResource? sprite)
{
return pManager.ResourceCache.TryGetResource(new ResourcePath(@"/Textures/") / key, out sprite);
return pManager.ResourceCache.TryGetResource(new ResPath(@"/Textures/") / key, out sprite);
}
/// <summary>

View File

@@ -29,7 +29,7 @@ namespace Robust.Client.Prototypes
private readonly List<FileSystemWatcher> _watchers = new();
private readonly TimeSpan _reloadDelay = TimeSpan.FromMilliseconds(10);
private CancellationTokenSource _reloadToken = new();
private readonly HashSet<ResourcePath> _reloadQueue = new();
private readonly HashSet<ResPath> _reloadQueue = new();
public override void Initialize()
{
@@ -111,7 +111,7 @@ namespace Robust.Client.Prototypes
TaskManager.RunOnMainThread(() =>
{
var file = new ResourcePath(args.FullPath);
var file = new ResPath(args.FullPath);
foreach (var root in Resources.GetContentRoots())
{
@@ -120,7 +120,7 @@ namespace Robust.Client.Prototypes
continue;
}
_reloadQueue.Add(relative);
_reloadQueue.Add(relative.Value);
}
});
};

View File

@@ -12,7 +12,7 @@ namespace Robust.Client.ResourceManagement
/// <summary>
/// Fallback resource path if this one does not exist.
/// </summary>
public virtual ResourcePath? Fallback => null;
public virtual ResPath Fallback => default;
/// <summary>
/// Disposes this resource.
@@ -26,9 +26,9 @@ namespace Robust.Client.ResourceManagement
/// </summary>
/// <param name="cache">ResourceCache this resource is being loaded into.</param>
/// <param name="path">Path of the resource requested on the VFS.</param>
public abstract void Load(IResourceCache cache, ResourcePath path);
public abstract void Load(IResourceCache cache, ResPath path);
public virtual void Reload(IResourceCache cache, ResourcePath path, CancellationToken ct = default)
public virtual void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
{
}

View File

@@ -11,34 +11,34 @@ namespace Robust.Client.ResourceManagement
T GetResource<T>(string path, bool useFallback = true)
where T : BaseResource, new();
T GetResource<T>(ResourcePath path, bool useFallback = true)
T GetResource<T>(ResPath path, bool useFallback = true)
where T : BaseResource, new();
bool TryGetResource<T>(string path, [NotNullWhen(true)] out T? resource)
where T : BaseResource, new();
bool TryGetResource<T>(ResourcePath path, [NotNullWhen(true)] out T? resource)
bool TryGetResource<T>(ResPath path, [NotNullWhen(true)] out T? resource)
where T : BaseResource, new();
void ReloadResource<T>(string path)
where T : BaseResource, new();
void ReloadResource<T>(ResourcePath path)
void ReloadResource<T>(ResPath path)
where T : BaseResource, new();
void CacheResource<T>(string path, T resource)
where T : BaseResource, new();
void CacheResource<T>(ResourcePath path, T resource)
void CacheResource<T>(ResPath path, T resource)
where T : BaseResource, new();
T GetFallback<T>()
where T : BaseResource, new();
IEnumerable<KeyValuePair<ResourcePath, T>> GetAllResources<T>() where T : BaseResource, new();
IEnumerable<KeyValuePair<ResPath, T>> GetAllResources<T>() where T : BaseResource, new();
// Resource load callbacks so content can hook stuff like click maps.
event Action<TextureLoadedEventArgs> OnRawTextureLoaded;
event Action<RsiLoadedEventArgs> OnRsiLoaded;
}
}
}

View File

@@ -9,7 +9,7 @@ namespace Robust.Client.ResourceManagement
void TextureLoaded(TextureLoadedEventArgs eventArgs);
void RsiLoaded(RsiLoadedEventArgs eventArgs);
void MountLoaderApi(IFileApi api, string apiPrefix, ResourcePath? prefix=null);
void MountLoaderApi(IFileApi api, string apiPrefix, ResPath? prefix=null);
void PreloadTextures();
}
}

View File

@@ -24,7 +24,7 @@ namespace Robust.Client.ResourceManagement
{
}
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
public bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream)
{
if (_api.TryOpen($"{_prefix}{relPath}", out stream))
{
@@ -35,14 +35,14 @@ namespace Robust.Client.ResourceManagement
return false;
}
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
public IEnumerable<ResPath> FindFiles(ResPath path)
{
foreach (var relPath in _api.AllFiles)
{
if (!relPath.StartsWith(_prefix))
continue;
var resP = new ResourcePath(relPath[_prefix.Length..]);
var resP = new ResPath(relPath[_prefix.Length..]);
if (resP.TryRelativeTo(path, out _))
{
yield return resP;

View File

@@ -12,17 +12,17 @@ namespace Robust.Client.ResourceManagement
{
internal sealed partial class ResourceCache : ResourceManager, IResourceCacheInternal, IDisposable
{
private readonly Dictionary<Type, Dictionary<ResourcePath, BaseResource>> CachedResources =
private readonly Dictionary<Type, Dictionary<ResPath, BaseResource>> CachedResources =
new();
private readonly Dictionary<Type, BaseResource> _fallbacks = new();
public T GetResource<T>(string path, bool useFallback = true) where T : BaseResource, new()
{
return GetResource<T>(new ResourcePath(path), useFallback);
return GetResource<T>(new ResPath(path), useFallback);
}
public T GetResource<T>(ResourcePath path, bool useFallback = true) where T : BaseResource, new()
public T GetResource<T>(ResPath path, bool useFallback = true) where T : BaseResource, new()
{
var cache = GetTypeDict<T>();
if (cache.TryGetValue(path, out var cached))
@@ -56,10 +56,10 @@ namespace Robust.Client.ResourceManagement
public bool TryGetResource<T>(string path, [NotNullWhen(true)] out T? resource) where T : BaseResource, new()
{
return TryGetResource(new ResourcePath(path), out resource);
return TryGetResource(new ResPath(path), out resource);
}
public bool TryGetResource<T>(ResourcePath path, [NotNullWhen(true)] out T? resource) where T : BaseResource, new()
public bool TryGetResource<T>(ResPath path, [NotNullWhen(true)] out T? resource) where T : BaseResource, new()
{
var cache = GetTypeDict<T>();
if (cache.TryGetValue(path, out var cached))
@@ -85,10 +85,10 @@ namespace Robust.Client.ResourceManagement
public void ReloadResource<T>(string path) where T : BaseResource, new()
{
ReloadResource<T>(new ResourcePath(path));
ReloadResource<T>(new ResPath(path));
}
public void ReloadResource<T>(ResourcePath path) where T : BaseResource, new()
public void ReloadResource<T>(ResPath path) where T : BaseResource, new()
{
var cache = GetTypeDict<T>();
@@ -110,20 +110,20 @@ namespace Robust.Client.ResourceManagement
public bool HasResource<T>(string path) where T : BaseResource, new()
{
return HasResource<T>(new ResourcePath(path));
return HasResource<T>(new ResPath(path));
}
public bool HasResource<T>(ResourcePath path) where T : BaseResource, new()
public bool HasResource<T>(ResPath path) where T : BaseResource, new()
{
return TryGetResource<T>(path, out var _);
}
public void CacheResource<T>(string path, T resource) where T : BaseResource, new()
{
CacheResource(new ResourcePath(path), resource);
CacheResource(new ResPath(path), resource);
}
public void CacheResource<T>(ResourcePath path, T resource) where T : BaseResource, new()
public void CacheResource<T>(ResPath path, T resource) where T : BaseResource, new()
{
GetTypeDict<T>()[path] = resource;
}
@@ -146,9 +146,9 @@ namespace Robust.Client.ResourceManagement
return (T) fallback;
}
public IEnumerable<KeyValuePair<ResourcePath, T>> GetAllResources<T>() where T : BaseResource, new()
public IEnumerable<KeyValuePair<ResPath, T>> GetAllResources<T>() where T : BaseResource, new()
{
return GetTypeDict<T>().Select(p => new KeyValuePair<ResourcePath, T>(p.Key, (T) p.Value));
return GetTypeDict<T>().Select(p => new KeyValuePair<ResPath, T>(p.Key, (T) p.Value));
}
public event Action<TextureLoadedEventArgs>? OnRawTextureLoaded;
@@ -190,11 +190,11 @@ namespace Robust.Client.ResourceManagement
#endregion IDisposable Members
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Dictionary<ResourcePath, BaseResource> GetTypeDict<T>()
private Dictionary<ResPath, BaseResource> GetTypeDict<T>()
{
if (!CachedResources.TryGetValue(typeof(T), out var ret))
{
ret = new Dictionary<ResourcePath, BaseResource>();
ret = new Dictionary<ResPath, BaseResource>();
CachedResources.Add(typeof(T), ret);
}
@@ -211,11 +211,11 @@ namespace Robust.Client.ResourceManagement
OnRsiLoaded?.Invoke(eventArgs);
}
public void MountLoaderApi(IFileApi api, string apiPrefix, ResourcePath? prefix=null)
public void MountLoaderApi(IFileApi api, string apiPrefix, ResPath? prefix=null)
{
prefix ??= ResourcePath.Root;
prefix ??= ResPath.Root;
var root = new LoaderApiLoader(api, apiPrefix);
AddRoot(prefix, root);
AddRoot(prefix.Value, root);
}
}
}

View File

@@ -11,7 +11,7 @@ namespace Robust.Client.ResourceManagement
{
public AudioStream AudioStream { get; private set; } = default!;
public override void Load(IResourceCache cache, ResourcePath path)
public override void Load(IResourceCache cache, ResPath path)
{
if (!cache.ContentFileExists(path))
{

View File

@@ -9,7 +9,7 @@ namespace Robust.Client.ResourceManagement
{
internal IFontFaceHandle FontFaceHandle { get; private set; } = default!;
public override void Load(IResourceCache cache, ResourcePath path)
public override void Load(IResourceCache cache, ResPath path)
{
if (!cache.TryContentFileRead(path, out var stream))
{

View File

@@ -18,7 +18,7 @@ namespace Robust.Client.ResourceManagement
/// </summary>
public sealed class RSIResource : BaseResource
{
public override ResourcePath? Fallback => new("/Textures/error.rsi");
public override ResPath Fallback => new("/Textures/error.rsi");
public RSI RSI { get; private set; } = default!;
@@ -32,7 +32,7 @@ namespace Robust.Client.ResourceManagement
/// </summary>
public const uint MAXIMUM_RSI_VERSION = RsiLoading.MAXIMUM_RSI_VERSION;
public override void Load(IResourceCache cache, ResourcePath path)
public override void Load(IResourceCache cache, ResPath path)
{
var clyde = IoCManager.Resolve<IClyde>();
@@ -373,7 +373,7 @@ namespace Robust.Client.ResourceManagement
internal sealed class LoadStepData
{
public bool Bad;
public ResourcePath Path = default!;
public ResPath Path = default!;
public Image<Rgba32> AtlasSheet = default!;
public int DimX;
public StateReg[] AtlasList = default!;

View File

@@ -15,7 +15,7 @@ namespace Robust.Client.ResourceManagement
internal ClydeHandle ClydeHandle { get; private set; }
internal ParsedShader ParsedShader { get; private set; } = default!;
public override void Load(IResourceCache cache, ResourcePath path)
public override void Load(IResourceCache cache, ResPath path)
{
using (var stream = cache.ContentFileRead(path))
using (var reader = new StreamReader(stream, EncodingHelpers.UTF8))
@@ -27,7 +27,7 @@ namespace Robust.Client.ResourceManagement
ClydeHandle = clyde.LoadShader(ParsedShader, path.ToString());
}
public override void Reload(IResourceCache cache, ResourcePath path, CancellationToken ct = default)
public override void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
{
ct = ct != default ? ct : new CancellationTokenSource(30000).Token;

View File

@@ -14,11 +14,11 @@ namespace Robust.Client.ResourceManagement
public sealed class TextureResource : BaseResource
{
private OwnedTexture _texture = default!;
public override ResourcePath Fallback => new("/Textures/noSprite.png");
public override ResPath Fallback => new("/Textures/noSprite.png");
public Texture Texture => _texture;
public override void Load(IResourceCache cache, ResourcePath path)
public override void Load(IResourceCache cache, ResPath path)
{
var clyde = IoCManager.Resolve<IClyde>();
@@ -64,7 +64,7 @@ namespace Robust.Client.ResourceManagement
data.Image.Dispose();
}
private static TextureLoadParameters? TryLoadTextureParameters(IResourceCache cache, ResourcePath path)
private static TextureLoadParameters? TryLoadTextureParameters(IResourceCache cache, ResPath path)
{
var metaPath = path.WithName(path.Filename + ".yml");
if (cache.TryContentFileRead(metaPath, out var stream))
@@ -91,7 +91,7 @@ namespace Robust.Client.ResourceManagement
return null;
}
public override void Reload(IResourceCache cache, ResourcePath path, CancellationToken ct = default)
public override void Reload(IResourceCache cache, ResPath path, CancellationToken ct = default)
{
var clyde = IoCManager.Resolve<IClyde>();
@@ -116,7 +116,7 @@ namespace Robust.Client.ResourceManagement
internal sealed class LoadStepData
{
public ResourcePath Path = default!;
public ResPath Path = default!;
public Image<Rgba32> Image = default!;
public TextureLoadParameters LoadParameters;
public OwnedTexture Texture = default!;

View File

@@ -8,7 +8,7 @@ namespace Robust.Client.ResourceManagement
{
public readonly struct RsiLoadedEventArgs
{
internal RsiLoadedEventArgs(ResourcePath path, RSIResource resource, Image atlas, Dictionary<RSI.StateId, Vector2i[][]> atlasOffsets)
internal RsiLoadedEventArgs(ResPath path, RSIResource resource, Image atlas, Dictionary<RSI.StateId, Vector2i[][]> atlasOffsets)
{
Path = path;
Resource = resource;
@@ -16,7 +16,7 @@ namespace Robust.Client.ResourceManagement
AtlasOffsets = atlasOffsets;
}
public ResourcePath Path { get; }
public ResPath Path { get; }
public RSIResource Resource { get; }
public Image Atlas { get; }
public Dictionary<RSI.StateId, Vector2i[][]> AtlasOffsets { get; }

View File

@@ -5,14 +5,14 @@ namespace Robust.Client.ResourceManagement
{
public readonly struct TextureLoadedEventArgs
{
internal TextureLoadedEventArgs(ResourcePath path, Image image, TextureResource resource)
internal TextureLoadedEventArgs(ResPath path, Image image, TextureResource resource)
{
Path = path;
Image = image;
Resource = resource;
}
public ResourcePath Path { get; }
public ResPath Path { get; }
public Image Image { get; }
public TextureResource Resource { get; }
}

View File

@@ -45,7 +45,7 @@ namespace Robust.Client.UserInterface.CustomControls
[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private static readonly ResourcePath HistoryPath = new("/debug_console_history.json");
private static readonly ResPath HistoryPath = new("/debug_console_history.json");
private readonly ConcurrentQueue<FormattedMessage> _messageQueue = new();

View File

@@ -11,5 +11,5 @@ public sealed class FontPrototype : IPrototype
public string ID { get; } = default!;
[DataField("path", required: true)]
public ResourcePath Path { get; } = default!;
public ResPath Path { get; } = default!;
}

View File

@@ -23,11 +23,11 @@ public sealed class UITheme : IPrototype
public string ID { get; } = default!;
[DataField("path")]
private ResourcePath? _path;
private ResPath _path;
[DataField("colors", readOnly: true)]
public Dictionary<string, Color>? Colors { get; }
public ResourcePath Path => _path == null ? new ResourcePath(DefaultPath+"/"+ID) : _path;
public ResPath Path => _path == default ? new ResPath(DefaultPath+"/"+ID) : _path;
private void ValidateFilePath(IResourceCache resourceCache)
{
@@ -41,7 +41,7 @@ public sealed class UITheme : IPrototype
}
public Texture ResolveTexture(IResourceCache cache, string texturePath)
{
return cache.TryGetResource<TextureResource>( new ResourcePath($"{Path}/{texturePath}.png"), out var texture) ? texture :
return cache.TryGetResource<TextureResource>( new ResPath($"{Path}/{texturePath}.png"), out var texture) ? texture :
cache.GetResource<TextureResource>($"{DefaultPath}/{DefaultName}/{texturePath}.png");
}

View File

@@ -192,7 +192,7 @@ namespace Robust.Server.GameObjects
return Layers.Count - 1;
}
public int AddLayerWithTexture(ResourcePath texture)
public int AddLayerWithTexture(ResPath texture)
{
return AddLayerWithTexture(texture.ToString());
}
@@ -216,7 +216,7 @@ namespace Robust.Server.GameObjects
return Layers.Count - 1;
}
public int AddLayerWithState(string stateId, ResourcePath rsiPath)
public int AddLayerWithState(string stateId, ResPath rsiPath)
{
return AddLayerWithState(stateId, rsiPath.ToString());
}
@@ -296,7 +296,7 @@ namespace Robust.Server.GameObjects
Dirty();
}
public void LayerSetTexture(int layer, ResourcePath texturePath)
public void LayerSetTexture(int layer, ResPath texturePath)
{
LayerSetTexture(layer, texturePath.ToString());
}
@@ -335,7 +335,7 @@ namespace Robust.Server.GameObjects
Dirty();
}
public void LayerSetState(int layer, string stateId, ResourcePath rsiPath)
public void LayerSetState(int layer, string stateId, ResPath rsiPath)
{
LayerSetState(layer, stateId, rsiPath.ToString());
}
@@ -355,7 +355,7 @@ namespace Robust.Server.GameObjects
Dirty();
}
public void LayerSetRSI(int layer, ResourcePath rsiPath)
public void LayerSetRSI(int layer, ResPath rsiPath)
{
LayerSetRSI(layer, rsiPath.ToString());
}

View File

@@ -129,7 +129,7 @@ public sealed class MapLoaderSystem : EntitySystem
{
options ??= DefaultLoadOptions;
var resPath = new ResourcePath(path).ToRootedPath();
var resPath = new ResPath(path).ToRootedPath();
if (!TryGetReader(resPath, out var reader))
{
@@ -199,7 +199,7 @@ public sealed class MapLoaderSystem : EntitySystem
var document = new YamlDocument(GetSaveData(uid).ToYaml());
var resPath = new ResourcePath(ymlPath).ToRootedPath();
var resPath = new ResPath(ymlPath).ToRootedPath();
_resourceManager.UserData.CreateDir(resPath.Directory);
using var writer = _resourceManager.UserData.OpenWriteText(resPath);
@@ -226,7 +226,7 @@ public sealed class MapLoaderSystem : EntitySystem
#region Loading
private bool TryGetReader(ResourcePath resPath, [NotNullWhen(true)] out TextReader? reader)
private bool TryGetReader(ResPath resPath, [NotNullWhen(true)] out TextReader? reader)
{
// try user
if (!_resourceManager.UserData.Exists(resPath))

View File

@@ -42,7 +42,7 @@ internal sealed class ReplayRecordingManager : IInternalReplayRecordingManager
private int _maxUncompressedSize;
private int _tickBatchSize;
private bool _enabled;
private ResourcePath? _path;
private ResPath _path;
public bool Recording => _curStream != null;
private int _index = 0;
private MemoryStream? _curStream;
@@ -106,7 +106,7 @@ internal sealed class ReplayRecordingManager : IInternalReplayRecordingManager
return false;
var path = directory ?? _netConf.GetCVar(CVars.ReplayDirectory);
_path = new ResourcePath(path).ToRootedPath();
_path = new ResPath(path).ToRootedPath();
if (_resourceManager.UserData.Exists(_path))
{
if (overwrite)

View File

@@ -33,7 +33,7 @@ public sealed class ServerSpriteSpecifierSerializer : SpriteSpecifierSerializer
return new ErrorNode(node, "Sprite specifier has missing/invalid state node");
}
var path = serializationManager.ValidateNode<ResourcePath>(
var path = serializationManager.ValidateNode<ResPath>(
new ValueDataNode($"{SharedSpriteComponent.TextureRoot / valuePathNode.Value}"), context);
if (path is ErrorNode) return path;
@@ -43,7 +43,7 @@ public sealed class ServerSpriteSpecifierSerializer : SpriteSpecifierSerializer
// the state exists. So lets just check if the state .png exists, without properly validating the RSI's
// meta.json
var statePath = serializationManager.ValidateNode<ResourcePath>(
var statePath = serializationManager.ValidateNode<ResPath>(
new ValueDataNode($"{SharedSpriteComponent.TextureRoot / valuePathNode.Value / valueStateNode.Value}.png"),
context);

View File

@@ -29,12 +29,12 @@ namespace Robust.Server
/// <summary>
/// Directory to load all assemblies from.
/// </summary>
public ResourcePath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
public ResPath AssemblyDirectory { get; init; } = new(@"/Assemblies/");
/// <summary>
/// Directory to load all prototypes from.
/// </summary>
public ResourcePath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
public ResPath PrototypeDirectory { get; init; } = new(@"/Prototypes/");
/// <summary>
/// Whether to disable mounting the "Resources/" folder on FULL_RELEASE.

View File

@@ -14,5 +14,5 @@ public sealed class SoundCollectionPrototype : IPrototype
public string ID { get; } = default!;
[DataField("files")]
public List<ResourcePath> PickFiles { get; } = new();
public List<ResPath> PickFiles { get; } = new();
}

View File

@@ -27,19 +27,19 @@ public sealed class SoundPathSpecifier : SoundSpecifier
{
public const string Node = "path";
[DataField(Node, customTypeSerializer: typeof(ResourcePathSerializer), required: true)]
public ResourcePath? Path { get; }
[DataField(Node, customTypeSerializer: typeof(ResPathSerializer), required: true)]
public ResPath Path { get; }
[UsedImplicitly]
public SoundPathSpecifier()
{
}
public SoundPathSpecifier(string path, AudioParams? @params = null) : this(new ResourcePath(path), @params)
public SoundPathSpecifier(string path, AudioParams? @params = null) : this(new ResPath(path), @params)
{
}
public SoundPathSpecifier(ResourcePath path, AudioParams? @params = null)
public SoundPathSpecifier(ResPath path, AudioParams? @params = null)
{
Path = path;
if (@params.HasValue)

View File

@@ -60,7 +60,7 @@ public sealed class SoundSpecifierTypeSerializer :
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies, ISerializationContext? context = null)
{
if (serializationManager.ValidateNode<ResourcePath>(node, context) is not ErrorNode)
if (serializationManager.ValidateNode<ResPath>(node, context) is not ErrorNode)
return new ValidatedValueNode(node);
return new ErrorNode(node, "SoundSpecifier value is not a valid resource path!");

View File

@@ -24,7 +24,7 @@ namespace Robust.Shared.Console.Commands
return;
}
var path = new ResourcePath(args[0]).ToRootedPath();
var path = new ResPath(args[0]).ToRootedPath();
if (!_resources.UserData.Exists(path))
{
shell.WriteError("File does not exist.");

View File

@@ -31,10 +31,12 @@ public static class CompletionHelper
if (!curPath.StartsWith("/"))
curPath = "/";
var resPath = new ResourcePath(curPath);
var resPath = new ResPath(curPath);
if (!curPath.EndsWith("/"))
resPath = (resPath / "..").Clean();
if (!curPath.EndsWith("/")){
resPath /= "..";
resPath = resPath.Clean();
}
var options = res.ContentGetDirectoryEntries(resPath)
.OrderBy(c => c)
@@ -57,13 +59,16 @@ public static class CompletionHelper
if (curPath == "")
curPath = "/";
var resPath = new ResourcePath(curPath);
var resPath = new ResPath(curPath);
if (!resPath.IsRooted)
return Enumerable.Empty<CompletionOption>();
if (!curPath.EndsWith("/"))
resPath = (resPath / "..").Clean();
{
resPath /= "..";
resPath = resPath.Clean();
}
var entries = provider.DirectoryEntries(resPath);

View File

@@ -89,7 +89,7 @@ namespace Robust.Shared.ContentPack
return new Resolver(
this,
loadDirs.ToArray(),
new[] {new ResourcePath("/Assemblies/")}
new[] {new ResPath("/Assemblies/")}
);
}
@@ -861,9 +861,9 @@ namespace Robust.Shared.ContentPack
private readonly ConcurrentDictionary<string, PEReader?> _dictionary = new();
private readonly AssemblyTypeChecker _parent;
private readonly string[] _diskLoadPaths;
private readonly ResourcePath[] _resLoadPaths;
private readonly ResPath[] _resLoadPaths;
public Resolver(AssemblyTypeChecker parent, string[] diskLoadPaths, ResourcePath[] resLoadPaths)
public Resolver(AssemblyTypeChecker parent, string[] diskLoadPaths, ResPath[] resLoadPaths)
{
_parent = parent;
_diskLoadPaths = diskLoadPaths;

View File

@@ -43,7 +43,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
public bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream)
{
var path = GetPath(relPath);
if (!File.Exists(path))
@@ -58,13 +58,13 @@ namespace Robust.Shared.ContentPack
return true;
}
internal string GetPath(ResourcePath relPath)
internal string GetPath(ResPath relPath)
{
return Path.GetFullPath(Path.Combine(_directory.FullName, relPath.ToRelativeSystemPath()));
}
/// <inheritdoc />
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
public IEnumerable<ResPath> FindFiles(ResPath path)
{
var fullPath = GetPath(path);
if (!Directory.Exists(fullPath))
@@ -78,11 +78,11 @@ namespace Robust.Shared.ContentPack
foreach (var filePath in paths)
{
var relPath = filePath.Substring(_directory.FullName.Length);
yield return ResourcePath.FromRelativeSystemPath(relPath);
yield return ResPath.FromRelativeSystemPath(relPath);
}
}
public IEnumerable<string> GetEntries(ResourcePath path)
public IEnumerable<string> GetEntries(ResPath path)
{
var fullPath = GetPath(path);
if (!Directory.Exists(fullPath))
@@ -100,7 +100,7 @@ namespace Robust.Shared.ContentPack
}
[Conditional("DEBUG")]
private void CheckPathCasing(ResourcePath path)
private void CheckPathCasing(ResPath path)
{
if (!_checkCasing)
return;
@@ -108,10 +108,10 @@ namespace Robust.Shared.ContentPack
// Run this inside the thread pool due to overhead.
Task.Run(() =>
{
var prevPath = GetPath(ResourcePath.Root);
var diskPath = ResourcePath.Root;
var prevPath = GetPath(ResPath.Root);
var diskPath = ResPath.Root;
var mismatch = false;
foreach (var segment in path.EnumerateSegments())
foreach (var segment in path.CanonPath.Split('/'))
{
var prevDir = new DirectoryInfo(prevPath);
var found = false;
@@ -166,7 +166,7 @@ namespace Robust.Shared.ContentPack
var filePath = file.FullName;
var relPath = filePath.Substring(_directory.FullName.Length);
yield return ResourcePath.FromRelativeSystemPath(relPath).ToRootedPath().ToString();
yield return ResPath.FromRelativeSystemPath(relPath).ToRootedPath().ToString();
}
foreach (var subDir in dir.EnumerateDirectories())

View File

@@ -23,14 +23,14 @@ namespace Robust.Shared.ContentPack
/// <param name="relPath">Relative path from the root directory.</param>
/// <param name="stream"></param>
/// <returns>A stream of the file loaded into memory.</returns>
bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream);
bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream);
/// <summary>
/// Recursively finds all files in a directory and all sub directories.
/// </summary>
/// <param name="path">Directory to search inside of.</param>
/// <returns>Enumeration of all relative file paths of the files found.</returns>
IEnumerable<ResourcePath> FindFiles(ResourcePath path);
IEnumerable<ResPath> FindFiles(ResPath path);
/// <summary>
/// Recursively returns relative paths to resource files.
@@ -38,14 +38,15 @@ namespace Robust.Shared.ContentPack
/// <returns>Enumeration of all relative file paths.</returns>
IEnumerable<string> GetRelativeFilePaths();
IEnumerable<string> GetEntries(ResourcePath path)
IEnumerable<string> GetEntries(ResPath path)
{
var countDirs = path == ResourcePath.Self ? 0 : path.EnumerateSegments().Count();
var countDirs = path == ResPath.Self ? 0 : path.CanonPath.Split('/').Count();
var options = FindFiles(path).Select(c =>
{
var segCount = c.EnumerateSegments().Count();
var newPath = c.EnumerateSegments().Skip(countDirs).First();
var segment = path.CanonPath.Split('/');
var segCount = segment.Count();
var newPath = segment.Skip(countDirs).First();
if (segCount > countDirs + 1)
newPath += "/";

View File

@@ -37,7 +37,7 @@ namespace Robust.Shared.ContentPack
/// <param name="mountPath">The directory in which to look for assemblies.</param>
/// <param name="filterPrefix">The prefix files need to have to be considered. e.g. <c>Content.</c></param>
/// <returns>True if all modules loaded successfully. False if there were load errors.</returns>
bool TryLoadModulesFrom(ResourcePath mountPath, string filterPrefix);
bool TryLoadModulesFrom(ResPath mountPath, string filterPrefix);
/// <summary>
/// Loads an assembly into the current AppDomain.

View File

@@ -23,7 +23,7 @@ namespace Robust.Shared.ContentPack
/// </summary>
/// <param name="prefix"></param>
/// <param name="loader"></param>
void AddRoot(ResourcePath prefix, IContentRoot loader);
void AddRoot(ResPath prefix, IContentRoot loader);
/// <summary>
/// Read a file from the mounted content roots.
@@ -34,7 +34,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
/// <seealso cref="ResourceManagerExt.ContentFileReadOrNull"/>
Stream ContentFileRead(ResourcePath path);
Stream ContentFileRead(ResPath path);
/// <summary>
/// Read a file from the mounted content roots.
@@ -53,7 +53,7 @@ namespace Robust.Shared.ContentPack
/// <returns>True if the file exists, false otherwise.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
bool ContentFileExists(ResourcePath path);
bool ContentFileExists(ResPath path);
/// <summary>
/// Check if a file exists in any of the mounted content roots.
@@ -73,7 +73,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
/// <seealso cref="ResourceManagerExt.ContentFileReadOrNull"/>
bool TryContentFileRead(ResourcePath path, [NotNullWhen(true)] out Stream? fileStream);
bool TryContentFileRead(ResPath? path, [NotNullWhen(true)] out Stream? fileStream);
/// <summary>
/// Try to read a file from the mounted content roots.
@@ -95,9 +95,9 @@ namespace Robust.Shared.ContentPack
/// <returns>Enumeration of all absolute file paths of the files found.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
IEnumerable<ResourcePath> ContentFindFiles(ResourcePath path);
IEnumerable<ResPath> ContentFindFiles(ResPath? path);
IEnumerable<ResourcePath> ContentFindRelativeFiles(ResourcePath path)
IEnumerable<ResPath> ContentFindRelativeFiles(ResPath path)
{
foreach (var absPath in ContentFindFiles(path))
{
@@ -107,7 +107,7 @@ namespace Robust.Shared.ContentPack
throw new InvalidOperationException("This is unreachable");
}
yield return rel;
yield return rel.Value;
}
}
@@ -121,7 +121,7 @@ namespace Robust.Shared.ContentPack
/// <returns>Enumeration of all absolute file paths of the files found.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
IEnumerable<ResourcePath> ContentFindFiles(string path);
IEnumerable<ResPath> ContentFindFiles(string path);
/// <summary>
/// Gets entries in a content directory.
@@ -133,13 +133,13 @@ namespace Robust.Shared.ContentPack
/// </remarks>
/// <param name="path"></param>
/// <returns>A sequence of entry names. If the entry name ends in a slash, it's a directory.</returns>
IEnumerable<string> ContentGetDirectoryEntries(ResourcePath path);
IEnumerable<string> ContentGetDirectoryEntries(ResPath path);
/// <summary>
/// Returns a list of paths to all top-level content directories
/// </summary>
/// <returns></returns>
IEnumerable<ResourcePath> GetContentRoots();
IEnumerable<ResPath> GetContentRoots();
/// <summary>
/// Read a file from the mounted content paths to a string.
@@ -147,14 +147,14 @@ namespace Robust.Shared.ContentPack
/// <param name="path">Path of the file to read.</param>
string ContentFileReadAllText(string path)
{
return ContentFileReadAllText(new ResourcePath(path));
return ContentFileReadAllText(new ResPath(path));
}
/// <summary>
/// Read a file from the mounted content paths to a string.
/// </summary>
/// <param name="path">Path of the file to read.</param>
string ContentFileReadAllText(ResourcePath path)
string ContentFileReadAllText(ResPath path)
{
return ContentFileReadAllText(path, EncodingHelpers.UTF8);
}
@@ -164,7 +164,7 @@ namespace Robust.Shared.ContentPack
/// </summary>
/// <param name="path">Path of the file to read.</param>
/// <param name="encoding">Text encoding to use when reading.</param>
string ContentFileReadAllText(ResourcePath path, Encoding encoding)
string ContentFileReadAllText(ResPath path, Encoding encoding)
{
using var stream = ContentFileRead(path);
using var reader = new StreamReader(stream, encoding);
@@ -172,7 +172,7 @@ namespace Robust.Shared.ContentPack
return reader.ReadToEnd();
}
public YamlStream ContentFileReadYaml(ResourcePath path)
public YamlStream ContentFileReadYaml(ResPath path)
{
using var reader = ContentFileReadText(path);
@@ -182,12 +182,12 @@ namespace Robust.Shared.ContentPack
return yamlStream;
}
public StreamReader ContentFileReadText(ResourcePath path)
public StreamReader ContentFileReadText(ResPath path)
{
return ContentFileReadText(path, EncodingHelpers.UTF8);
}
public StreamReader ContentFileReadText(ResourcePath path, Encoding encoding)
public StreamReader ContentFileReadText(ResPath path, Encoding encoding)
{
var stream = ContentFileRead(path);
return new StreamReader(stream, encoding);

View File

@@ -21,7 +21,7 @@ namespace Robust.Shared.ContentPack
/// </summary>
/// <param name="stream">The stream to mount.</param>
/// <param name="path">The path that the file will be mounted at.</param>
void MountStreamAt(MemoryStream stream, ResourcePath path);
void MountStreamAt(MemoryStream stream, ResPath path);
/// <summary>
/// Loads the default content pack from the configuration file into the VFS.
@@ -37,9 +37,9 @@ namespace Robust.Shared.ContentPack
/// <exception cref="FileNotFoundException">Thrown if <paramref name="pack"/> does not exist on disk.</exception>
/// <exception cref="ArgumentException">Thrown if <paramref name="prefix"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="pack"/> is null.</exception>
void MountContentPack(string pack, ResourcePath? prefix = null);
void MountContentPack(string pack, ResPath? prefix = null);
void MountContentPack(Stream zipStream, ResourcePath? prefix = null);
void MountContentPack(Stream zipStream, ResPath? prefix = null);
/// <summary>
/// Adds a directory to search inside of to the VFS. The directory is relative to
@@ -50,7 +50,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="DirectoryNotFoundException">Thrown if <paramref name="path"/> does not exist on disk.</exception>
/// <exception cref="ArgumentException">Thrown if <paramref name="prefix"/> passed is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
void MountContentDirectory(string path, ResourcePath? prefix = null);
void MountContentDirectory(string path, ResPath? prefix = null);
/// <summary>
/// Attempts to get an on-disk path absolute file path for the specified resource path.
@@ -64,6 +64,6 @@ namespace Robust.Shared.ContentPack
/// This can be used for optimizations such as assembly loading, where an on-disk path is better.
/// </para>
/// </remarks>
bool TryGetDiskFilePath(ResourcePath path, [NotNullWhen(true)] out string? diskPath);
bool TryGetDiskFilePath(ResPath path, [NotNullWhen(true)] out string? diskPath);
}
}

View File

@@ -21,21 +21,21 @@ namespace Robust.Shared.ContentPack
/// Creates a directory. If the directory exists, does nothing.
/// </summary>
/// <param name="path">Path of directory to create.</param>
void CreateDir(ResourcePath path);
void CreateDir(ResPath path);
/// <summary>
/// Deletes a file or directory. If the file or directory
/// does not exist, does nothing.
/// </summary>
/// <param name="path">Path of object to delete.</param>
void Delete(ResourcePath path);
void Delete(ResPath path);
/// <summary>
/// Tests if a file or directory exists.
/// </summary>
/// <param name="path">Path to test.</param>
/// <returns>If the object exists.</returns>
bool Exists(ResourcePath path);
bool Exists(ResPath path);
/// <summary>
/// Finds all files and directories that match the expression. This will include empty directories.
@@ -43,17 +43,17 @@ namespace Robust.Shared.ContentPack
/// <param name="pattern"></param>
/// <param name="recursive"></param>
/// <returns>A tuple that contains collections of files, directories that matched the expression.</returns>
(IEnumerable<ResourcePath> files, IEnumerable<ResourcePath> directories) Find(string pattern,
(IEnumerable<ResPath> files, IEnumerable<ResPath> directories) Find(string pattern,
bool recursive = true);
IEnumerable<string> DirectoryEntries(ResourcePath path);
IEnumerable<string> DirectoryEntries(ResPath path);
/// <summary>
/// Tests if a path is a directory.
/// </summary>
/// <param name="path">Path to test.</param>
/// <returns>True if it is a directory, false if it is a file.</returns>
bool IsDir(ResourcePath path);
bool IsDir(ResPath path);
/// <summary>
/// Attempts to open a file.
@@ -66,7 +66,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="FileNotFoundException">
/// Thrown if the file does not exist.
/// </exception>
Stream Open(ResourcePath path, FileMode fileMode, FileAccess access, FileShare share);
Stream Open(ResPath path, FileMode fileMode, FileAccess access, FileShare share);
/// <summary>
/// Attempts to open a file.
@@ -77,7 +77,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="FileNotFoundException">
/// Thrown if the file does not exist.
/// </exception>
Stream Open(ResourcePath path, FileMode fileMode)
Stream Open(ResPath path, FileMode fileMode)
{
return Open(path,
fileMode,
@@ -89,7 +89,7 @@ namespace Robust.Shared.ContentPack
/// Returns a new <see cref="IWritableDirProvider"/> that points to a subdirectory.
/// </summary>
/// <param name="path">Path of directory to open.</param>
IWritableDirProvider OpenSubdirectory(ResourcePath path);
IWritableDirProvider OpenSubdirectory(ResPath path);
/// <summary>
/// Attempts to rename a file.
@@ -97,6 +97,6 @@ namespace Robust.Shared.ContentPack
/// <param name="oldPath">Path of the file to rename.</param>
/// <param name="newPath">New name of the file.</param>
/// <returns></returns>
void Rename(ResourcePath oldPath, ResourcePath newPath);
void Rename(ResPath oldPath, ResPath newPath);
}
}

View File

@@ -12,7 +12,7 @@ namespace Robust.Shared.ContentPack;
/// </summary>
public sealed class MemoryContentRoot : IContentRoot, IDisposable
{
private readonly Dictionary<ResourcePath, byte[]> _files = new();
private readonly Dictionary<ResPath, byte[]> _files = new();
private readonly ReaderWriterLockSlim _lock = new();
@@ -21,7 +21,7 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable
/// </summary>
/// <param name="relPath">The relative path of the file.</param>
/// <param name="data">The data byte array to store in the content root. Stored as is, without being copied or cloned.</param>
public void AddOrUpdateFile(ResourcePath relPath, byte[] data)
public void AddOrUpdateFile(ResPath relPath, byte[] data)
{
// Just in case, we ensure it's a clean relative path.
relPath = relPath.Clean().ToRelativePath();
@@ -42,7 +42,7 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable
/// </summary>
/// <param name="relPath">The relative path to the file.</param>
/// <returns></returns>
public bool RemoveFile(ResourcePath relPath)
public bool RemoveFile(ResPath relPath)
{
_lock.EnterWriteLock();
try
@@ -56,7 +56,7 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable
}
/// <inheritdoc />
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
public bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream)
{
_lock.EnterReadLock();
try
@@ -78,7 +78,7 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable
}
/// <inheritdoc />
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
public IEnumerable<ResPath> FindFiles(ResPath path)
{
_lock.EnterReadLock();
try
@@ -116,7 +116,7 @@ public sealed class MemoryContentRoot : IContentRoot, IDisposable
/// Enumerates all files and their resource paths on this content root.
/// </summary>
/// <remarks>Do not modify or keep around the returned byte array, it's meant to be read-only.</remarks>
public IEnumerable<(ResourcePath relPath, byte[] data)> GetAllFiles()
public IEnumerable<(ResPath relPath, byte[] data)> GetAllFiles()
{
_lock.EnterReadLock();
try

View File

@@ -74,11 +74,11 @@ namespace Robust.Shared.ContentPack
_engineModuleDirectories.Add(dir);
}
public bool TryLoadModulesFrom(ResourcePath mountPath, string filterPrefix)
public bool TryLoadModulesFrom(ResPath mountPath, string filterPrefix)
{
var sw = Stopwatch.StartNew();
Logger.DebugS("res.mod", "LOADING modules");
var files = new Dictionary<string, (ResourcePath Path, string[] references)>();
var files = new Dictionary<string, (ResPath Path, string[] references)>();
// Find all modules we want to load.
foreach (var filePath in _res.ContentFindRelativeFiles(mountPath)
@@ -246,7 +246,7 @@ namespace Robust.Shared.ContentPack
public bool TryLoadAssembly(string assemblyName)
{
var dllPath = new ResourcePath($@"/Assemblies/{assemblyName}.dll");
var dllPath = new ResPath($@"/Assemblies/{assemblyName}.dll");
// To prevent breaking debugging on Rider, try to load from disk if possible.
if (_res.TryGetDiskFilePath(dllPath, out var path))
{
@@ -270,7 +270,7 @@ namespace Robust.Shared.ContentPack
Logger.DebugS("srv", $"Loading {assemblyName} DLL");
// see if debug info is present
if (_res.TryContentFileRead(new ResourcePath($@"/Assemblies/{assemblyName}.pdb"),
if (_res.TryContentFileRead(new ResPath($@"/Assemblies/{assemblyName}.pdb"),
out var gamePdb))
{
using (gamePdb)

View File

@@ -51,7 +51,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
public bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream)
{
var entry = _zip.GetEntry(relPath.ToString());
@@ -76,7 +76,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
public IEnumerable<ResPath> FindFiles(ResPath path)
{
var rootPath = path + "/";
foreach (var entry in _zip.Entries)
@@ -89,7 +89,7 @@ namespace Robust.Shared.ContentPack
if (entry.FullName.StartsWith(rootPath))
{
yield return new ResourcePath(entry.FullName).ToRelativePath();
yield return new ResPath(entry.FullName).ToRelativePath();
}
}
}
@@ -104,7 +104,7 @@ namespace Robust.Shared.ContentPack
continue;
}
yield return new ResourcePath(entry.FullName).ToRootedPath().ToString();
yield return new ResPath(entry.FullName).ToRootedPath().ToString();
}
}
}

View File

@@ -10,9 +10,9 @@ namespace Robust.Shared.ContentPack
private sealed class SingleStreamLoader : IContentRoot
{
private readonly MemoryStream _stream;
private readonly ResourcePath _resourcePath;
private readonly ResPath _resourcePath;
public SingleStreamLoader(MemoryStream stream, ResourcePath resourcePath)
public SingleStreamLoader(MemoryStream stream, ResPath resourcePath)
{
_stream = stream;
_resourcePath = resourcePath;
@@ -23,7 +23,7 @@ namespace Robust.Shared.ContentPack
// Nothing to do here I'm pretty sure.
}
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
public bool TryGetFile(ResPath relPath, [NotNullWhen(true)] out Stream? stream)
{
if (relPath == _resourcePath)
{
@@ -40,7 +40,7 @@ namespace Robust.Shared.ContentPack
return false;
}
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
public IEnumerable<ResPath> FindFiles(ResPath path)
{
if (_resourcePath.TryRelativeTo(path, out var relative))
{

View File

@@ -18,8 +18,8 @@ namespace Robust.Shared.ContentPack
{
[Dependency] private readonly IConfigurationManager _config = default!;
private (ResourcePath prefix, IContentRoot root)[] _contentRoots =
new (ResourcePath prefix, IContentRoot root)[0];
private (ResPath prefix, IContentRoot root)[] _contentRoots =
new (ResPath prefix, IContentRoot root)[0];
private StreamSeekMode _streamSeekMode;
private readonly object _rootMutateLock = new();
@@ -68,7 +68,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public void MountContentPack(string pack, ResourcePath? prefix = null)
public void MountContentPack(string pack, ResPath? prefix = null)
{
prefix = SanitizePrefix(prefix);
@@ -85,18 +85,18 @@ namespace Robust.Shared.ContentPack
//create new PackLoader
var loader = new PackLoader(packInfo);
AddRoot(prefix, loader);
AddRoot(prefix.Value, loader);
}
public void MountContentPack(Stream zipStream, ResourcePath? prefix = null)
public void MountContentPack(Stream zipStream, ResPath? prefix = null)
{
prefix = SanitizePrefix(prefix);
var loader = new PackLoader(zipStream);
AddRoot(prefix, loader);
AddRoot(prefix.Value, loader);
}
public void AddRoot(ResourcePath prefix, IContentRoot loader)
public void AddRoot(ResPath prefix, IContentRoot loader)
{
lock (_rootMutateLock)
{
@@ -112,22 +112,22 @@ namespace Robust.Shared.ContentPack
}
}
private static ResourcePath SanitizePrefix(ResourcePath? prefix)
private static ResPath SanitizePrefix(ResPath? prefix)
{
if (prefix == null)
{
prefix = ResourcePath.Root;
prefix = ResPath.Root;
}
else if (!prefix.IsRooted)
else if (!prefix.Value.IsRooted)
{
throw new ArgumentException("Prefix must be rooted.", nameof(prefix));
}
return prefix;
return prefix.Value;
}
/// <inheritdoc />
public void MountContentDirectory(string path, ResourcePath? prefix = null)
public void MountContentDirectory(string path, ResPath? prefix = null)
{
prefix = SanitizePrefix(prefix);
@@ -141,17 +141,17 @@ namespace Robust.Shared.ContentPack
}
var loader = new DirLoader(pathInfo, Logger.GetSawmill("res"), _config.GetCVar(CVars.ResCheckPathCasing));
AddRoot(prefix, loader);
AddRoot(prefix.Value, loader);
}
/// <inheritdoc />
public Stream ContentFileRead(string path)
{
return ContentFileRead(new ResourcePath(path));
return ContentFileRead(new ResPath(path));
}
/// <inheritdoc />
public Stream ContentFileRead(ResourcePath path)
public Stream ContentFileRead(ResPath path)
{
if (TryContentFileRead(path, out var fileStream))
{
@@ -164,35 +164,35 @@ namespace Robust.Shared.ContentPack
/// <inheritdoc />
public bool TryContentFileRead(string path, [NotNullWhen(true)] out Stream? fileStream)
{
return TryContentFileRead(new ResourcePath(path), out fileStream);
return TryContentFileRead(new ResPath(path), out fileStream);
}
/// <inheritdoc />
public bool TryContentFileRead(ResourcePath path, [NotNullWhen(true)] out Stream? fileStream)
public bool TryContentFileRead(ResPath? path, [NotNullWhen(true)] out Stream? fileStream)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (!path.IsRooted)
if (!path.Value.IsRooted)
{
throw new ArgumentException($"Path '{path}' must be rooted", nameof(path));
}
#if DEBUG
if (!IsPathValid(path))
if (!IsPathValid(path.Value))
{
throw new FileNotFoundException($"Path '{path}' contains invalid characters/filenames.");
}
#endif
foreach (var (prefix, root) in _contentRoots)
{
if (!path.TryRelativeTo(prefix, out var relative))
if (!path.Value.TryRelativeTo(prefix, out var relative))
{
continue;
}
if (root.TryGetFile(relative, out var stream))
if (root.TryGetFile(relative.Value, out var stream))
{
fileStream = WrapStream(stream);
return true;
@@ -235,11 +235,11 @@ namespace Robust.Shared.ContentPack
/// <inheritdoc />
public bool ContentFileExists(string path)
{
return ContentFileExists(new ResourcePath(path));
return ContentFileExists(new ResPath(path));
}
/// <inheritdoc />
public bool ContentFileExists(ResourcePath path)
public bool ContentFileExists(ResPath path)
{
if (TryContentFileRead(path, out var stream))
{
@@ -251,12 +251,12 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public IEnumerable<ResourcePath> ContentFindFiles(string path)
public IEnumerable<ResPath> ContentFindFiles(string path)
{
return ContentFindFiles(new ResourcePath(path));
return ContentFindFiles(new ResPath(path));
}
public IEnumerable<string> ContentGetDirectoryEntries(ResourcePath path)
public IEnumerable<string> ContentGetDirectoryEntries(ResPath path)
{
ArgumentNullException.ThrowIfNull(path, nameof(path));
@@ -272,35 +272,35 @@ namespace Robust.Shared.ContentPack
continue;
}
entries.UnionWith(root.GetEntries(relative));
entries.UnionWith(root.GetEntries(relative.Value));
}
return entries;
}
/// <inheritdoc />
public IEnumerable<ResourcePath> ContentFindFiles(ResourcePath path)
public IEnumerable<ResPath> ContentFindFiles(ResPath? path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (!path.IsRooted)
if (!path.Value.IsRooted)
{
throw new ArgumentException("Path is not rooted", nameof(path));
}
var alreadyReturnedFiles = new HashSet<ResourcePath>();
var alreadyReturnedFiles = new HashSet<ResPath>();
foreach (var (prefix, root) in _contentRoots)
{
if (!path.TryRelativeTo(prefix, out var relative))
if (!path.Value.TryRelativeTo(prefix, out var relative))
{
continue;
}
foreach (var filename in root.FindFiles(relative))
foreach (var filename in root.FindFiles(relative.Value))
{
var newPath = prefix / filename;
if (!alreadyReturnedFiles.Contains(newPath))
@@ -312,7 +312,7 @@ namespace Robust.Shared.ContentPack
}
}
public bool TryGetDiskFilePath(ResourcePath path, [NotNullWhen(true)] out string? diskPath)
public bool TryGetDiskFilePath(ResPath path, [NotNullWhen(true)] out string? diskPath)
{
// loop over each root trying to get the file
foreach (var (prefix, root) in _contentRoots)
@@ -322,7 +322,7 @@ namespace Robust.Shared.ContentPack
continue;
}
diskPath = dirLoader.GetPath(tempPath);
diskPath = dirLoader.GetPath(tempPath.Value);
if (File.Exists(diskPath))
return true;
}
@@ -331,24 +331,24 @@ namespace Robust.Shared.ContentPack
return false;
}
public void MountStreamAt(MemoryStream stream, ResourcePath path)
public void MountStreamAt(MemoryStream stream, ResPath path)
{
var loader = new SingleStreamLoader(stream, path.ToRelativePath());
AddRoot(ResourcePath.Root, loader);
AddRoot(ResPath.Root, loader);
}
public IEnumerable<ResourcePath> GetContentRoots()
public IEnumerable<ResPath> GetContentRoots()
{
foreach (var (_, root) in _contentRoots)
{
if (root is DirLoader loader)
{
yield return new ResourcePath(loader.GetPath(new ResourcePath(@"/")));
yield return new ResPath(loader.GetPath(new ResPath(@"/")));
}
}
}
internal static bool IsPathValid(ResourcePath path)
internal static bool IsPathValid(ResPath path)
{
var asString = path.ToString();
if (BadPathCharacterRegex.IsMatch(asString))
@@ -356,7 +356,7 @@ namespace Robust.Shared.ContentPack
return false;
}
foreach (var segment in path.EnumerateSegments())
foreach (var segment in path.CanonPath.Split('/'))
{
if (BadPathSegmentRegex.IsMatch(segment))
{

View File

@@ -14,9 +14,9 @@ namespace Robust.Shared.ContentPack
/// <returns>The memory stream of the file, or null if the file does not exist.</returns>
/// <exception cref="ArgumentException">Thrown if <paramref name="path"/> is not rooted.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="path"/> is null.</exception>
/// <seealso cref="IResourceManager.ContentFileRead(ResourcePath)"/>
/// <seealso cref="IResourceManager.TryContentFileRead(ResourcePath, out Stream)"/>
public static Stream? ContentFileReadOrNull(this IResourceManager res, ResourcePath path)
/// <seealso cref="IResourceManager.ContentFileRead(ResPath)"/>
/// <seealso cref="IResourceManager.TryContentFileRead(ResPath, out Stream)"/>
public static Stream? ContentFileReadOrNull(this IResourceManager res, ResPath path)
{
if (res.TryContentFileRead(path, out var stream))
{

View File

@@ -29,7 +29,7 @@ namespace Robust.Shared.ContentPack
/// <inheritdoc />
public string? RootDir => null;
public void CreateDir(ResourcePath path)
public void CreateDir(ResPath path)
{
if (!path.IsRooted)
{
@@ -39,6 +39,7 @@ namespace Robust.Shared.ContentPack
path = path.Clean();
var directory = _rootDirectoryNode;
foreach (var segment in path.EnumerateSegments())
{
if (directory.Children.TryGetValue(segment, out var child))
@@ -58,7 +59,7 @@ namespace Robust.Shared.ContentPack
}
}
public void Delete(ResourcePath path)
public void Delete(ResPath path)
{
if (!path.IsRooted)
{
@@ -77,18 +78,18 @@ namespace Robust.Shared.ContentPack
directory.Children.Remove(path.Filename);
}
public bool Exists(ResourcePath path)
public bool Exists(ResPath path)
{
return TryGetNodeAt(path, out _);
}
public (IEnumerable<ResourcePath> files, IEnumerable<ResourcePath> directories) Find(string pattern,
public (IEnumerable<ResPath> files, IEnumerable<ResPath> directories) Find(string pattern,
bool recursive = true)
{
throw new NotImplementedException();
}
public IEnumerable<string> DirectoryEntries(ResourcePath path)
public IEnumerable<string> DirectoryEntries(ResPath path)
{
if (!TryGetNodeAt(path, out var dir) || dir is not DirectoryNode dirNode)
throw new ArgumentException("Path is not a valid directory node.");
@@ -96,20 +97,18 @@ namespace Robust.Shared.ContentPack
return dirNode.Children.Keys;
}
public bool IsDir(ResourcePath path)
public bool IsDir(ResPath path)
{
return TryGetNodeAt(path, out var node) && node is DirectoryNode;
}
public Stream Open(ResourcePath path, FileMode fileMode, FileAccess access, FileShare share)
public Stream Open(ResPath path, FileMode fileMode, FileAccess access, FileShare share)
{
if (!path.IsRooted)
{
throw new ArgumentException("Path must be rooted", nameof(path));
}
path = path.Clean();
var parentPath = path.Directory;
if (!TryGetNodeAt(parentPath, out var parent) || !(parent is DirectoryNode parentDir))
{
@@ -205,12 +204,12 @@ namespace Robust.Shared.ContentPack
}
}
public void Rename(ResourcePath oldPath, ResourcePath newPath)
public void Rename(ResPath oldPath, ResPath newPath)
{
throw new NotImplementedException();
}
private bool TryGetNodeAt(ResourcePath path, [NotNullWhen(true)] out INode? node)
private bool TryGetNodeAt(ResPath path, [NotNullWhen(true)] out INode? node)
{
if (!path.IsRooted)
{
@@ -219,14 +218,14 @@ namespace Robust.Shared.ContentPack
path = path.Clean();
if (path == ResourcePath.Root)
if (path == ResPath.Root)
{
node = _rootDirectoryNode;
return true;
}
var directory = _rootDirectoryNode;
var segments = path.EnumerateSegments().ToArray();
var segments = path.EnumerateSegments();
for (var i = 0; i < segments.Length; i++)
{
var segment = segments[i];
@@ -248,7 +247,7 @@ namespace Robust.Shared.ContentPack
throw new InvalidOperationException("Unreachable.");
}
public IWritableDirProvider OpenSubdirectory(ResourcePath path)
public IWritableDirProvider OpenSubdirectory(ResPath path)
{
if (!TryGetNodeAt(path, out var node) || node is not DirectoryNode dirNode)
throw new FileNotFoundException();

View File

@@ -26,14 +26,14 @@ namespace Robust.Shared.ContentPack
#region File Access
/// <inheritdoc />
public void CreateDir(ResourcePath path)
public void CreateDir(ResPath path)
{
var fullPath = GetFullPath(path);
Directory.CreateDirectory(fullPath);
}
/// <inheritdoc />
public void Delete(ResourcePath path)
public void Delete(ResPath path)
{
var fullPath = GetFullPath(path);
if (Directory.Exists(fullPath))
@@ -47,14 +47,14 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool Exists(ResourcePath path)
public bool Exists(ResPath path)
{
var fullPath = GetFullPath(path);
return Directory.Exists(fullPath) || File.Exists(fullPath);
}
/// <inheritdoc />
public (IEnumerable<ResourcePath> files, IEnumerable<ResourcePath> directories) Find(string pattern, bool recursive = true)
public (IEnumerable<ResPath> files, IEnumerable<ResPath> directories) Find(string pattern, bool recursive = true)
{
var rootLen = RootDir.Length - 1;
var option = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
@@ -62,23 +62,23 @@ namespace Robust.Shared.ContentPack
var files = Directory.GetFiles(RootDir, pattern, option);
var dirs = Directory.GetDirectories(RootDir, pattern, option);
var resFiles = new List<ResourcePath>(files.Length);
var resDirs = new List<ResourcePath>(dirs.Length);
var resFiles = new List<ResPath>(files.Length);
var resDirs = new List<ResPath>(dirs.Length);
foreach (var file in files)
{
resFiles.Add(new ResourcePath(file.Substring(rootLen), ResourcePath.SYSTEM_SEPARATOR).ChangeSeparator("/"));
resFiles.Add(new ResPath(file.Substring(rootLen)));
}
foreach (var dir in dirs)
{
resDirs.Add(new ResourcePath(dir.Substring(rootLen), ResourcePath.SYSTEM_SEPARATOR).ChangeSeparator("/"));
resDirs.Add(new ResPath(dir.Substring(rootLen)));
}
return (resFiles, resDirs);
}
public IEnumerable<string> DirectoryEntries(ResourcePath path)
public IEnumerable<string> DirectoryEntries(ResPath path)
{
var fullPath = GetFullPath(path);
@@ -92,19 +92,19 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public bool IsDir(ResourcePath path)
public bool IsDir(ResPath path)
{
return Directory.Exists(GetFullPath(path));
}
/// <inheritdoc />
public Stream Open(ResourcePath path, FileMode fileMode, FileAccess access, FileShare share)
public Stream Open(ResPath path, FileMode fileMode, FileAccess access, FileShare share)
{
var fullPath = GetFullPath(path);
return File.Open(fullPath, fileMode, access, share);
}
public IWritableDirProvider OpenSubdirectory(ResourcePath path)
public IWritableDirProvider OpenSubdirectory(ResPath path)
{
if (!IsDir(path))
throw new FileNotFoundException();
@@ -114,7 +114,7 @@ namespace Robust.Shared.ContentPack
}
/// <inheritdoc />
public void Rename(ResourcePath oldPath, ResourcePath newPath)
public void Rename(ResPath oldPath, ResPath newPath)
{
var fullOldPath = GetFullPath(oldPath);
var fullNewPath = GetFullPath(newPath);
@@ -123,19 +123,21 @@ namespace Robust.Shared.ContentPack
#endregion
public string GetFullPath(ResourcePath path)
public string GetFullPath(ResPath path)
{
if (!path.IsRooted)
{
throw new ArgumentException("Path must be rooted.");
}
path = path.Clean();
return GetFullPath(RootDir, path);
}
private static string GetFullPath(string root, ResourcePath path)
private static string GetFullPath(string root, ResPath path)
{
var relPath = path.Clean().ToRelativeSystemPath();
var relPath = path.ToRelativeSystemPath();
if (relPath.Contains("\\..") || relPath.Contains("/.."))
{
// Hard cap on any exploit smuggling a .. in there.

View File

@@ -18,7 +18,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="FileNotFoundException">
/// Thrown if the file does not exist.
/// </exception>
public static Stream OpenRead(this IWritableDirProvider provider, ResourcePath path)
public static Stream OpenRead(this IWritableDirProvider provider, ResPath path)
{
return provider.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
}
@@ -32,7 +32,7 @@ namespace Robust.Shared.ContentPack
/// <exception cref="FileNotFoundException">
/// Thrown if the file does not exist.
/// </exception>
public static StreamReader OpenText(this IWritableDirProvider provider, ResourcePath path)
public static StreamReader OpenText(this IWritableDirProvider provider, ResPath path)
{
var stream = OpenRead(provider, path);
return new StreamReader(stream, EncodingHelpers.UTF8);
@@ -44,7 +44,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory provider</param>
/// <param name="path">The path of the file to open.</param>
/// <returns>A valid file stream.</returns>
public static Stream OpenWrite(this IWritableDirProvider provider, ResourcePath path)
public static Stream OpenWrite(this IWritableDirProvider provider, ResPath path)
{
return provider.Open(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
}
@@ -55,7 +55,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory provider</param>
/// <param name="path">The path of the file to open.</param>
/// <returns>A valid file stream writer.</returns>
public static StreamWriter OpenWriteText(this IWritableDirProvider provider, ResourcePath path)
public static StreamWriter OpenWriteText(this IWritableDirProvider provider, ResPath path)
{
var stream = OpenWrite(provider, path);
return new StreamWriter(stream, EncodingHelpers.UTF8);
@@ -68,7 +68,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory provider</param>
/// <param name="path">Path of file to append to.</param>
/// <param name="content">String to append.</param>
public static void AppendAllText(this IWritableDirProvider provider, ResourcePath path, ReadOnlySpan<char> content)
public static void AppendAllText(this IWritableDirProvider provider, ResPath path, ReadOnlySpan<char> content)
{
using var stream = provider.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read);
using var writer = new StreamWriter(stream, EncodingHelpers.UTF8);
@@ -82,7 +82,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider"></param>
/// <param name="path">File to read.</param>
/// <returns>String of the file contents</returns>
public static string ReadAllText(this IWritableDirProvider provider, ResourcePath path)
public static string ReadAllText(this IWritableDirProvider provider, ResPath path)
{
using var reader = provider.OpenText(path);
@@ -96,7 +96,7 @@ namespace Robust.Shared.ContentPack
/// <param name="path">The path to read the contents from.</param>
/// <param name="text">The content read from the path, or null if the path did not exist.</param>
/// <returns>true if path was successfully read; otherwise, false.</returns>
public static bool TryReadAllText(this IWritableDirProvider provider, ResourcePath path, [NotNullWhen(true)] out string? text)
public static bool TryReadAllText(this IWritableDirProvider provider, ResPath path, [NotNullWhen(true)] out string? text)
{
try
{
@@ -116,7 +116,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory to look for the path in.</param>
/// <param name="path">The path to read the contents from.</param>
/// <returns>The contents of the path as a byte array.</returns>
public static byte[] ReadAllBytes(this IWritableDirProvider provider, ResourcePath path)
public static byte[] ReadAllBytes(this IWritableDirProvider provider, ResPath path)
{
using var stream = provider.OpenRead(path);
using var memoryStream = new MemoryStream((int) stream.Length);
@@ -131,7 +131,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory provider</param>
/// <param name="path">Path of the file to write to.</param>
/// <param name="content">String contents of the file.</param>
public static void WriteAllText(this IWritableDirProvider provider, ResourcePath path, ReadOnlySpan<char> content)
public static void WriteAllText(this IWritableDirProvider provider, ResPath path, ReadOnlySpan<char> content)
{
using var writer = provider.OpenWriteText(path);
@@ -145,7 +145,7 @@ namespace Robust.Shared.ContentPack
/// <param name="provider">The writable directory provider</param>
/// <param name="path">Path of the file to write to.</param>
/// <param name="content">Bytes to write to the file.</param>
public static void WriteAllBytes(this IWritableDirProvider provider, ResourcePath path, ReadOnlySpan<byte> content)
public static void WriteAllBytes(this IWritableDirProvider provider, ResPath path, ReadOnlySpan<byte> content)
{
using var stream = provider.OpenWrite(path);

View File

@@ -16,8 +16,7 @@ namespace Robust.Shared.GameObjects
/// <summary>
/// The resource path from which all texture paths are relative to.
/// </summary>
public static readonly ResourcePath TextureRoot = new("/Textures");
public static readonly ResPath TextureRootResPath = new("/Textures");
public static readonly ResPath TextureRoot = new("/Textures");
[Serializable, NetSerializable]
protected sealed class SpriteComponentState : ComponentState

View File

@@ -240,7 +240,7 @@ namespace Robust.Shared.Localization
// Load data from .ftl files.
// Data is loaded from /Locale/<language-code>/*
var root = new ResourcePath($"/Locale/{culture.Name}/");
var root = new ResPath($"/Locale/{culture.Name}/");
var files = resourceManager.ContentFindFiles(root)
.Where(c => c.Filename.EndsWith(".ftl", StringComparison.InvariantCultureIgnoreCase))
@@ -264,7 +264,7 @@ namespace Robust.Shared.Localization
}
}
private void WriteWarningForErrs(ResourcePath path, List<ParseError> errs, ReadOnlyMemory<char> resource)
private void WriteWarningForErrs(ResPath path, List<ParseError> errs, ReadOnlyMemory<char> resource)
{
foreach (var err in errs)
{

View File

@@ -27,12 +27,12 @@ namespace Robust.Shared.Map
/// <summary>
/// The path of the sprite to draw.
/// </summary>
ResourcePath? Sprite { get; }
ResPath? Sprite { get; }
/// <summary>
/// Possible sprites to use if we're neighboring another tile.
/// </summary>
Dictionary<Direction, ResourcePath> EdgeSprites { get; }
Dictionary<Direction, ResPath> EdgeSprites { get; }
/// <summary>
/// Physics objects that are interacting on this tile are slowed down by this float.

View File

@@ -8,16 +8,16 @@ namespace Robust.Shared.Network.Messages
{
public override MsgGroups MsgGroup => MsgGroups.Command;
public ResourcePath[] Paths = default!;
public ResPath[] Paths = default!;
public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer)
{
var count = buffer.ReadInt32();
Paths = new ResourcePath[count];
Paths = new ResPath[count];
for (var i = 0; i < count; i++)
{
Paths[i] = new ResourcePath(buffer.ReadString());
Paths[i] = new ResPath(buffer.ReadString());
}
}

View File

@@ -45,7 +45,7 @@ internal static class ProgramShared
sawmill.Debug($"OS: {RuntimeInformation.OSDescription} {RuntimeInformation.OSArchitecture}");
}
internal static void DoMounts(IResourceManagerInternal res, MountOptions? options, string contentBuildDir, ResourcePath assembliesPath, bool loadContentResources = true,
internal static void DoMounts(IResourceManagerInternal res, MountOptions? options, string contentBuildDir, ResPath assembliesPath, bool loadContentResources = true,
bool loader = false, bool contentStart = false)
{
#if FULL_RELEASE

View File

@@ -196,9 +196,9 @@ public interface IPrototypeManager
/// <summary>
/// Load prototypes from files in a directory, recursively.
/// </summary>
void LoadDirectory(ResourcePath path, bool overwrite = false, Dictionary<Type, HashSet<string>>? changed = null);
void LoadDirectory(ResPath path, bool overwrite = false, Dictionary<Type, HashSet<string>>? changed = null);
Dictionary<string, HashSet<ErrorNode>> ValidateDirectory(ResourcePath path);
Dictionary<string, HashSet<ErrorNode>> ValidateDirectory(ResPath path);
void LoadFromStream(TextReader stream, bool overwrite = false, Dictionary<Type, HashSet<string>>? changed = null);

View File

@@ -19,7 +19,7 @@ public partial class PrototypeManager
public event Action<DataNodeDocument>? LoadedData;
/// <inheritdoc />
public void LoadDirectory(ResourcePath path, bool overwrite = false,
public void LoadDirectory(ResPath path, bool overwrite = false,
Dictionary<Type, HashSet<string>>? changed = null)
{
_hasEverBeenReloaded = true;
@@ -33,7 +33,7 @@ public partial class PrototypeManager
var sawmill = _logManager.GetSawmill("eng");
var results = streams.AsParallel()
.Select<ResourcePath, (ResourcePath, IEnumerable<ExtractedMappingData>)>(file =>
.Select<ResPath, (ResPath, IEnumerable<ExtractedMappingData>)>(file =>
{
try
{
@@ -81,7 +81,7 @@ public partial class PrototypeManager
}
}
public Dictionary<string, HashSet<ErrorNode>> ValidateDirectory(ResourcePath path)
public Dictionary<string, HashSet<ErrorNode>> ValidateDirectory(ResPath path)
{
var streams = Resources.ContentFindFiles(path).ToList().AsParallel()
.Where(filePath => filePath.Extension == "yml" && !filePath.Filename.StartsWith("."));
@@ -130,7 +130,7 @@ public partial class PrototypeManager
return dict;
}
private StreamReader? ReadFile(ResourcePath file, bool @throw = true)
private StreamReader? ReadFile(ResPath file, bool @throw = true)
{
var retries = 0;
@@ -161,7 +161,7 @@ public partial class PrototypeManager
}
}
public void LoadFile(ResourcePath file, bool overwrite = false, Dictionary<Type, HashSet<string>>? changed = null)
public void LoadFile(ResPath file, bool overwrite = false, Dictionary<Type, HashSet<string>>? changed = null)
{
try
{

View File

@@ -192,7 +192,7 @@ namespace Robust.Shared.Prototypes
return _kindPriorities[b].CompareTo(_kindPriorities[a]);
}
protected void ReloadPrototypes(IEnumerable<ResourcePath> filePaths)
protected void ReloadPrototypes(IEnumerable<ResPath> filePaths)
{
#if TOOLS
var changed = new Dictionary<Type, HashSet<string>>();

View File

@@ -28,7 +28,7 @@ public sealed class ResPathSerializer : ITypeSerializer<ResPath, ValueDataNode>,
if (!path.CanonPath.Split('/').First().Equals("Textures", StringComparison.InvariantCultureIgnoreCase))
{
path = SharedSpriteComponent.TextureRootResPath / path;
path = SharedSpriteComponent.TextureRoot / path;
}
path = path.ToRootedPath();
@@ -44,7 +44,7 @@ public sealed class ResPathSerializer : ITypeSerializer<ResPath, ValueDataNode>,
if (node.Value.EndsWith(ResPath.SeparatorStr)
// Once Resource path is purged this will be
// resourceManager.ContentGetDirectoryEntries(path).Any()
&& resourceManager.ContentGetDirectoryEntries(new ResourcePath(path.CanonPath)).Any())
&& resourceManager.ContentGetDirectoryEntries(new ResPath(path.CanonPath)).Any())
{
return new ValidatedValueNode(node);
}

View File

@@ -1,85 +0,0 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.Markdown;
using Robust.Shared.Serialization.Markdown.Validation;
using Robust.Shared.Serialization.Markdown.Value;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
using Robust.Shared.Utility;
namespace Robust.Shared.Serialization.TypeSerializers.Implementations
{
[TypeSerializer]
public sealed class ResourcePathSerializer : ITypeSerializer<ResourcePath, ValueDataNode>, ITypeCopyCreator<ResourcePath>
{
public ResourcePath Read(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies,
SerializationHookContext hookCtx,
ISerializationContext? context = null,
ISerializationManager.InstantiationDelegate<ResourcePath>? instanceProvider = null)
{
return new ResourcePath(node.Value);
}
public ValidationNode Validate(ISerializationManager serializationManager, ValueDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context = null)
{
var path = new ResourcePath(node.Value);
if (path.Extension.Equals("rsi"))
{
path /= "meta.json";
}
if (!path.EnumerateSegments().First().Equals("Textures", StringComparison.InvariantCultureIgnoreCase))
{
path = SharedSpriteComponent.TextureRoot / path;
}
path = path.ToRootedPath();
try
{
var resourceManager = dependencies.Resolve<IResourceManager>();
if(resourceManager.ContentFileExists(path))
{
return new ValidatedValueNode(node);
}
if (node.Value.EndsWith(path.Separator) && resourceManager.ContentGetDirectoryEntries(path).Any())
{
return new ValidatedValueNode(node);
}
return new ErrorNode(node, $"File not found. ({path})");
}
catch (Exception e)
{
return new ErrorNode(node, $"Failed parsing filepath. ({path}) ({e.Message})");
}
}
public DataNode Write(ISerializationManager serializationManager, ResourcePath value,
IDependencyCollection dependencies,
bool alwaysWrite = false,
ISerializationContext? context = null)
{
return new ValueDataNode(value.ToString());
}
[MustUseReturnValue]
public ResourcePath CreateCopy(ISerializationManager serializationManager, ResourcePath source,
SerializationHookContext hookCtx,
ISerializationContext? context = null)
{
return new(source.ToString());
}
}
}

View File

@@ -31,7 +31,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
SerializationHookContext hookCtx, ISerializationContext? context,
ISerializationManager.InstantiationDelegate<Texture>? instanceProvider)
{
var path = serializationManager.Read<ResourcePath>(node, hookCtx, context, notNullableOverride: true);
var path = serializationManager.Read<ResPath>(node, hookCtx, context);
return new Texture(path);
}
@@ -69,7 +69,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
throw new InvalidMappingException("Expected state-node as a valuenode");
}
var path = serializationManager.Read<ResourcePath>(pathNode, hookCtx, context, notNullableOverride: true);
var path = serializationManager.Read<ResPath>(pathNode, hookCtx, context);
return new Rsi(path, valueDataNode.Value);
}
@@ -108,7 +108,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
IDependencyCollection dependencies,
ISerializationContext? context)
{
return serializationManager.ValidateNode<ResourcePath>(new ValueDataNode($"{SharedSpriteComponent.TextureRoot / node.Value}"), context);
return serializationManager.ValidateNode<ResPath>(new ValueDataNode($"{SharedSpriteComponent.TextureRoot / node.Value}"), context);
}
ValidationNode ITypeValidator<SpriteSpecifier, MappingDataNode>.Validate(
@@ -145,7 +145,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
IDependencyCollection dependencies, bool alwaysWrite = false,
ISerializationContext? context = null)
{
return serializationManager.WriteValue(value.TexturePath, alwaysWrite, context, notNullableOverride: true);
return serializationManager.WriteValue(value.TexturePath, alwaysWrite, context);
}
public DataNode Write(ISerializationManager serializationManager, EntityPrototype value,
@@ -162,7 +162,7 @@ namespace Robust.Shared.Serialization.TypeSerializers.Implementations
ISerializationContext? context = null)
{
var mapping = new MappingDataNode();
mapping.Add("sprite", serializationManager.WriteValue(value.RsiPath, notNullableOverride: true));
mapping.Add("sprite", serializationManager.WriteValue(value.RsiPath));
mapping.Add("state", new ValueDataNode(value.RsiState));
return mapping;
}

View File

@@ -1,6 +1,8 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using JetBrains.Annotations;
using Robust.Shared.Collections;
using Robust.Shared.Serialization;
using ArgumentException = System.ArgumentException;
@@ -101,9 +103,12 @@ public readonly struct ResPath : IEquatable<ResPath>
var ind = CanonPath.Length > 1 && CanonPath[^1] == '/'
? CanonPath[..^1].LastIndexOf('/')
: CanonPath.LastIndexOf('/');
return ind != -1
? new ResPath(CanonPath[..ind])
: Self;
return ind switch
{
-1 => Self,
0 => new ResPath(CanonPath[..1]),
_ => new ResPath(CanonPath[..ind])
};
}
}
@@ -267,6 +272,11 @@ public readonly struct ResPath : IEquatable<ResPath>
return left;
}
if (left == Root)
{
return new ResPath("/" + right.CanonPath);
}
return new ResPath(left.CanonPath + "/" + right.CanonPath);
}
@@ -348,7 +358,7 @@ public readonly struct ResPath : IEquatable<ResPath>
/// </summary>
/// <seealso cref="IsRelative" />
/// <seealso cref="ToRootedPath"/>
public bool IsRooted => CanonPath[0] == '/';
public bool IsRooted => CanonPath.Length > 0 && CanonPath[0] == '/';
/// <summary>
/// Returns true if the path is not rooted.
@@ -364,8 +374,8 @@ public readonly struct ResPath : IEquatable<ResPath>
/// </summary>
/// <example>
/// <code>
/// var path1 = new ResourcePath("/a/b/c");
/// var path2 = new ResourcePath("/a");
/// var path1 = new ResPath("/a/b/c");
/// var path2 = new ResPath("/a");
/// Console.WriteLine(path1.RelativeTo(path2)); // prints "b/c".
/// </code>
/// </example>
@@ -398,7 +408,7 @@ public readonly struct ResPath : IEquatable<ResPath>
if (CanonPath.StartsWith(basePath.CanonPath))
{
var x = CanonPath[basePath.CanonPath.Length..]
.TrimStart('/');
.Trim('/');
relative = new ResPath(x);
return true;
}
@@ -475,3 +485,82 @@ public readonly struct ResPath : IEquatable<ResPath>
: CanonPath.Replace("/", newSeparator);
}
}
public static class ResPathUtil
{
/// <summary>
/// Returns cleaned version of the resource path, removing <c>..</c>.
/// </summary>
/// <remarks>
/// If <c>..</c> appears at the base of a path, it is left alone. If it appears at root level (like <c>/..</c>) it is removed entirely.
/// </remarks>
public static ResPath Clean(this ResPath path)
{
if (path.CanonPath == "")
{
return ResPath.Empty;
}
var segments = new ValueList<string>();
if (path.IsRooted)
{
segments.Add("/");
}
foreach (var segment in path.CanonPath.Split(ResPath.Separator))
{
// Skip pointless segments
if (segment == "." || segment == "")
{
continue;
}
// If you have ".." cleaning that up doesn't remove that.
if (segment == ".." && segments.Count > 0)
{
if (segments is ["/"])
{
continue;
}
var pos = segments.Count - 1;
if (segments[pos] != "..")
{
segments.RemoveAt(pos);
continue;
}
}
segments.Add(segment);
}
// Build Canon path from segments with StringBuilder
var sb = new StringBuilder(path.CanonPath.Length);
var start = path.IsRooted && segments.Count > 1 ? 1 : 0;
for (var i = 0; i < segments.Count; i++)
{
if (i > start)
{
sb.Append('/');
}
sb.Append(segments[i]);
}
return sb.Length == 0
? ResPath.Self
: new ResPath(sb.ToString());
}
/// <summary>
/// Enumerates segments skipping over first element in
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string[] EnumerateSegments(this ResPath path)
{
return path.IsRooted
? path.CanonPath[1..].Split(ResPath.Separator)
: path.CanonPath.Split(ResPath.Separator);
}
}

View File

@@ -1,722 +0,0 @@
// Because System.IO.Path sucks.
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Robust.Shared.Serialization;
namespace Robust.Shared.Utility
{
/// <summary>
/// Provides object-oriented path manipulation for resource paths.
/// ResourcePaths are immutable.
/// </summary>
[PublicAPI, Serializable, NetSerializable]
[Obsolete(@$"Use {nameof(ResPath)} instead")]
public sealed class ResourcePath : IEquatable<ResourcePath>
{
/// <summary>
/// The separator for the file system of the system we are compiling to.
/// Backslash on Windows, forward slash on sane systems.
/// </summary>
#if WINDOWS
public const string SYSTEM_SEPARATOR = "\\";
#else
public const string SYSTEM_SEPARATOR = "/";
#endif
/// <summary>
/// "." as a static. Separator used is <c>/</c>.
/// </summary>
public static readonly ResourcePath Self = new(".");
/// <summary>
/// "/" (root) as a static. Separator used is <c>/</c>.
/// </summary>
public static readonly ResourcePath Root = new("/");
/// <summary>
/// List of the segments of the path.
/// This is pretty much a split of the input string path by separator,
/// except for the root, which is represented as the separator in position #0.
/// </summary>
private readonly string[] Segments;
/// <summary>
/// The separator between "segments"/"directories" for this path.
/// </summary>
public string Separator { get; }
/// <summary>
/// This exists for serv3.
/// </summary>
private ResourcePath() : this("") {}
/// <summary>
/// Create a new path from a string, splitting it by the separator provided.
/// </summary>
/// <param name="path">The string path to turn into a resource path.</param>
/// <param name="separator">The separator for the resource path.</param>
/// <exception cref="ArgumentException">Thrown if you try to use "." as separator.</exception>
/// <exception cref="ArgumentNullException">Thrown if either argument is null.</exception>
public ResourcePath(string path, string separator = "/")
{
ValidateSeparate(separator);
Separator = separator;
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (path == "")
{
Segments = new string[] {"."};
return;
}
var splitSegments = path.Split(separator);
var segments = new List<string>(splitSegments.Length);
var i = 0;
if (splitSegments[0] == "")
{
i = 1;
segments.Add(separator);
}
for (; i < splitSegments.Length; i++)
{
var segment = splitSegments[i];
if (segment == "" || (segment == "." && segments.Count != 0))
{
continue;
}
if (i == 1 && segments[0] == ".")
{
segments[0] = segment;
}
else
{
segments.Add(segment);
}
}
Segments = ListToArray(segments);
}
private ResourcePath(string[] segments, string separator)
{
Segments = segments;
Separator = separator;
}
/// <inheritdoc />
public override string ToString()
{
var builder = new StringBuilder();
var i = 0;
if (IsRooted)
{
i = 1;
builder.Append(Separator);
}
for (; i < Segments.Length; i++)
{
builder.Append(Segments[i]);
if (i + 1 < Segments.Length)
{
builder.Append(Separator);
}
}
return builder.ToString();
}
/// <summary>
/// Returns true if the path is rooted (starts with the separator).
/// </summary>
/// <seealso cref="IsRelative" />
/// <seealso cref="ToRootedPath"/>
public bool IsRooted => Segments[0] == Separator;
/// <summary>
/// Returns true if the path is not rooted.
/// </summary>
/// <seealso cref="IsRooted" />
/// <seealso cref="ToRelativePath"/>
public bool IsRelative => !IsRooted;
/// <summary>
/// Returns true if the path is equal to "."
/// </summary>
public bool IsSelf => Segments.Length == 1 && Segments[0] == ".";
/// <summary>
/// Returns the file extension of file path, if any.
/// Returns "" if there is no file extension.
/// The extension returned does NOT include a period.
/// </summary>
public string Extension
{
get
{
var filename = Filename;
if (string.IsNullOrWhiteSpace(filename))
{
return "";
}
var index = filename.LastIndexOf('.');
if (index == 0 || index == -1 || index == filename.Length - 1)
{
// The path is a dotfile (like .bashrc),
// or there's no period at all,
// or the period is at the very end.
// Non of these cases are truly an extension.
return "";
}
return filename.Substring(index + 1);
}
}
/// <summary>
/// Returns the file name.
/// </summary>
public string Filename
{
get
{
if (Segments.Length == 1 && IsRooted)
{
return "";
}
return Segments[Segments.Length - 1];
}
}
/// <summary>
/// Returns the file name, without extension.
/// </summary>
public string FilenameWithoutExtension
{
get
{
var filename = Filename;
if (string.IsNullOrWhiteSpace(filename))
{
return filename;
}
var index = filename.LastIndexOf('.');
if (index == 0 || index == -1 || index == filename.Length - 1)
{
return filename;
}
return filename.Substring(0, index);
}
}
/// <summary>
/// Returns the directory that this file resides in.
/// </summary>
public ResourcePath Directory
{
get
{
if (IsSelf) return this;
var fileName = Filename;
if (!string.IsNullOrWhiteSpace(fileName))
{
var path = ToString();
var dir = path.Remove(path.Length - fileName.Length);
return new ResourcePath(dir);
}
return this;
}
}
/// <summary>
/// Returns a new instance with a different separator set.
/// </summary>
/// <param name="newSeparator">The new separator to use.</param>
/// <exception cref="ArgumentException">Thrown if the new separator is invalid.</exception>
public ResourcePath ChangeSeparator(string newSeparator)
{
ValidateSeparate(newSeparator);
// Convert the segments into a string path, then re-parse it.
// Solves the edge case of the segments containing the new separator.
ResourcePath path;
if (IsRooted)
{
var clone = (string[]) Segments.Clone();
clone[0] = newSeparator;
path = new ResourcePath(clone, newSeparator);
}
else
{
path = new ResourcePath(Segments, newSeparator);
}
return new ResourcePath(path.ToString(), newSeparator);
}
/// <summary>
/// Joins two resource paths together, with separator in between.
/// If the second path is absolute, the first path is completely ignored.
/// </summary>
/// <exception cref="ArgumentException">Thrown if the separators of the two paths do not match.</exception>
// "Why use / instead of +" you may think:
// * It's clever, although I got the idea from Python's pathlib.
// * It avoids confusing operator precedence causing you to join two strings,
// because path + string + string != path + (string + string),
// whereas path / (string / string) doesn't compile.
public static ResourcePath operator /(ResourcePath a, ResourcePath b)
{
if (a.Separator != b.Separator)
{
throw new ArgumentException("Both separators must be the same.");
}
if (b.IsRooted)
{
return b;
}
if (b.IsSelf)
{
return a;
}
string[] segments = new string[a.Segments.Length + b.Segments.Length];
a.Segments.CopyTo(segments, 0);
b.Segments.CopyTo(segments, a.Segments.Length);
return new ResourcePath(segments, a.Separator);
}
/// <summary>
/// Adds a new segment to the path as string.
/// </summary>
public static ResourcePath operator /(ResourcePath path, string b)
{
return path / new ResourcePath(b, path.Separator);
}
/// <summary>
/// "Cleans" the resource path, removing <c>..</c>.
/// </summary>
/// <remarks>
/// If .. appears at the base of a path, it is left alone. If it appears at root level (like /..) it is removed entirely.
/// </remarks>
public ResourcePath Clean()
{
var segments = new List<string>();
foreach (var segment in Segments)
{
// If you have ".." cleaning that up doesn't remove that.
if (segment == ".." && segments.Count != 0)
{
// Trying to do /.. results in /
if (segments.Count == 1 && segments[0] == Separator)
{
continue;
}
var pos = segments.Count - 1;
if (segments[pos] != "..")
{
segments.RemoveAt(pos);
continue;
}
}
segments.Add(segment);
}
if (segments.Count == 0)
{
return new ResourcePath(".", Separator);
}
return new ResourcePath(ListToArray(segments), Separator);
}
/// <summary>
/// Check whether a path is clean, i.e. <see cref="Clean"/> would not modify it.
/// </summary>
/// <returns></returns>
public bool IsClean()
{
for (var i = 0; i < Segments.Length; i++)
{
if (Segments[i] == "..")
{
if (IsRooted)
{
return false;
}
if (i > 0 && Segments[i - 1] != "..")
{
return false;
}
}
}
return true;
}
/// <summary>
/// Turns the path into a rooted path by prepending it with the separator.
/// Does nothing if the path is already rooted.
/// </summary>
/// <seealso cref="IsRooted" />
/// <seealso cref="ToRelativePath" />
public ResourcePath ToRootedPath()
{
if (IsRooted)
{
return this;
}
var segments = new string[Segments.Length + 1];
Segments.CopyTo(segments, 1);
segments[0] = Separator;
return new ResourcePath(segments, Separator);
}
/// <summary>
/// Turns the path into a relative path by removing the root separator, if any.
/// Does nothing if the path is already relative.
/// </summary>
/// <seealso cref="IsRelative"/>
/// <seealso cref="ToRootedPath" />
public ResourcePath ToRelativePath()
{
if (IsRelative)
{
return this;
}
if (Segments.Length == 1)
{
// This path is literally just "/"
return new ResourcePath(".", Separator);
}
var segments = new string[Segments.Length - 1];
Array.Copy(Segments, 1, segments, 0, Segments.Length - 1);
return new ResourcePath(segments, Separator);
}
/// <summary>
/// Turns the path into a relative path with system-specific separator.
/// For usage in disk I/O.
/// </summary>
public string ToRelativeSystemPath()
{
return ChangeSeparator(SYSTEM_SEPARATOR).ToRelativePath().ToString();
}
/// <summary>
/// Converts a relative disk path back into a resource path.
/// </summary>
/// <exception cref="ArgumentNullException">Thrown if either argument is null.</exception>
public static ResourcePath FromRelativeSystemPath(string path, string newSeparator = "/")
{
// ReSharper disable once RedundantArgumentDefaultValue
return new ResourcePath(path, SYSTEM_SEPARATOR).ChangeSeparator(newSeparator);
}
/// <summary>
/// Returns the path of how this instance is "relative" to <paramref name="basePath"/>,
/// such that <c>basePath/result == this</c>.
/// </summary>
/// <example>
/// <code>
/// var path1 = new ResourcePath("/a/b/c");
/// var path2 = new ResourcePath("/a");
/// Console.WriteLine(path1.RelativeTo(path2)); // prints "b/c".
/// </code>
/// </example>
/// <exception cref="ArgumentException">Thrown if we are not relative to the base path or the separators are not the same.</exception>
public ResourcePath RelativeTo(ResourcePath basePath)
{
if (TryRelativeTo(basePath, out var relative))
{
return relative;
}
throw new ArgumentException($"{this} does not start with {basePath}.");
}
/// <summary>
/// Try pattern version of <see cref="RelativeTo(ResourcePath)"/>.
/// </summary>
/// <param name="basePath">The base path which we can be made relative to.</param>
/// <param name="relative">The path of how we are relative to <paramref name="basePath"/>, if at all.</param>
/// <returns>True if we are relative to <paramref name="basePath"/>, false otherwise.</returns>
/// <exception cref="ArgumentException">Thrown if the separators are not the same.</exception>
public bool TryRelativeTo(ResourcePath basePath, [NotNullWhen(true)] out ResourcePath? relative)
{
if (basePath.Separator != Separator)
{
throw new ArgumentException("Separators must be the same.", nameof(basePath));
}
if (Segments.Length < basePath.Segments.Length)
{
relative = null;
return false;
}
if (Segments.Length == basePath.Segments.Length)
{
if (this == basePath)
{
relative = new ResourcePath(".", Separator);
return true;
}
else
{
relative = null;
return false;
}
}
for (var i = 0; i < basePath.Segments.Length; i++)
{
if (Segments[i] != basePath.Segments[i])
{
relative = null;
return false;
}
}
var segments = new string[Segments.Length - basePath.Segments.Length];
Array.Copy(Segments, basePath.Segments.Length, segments, 0, segments.Length);
relative = new ResourcePath(segments, Separator);
return true;
}
/// <summary>
/// Gets the common base of two paths.
/// </summary>
/// <example>
/// <code>
/// var path1 = new ResourcePath("/a/b/c");
/// var path2 = new ResourcePath("/a/e/d");
/// Console.WriteLine(path1.RelativeTo(path2)); // prints "/a".
/// </code>
/// </example>
/// <param name="other">The other path.</param>
/// <exception cref="ArgumentException">Thrown if there is no common base between the two paths.</exception>
public ResourcePath CommonBase(ResourcePath other)
{
if (other.Separator != Separator)
{
throw new ArgumentException("Separators must match.");
}
var i = 0;
for (; i < Segments.Length && i < other.Segments.Length; i++)
{
if (Segments[i] != other.Segments[i])
{
break;
}
}
if (i == 0)
{
throw new ArgumentException($"{this} and {other} have no common base.");
}
var segments = new string[i];
Array.Copy(Segments, segments, i);
return new ResourcePath(segments, Separator);
}
/// <summary>
/// Return a copy of this resource path with the file name changed.
/// </summary>
/// <param name="name">
/// The new file name.
/// </param>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="name"/> is null, empty,
/// contains <see cref="Separator"/> or is equal to <c>.</c>
/// </exception>
public ResourcePath WithName(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("New file name cannot be null or empty.");
}
if (name.Contains(Separator))
{
throw new ArgumentException("New file name cannot contain the separator.");
}
if (name == ".")
{
throw new ArgumentException("New file name cannot be '.'");
}
var newSegments = (string[]) Segments.Clone();
newSegments[newSegments.Length - 1] = name;
return new ResourcePath(newSegments, Separator);
}
/// <summary>
/// Return a copy of this resource path with the file extension changed.
/// </summary>
/// <param name="newExtension">
/// The new file extension.
/// </param>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="newExtension"/> is null, empty,
/// contains <see cref="Separator"/> or is equal to <c>.</c>
/// </exception>
public ResourcePath WithExtension(string newExtension)
{
if (string.IsNullOrEmpty(newExtension))
{
throw new ArgumentException("New file name cannot be null or empty.");
}
if (newExtension.Contains(Separator))
{
throw new ArgumentException("New file name cannot contain the separator.");
}
return WithName($"{FilenameWithoutExtension}.{newExtension}");
}
/// <summary>
/// Enumerates the segments of this path.
/// </summary>
/// <remarks>
/// Segments are returned from highest to deepest.
/// For example <c>/a/b</c> will yield <c>a</c> then <c>b</c>.
/// No special indication is given for rooted paths,
/// so <c>/a/b</c> yields the same as <c>a/b</c>.
/// </remarks>
public IEnumerable<string> EnumerateSegments()
{
if (IsRooted)
{
// Skip '/' root.
return Segments.Skip(1);
}
return Segments;
}
/// <inheritdoc />
public override int GetHashCode()
{
var code = Separator.GetHashCode();
foreach (var segment in Segments)
{
unchecked
{
code = code * 31 + segment.GetHashCode();
}
}
return code;
}
/// <inheritdoc />
public override bool Equals(object? obj)
{
return obj is ResourcePath path && Equals(path);
}
/// <summary>
/// Checks that we are equal with <paramref name="path"/>.
/// This method does NOT clean the paths beforehand, so paths that point to the same location may fail if they are not cleaned beforehand.
/// Paths are never equal if they do not have the same separator.
/// </summary>
/// <param name="other">The path to check equality with.</param>
/// <returns>True if the paths are equal, false otherwise.</returns>
public bool Equals(ResourcePath? other)
{
if (other == null)
{
return false;
}
if (other.Separator != Separator || Segments.Length != other.Segments.Length)
{
return false;
}
for (var i = 0; i < Segments.Length; i++)
{
if (Segments[i] != other.Segments[i])
{
return false;
}
}
return true;
}
public static bool operator ==(ResourcePath? a, ResourcePath? b)
{
if ((object?) a == null)
{
return (object?) b == null;
}
return a.Equals(b);
}
public static bool operator !=(ResourcePath? a, ResourcePath? b)
{
return !(a == b);
}
// While profiling I found that List<T>.ToArray() is just incredibly slow. No idea why honestly.
private static string[] ListToArray(List<string> list)
{
var array = new string[list.Count];
for (var i = 0; i < list.Count; i++)
{
array[i] = list[i];
}
return array;
}
private static void ValidateSeparate(string separator)
{
if (string.IsNullOrWhiteSpace(separator))
{
throw new ArgumentException("Separator may not be null or whitespace.");
}
if (separator == "." || separator == "..")
{
throw new ArgumentException("Separator may not be . or ..");
}
}
}
}

View File

@@ -6,8 +6,8 @@ namespace Robust.Shared.Utility
{
// >tfw you're not using Rust and you don't have easy sum types.
// pub enum SpriteSpecifier {
// Rsi { path: ResourcePath, state: String, },
// Texture(ResourcePath),
// Rsi { path: ResPath, state: String, },
// Texture(ResPath),
// }
/// <summary>
/// Is a reference to EITHER an RSI + RSI State, OR a bare texture path.
@@ -15,7 +15,7 @@ namespace Robust.Shared.Utility
[Serializable, NetSerializable]
public abstract class SpriteSpecifier
{
public static readonly SpriteSpecifier Invalid = new Texture(new ResourcePath("."));
public static readonly SpriteSpecifier Invalid = new Texture(ResPath.Self);
public static SpriteSpecifier FromYaml(YamlNode node)
{
@@ -33,7 +33,7 @@ namespace Robust.Shared.Utility
[Serializable, NetSerializable]
public sealed class Rsi : SpriteSpecifier
{
public ResourcePath RsiPath { get; internal set; }
public ResPath RsiPath { get; internal set; }
public string RsiState { get; internal set; }
// For serialization
@@ -43,7 +43,7 @@ namespace Robust.Shared.Utility
RsiState = default!;
}
public Rsi(ResourcePath rsiPath, string rsiState)
public Rsi(ResPath rsiPath, string rsiState)
{
RsiPath = rsiPath;
RsiState = rsiState;
@@ -63,7 +63,7 @@ namespace Robust.Shared.Utility
[Serializable, NetSerializable]
public sealed class Texture : SpriteSpecifier
{
public ResourcePath TexturePath { get; internal set; }
public ResPath TexturePath { get; internal set; }
// For serialization
private Texture()
@@ -71,7 +71,7 @@ namespace Robust.Shared.Utility
TexturePath = default!;
}
public Texture(ResourcePath texturePath)
public Texture(ResPath texturePath)
{
TexturePath = texturePath;
}

View File

@@ -165,7 +165,7 @@ namespace Robust.Shared.Utility
}
[Pure]
public static ResourcePath AsResourcePath(this YamlNode node)
public static ResPath AsResourcePath(this YamlNode node)
{
return new(node.ToString());
}

View File

@@ -18,7 +18,7 @@ namespace Robust.UnitTesting
var stream = new MemoryStream();
stream.Write(Encoding.UTF8.GetBytes(content));
stream.Position = 0;
resourceManager.MountStreamAt(stream, new ResourcePath(path));
resourceManager.MountStreamAt(stream, new (path));
}
}
}

View File

@@ -215,7 +215,7 @@ namespace Robust.UnitTesting
var modLoader = deps.Resolve<TestingModLoader>();
modLoader.Assemblies = contentAssemblies;
modLoader.TryLoadModulesFrom(ResourcePath.Root, "");
modLoader.TryLoadModulesFrom(ResPath.Root, "");
entMan.Startup();
mapMan.Startup();

View File

@@ -79,8 +79,8 @@ entities:
var protoMan = IoCManager.Resolve<IPrototypeManager>();
protoMan.RegisterKind(typeof(EntityPrototype));
protoMan.LoadDirectory(new ResourcePath("/EnginePrototypes"));
protoMan.LoadDirectory(new ResourcePath("/Prototypes"));
protoMan.LoadDirectory(new ("/EnginePrototypes"));
protoMan.LoadDirectory(new ("/Prototypes"));
protoMan.ResolveResults();
}

View File

@@ -67,7 +67,7 @@ namespace Robust.UnitTesting.Shared.ContentPack
var stream = new MemoryStream(Data);
var resourceManager = IoCManager.Resolve<IResourceManagerInternal>();
resourceManager.MountStreamAt(stream, new ResourcePath("/a/b/c.dat"));
resourceManager.MountStreamAt(stream, new ("/a/b/c.dat"));
}
[Test]
@@ -83,13 +83,13 @@ namespace Robust.UnitTesting.Shared.ContentPack
[Test]
public void TestInvalidPaths([ValueSource(nameof(InvalidPaths))] string path)
{
Assert.That(ResourceManager.IsPathValid(new ResourcePath(path)), Is.False);
Assert.That(ResourceManager.IsPathValid(new (path)), Is.False);
}
[Test]
public void TestInvalidPathsLowerCase([ValueSource(nameof(InvalidPaths))] string path)
{
Assert.That(ResourceManager.IsPathValid(new ResourcePath(path.ToLowerInvariant())), Is.False);
Assert.That(ResourceManager.IsPathValid(new (path.ToLowerInvariant())), Is.False);
}
[Test]
@@ -112,8 +112,8 @@ namespace Robust.UnitTesting.Shared.ContentPack
Assert.That(found, Is.EquivalentTo(new[]
{
new ResourcePath("/bar/a.txt"),
new ResourcePath("/bar/b.txt"),
new ResPath("/bar/a.txt"),
new ResPath("/bar/b.txt"),
}));
}

View File

@@ -32,7 +32,7 @@ namespace Robust.UnitTesting.Shared.Localization
var protoMan = IoCManager.Resolve<IPrototypeManager>();
protoMan.RegisterKind(typeof(EntityPrototype));
protoMan.LoadDirectory(new ResourcePath("/EnginePrototypes"));
protoMan.LoadDirectory(new ResPath("/EnginePrototypes"));
protoMan.ResolveResults();
var loc = IoCManager.Resolve<ILocalizationManager>();

View File

@@ -39,7 +39,7 @@ namespace Robust.UnitTesting.Shared.Resources
File.WriteAllText(Path.Combine(_testDirPath, "dummy"), "foobar");
// No, ../ does not work to read stuff in the parent dir.
Assert.That(() => _dirProvider.ReadAllText(new ResourcePath("/../dummy")),
Assert.That(() => _dirProvider.ReadAllText(new ResPath("/../dummy")),
Throws.InstanceOf<FileNotFoundException>());
}
@@ -47,7 +47,7 @@ namespace Robust.UnitTesting.Shared.Resources
public void TestNotRooted()
{
// Path must be rooted.
Assert.That(() => _dirProvider.OpenRead(new ResourcePath("foo.bar")),
Assert.That(() => _dirProvider.OpenRead(new ResPath("foo.bar")),
Throws.InstanceOf<ArgumentException>());
}
@@ -56,10 +56,10 @@ namespace Robust.UnitTesting.Shared.Resources
{
File.WriteAllText(Path.Combine(_testDirPath, "dummy"), "foobar");
_dirProvider.WriteAllText(new ResourcePath("/dummy"), "pranked");
_dirProvider.WriteAllText(new ResPath("/dummy"), "pranked");
// ../ should get clamped to /.
Assert.That(_dirProvider.ReadAllText(new ResourcePath("/../dummy")), Is.EqualTo("pranked"));
Assert.That(_dirProvider.ReadAllText(new ResPath("/../dummy")), Is.EqualTo("pranked"));
}
}
}

View File

@@ -22,7 +22,7 @@ public sealed class ResPathTest
public string ExtensionTest(string input)
{
var resPathExt = new ResPath(input).Extension;
var resourceExt = new ResourcePath(input).Extension;
var resourceExt = new ResPath(input).Extension;
Assert.That(resPathExt, Is.EqualTo(resourceExt),
message: "Found discrepancy between ResPath and ResourcePath Extension");
return resPathExt;
@@ -42,9 +42,6 @@ public sealed class ResPathTest
public string FilenameTest(string input)
{
var resPathFilename = new ResPath(input).Filename;
var resourceFilename = new ResourcePath(input).Filename;
Assert.That(resPathFilename, Is.EqualTo(resourceFilename),
message: "Found discrepancy between ResPath and ResourcePath Extension");
return resPathFilename;
}
@@ -61,10 +58,7 @@ public sealed class ResPathTest
public string FilenameWithoutExtension(string input)
{
var resPathFileNoExt = new ResPath(input).FilenameWithoutExtension;
var resourceFileNoExt = new ResourcePath(input).FilenameWithoutExtension;
Assert.That(resPathFileNoExt, Is.EqualTo(resourceFileNoExt),
message: "Found discrepancy between ResPath and ResourcePath FilenameWithoutExtension methods");
return resourceFileNoExt;
return resPathFileNoExt;
}
[Test]
@@ -74,12 +68,10 @@ public sealed class ResPathTest
[TestCase(@"/foo/bar/", ExpectedResult = @"/foo")]
[TestCase(@"/foo/bar/x", ExpectedResult = @"/foo/bar")]
[TestCase(@"/foo/bar.txt", ExpectedResult = @"/foo")]
[TestCase(@"/bar.txt", ExpectedResult = @"/")]
public string DirectoryTest(string path)
{
var resPathDirectory = new ResPath(path).Directory.ToString();
var resourceDirectory = new ResourcePath(path).Directory.ToString();
Assert.That(resPathDirectory, Is.EqualTo(resourceDirectory),
message: "Found discrepancy between ResPath and ResourcePath Directory methods");
return resPathDirectory;
}
@@ -105,6 +97,8 @@ public sealed class ResPathTest
[TestCase("/a/b", "z", ExpectedResult = "/a/b/z")]
[TestCase("/a/b", "/z", ExpectedResult = "/z")]
[TestCase("/a/b", ".", ExpectedResult = "/a/b")]
[TestCase("/", "/a", ExpectedResult = "/a")]
[TestCase("/", "a", ExpectedResult = "/a")]
public string CombineTest(string left, string right)
{
var pathDivRes = new ResPath(left) / new ResPath(right);
@@ -134,6 +128,7 @@ public sealed class ResPathTest
[TestCase("/a/b/c", "/", ExpectedResult = "a/b/c")]
[TestCase("/a", "/a", ExpectedResult = ".")]
[TestCase("a/b", "a", ExpectedResult = "b")]
[TestCase("/bar/", "/", ExpectedResult = "bar")]
[TestCase("/Textures/Weapons/laser.png", "/Textures/", ExpectedResult = "Weapons/laser.png")]
public string RelativeToTest(string source, string baseDir)
{

View File

@@ -10,7 +10,7 @@ namespace Robust.UnitTesting
{
public Assembly[] Assemblies { get; set; } = Array.Empty<Assembly>();
public bool TryLoadModulesFrom(ResourcePath mountPath, string filterPrefix)
public bool TryLoadModulesFrom(ResPath mountPath, string filterPrefix)
{
foreach (var assembly in Assemblies)
{