public ModPackage(MiniYaml yaml) { Title = yaml.Value; FieldLoader.Load(this, yaml); }
public PlayerReference(MiniYaml my) { FieldLoader.Load(this, my); }
public Manifest(string modId, IReadOnlyPackage package) { Id = modId; Package = package; var nodes = MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml"); for (var i = nodes.Count - 1; i >= 0; i--) { if (nodes[i].Key != "Include") { continue; } // Replace `Includes: filename.yaml` with the contents of filename.yaml var filename = nodes[i].Value.Value; var contents = package.GetStream(filename); if (contents == null) { throw new YamlException($"{nodes[i].Location}: File `{filename}` not found."); } nodes.RemoveAt(i); nodes.InsertRange(i, MiniYaml.FromStream(contents, filename)); } // Merge inherited overrides yaml = new MiniYaml(null, MiniYaml.Merge(new[] { nodes })).ToDictionary(); Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]); // TODO: Use fieldloader MapFolders = YamlDictionary(yaml, "MapFolders"); if (yaml.TryGetValue("Packages", out var packages)) { Packages = packages.ToDictionary(x => x.Value); } 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); } if (yaml.ContainsKey("VideoFormats")) { VideoFormats = FieldLoader.GetValue <string[]>("VideoFormats", yaml["VideoFormats"].Value); } }
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; newData.MapFormat = r.mapformat; 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; try { newData.Preview = new Png(new MemoryStream(Convert.FromBase64String(r.minimap))); } catch (Exception e) { Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e); newData.Preview = null; } var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block)); newData.Players = new MapPlayers(MiniYaml.FromString(playersString)); var rulesString = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules)); var rulesYaml = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary(); newData.SetCustomRules(modData, this, rulesYaml); } catch (Exception e) { Log.Write("debug", "Failed parsing mapserver response: {0}", e); } // Commit updated data before running the callbacks innerData = newData; if (innerData.Preview != null) { cache.CacheMinimap(this); } parseMetadata?.Invoke(this); } // Update the status and class unconditionally innerData = newData; }
/// <summary>Initializes a map loaded from disk.</summary> public Map(string path) { 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"), path)); 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 // Use release-20141029 to convert older maps to format 6 if (MapFormat < 6) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } var nd = yaml.ToDictionary(); // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum if (MapFormat < 7) { MiniYaml useAsShellmap; if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) { Visibility = MapVisibility.Shellmap; } else if (Type == "Mission" || Type == "Campaign") { Visibility = MapVisibility.MissionSelector; } } SpawnPoints = Exts.Lazy(() => { var spawns = new List <CPos>(); foreach (var kv in ActorDefinitions.Where(d => d.Value.Value == "mpspawn")) { var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary()); spawns.Add(s.InitDict.Get <LocationInit>().Value(null)); } return(spawns.ToArray()); }); 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"); PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players"); ActorDefinitions = MiniYaml.NodesOrEmpty(yaml, "Actors"); SmudgeDefinitions = MiniYaml.NodesOrEmpty(yaml, "Smudges"); MapTiles = Exts.Lazy(LoadMapTiles); MapResources = Exts.Lazy(LoadResourceTiles); MapHeight = Exts.Lazy(LoadMapHeight); TileShape = Game.ModData.Manifest.TileShape; MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight; SubCellOffsets = Game.ModData.Manifest.SubCellOffsets; LastSubCell = (SubCell)(SubCellOffsets.Length - 1); DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex; if (Container.Exists("map.png")) { using (var dataStream = Container.GetContent("map.png")) CustomPreview = new Bitmap(dataStream); } PostInit(); // 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 < 7) { Save(path); } Uid = ComputeHash(); }
public TerrainTypeInfo(MiniYaml my) { FieldLoader.Load(this, my); }
public Manifest(string mod) { var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml"); yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary(); Mod = FieldLoader.Load <ModMetadata>(yaml["Metadata"]); Mod.Id = mod; // TODO: Use fieldloader 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); Translations = YamlList(yaml, "Translations", true); TileSets = YamlList(yaml, "TileSets", true); ChromeMetrics = YamlList(yaml, "ChromeMetrics", true); Missions = YamlList(yaml, "Missions", true); ServerTraits = YamlList(yaml, "ServerTraits"); if (!yaml.TryGetValue("LoadScreen", out LoadScreen)) { throw new InvalidDataException("`LoadScreen` section is not defined."); } if (!yaml.TryGetValue("LobbyDefaults", out LobbyDefaults)) { throw new InvalidDataException("`LobbyDefaults` section is not defined."); } Fonts = yaml["Fonts"].ToDictionary(my => { var nd = my.ToDictionary(); return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value))); }); RequiresMods = yaml["RequiresMods"].ToDictionary(my => my.Value); // Allow inherited mods to import parent maps. var compat = new List <string>(); compat.Add(mod); if (yaml.ContainsKey("SupportsMapsFrom")) { foreach (var c in yaml["SupportsMapsFrom"].Value.Split(',')) { compat.Add(c.Trim()); } } MapCompatibility = compat.ToArray(); if (yaml.ContainsKey("SoundFormats")) { SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value); } if (yaml.ContainsKey("SpriteFormats")) { SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value); } }
// The standard constructor for most purposes public Map(string path) { 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"), path)); 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 // Use release-20141029 to convert older maps to format 6 if (MapFormat < 6) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path)); } var nd = yaml.ToDictionary(); // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum if (MapFormat < 7) { MiniYaml useAsShellmap; if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value)) { Visibility = MapVisibility.Shellmap; } else if (Type == "Mission" || Type == "Campaign") { Visibility = MapVisibility.MissionSelector; } } // Load players foreach (var my in nd["Players"].ToDictionary().Values) { var player = new PlayerReference(my); Players.Add(player.Name, player); } Actors = Exts.Lazy(() => { var ret = new Dictionary <string, ActorReference>(); foreach (var kv in nd["Actors"].ToDictionary()) { ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary())); } return(ret); }); // Smudges Smudges = Exts.Lazy(() => { var ret = new List <SmudgeReference>(); foreach (var name in nd["Smudges"].ToDictionary().Keys) { var vals = name.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"); MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); MapHeight = Exts.Lazy(() => LoadMapHeight()); TileShape = Game.ModData.Manifest.TileShape; SubCellOffsets = Game.ModData.Manifest.SubCellOffsets; LastSubCell = (SubCell)(SubCellOffsets.Length - 1); DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex; if (Container.Exists("map.png")) { using (var dataStream = Container.GetContent("map.png")) CustomPreview = new Bitmap(dataStream); } PostInit(); // 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 < 7) { Save(path); } Uid = ComputeHash(); }
public Manifest(string modId) { var package = ModMetadata.AllMods[modId].Package; yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"))).ToDictionary(); Mod = FieldLoader.Load <ModMetadata>(yaml["Metadata"]); Mod.Id = modId; // 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"); 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"); Translations = YamlList(yaml, "Translations"); TileSets = YamlList(yaml, "TileSets"); ChromeMetrics = YamlList(yaml, "ChromeMetrics"); Missions = YamlList(yaml, "Missions"); ServerTraits = YamlList(yaml, "ServerTraits"); if (!yaml.TryGetValue("LoadScreen", out LoadScreen)) { throw new InvalidDataException("`LoadScreen` section is not defined."); } Fonts = yaml["Fonts"].ToDictionary(my => { var nd = my.ToDictionary(); return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value))); }); RequiresMods = yaml["RequiresMods"].ToDictionary(my => my.Value); // Allow inherited mods to import parent maps. var compat = new List <string> { Mod.Id }; if (yaml.ContainsKey("SupportsMapsFrom")) { compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim())); } MapCompatibility = compat.ToArray(); if (yaml.ContainsKey("SoundFormats")) { SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value); } if (yaml.ContainsKey("SpriteFormats")) { SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value); } }
public Manifest(string mod) { var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine); 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"); PackageContents = YamlList(yaml, "PackageContents"); LuaScripts = YamlList(yaml, "LuaScripts"); Missions = YamlList(yaml, "Missions"); LoadScreen = yaml["LoadScreen"]; LobbyDefaults = yaml["LobbyDefaults"]; if (yaml.ContainsKey("ContentInstaller")) { ContentInstaller = FieldLoader.Load <InstallData>(yaml["ContentInstaller"]); } Fonts = yaml["Fonts"].ToDictionary(my => { var nd = my.ToDictionary(); return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value))); }); if (yaml.ContainsKey("TileSize")) { TileSize = FieldLoader.GetValue <Size>("TileSize", yaml["TileSize"].Value); } if (yaml.ContainsKey("TileShape")) { TileShape = FieldLoader.GetValue <TileShape>("TileShape", yaml["TileShape"].Value); } // Allow inherited mods to import parent maps. var compat = new List <string>(); compat.Add(mod); if (yaml.ContainsKey("SupportsMapsFrom")) { foreach (var c in yaml["SupportsMapsFrom"].Value.Split(',')) { compat.Add(c.Trim()); } } MapCompatibility = compat.ToArray(); }
} /* doesn't really produce a valid map, but enough for loading a mod */ public Map(string path) { Path = path; container = FileSystem.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); 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 = MiniYaml.NodesOrEmpty(yaml, "Rules"); Sequences = MiniYaml.NodesOrEmpty(yaml, "Sequences"); VoxelSequences = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences"); Weapons = MiniYaml.NodesOrEmpty(yaml, "Weapons"); Voices = MiniYaml.NodesOrEmpty(yaml, "Voices"); Notifications = MiniYaml.NodesOrEmpty(yaml, "Notifications"); CustomTerrain = new string[MapSize.X, MapSize.Y]; MapTiles = Lazy.New(() => LoadMapTiles()); MapResources = Lazy.New(() => LoadResourceTiles()); }
public Manifest(string mod) { var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml"); yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary(); Mod = FieldLoader.Load <ModMetadata>(yaml["Metadata"]); Mod.Id = mod; // TODO: Use fieldloader 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); Translations = YamlList(yaml, "Translations", true); TileSets = YamlList(yaml, "TileSets", true); ChromeMetrics = YamlList(yaml, "ChromeMetrics", true); Missions = YamlList(yaml, "Missions", true); ServerTraits = YamlList(yaml, "ServerTraits"); if (!yaml.TryGetValue("LoadScreen", out LoadScreen)) { throw new InvalidDataException("`LoadScreen` section is not defined."); } if (!yaml.TryGetValue("LobbyDefaults", out LobbyDefaults)) { throw new InvalidDataException("`LobbyDefaults` section is not defined."); } Fonts = yaml["Fonts"].ToDictionary(my => { var nd = my.ToDictionary(); return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value))); }); if (yaml.ContainsKey("TileSize")) { TileSize = FieldLoader.GetValue <Size>("TileSize", yaml["TileSize"].Value); } if (yaml.ContainsKey("TileShape")) { TileShape = FieldLoader.GetValue <TileShape>("TileShape", yaml["TileShape"].Value); } if (yaml.ContainsKey("SubCells")) { var subcells = yaml["SubCells"].ToDictionary(); // Read (x,y,z) offset (relative to cell center) pairs for positioning subcells if (subcells.ContainsKey("Offsets")) { SubCellOffsets = FieldLoader.GetValue <WVec[]>("Offsets", subcells["Offsets"].Value); } if (subcells.ContainsKey("DefaultIndex")) { SubCellDefaultIndex = FieldLoader.GetValue <int>("DefaultIndex", subcells["DefaultIndex"].Value); } else // Otherwise set the default subcell index to the middle subcell entry { SubCellDefaultIndex = SubCellOffsets.Length / 2; } } // Validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1) if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length) { throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); } // Allow inherited mods to import parent maps. var compat = new List <string>(); compat.Add(mod); if (yaml.ContainsKey("SupportsMapsFrom")) { foreach (var c in yaml["SupportsMapsFrom"].Value.Split(',')) { compat.Add(c.Trim()); } } MapCompatibility = compat.ToArray(); if (yaml.ContainsKey("SpriteFormats")) { SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value); } }
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); } }
public MapGrid(MiniYaml yaml) { FieldLoader.Load(this, yaml); // The default subcell index defaults to the middle entry var defaultSubCellIndex = (byte)DefaultSubCell; if (defaultSubCellIndex == byte.MaxValue) { DefaultSubCell = (SubCell)(SubCellOffsets.Length / 2); } else { var minSubCellOffset = SubCellOffsets.Length > 1 ? 1 : 0; if (defaultSubCellIndex < minSubCellOffset || defaultSubCellIndex >= SubCellOffsets.Length) { throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); } } // Rotation axes and amounts for the different slope types var southEast = new WVec(724, 724, 0); var southWest = new WVec(-724, 724, 0); var south = new WVec(0, 1024, 0); var east = new WVec(1024, 0, 0); var forward = new WAngle(64); var backward = -forward; var halfForward = new WAngle(48); var halfBackward = -halfForward; // Slope types are hardcoded following the convention from the TS and RA2 map format Ramps = new[] { // Flat new CellRamp(Type, WRot.None), // Two adjacent corners raised by half a cell new CellRamp(Type, new WRot(southEast, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, backward), br: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southEast, forward), tl: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, forward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half), // One corner raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), br: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tr: RampCornerHeight.Half, split: RampSplit.Y), // Three corners raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), // Full tile sloped (mid corners raised by half cell, far corner by full cell) new CellRamp(Type, new WRot(south, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Full, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, forward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Full), new CellRamp(Type, new WRot(south, forward), tl: RampCornerHeight.Full, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, backward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Full, br: RampCornerHeight.Half), // Two opposite corners raised by half a cell new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.X), }; TilesByDistance = CreateTilesByDistance(); }
public ModDownload(MiniYaml yaml) { Title = yaml.Value; FieldLoader.Load(this, yaml); }
public TileTemplate(TileSet tileSet, MiniYaml my) { FieldLoader.Load(this, my); tiles = LoadTiles(tileSet, my); }
public virtual void Initialize(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
/// <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); } 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 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; try { newData.Preview = new Png(new MemoryStream(Convert.FromBase64String(r.minimap))); } catch (Exception e) { Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e); newData.Preview = null; } 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 modelSequenceDefinitions = LoadRuleSection(rulesYaml, "ModelSequences"); var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions); var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions, weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions); return(Pair.New(rules, flagged)); }); } catch (Exception e) { Log.Write("debug", "Failed parsing mapserver response: {0}", e); } // 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; }
// 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(); }