Exemplo n.º 1
0
 public ModPackage(MiniYaml yaml)
 {
     Title = yaml.Value;
     FieldLoader.Load(this, yaml);
 }
Exemplo n.º 2
0
 public PlayerReference(MiniYaml my)
 {
     FieldLoader.Load(this, my);
 }
Exemplo n.º 3
0
        public Manifest(string modId, IReadOnlyPackage package)
        {
            Id      = modId;
            Package = package;

            var nodes = MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml");

            for (var i = nodes.Count - 1; i >= 0; i--)
            {
                if (nodes[i].Key != "Include")
                {
                    continue;
                }

                // Replace `Includes: filename.yaml` with the contents of filename.yaml
                var filename = nodes[i].Value.Value;
                var contents = package.GetStream(filename);
                if (contents == null)
                {
                    throw new YamlException($"{nodes[i].Location}: File `{filename}` not found.");
                }

                nodes.RemoveAt(i);
                nodes.InsertRange(i, MiniYaml.FromStream(contents, filename));
            }

            // Merge inherited overrides
            yaml = new MiniYaml(null, MiniYaml.Merge(new[] { nodes })).ToDictionary();

            Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);

            // TODO: Use fieldloader
            MapFolders = YamlDictionary(yaml, "MapFolders");

            if (yaml.TryGetValue("Packages", out var packages))
            {
                Packages = packages.ToDictionary(x => x.Value);
            }

            Rules          = YamlList(yaml, "Rules");
            Sequences      = YamlList(yaml, "Sequences");
            ModelSequences = YamlList(yaml, "ModelSequences");
            Cursors        = YamlList(yaml, "Cursors");
            Chrome         = YamlList(yaml, "Chrome");
            Assemblies     = YamlList(yaml, "Assemblies");
            ChromeLayout   = YamlList(yaml, "ChromeLayout");
            Weapons        = YamlList(yaml, "Weapons");
            Voices         = YamlList(yaml, "Voices");
            Notifications  = YamlList(yaml, "Notifications");
            Music          = YamlList(yaml, "Music");
            Translations   = YamlList(yaml, "Translations");
            TileSets       = YamlList(yaml, "TileSets");
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics");
            Missions       = YamlList(yaml, "Missions");
            Hotkeys        = YamlList(yaml, "Hotkeys");

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            // Allow inherited mods to import parent maps.
            var compat = new List <string> {
                Id
            };

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("PackageFormats"))
            {
                PackageFormats = FieldLoader.GetValue <string[]>("PackageFormats", yaml["PackageFormats"].Value);
            }

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }

            if (yaml.ContainsKey("VideoFormats"))
            {
                VideoFormats = FieldLoader.GetValue <string[]>("VideoFormats", yaml["VideoFormats"].Value);
            }
        }
Exemplo n.º 4
0
        public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action <MapPreview> parseMetadata = null)
        {
            var newData = innerData.Clone();

            newData.Status = status;
            newData.Class  = MapClassification.Remote;

            if (status == MapStatus.DownloadAvailable)
            {
                try
                {
                    var r = FieldLoader.Load <RemoteMapData>(yaml);

                    // Map download has been disabled server side
                    if (!r.downloading)
                    {
                        newData.Status = MapStatus.Unavailable;
                        return;
                    }

                    newData.Title       = r.title;
                    newData.Categories  = r.categories;
                    newData.Author      = r.author;
                    newData.PlayerCount = r.players;
                    newData.Bounds      = r.bounds;
                    newData.TileSet     = r.tileset;
                    newData.MapFormat   = r.mapformat;

                    var spawns = new CPos[r.spawnpoints.Length / 2];
                    for (var j = 0; j < r.spawnpoints.Length; j += 2)
                    {
                        spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]);
                    }
                    newData.SpawnPoints = spawns;
                    newData.GridType    = r.map_grid_type;
                    try
                    {
                        newData.Preview = new Png(new MemoryStream(Convert.FromBase64String(r.minimap)));
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e);
                        newData.Preview = null;
                    }

                    var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block));
                    newData.Players = new MapPlayers(MiniYaml.FromString(playersString));

                    var rulesString = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules));
                    var rulesYaml   = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary();
                    newData.SetCustomRules(modData, this, rulesYaml);
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed parsing mapserver response: {0}", e);
                }

                // Commit updated data before running the callbacks
                innerData = newData;

                if (innerData.Preview != null)
                {
                    cache.CacheMinimap(this);
                }

                parseMetadata?.Invoke(this);
            }

            // Update the status and class unconditionally
            innerData = newData;
        }
