static Dictionary<string, string[]> Load(MiniYaml y, string name) { var nd = y.ToDictionary(); return nd.ContainsKey(name) ? nd[name].ToDictionary(my => FieldLoader.GetValue<string[]>("(value)", my.Value)) : new Dictionary<string, string[]>(); }
public ActorInfo(string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits) { try { var allParents = new HashSet<string>(); var abstractActorType = name.StartsWith("^"); // Guard against circular inheritance allParents.Add(name); var mergedNode = MergeWithParents(node, allUnits, allParents).ToDictionary(); Name = name; foreach (var t in mergedNode) { if (t.Key[0] == '-') throw new YamlException("Bogus trait removal: " + t.Key); if (t.Key != "Inherits" && !t.Key.StartsWith("Inherits@")) try { Traits.Add(LoadTraitInfo(t.Key.Split('@')[0], t.Value)); } catch (FieldLoader.MissingFieldsException e) { if (!abstractActorType) throw new YamlException(e.Message); } } } catch (YamlException e) { throw new YamlException("Actor type {0}: {1}".F(name, e.Message)); } }
public SoundInfo(MiniYaml y) { FieldLoader.Load(this, y); VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(a.Value))); NotificationsPools = Exts.Lazy(() => Notifications.ToDictionary(a => a.Key, a => new SoundPool(a.Value))); }
void MergeAndPrint(Map map, string key, MiniYaml value) { var nodes = new List<MiniYamlNode>(); var includes = new List<string>(); if (value != null && value.Value != null) { // The order of the included files matter, so we can defer to system files // only as long as they are included first. var include = false; var files = FieldLoader.GetValue<string[]>("value", value.Value); foreach (var f in files) { include |= map.Package.Contains(f); if (include) nodes.AddRange(MiniYaml.FromStream(map.Open(f))); else includes.Add(f); } } if (value != null) nodes.AddRange(value.Nodes); var output = new MiniYaml(includes.JoinWith(", "), nodes); Console.WriteLine(output.ToLines(key).JoinWith("\n")); }
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[] { }; if (sequences.NodesDict.ContainsKey("ShadowIndex")) { Array.Resize(ref shadowIndex, shadowIndex.Length + 1); Exts.TryParseIntegerInvariant(sequences.NodesDict["ShadowIndex"].Value, out shadowIndex[shadowIndex.Length - 1]); } palette = new HardwarePalette(); foreach (var p in sequences.NodesDict["Palettes"].Nodes) palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed)); foreach (var s in sequences.NodesDict["Cursors"].Nodes) LoadSequencesForCursor(spriteLoader, s.Key, s.Value); palette.Initialize(); }
static void ProcessYaml(ModData modData, Map map, MiniYaml yaml, int engineDate, UpgradeAction processYaml) { if (yaml == null) return; if (yaml.Value != null) { var files = FieldLoader.GetValue<string[]>("value", yaml.Value); foreach (var filename in files) { var fileNodes = MiniYaml.FromStream(map.Open(filename), filename); processYaml(modData, engineDate, ref fileNodes, null, 0); // HACK: Obtain the writable save path using knowledge of the underlying filesystem workings var packagePath = filename; var package = map.Package; if (filename.Contains("|")) modData.DefaultFileSystem.TryGetPackageContaining(filename, out package, out packagePath); ((IReadWritePackage)package).Update(packagePath, Encoding.ASCII.GetBytes(fileNodes.WriteToString())); } } processYaml(modData, engineDate, ref yaml.Nodes, null, 1); }
public CursorProvider(ModData modData) { var fileSystem = modData.DefaultFileSystem; var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select( s => MiniYaml.FromStream(fileSystem.Open(s), s))); var shadowIndex = new int[] { }; var nodesDict = new MiniYaml(null, sequenceYaml).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(fileSystem.Open(p.Value.Value), shadowIndex)); Palettes = palettes.AsReadOnly(); var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders); var cursors = new Dictionary<string, CursorSequence>(); foreach (var s in nodesDict["Cursors"].Nodes) foreach (var sequence in s.Value.Nodes) cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value)); Cursors = cursors.AsReadOnly(); }
static Dictionary<string, ModMetadata> ValidateMods() { var basePath = Platform.ResolvePath(".", "mods"); var mods = Directory.GetDirectories(basePath) .Select(x => x.Substring(basePath.Length + 1)); var ret = new Dictionary<string, ModMetadata>(); foreach (var m in mods) { var yamlPath = Platform.ResolvePath(".", "mods", m, "mod.yaml"); if (!File.Exists(yamlPath)) continue; var yaml = new MiniYaml(null, MiniYaml.FromFile(yamlPath)); var nd = yaml.ToDictionary(); if (!nd.ContainsKey("Metadata")) continue; var mod = FieldLoader.Load<ModMetadata>(nd["Metadata"]); mod.Id = m; ret.Add(m, mod); } return ret; }
public TerrainTemplateInfo(TileSet tileSet, MiniYaml my) { FieldLoader.Load(this, my); var nodes = my.ToDictionary()["Tiles"].Nodes; if (!PickAny) { tileInfo = new TerrainTileInfo[Size.X * Size.Y]; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key < 0 || key >= tileInfo.Length) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tileInfo[key] = LoadTileInfo(tileSet, node.Value); } } else { tileInfo = new TerrainTileInfo[nodes.Count]; var i = 0; foreach (var node in nodes) { int key; if (!int.TryParse(node.Key, out key) || key != i++) throw new InvalidDataException("Invalid tile key '{0}' on template '{1}' of tileset '{2}'.".F(node.Key, Id, tileSet.Id)); tileInfo[key] = LoadTileInfo(tileSet, node.Value); } } }
public 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(); }
public MappedImage(string defaultSrc, MiniYaml info) { FieldLoader.LoadField(this, "rect", info.Value); FieldLoader.Load(this, info); if (src == null) src = defaultSrc; }
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>(); }
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[]>(); }
static object LoadSpeeds(MiniYaml y) { var ret = new Dictionary<string, GameSpeed>(); foreach (var node in y.Nodes) ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value)); return ret; }
static object LoadProjectile(MiniYaml yaml) { MiniYaml proj; if (!yaml.ToDictionary().TryGetValue("Projectile", out proj)) return null; var ret = Game.CreateObject<IProjectileInfo>(proj.Value + "Info"); FieldLoader.Load(ret, proj); return ret; }
static object LoadConsiderations(MiniYaml yaml) { var ret = new List<Consideration>(); foreach (var d in yaml.Nodes) if (d.Key.Split('@')[0] == "Consideration") ret.Add(new Consideration(d.Value)); return ret; }
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my) { if (!string.IsNullOrEmpty(my.Value)) throw new YamlException("Junk value `{0}` on trait node {1}" .F(my.Value, traitName)); var info = Game.CreateObject<ITraitInfo>(traitName + "Info"); FieldLoader.Load(info, my); return info; }
static object LoadOptions(MiniYaml y) { var options = new MapOptions(); var nodesDict = y.ToDictionary(); if (nodesDict.ContainsKey("Options")) FieldLoader.Load(options, nodesDict["Options"]); return options; }
static object LoadPackages(MiniYaml yaml) { var packages = new Dictionary<string, ModPackage>(); var packageNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Packages"); if (packageNode != null) foreach (var node in packageNode.Value.Nodes) packages.Add(node.Key, new ModPackage(node.Value)); return packages; }
void TestMixedMerge(MiniYaml result) { Console.WriteLine(result.ToLines("result").JoinWith("\n")); Assert.That(result.Nodes.Any(n => n.Key == "FromA"), Is.True, "Node from A"); Assert.That(result.Nodes.Any(n => n.Key == "FromB"), Is.True, "Node from B"); Assert.That(result.Nodes.Any(n => n.Key == "FromARemovedA"), Is.Not.True, "Node from A removed by A"); Assert.That(result.Nodes.Any(n => n.Key == "FromARemovedB"), Is.Not.True, "Node from A removed by B"); Assert.That(result.Nodes.Any(n => n.Key == "FromBRemovedA"), Is.Not.True, "Node from B removed by A"); Assert.That(result.Nodes.Any(n => n.Key == "FromBRemovedB"), Is.Not.True, "Node from B removed by B"); }
public MiniYaml Save() { var ret = new MiniYaml( Type ); foreach( var init in InitDict ) { var initName = init.GetType().Name; ret.Nodes.Add( new MiniYamlNode( initName.Substring( 0, initName.Length - 4 ), FieldSaver.Save( init ) ) ); } return ret; }
static void LoadVoxelsForUnit(string unit, MiniYaml sequences) { Game.ModData.LoadScreen.Display(); try { var seq = sequences.ToDictionary(my => LoadVoxel(unit, my)); units.Add(unit, seq); } catch (FileNotFoundException) { } // Do nothing; we can crash later if we actually wanted art }
public MapGrid(MiniYaml yaml) { FieldLoader.Load(this, yaml); // The default subcell index defaults to the middle entry if (SubCellDefaultIndex == byte.MaxValue) SubCellDefaultIndex = (byte)(SubCellOffsets.Length / 2); else 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"); }
static void LoadCollection(string name, MiniYaml yaml) { Game.modData.LoadScreen.Display(); var collection = new Collection() { src = yaml.Value, regions = yaml.Nodes.ToDictionary(n => n.Key, n => new MappedImage(yaml.Value, n.Value)) }; collections.Add(name, collection); }
static object LoadPercents(MiniYaml y) { MiniYaml percents; if (!y.ToDictionary().TryGetValue("TerrainModifier", out percents)) return new Dictionary<string, int>(); return percents.Nodes.ToDictionary( kv => FieldLoader.GetValue<string>("(key)", kv.Key), kv => FieldLoader.GetValue<int>("(value)", kv.Value.Value)); }
public SoundInfo( MiniYaml y ) { FieldLoader.Load( this, y ); Variants = Load(y, "Variants"); Prefixes = Load(y, "Prefixes"); Voices = Load(y, "Voices"); Notifications = Load(y, "Notifications"); VoicePools = Exts.Lazy(() => Voices.ToDictionary(a => a.Key, a => new SoundPool(a.Value))); NotificationsPools = Exts.Lazy(() => Notifications.ToDictionary( a => a.Key, a => new SoundPool(a.Value) )); }
static object LoadWarheads(MiniYaml yaml) { var retList = new List<IWarhead>(); foreach (var node in yaml.Nodes.Where(n => n.Key.StartsWith("Warhead"))) { var ret = Game.CreateObject<IWarhead>(node.Value.Value + "Warhead"); FieldLoader.Load(ret, node.Value); retList.Add(ret); } return retList; }
static MiniYaml MergeWithParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits ) { var parent = GetParent( node, allUnits ); if (parent != null) { var result = MiniYaml.MergeStrict(node, MergeWithParent(parent, allUnits)); // strip the '-' result.Nodes.RemoveAll(a => a.Key.StartsWith("-")); return result; } return node; }
public MissionBrowserLogic(Widget widget, Action onStart, Action onExit) { this.onStart = onStart; var missionList = widget.Get<ScrollPanelWidget>("MISSION_LIST"); var template = widget.Get<ScrollItemWidget>("MISSION_TEMPLATE"); widget.Get("MISSION_INFO").IsVisible = () => selectedMapPreview != null; var previewWidget = widget.Get<MapPreviewWidget>("MISSION_PREVIEW"); previewWidget.Preview = () => selectedMapPreview; descriptionPanel = widget.Get<ScrollPanelWidget>("MISSION_DESCRIPTION_PANEL"); description = widget.Get<LabelWidget>("MISSION_DESCRIPTION"); descriptionFont = Game.Renderer.Fonts[description.Font]; var yaml = new MiniYaml(null, Game.modData.Manifest.Missions.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal)).ToDictionary(); var missionMapPaths = yaml["Missions"].Nodes.Select(n => Path.GetFullPath(n.Key)); var maps = Game.modData.MapCache .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Map.Path))) .Select(p => p.Map); missionList.RemoveChildren(); foreach (var m in maps) { var map = m; var item = ScrollItemWidget.Setup(template, () => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid, () => SelectMap(map), StartMission); item.Get<LabelWidget>("TITLE").GetText = () => map.Title; missionList.AddChild(item); } if (maps.Any()) SelectMap(maps.First()); widget.Get<ButtonWidget>("STARTGAME_BUTTON").OnClick = StartMission; widget.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => { Game.Disconnect(); Ui.CloseWindow(); onExit(); }; }
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits ) { MiniYaml inherits; node.ToDictionary().TryGetValue( "Inherits", out inherits ); if( inherits == null || string.IsNullOrEmpty( inherits.Value ) ) return null; MiniYaml parent; allUnits.TryGetValue( inherits.Value, out parent ); if (parent == null) throw new InvalidOperationException( "Bogus inheritance -- actor type {0} does not exist".F(inherits.Value)); return parent; }
public ClassicTilesetSpecificSpriteSequence(ModData modData, TileSet tileSet, SpriteCache cache, ISpriteSequenceLoader loader, string sequence, string animation, MiniYaml info) : base(modData, tileSet, cache, loader, sequence, animation, info) { }
static object LoadBuildings(MiniYaml y) { return(LoadActorList(y, "BuildingFractions")); }
void CheckMapYaml(Action <string> emitError, Action <string> emitWarning, ModData modData, IReadOnlyFileSystem fileSystem, MiniYaml weaponDefinitions) { if (weaponDefinitions == null) { return; } var mapFiles = FieldLoader.GetValue <string[]>("value", weaponDefinitions.Value); foreach (var f in mapFiles) { CheckWeapons(MiniYaml.FromStream(fileSystem.Open(f), f), emitError, emitWarning, modData); } if (weaponDefinitions.Nodes.Any()) { CheckWeapons(weaponDefinitions.Nodes, emitError, emitWarning, modData); } }
public void RefreshServerList() { // Query in progress if (currentQuery != null) { return; } searchStatus = SearchStatus.Fetching; Action <DownloadDataCompletedEventArgs> onComplete = i => { currentQuery = null; List <GameServer> games = null; if (i.Error == null) { try { var data = Encoding.UTF8.GetString(i.Result); var yaml = MiniYaml.FromString(data); games = yaml.Select(a => new GameServer(a.Value)) .Where(gs => gs.Address != null) .ToList(); } catch { searchStatus = SearchStatus.Failed; } } var lanGames = new List <GameServer>(); foreach (var bl in lanGameLocations) { try { if (string.IsNullOrEmpty(bl.Data)) { continue; } var game = MiniYaml.FromString(bl.Data)[0].Value; var idNode = game.Nodes.FirstOrDefault(n => n.Key == "Id"); // Skip beacons created by this instance and replace Id by expected int value if (idNode != null && idNode.Value.Value != Platform.SessionGUID.ToString()) { idNode.Value.Value = "-1"; // Rewrite the server address with the correct IP var addressNode = game.Nodes.FirstOrDefault(n => n.Key == "Address"); if (addressNode != null) { addressNode.Value.Value = bl.Address.ToString().Split(':')[0] + ":" + addressNode.Value.Value.Split(':')[1]; } lanGames.Add(new GameServer(game)); } } catch { // Ignore any invalid LAN games advertised. } } var groupedLanGames = lanGames.GroupBy(gs => gs.Address).Select(g => g.Last()); if (games != null) { games.AddRange(groupedLanGames); } else if (groupedLanGames.Any()) { games = groupedLanGames.ToList(); } Game.RunAfterTick(() => RefreshServerListInner(games)); }; var queryURL = services.ServerList + "?protocol={0}&engine={1}&mod={2}&version={3}".F( GameServer.ProtocolVersion, Uri.EscapeUriString(Game.EngineVersion), Uri.EscapeUriString(Game.ModData.Manifest.Id), Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version)); currentQuery = new Download(queryURL, _ => { }, onComplete); }
public static Squad Deserialize(IBot bot, SquadManagerBotModule squadManager, MiniYaml yaml) { var type = SquadType.Rush; Actor targetActor = null; var typeNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Type"); if (typeNode != null) { type = FieldLoader.GetValue <SquadType>("Type", typeNode.Value.Value); } var targetNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Target"); if (targetNode != null) { targetActor = squadManager.World.GetActorById(FieldLoader.GetValue <uint>("ActiveUnits", targetNode.Value.Value)); } var squad = new Squad(bot, squadManager, type, targetActor); var unitsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Units"); if (unitsNode != null) { squad.Units.AddRange(FieldLoader.GetValue <uint[]>("Units", unitsNode.Value.Value) .Select(a => squadManager.World.GetActorById(a))); } return(squad); }
public static Slot Deserialize(MiniYaml data) { return(FieldLoader.Load <Slot>(data)); }
static void ExtractFromPackage(ExtractionType type, string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage) { var sourcePath = Path.Combine(path, actionYaml.Value); // Try as an absolute path if (!File.Exists(sourcePath)) { sourcePath = Platform.ResolvePath(actionYaml.Value); } using (var source = File.OpenRead(sourcePath)) { foreach (var node in actionYaml.Nodes) { var targetPath = Platform.ResolvePath(node.Key); if (File.Exists(targetPath)) { Log.Write("install", "Skipping installed file " + targetPath); continue; } var offsetNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Offset"); if (offsetNode == null) { Log.Write("install", "Skipping entry with missing Offset definition " + targetPath); continue; } var lengthNode = node.Value.Nodes.FirstOrDefault(n => n.Key == "Length"); if (lengthNode == null) { Log.Write("install", "Skipping entry with missing Length definition " + targetPath); continue; } var length = FieldLoader.GetValue <int>("Length", lengthNode.Value.Value); source.Position = FieldLoader.GetValue <int>("Offset", offsetNode.Value.Value); extractedFiles.Add(targetPath); Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); Action <long> onProgress = null; if (length < ShowPercentageThreshold) { updateMessage("Extracting " + displayFilename); } else { onProgress = b => updateMessage("Extracting " + displayFilename + " ({0}%)".F(100 * b / length)); } using (var target = File.OpenWrite(targetPath)) { Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath)); if (type == ExtractionType.Blast) { Action <long, long> onBlastProgress = (read, _) => { if (onProgress != null) { onProgress(read); } }; Blast.Decompress(source, target, onBlastProgress); } else { CopyStream(source, target, length, onProgress); } } } } }
/// <summary> /// Loads a YamlFileSet containing any internal definitions yaml referenced by a map yaml block. /// External references or internal references to missing files are ignored. /// </summary> static YamlFileSet LoadInternalMapYaml(ModData modData, IReadWritePackage mapPackage, MiniYaml yaml, HashSet <string> externalFilenames) { var fileSet = new YamlFileSet() { Tuple.Create <IReadWritePackage, string, List <MiniYamlNode> >(null, "map.yaml", yaml.Nodes) }; var files = FieldLoader.GetValue <string[]>("value", yaml.Value); foreach (var filename in files) { // Ignore any files that aren't in the map bundle if (!filename.Contains("|") && mapPackage.Contains(filename)) { fileSet.Add(Tuple.Create(mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename, false))); } else if (modData.ModFiles.Exists(filename)) { externalFilenames.Add(filename); } } return(fileSet); }
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)); } }
public void RefreshServerList() { // Query in progress if (activeQuery) { return; } searchStatus = SearchStatus.Fetching; var queryURL = new HttpQueryBuilder(services.ServerList) { { "protocol", GameServer.ProtocolVersion }, { "engine", Game.EngineVersion }, { "mod", Game.ModData.Manifest.Id }, { "version", Game.ModData.Manifest.Metadata.Version } }.ToString(); Task.Run(async() => { var games = new List <GameServer>(); var client = HttpClientFactory.Create(); var httpResponseMessage = await client.GetAsync(queryURL); var result = await httpResponseMessage.Content.ReadAsStringAsync(); activeQuery = true; try { var yaml = MiniYaml.FromString(result); foreach (var node in yaml) { try { var gs = new GameServer(node.Value); if (gs.Address != null) { games.Add(gs); } } catch { // Ignore any invalid games advertised. } } } catch { searchStatus = SearchStatus.Failed; } var lanGames = new List <GameServer>(); foreach (var bl in lanGameLocations) { try { if (string.IsNullOrEmpty(bl.Data)) { continue; } var game = MiniYaml.FromString(bl.Data)[0].Value; var idNode = game.Nodes.FirstOrDefault(n => n.Key == "Id"); // Skip beacons created by this instance and replace Id by expected int value if (idNode != null && idNode.Value.Value != Platform.SessionGUID.ToString()) { idNode.Value.Value = "-1"; // Rewrite the server address with the correct IP var addressNode = game.Nodes.FirstOrDefault(n => n.Key == "Address"); if (addressNode != null) { addressNode.Value.Value = bl.Address.ToString().Split(':')[0] + ":" + addressNode.Value.Value.Split(':')[1]; } game.Nodes.Add(new MiniYamlNode("Location", "Local Network")); lanGames.Add(new GameServer(game)); } } catch { // Ignore any invalid LAN games advertised. } } var groupedLanGames = lanGames.GroupBy(gs => gs.Address).Select(g => g.Last()); if (games != null) { games.AddRange(groupedLanGames); } else if (groupedLanGames.Any()) { games = groupedLanGames.ToList(); } Game.RunAfterTick(() => RefreshServerListInner(games)); activeQuery = false; }); }
public void Run(ModData modData, string[] args) { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; Game.ModData.MapCache.LoadMaps(); var engineDate = Exts.ParseIntegerInvariant(args[1]); Console.WriteLine("Processing Rules:"); foreach (var filename in Game.ModData.Manifest.Rules) { Console.WriteLine("\t" + filename); var yaml = MiniYaml.FromFile(filename); UpgradeRules.UpgradeActorRules(engineDate, ref yaml, null, 0); using (var file = new StreamWriter(filename)) file.WriteLine(yaml.WriteToString()); } Console.WriteLine("Processing Weapons:"); foreach (var filename in Game.ModData.Manifest.Weapons) { Console.WriteLine("\t" + filename); var yaml = MiniYaml.FromFile(filename); UpgradeRules.UpgradeWeaponRules(engineDate, ref yaml, null, 0); using (var file = new StreamWriter(filename)) file.WriteLine(yaml.WriteToString()); } Console.WriteLine("Processing Tilesets:"); foreach (var filename in Game.ModData.Manifest.TileSets) { Console.WriteLine("\t" + filename); var yaml = MiniYaml.FromFile(filename); UpgradeRules.UpgradeTileset(engineDate, ref yaml, null, 0); using (var file = new StreamWriter(filename)) file.WriteLine(yaml.WriteToString()); } Console.WriteLine("Processing Cursors:"); foreach (var filename in Game.ModData.Manifest.Cursors) { Console.WriteLine("\t" + filename); var yaml = MiniYaml.FromFile(filename); UpgradeRules.UpgradeCursors(engineDate, ref yaml, null, 0); using (var file = new StreamWriter(filename)) file.WriteLine(yaml.WriteToString()); } Console.WriteLine("Processing Maps:"); var maps = Game.ModData.MapCache .Where(m => m.Status == MapStatus.Available) .Select(m => m.Map); foreach (var map in maps) { Console.WriteLine("\t" + map.Path); UpgradeRules.UpgradeActorRules(engineDate, ref map.RuleDefinitions, null, 0); UpgradeRules.UpgradeWeaponRules(engineDate, ref map.WeaponDefinitions, null, 0); map.Save(map.Path); } }
public ResourceTypeInfo(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
static object LoadBuildingLimits(MiniYaml y) { return(LoadList <int>(y, "BuildingLimits")); }
public override ISpriteSequence CreateSequence(ModData modData, TileSet tileSet, SpriteCache cache, string sequence, string animation, MiniYaml info) { return(new ClassicTilesetSpecificSpriteSequence(modData, tileSet, cache, this, sequence, animation, info)); }
static void ExtractFromISCab(string path, MiniYaml actionYaml, List <string> extractedFiles, Action <string> updateMessage) { var sourcePath = Path.Combine(path, actionYaml.Value); // Try as an absolute path if (!File.Exists(sourcePath)) { sourcePath = Platform.ResolvePath(actionYaml.Value); } var volumeNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Volumes"); if (volumeNode == null) { throw new InvalidDataException("extract-iscab entry doesn't define a Volumes node"); } var extractNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Extract"); if (extractNode == null) { throw new InvalidDataException("extract-iscab entry doesn't define an Extract node"); } var volumes = new Dictionary <int, Stream>(); try { foreach (var node in volumeNode.Value.Nodes) { var volume = FieldLoader.GetValue <int>("(key)", node.Key); var stream = File.OpenRead(Path.Combine(path, node.Value.Value)); volumes.Add(volume, stream); } using (var source = File.OpenRead(sourcePath)) { var reader = new InstallShieldCABCompression(source, volumes); foreach (var node in extractNode.Value.Nodes) { var targetPath = Platform.ResolvePath(node.Key); if (File.Exists(targetPath)) { Log.Write("install", "Skipping installed file " + targetPath); continue; } extractedFiles.Add(targetPath); Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); using (var target = File.OpenWrite(targetPath)) { Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath)); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); Action <int> onProgress = percent => updateMessage("Extracting {0} ({1}%)".F(displayFilename, percent)); reader.ExtractFile(node.Value.Value, target, onProgress); } } } } finally { foreach (var kv in volumes) { kv.Value.Dispose(); } } }
public Consideration(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
public GameServer(MiniYaml yaml) { FieldLoader.Load(this, yaml); // Games advertised using the old API used a single Mods field if (Mod == null || Version == null) { var modsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Mods"); if (modsNode != null) { var modVersion = modsNode.Value.Value.Split('@'); Mod = modVersion[0]; Version = modVersion[1]; } } // Games advertised using the old API calculated the play time locally if (State == 2 && PlayTime < 0) { DateTime startTime; if (DateTime.TryParse(Started, out startTime)) { PlayTime = (int)(DateTime.UtcNow - startTime).TotalSeconds; } } ExternalMod external; var externalKey = ExternalMod.MakeKey(Mod, Version); if (Game.ExternalMods.TryGetValue(externalKey, out external) && external.Version == Version) { IsCompatible = true; } // Games advertised using the old API used local mod metadata if (string.IsNullOrEmpty(ModTitle)) { Manifest mod; if (external != null && external.Version == Version) { // Use external mod registration to populate the section header ModTitle = external.Title; } else if (Game.Mods.TryGetValue(Mod, out mod)) { // Use internal mod data to populate the section header, but // on-connect switching must use the external mod plumbing. ModTitle = mod.Metadata.Title; } else { // Some platforms (e.g. macOS) package each mod separately, so the Mods check above won't work. // Guess based on the most recent ExternalMod instead. var guessMod = Game.ExternalMods.Values .OrderByDescending(m => m.Version) .FirstOrDefault(m => m.Id == Mod); if (guessMod != null) { ModTitle = "{0}".F(guessMod.Title); } else { ModTitle = "Unknown mod: {0}".F(Mod); } } } var mapAvailable = Game.Settings.Game.AllowDownloading || Game.ModData.MapCache[Map].Status == MapStatus.Available; IsJoinable = IsCompatible && State == 1 && mapAvailable; }
public SupportPowerDecision(MiniYaml yaml) { FieldLoader.Load(this, yaml); }
public static ClientPing Deserialize(MiniYaml data) { return(FieldLoader.Load <ClientPing>(data)); }
public SequenceProvider(IReadOnlyFileSystem fileSystem, ModData modData, TileSet tileSet, MiniYaml additionalSequences) { this.modData = modData; this.tileSet = tileSet; sequences = Exts.Lazy(() => { using (new Support.PerfTimer("LoadSequences")) return(Load(fileSystem, additionalSequences)); }); spriteCache = Exts.Lazy(() => new SpriteCache(fileSystem, modData.SpriteLoaders)); }
static object LoadUnits(MiniYaml y) { return(LoadList <float>(y, "UnitsToBuild")); }
static object LoadBuildings(MiniYaml y) { return(LoadList <float>(y, "BuildingFractions")); }
public void Run(Action <string> emitError, Action <string> emitWarning, Map map) { if (map.SequenceDefinitions == null) { return; } var modData = Game.ModData; this.emitError = emitError; sequenceDefinitions = MiniYaml.Load(map, modData.Manifest.Sequences, map.SequenceDefinitions); var rules = map.Rules; var factions = rules.Actors["world"].TraitInfos <FactionInfo>().Select(f => f.InternalName).ToArray(); var sequenceProviders = new[] { rules.Sequences }; foreach (var actorInfo in rules.Actors) { foreach (var renderInfo in actorInfo.Value.TraitInfos <RenderSpritesInfo>()) { foreach (var faction in factions) { foreach (var sequenceProvider in sequenceProviders) { var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, faction); if (sequenceDefinitions.All(s => s.Key != image.ToLowerInvariant()) && !actorInfo.Value.Name.Contains("^")) { emitError("Sprite image {0} from actor {1} using faction {2} has no sequence definition." .F(image, actorInfo.Value.Name, faction)); } } } } foreach (var traitInfo in actorInfo.Value.TraitInfos <ITraitInfo>()) { var fields = traitInfo.GetType().GetFields(); foreach (var field in fields) { if (field.HasAttribute <SequenceReferenceAttribute>()) { var sequences = LintExts.GetFieldValues(traitInfo, field, emitError); foreach (var sequence in sequences) { if (string.IsNullOrEmpty(sequence)) { continue; } var renderInfo = actorInfo.Value.TraitInfos <RenderSpritesInfo>().FirstOrDefault(); if (renderInfo == null) { continue; } foreach (var faction in factions) { var sequenceReference = field.GetCustomAttributes <SequenceReferenceAttribute>(true).FirstOrDefault(); if (sequenceReference != null && !string.IsNullOrEmpty(sequenceReference.ImageReference)) { var imageField = fields.FirstOrDefault(f => f.Name == sequenceReference.ImageReference); if (imageField != null) { foreach (var imageOverride in LintExts.GetFieldValues(traitInfo, imageField, emitError)) { if (!string.IsNullOrEmpty(imageOverride) && sequenceDefinitions.All(s => s.Key != imageOverride.ToLowerInvariant())) { emitError("Custom sprite image {0} from actor {1} has no sequence definition.".F(imageOverride, actorInfo.Value.Name)); } else { CheckDefintions(imageOverride, sequenceReference, actorInfo, sequence, faction, field, traitInfo); } } } } else { foreach (var sequenceProvider in sequenceProviders) { var image = renderInfo.GetImage(actorInfo.Value, sequenceProvider, faction); CheckDefintions(image, sequenceReference, actorInfo, sequence, faction, field, traitInfo); } } } } } } } foreach (var weaponInfo in rules.Weapons) { var projectileInfo = weaponInfo.Value.Projectile; if (projectileInfo == null) { continue; } var fields = projectileInfo.GetType().GetFields(); foreach (var field in fields) { if (field.HasAttribute <SequenceReferenceAttribute>()) { var sequences = LintExts.GetFieldValues(projectileInfo, field, emitError); foreach (var sequence in sequences) { if (string.IsNullOrEmpty(sequence)) { continue; } var sequenceReference = field.GetCustomAttributes <SequenceReferenceAttribute>(true).FirstOrDefault(); if (sequenceReference != null && !string.IsNullOrEmpty(sequenceReference.ImageReference)) { var imageField = fields.FirstOrDefault(f => f.Name == sequenceReference.ImageReference); if (imageField != null) { foreach (var imageOverride in LintExts.GetFieldValues(projectileInfo, imageField, emitError)) { if (!string.IsNullOrEmpty(imageOverride)) { var definitions = sequenceDefinitions.FirstOrDefault(n => n.Key == imageOverride.ToLowerInvariant()); if (definitions == null) { emitError("Can't find sequence definition for projectile image {0} at weapon {1}.".F(imageOverride, weaponInfo.Key)); } else if (!definitions.Value.Nodes.Any(n => n.Key == sequence)) { emitError("Projectile sprite image {0} from weapon {1} does not define sequence {2} from field {3} of {4}" .F(imageOverride, weaponInfo.Key, sequence, field.Name, projectileInfo)); } } } } } } } } } } }
static void ExtractSmudges(MiniYaml yaml) { var smudges = yaml.Nodes.FirstOrDefault(n => n.Key == "Smudges"); if (smudges == null || !smudges.Value.Nodes.Any()) { return; } var scorches = new List <MiniYamlNode>(); var craters = new List <MiniYamlNode>(); foreach (var s in smudges.Value.Nodes) { // loc=type,loc,depth var parts = s.Key.Split(' '); var value = "{0},{1}".F(parts[0], parts[2]); var node = new MiniYamlNode(parts[1], value); if (parts[0].StartsWith("sc")) { scorches.Add(node); } else if (parts[0].StartsWith("cr")) { craters.Add(node); } } var rulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules"); if (rulesNode == null) { rulesNode = new MiniYamlNode("Rules", new MiniYaml("", new List <MiniYamlNode>())); yaml.Nodes.Add(rulesNode); } var worldNode = rulesNode.Value.Nodes.FirstOrDefault(n => n.Key == "World"); if (worldNode == null) { worldNode = new MiniYamlNode("World", new MiniYaml("", new List <MiniYamlNode>())); rulesNode.Value.Nodes.Add(rulesNode); } if (scorches.Any()) { var initialScorches = new MiniYamlNode("InitialSmudges", new MiniYaml("", scorches)); var smudgeLayer = new MiniYamlNode("SmudgeLayer@SCORCH", new MiniYaml("", new List <MiniYamlNode>() { initialScorches })); worldNode.Value.Nodes.Add(smudgeLayer); } if (craters.Any()) { var initialCraters = new MiniYamlNode("InitialSmudges", new MiniYaml("", craters)); var smudgeLayer = new MiniYamlNode("SmudgeLayer@CRATER", new MiniYaml("", new List <MiniYamlNode>() { initialCraters })); worldNode.Value.Nodes.Add(smudgeLayer); } }
public ModContentPromptLogic(Widget widget, Manifest mod, ModContent content, Action continueLoading) { this.content = content; CheckRequiredContentInstalled(); var panel = widget.Get("CONTENT_PROMPT_PANEL"); var headerTemplate = panel.Get <LabelWidget>("HEADER_TEMPLATE"); var headerLines = !string.IsNullOrEmpty(content.InstallPromptMessage) ? content.InstallPromptMessage.Replace("\\n", "\n").Split('\n') : Array.Empty <string>(); var headerHeight = 0; foreach (var l in headerLines) { var line = (LabelWidget)headerTemplate.Clone(); line.GetText = () => l; line.Bounds.Y += headerHeight; panel.AddChild(line); headerHeight += headerTemplate.Bounds.Height; } panel.Bounds.Height += headerHeight; panel.Bounds.Y -= headerHeight / 2; var advancedButton = panel.Get <ButtonWidget>("ADVANCED_BUTTON"); advancedButton.Bounds.Y += headerHeight; advancedButton.OnClick = () => { Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs { { "mod", mod }, { "content", content }, { "onCancel", CheckRequiredContentInstalled } }); }; var quickButton = panel.Get <ButtonWidget>("QUICK_BUTTON"); quickButton.IsVisible = () => !string.IsNullOrEmpty(content.QuickDownload); quickButton.Bounds.Y += headerHeight; quickButton.OnClick = () => { var modObjectCreator = new ObjectCreator(mod, Game.Mods); var modPackageLoaders = modObjectCreator.GetLoaders <IPackageLoader>(mod.PackageFormats, "package"); var modFileSystem = new FS(mod.Id, Game.Mods, modPackageLoaders); modFileSystem.LoadFromManifest(mod); var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null); modFileSystem.UnmountAll(); var download = downloadYaml.FirstOrDefault(n => n.Key == content.QuickDownload); if (download == null) { throw new InvalidOperationException($"Mod QuickDownload `{content.QuickDownload}` definition not found."); } Ui.OpenWindow("PACKAGE_DOWNLOAD_PANEL", new WidgetArgs { { "download", new ModContent.ModDownload(download.Value) }, { "onSuccess", continueLoading } }); }; var quitButton = panel.Get <ButtonWidget>("QUIT_BUTTON"); quitButton.GetText = () => requiredContentInstalled ? "Continue" : "Quit"; quitButton.Bounds.Y += headerHeight; quitButton.OnClick = () => { if (requiredContentInstalled) { continueLoading(); } else { Game.Exit(); } }; Game.RunAfterTick(Ui.ResetTooltips); }
static object LoadUnitsCommonNames(MiniYaml y) { return(LoadList <string[]>(y, "UnitsCommonNames")); }
static object LoadUnits(MiniYaml y) { return(LoadActorList(y, "UnitsToBuild")); }
static object LoadActorList(MiniYaml y, string field) { return(y.NodesDict[field].Nodes.ToDictionary( t => t.Key, t => FieldLoader.GetValue <float>(field, t.Value.Value))); }
static object LoadBuildingsCommonNames(MiniYaml y) { return(LoadList <string[]>(y, "BuildingCommonNames")); }
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())); }