diff --git a/lib/mod_list.dart b/lib/mod_list.dart index 1f1aead..82e187e 100644 --- a/lib/mod_list.dart +++ b/lib/mod_list.dart @@ -397,13 +397,69 @@ class ModList { }); } - LoadOrder loadRequired() { - final loadOrder = generateLoadOrder(); - for (final modId in loadOrder.order.map((e) => e.id)) { - setEnabled(modId, true); + LoadOrder loadDependencies( + String modId, [ + LoadOrder? loadOrder, + List? toEnable, + Map? seen, + List? cyclePath, + ]) { + final mod = mods[modId]!; + loadOrder ??= LoadOrder(); + toEnable ??= []; + seen ??= {}; + cyclePath ??= []; + + // Add current mod to cycle path + cyclePath.add(modId); + + for (final dep in mod.dependencies) { + if (!mods.containsKey(dep)) { + loadOrder.errors.add( + 'Missing dependency: ${mod.name} requires mod with ID $dep', + ); + continue; + } + final depMod = mods[dep]!; + if (seen[dep] == true) { + // Find the start of the cycle + int cycleStart = cyclePath.indexOf(dep); + if (cycleStart >= 0) { + // Extract the cycle part + List cycleIds = [...cyclePath.sublist(cycleStart), modId]; + loadOrder.errors.add( + 'Cyclic dependency detected: ${cycleIds.join(' -> ')}', + ); + } else { + loadOrder.errors.add('Cyclic dependency detected: $modId -> $dep'); + } + continue; + } + seen[dep] = true; + toEnable.add(depMod.id); + loadDependencies( + depMod.id, + loadOrder, + toEnable, + seen, + List.from(cyclePath), + ); } + return loadOrder; } + + LoadOrder loadRequired([LoadOrder? loadOrder]) { + loadOrder ??= LoadOrder(); + final toEnable = []; + for (final modid in activeMods.keys) { + loadDependencies(modid, loadOrder, toEnable); + } + for (final modid in toEnable) { + setEnabled(modid, true); + } + return generateLoadOrder(loadOrder); + } } String _expansionNameFromId(String id) {