Exemplo n.º 5
0
        /// <summary>Initializes a map loaded from disk.</summary>
        public Map(string path)
        {
            Path      = path;
            Container = GlobalFileSystem.OpenPackage(path, null, int.MaxValue);

            AssertExists("map.yaml");
            AssertExists("map.bin");

            var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"), path));

            FieldLoader.Load(this, yaml);

            // Support for formats 1-3 dropped 2011-02-11.
            // Use release-20110207 to convert older maps to format 4
            // Use release-20110511 to convert older maps to format 5
            // Use release-20141029 to convert older maps to format 6
            if (MapFormat < 6)
            {
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path));
            }

            var nd = yaml.ToDictionary();

            // Format 6 -> 7 combined the Selectable and UseAsShellmap flags into the Class enum
            if (MapFormat < 7)
            {
                MiniYaml useAsShellmap;
                if (nd.TryGetValue("UseAsShellmap", out useAsShellmap) && bool.Parse(useAsShellmap.Value))
                {
                    Visibility = MapVisibility.Shellmap;
                }
                else if (Type == "Mission" || Type == "Campaign")
                {
                    Visibility = MapVisibility.MissionSelector;
                }
            }

            SpawnPoints = Exts.Lazy(() =>
            {
                var spawns = new List <CPos>();
                foreach (var kv in ActorDefinitions.Where(d => d.Value.Value == "mpspawn"))
                {
                    var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());

                    spawns.Add(s.InitDict.Get <LocationInit>().Value(null));
                }

                return(spawns.ToArray());
            });

            RuleDefinitions          = MiniYaml.NodesOrEmpty(yaml, "Rules");
            SequenceDefinitions      = MiniYaml.NodesOrEmpty(yaml, "Sequences");
            VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
            WeaponDefinitions        = MiniYaml.NodesOrEmpty(yaml, "Weapons");
            VoiceDefinitions         = MiniYaml.NodesOrEmpty(yaml, "Voices");
            NotificationDefinitions  = MiniYaml.NodesOrEmpty(yaml, "Notifications");
            TranslationDefinitions   = MiniYaml.NodesOrEmpty(yaml, "Translations");
            PlayerDefinitions        = MiniYaml.NodesOrEmpty(yaml, "Players");

            ActorDefinitions  = MiniYaml.NodesOrEmpty(yaml, "Actors");
            SmudgeDefinitions = MiniYaml.NodesOrEmpty(yaml, "Smudges");

            MapTiles     = Exts.Lazy(LoadMapTiles);
            MapResources = Exts.Lazy(LoadResourceTiles);
            MapHeight    = Exts.Lazy(LoadMapHeight);

            TileShape            = Game.ModData.Manifest.TileShape;
            MaximumTerrainHeight = Game.ModData.Manifest.MaximumTerrainHeight;

            SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
            LastSubCell    = (SubCell)(SubCellOffsets.Length - 1);
            DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex;

            if (Container.Exists("map.png"))
            {
                using (var dataStream = Container.GetContent("map.png"))
                    CustomPreview = new Bitmap(dataStream);
            }

            PostInit();

            // The Uid is calculated from the data on-disk, so
            // format changes must be flushed to disk.
            // TODO: this isn't very nice
            if (MapFormat < 7)
            {
                Save(path);
            }

            Uid = ComputeHash();
        }
Exemplo n.º 6
0
 public TerrainTypeInfo(MiniYaml my)
 {
     FieldLoader.Load(this, my);
 }
