Allow engine to be loaded from a zip file itself.

This commit is contained in:
Pieter-Jan Briers
2020-12-12 11:12:19 +01:00
parent 50f0a4389e
commit f15c1c7a95
16 changed files with 172 additions and 29 deletions

3
.gitmodules vendored
View File

@@ -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

View File

@@ -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)

View 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);
}
}
}
}

View File

@@ -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.

View File

@@ -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);
}
}

View 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;
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

Submodule Robust.LoaderApi added at 0d5c015792

View File

@@ -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;
}
}

View File

@@ -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; }
}
}

View File

@@ -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)>();

View File

@@ -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)

View File

@@ -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/");

View File

@@ -44,5 +44,7 @@ namespace Robust.UnitTesting
{
// Nada.
}
public Func<string, Stream?>? VerifierExtraLoadHandler { get; set; }
}
}

View File

@@ -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}