public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; cursors = new Dictionary<string, CursorSequence>(); palettes = new Cache<string, PaletteReference>(CreatePaletteReference); var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); var shadowIndex = new int[] { }; var nodesDict = sequences.ToDictionary(); if (nodesDict.ContainsKey("ShadowIndex")) { Array.Resize(ref shadowIndex, shadowIndex.Length + 1); Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value, out shadowIndex[shadowIndex.Length - 1]); } palette = new HardwarePalette(); foreach (var p in nodesDict["Palettes"].Nodes) palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed)); foreach (var s in nodesDict["Cursors"].Nodes) LoadSequencesForCursor(spriteLoader, s.Key, s.Value); spriteLoader.SheetBuilder.Current.ReleaseBuffer(); palette.Initialize(); }
static object LoadVersus(MiniYaml y) { var nd = y.ToDictionary(); return nd.ContainsKey("Versus") ? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value)) : new Dictionary<string, float>(); }
private static MiniYaml FlipFacings(MiniYaml info) { var d = info.ToDictionary(); if (!LoadField(d, "FlipFacings", false)) { return(info); } var source = info.Value; info.Value = null; var frames = LoadField <int[]>(d, "Frames", null); info.Nodes.Remove(info.Nodes.First(node => node.Key == "Frames")); var combine = "Combine:\n"; for (var i = 0; i < frames.Length; i++) { combine += "\t" + source + ":\n\t\tStart:" + frames[i] + "\n\t\tAddExtension:false\n"; } for (var i = frames.Length - 2; i > 0; i--) { combine += "\t" + source + ":\n\t\tStart:" + frames[i] + "\n\t\tAddExtension:false\n\t\tFlipX:true\n"; } info.Nodes.Add(MiniYaml.FromString(combine)[0]); return(info); }
internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package) { if (package == null) { return; } var yamlStream = package.GetStream("map.yaml"); if (yamlStream == null) { return; } var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name)); var nd = yaml.ToDictionary(); var mapFormat = FieldLoader.GetValue <int>("MapFormat", nd["MapFormat"].Value); if (mapFormat < 11) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name)); } if (mapFormat < Map.SupportedMapFormat) { yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString()); Console.WriteLine("Converted {0} to MapFormat {1}.", package.Name, Map.SupportedMapFormat); } package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); }
public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; cursors = new Dictionary <string, CursorSequence>(); palettes = new Cache <string, PaletteReference>(CreatePaletteReference); var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); var shadowIndex = new int[] { }; var nodesDict = sequences.ToDictionary(); if (nodesDict.ContainsKey("ShadowIndex")) { Array.Resize(ref shadowIndex, shadowIndex.Length + 1); Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value, out shadowIndex[shadowIndex.Length - 1]); } palette = new HardwarePalette(); foreach (var p in nodesDict["Palettes"].Nodes) { palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); } var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed)); foreach (var s in nodesDict["Cursors"].Nodes) { LoadSequencesForCursor(spriteLoader, s.Key, s.Value); } spriteLoader.SheetBuilder.Current.ReleaseBuffer(); palette.Initialize(); }
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info) { sprites = loader.LoadAllSprites(cursorSrc); var d = info.ToDictionary(); start = Exts.ParseIntegerInvariant(d["start"].Value); this.palette = palette; if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*")) { length = sprites.Length - start; } else if (d.ContainsKey("length")) { length = Exts.ParseIntegerInvariant(d["length"].Value); } else if (d.ContainsKey("end")) { length = Exts.ParseIntegerInvariant(d["end"].Value) - start; } else { length = 1; } if (d.ContainsKey("x")) { Exts.TryParseIntegerInvariant(d["x"].Value, out Hotspot.X); } if (d.ContainsKey("y")) { Exts.TryParseIntegerInvariant(d["y"].Value, out Hotspot.Y); } }
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 = Platform.ResolvePath(".", "mods", m, "mod.yaml"); if (!File.Exists(yamlPath)) continue; var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath)); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) continue; var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]); mod.Id = m; ret.Add(m, mod); } return ret; }
public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); var shadowIndex = new int[] { }; var nodesDict = sequences.ToDictionary(); if (nodesDict.ContainsKey("ShadowIndex")) { Array.Resize(ref shadowIndex, shadowIndex.Length + 1); Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value, out shadowIndex[shadowIndex.Length - 1]); } var palettes = new Dictionary<string, ImmutablePalette>(); foreach (var p in nodesDict["Palettes"].Nodes) palettes.Add(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex)); Palettes = palettes.AsReadOnly(); var frameCache = new FrameCache(modData.SpriteLoaders); var cursors = new Dictionary<string, CursorSequence>(); foreach (var s in nodesDict["Cursors"].Nodes) foreach (var sequence in s.Value.Nodes) cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value)); Cursors = cursors.AsReadOnly(); }
static Dictionary<string, string[]> Load(MiniYaml y, string name) { var nd = y.ToDictionary(); return nd.ContainsKey(name) ? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value)) : new Dictionary<string, string[]>(); }
public MusicInfo(string key, MiniYaml value) { Title = value.Value; var nd = value.ToDictionary(); if (nd.ContainsKey("Hidden")) { bool.TryParse(nd["Hidden"].Value, out Hidden); } var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud"; Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext; if (!GlobalFileSystem.Exists(Filename)) { return; } Exists = true; using (var s = GlobalFileSystem.Open(Filename)) { if (Filename.ToLowerInvariant().EndsWith("wav")) { Length = (int)WavLoader.WaveLength(s); } else { Length = (int)AudLoader.SoundLength(s); } } }
public static object LoadInitialSmudges(MiniYaml yaml) { MiniYaml smudgeYaml; var nd = yaml.ToDictionary(); var smudges = new Dictionary <CPos, MapSmudge>(); if (nd.TryGetValue("InitialSmudges", out smudgeYaml)) { foreach (var node in smudgeYaml.Nodes) { try { var cell = FieldLoader.GetValue <CPos>("key", node.Key); var parts = node.Value.Value.Split(','); var type = parts[0]; var depth = FieldLoader.GetValue <int>("depth", parts[1]); smudges.Add(cell, new MapSmudge { Type = type, Depth = depth }); } catch { } } } return(smudges); }
public TerrainTemplateInfo(TileSet tileSet, MiniYaml my) { FieldLoader.Load(this, my); var nodes = my.ToDictionary()["Tiles"].Nodes; if (!PickAny) { tileInfo = new TerrainTileInfo[Size.X * Size.Y]; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key < 0 || key >= tileInfo.Length) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tileInfo[key] = LoadTileInfo(tileSet, node.Value); } } else { tileInfo = new TerrainTileInfo[nodes.Count]; var i = 0; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key != i++) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tileInfo[key] = LoadTileInfo(tileSet, node.Value); } } }
public static object LoadWeaponSequences(MiniYaml yaml) { var md = yaml.ToDictionary(); return(md.ContainsKey("AttackSequences") ? md["AttackSequences"].ToDictionary(my => FieldLoader.GetValue <string>("(value)", my.Value)) : new Dictionary <string, string>()); }
public static object LoadDeathTypes(MiniYaml yaml) { var md = yaml.ToDictionary(); return(md.ContainsKey("DeathTypes") ? md["DeathTypes"].ToDictionary(my => FieldLoader.GetValue <int>("(value)", my.Value)) : new Dictionary <string, int>()); }
static object LoadUpgrades(MiniYaml y) { MiniYaml upgrades = y.ToDictionary()["Upgrades"]; return(upgrades.Nodes.ToDictionary( kv => FieldLoader.GetValue <int>("(key)", kv.Key), kv => FieldLoader.GetValue <string[]>("(value)", kv.Value.Value))); }
public static Dictionary<string, string[]> LoadFilesToExtract(MiniYaml yaml) { var md = yaml.ToDictionary(); return md.ContainsKey("ExtractFilesFromCD") ? md["ExtractFilesFromCD"].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value)) : new Dictionary<string, string[]>(); }
public static Dictionary <string, string[]> LoadFilesToCopy(MiniYaml yaml) { var md = yaml.ToDictionary(); return(md.ContainsKey("CopyFilesFromCD") ? md["CopyFilesFromCD"].ToDictionary(my => FieldLoader.GetValue <string[]>("(value)", my.Value)) : new Dictionary <string, string[]>()); }
public static object LoadVersus(MiniYaml yaml) { var nd = yaml.ToDictionary(); return(nd.ContainsKey("Versus") ? nd["Versus"].ToDictionary(my => FieldLoader.GetValue <int>("(value)", my.Value)) : new Dictionary <string, int>()); }
static Dictionary <string, string[]> Load(MiniYaml y, string name) { var nd = y.ToDictionary(); return(nd.ContainsKey(name) ? nd[name].ToDictionary(my => FieldLoader.GetValue <string[]>("(value)", my.Value)) : new Dictionary <string, string[]>()); }
static object LoadList <T>(MiniYaml y, string field) { var nd = y.ToDictionary(); return(nd.ContainsKey(field) ? nd[field].ToDictionary(my => FieldLoader.GetValue <T>(field, my.Value)) : new Dictionary <string, T>()); }
static object LoadProjectile(MiniYaml yaml) { MiniYaml proj; if (!yaml.ToDictionary().TryGetValue("Projectile", out proj)) return null; var ret = Game.CreateObject<IProjectileInfo>(proj.Value + "Info"); FieldLoader.Load(ret, proj); return ret; }
static void LoadVoxelsForUnit(string unit, MiniYaml sequences) { Game.ModData.LoadScreen.Display(); try { var seq = sequences.ToDictionary(my => LoadVoxel(unit, my)); units.Add(unit, seq); } catch (FileNotFoundException) { } // Do nothing; we can crash later if we actually wanted art }
static void LoadVoxelsForUnit(string unit, MiniYaml sequences) { Game.modData.LoadScreen.Display(); try { var seq = sequences.ToDictionary(my => LoadVoxel(unit, my)); units.Add(unit, seq); } catch (FileNotFoundException) {} // Do nothing; we can crash later if we actually wanted art }
public MusicInfo(string key, MiniYaml value) { Title = value.Value; var nd = value.ToDictionary(); if (nd.ContainsKey("Hidden")) bool.TryParse(nd["Hidden"].Value, out Hidden); var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud"; Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext; }
protected static object LoadRaceImages(MiniYaml y) { MiniYaml images; if (!y.ToDictionary().TryGetValue("RaceImages", out images)) { return(null); } return(images.Nodes.ToDictionary(kv => kv.Key, kv => kv.Value.Value)); }
static object LoadProjectile(MiniYaml yaml) { if (!yaml.ToDictionary().TryGetValue("Projectile", out var proj)) { return(null); } var ret = Game.CreateObject <IProjectileInfo>(proj.Value + "Info"); FieldLoader.Load(ret, proj); return(ret); }
static object LoadPercents(MiniYaml y) { MiniYaml percents; if (!y.ToDictionary().TryGetValue("TerrainModifier", out percents)) { return(new Dictionary <string, int>()); } return(percents.Nodes.ToDictionary( kv => FieldLoader.GetValue <string>("(key)", kv.Key), kv => FieldLoader.GetValue <int>("(value)", kv.Value.Value))); }
static object LoadUpgrades(MiniYaml y) { MiniYaml upgrades; if (!y.ToDictionary().TryGetValue("Upgrades", out upgrades)) { return(new Dictionary <string, string[]>()); } return(upgrades.Nodes.ToDictionary( kv => kv.Key, kv => FieldLoader.GetValue <string[]>("(value)", kv.Value.Value))); }
public ClassicSpriteSequence(ModData modData, string tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) : base(modData, tileSet, cache, loader, sequence, animation, info) { var d = info.ToDictionary(); useClassicFacings = LoadField(d, "UseClassicFacings", false); if (useClassicFacings && Facings != 32) { throw new InvalidOperationException( $"{info.Nodes[0].Location}: Sequence {sequence}.{animation}: UseClassicFacings is only valid for 32 facings"); } }
static object LoadSpeeds(MiniYaml y) { var ret = new Dictionary <string, TerrainInfo>(); foreach (var t in y.ToDictionary()["TerrainSpeeds"].Nodes) { var speed = FieldLoader.GetValue <int>("speed", t.Value.Value); var nodesDict = t.Value.ToDictionary(); var cost = nodesDict.ContainsKey("PathingCost") ? FieldLoader.GetValue <int>("cost", nodesDict["PathingCost"].Value) : 1000 / speed; ret.Add(t.Key, new TerrainInfo(speed, cost)); } return(ret); }
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits ) { MiniYaml inherits; node.ToDictionary().TryGetValue( "Inherits", out inherits ); if( inherits == null || string.IsNullOrEmpty( inherits.Value ) ) return null; MiniYaml parent; allUnits.TryGetValue( inherits.Value, out parent ); if (parent == null) throw new InvalidOperationException( "Bogus inheritance -- actor type {0} does not exist".F(inherits.Value)); return parent; }
public MusicInfo(string key, MiniYaml value) { Title = value.Value; var nd = value.ToDictionary(); var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud"; Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext; if (!GlobalFileSystem.Exists(Filename)) { return; } Exists = true; using (var s = GlobalFileSystem.Open(Filename)) Length = (int)AudLoader.SoundLength(s); }
public TerrainTemplateInfo(ITerrainInfo terrainInfo, MiniYaml my) { FieldLoader.Load(this, my); var nodes = my.ToDictionary()["Tiles"].Nodes; if (!PickAny) { tileInfo = new TerrainTileInfo[Size.X * Size.Y]; foreach (var node in nodes) { if (!int.TryParse(node.Key, out var key)) { throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` defines a frame `{node.Key}` that is not a valid integer."); } if (key < 0 || key >= tileInfo.Length) { throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` references frame {key}, but only [0..{tileInfo.Length - 1}] are valid for a {Size.X}x{Size.Y} Size template."); } tileInfo[key] = LoadTileInfo(terrainInfo, node.Value); } } else { tileInfo = new TerrainTileInfo[nodes.Count]; var i = 0; foreach (var node in nodes) { if (!int.TryParse(node.Key, out var key)) { throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` defines a frame `{node.Key}` that is not a valid integer."); } if (key != i++) { throw new YamlException($"Tileset `{terrainInfo.Id}` template `{Id}` is missing a definition for frame {i - 1}."); } tileInfo[key] = LoadTileInfo(terrainInfo, node.Value); } } }
public CursorSequence(FrameCache cache, string name, string cursorSrc, string palette, MiniYaml info) { var d = info.ToDictionary(); Start = Exts.ParseIntegerInvariant(d["Start"].Value); Palette = palette; Name = name; if ((d.ContainsKey("Length") && d["Length"].Value == "*") || (d.ContainsKey("End") && d["End"].Value == "*")) { Length = Frames.Length - Start; } else if (d.ContainsKey("Length")) { Length = Exts.ParseIntegerInvariant(d["Length"].Value); } else if (d.ContainsKey("End")) { Length = Exts.ParseIntegerInvariant(d["End"].Value) - Start; } else { Length = 1; } Frames = cache[cursorSrc] .Skip(Start) .Take(Length) .ToArray(); if (d.ContainsKey("X")) { int x; Exts.TryParseIntegerInvariant(d["X"].Value, out x); Hotspot = Hotspot.WithX(x); } if (d.ContainsKey("Y")) { int y; Exts.TryParseIntegerInvariant(d["Y"].Value, out y); Hotspot = Hotspot.WithY(y); } }
static object LoadUpgrades(MiniYaml y) { MiniYaml upgrades; if (!y.ToDictionary().TryGetValue("Upgrades", out upgrades)) { return(new Dictionary <int, string[]>() { { 200, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, { 400, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, { 800, new[] { "firepower", "damage", "speed", "reload", "inaccuracy" } }, { 1600, new[] { "firepower", "damage", "speed", "reload", "inaccuracy", "selfheal" } } }); } return(upgrades.Nodes.ToDictionary( kv => FieldLoader.GetValue <int>("(key)", kv.Key), kv => FieldLoader.GetValue <string[]>("(value)", kv.Value.Value))); }
public MusicInfo(string key, MiniYaml value) { Title = value.Value; var nd = value.ToDictionary(); if (nd.ContainsKey("Hidden")) { bool.TryParse(nd["Hidden"].Value, out Hidden); } if (nd.ContainsKey("VolumeModifier")) { VolumeModifier = FieldLoader.GetValue <float>("VolumeModifier", nd["VolumeModifier"].Value); } var ext = nd.ContainsKey("Extension") ? nd["Extension"].Value : "aud"; Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext; }
public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; var partial = sequenceFiles .Select(s => MiniYaml.FromFile(s)) .Aggregate(MiniYaml.MergePartial); var sequences = new MiniYaml(null, MiniYaml.ApplyRemovals(partial)); var shadowIndex = new int[] { }; var nodesDict = sequences.ToDictionary(); if (nodesDict.ContainsKey("ShadowIndex")) { Array.Resize(ref shadowIndex, shadowIndex.Length + 1); Exts.TryParseIntegerInvariant(nodesDict["ShadowIndex"].Value, out shadowIndex[shadowIndex.Length - 1]); } var palettes = new Dictionary <string, ImmutablePalette>(); foreach (var p in nodesDict["Palettes"].Nodes) { palettes.Add(p.Key, new ImmutablePalette(modData.ModFiles.Open(p.Value.Value), shadowIndex)); } Palettes = palettes.AsReadOnly(); var frameCache = new FrameCache(modData.SpriteLoaders); var cursors = new Dictionary <string, CursorSequence>(); foreach (var s in nodesDict["Cursors"].Nodes) { foreach (var sequence in s.Value.Nodes) { cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value)); } } Cursors = cursors.AsReadOnly(); }
public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info) { sprites = loader.LoadAllSprites(cursorSrc); var d = info.ToDictionary(); start = Exts.ParseIntegerInvariant(d["start"].Value); this.palette = palette; if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*")) length = sprites.Length - start; else if (d.ContainsKey("length")) length = Exts.ParseIntegerInvariant(d["length"].Value); else if (d.ContainsKey("end")) length = Exts.ParseIntegerInvariant(d["end"].Value) - start; else length = 1; if (d.ContainsKey("x")) Exts.TryParseIntegerInvariant(d["x"].Value, out Hotspot.X); if (d.ContainsKey("y")) Exts.TryParseIntegerInvariant(d["y"].Value, out Hotspot.Y); }
public static Dictionary<string, ModMetadata> ValidateMods(string[] mods) { var ret = new Dictionary<string, ModMetadata>(); foreach (var m in mods) { var yamlPath = new[] { "mods", m, "mod.yaml" }.Aggregate(Path.Combine); if (!File.Exists(yamlPath)) continue; var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath)); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) continue; var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]); mod.Id = m; ret.Add(m, mod); } return ret; }
int[] LoadTiles(TileSet tileSet, MiniYaml y) { var nodes = y.ToDictionary()["Tiles"].Nodes; if (!PickAny) { var tiles = new int[Size.X * Size.Y]; for (var i = 0; i < tiles.Length; i++) tiles[i] = -1; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key < 0 || key >= tiles.Length) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tiles[key] = tileSet.GetTerrainIndex(node.Value.Value); } return tiles; } else { var tiles = new int[nodes.Count]; var i = 0; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key != i++) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tiles[key] = tileSet.GetTerrainIndex(node.Value.Value); } return tiles; } }
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) { try { var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml"); if (!File.Exists(yamlPath)) continue; var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath)); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) continue; var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]); mod.Id = m; if (nd.ContainsKey("ContentInstaller")) mod.Content = FieldLoader.Load<ContentInstaller>(nd["ContentInstaller"]); ret.Add(m, mod); } catch (Exception ex) { Console.WriteLine("An exception occured when trying to load ModMetadata for `{0}`:".F(m)); Console.WriteLine(ex.Message); } } return ret; }
public CursorSequence(FrameCache cache, string name, string cursorSrc, string palette, MiniYaml info) { var d = info.ToDictionary(); Start = Exts.ParseIntegerInvariant(d["Start"].Value); Palette = palette; Name = name; if ((d.ContainsKey("Length") && d["Length"].Value == "*") || (d.ContainsKey("End") && d["End"].Value == "*")) Length = Frames.Length - Start; else if (d.ContainsKey("Length")) Length = Exts.ParseIntegerInvariant(d["Length"].Value); else if (d.ContainsKey("End")) Length = Exts.ParseIntegerInvariant(d["End"].Value) - Start; else Length = 1; Frames = cache[cursorSrc] .Skip(Start) .Take(Length) .ToArray(); if (d.ContainsKey("X")) { int x; Exts.TryParseIntegerInvariant(d["X"].Value, out x); Hotspot = Hotspot.WithX(x); } if (d.ContainsKey("Y")) { int y; Exts.TryParseIntegerInvariant(d["Y"].Value, out y); Hotspot = Hotspot.WithY(y); } }
protected static object LoadRaceImages(MiniYaml y) { MiniYaml images; if (!y.ToDictionary().TryGetValue("RaceImages", out images)) return null; return images.Nodes.ToDictionary(kv => kv.Key, kv => kv.Value.Value); }
public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) { Name = animation; Loader = loader; //Console.WriteLine("Sequence:" + sequence + " animation:" + animation); var d = info.ToDictionary(); try { Start = LoadField(d, "Start", 0); ShadowStart = LoadField(d, "ShadowStart", -1); ShadowZOffset = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length; ZOffset = LoadField(d, "ZOffset", WDist.Zero).Length; ZRamp = LoadField(d, "ZRamp", 0); Tick = LoadField(d, "Tick", 40); transpose = LoadField(d, "Transpose", false); Frames = LoadField <int[]>(d, "Frames", null); useClassicFacingFudge = LoadField(d, "UseClassicFacingFudge", false); var flipX = LoadField(d, "FlipX", false); var flipY = LoadField(d, "FlipY", false); Facings = LoadField(d, "Facings", 1); if (Facings < 0) { reverseFacings = true; Facings = -Facings; } if (useClassicFacingFudge && Facings != 32) { throw new InvalidDataException("{0}: Sequence {1}.{2}: UseClassicFacingFudge is only valid for 32 facings".F(info.Nodes[0].Location, sequence, animation)); } var offset = LoadField(d, "Offset", Vector3.Zero); var blendmode = LoadField(d, "BlendMode", BlendMode.Alpha); MiniYaml combine; if (d.TryGetValue("Combine", out combine)) { var combined = Enumerable.Empty <Sprite>(); foreach (var sub in combine.Nodes) { var sd = sub.Value.ToDictionary(); //Allow per-sprite offset,flipping,start,and length var subStart = LoadField(sd, "Start", 0); var subOffset = LoadField(sd, "Offset", Vector3.Zero); var subFlipX = LoadField(sd, "FlipX", false); var subFlipY = LoadField(sd, "FlipY", false); var subSrc = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd); var subSprites = cache[subSrc].Select(s => new Sprite(s.Sheet, FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp, new Vector3(subFlipX?-s.Offset.X:s.Offset.X, subFlipY?-s.Offset.Y:s.Offset.Y, s.Offset.Z) + subOffset + offset, s.Channel, blendmode)); var subLength = 0; MiniYaml subLengthYaml; if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*") { subLength = subSprites.Count() - subStart; } else { subLength = LoadField(sd, "Length", 1); } combined = combined.Concat(subSprites.Skip(subStart).Take(subLength)); } sprites = combined.ToArray(); } else { //Apply offset to each sprite in the sequence //Different sequences may apply different offsets to the same frame. //对序列中的每个子画面应用偏移,不同的序列可以对同一帧应用不同的偏移 var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d); sprites = cache[src].Select(s => new Sprite(s.Sheet, FlipRectangle(s.Bounds, flipX, flipY), ZRamp, new Vector3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset, s.Channel, blendmode)).ToArray(); } var depthSprite = LoadField <string>(d, "DepthSprite", null); if (!string.IsNullOrEmpty(depthSprite)) { //Console.WriteLine("DepthSprite:" + depthSprite); var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0); var depthOffset = LoadField(d, "DepthSpriteOffset", Vector2.Zero); var depthSprites = cache.AllCached(depthSprite).Select(s => s[depthSpriteFrame]); sprites = sprites.Select(s => { //The depth sprite must be live on the same sheet as the main sprite var ds = depthSprites.FirstOrDefault(dss => dss.Sheet == s.Sheet); if (ds == null) { //The sequence has probably overflowed onto a new sheet. //Allocating a new depth sprite on this sheet will almost certainly work //该序列可能已经溢出到新的Sheet上, ds = cache.Reload(depthSprite)[depthSpriteFrame]; depthSprites = cache.AllCached(depthSprite).Select(ss => ss[depthSpriteFrame]); if (ds.Sheet != s.Sheet) { throw new SheetOverflowException("Cross-sheet depth sprite reference:{0}.{1}: {2}"); } } var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X); var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y); var w = s.Bounds.Width / 2; var h = s.Bounds.Height / 2; var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h); return(new SpriteWithSecondaryData(s, r, ds.Channel)); }).ToArray(); } MiniYaml length; if (d.TryGetValue("Length", out length) && length.Value == "*") { Length = sprites.Length - Start; } else { Length = LoadField(d, "Length", 1); } //Plays the animation forwards,and then in reverse if (LoadField(d, "Reverses", false)) { var frames = Frames ?? Exts.MakeArray(Length, i => Start + i); Frames = frames.Concat(frames.Skip(1).Take(frames.Length - 2).Reverse()).ToArray(); Length = 2 * Length - 2; } Stride = LoadField(d, "Stride", Length); if (Length > Stride) { throw new InvalidOperationException("{0}:Sequence {1}.{2}: Length must be <= Stride".F(info.Nodes[0].Location, sequence, animation)); } if (Frames != null && Length > Frames.Length) { throw new InvalidOperationException("{0}:Sequence {1}.{2}: Length must be <=Frames.Length".F(info.Nodes[0].Location, sequence, animation)); } if (Start < 0 || Start + Facings * Stride > sprites.Length) { throw new InvalidOperationException("{5}: Sequence {0}.{1} uses frames [{2}...{3}],but only 0..{4} actually exist".F(sequence, animation, Start, Start + Facings * Stride - 1, sprites.Length - 1, info.Nodes[0].Location)); } if (ShadowStart + Facings * Stride > sprites.Length) { throw new InvalidOperationException("{5}:Sequence {0}.{1}'s shadow frames use frames [{2}...{3}],but only [0..{4}] actually exist".F(sequence, animation, ShadowStart, ShadowStart + Facings * Stride - 1, sprites.Length - 1, info.Nodes[0].Location)); } var boundSprites = SpriteBounds(sprites, Frames, Start, Facings, Length); if (ShadowStart > 0) { boundSprites = boundSprites.Concat(SpriteBounds(sprites, Frames, ShadowStart, Facings, Length)); } if (boundSprites.Any()) { Bounds = boundSprites.First(); foreach (var b in boundSprites.Skip(1)) { Bounds = Rectangle.Union(Bounds, b); } } } catch (FormatException f) { throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f)); } }
public DefaultSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) { this.sequence = sequence; Name = animation; Loader = loader; var d = info.ToDictionary(); try { Start = LoadField(d, "Start", 0); ShadowStart = LoadField(d, "ShadowStart", -1); ShadowZOffset = LoadField(d, "ShadowZOffset", DefaultShadowSpriteZOffset).Length; ZOffset = LoadField(d, "ZOffset", WDist.Zero).Length; ZRamp = LoadField(d, "ZRamp", 0); Tick = LoadField(d, "Tick", 40); transpose = LoadField(d, "Transpose", false); Frames = LoadField <int[]>(d, "Frames", null); var flipX = LoadField(d, "FlipX", false); var flipY = LoadField(d, "FlipY", false); Facings = LoadField(d, "Facings", 1); if (Facings < 0) { reverseFacings = true; Facings = -Facings; } var offset = LoadField(d, "Offset", float3.Zero); var blendMode = LoadField(d, "BlendMode", BlendMode.Alpha); Func <int, IEnumerable <int> > getUsedFrames = frameCount => { MiniYaml length; if (d.TryGetValue("Length", out length) && length.Value == "*") { Length = Frames != null ? Frames.Length : frameCount - Start; } else { Length = LoadField(d, "Length", 1); } // Plays the animation forwards, and then in reverse if (LoadField(d, "Reverses", false)) { var frames = Frames != null?Frames.Skip(Start).Take(Length).ToArray() : Exts.MakeArray(Length, i => Start + i); Frames = frames.Concat(frames.Skip(1).Take(Length - 2).Reverse()).ToArray(); Length = 2 * Length - 2; Start = 0; } Stride = LoadField(d, "Stride", Length); if (Length > Stride) { throw new InvalidOperationException( "{0}: Sequence {1}.{2}: Length must be <= stride" .F(info.Nodes[0].Location, sequence, animation)); } if (Frames != null && Length > Frames.Length) { throw new InvalidOperationException( "{0}: Sequence {1}.{2}: Length must be <= Frames.Length" .F(info.Nodes[0].Location, sequence, animation)); } var end = Start + (Facings - 1) * Stride + Length - 1; if (Frames != null) { foreach (var f in Frames) { if (f < 0 || f >= frameCount) { throw new InvalidOperationException( "{5}: Sequence {0}.{1} defines a Frames override that references frame {4}, but only [{2}..{3}] actually exist" .F(sequence, animation, Start, end, f, info.Nodes[0].Location)); } } if (Start < 0 || end >= Frames.Length) { throw new InvalidOperationException( "{5}: Sequence {0}.{1} uses indices [{2}..{3}] of the Frames list, but only {4} frames are defined" .F(sequence, animation, Start, end, Frames.Length, info.Nodes[0].Location)); } } else if (Start < 0 || end >= frameCount) { throw new InvalidOperationException( "{5}: Sequence {0}.{1} uses frames [{2}..{3}], but only 0..{4} actually exist" .F(sequence, animation, Start, end, frameCount - 1, info.Nodes[0].Location)); } if (ShadowStart >= 0 && ShadowStart + (Facings - 1) * Stride + Length > frameCount) { throw new InvalidOperationException( "{5}: Sequence {0}.{1}'s shadow frames use frames [{2}..{3}], but only [0..{4}] actually exist" .F(sequence, animation, ShadowStart, ShadowStart + (Facings - 1) * Stride + Length - 1, frameCount - 1, info.Nodes[0].Location)); } var usedFrames = new List <int>(); for (var facing = 0; facing < Facings; facing++) { for (var frame = 0; frame < Length; frame++) { var i = transpose ? (frame % Length) * Facings + facing : (facing * Stride) + (frame % Length); usedFrames.Add(Frames != null ? Frames[i] : Start + i); } } if (ShadowStart >= 0) { return(usedFrames.Concat(usedFrames.Select(i => i + ShadowStart - Start))); } return(usedFrames); }; MiniYaml combine; if (d.TryGetValue("Combine", out combine)) { var combined = Enumerable.Empty <Sprite>(); foreach (var sub in combine.Nodes) { var sd = sub.Value.ToDictionary(); // Allow per-sprite offset, flipping, start, and length var subStart = LoadField(sd, "Start", 0); var subOffset = LoadField(sd, "Offset", float3.Zero); var subFlipX = LoadField(sd, "FlipX", false); var subFlipY = LoadField(sd, "FlipY", false); var subFrames = LoadField <int[]>(sd, "Frames", null); var subLength = 0; Func <int, IEnumerable <int> > subGetUsedFrames = subFrameCount => { MiniYaml subLengthYaml; if (sd.TryGetValue("Length", out subLengthYaml) && subLengthYaml.Value == "*") { subLength = subFrames != null ? subFrames.Length : subFrameCount - subStart; } else { subLength = LoadField(sd, "Length", 1); } return(subFrames != null?subFrames.Skip(subStart).Take(subLength) : Enumerable.Range(subStart, subLength)); }; var subSrc = GetSpriteSrc(modData, tileSet, sequence, animation, sub.Key, sd); var subSprites = cache[subSrc, subGetUsedFrames].Select( s => s != null ? new Sprite(s.Sheet, FlipRectangle(s.Bounds, subFlipX, subFlipY), ZRamp, new float3(subFlipX ? -s.Offset.X : s.Offset.X, subFlipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + subOffset + offset, s.Channel, blendMode) : null).ToList(); var frames = subFrames != null?subFrames.Skip(subStart).Take(subLength).ToArray() : Exts.MakeArray(subLength, i => subStart + i); combined = combined.Concat(frames.Select(i => subSprites[i])); } sprites = combined.ToArray(); getUsedFrames(sprites.Length); } else { // Apply offset to each sprite in the sequence // Different sequences may apply different offsets to the same frame var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d); sprites = cache[src, getUsedFrames].Select( s => s != null ? new Sprite(s.Sheet, FlipRectangle(s.Bounds, flipX, flipY), ZRamp, new float3(flipX ? -s.Offset.X : s.Offset.X, flipY ? -s.Offset.Y : s.Offset.Y, s.Offset.Z) + offset, s.Channel, blendMode) : null).ToArray(); } var depthSprite = LoadField <string>(d, "DepthSprite", null); if (!string.IsNullOrEmpty(depthSprite)) { var depthSpriteFrame = LoadField(d, "DepthSpriteFrame", 0); var depthOffset = LoadField(d, "DepthSpriteOffset", float2.Zero); Func <int, IEnumerable <int> > getDepthFrame = _ => new int[] { depthSpriteFrame }; var ds = cache[depthSprite, getDepthFrame][depthSpriteFrame]; sprites = sprites.Select(s => { if (s == null) { return(null); } var cw = (ds.Bounds.Left + ds.Bounds.Right) / 2 + (int)(s.Offset.X + depthOffset.X); var ch = (ds.Bounds.Top + ds.Bounds.Bottom) / 2 + (int)(s.Offset.Y + depthOffset.Y); var w = s.Bounds.Width / 2; var h = s.Bounds.Height / 2; var r = Rectangle.FromLTRB(cw - w, ch - h, cw + w, ch + h); return(new SpriteWithSecondaryData(s, ds.Sheet, r, ds.Channel)); }).ToArray(); } var exportPalette = LoadField <string>(d, "EmbeddedPalette", null); if (exportPalette != null) { var src = GetSpriteSrc(modData, tileSet, sequence, animation, info.Value, d); var metadata = cache.FrameMetadata(src); var i = Frames != null ? Frames[0] : Start; var palettes = metadata != null?metadata.GetOrDefault <EmbeddedSpritePalette>() : null; if (palettes == null || !palettes.TryGetPaletteForFrame(i, out EmbeddedPalette)) { throw new YamlException("Cannot export palettes from {0}: frame {1} does not define an embedded palette".F(src, i)); } } var boundSprites = SpriteBounds(sprites, Frames, Start, Facings, Length, Stride, transpose); if (ShadowStart > 0) { boundSprites = boundSprites.Concat(SpriteBounds(sprites, Frames, ShadowStart, Facings, Length, Stride, transpose)); } Bounds = boundSprites.Union(); } catch (FormatException f) { throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(sequence, animation, info.Nodes[0].Location, f)); } }
static object LoadPercents(MiniYaml y) { return y.ToDictionary()["TerrainModifier"].Nodes.ToDictionary( kv => FieldLoader.GetValue<string>("(key)", kv.Key), kv => FieldLoader.GetValue<int>("(value)", kv.Value.Value)); }
static Dictionary<string, ModMetadata> ValidateMods() { var ret = new Dictionary<string, ModMetadata>(); foreach (var pair in GetCandidateMods()) { IReadOnlyPackage package = null; try { if (Directory.Exists(pair.Second)) package = new Folder(pair.Second); else { try { package = new ZipFile(null, pair.Second); } catch { throw new InvalidDataException(pair.Second + " is not a valid mod package"); } } if (!package.Contains("mod.yaml")) { package.Dispose(); continue; } var yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"))); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) { package.Dispose(); continue; } var metadata = FieldLoader.Load<ModMetadata>(nd["Metadata"]); metadata.Id = pair.First; metadata.Package = package; if (nd.ContainsKey("RequiresMods")) metadata.RequiresMods = nd["RequiresMods"].ToDictionary(my => my.Value); else metadata.RequiresMods = new Dictionary<string, string>(); if (nd.ContainsKey("ContentInstaller")) metadata.Content = FieldLoader.Load<ContentInstaller>(nd["ContentInstaller"]); // Mods in the support directory and oramod packages (which are listed later // in the CandidateMods list) override mods in the main install. ret[pair.First] = metadata; } catch (Exception ex) { if (package != null) package.Dispose(); Console.WriteLine("An exception occurred when trying to load ModMetadata for `{0}`:".F(pair.First)); Console.WriteLine(ex.Message); } } return ret; }
public static object LoadInitialSmudges(MiniYaml yaml) { MiniYaml smudgeYaml; var nd = yaml.ToDictionary(); var smudges = new Dictionary<CPos, MapSmudge>(); if (nd.TryGetValue("InitialSmudges", out smudgeYaml)) { foreach (var node in smudgeYaml.Nodes) { try { var cell = FieldLoader.GetValue<CPos>("key", node.Key); var parts = node.Value.Value.Split(','); var type = parts[0]; var depth = FieldLoader.GetValue<int>("depth", parts[1]); smudges.Add(cell, new MapSmudge { Type = type, Depth = depth }); } catch { } } } return smudges; }
// 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; } var nd = yaml.ToDictionary(); // 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()); TileShape = Game.modData.Manifest.TileShape; // 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(); }
static object LoadVideos(MiniYaml y) { var videos = new MapVideos(); var nodesDict = y.ToDictionary(); if (nodesDict.ContainsKey("Videos")) FieldLoader.Load(videos, nodesDict["Videos"]); return videos; }
static object LoadOptions(MiniYaml y) { var options = new MapOptions(); var nodesDict = y.ToDictionary(); if (nodesDict.ContainsKey("Options")) FieldLoader.Load(options, nodesDict["Options"]); return options; }
// 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; } 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; 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(); }
internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package) { if (package == null) return; var yamlStream = package.GetStream("map.yaml"); if (yamlStream == null) return; var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name)); var nd = yaml.ToDictionary(); var mapFormat = FieldLoader.GetValue<int>("MapFormat", nd["MapFormat"].Value); if (mapFormat < 6) throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name)); // 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)) yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap"))); else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign") yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector"))); } // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors if (mapFormat < 8) { var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players"); if (players != null) { bool noteHexColors = false; bool noteColorRamp = false; foreach (var player in players.Value.Nodes) { var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp"); if (colorRampNode != null) { Color dummy; var parts = colorRampNode.Value.Value.Split(','); if (parts.Length == 3 || parts.Length == 4) { // Try to convert old normalized HSL value to a rgb hex color try { HSLColor color = new HSLColor( (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255)); colorRampNode.Value.Value = FieldSaver.FormatValue(color); noteHexColors = true; } catch (Exception) { throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); } } else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy)) throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); colorRampNode.Key = "Color"; noteColorRamp = true; } } if (noteHexColors) Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa]."); else if (noteColorRamp) Console.WriteLine("ColorRamp is now called Color."); } } // Format 8 -> 9 moved map options and videos from the map file itself to traits if (mapFormat < 9) { var rules = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules"); var worldNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "World"); if (worldNode == null) worldNode = new MiniYamlNode("World", new MiniYaml("", new List<MiniYamlNode>())); var playerNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "Player"); if (playerNode == null) playerNode = new MiniYamlNode("Player", new MiniYaml("", new List<MiniYamlNode>())); var visibilityNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Visibility"); if (visibilityNode != null) { var visibility = FieldLoader.GetValue<MapVisibility>("Visibility", visibilityNode.Value.Value); if (visibility.HasFlag(MapVisibility.MissionSelector)) { var missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List<MiniYamlNode>())); worldNode.Value.Nodes.Add(missionData); var description = yaml.Nodes.FirstOrDefault(n => n.Key == "Description"); if (description != null) missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", description.Value.Value)); var videos = yaml.Nodes.FirstOrDefault(n => n.Key == "Videos"); if (videos != null && videos.Value.Nodes.Any()) { var backgroundVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "BackgroundInfo"); if (backgroundVideo != null) missionData.Value.Nodes.Add(new MiniYamlNode("BackgroundVideo", backgroundVideo.Value.Value)); var briefingVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "Briefing"); if (briefingVideo != null) missionData.Value.Nodes.Add(new MiniYamlNode("BriefingVideo", briefingVideo.Value.Value)); var startVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameStart"); if (startVideo != null) missionData.Value.Nodes.Add(new MiniYamlNode("StartVideo", startVideo.Value.Value)); var winVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameWon"); if (winVideo != null) missionData.Value.Nodes.Add(new MiniYamlNode("WinVideo", winVideo.Value.Value)); var lossVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameLost"); if (lossVideo != null) missionData.Value.Nodes.Add(new MiniYamlNode("LossVideo", lossVideo.Value.Value)); } } } var mapOptions = yaml.Nodes.FirstOrDefault(n => n.Key == "Options"); if (mapOptions != null) { var cheats = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Cheats"); if (cheats != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("DeveloperMode", new MiniYaml("", new List<MiniYamlNode>() { new MiniYamlNode("Locked", "True"), new MiniYamlNode("Enabled", cheats.Value.Value) }))); } var crates = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Crates"); if (crates != null && !worldNode.Value.Nodes.Any(n => n.Key == "-CrateSpawner")) { if (!FieldLoader.GetValue<bool>("crates", crates.Value.Value)) worldNode.Value.Nodes.Add(new MiniYamlNode("-CrateSpawner", new MiniYaml(""))); } var creeps = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Creeps"); if (creeps != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("MapCreeps", new MiniYaml("", new List<MiniYamlNode>() { new MiniYamlNode("Locked", "True"), new MiniYamlNode("Enabled", creeps.Value.Value) }))); } var fog = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Fog"); var shroud = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Shroud"); if (fog != null || shroud != null) { var shroudNode = new MiniYamlNode("Shroud", new MiniYaml("", new List<MiniYamlNode>())); playerNode.Value.Nodes.Add(shroudNode); if (fog != null) { shroudNode.Value.Nodes.Add(new MiniYamlNode("FogLocked", "True")); shroudNode.Value.Nodes.Add(new MiniYamlNode("FogEnabled", fog.Value.Value)); } if (shroud != null) { var enabled = FieldLoader.GetValue<bool>("shroud", shroud.Value.Value); shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapLocked", "True")); shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapEnabled", FieldSaver.FormatValue(!enabled))); } } var allyBuildRadius = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "AllyBuildRadius"); if (allyBuildRadius != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("MapBuildRadius", new MiniYaml("", new List<MiniYamlNode>() { new MiniYamlNode("AllyBuildRadiusLocked", "True"), new MiniYamlNode("AllyBuildRadiusEnabled", allyBuildRadius.Value.Value) }))); } var startingCash = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "StartingCash"); if (startingCash != null) { playerNode.Value.Nodes.Add(new MiniYamlNode("PlayerResources", new MiniYaml("", new List<MiniYamlNode>() { new MiniYamlNode("DefaultCashLocked", "True"), new MiniYamlNode("DefaultCash", startingCash.Value.Value) }))); } var startingUnits = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ConfigurableStartingUnits"); if (startingUnits != null && !worldNode.Value.Nodes.Any(n => n.Key == "-SpawnMPUnits")) { worldNode.Value.Nodes.Add(new MiniYamlNode("SpawnMPUnits", new MiniYaml("", new List<MiniYamlNode>() { new MiniYamlNode("Locked", "True"), }))); } var techLevel = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "TechLevel"); var difficulties = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulties"); var shortGame = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ShortGame"); if (techLevel != null || difficulties != null || shortGame != null) { var optionsNode = new MiniYamlNode("MapOptions", new MiniYaml("", new List<MiniYamlNode>())); worldNode.Value.Nodes.Add(optionsNode); if (techLevel != null) { optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevelLocked", "True")); optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevel", techLevel.Value.Value)); } if (difficulties != null) optionsNode.Value.Nodes.Add(new MiniYamlNode("Difficulties", difficulties.Value.Value)); if (shortGame != null) { optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameLocked", "True")); optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameEnabled", shortGame.Value.Value)); } } } if (worldNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(worldNode)) rules.Value.Nodes.Add(worldNode); if (playerNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(playerNode)) rules.Value.Nodes.Add(playerNode); } // Format 9 -> 10 moved smudges to SmudgeLayer, and uses map.png for all maps if (mapFormat < 10) { ExtractSmudges(yaml); if (package.Contains("map.png")) yaml.Nodes.Add(new MiniYamlNode("LockPreview", new MiniYaml("True"))); } // Format 10 -> 11 replaced the single map type field with a list of categories if (mapFormat < 11) { var type = yaml.Nodes.First(n => n.Key == "Type"); yaml.Nodes.Add(new MiniYamlNode("Categories", type.Value)); yaml.Nodes.Remove(type); } if (mapFormat < Map.SupportedMapFormat) { yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString()); Console.WriteLine("Converted {0} to MapFormat {1}.", package.Name, Map.SupportedMapFormat); } package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); }
public static object LoadModifiers(MiniYaml yaml) { var md = yaml.ToDictionary(); return md.ContainsKey("DamageModifiers") ? md["DamageModifiers"].ToDictionary(my => FieldLoader.GetValue<int>("(value)", my.Value)) : new Dictionary<string, int>(); }
internal static void UpgradeMapFormat(ModData modData, IReadWritePackage package) { if (package == null) { return; } var yamlStream = package.GetStream("map.yaml"); if (yamlStream == null) { return; } var yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, package.Name)); var nd = yaml.ToDictionary(); var mapFormat = FieldLoader.GetValue <int>("MapFormat", nd["MapFormat"].Value); if (mapFormat < 6) { throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(mapFormat, package.Name)); } // 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)) { yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("Shellmap"))); } else if (nd["Type"].Value == "Mission" || nd["Type"].Value == "Campaign") { yaml.Nodes.Add(new MiniYamlNode("Visibility", new MiniYaml("MissionSelector"))); } } // Format 7 -> 8 replaced normalized HSL triples with rgb(a) hex colors if (mapFormat < 8) { var players = yaml.Nodes.FirstOrDefault(n => n.Key == "Players"); if (players != null) { bool noteHexColors = false; bool noteColorRamp = false; foreach (var player in players.Value.Nodes) { var colorRampNode = player.Value.Nodes.FirstOrDefault(n => n.Key == "ColorRamp"); if (colorRampNode != null) { Color dummy; var parts = colorRampNode.Value.Value.Split(','); if (parts.Length == 3 || parts.Length == 4) { // Try to convert old normalized HSL value to a rgb hex color try { HSLColor color = new HSLColor( (byte)Exts.ParseIntegerInvariant(parts[0].Trim()).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[1].Trim()).Clamp(0, 255), (byte)Exts.ParseIntegerInvariant(parts[2].Trim()).Clamp(0, 255)); colorRampNode.Value.Value = FieldSaver.FormatValue(color); noteHexColors = true; } catch (Exception) { throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); } } else if (parts.Length != 1 || !HSLColor.TryParseRGB(parts[0], out dummy)) { throw new InvalidDataException("Invalid ColorRamp value.\n File: " + package.Name); } colorRampNode.Key = "Color"; noteColorRamp = true; } } if (noteHexColors) { Console.WriteLine("ColorRamp is now called Color and uses rgb(a) hex value - rrggbb[aa]."); } else if (noteColorRamp) { Console.WriteLine("ColorRamp is now called Color."); } } } // Format 8 -> 9 moved map options and videos from the map file itself to traits if (mapFormat < 9) { var rules = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules"); var worldNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "World"); if (worldNode == null) { worldNode = new MiniYamlNode("World", new MiniYaml("", new List <MiniYamlNode>())); } var playerNode = rules.Value.Nodes.FirstOrDefault(n => n.Key == "Player"); if (playerNode == null) { playerNode = new MiniYamlNode("Player", new MiniYaml("", new List <MiniYamlNode>())); } var visibilityNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Visibility"); if (visibilityNode != null) { var visibility = FieldLoader.GetValue <MapVisibility>("Visibility", visibilityNode.Value.Value); if (visibility.HasFlag(MapVisibility.MissionSelector)) { var missionData = new MiniYamlNode("MissionData", new MiniYaml("", new List <MiniYamlNode>())); worldNode.Value.Nodes.Add(missionData); var description = yaml.Nodes.FirstOrDefault(n => n.Key == "Description"); if (description != null) { missionData.Value.Nodes.Add(new MiniYamlNode("Briefing", description.Value.Value)); } var videos = yaml.Nodes.FirstOrDefault(n => n.Key == "Videos"); if (videos != null && videos.Value.Nodes.Any()) { var backgroundVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "BackgroundInfo"); if (backgroundVideo != null) { missionData.Value.Nodes.Add(new MiniYamlNode("BackgroundVideo", backgroundVideo.Value.Value)); } var briefingVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "Briefing"); if (briefingVideo != null) { missionData.Value.Nodes.Add(new MiniYamlNode("BriefingVideo", briefingVideo.Value.Value)); } var startVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameStart"); if (startVideo != null) { missionData.Value.Nodes.Add(new MiniYamlNode("StartVideo", startVideo.Value.Value)); } var winVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameWon"); if (winVideo != null) { missionData.Value.Nodes.Add(new MiniYamlNode("WinVideo", winVideo.Value.Value)); } var lossVideo = videos.Value.Nodes.FirstOrDefault(n => n.Key == "GameLost"); if (lossVideo != null) { missionData.Value.Nodes.Add(new MiniYamlNode("LossVideo", lossVideo.Value.Value)); } } } } var mapOptions = yaml.Nodes.FirstOrDefault(n => n.Key == "Options"); if (mapOptions != null) { var cheats = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Cheats"); if (cheats != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("DeveloperMode", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("Locked", "True"), new MiniYamlNode("Enabled", cheats.Value.Value) }))); } var crates = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Crates"); if (crates != null && !worldNode.Value.Nodes.Any(n => n.Key == "-CrateSpawner")) { if (!FieldLoader.GetValue <bool>("crates", crates.Value.Value)) { worldNode.Value.Nodes.Add(new MiniYamlNode("-CrateSpawner", new MiniYaml(""))); } } var creeps = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Creeps"); if (creeps != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("MapCreeps", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("Locked", "True"), new MiniYamlNode("Enabled", creeps.Value.Value) }))); } var fog = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Fog"); var shroud = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Shroud"); if (fog != null || shroud != null) { var shroudNode = new MiniYamlNode("Shroud", new MiniYaml("", new List <MiniYamlNode>())); playerNode.Value.Nodes.Add(shroudNode); if (fog != null) { shroudNode.Value.Nodes.Add(new MiniYamlNode("FogLocked", "True")); shroudNode.Value.Nodes.Add(new MiniYamlNode("FogEnabled", fog.Value.Value)); } if (shroud != null) { var enabled = FieldLoader.GetValue <bool>("shroud", shroud.Value.Value); shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapLocked", "True")); shroudNode.Value.Nodes.Add(new MiniYamlNode("ExploredMapEnabled", FieldSaver.FormatValue(!enabled))); } } var allyBuildRadius = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "AllyBuildRadius"); if (allyBuildRadius != null) { worldNode.Value.Nodes.Add(new MiniYamlNode("MapBuildRadius", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("AllyBuildRadiusLocked", "True"), new MiniYamlNode("AllyBuildRadiusEnabled", allyBuildRadius.Value.Value) }))); } var startingCash = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "StartingCash"); if (startingCash != null) { playerNode.Value.Nodes.Add(new MiniYamlNode("PlayerResources", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("DefaultCashLocked", "True"), new MiniYamlNode("DefaultCash", startingCash.Value.Value) }))); } var startingUnits = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ConfigurableStartingUnits"); if (startingUnits != null && !worldNode.Value.Nodes.Any(n => n.Key == "-SpawnMPUnits")) { worldNode.Value.Nodes.Add(new MiniYamlNode("SpawnMPUnits", new MiniYaml("", new List <MiniYamlNode>() { new MiniYamlNode("Locked", "True"), }))); } var techLevel = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "TechLevel"); var difficulties = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "Difficulties"); var shortGame = mapOptions.Value.Nodes.FirstOrDefault(n => n.Key == "ShortGame"); if (techLevel != null || difficulties != null || shortGame != null) { var optionsNode = new MiniYamlNode("MapOptions", new MiniYaml("", new List <MiniYamlNode>())); worldNode.Value.Nodes.Add(optionsNode); if (techLevel != null) { optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevelLocked", "True")); optionsNode.Value.Nodes.Add(new MiniYamlNode("TechLevel", techLevel.Value.Value)); } if (difficulties != null) { optionsNode.Value.Nodes.Add(new MiniYamlNode("Difficulties", difficulties.Value.Value)); } if (shortGame != null) { optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameLocked", "True")); optionsNode.Value.Nodes.Add(new MiniYamlNode("ShortGameEnabled", shortGame.Value.Value)); } } } if (worldNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(worldNode)) { rules.Value.Nodes.Add(worldNode); } if (playerNode.Value.Nodes.Any() && !rules.Value.Nodes.Contains(playerNode)) { rules.Value.Nodes.Add(playerNode); } } // Format 9 -> 10 moved smudges to SmudgeLayer, and uses map.png for all maps if (mapFormat < 10) { ExtractSmudges(yaml); if (package.Contains("map.png")) { yaml.Nodes.Add(new MiniYamlNode("LockPreview", new MiniYaml("True"))); } } // Format 10 -> 11 replaced the single map type field with a list of categories if (mapFormat < 11) { var type = yaml.Nodes.First(n => n.Key == "Type"); yaml.Nodes.Add(new MiniYamlNode("Categories", type.Value)); yaml.Nodes.Remove(type); } if (mapFormat < Map.SupportedMapFormat) { yaml.Nodes.First(n => n.Key == "MapFormat").Value = new MiniYaml(Map.SupportedMapFormat.ToString()); Console.WriteLine("Converted {0} to MapFormat {1}.", package.Name, Map.SupportedMapFormat); } package.Update("map.yaml", Encoding.UTF8.GetBytes(yaml.Nodes.WriteToString())); }
static object LoadPercents(MiniYaml y) { MiniYaml percents; if (!y.ToDictionary().TryGetValue("TerrainModifier", out percents)) return new Dictionary<string, int>(); return percents.Nodes.ToDictionary( kv => FieldLoader.GetValue<string>("(key)", kv.Key), kv => FieldLoader.GetValue<int>("(value)", kv.Value.Value)); }
public Sequence(SpriteCache cache, string unit, string name, MiniYaml info) { var srcOverride = info.Value; Name = name; var d = info.ToDictionary(); var offset = float2.Zero; var blendMode = BlendMode.Alpha; try { if (d.ContainsKey("Start")) Start = Exts.ParseIntegerInvariant(d["Start"].Value); if (d.ContainsKey("Offset")) offset = FieldLoader.GetValue<float2>("Offset", d["Offset"].Value); if (d.ContainsKey("BlendMode")) blendMode = FieldLoader.GetValue<BlendMode>("BlendMode", d["BlendMode"].Value); // Apply offset to each sprite in the sequence // Different sequences may apply different offsets to the same frame sprites = cache[srcOverride ?? unit].Select( s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray(); if (!d.ContainsKey("Length")) Length = 1; else if (d["Length"].Value == "*") Length = sprites.Length - Start; else Length = Exts.ParseIntegerInvariant(d["Length"].Value); if (d.ContainsKey("Stride")) Stride = Exts.ParseIntegerInvariant(d["Stride"].Value); else Stride = Length; if (d.ContainsKey("Facings")) { var f = Exts.ParseIntegerInvariant(d["Facings"].Value); Facings = Math.Abs(f); reverseFacings = f < 0; } else Facings = 1; if (d.ContainsKey("Tick")) Tick = Exts.ParseIntegerInvariant(d["Tick"].Value); else Tick = 40; if (d.ContainsKey("Transpose")) transpose = bool.Parse(d["Transpose"].Value); if (d.ContainsKey("Frames")) Frames = Array.ConvertAll<string, int>(d["Frames"].Value.Split(','), Exts.ParseIntegerInvariant); if (d.ContainsKey("ShadowStart")) ShadowStart = Exts.ParseIntegerInvariant(d["ShadowStart"].Value); else ShadowStart = -1; if (d.ContainsKey("ShadowZOffset")) { WRange r; if (WRange.TryParse(d["ShadowZOffset"].Value, out r)) ShadowZOffset = r.Range; } else ShadowZOffset = -5; if (d.ContainsKey("ZOffset")) { WRange r; if (WRange.TryParse(d["ZOffset"].Value, out r)) ZOffset = r.Range; } if (Length > Stride) throw new InvalidOperationException( "{0}: Sequence {1}.{2}: Length must be <= stride" .F(info.Nodes[0].Location, unit, name)); if (Start < 0 || Start + Facings * Stride > sprites.Length || ShadowStart + Facings * Stride > sprites.Length) throw new InvalidOperationException( "{6}: Sequence {0}.{1} uses frames [{2}..{3}] of SHP `{4}`, but only 0..{5} actually exist" .F(unit, name, Start, Start + Facings * Stride - 1, srcOverride ?? unit, sprites.Length - 1, info.Nodes[0].Location)); } catch (FormatException f) { throw new FormatException("Failed to parse sequences for {0}.{1} at {2}:\n{3}".F(unit, name, info.Nodes[0].Location, f)); } }