Exemplo n.º 7
0
        public Manifest(string mod)
        {
            var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml");

            yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();

            Mod    = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);
            Mod.Id = mod;

            // TODO: Use fieldloader
            Folders        = YamlList(yaml, "Folders", true);
            MapFolders     = YamlDictionary(yaml, "MapFolders", true);
            Packages       = YamlDictionary(yaml, "Packages", true);
            Rules          = YamlList(yaml, "Rules", true);
            Sequences      = YamlList(yaml, "Sequences", true);
            VoxelSequences = YamlList(yaml, "VoxelSequences", true);
            Cursors        = YamlList(yaml, "Cursors", true);
            Chrome         = YamlList(yaml, "Chrome", true);
            Assemblies     = YamlList(yaml, "Assemblies", true);
            ChromeLayout   = YamlList(yaml, "ChromeLayout", true);
            Weapons        = YamlList(yaml, "Weapons", true);
            Voices         = YamlList(yaml, "Voices", true);
            Notifications  = YamlList(yaml, "Notifications", true);
            Music          = YamlList(yaml, "Music", true);
            Translations   = YamlList(yaml, "Translations", true);
            TileSets       = YamlList(yaml, "TileSets", true);
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics", true);
            Missions       = YamlList(yaml, "Missions", true);

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            if (!yaml.TryGetValue("LobbyDefaults", out LobbyDefaults))
            {
                throw new InvalidDataException("`LobbyDefaults` section is not defined.");
            }

            Fonts = yaml["Fonts"].ToDictionary(my =>
            {
                var nd = my.ToDictionary();
                return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value)));
            });

            RequiresMods = yaml["RequiresMods"].ToDictionary(my => my.Value);

            // Allow inherited mods to import parent maps.
            var compat = new List <string>();

            compat.Add(mod);

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                foreach (var c in yaml["SupportsMapsFrom"].Value.Split(','))
                {
                    compat.Add(c.Trim());
                }
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }
        }
Exemplo n.º 8
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;
                }
            }

            // Load players
            foreach (var my in nd["Players"].ToDictionary().Values)
            {
                var player = new PlayerReference(my);
                Players.Add(player.Name, player);
            }

            Actors = Exts.Lazy(() =>
            {
                var ret = new Dictionary <string, ActorReference>();
                foreach (var kv in nd["Actors"].ToDictionary())
                {
                    ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.ToDictionary()));
                }
                return(ret);
            });

            // Smudges
            Smudges = Exts.Lazy(() =>
            {
                var ret = new List <SmudgeReference>();
                foreach (var name in nd["Smudges"].ToDictionary().Keys)
                {
                    var vals = name.Split(' ');
                    var loc  = vals[1].Split(',');
                    ret.Add(new SmudgeReference(vals[0], new int2(
                                                    Exts.ParseIntegerInvariant(loc[0]),
                                                    Exts.ParseIntegerInvariant(loc[1])),
                                                Exts.ParseIntegerInvariant(vals[2])));
                }

                return(ret);
            });

            RuleDefinitions          = MiniYaml.NodesOrEmpty(yaml, "Rules");
            SequenceDefinitions      = MiniYaml.NodesOrEmpty(yaml, "Sequences");
            VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
            WeaponDefinitions        = MiniYaml.NodesOrEmpty(yaml, "Weapons");
            VoiceDefinitions         = MiniYaml.NodesOrEmpty(yaml, "Voices");
            NotificationDefinitions  = MiniYaml.NodesOrEmpty(yaml, "Notifications");
            TranslationDefinitions   = MiniYaml.NodesOrEmpty(yaml, "Translations");

            MapTiles     = Exts.Lazy(() => LoadMapTiles());
            MapResources = Exts.Lazy(() => LoadResourceTiles());
            MapHeight    = Exts.Lazy(() => LoadMapHeight());

            TileShape      = Game.ModData.Manifest.TileShape;
            SubCellOffsets = Game.ModData.Manifest.SubCellOffsets;
            LastSubCell    = (SubCell)(SubCellOffsets.Length - 1);
            DefaultSubCell = (SubCell)Game.ModData.Manifest.SubCellDefaultIndex;

            if (Container.Exists("map.png"))
            {
                using (var dataStream = Container.GetContent("map.png"))
                    CustomPreview = new Bitmap(dataStream);
            }

            PostInit();

            // The Uid is calculated from the data on-disk, so
            // format changes must be flushed to disk.
            // TODO: this isn't very nice
            if (MapFormat < 7)
            {
                Save(path);
            }

            Uid = ComputeHash();
        }
