Skip to content

Commit

Permalink
Allow the game root directory to be moved away from the binaries.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote authored and teinarss committed Nov 24, 2020
1 parent dd0b08d commit 6ad5b9e
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 8 deletions.
4 changes: 2 additions & 2 deletions OpenRA.Game/ExternalMods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void LoadMod(MiniYaml yaml, string path = null, bool forceRegistration = false)
mods[key] = mod;
}

internal void Register(Manifest mod, string launchPath, ModRegistration registration)
internal void Register(Manifest mod, string launchPath, IEnumerable<string> launchArgs, ModRegistration registration)
{
if (mod.Metadata.Hidden)
return;
Expand All @@ -133,7 +133,7 @@ internal void Register(Manifest mod, string launchPath, ModRegistration registra
new MiniYamlNode("Version", mod.Metadata.Version),
new MiniYamlNode("Title", mod.Metadata.Title),
new MiniYamlNode("LaunchPath", launchPath),
new MiniYamlNode("LaunchArgs", "Game.Mod=" + mod.Id)
new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", "))
}));

using (var stream = mod.Package.GetStream("icon.png"))
Expand Down
22 changes: 18 additions & 4 deletions OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ public static RunStatus InitializeAndRun(string[] args)

static void Initialize(Arguments args)
{
var engineDirArg = args.GetValue("Engine.EngineDir", null);
if (!string.IsNullOrEmpty(engineDirArg))
Platform.OverrideEngineDir(engineDirArg);

var supportDirArg = args.GetValue("Engine.SupportDir", null);
if (!string.IsNullOrEmpty(supportDirArg))
Platform.OverrideSupportDir(supportDirArg);
Expand Down Expand Up @@ -324,7 +328,7 @@ static void Initialize(Arguments args)
Settings.Game.Platform = p;
try
{
var rendererPath = Path.Combine(Platform.EngineDir, "OpenRA.Platforms." + p + ".dll");
var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + p + ".dll");
var assembly = Assembly.LoadFile(rendererPath);

var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
Expand Down Expand Up @@ -367,14 +371,24 @@ static void Initialize(Arguments args)

if (modID != null && Mods.TryGetValue(modID, out _))
{
var launchPath = args.GetValue("Engine.LaunchPath", Assembly.GetEntryAssembly().Location);
var launchPath = args.GetValue("Engine.LaunchPath", null);
var launchArgs = new List<string>();

// Sanitize input from platform-specific launchers
// Process.Start requires paths to not be quoted, even if they contain spaces
if (launchPath.First() == '"' && launchPath.Last() == '"')
if (launchPath != null && launchPath.First() == '"' && launchPath.Last() == '"')
launchPath = launchPath.Substring(1, launchPath.Length - 2);

ExternalMods.Register(Mods[modID], launchPath, ModRegistration.User);
if (launchPath == null)
{
// When launching the assembly directly we must propagate the Engine.EngineDir argument if defined
// Platform-specific launchers are expected to manage this internally.
launchPath = Assembly.GetEntryAssembly().Location;
if (!string.IsNullOrEmpty(engineDirArg))
launchArgs.Add("Engine.EngineDir=\"" + engineDirArg + "\"");
}

ExternalMods.Register(Mods[modID], launchPath, launchArgs, ModRegistration.User);

if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out var activeMod))
ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User);
Expand Down
47 changes: 47 additions & 0 deletions OpenRA.Game/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public static class Platform

static Lazy<PlatformType> currentPlatform = Exts.Lazy(GetCurrentPlatform);

static bool engineDirAccessed;
static string engineDir;

static bool supportDirInitialized;
static string systemSupportPath;
static string legacyUserSupportPath;
Expand Down Expand Up @@ -170,6 +173,44 @@ public static void OverrideSupportDir(string path)
}

public static string EngineDir
{
get
{
// Engine directory defaults to the location of the binaries,
// unless OverrideGameDir is called during startup.
if (!engineDirAccessed)
engineDir = BinDir;

engineDirAccessed = true;
return engineDir;
}
}

/// <summary>
/// Specify a custom engine directory that already exists on the filesystem.
/// Cannot be called after Platform.EngineDir has been accessed.
/// </summary>
public static void OverrideEngineDir(string path)
{
if (engineDirAccessed)
throw new InvalidOperationException("Attempted to override engine directory after it has already been accessed.");

// Note: Relative paths are interpreted as being relative to BinDir, not the current working dir.
if (!Path.IsPathRooted(path))
path = Path.Combine(BinDir, path);

if (!Directory.Exists(path))
throw new DirectoryNotFoundException(path);

if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) &&
!path.EndsWith(Path.AltDirectorySeparatorChar.ToString(), StringComparison.Ordinal))
path += Path.DirectorySeparatorChar;

engineDirAccessed = true;
engineDir = path;
}

public static string BinDir
{
get
{
Expand All @@ -194,12 +235,18 @@ public static string ResolvePath(string path)
if (path == "^EngineDir")
return EngineDir;

if (path == "^BinDir")
return BinDir;

if (path.StartsWith("^SupportDir|", StringComparison.Ordinal))
path = SupportDir + path.Substring(12);

if (path.StartsWith("^EngineDir|", StringComparison.Ordinal))
path = EngineDir + path.Substring(11);

if (path.StartsWith("^BinDir|", StringComparison.Ordinal))
path = BinDir + path.Substring(8);

return path;
}
}
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/UtilityCommands/RegisterModCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void IUtilityCommand.Run(Utility utility, string[] args)
if (args[2] == "user" || args[2] == "both")
type |= ModRegistration.User;

new ExternalMods().Register(utility.ModData.Manifest, args[1], type);
new ExternalMods().Register(utility.ModData.Manifest, args[1], Enumerable.Empty<string>(), type);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void IUtilityCommand.Run(Utility utility, string[] args)
.ToArray();

// Load the renderer assembly so we can check its dependencies
Assembly.LoadFile(Path.Combine(Platform.EngineDir, "OpenRA.Platforms.Default.dll"));
Assembly.LoadFile(Path.Combine(Platform.BinDir, "OpenRA.Platforms.Default.dll"));

var missing = new List<string>();
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
Expand Down
5 changes: 5 additions & 0 deletions OpenRA.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class Program
static void Main(string[] args)
{
var arguments = new Arguments(args);

var engineDirArg = arguments.GetValue("Engine.EngineDir", null);
if (!string.IsNullOrEmpty(engineDirArg))
Platform.OverrideEngineDir(engineDirArg);

var supportDirArg = arguments.GetValue("Engine.SupportDir", null);
if (!string.IsNullOrEmpty(supportDirArg))
Platform.OverrideSupportDir(supportDirArg);
Expand Down
4 changes: 4 additions & 0 deletions OpenRA.Utility/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class Program
{
static void Main(string[] args)
{
var engineDir = Environment.GetEnvironmentVariable("ENGINE_DIR");
if (!string.IsNullOrEmpty(engineDir))
Platform.OverrideEngineDir(engineDir);

Log.AddChannel("perf", null);
Log.AddChannel("debug", null);

Expand Down

0 comments on commit 6ad5b9e

Please sign in to comment.