Prioritize larger mods

This commit is contained in:
2025-03-15 23:17:21 +01:00
parent 7e4bee3482
commit 74eec3f3cc
2 changed files with 140 additions and 49 deletions

View File

@@ -332,7 +332,7 @@ class ModList {
return null; // No cycle found
}
// Perform a topological sort using Kahn's algorithm
// Perform a topological sort using Kahn's algorithm with size prioritization
List<String> topologicalSort(Map<String, Set<String>> graph) {
// Create a copy of the graph to work with
final Map<String, Set<String>> graphCopy = {};
@@ -352,54 +352,68 @@ class ModList {
}
}
// Start with nodes that have no dependencies (in-degree = 0)
List<String> nodesWithNoDependencies = [];
for (final node in inDegree.keys) {
if (inDegree[node] == 0) {
nodesWithNoDependencies.add(node);
// Separate nodes by "layers" (nodes that can be processed at the same time)
List<List<String>> layers = [];
// Process until all nodes are assigned to layers
while (inDegree.isNotEmpty) {
// Find all nodes with in-degree 0 in this iteration
List<String> currentLayer = [];
inDegree.forEach((node, degree) {
if (degree == 0) {
currentLayer.add(node);
}
});
if (currentLayer.isEmpty && inDegree.isNotEmpty) {
// We have a cycle - add all remaining nodes to a final layer
currentLayer = inDegree.keys.toList();
print("Warning: Cycle detected in dependency graph. Adding all remaining nodes to final layer.");
}
// Sort this layer by mod size (descending)
currentLayer.sort((a, b) {
final modA = mods[a];
final modB = mods[b];
if (modA == null || modB == null) return 0;
return modB.size.compareTo(modA.size); // Larger mods first
});
// Add the layer to our layers list
layers.add(currentLayer);
// Remove processed nodes from inDegree
for (final node in currentLayer) {
inDegree.remove(node);
// Update in-degrees for remaining nodes
for (final entry in graphCopy.entries) {
if (entry.value.contains(node)) {
if (inDegree.containsKey(entry.key)) {
inDegree[entry.key] = inDegree[entry.key]! - 1;
}
}
}
}
}
// Result will store the topological order
// Flatten the layers to get the final order (first layer first)
List<String> result = [];
// Process nodes with no dependencies
while (nodesWithNoDependencies.isNotEmpty) {
final node = nodesWithNoDependencies.removeLast();
result.add(node);
// For each node that depends on this one, decrement its in-degree
final dependents = [];
for (final entry in graphCopy.entries) {
if (entry.value.contains(node)) {
dependents.add(entry.key);
}
}
for (final dependent in dependents) {
graphCopy[dependent]!.remove(node);
inDegree[dependent] = inDegree[dependent]! - 1;
if (inDegree[dependent] == 0) {
nodesWithNoDependencies.add(dependent);
}
}
for (final layer in layers) {
result.addAll(layer);
}
// Check if we have a valid topological sort
// Final sanity check to make sure all nodes are included
if (result.length != graph.keys.length) {
print(
"Warning: Cyclic dependency detected, topological sort may be incomplete",
);
// Add any remaining nodes to keep all mods
// Add any missing nodes
for (final node in graph.keys) {
if (!result.contains(node)) {
result.add(node);
}
}
}
return result.reversed.toList(); // Reverse to get correct load order
return result;
}
// Adjust the order to respect soft dependencies where possible
@@ -478,7 +492,7 @@ class ModList {
print("Will attempt to break cycle to produce a valid load order");
}
print("Performing topological sort for hard dependencies...");
print("Performing topological sort for hard dependencies (prioritizing larger mods)...");
final hardOrder = topologicalSort(hardGraph);
print("Adjusting for soft dependencies...");