Exemplo n.º 9
0
        public Manifest(string modId)
        {
            var package = ModMetadata.AllMods[modId].Package;

            yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"))).ToDictionary();

            Mod    = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);
            Mod.Id = modId;

            // TODO: Use fieldloader
            MapFolders = YamlDictionary(yaml, "MapFolders");

            MiniYaml packages;

            if (yaml.TryGetValue("Packages", out packages))
            {
                Packages = packages.ToDictionary(x => x.Value).AsReadOnly();
            }

            Rules          = YamlList(yaml, "Rules");
            Sequences      = YamlList(yaml, "Sequences");
            VoxelSequences = YamlList(yaml, "VoxelSequences");
            Cursors        = YamlList(yaml, "Cursors");
            Chrome         = YamlList(yaml, "Chrome");
            Assemblies     = YamlList(yaml, "Assemblies");
            ChromeLayout   = YamlList(yaml, "ChromeLayout");
            Weapons        = YamlList(yaml, "Weapons");
            Voices         = YamlList(yaml, "Voices");
            Notifications  = YamlList(yaml, "Notifications");
            Music          = YamlList(yaml, "Music");
            Translations   = YamlList(yaml, "Translations");
            TileSets       = YamlList(yaml, "TileSets");
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics");
            Missions       = YamlList(yaml, "Missions");

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            Fonts = yaml["Fonts"].ToDictionary(my =>
            {
                var nd = my.ToDictionary();
                return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value)));
            });

            RequiresMods = yaml["RequiresMods"].ToDictionary(my => my.Value);

            // Allow inherited mods to import parent maps.
            var compat = new List <string> {
                Mod.Id
            };

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }
        }
Exemplo n.º 10
0
        public Manifest(string mod)
        {
            var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine);
            var yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();

            Mod    = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);
            Mod.Id = mod;

            // TODO: Use fieldloader
            Folders         = YamlList(yaml, "Folders");
            MapFolders      = YamlDictionary(yaml, "MapFolders");
            Packages        = YamlDictionary(yaml, "Packages");
            Rules           = YamlList(yaml, "Rules");
            ServerTraits    = YamlList(yaml, "ServerTraits");
            Sequences       = YamlList(yaml, "Sequences");
            VoxelSequences  = YamlList(yaml, "VoxelSequences");
            Cursors         = YamlList(yaml, "Cursors");
            Chrome          = YamlList(yaml, "Chrome");
            Assemblies      = YamlList(yaml, "Assemblies");
            ChromeLayout    = YamlList(yaml, "ChromeLayout");
            Weapons         = YamlList(yaml, "Weapons");
            Voices          = YamlList(yaml, "Voices");
            Notifications   = YamlList(yaml, "Notifications");
            Music           = YamlList(yaml, "Music");
            Movies          = YamlList(yaml, "Movies");
            Translations    = YamlList(yaml, "Translations");
            TileSets        = YamlList(yaml, "TileSets");
            ChromeMetrics   = YamlList(yaml, "ChromeMetrics");
            PackageContents = YamlList(yaml, "PackageContents");
            LuaScripts      = YamlList(yaml, "LuaScripts");
            Missions        = YamlList(yaml, "Missions");

            LoadScreen    = yaml["LoadScreen"];
            LobbyDefaults = yaml["LobbyDefaults"];

            if (yaml.ContainsKey("ContentInstaller"))
            {
                ContentInstaller = FieldLoader.Load <InstallData>(yaml["ContentInstaller"]);
            }

            Fonts = yaml["Fonts"].ToDictionary(my =>
            {
                var nd = my.ToDictionary();
                return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value)));
            });

            if (yaml.ContainsKey("TileSize"))
            {
                TileSize = FieldLoader.GetValue <Size>("TileSize", yaml["TileSize"].Value);
            }

            if (yaml.ContainsKey("TileShape"))
            {
                TileShape = FieldLoader.GetValue <TileShape>("TileShape", yaml["TileShape"].Value);
            }

            // Allow inherited mods to import parent maps.
            var compat = new List <string>();

            compat.Add(mod);

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                foreach (var c in yaml["SupportsMapsFrom"].Value.Split(','))
                {
                    compat.Add(c.Trim());
                }
            }

            MapCompatibility = compat.ToArray();
        }
