Пример #1
0
		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();
		}
Пример #2
0
		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>();
		}
Пример #3
0
        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);
        }
Пример #4
0
        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()));
        }
Пример #5
0
        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();
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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;
        }
Пример #8
0
		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();
		}
Пример #9
0
 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[]>();
 }
Пример #10
0
        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);
                }
            }
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
                }
            }
        }
Пример #13
0
        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>());
        }
Пример #14
0
        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>());
        }
Пример #15
0
        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)));
        }
Пример #16
0
        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[]>();
        }
Пример #17
0
        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[]>());
        }
Пример #18
0
        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>());
        }
Пример #19
0
        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[]>());
        }
Пример #20
0
        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>());
        }
Пример #21
0
		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;
		}
Пример #22
0
		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
		}
Пример #23
0
 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
 }
Пример #24
0
		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;
		}
Пример #25
0
        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));
        }
Пример #26
0
        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);
        }
Пример #27
0
        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)));
        }
Пример #28
0
        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)));
        }
Пример #29
0
        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");
            }
        }
Пример #30
0
        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);
        }
Пример #31
0
		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;
		}
Пример #32
0
        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);
        }
Пример #33
0
        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);
                }
            }
        }
Пример #34
0
        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);
            }
        }
Пример #35
0
        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)));
        }
Пример #36
0
        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;
        }
Пример #37
0
        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();
        }
Пример #38
0
		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);
		}
Пример #39
0
		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;
		}
Пример #40
0
		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;
			}
		}
Пример #41
0
		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;
		}
Пример #42
0
        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);
            }
        }
Пример #43
0
        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);
        }
Пример #44
0
        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));
            }
        }
Пример #45
0
        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));
            }
        }
Пример #46
0
 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));
 }
Пример #47
0
        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;
        }
Пример #48
0
        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;
        }
Пример #49
0
		// 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();
		}
Пример #50
0
        static object LoadVideos(MiniYaml y)
        {
            var videos = new MapVideos();
            var nodesDict = y.ToDictionary();
            if (nodesDict.ContainsKey("Videos"))
                FieldLoader.Load(videos, nodesDict["Videos"]);

            return videos;
        }
Пример #51
0
        static object LoadOptions(MiniYaml y)
        {
            var options = new MapOptions();
            var nodesDict = y.ToDictionary();
            if (nodesDict.ContainsKey("Options"))
                FieldLoader.Load(options, nodesDict["Options"]);

            return options;
        }
Пример #52
0
        // 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();
        }
Пример #53
0
        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()));
        }
Пример #54
0
        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>();
        }
Пример #55
0
        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()));
        }
Пример #56
0
        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));
        }
Пример #57
0
        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));
            }
        }