Ejemplo n.º 1
0
        public static List <string> UpdateMod(ModData modData, UpdateRule rule, out YamlFileSet files, HashSet <string> externalFilenames)
        {
            var manualSteps = new List <string>();

            var modRules        = LoadModYaml(modData, FilterExternalModFiles(modData, modData.Manifest.Rules, externalFilenames));
            var modWeapons      = LoadModYaml(modData, FilterExternalModFiles(modData, modData.Manifest.Weapons, externalFilenames));
            var modTilesets     = LoadModYaml(modData, FilterExternalModFiles(modData, modData.Manifest.TileSets, externalFilenames));
            var modChromeLayout = LoadModYaml(modData, FilterExternalModFiles(modData, modData.Manifest.ChromeLayout, externalFilenames));

            // Find and add shared map includes
            foreach (var package in modData.MapCache.EnumerateMapPackagesWithoutCaching())
            {
                using (var mapStream = package.GetStream("map.yaml"))
                {
                    if (mapStream == null)
                    {
                        continue;
                    }

                    var yaml         = new MiniYaml(null, MiniYaml.FromStream(mapStream, package.Name, false));
                    var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
                    if (mapRulesNode != null)
                    {
                        foreach (var f in LoadExternalMapYaml(modData, mapRulesNode.Value, externalFilenames))
                        {
                            if (!modRules.Any(m => m.Item1 == f.Item1 && m.Item2 == f.Item2))
                            {
                                modRules.Add(f);
                            }
                        }
                    }

                    var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons");
                    if (mapWeaponsNode != null)
                    {
                        foreach (var f in LoadExternalMapYaml(modData, mapWeaponsNode.Value, externalFilenames))
                        {
                            if (!modWeapons.Any(m => m.Item1 == f.Item1 && m.Item2 == f.Item2))
                            {
                                modWeapons.Add(f);
                            }
                        }
                    }
                }
            }

            manualSteps.AddRange(rule.BeforeUpdate(modData));
            manualSteps.AddRange(ApplyTopLevelTransform(modData, modRules, rule.UpdateActorNode));
            manualSteps.AddRange(ApplyTopLevelTransform(modData, modWeapons, rule.UpdateWeaponNode));
            manualSteps.AddRange(ApplyTopLevelTransform(modData, modTilesets, rule.UpdateTilesetNode));
            manualSteps.AddRange(ApplyChromeTransform(modData, modChromeLayout, rule.UpdateChromeNode));
            manualSteps.AddRange(rule.AfterUpdate(modData));

            files = modRules.ToList();
            files.AddRange(modWeapons);
            files.AddRange(modTilesets);
            files.AddRange(modChromeLayout);

            return(manualSteps);
        }
Ejemplo n.º 2
0
 public static void Save(this YamlFileSet files)
 {
     foreach (var file in files)
     {
         file.Item1?.Update(file.Item2, Encoding.UTF8.GetBytes(file.Item3.WriteToString()));
     }
 }