Exemplo n.º 11
0
        }                               /* doesn't really produce a valid map, but enough for loading a mod */

        public Map(string path)
        {
            Path      = path;
            container = FileSystem.OpenPackage(path, null, int.MaxValue);

            AssertExists("map.yaml");
            AssertExists("map.bin");

            var yaml = new MiniYaml(null, MiniYaml.FromStream(container.GetContent("map.yaml")));

            FieldLoader.Load(this, yaml);
            Uid = ComputeHash();

            // Support for formats 1-3 dropped 2011-02-11.
            // Use release-20110207 to convert older maps to format 4
            // Use release-20110511 to convert older maps to format 5
            if (MapFormat < 5)
            {
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, path));
            }

            // Load players
            foreach (var kv in yaml.NodesDict["Players"].NodesDict)
            {
                var player = new PlayerReference(kv.Value);
                Players.Add(player.Name, player);
            }

            Actors = Lazy.New(() =>
            {
                var ret = new Dictionary <string, ActorReference>();
                foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
                {
                    ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
                }
                return(ret);
            });

            // Smudges
            Smudges = Lazy.New(() =>
            {
                var ret = new List <SmudgeReference>();
                foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
                {
                    var vals = kv.Key.Split(' ');
                    var loc  = vals[1].Split(',');
                    ret.Add(new SmudgeReference(vals[0], new int2(int.Parse(loc[0]), int.Parse(loc[1])), int.Parse(vals[2])));
                }

                return(ret);
            });

            Rules          = MiniYaml.NodesOrEmpty(yaml, "Rules");
            Sequences      = MiniYaml.NodesOrEmpty(yaml, "Sequences");
            VoxelSequences = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
            Weapons        = MiniYaml.NodesOrEmpty(yaml, "Weapons");
            Voices         = MiniYaml.NodesOrEmpty(yaml, "Voices");
            Notifications  = MiniYaml.NodesOrEmpty(yaml, "Notifications");

            CustomTerrain = new string[MapSize.X, MapSize.Y];

            MapTiles     = Lazy.New(() => LoadMapTiles());
            MapResources = Lazy.New(() => LoadResourceTiles());
        }
Exemplo n.º 12
0
        public Manifest(string mod)
        {
            var path = Platform.ResolvePath(".", "mods", mod, "mod.yaml");

            yaml = new MiniYaml(null, MiniYaml.FromFile(path)).ToDictionary();

            Mod    = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);
            Mod.Id = mod;

            // TODO: Use fieldloader
            Folders        = YamlList(yaml, "Folders", true);
            MapFolders     = YamlDictionary(yaml, "MapFolders", true);
            Packages       = YamlDictionary(yaml, "Packages", true);
            Rules          = YamlList(yaml, "Rules", true);
            Sequences      = YamlList(yaml, "Sequences", true);
            VoxelSequences = YamlList(yaml, "VoxelSequences", true);
            Cursors        = YamlList(yaml, "Cursors", true);
            Chrome         = YamlList(yaml, "Chrome", true);
            Assemblies     = YamlList(yaml, "Assemblies", true);
            ChromeLayout   = YamlList(yaml, "ChromeLayout", true);
            Weapons        = YamlList(yaml, "Weapons", true);
            Voices         = YamlList(yaml, "Voices", true);
            Notifications  = YamlList(yaml, "Notifications", true);
            Music          = YamlList(yaml, "Music", true);
            Translations   = YamlList(yaml, "Translations", true);
            TileSets       = YamlList(yaml, "TileSets", true);
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics", true);
            Missions       = YamlList(yaml, "Missions", true);

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            if (!yaml.TryGetValue("LobbyDefaults", out LobbyDefaults))
            {
                throw new InvalidDataException("`LobbyDefaults` section is not defined.");
            }

            Fonts = yaml["Fonts"].ToDictionary(my =>
            {
                var nd = my.ToDictionary();
                return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value)));
            });

            if (yaml.ContainsKey("TileSize"))
            {
                TileSize = FieldLoader.GetValue <Size>("TileSize", yaml["TileSize"].Value);
            }

            if (yaml.ContainsKey("TileShape"))
            {
                TileShape = FieldLoader.GetValue <TileShape>("TileShape", yaml["TileShape"].Value);
            }

            if (yaml.ContainsKey("SubCells"))
            {
                var subcells = yaml["SubCells"].ToDictionary();

                // Read (x,y,z) offset (relative to cell center) pairs for positioning subcells
                if (subcells.ContainsKey("Offsets"))
                {
                    SubCellOffsets = FieldLoader.GetValue <WVec[]>("Offsets", subcells["Offsets"].Value);
                }

                if (subcells.ContainsKey("DefaultIndex"))
                {
                    SubCellDefaultIndex = FieldLoader.GetValue <int>("DefaultIndex", subcells["DefaultIndex"].Value);
                }
                else                    // Otherwise set the default subcell index to the middle subcell entry
                {
                    SubCellDefaultIndex = SubCellOffsets.Length / 2;
                }
            }

            // Validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1)
            if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length)
            {
                throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
            }

            // Allow inherited mods to import parent maps.
            var compat = new List <string>();

            compat.Add(mod);

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                foreach (var c in yaml["SupportsMapsFrom"].Value.Split(','))
                {
                    compat.Add(c.Trim());
                }
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }
        }
