public static ModDependencySet GetDependencies(ModConfig config, IEnumerable <ModConfig> allMods = null) { if (allMods == null) { allMods = GetAllMods().Select(x => x.Object); } var dependencySet = new ModDependencySet(); // Populate whole list of nodes (graph), connected up with dependencies as edges. var allModsNodes = new List <Node <ModConfig> >(); foreach (var mod in allMods) { allModsNodes.Add(new Node <ModConfig>(mod)); } foreach (var node in allModsNodes) { node.Edges = allModsNodes.Where(x => node.Element.ModDependencies.Contains(x.Element.ModId)).ToList(); } // Find our mod configuration in set of nodes. var initialNode = new Node <ModConfig>(config); initialNode.Edges = allModsNodes.Where(x => initialNode.Element.ModDependencies.Contains(x.Element.ModId)).ToList(); // Recursive resolution. GetDependenciesVisitNode(initialNode, allMods, dependencySet); return(dependencySet); }
public static ModDependencySet GetDependencies(ModConfig config, IEnumerable <ModConfig> allMods = null) { if (allMods == null) { allMods = GetAllMods().Select(x => x.Config); } var dependencySet = new ModDependencySet(); // Populate whole list of nodes (graph). var allModsDict = PopulateNodeDictionary(allMods); // Recursive resolution. GetDependenciesVisitNode(new Node <ModConfig>(config), allModsDict, dependencySet); return(dependencySet); }
private static void PopulateNodeDependencies(Node <ModConfig> node, Dictionary <string, Node <ModConfig> > allModsDict, ModDependencySet dependencySet) { // Populates the dependencies for each node given a dictionary of all available mods. node.Edges = new List <Node <ModConfig> >(allModsDict.Count); foreach (string dependencyId in node.Element.ModDependencies) { if (allModsDict.TryGetValue(dependencyId, out var dependency)) { node.Edges.Add(dependency); dependencySet?.Configurations.Add(dependency.Element); } else { dependencySet?.MissingConfigurations.Add(dependencyId); } } }
/// <summary> /// Returns a list of all Mod IDs that are not installed referenced by a mod config. /// </summary> /// <param name="node">The mod configuration for which to find missing dependencies.</param> /// <param name="allModsDict">Collection containing all of the mod configurations.</param> /// <param name="dependencySet">Accumulator for all missing dependencies.</param> private static void GetDependenciesVisitNode(Node <ModConfig> node, Dictionary <string, Node <ModConfig> > allModsDict, ModDependencySet dependencySet) { // Already fully visited, already in list. if (node.Visited == Mark.Visited) { return; } // Disallow looping on itself. // Not a directed acyclic graph. if (node.Visited == Mark.Visiting) { return; } node.Visited = Mark.Visiting; // Get all dependencies (children/edge nodes). PopulateNodeDependencies(node, allModsDict, dependencySet); // Visit all children, depth first. foreach (var dependency in node.Edges) { GetDependenciesVisitNode(dependency, allModsDict, dependencySet); } // Set visited and return to next in stack. node.Visited = Mark.Visited; }
/// <summary> /// Returns a list of all Mod IDs that are not installed referenced by a mod config. /// </summary> /// <param name="node">The mod configuration for which to find missing dependencies.</param> /// <param name="allMods">Collection containing all of the mod configurations.</param> /// <param name="dependencySet">Accumulator for all missing dependencies.</param> private static void GetDependenciesVisitNode(Node <ModConfig> node, IEnumerable <ModConfig> allMods, ModDependencySet dependencySet) { // Already fully visited, already in list. if (node.Visited == Mark.Visited) { return; } // Disallow looping on itself. // Not a directed acyclic graph. if (node.Visited == Mark.Visiting) { return; } node.Visited = Mark.Visiting; // Visit all children, depth first. foreach (var dependency in node.Edges) { GetDependenciesVisitNode(dependency, allMods, dependencySet); } // Do collect missing dependencies. foreach (string dependencyId in node.Element.ModDependencies) { var dependencyConfig = allMods.FirstOrDefault(x => x.ModId == dependencyId); if (dependencyConfig != null) { dependencySet.Configurations.Add(dependencyConfig); } else { dependencySet.MissingConfigurations.Add(dependencyId); } } // Set visited and return to next in stack. node.Visited = Mark.Visited; }