Load assets using absolute paths. Fixes #6717.
This commit is contained in:
@@ -104,20 +104,13 @@ namespace OpenRA.FileSystem
|
||||
return new Folder(filename, order);
|
||||
}
|
||||
|
||||
public static void Mount(string name)
|
||||
{
|
||||
Mount(name, null);
|
||||
}
|
||||
|
||||
public static void Mount(string name, string annotation)
|
||||
public static void Mount(string name, string annotation = null)
|
||||
{
|
||||
var optional = name.StartsWith("~");
|
||||
if (optional)
|
||||
name = name.Substring(1);
|
||||
|
||||
// paths starting with ^ are relative to the support dir
|
||||
if (name.StartsWith("^"))
|
||||
name = Platform.SupportDir + name.Substring(1);
|
||||
name = Platform.ResolvePath(name);
|
||||
|
||||
FolderPaths.Add(name);
|
||||
Action a = () => MountInner(OpenPackage(name, annotation, order++));
|
||||
|
||||
@@ -180,9 +180,9 @@ namespace OpenRA
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += GlobalFileSystem.ResolveAssembly;
|
||||
|
||||
Settings = new Settings(Platform.SupportDir + "settings.yaml", args);
|
||||
Settings = new Settings(Platform.ResolvePath("^", "settings.yaml"), args);
|
||||
|
||||
Log.LogPath = Platform.SupportDir + "Logs" + Path.DirectorySeparatorChar;
|
||||
Log.LogPath = Platform.ResolvePath("^", "Logs");
|
||||
Log.AddChannel("perf", "perf.log");
|
||||
Log.AddChannel("debug", "debug.log");
|
||||
Log.AddChannel("sync", "syncreport.log");
|
||||
@@ -208,7 +208,7 @@ namespace OpenRA
|
||||
Log.Write("geoip", "DatabaseReader failed: {0}", e);
|
||||
}
|
||||
|
||||
GlobalFileSystem.Mount("."); // Needed to access shaders
|
||||
GlobalFileSystem.Mount(Platform.GameDir); // Needed to access shaders
|
||||
var renderers = new[] { Settings.Graphics.Renderer, "Sdl2", null };
|
||||
foreach (var r in renderers)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void InitializeFonts(Manifest m)
|
||||
{
|
||||
Fonts = m.Fonts.ToDictionary(x => x.Key, x => new SpriteFont(x.Value.First, x.Value.Second));
|
||||
Fonts = m.Fonts.ToDictionary(x => x.Key, x => new SpriteFont(Platform.ResolvePath(x.Value.First), x.Value.Second));
|
||||
}
|
||||
|
||||
internal IGraphicsDevice Device { get { return device; } }
|
||||
@@ -146,7 +146,7 @@ namespace OpenRA.Graphics
|
||||
var resolution = GetResolution(windowMode);
|
||||
|
||||
var renderer = Game.Settings.Server.Dedicated ? "Null" : Game.Settings.Graphics.Renderer;
|
||||
var rendererPath = Path.GetFullPath("OpenRA.Renderer.{0}.dll".F(renderer));
|
||||
var rendererPath = Platform.ResolvePath(".", "OpenRA.Renderer." + renderer + ".dll");
|
||||
|
||||
device = CreateDevice(Assembly.LoadFile(rendererPath), resolution.Width, resolution.Height, windowMode);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
@@ -55,35 +56,35 @@ namespace OpenRA
|
||||
|
||||
public Manifest(string mod)
|
||||
{
|
||||
var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
|
||||
var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml");
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();
|
||||
|
||||
Mod = FieldLoader.Load<ModMetadata>(yaml["Metadata"]);
|
||||
Mod.Id = mod;
|
||||
|
||||
// TODO: Use fieldloader
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
MapFolders = YamlDictionary(yaml, "MapFolders");
|
||||
Packages = YamlDictionary(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
VoxelSequences = YamlList(yaml, "VoxelSequences");
|
||||
Cursors = YamlList(yaml, "Cursors");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout");
|
||||
Weapons = YamlList(yaml, "Weapons");
|
||||
Voices = YamlList(yaml, "Voices");
|
||||
Notifications = YamlList(yaml, "Notifications");
|
||||
Music = YamlList(yaml, "Music");
|
||||
Movies = YamlList(yaml, "Movies");
|
||||
Translations = YamlList(yaml, "Translations");
|
||||
TileSets = YamlList(yaml, "TileSets");
|
||||
ChromeMetrics = YamlList(yaml, "ChromeMetrics");
|
||||
LuaScripts = YamlList(yaml, "LuaScripts");
|
||||
Missions = YamlList(yaml, "Missions");
|
||||
Folders = YamlList(yaml, "Folders", true);
|
||||
MapFolders = YamlDictionary(yaml, "MapFolders", true);
|
||||
Packages = YamlDictionary(yaml, "Packages", true);
|
||||
Rules = YamlList(yaml, "Rules", true);
|
||||
Sequences = YamlList(yaml, "Sequences", true);
|
||||
VoxelSequences = YamlList(yaml, "VoxelSequences", true);
|
||||
Cursors = YamlList(yaml, "Cursors", true);
|
||||
Chrome = YamlList(yaml, "Chrome", true);
|
||||
Assemblies = YamlList(yaml, "Assemblies", true);
|
||||
ChromeLayout = YamlList(yaml, "ChromeLayout", true);
|
||||
Weapons = YamlList(yaml, "Weapons", true);
|
||||
Voices = YamlList(yaml, "Voices", true);
|
||||
Notifications = YamlList(yaml, "Notifications", true);
|
||||
Music = YamlList(yaml, "Music", true);
|
||||
Movies = YamlList(yaml, "Movies", true);
|
||||
Translations = YamlList(yaml, "Translations", true);
|
||||
TileSets = YamlList(yaml, "TileSets", true);
|
||||
ChromeMetrics = YamlList(yaml, "ChromeMetrics", true);
|
||||
LuaScripts = YamlList(yaml, "LuaScripts", true);
|
||||
Missions = YamlList(yaml, "Missions", true);
|
||||
|
||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||
LoadScreen = yaml["LoadScreen"];
|
||||
LobbyDefaults = yaml["LobbyDefaults"];
|
||||
|
||||
@@ -134,20 +135,23 @@ namespace OpenRA
|
||||
SpriteFormats = FieldLoader.GetValue<string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
|
||||
}
|
||||
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key)
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key, bool parsePaths = false)
|
||||
{
|
||||
if (!yaml.ContainsKey(key))
|
||||
return new string[] { };
|
||||
|
||||
return yaml[key].ToDictionary().Keys.ToArray();
|
||||
var list = yaml[key].ToDictionary().Keys.ToArray();
|
||||
return parsePaths ? list.Select(Platform.ResolvePath).ToArray() : list;
|
||||
}
|
||||
|
||||
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key)
|
||||
static IReadOnlyDictionary<string, string> YamlDictionary(Dictionary<string, MiniYaml> yaml, string key, bool parsePaths = false)
|
||||
{
|
||||
if (!yaml.ContainsKey(key))
|
||||
return new ReadOnlyDictionary<string, string>();
|
||||
|
||||
var inner = yaml[key].ToDictionary(my => my.Value);
|
||||
Func<string, string> keySelector = parsePaths ? (Func<string, string>)Platform.ResolvePath : k => k;
|
||||
var inner = yaml[key].ToDictionary(keySelector, my => my.Value);
|
||||
|
||||
return new ReadOnlyDictionary<string, string>(inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,9 +114,7 @@ namespace OpenRA
|
||||
if (dir.StartsWith("~"))
|
||||
dir = dir.Substring(1);
|
||||
|
||||
// Paths starting with ^ are relative to the user directory
|
||||
if (dir.StartsWith("^"))
|
||||
dir = Platform.SupportDir + dir.Substring(1);
|
||||
dir = Platform.ResolvePath(dir);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
return noMaps;
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace OpenRA
|
||||
return;
|
||||
|
||||
Status = MapStatus.Downloading;
|
||||
var baseMapPath = new[] { Platform.SupportDir, "maps", Game.modData.Manifest.Mod.Id }.Aggregate(Path.Combine);
|
||||
var baseMapPath = Platform.ResolvePath("^", "maps", Game.modData.Manifest.Mod.Id);
|
||||
|
||||
// Create the map directory if it doesn't exist
|
||||
if (!Directory.Exists(baseMapPath))
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace OpenRA
|
||||
{
|
||||
public class ModMetadata
|
||||
{
|
||||
public static readonly Dictionary<string, ModMetadata> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
|
||||
public static readonly Dictionary<string, ModMetadata> AllMods = ValidateMods();
|
||||
|
||||
public string Id;
|
||||
public string Title;
|
||||
@@ -24,12 +24,16 @@ namespace OpenRA
|
||||
public string Version;
|
||||
public string Author;
|
||||
|
||||
public static Dictionary<string, ModMetadata> ValidateMods(string[] mods)
|
||||
static Dictionary<string, ModMetadata> ValidateMods()
|
||||
{
|
||||
var basePath = Platform.ResolvePath(".", "mods");
|
||||
var mods = Directory.GetDirectories(basePath)
|
||||
.Select(x => x.Substring(basePath.Length + 1));
|
||||
|
||||
var ret = new Dictionary<string, ModMetadata>();
|
||||
foreach (var m in mods)
|
||||
{
|
||||
var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine);
|
||||
var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml");
|
||||
if (!File.Exists(yamlPath))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
var filename = chooseFilename();
|
||||
var mod = Game.modData.Manifest.Mod;
|
||||
var dir = new[] { Platform.SupportDir, "Replays", mod.Id, mod.Version }.Aggregate(Path.Combine);
|
||||
var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Version);
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA
|
||||
// Namespaces from each mod assembly
|
||||
foreach (var a in manifest.Assemblies)
|
||||
{
|
||||
var asm = Assembly.LoadFile(Path.GetFullPath(a));
|
||||
var asm = Assembly.LoadFile(Platform.ResolvePath(a));
|
||||
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,40 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public static string GameDir { get { return AppDomain.CurrentDomain.BaseDirectory; } }
|
||||
|
||||
/// <summary>Replace special character prefixes with full paths</summary>
|
||||
public static string ResolvePath(string path)
|
||||
{
|
||||
// paths starting with ^ are relative to the support dir
|
||||
if (path.StartsWith("^"))
|
||||
path = SupportDir + path.Substring(1);
|
||||
|
||||
// paths starting with . are relative to the game dir
|
||||
if (path.StartsWith("./") || path.StartsWith(".\\"))
|
||||
path = GameDir + path.Substring(2);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>Replace special character prefixes with full paths</summary>
|
||||
public static string ResolvePath(params string[] path)
|
||||
{
|
||||
return ResolvePath(path.Aggregate(Path.Combine));
|
||||
}
|
||||
|
||||
/// <summary>Replace the full path prefix with the special notation characters ^ or .</summary>
|
||||
public static string UnresolvePath(string path)
|
||||
{
|
||||
if (path.StartsWith(SupportDir))
|
||||
path = "^" + path.Substring(SupportDir.Length);
|
||||
|
||||
if (path.StartsWith(GameDir))
|
||||
path = "." + path.Substring(GameDir.Length);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void ShowFatalErrorDialog()
|
||||
{
|
||||
var process = "OpenRA.CrashDialog.exe";
|
||||
|
||||
@@ -129,7 +129,8 @@ namespace OpenRA.Scripting
|
||||
.GetTypesImplementing<ScriptPlayerProperties>()
|
||||
.ToArray();
|
||||
|
||||
runtime.DoBuffer(GlobalFileSystem.Open(Path.Combine("lua", "scriptwrapper.lua")).ReadAllText(), "scriptwrapper.lua").Dispose();
|
||||
runtime.Globals["GameDir"] = Platform.GameDir;
|
||||
runtime.DoBuffer(GlobalFileSystem.Open(Platform.ResolvePath(".", "lua", "scriptwrapper.lua")).ReadAllText(), "scriptwrapper.lua").Dispose();
|
||||
tick = (LuaFunction)runtime.Globals["Tick"];
|
||||
|
||||
// Register globals
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace OpenRA.Server
|
||||
|
||||
if (Settings.Dedicated)
|
||||
{
|
||||
var motdFile = Path.Combine(Platform.SupportDir, "motd.txt");
|
||||
var motdFile = Platform.ResolvePath("^", "motd.txt");
|
||||
if (!File.Exists(motdFile))
|
||||
System.IO.File.WriteAllText(motdFile, "Welcome, have fun and good luck!");
|
||||
var motd = System.IO.File.ReadAllText(motdFile);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRA
|
||||
|
||||
public static class Log
|
||||
{
|
||||
static string LogPathPrefix = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + Path.DirectorySeparatorChar;
|
||||
static string LogPathPrefix = ".";
|
||||
public static readonly Dictionary<string, ChannelInfo> Channels = new Dictionary<string, ChannelInfo>();
|
||||
|
||||
public static string LogPath
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
static Dictionary<string, string> data = new Dictionary<string, string>();
|
||||
|
||||
public static void Initialize(string[] yaml)
|
||||
public static void Initialize(IEnumerable<string> yaml)
|
||||
{
|
||||
data = new Dictionary<string, string>();
|
||||
var metrics = yaml.Select(y => MiniYaml.FromFile(y))
|
||||
|
||||
Reference in New Issue
Block a user