Exemplo n.º 13
0
        public Manifest(string modId, IReadOnlyPackage package)
        {
            Id      = modId;
            Package = package;
            yaml    = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml")).ToDictionary();

            Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);

            // TODO: Use fieldloader
            MapFolders = YamlDictionary(yaml, "MapFolders");

            MiniYaml packages;

            if (yaml.TryGetValue("Packages", out packages))
            {
                Packages = packages.ToDictionary(x => x.Value).AsReadOnly();
            }

            Rules          = YamlList(yaml, "Rules");
            Sequences      = YamlList(yaml, "Sequences");
            ModelSequences = YamlList(yaml, "ModelSequences");
            Cursors        = YamlList(yaml, "Cursors");
            Chrome         = YamlList(yaml, "Chrome");
            Assemblies     = YamlList(yaml, "Assemblies");
            ChromeLayout   = YamlList(yaml, "ChromeLayout");
            Weapons        = YamlList(yaml, "Weapons");
            Voices         = YamlList(yaml, "Voices");
            Notifications  = YamlList(yaml, "Notifications");
            Music          = YamlList(yaml, "Music");
            Translations   = YamlList(yaml, "Translations");
            TileSets       = YamlList(yaml, "TileSets");
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics");
            Missions       = YamlList(yaml, "Missions");
            Hotkeys        = YamlList(yaml, "Hotkeys");

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            // Allow inherited mods to import parent maps.
            var compat = new List <string> {
                Id
            };

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("PackageFormats"))
            {
                PackageFormats = FieldLoader.GetValue <string[]>("PackageFormats", yaml["PackageFormats"].Value);
            }

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }
        }