Ejemplo n.º 3
0
        static void ApplyRules(ModData modData, IReadWritePackage mapPackage, IEnumerable <UpdateRule> rules)
        {
            var externalFilenames = new HashSet <string>();

            foreach (var rule in rules)
            {
                Console.WriteLine("{0}: {1}", rule.GetType().Name, rule.Name);
                var mapFiles    = new YamlFileSet();
                var manualSteps = new List <string>();

                Console.Write("   Updating map... ");

                try
                {
                    manualSteps = UpdateUtils.UpdateMap(modData, mapPackage, rule, out mapFiles, externalFilenames);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("FAILED");

                    Console.WriteLine();
                    Console.WriteLine("   The automated changes for this rule were not applied because of an error.");
                    Console.WriteLine("   After the issue reported below is resolved you should run the updater");
                    Console.WriteLine("   with SOURCE set to {0} to retry these changes", rule.GetType().Name);
                    Console.WriteLine();
                    Console.WriteLine("   The exception reported was:");
                    Console.WriteLine("     " + ex.ToString().Replace("\n", "\n     "));
                    continue;
                }

                // Files are saved after each successful automated rule update
                mapFiles.Save();
                Console.WriteLine("COMPLETE");

                if (manualSteps.Any())
                {
                    Console.WriteLine("   Manual changes are required to complete this update:");
                    foreach (var manualStep in manualSteps)
                    {
                        Console.WriteLine("    * " + manualStep.Replace("\n", "\n      "));
                    }
                }

                Console.WriteLine();
            }

            if (externalFilenames.Any())
            {
                Console.WriteLine("The following shared yaml files referenced by the map have been ignored:");
                Console.WriteLine(UpdateUtils.FormatMessageList(externalFilenames));
                Console.WriteLine("These files are assumed to have already been updated by the --update-mod command");
                Console.WriteLine();
            }

            Console.WriteLine("Semi-automated update complete.");
            Console.WriteLine("Please review the messages above for any manual actions that must be applied.");
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Run a given update rule on a map.
        /// The rule is only applied to internal files - external includes are assumed to be handled separately
        /// but are noted in the externalFilenames list for informational purposes.
        /// </summary>
        public static List <string> UpdateMap(ModData modData, IReadWritePackage mapPackage, UpdateRule rule, out YamlFileSet files, HashSet <string> externalFilenames)
        {
            var manualSteps = new List <string>();

            using (var mapStream = mapPackage.GetStream("map.yaml"))
            {
                if (mapStream == null)
                {
                    // Not a valid map
                    files = new YamlFileSet();
                    return(manualSteps);
                }

                var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, mapPackage.Name, false));
                files = new YamlFileSet()
                {
                    Tuple.Create(mapPackage, "map.yaml", yaml.Nodes)
                };

                manualSteps.AddRange(rule.BeforeUpdate(modData));

                var mapRulesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Rules");
                if (mapRulesNode != null)
                {
                    var mapRules = LoadInternalMapYaml(modData, mapPackage, mapRulesNode.Value, externalFilenames);
                    manualSteps.AddRange(ApplyTopLevelTransform(modData, mapRules, rule.UpdateActorNode));
                    files.AddRange(mapRules);
                }

                var mapWeaponsNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Weapons");
                if (mapWeaponsNode != null)
                {
                    var mapWeapons = LoadInternalMapYaml(modData, mapPackage, mapWeaponsNode.Value, externalFilenames);
                    manualSteps.AddRange(ApplyTopLevelTransform(modData, mapWeapons, rule.UpdateWeaponNode));
                    files.AddRange(mapWeapons);
                }

                var mapSequencesNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Sequences");
                if (mapSequencesNode != null)
                {
                    var mapSequences = LoadInternalMapYaml(modData, mapPackage, mapSequencesNode.Value, externalFilenames);
                    manualSteps.AddRange(ApplyTopLevelTransform(modData, mapSequences, rule.UpdateWeaponNode));
                    files.AddRange(mapSequences);
                }

                manualSteps.AddRange(rule.AfterUpdate(modData));
            }

            return(manualSteps);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Loads a YamlFileSet from a list of mod files.
        /// </summary>
        static YamlFileSet LoadModYaml(ModData modData, IEnumerable <string> files)
        {
            var yaml = new YamlFileSet();

            foreach (var filename in files)
            {
                if (!modData.ModFiles.TryGetPackageContaining(filename, out var package, out var name) || !(package is IReadWritePackage))
                {
                    Console.WriteLine("Failed to load file `{0}` for writing. It will not be updated.", filename);
                    continue;
                }

                yaml.Add(((IReadWritePackage)package, name, MiniYaml.FromStream(package.GetStream(name), name, false)));
            }

            return(yaml);
        }
