public Manifest(string modId, IReadOnlyPackage package) { Id = modId; Package = package; yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml")).ToDictionary(); Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]); // TODO: Use fieldloader MapFolders = YamlDictionary(yaml, "MapFolders"); MiniYaml packages; if (yaml.TryGetValue("Packages", out packages)) { Packages = packages.ToDictionary(x => x.Value).AsReadOnly(); } Rules = YamlList(yaml, "Rules"); Sequences = YamlList(yaml, "Sequences"); ModelSequences = YamlList(yaml, "ModelSequences"); 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"); Translations = YamlList(yaml, "Translations"); TileSets = YamlList(yaml, "TileSets"); ChromeMetrics = YamlList(yaml, "ChromeMetrics"); Missions = YamlList(yaml, "Missions"); Hotkeys = YamlList(yaml, "Hotkeys"); ServerTraits = YamlList(yaml, "ServerTraits"); if (!yaml.TryGetValue("LoadScreen", out LoadScreen)) { throw new InvalidDataException("`LoadScreen` section is not defined."); } // Allow inherited mods to import parent maps. var compat = new List <string> { Id }; if (yaml.ContainsKey("SupportsMapsFrom")) { compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim())); } MapCompatibility = compat.ToArray(); if (yaml.ContainsKey("PackageFormats")) { PackageFormats = FieldLoader.GetValue <string[]>("PackageFormats", yaml["PackageFormats"].Value); } if (yaml.ContainsKey("SoundFormats")) { SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value); } if (yaml.ContainsKey("SpriteFormats")) { SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value); } }
/// <summary> /// Removes invalid mod registrations: /// * LaunchPath no longer exists /// * LaunchPath and mod id matches the active mod, but the version is different /// * Filename doesn't match internal key /// * Fails to parse as a mod registration /// </summary> internal void ClearInvalidRegistrations(ExternalMod activeMod, ModRegistration registration) { var sources = new List<string>(); if (registration.HasFlag(ModRegistration.System)) sources.Add(Platform.GetSupportDir(SupportDirType.System)); if (registration.HasFlag(ModRegistration.User)) { // User support dir may be using the modern or legacy value, or overridden by the user // Add all the possibilities and let the .Distinct() below ignore the duplicates sources.Add(Platform.GetSupportDir(SupportDirType.User)); sources.Add(Platform.GetSupportDir(SupportDirType.ModernUser)); sources.Add(Platform.GetSupportDir(SupportDirType.LegacyUser)); } var activeModKey = ExternalMod.MakeKey(activeMod); foreach (var source in sources.Distinct()) { var metadataPath = Path.Combine(source, "ModMetadata"); if (!Directory.Exists(metadataPath)) continue; foreach (var path in Directory.GetFiles(metadataPath, "*.yaml")) { string modKey = null; try { var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value; var m = FieldLoader.Load<ExternalMod>(yaml); modKey = ExternalMod.MakeKey(m); // Continue to the next entry if it is the active mod (even if the LaunchPath is bogus) if (modKey == activeModKey) continue; // Continue to the next entry if this one is valid if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey && !(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version)) continue; } catch (Exception e) { Log.Write("debug", "Failed to parse mod metadata file '{0}'", path); Log.Write("debug", e.ToString()); } // Remove from the ingame mod switcher if (Path.GetFileNameWithoutExtension(path) == modKey) mods.Remove(modKey); // Remove stale or corrupted metadata try { File.Delete(path); Log.Write("debug", "Removed invalid mod metadata file '{0}'", path); } catch (Exception e) { Log.Write("debug", "Failed to remove mod metadata file '{0}'", path); Log.Write("debug", e.ToString()); } } } }
public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassification classification, string[] mapCompatibility, MapGridType gridType) { Dictionary <string, MiniYaml> yaml; using (var yamlStream = p.GetStream("map.yaml")) { if (yamlStream == null) { throw new FileNotFoundException("Required file map.yaml not present in this map"); } yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, "map.yaml")).ToDictionary(); } Package = p; parentPackage = parent; var newData = innerData.Clone(); newData.GridType = gridType; newData.Class = classification; MiniYaml temp; if (yaml.TryGetValue("MapFormat", out temp)) { var format = FieldLoader.GetValue <int>("MapFormat", temp.Value); if (format != Map.SupportedMapFormat) { throw new InvalidDataException("Map format {0} is not supported.".F(format)); } } if (yaml.TryGetValue("Title", out temp)) { newData.Title = temp.Value; } if (yaml.TryGetValue("Categories", out temp)) { newData.Categories = FieldLoader.GetValue <string[]>("Categories", temp.Value); } if (yaml.TryGetValue("Tileset", out temp)) { newData.TileSet = temp.Value; } if (yaml.TryGetValue("Author", out temp)) { newData.Author = temp.Value; } if (yaml.TryGetValue("Bounds", out temp)) { newData.Bounds = FieldLoader.GetValue <Rectangle>("Bounds", temp.Value); } if (yaml.TryGetValue("Visibility", out temp)) { newData.Visibility = FieldLoader.GetValue <MapVisibility>("Visibility", temp.Value); } string requiresMod = string.Empty; if (yaml.TryGetValue("RequiresMod", out temp)) { requiresMod = temp.Value; } newData.Status = mapCompatibility == null || mapCompatibility.Contains(requiresMod) ? MapStatus.Available : MapStatus.Unavailable; try { // Actor definitions may change if the map format changes MiniYaml actorDefinitions; if (yaml.TryGetValue("Actors", out actorDefinitions)) { var spawns = new List <CPos>(); foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn")) { var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary()); spawns.Add(s.InitDict.Get <LocationInit>().Value(null)); } newData.SpawnPoints = spawns.ToArray(); } else { newData.SpawnPoints = new CPos[0]; } } catch (Exception) { newData.SpawnPoints = new CPos[0]; newData.Status = MapStatus.Unavailable; } try { // Player definitions may change if the map format changes MiniYaml playerDefinitions; if (yaml.TryGetValue("Players", out playerDefinitions)) { newData.Players = new MapPlayers(playerDefinitions.Nodes); newData.PlayerCount = newData.Players.Players.Count(x => x.Value.Playable); newData.SuitableForInitialMap = EvaluateUserFriendliness(newData.Players.Players); } } catch (Exception) { newData.Status = MapStatus.Unavailable; } newData.SetRulesetGenerator(modData, () => { var ruleDefinitions = LoadRuleSection(yaml, "Rules"); var weaponDefinitions = LoadRuleSection(yaml, "Weapons"); var voiceDefinitions = LoadRuleSection(yaml, "Voices"); var musicDefinitions = LoadRuleSection(yaml, "Music"); var notificationDefinitions = LoadRuleSection(yaml, "Notifications"); var sequenceDefinitions = LoadRuleSection(yaml, "Sequences"); var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions); var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions); return(Pair.New(rules, flagged)); }); if (p.Contains("map.png")) { using (var dataStream = p.GetStream("map.png")) newData.Preview = new Bitmap(dataStream); } // Assign the new data atomically innerData = newData; }
public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action <MapPreview> parseMetadata = null) { var newData = innerData.Clone(); newData.Status = status; newData.Class = MapClassification.Remote; if (status == MapStatus.DownloadAvailable) { try { var r = FieldLoader.Load <RemoteMapData>(yaml); // Map download has been disabled server side if (!r.downloading) { newData.Status = MapStatus.Unavailable; return; } newData.Title = r.title; newData.Categories = r.categories; newData.Author = r.author; newData.PlayerCount = r.players; newData.Bounds = r.bounds; newData.TileSet = r.tileset; var spawns = new CPos[r.spawnpoints.Length / 2]; for (var j = 0; j < r.spawnpoints.Length; j += 2) { spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]); } newData.SpawnPoints = spawns; newData.GridType = r.map_grid_type; newData.Preview = new Bitmap(new MemoryStream(Convert.FromBase64String(r.minimap))); var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block)); newData.Players = new MapPlayers(MiniYaml.FromString(playersString)); newData.SetRulesetGenerator(modData, () => { var rulesString = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules)); var rulesYaml = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary(); var ruleDefinitions = LoadRuleSection(rulesYaml, "Rules"); var weaponDefinitions = LoadRuleSection(rulesYaml, "Weapons"); var voiceDefinitions = LoadRuleSection(rulesYaml, "Voices"); var musicDefinitions = LoadRuleSection(rulesYaml, "Music"); var notificationDefinitions = LoadRuleSection(rulesYaml, "Notifications"); var sequenceDefinitions = LoadRuleSection(rulesYaml, "Sequences"); var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions); var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions); return(Pair.New(rules, flagged)); }); } catch (Exception) { } // Commit updated data before running the callbacks innerData = newData; if (innerData.Preview != null) { cache.CacheMinimap(this); } if (parseMetadata != null) { parseMetadata(this); } } // Update the status and class unconditionally innerData = newData; }
public PlayerReference(MiniYaml my) { FieldLoader.Load(this, my); }
public Settings(string file, Arguments args) { settingsFile = file; Sections = new Dictionary <string, object>() { { "Player", Player }, { "Game", Game }, { "Sound", Sound }, { "Graphics", Graphics }, { "Server", Server }, { "Debug", Debug }, }; // Override fieldloader to ignore invalid entries var err1 = FieldLoader.UnknownFieldAction; var err2 = FieldLoader.InvalidValueAction; try { FieldLoader.UnknownFieldAction = (s, f) => Console.WriteLine("Ignoring unknown field `{0}` on `{1}`".F(s, f.Name)); if (File.Exists(settingsFile)) { yamlCache = MiniYaml.FromFile(settingsFile, false); foreach (var yamlSection in yamlCache) { if (yamlSection.Key != null && Sections.TryGetValue(yamlSection.Key, out var settingsSection)) { LoadSectionYaml(yamlSection.Value, settingsSection); } } var keysNode = yamlCache.FirstOrDefault(n => n.Key == "Keys"); if (keysNode != null) { foreach (var node in keysNode.Value.Nodes) { if (node.Key != null) { Keys[node.Key] = FieldLoader.GetValue <Hotkey>(node.Key, node.Value.Value); } } } } // Override with commandline args foreach (var kv in Sections) { foreach (var f in kv.Value.GetType().GetFields()) { if (args.Contains(kv.Key + "." + f.Name)) { FieldLoader.LoadField(kv.Value, f.Name, args.GetValue(kv.Key + "." + f.Name, "")); } } } } finally { FieldLoader.UnknownFieldAction = err1; FieldLoader.InvalidValueAction = err2; } }
public virtual void Initialize(MiniYaml yaml) { Initialize((T)FieldLoader.GetValue(nameof(value), typeof(T), yaml.Value)); }
// Support upgrading format 5 maps to a more // recent version by defining upgradeForMod. public Map(string path, string upgradeForMod) { Path = path; Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"))); FieldLoader.Load(this, yaml); // Support for formats 1-3 dropped 2011-02-11. // Use release-20110207 to convert older maps to format 4 // Use release-20110511 to convert older maps to format 5 if (MapFormat < 5) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } // Format 5 -> 6 enforces the use of RequiresMod if (MapFormat == 5) { if (upgradeForMod == null) { throw new InvalidDataException("Map format {0} is not supported, but can be upgraded.\n File: {1}".F(MapFormat, path)); } Console.WriteLine("Upgrading {0} from Format 5 to Format 6", path); // TODO: This isn't very nice, but there is no other consistent way // of finding the mod early during the engine initialization. RequiresMod = upgradeForMod; } // Load players foreach (var kv in yaml.NodesDict["Players"].NodesDict) { var player = new PlayerReference(kv.Value); Players.Add(player.Name, player); } Actors = Exts.Lazy(() => { var ret = new Dictionary <string, ActorReference>(); foreach (var kv in yaml.NodesDict["Actors"].NodesDict) { ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict)); } return(ret); }); // Smudges Smudges = Exts.Lazy(() => { var ret = new List <SmudgeReference>(); foreach (var kv in yaml.NodesDict["Smudges"].NodesDict) { var vals = kv.Key.Split(' '); var loc = vals[1].Split(','); ret.Add(new SmudgeReference(vals[0], new int2( Exts.ParseIntegerInvariant(loc[0]), Exts.ParseIntegerInvariant(loc[1])), Exts.ParseIntegerInvariant(vals[2]))); } return(ret); }); RuleDefinitions = MiniYaml.NodesOrEmpty(yaml, "Rules"); SequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Sequences"); VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); WeaponDefinitions = MiniYaml.NodesOrEmpty(yaml, "Weapons"); VoiceDefinitions = MiniYaml.NodesOrEmpty(yaml, "Voices"); NotificationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Notifications"); TranslationDefinitions = MiniYaml.NodesOrEmpty(yaml, "Translations"); CustomTerrain = new string[MapSize.X, MapSize.Y]; MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. // TODO: this isn't very nice if (MapFormat < 6) { Save(path); } Uid = ComputeHash(); if (Container.Exists("map.png")) { CustomPreview = new Bitmap(Container.GetContent("map.png")); } PostInit(); }
public ModPackage(MiniYaml yaml) { Title = yaml.Value; FieldLoader.Load(this, yaml); }
public ModDownload(MiniYaml yaml) { Title = yaml.Value; FieldLoader.Load(this, yaml); }
internal static void Initialize(Arguments args) { Console.WriteLine("Platform is {0}", Platform.CurrentPlatform); // Special case handling of Game.Mod argument: if it matches a real filesystem path // then we use this to override the mod search path, and replace it with the mod id var modID = args.GetValue("Game.Mod", null); var explicitModPaths = new string[0]; if (modID != null && (File.Exists(modID) || Directory.Exists(modID))) { explicitModPaths = new[] { modID }; modID = Path.GetFileNameWithoutExtension(modID); } InitializeSettings(args); Log.AddChannel("perf", "perf.log"); Log.AddChannel("debug", "debug.log"); Log.AddChannel("server", "server.log"); Log.AddChannel("sound", "sound.log"); Log.AddChannel("graphics", "graphics.log"); Log.AddChannel("geoip", "geoip.log"); Log.AddChannel("irc", "irc.log"); Log.AddChannel("nat", "nat.log"); var platforms = new[] { Settings.Game.Platform, "Default", null }; foreach (var p in platforms) { if (p == null) { throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details."); } Settings.Game.Platform = p; try { var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll")); var assembly = Assembly.LoadFile(rendererPath); var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t)); if (platformType == null) { throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation."); } var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null); Renderer = new Renderer(platform, Settings.Graphics); Sound = new Sound(platform, Settings.Sound); break; } catch (Exception e) { Log.Write("graphics", "{0}", e); Console.WriteLine("Renderer initialization failed. Check graphics.log for details."); if (Renderer != null) { Renderer.Dispose(); } if (Sound != null) { Sound.Dispose(); } } } GeoIP.Initialize(); if (!Settings.Server.DiscoverNatDevices) { Settings.Server.AllowPortForward = false; } else { discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout); Settings.Server.AllowPortForward = true; } GlobalChat = new GlobalChat(); var modSearchArg = args.GetValue("Engine.ModSearchPaths", null); var modSearchPaths = modSearchArg != null? FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) : new[] { Path.Combine(".", "mods") }; Mods = new InstalledMods(modSearchPaths, explicitModPaths); Console.WriteLine("Internal mods:"); foreach (var mod in Mods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version); } var launchPath = args.GetValue("Engine.LaunchPath", Assembly.GetEntryAssembly().Location); ExternalMods = new ExternalMods(launchPath); Console.WriteLine("External mods:"); foreach (var mod in ExternalMods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); } InitializeMod(modID, args); }
public Map(string path) { Path = path; Container = FileSystem.OpenPackage(path, int.MaxValue); AssertExists("map.yaml"); AssertExists("map.bin"); var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"))); FieldLoader.Load(this, yaml); Uid = ComputeHash(); // Support for formats 1-3 dropped 2011-02-11. // Use release-20110207 to convert older maps to format 4 // Use release-20110511 to convert older maps to format 5 if (MapFormat < 5) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } // Load players foreach (var kv in yaml.NodesDict["Players"].NodesDict) { var player = new PlayerReference(kv.Value); Players.Add(player.Name, player); } Actors = Lazy.New(() => { var ret = new Dictionary <string, ActorReference>(); foreach (var kv in yaml.NodesDict["Actors"].NodesDict) { ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict)); } return(ret); }); // Smudges Smudges = Lazy.New(() => { var ret = new List <SmudgeReference>(); foreach (var kv in yaml.NodesDict["Smudges"].NodesDict) { var vals = kv.Key.Split(' '); var loc = vals[1].Split(','); ret.Add(new SmudgeReference(vals[0], new int2(int.Parse(loc[0]), int.Parse(loc[1])), int.Parse(vals[2]))); } return(ret); }); Rules = NodesOrEmpty(yaml, "Rules"); Sequences = NodesOrEmpty(yaml, "Sequences"); Weapons = NodesOrEmpty(yaml, "Weapons"); Voices = NodesOrEmpty(yaml, "Voices"); Notifications = NodesOrEmpty(yaml, "Notifications"); CustomTerrain = new string[MapSize.X, MapSize.Y]; MapTiles = Lazy.New(() => LoadMapTiles()); MapResources = Lazy.New(() => LoadResourceTiles()); }
/// <summary> /// Removes invalid mod registrations: /// * LaunchPath no longer exists /// * LaunchPath and mod id matches the active mod, but the version is different /// * Filename doesn't match internal key /// * Fails to parse as a mod registration /// </summary> internal void ClearInvalidRegistrations(ExternalMod activeMod, ModRegistration registration) { var sources = new List <string>(); if (registration.HasFlag(ModRegistration.System)) { sources.Add(Platform.SystemSupportDir); } if (registration.HasFlag(ModRegistration.User)) { sources.Add(Platform.SupportDir); } foreach (var source in sources.Distinct()) { var metadataPath = Path.Combine(source, "ModMetadata"); if (!Directory.Exists(metadataPath)) { continue; } foreach (var path in Directory.GetFiles(metadataPath, "*.yaml")) { string modKey = null; try { var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value; var m = FieldLoader.Load <ExternalMod>(yaml); modKey = ExternalMod.MakeKey(m); // Continue to the next entry if this one is valid if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey && !(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version)) { continue; } } catch (Exception e) { Log.Write("debug", "Failed to parse mod metadata file '{0}'", path); Log.Write("debug", e.ToString()); } // Remove from the ingame mod switcher if (Path.GetFileNameWithoutExtension(path) == modKey) { mods.Remove(modKey); } // Remove stale or corrupted metadata try { File.Delete(path); Log.Write("debug", "Removed invalid mod metadata file '{0}'", path); } catch (Exception e) { Log.Write("debug", "Failed to remove mod metadata file '{0}'", path); Log.Write("debug", e.ToString()); } } } }
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
public virtual void Initialize(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
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); } Console.WriteLine("Platform is {0}", Platform.CurrentPlatform); // Load the engine version as early as possible so it can be written to exception logs try { EngineVersion = File.ReadAllText(Path.Combine(Platform.EngineDir, "VERSION")).Trim(); } catch { } if (string.IsNullOrEmpty(EngineVersion)) { EngineVersion = "Unknown"; } Console.WriteLine("Engine version is {0}", EngineVersion); Console.WriteLine("Runtime: {0}", Platform.RuntimeVersion); // Special case handling of Game.Mod argument: if it matches a real filesystem path // then we use this to override the mod search path, and replace it with the mod id var modID = args.GetValue("Game.Mod", null); var explicitModPaths = new string[0]; if (modID != null && (File.Exists(modID) || Directory.Exists(modID))) { explicitModPaths = new[] { modID }; modID = Path.GetFileNameWithoutExtension(modID); } InitializeSettings(args); Log.AddChannel("perf", "perf.log"); Log.AddChannel("debug", "debug.log"); Log.AddChannel("server", "server.log", true); Log.AddChannel("sound", "sound.log"); Log.AddChannel("graphics", "graphics.log"); Log.AddChannel("geoip", "geoip.log"); Log.AddChannel("nat", "nat.log"); Log.AddChannel("client", "client.log"); var platforms = new[] { Settings.Game.Platform, "Default", null }; foreach (var p in platforms) { if (p == null) { throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details."); } Settings.Game.Platform = p; try { var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + p + ".dll"); #if !MONO var loader = new AssemblyLoader(rendererPath); var platformType = loader.LoadDefaultAssembly().GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t)); #else var assembly = Assembly.LoadFile(rendererPath); var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t)); #endif if (platformType == null) { throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation."); } var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null); Renderer = new Renderer(platform, Settings.Graphics); Sound = new Sound(platform, Settings.Sound); break; } catch (Exception e) { Log.Write("graphics", "{0}", e); Console.WriteLine("Renderer initialization failed. Check graphics.log for details."); Renderer?.Dispose(); Sound?.Dispose(); } } Nat.Initialize(); var modSearchArg = args.GetValue("Engine.ModSearchPaths", null); var modSearchPaths = modSearchArg != null? FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) : new[] { Path.Combine(Platform.EngineDir, "mods") }; Mods = new InstalledMods(modSearchPaths, explicitModPaths); Console.WriteLine("Internal mods:"); foreach (var mod in Mods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version); } modLaunchWrapper = args.GetValue("Engine.LaunchWrapper", null); ExternalMods = new ExternalMods(); if (modID != null && Mods.TryGetValue(modID, out _)) { 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 != null && launchPath.First() == '"' && launchPath.Last() == '"') { launchPath = launchPath.Substring(1, launchPath.Length - 2); } 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); } } Console.WriteLine("External mods:"); foreach (var mod in ExternalMods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); } InitializeMod(modID, args); Ui.InitializeTranslation(); }
static void Initialize(Arguments args) { Console.WriteLine("Platform is {0}", Platform.CurrentPlatform); // Load the engine version as early as possible so it can be written to exception logs try { EngineVersion = File.ReadAllText(Platform.ResolvePath(Path.Combine(".", "VERSION"))).Trim(); } catch { } if (string.IsNullOrEmpty(EngineVersion)) { EngineVersion = "Unknown"; } Console.WriteLine("Engine version is {0}", EngineVersion); // Special case handling of Game.Mod argument: if it matches a real filesystem path // then we use this to override the mod search path, and replace it with the mod id var modID = args.GetValue("Game.Mod", null); var explicitModPaths = new string[0]; if (modID != null && (File.Exists(modID) || Directory.Exists(modID))) { explicitModPaths = new[] { modID }; modID = Path.GetFileNameWithoutExtension(modID); } InitializeSettings(args); Log.AddChannel("perf", "perf.log"); Log.AddChannel("debug", "debug.log"); Log.AddChannel("server", "server.log"); Log.AddChannel("sound", "sound.log"); Log.AddChannel("graphics", "graphics.log"); Log.AddChannel("geoip", "geoip.log"); Log.AddChannel("irc", "irc.log"); Log.AddChannel("nat", "nat.log"); var platforms = new[] { Settings.Game.Platform, "Default", null }; foreach (var p in platforms) { if (p == null) { throw new InvalidOperationException("Failed to initialize platform-integration library. Check graphics.log for details."); } Settings.Game.Platform = p; try { var rendererPath = Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms." + p + ".dll")); var assembly = Assembly.LoadFile(rendererPath); var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t)); if (platformType == null) { throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation."); } var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null); Renderer = new Renderer(platform, Settings.Graphics); Sound = new Sound(platform, Settings.Sound); break; } catch (Exception e) { Log.Write("graphics", "{0}", e); Console.WriteLine("Renderer initialization failed. Check graphics.log for details."); if (Renderer != null) { Renderer.Dispose(); } if (Sound != null) { Sound.Dispose(); } } } GeoIP.Initialize(); if (Settings.Server.DiscoverNatDevices) { discoverNat = UPnP.DiscoverNatDevices(Settings.Server.NatDiscoveryTimeout); } var modSearchArg = args.GetValue("Engine.ModSearchPaths", null); var modSearchPaths = modSearchArg != null? FieldLoader.GetValue <string[]>("Engine.ModsPath", modSearchArg) : new[] { Path.Combine(".", "mods") }; Mods = new InstalledMods(modSearchPaths, explicitModPaths); Console.WriteLine("Internal mods:"); foreach (var mod in Mods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Metadata.Title, mod.Value.Metadata.Version); } ExternalMods = new ExternalMods(); Manifest currentMod; if (modID != null && Mods.TryGetValue(modID, out currentMod)) { var launchPath = args.GetValue("Engine.LaunchPath", Assembly.GetEntryAssembly().Location); // Sanitize input from platform-specific launchers // Process.Start requires paths to not be quoted, even if they contain spaces if (launchPath.First() == '"' && launchPath.Last() == '"') { launchPath = launchPath.Substring(1, launchPath.Length - 2); } ExternalMods.Register(Mods[modID], launchPath, ModRegistration.User); ExternalMod activeMod; if (ExternalMods.TryGetValue(ExternalMod.MakeKey(Mods[modID]), out activeMod)) { ExternalMods.ClearInvalidRegistrations(activeMod, ModRegistration.User); } } Console.WriteLine("External mods:"); foreach (var mod in ExternalMods) { Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version); } InitializeMod(modID, args); }