Fix up activemods to be a String, Mod
This commit is contained in:
@@ -6,8 +6,9 @@ import 'package:rimworld_modman/mod.dart';
|
|||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
|
|
||||||
class LoadOrder {
|
class LoadOrder {
|
||||||
final List<String> loadOrder = [];
|
final List<Mod> order = [];
|
||||||
final List<String> errors = [];
|
final List<String> errors = [];
|
||||||
|
List<String> get loadOrder => order.map((e) => e.id).toList();
|
||||||
|
|
||||||
LoadOrder();
|
LoadOrder();
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ class ModList {
|
|||||||
String configPath = '';
|
String configPath = '';
|
||||||
String modsPath = '';
|
String modsPath = '';
|
||||||
// O(1) lookup
|
// O(1) lookup
|
||||||
Map<String, bool> activeMods = {};
|
Map<String, Mod> activeMods = {};
|
||||||
Map<String, Mod> mods = {};
|
Map<String, Mod> mods = {};
|
||||||
|
|
||||||
ModList({this.configPath = '', this.modsPath = ''});
|
ModList({this.configPath = '', this.modsPath = ''});
|
||||||
@@ -202,9 +203,10 @@ class ModList {
|
|||||||
|
|
||||||
void setEnabled(String modId, bool enabled) {
|
void setEnabled(String modId, bool enabled) {
|
||||||
if (mods.containsKey(modId)) {
|
if (mods.containsKey(modId)) {
|
||||||
mods[modId]!.enabled = enabled;
|
final mod = mods[modId]!;
|
||||||
|
mod.enabled = enabled;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
activeMods[modId] = true;
|
activeMods[modId] = mod;
|
||||||
} else {
|
} else {
|
||||||
activeMods.remove(modId);
|
activeMods.remove(modId);
|
||||||
}
|
}
|
||||||
@@ -247,9 +249,10 @@ class ModList {
|
|||||||
// return generateLoadOrder(loadOrder);
|
// return generateLoadOrder(loadOrder);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
LoadOrder generateLoadOrder() {
|
LoadOrder generateLoadOrder([LoadOrder? loadOrder]) {
|
||||||
final modMap = {for (final m in mods.values) m.id: m};
|
loadOrder ??= LoadOrder();
|
||||||
_validateIncompatibilities(mods.values.toList());
|
final modMap = {for (final m in activeMods.values) m.id: m};
|
||||||
|
_validateIncompatibilities(loadOrder);
|
||||||
|
|
||||||
// Hard dependency graph
|
// Hard dependency graph
|
||||||
final inDegree = <String, int>{};
|
final inDegree = <String, int>{};
|
||||||
@@ -260,7 +263,7 @@ class ModList {
|
|||||||
final reverseLoadAfter = <String, List<Mod>>{};
|
final reverseLoadAfter = <String, List<Mod>>{};
|
||||||
|
|
||||||
// Initialize data structures
|
// Initialize data structures
|
||||||
for (final mod in mods.values) {
|
for (final mod in activeMods.values) {
|
||||||
mod.loadBeforeNotPlaced = mod.loadBefore.length;
|
mod.loadBeforeNotPlaced = mod.loadBefore.length;
|
||||||
mod.loadAfterPlaced = 0;
|
mod.loadAfterPlaced = 0;
|
||||||
|
|
||||||
@@ -271,7 +274,7 @@ class ModList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build dependency graph and reverse soft constraints
|
// Build dependency graph and reverse soft constraints
|
||||||
for (final mod in mods.values) {
|
for (final mod in activeMods.values) {
|
||||||
for (final depId in mod.dependencies) {
|
for (final depId in mod.dependencies) {
|
||||||
adjacency[depId]!.add(mod.id);
|
adjacency[depId]!.add(mod.id);
|
||||||
inDegree[mod.id] = (inDegree[mod.id] ?? 0) + 1;
|
inDegree[mod.id] = (inDegree[mod.id] ?? 0) + 1;
|
||||||
@@ -318,17 +321,15 @@ class ModList {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Initialize heap with available mods
|
// Initialize heap with available mods
|
||||||
for (final modId in activeMods.keys) {
|
for (final mod in activeMods.values) {
|
||||||
final mod = modMap[modId];
|
if (inDegree[mod.id] == 0) {
|
||||||
if (mod != null && inDegree[modId] == 0) {
|
|
||||||
heap.add(mod);
|
heap.add(mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final sortedMods = <Mod>[];
|
|
||||||
while (heap.isNotEmpty) {
|
while (heap.isNotEmpty) {
|
||||||
final current = heap.removeFirst();
|
final current = heap.removeFirst();
|
||||||
sortedMods.add(current);
|
loadOrder.order.add(current);
|
||||||
|
|
||||||
// Update dependents' in-degree
|
// Update dependents' in-degree
|
||||||
for (final neighborId in adjacency[current.id]!) {
|
for (final neighborId in adjacency[current.id]!) {
|
||||||
@@ -342,34 +343,32 @@ class ModList {
|
|||||||
_updateReverseConstraints(
|
_updateReverseConstraints(
|
||||||
current,
|
current,
|
||||||
reverseLoadBefore,
|
reverseLoadBefore,
|
||||||
sortedMods,
|
loadOrder,
|
||||||
heap,
|
heap,
|
||||||
(mod) => mod.loadBeforeNotPlaced--,
|
(mod) => mod.loadBeforeNotPlaced--,
|
||||||
);
|
);
|
||||||
_updateReverseConstraints(
|
_updateReverseConstraints(
|
||||||
current,
|
current,
|
||||||
reverseLoadAfter,
|
reverseLoadAfter,
|
||||||
sortedMods,
|
loadOrder,
|
||||||
heap,
|
heap,
|
||||||
(mod) => mod.loadAfterPlaced++,
|
(mod) => mod.loadAfterPlaced++,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortedMods.length != mods.length) {
|
if (loadOrder.order.length != activeMods.length) {
|
||||||
throw Exception("Cyclic dependencies detected");
|
loadOrder.errors.add("Cyclic dependencies detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
final loadOrder = LoadOrder();
|
|
||||||
loadOrder.loadOrder.addAll(sortedMods.map((e) => e.id));
|
|
||||||
return loadOrder;
|
return loadOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _validateIncompatibilities(List<Mod> mods) {
|
void _validateIncompatibilities(LoadOrder loadOrder) {
|
||||||
final enabledMods = mods.where((m) => m.enabled).toList();
|
final enabledMods = loadOrder.order.where((m) => m.enabled).toList();
|
||||||
for (final mod in enabledMods) {
|
for (final mod in enabledMods) {
|
||||||
for (final incompatibleId in mod.incompatibilities) {
|
for (final incompatibleId in mod.incompatibilities) {
|
||||||
if (enabledMods.any((m) => m.id == incompatibleId)) {
|
if (enabledMods.any((m) => m.id == incompatibleId)) {
|
||||||
throw Exception("Conflict: ${mod.id} vs $incompatibleId");
|
loadOrder.errors.add("Incompatible mods: ${mod.id} and $incompatibleId");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -378,12 +377,12 @@ class ModList {
|
|||||||
void _updateReverseConstraints(
|
void _updateReverseConstraints(
|
||||||
Mod current,
|
Mod current,
|
||||||
Map<String, List<Mod>> reverseMap,
|
Map<String, List<Mod>> reverseMap,
|
||||||
List<Mod> sortedMods,
|
LoadOrder loadOrder,
|
||||||
PriorityQueue<Mod> heap,
|
PriorityQueue<Mod> heap,
|
||||||
void Function(Mod) update,
|
void Function(Mod) update,
|
||||||
) {
|
) {
|
||||||
reverseMap[current.id]?.forEach((affectedMod) {
|
reverseMap[current.id]?.forEach((affectedMod) {
|
||||||
if (!sortedMods.contains(affectedMod)) {
|
if (!loadOrder.order.contains(affectedMod)) {
|
||||||
update(affectedMod);
|
update(affectedMod);
|
||||||
// If mod is already in heap, re-add to update position
|
// If mod is already in heap, re-add to update position
|
||||||
if (heap.contains(affectedMod)) {
|
if (heap.contains(affectedMod)) {
|
||||||
@@ -396,7 +395,7 @@ class ModList {
|
|||||||
|
|
||||||
LoadOrder loadRequired() {
|
LoadOrder loadRequired() {
|
||||||
final loadOrder = generateLoadOrder();
|
final loadOrder = generateLoadOrder();
|
||||||
for (final modId in loadOrder.loadOrder) {
|
for (final modId in loadOrder.order.map((e) => e.id)) {
|
||||||
setEnabled(modId, true);
|
setEnabled(modId, true);
|
||||||
}
|
}
|
||||||
return loadOrder;
|
return loadOrder;
|
||||||
|
Reference in New Issue
Block a user