Ejemplo n.º 6
0
        static IEnumerable <string> ApplyTopLevelTransform(ModData modData, YamlFileSet files, UpdateRule.TopLevelNodeTransform transform)
        {
            if (transform == null)
            {
                yield break;
            }

            foreach (var file in files)
            {
                foreach (var node in file.Item3)
                {
                    if (node.Key != null)
                    {
                        foreach (var manualStep in transform(modData, node))
                        {
                            yield return(manualStep);
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <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);
        }
Ejemplo n.º 8
0
        static void ApplyRules(ModData modData, IEnumerable <UpdateRule> rules, bool skipMaps)
        {
            Console.WriteLine();

            var logWriter = File.CreateText("update.log");

            logWriter.AutoFlush = true;

            var externalFilenames = new HashSet <string>();

            foreach (var rule in rules)
            {
                var manualSteps = new List <string>();
                var allFiles    = new YamlFileSet();

                LogLine(logWriter, "{0}: {1}", rule.GetType().Name, rule.Name);

                try
                {
                    Log(logWriter, "   Updating mod... ");
                    manualSteps.AddRange(UpdateUtils.UpdateMod(modData, rule, out allFiles, externalFilenames));
                    LogLine(logWriter, "COMPLETE");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("FAILED");

                    LogLine(logWriter);
                    LogLine(logWriter, "   The automated changes for this rule were not applied because of an error.");
                    LogLine(logWriter, "   After the issue reported below is resolved you should run the updater");
                    LogLine(logWriter, "   with SOURCE set to {0} to retry these changes", rule.GetType().Name);
                    LogLine(logWriter);
                    LogLine(logWriter, "   The exception reported was:");
                    LogLine(logWriter, "     " + ex.ToString().Replace("\n", "\n     "));

                    continue;
                }

                Log(logWriter, "   Updating system maps... ");

                if (!skipMaps)
                {
                    var mapsFailed           = false;
                    var mapExternalFilenames = new HashSet <string>();
                    foreach (var package in modData.MapCache.EnumerateMapPackagesWithoutCaching())
                    {
                        try
                        {
                            var mapSteps = UpdateUtils.UpdateMap(modData, package, rule, out var mapFiles, mapExternalFilenames);
                            allFiles.AddRange(mapFiles);

                            if (mapSteps.Any())
                            {
                                manualSteps.Add("Map: " + package.Name + ":\n" + UpdateUtils.FormatMessageList(mapSteps));
                            }
                        }
                        catch (Exception ex)
                        {
                            LogLine(logWriter, "FAILED");
                            LogLine(logWriter);
                            LogLine(logWriter, "   The automated changes for this rule were not applied because of an error.");
                            LogLine(logWriter, "   After the issue reported below is resolved you should run the updater");
                            LogLine(logWriter, "   with SOURCE set to {0} to retry these changes", rule.GetType().Name);
                            LogLine(logWriter);
                            LogLine(logWriter, "   The map that caused the error was:");
                            LogLine(logWriter, "     " + package.Name);
                            LogLine(logWriter);
                            LogLine(logWriter, "   The exception reported was:");
                            LogLine(logWriter, "     " + ex.ToString().Replace("\n", "\n     "));
                            mapsFailed = true;
                            break;
                        }
                    }

                    if (mapsFailed)
                    {
                        continue;
                    }

                    LogLine(logWriter, "COMPLETE");
                }
                else
                {
                    LogLine(logWriter, "SKIPPED");
                }

                // Files are saved after each successful automated rule update
                allFiles.Save();

                if (manualSteps.Any())
                {
                    LogLine(logWriter, "   Manual changes are required to complete this update:");
                    LogLine(logWriter, UpdateUtils.FormatMessageList(manualSteps, 1));
                }

                LogLine(logWriter);
            }

            if (externalFilenames.Any())
            {
                LogLine(logWriter, "The following external mod files have been ignored:");
                LogLine(logWriter, UpdateUtils.FormatMessageList(externalFilenames));
                LogLine(logWriter, "These files should be updated by running --update-mod on the referenced mod(s)");
                LogLine(logWriter);
            }

            Console.WriteLine("Semi-automated update complete.");
            Console.WriteLine("Please review the messages above for any manual actions that must be applied.");
            Console.WriteLine("These messages have also been written to an update.log file in the current directory.");
        }