mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Allow engine to be loaded from a zip file itself.
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -4,3 +4,6 @@
|
||||
[submodule "Lidgren.Network"]
|
||||
path = Lidgren.Network/Lidgren.Network
|
||||
url = https://github.com/space-wizards/lidgren-network-gen3.git
|
||||
[submodule "Robust.LoaderApi"]
|
||||
path = Robust.LoaderApi
|
||||
url = https://github.com/space-wizards/Robust.LoaderApi.git
|
||||
|
||||
@@ -17,6 +17,7 @@ using Robust.Client.Interfaces.Utility;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Client.ViewVariables;
|
||||
using Robust.LoaderApi;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Asynchronous;
|
||||
using Robust.Shared.Configuration;
|
||||
@@ -67,6 +68,8 @@ namespace Robust.Client
|
||||
|
||||
private CommandLineArgs? _commandLineArgs;
|
||||
private bool _disableAssemblyLoadContext;
|
||||
// Arguments for loader-load. Not used otherwise.
|
||||
private IMainArgs? _loaderArgs;
|
||||
|
||||
public InitialLaunchState LaunchState { get; private set; } = default!;
|
||||
|
||||
@@ -119,7 +122,12 @@ namespace Robust.Client
|
||||
|
||||
_resourceCache.Initialize(LoadConfigAndUserData ? userDataDir : null);
|
||||
|
||||
ProgramShared.DoMounts(_resourceCache, _commandLineArgs?.MountOptions, "Content.Client");
|
||||
ProgramShared.DoMounts(_resourceCache, _commandLineArgs?.MountOptions, "Content.Client", _loaderArgs != null);
|
||||
if (_loaderArgs != null)
|
||||
{
|
||||
_resourceCache.MountLoaderApi(_loaderArgs.FileApi, "Resources/");
|
||||
_modLoader.VerifierExtraLoadHandler = VerifierExtraLoadHandler;
|
||||
}
|
||||
|
||||
// Bring display up as soon as resources are mounted.
|
||||
if (!_clyde.Initialize())
|
||||
@@ -185,6 +193,18 @@ namespace Robust.Client
|
||||
return true;
|
||||
}
|
||||
|
||||
private Stream? VerifierExtraLoadHandler(string arg)
|
||||
{
|
||||
DebugTools.AssertNotNull(_loaderArgs);
|
||||
|
||||
if (!_loaderArgs!.FileApi.TryOpen(arg, out var stream))
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void ReadInitialLaunchState()
|
||||
{
|
||||
if (_commandLineArgs == null)
|
||||
|
||||
18
Robust.Client/GameController/GameController.Loader.cs
Normal file
18
Robust.Client/GameController/GameController.Loader.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Robust.Client;
|
||||
using Robust.LoaderApi;
|
||||
|
||||
[assembly: LoaderEntryPoint(typeof(GameController.LoaderEntryPoint))]
|
||||
|
||||
namespace Robust.Client
|
||||
{
|
||||
internal partial class GameController
|
||||
{
|
||||
internal class LoaderEntryPoint : ILoaderEntryPoint
|
||||
{
|
||||
public void Main(IMainArgs args)
|
||||
{
|
||||
GameController.Start(args.Args, contentStart: false, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Robust.Client.Interfaces;
|
||||
using Robust.LoaderApi;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
@@ -21,7 +21,7 @@ namespace Robust.Client
|
||||
Start(args);
|
||||
}
|
||||
|
||||
public static void Start(string[] args, bool contentStart = false)
|
||||
public static void Start(string[] args, bool contentStart = false, IMainArgs? loaderArgs=null)
|
||||
{
|
||||
if (_hasStarted)
|
||||
{
|
||||
@@ -32,11 +32,11 @@ namespace Robust.Client
|
||||
|
||||
if (CommandLineArgs.TryParse(args, out var parsed))
|
||||
{
|
||||
ParsedMain(parsed, contentStart);
|
||||
ParsedMain(parsed, contentStart, loaderArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParsedMain(CommandLineArgs args, bool contentStart)
|
||||
private static void ParsedMain(CommandLineArgs args, bool contentStart, IMainArgs? loaderArgs)
|
||||
{
|
||||
IoCManager.InitThread();
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace Robust.Client
|
||||
|
||||
var gc = (GameController) IoCManager.Resolve<IGameController>();
|
||||
gc.SetCommandLineArgs(args);
|
||||
gc._loaderArgs = loaderArgs;
|
||||
|
||||
// When the game is ran with the startup executable being content,
|
||||
// we have to disable the separate load context.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.LoaderApi;
|
||||
using Robust.Shared.Interfaces.Resources;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -47,5 +48,7 @@ namespace Robust.Client.Interfaces.ResourceManagement
|
||||
{
|
||||
void TextureLoaded(TextureLoadedEventArgs eventArgs);
|
||||
void RsiLoaded(RsiLoadedEventArgs eventArgs);
|
||||
|
||||
void MountLoaderApi(IFileApi api, string apiPrefix, ResourcePath? prefix=null);
|
||||
}
|
||||
}
|
||||
|
||||
55
Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs
Normal file
55
Robust.Client/ResourceManagement/ResourceCache.LoaderApi.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using Robust.LoaderApi;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Client.ResourceManagement
|
||||
{
|
||||
internal partial class ResourceCache
|
||||
{
|
||||
private sealed class LoaderApiLoader : IContentRoot
|
||||
{
|
||||
private readonly IFileApi _api;
|
||||
private readonly string _prefix;
|
||||
|
||||
public LoaderApiLoader(IFileApi api, string prefix)
|
||||
{
|
||||
_api = api;
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
public void Mount()
|
||||
{
|
||||
}
|
||||
|
||||
public bool TryGetFile(ResourcePath relPath, [NotNullWhen(true)] out Stream? stream)
|
||||
{
|
||||
if (_api.TryOpen($"{_prefix}{relPath}", out stream))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<ResourcePath> FindFiles(ResourcePath path)
|
||||
{
|
||||
foreach (var relPath in _api.AllFiles)
|
||||
{
|
||||
var resP = new ResourcePath(relPath);
|
||||
if (resP.TryRelativeTo(path, out _))
|
||||
{
|
||||
yield return resP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetRelativeFilePaths()
|
||||
{
|
||||
return _api.AllFiles;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,11 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Robust.LoaderApi;
|
||||
|
||||
namespace Robust.Client.ResourceManagement
|
||||
{
|
||||
internal class ResourceCache : ResourceManager, IResourceCacheInternal, IDisposable
|
||||
internal partial class ResourceCache : ResourceManager, IResourceCacheInternal, IDisposable
|
||||
{
|
||||
private readonly Dictionary<Type, Dictionary<ResourcePath, BaseResource>> CachedResources =
|
||||
new();
|
||||
@@ -210,5 +211,12 @@ namespace Robust.Client.ResourceManagement
|
||||
{
|
||||
OnRsiLoaded?.Invoke(eventArgs);
|
||||
}
|
||||
|
||||
public void MountLoaderApi(IFileApi api, string apiPrefix, ResourcePath? prefix=null)
|
||||
{
|
||||
prefix ??= ResourcePath.Root;
|
||||
var root = new LoaderApiLoader(api, apiPrefix);
|
||||
AddRoot(prefix, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\OpenToolkit.GraphicsLibraryFramework\OpenToolkit.GraphicsLibraryFramework.csproj" />
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj" />
|
||||
<ProjectReference Include="..\Robust.Physics\Robust.Physics.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\Robust.Shared\Robust.Shared.csproj" />
|
||||
|
||||
1
Robust.LoaderApi
Submodule
1
Robust.LoaderApi
Submodule
Submodule Robust.LoaderApi added at 0d5c015792
@@ -42,6 +42,9 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
private bool WouldNoOp => Dump == DumpFlags.None && DisableTypeCheck && !VerifyIL;
|
||||
|
||||
// Necessary for loads with launcher loader.
|
||||
public Func<string, Stream?>? ExtraRobustLoader { get; set; }
|
||||
|
||||
public AssemblyTypeChecker(IResourceManager res)
|
||||
{
|
||||
_res = res;
|
||||
@@ -50,14 +53,24 @@ namespace Robust.Shared.ContentPack
|
||||
private Resolver CreateResolver()
|
||||
{
|
||||
var dotnetDir = Path.GetDirectoryName(typeof(int).Assembly.Location)!;
|
||||
var ourDir = Path.GetDirectoryName(typeof(AssemblyTypeChecker).Assembly.Location)!;
|
||||
var ourPath = typeof(AssemblyTypeChecker).Assembly.Location;
|
||||
string[] loadDirs;
|
||||
if (string.IsNullOrEmpty(ourPath))
|
||||
{
|
||||
Logger.DebugS("res.typecheck", "Robust directory not available");
|
||||
loadDirs = new[] {dotnetDir};
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.DebugS("res.typecheck", "Robust directory is {0}", ourPath);
|
||||
loadDirs = new[] {dotnetDir, Path.GetDirectoryName(ourPath)!};
|
||||
}
|
||||
|
||||
Logger.DebugS("res.typecheck", ".NET runtime directory is {0}", dotnetDir);
|
||||
Logger.DebugS("res.typecheck", "Robust directory is {0}", ourDir);
|
||||
|
||||
return new Resolver(
|
||||
this,
|
||||
new[] {dotnetDir, ourDir},
|
||||
loadDirs,
|
||||
new[] {new ResourcePath("/Assemblies/")}
|
||||
);
|
||||
}
|
||||
@@ -751,6 +764,12 @@ namespace Robust.Shared.ContentPack
|
||||
}
|
||||
}
|
||||
|
||||
var extraStream = _parent.ExtraRobustLoader?.Invoke(dllName);
|
||||
if (extraStream != null)
|
||||
{
|
||||
return new PEReader(extraStream);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
@@ -65,5 +66,7 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
void SetUseLoadContext(bool useLoadContext);
|
||||
void SetEnableSandboxing(bool sandboxing);
|
||||
|
||||
Func<string, Stream?>? VerifierExtraLoadHandler { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,12 @@ namespace Robust.Shared.ContentPack
|
||||
Logger.DebugS("res", "{0} sandboxing", sandboxing ? "ENABLING" : "DISABLING");
|
||||
}
|
||||
|
||||
public Func<string, Stream?>? VerifierExtraLoadHandler
|
||||
{
|
||||
get => _typeChecker.ExtraRobustLoader;
|
||||
set => _typeChecker.ExtraRobustLoader = value;
|
||||
}
|
||||
|
||||
public bool TryLoadModulesFrom(ResourcePath mountPath, string filterPrefix)
|
||||
{
|
||||
var files = new Dictionary<string, (ResourcePath Path, string[] references)>();
|
||||
|
||||
@@ -70,7 +70,8 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
prefix = SanitizePrefix(prefix);
|
||||
|
||||
pack = PathHelpers.ExecutableRelativeFile(pack);
|
||||
if (!Path.IsPathRooted(pack))
|
||||
pack = PathHelpers.ExecutableRelativeFile(pack);
|
||||
|
||||
var packInfo = new FileInfo(pack);
|
||||
|
||||
@@ -93,7 +94,7 @@ namespace Robust.Shared.ContentPack
|
||||
AddRoot(prefix, loader);
|
||||
}
|
||||
|
||||
private void AddRoot(ResourcePath prefix, IContentRoot loader)
|
||||
protected void AddRoot(ResourcePath prefix, IContentRoot loader)
|
||||
{
|
||||
loader.Mount();
|
||||
_contentRootsLock.EnterWriteLock();
|
||||
@@ -126,7 +127,9 @@ namespace Robust.Shared.ContentPack
|
||||
{
|
||||
prefix = SanitizePrefix(prefix);
|
||||
|
||||
path = PathHelpers.ExecutableRelativeFile(path);
|
||||
if (!Path.IsPathRooted(path))
|
||||
path = PathHelpers.ExecutableRelativeFile(path);
|
||||
|
||||
var pathInfo = new DirectoryInfo(path);
|
||||
if (!pathInfo.Exists)
|
||||
{
|
||||
@@ -293,22 +296,8 @@ namespace Robust.Shared.ContentPack
|
||||
|
||||
public void MountStreamAt(MemoryStream stream, ResourcePath path)
|
||||
{
|
||||
if (!path.IsRooted)
|
||||
{
|
||||
throw new ArgumentException("Path must be rooted.", nameof(path));
|
||||
}
|
||||
|
||||
var loader = new SingleStreamLoader(stream, path.ToRelativePath());
|
||||
loader.Mount();
|
||||
_contentRootsLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_contentRoots.Add((ResourcePath.Root, loader));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_contentRootsLock.ExitWriteLock();
|
||||
}
|
||||
AddRoot(ResourcePath.Root, loader);
|
||||
}
|
||||
|
||||
internal static bool IsPathValid(ResourcePath path)
|
||||
|
||||
@@ -23,10 +23,11 @@ namespace Robust.Shared
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static void DoMounts(IResourceManagerInternal res, MountOptions? options, string contentBuildDir)
|
||||
internal static void DoMounts(IResourceManagerInternal res, MountOptions? options, string contentBuildDir, bool loader=false)
|
||||
{
|
||||
#if FULL_RELEASE
|
||||
res.MountContentDirectory(@"Resources/");
|
||||
if (!loader)
|
||||
res.MountContentDirectory(@"Resources/");
|
||||
#else
|
||||
var contentRootDir = FindContentRootDir();
|
||||
res.MountContentDirectory($@"{contentRootDir}RobustToolbox/Resources/");
|
||||
|
||||
@@ -44,5 +44,7 @@ namespace Robust.UnitTesting
|
||||
{
|
||||
// Nada.
|
||||
}
|
||||
|
||||
public Func<string, Stream?>? VerifierExtraLoadHandler { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSerializer", "NetSeriali
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.Physics", "Robust.Physics\Robust.Physics.csproj", "{887A54FA-7D31-4D6D-9D7F-9AE3739E4982}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Robust.LoaderApi", "Robust.LoaderApi", "{805C8FD2-0C32-4DA8-BC4B-143BA5D48FF4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.LoaderApi", "Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj", "{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -113,12 +117,21 @@ Global
|
||||
{887A54FA-7D31-4D6D-9D7F-9AE3739E4982}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{887A54FA-7D31-4D6D-9D7F-9AE3739E4982}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{887A54FA-7D31-4D6D-9D7F-9AE3739E4982}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{ECBCE1D8-05C2-4881-9446-197C4C8E1C14} = {9143C8DD-A989-4089-9149-C50D12189FE4}
|
||||
{4FC5049F-AEEC-4DC0-9F4D-EB927AAB4F15} = {805C8FD2-0C32-4DA8-BC4B-143BA5D48FF4}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {57757344-0FF4-4842-8A68-141CAA18A35D}
|
||||
|
||||
Reference in New Issue
Block a user