Exemplo n.º 14
0
        public MapGrid(MiniYaml yaml)
        {
            FieldLoader.Load(this, yaml);

            // The default subcell index defaults to the middle entry
            var defaultSubCellIndex = (byte)DefaultSubCell;

            if (defaultSubCellIndex == byte.MaxValue)
            {
                DefaultSubCell = (SubCell)(SubCellOffsets.Length / 2);
            }
            else
            {
                var minSubCellOffset = SubCellOffsets.Length > 1 ? 1 : 0;
                if (defaultSubCellIndex < minSubCellOffset || defaultSubCellIndex >= SubCellOffsets.Length)
                {
                    throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
                }
            }

            // Rotation axes and amounts for the different slope types
            var southEast = new WVec(724, 724, 0);
            var southWest = new WVec(-724, 724, 0);
            var south     = new WVec(0, 1024, 0);
            var east      = new WVec(1024, 0, 0);

            var forward      = new WAngle(64);
            var backward     = -forward;
            var halfForward  = new WAngle(48);
            var halfBackward = -halfForward;

            // Slope types are hardcoded following the convention from the TS and RA2 map format
            Ramps = new[]
            {
                // Flat
                new CellRamp(Type, WRot.None),

                // Two adjacent corners raised by half a cell
                new CellRamp(Type, new WRot(southEast, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half),
                new CellRamp(Type, new WRot(southWest, backward), br: RampCornerHeight.Half, bl: RampCornerHeight.Half),
                new CellRamp(Type, new WRot(southEast, forward), tl: RampCornerHeight.Half, bl: RampCornerHeight.Half),
                new CellRamp(Type, new WRot(southWest, forward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half),

                // One corner raised by half a cell
                new CellRamp(Type, new WRot(south, halfBackward), br: RampCornerHeight.Half, split: RampSplit.X),
                new CellRamp(Type, new WRot(east, halfForward), bl: RampCornerHeight.Half, split: RampSplit.Y),
                new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, split: RampSplit.X),
                new CellRamp(Type, new WRot(east, halfBackward), tr: RampCornerHeight.Half, split: RampSplit.Y),

                // Three corners raised by half a cell
                new CellRamp(Type, new WRot(south, halfBackward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
                new CellRamp(Type, new WRot(east, halfForward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y),
                new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
                new CellRamp(Type, new WRot(east, halfBackward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y),

                // Full tile sloped (mid corners raised by half cell, far corner by full cell)
                new CellRamp(Type, new WRot(south, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Full, bl: RampCornerHeight.Half),
                new CellRamp(Type, new WRot(east, forward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Full),
                new CellRamp(Type, new WRot(south, forward), tl: RampCornerHeight.Full, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half),
                new CellRamp(Type, new WRot(east, backward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Full, br: RampCornerHeight.Half),

                // Two opposite corners raised by half a cell
                new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y),
                new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y),
                new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
                new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.X),
            };

            TilesByDistance = CreateTilesByDistance();
        }
Exemplo n.º 15
0
 public ModDownload(MiniYaml yaml)
 {
     Title = yaml.Value;
     FieldLoader.Load(this, yaml);
 }
Exemplo n.º 16
0
        public TileTemplate(TileSet tileSet, MiniYaml my)
        {
            FieldLoader.Load(this, my);

            tiles = LoadTiles(tileSet, my);
        }
Exemplo n.º 17
0
 public virtual void Initialize(MiniYaml yaml)
 {
     FieldLoader.Load(this, yaml);
 }
Exemplo n.º 18
0
        /// <summary>
        /// Removes invalid mod registrations:
        /// * LaunchPath no longer exists
        /// * LaunchPath and mod id matches the active mod, but the version is different
        /// * Filename doesn't match internal key
        /// * Fails to parse as a mod registration
        /// </summary>
        internal void ClearInvalidRegistrations(ExternalMod activeMod, ModRegistration registration)
        {
            var sources = new List <string>();

            if (registration.HasFlag(ModRegistration.System))
            {
                sources.Add(Platform.SystemSupportDir);
            }

            if (registration.HasFlag(ModRegistration.User))
            {
                sources.Add(Platform.SupportDir);
            }

            var activeModKey = ExternalMod.MakeKey(activeMod);

            foreach (var source in sources.Distinct())
            {
                var metadataPath = Path.Combine(source, "ModMetadata");
                if (!Directory.Exists(metadataPath))
                {
                    continue;
                }

                foreach (var path in Directory.GetFiles(metadataPath, "*.yaml"))
                {
                    string modKey = null;
                    try
                    {
                        var yaml = MiniYaml.FromStream(File.OpenRead(path), path).First().Value;
                        var m    = FieldLoader.Load <ExternalMod>(yaml);
                        modKey = ExternalMod.MakeKey(m);

                        // Continue to the next entry if it is the active mod (even if the LaunchPath is bogus)
                        if (modKey == activeModKey)
                        {
                            continue;
                        }

                        // Continue to the next entry if this one is valid
                        if (File.Exists(m.LaunchPath) && Path.GetFileNameWithoutExtension(path) == modKey &&
                            !(activeMod != null && m.LaunchPath == activeMod.LaunchPath && m.Id == activeMod.Id && m.Version != activeMod.Version))
                        {
                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed to parse mod metadata file '{0}'", path);
                        Log.Write("debug", e.ToString());
                    }

                    // Remove from the ingame mod switcher
                    if (Path.GetFileNameWithoutExtension(path) == modKey)
                    {
                        mods.Remove(modKey);
                    }

                    // Remove stale or corrupted metadata
                    try
                    {
                        File.Delete(path);
                        Log.Write("debug", "Removed invalid mod metadata file '{0}'", path);
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed to remove mod metadata file '{0}'", path);
                        Log.Write("debug", e.ToString());
                    }
                }
            }
        }
Exemplo n.º 19
0
        public void UpdateRemoteSearch(MapStatus status, MiniYaml yaml, Action <MapPreview> parseMetadata = null)
        {
            var newData = innerData.Clone();

            newData.Status = status;
            newData.Class  = MapClassification.Remote;

            if (status == MapStatus.DownloadAvailable)
            {
                try
                {
                    var r = FieldLoader.Load <RemoteMapData>(yaml);

                    // Map download has been disabled server side
                    if (!r.downloading)
                    {
                        newData.Status = MapStatus.Unavailable;
                        return;
                    }

                    newData.Title       = r.title;
                    newData.Categories  = r.categories;
                    newData.Author      = r.author;
                    newData.PlayerCount = r.players;
                    newData.Bounds      = r.bounds;
                    newData.TileSet     = r.tileset;

                    var spawns = new CPos[r.spawnpoints.Length / 2];
                    for (var j = 0; j < r.spawnpoints.Length; j += 2)
                    {
                        spawns[j / 2] = new CPos(r.spawnpoints[j], r.spawnpoints[j + 1]);
                    }
                    newData.SpawnPoints = spawns;
                    newData.GridType    = r.map_grid_type;
                    try
                    {
                        newData.Preview = new Png(new MemoryStream(Convert.FromBase64String(r.minimap)));
                    }
                    catch (Exception e)
                    {
                        Log.Write("debug", "Failed parsing mapserver minimap response: {0}", e);
                        newData.Preview = null;
                    }

                    var playersString = Encoding.UTF8.GetString(Convert.FromBase64String(r.players_block));
                    newData.Players = new MapPlayers(MiniYaml.FromString(playersString));

                    newData.SetRulesetGenerator(modData, () =>
                    {
                        var rulesString              = Encoding.UTF8.GetString(Convert.FromBase64String(r.rules));
                        var rulesYaml                = new MiniYaml("", MiniYaml.FromString(rulesString)).ToDictionary();
                        var ruleDefinitions          = LoadRuleSection(rulesYaml, "Rules");
                        var weaponDefinitions        = LoadRuleSection(rulesYaml, "Weapons");
                        var voiceDefinitions         = LoadRuleSection(rulesYaml, "Voices");
                        var musicDefinitions         = LoadRuleSection(rulesYaml, "Music");
                        var notificationDefinitions  = LoadRuleSection(rulesYaml, "Notifications");
                        var sequenceDefinitions      = LoadRuleSection(rulesYaml, "Sequences");
                        var modelSequenceDefinitions = LoadRuleSection(rulesYaml, "ModelSequences");
                        var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
                                                 voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
                        var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
                                                                       weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
                        return(Pair.New(rules, flagged));
                    });
                }
                catch (Exception e)
                {
                    Log.Write("debug", "Failed parsing mapserver response: {0}", e);
                }

                // Commit updated data before running the callbacks
                innerData = newData;

                if (innerData.Preview != null)
                {
                    cache.CacheMinimap(this);
                }

                if (parseMetadata != null)
                {
                    parseMetadata(this);
                }
            }

            // Update the status and class unconditionally
            innerData = newData;
        }
Exemplo n.º 20
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;
            }

            // Load players
            foreach (var kv in yaml.NodesDict["Players"].NodesDict)
            {
                var player = new PlayerReference(kv.Value);
                Players.Add(player.Name, player);
            }

            Actors = Exts.Lazy(() =>
            {
                var ret = new Dictionary <string, ActorReference>();
                foreach (var kv in yaml.NodesDict["Actors"].NodesDict)
                {
                    ret.Add(kv.Key, new ActorReference(kv.Value.Value, kv.Value.NodesDict));
                }
                return(ret);
            });

            // Smudges
            Smudges = Exts.Lazy(() =>
            {
                var ret = new List <SmudgeReference>();
                foreach (var kv in yaml.NodesDict["Smudges"].NodesDict)
                {
                    var vals = kv.Key.Split(' ');
                    var loc  = vals[1].Split(',');
                    ret.Add(new SmudgeReference(vals[0], new int2(
                                                    Exts.ParseIntegerInvariant(loc[0]),
                                                    Exts.ParseIntegerInvariant(loc[1])),
                                                Exts.ParseIntegerInvariant(vals[2])));
                }

                return(ret);
            });

            RuleDefinitions          = MiniYaml.NodesOrEmpty(yaml, "Rules");
            SequenceDefinitions      = MiniYaml.NodesOrEmpty(yaml, "Sequences");
            VoxelSequenceDefinitions = MiniYaml.NodesOrEmpty(yaml, "VoxelSequences");
            WeaponDefinitions        = MiniYaml.NodesOrEmpty(yaml, "Weapons");
            VoiceDefinitions         = MiniYaml.NodesOrEmpty(yaml, "Voices");
            NotificationDefinitions  = MiniYaml.NodesOrEmpty(yaml, "Notifications");
            TranslationDefinitions   = MiniYaml.NodesOrEmpty(yaml, "Translations");

            CustomTerrain = new string[MapSize.X, MapSize.Y];

            MapTiles     = Exts.Lazy(() => LoadMapTiles());
            MapResources = Exts.Lazy(() => LoadResourceTiles());

            // The Uid is calculated from the data on-disk, so
            // format changes must be flushed to disk.
            // TODO: this isn't very nice
            if (MapFormat < 6)
            {
                Save(path);
            }

            Uid = ComputeHash();

            if (Container.Exists("map.png"))
            {
                CustomPreview = new Bitmap(Container.GetContent("map.png"));
            }

            PostInit();
        }