Load assets using absolute paths. Fixes #6717.

This commit is contained in:
Paul Chote
2014-10-09 08:36:24 +13:00
parent 0d0b8c1e22
commit 4f44cc1969
35 changed files with 491 additions and 458 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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