Refactor modlist
This commit is contained in:
195
lib/mod_list.dart
Normal file
195
lib/mod_list.dart
Normal file
@@ -0,0 +1,195 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:rimworld_modman/logger.dart';
|
||||
import 'package:rimworld_modman/mod.dart';
|
||||
import 'package:xml/xml.dart';
|
||||
|
||||
class ModList {
|
||||
final String configPath;
|
||||
final String modsPath;
|
||||
Map<String, Mod> mods = {};
|
||||
Set<String> activeMods = {};
|
||||
Set<String> availableMods = {};
|
||||
|
||||
ModList({required this.configPath, required this.modsPath});
|
||||
|
||||
Stream<Mod> loadAvailable() async* {
|
||||
final logger = Logger.instance;
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
final directory = Directory(modsPath);
|
||||
|
||||
if (!directory.existsSync()) {
|
||||
logger.error('Error: Mods root directory does not exist: $modsPath');
|
||||
return;
|
||||
}
|
||||
|
||||
final List<FileSystemEntity> entities = directory.listSync();
|
||||
final List<String> modDirectories =
|
||||
entities.whereType<Directory>().map((dir) => dir.path).toList();
|
||||
|
||||
logger.info(
|
||||
'Found ${modDirectories.length} mod directories (${stopwatch.elapsedMilliseconds}ms)',
|
||||
);
|
||||
|
||||
for (final modDir in modDirectories) {
|
||||
try {
|
||||
final modStart = stopwatch.elapsedMilliseconds;
|
||||
|
||||
// Check if this directory contains a valid mod
|
||||
final aboutFile = File('$modDir/About/About.xml');
|
||||
if (!aboutFile.existsSync()) {
|
||||
logger.warning('No About.xml found in directory: $modDir');
|
||||
continue;
|
||||
}
|
||||
|
||||
final mod = Mod.fromDirectory(modDir);
|
||||
logger.info('Loaded mod from directory: ${mod.name} (ID: ${mod.id})');
|
||||
|
||||
if (mods.containsKey(mod.id)) {
|
||||
logger.warning('Mod $mod.id already exists in mods list, overwriting');
|
||||
final existingMod = mods[mod.id]!;
|
||||
mods[mod.id] = Mod(
|
||||
name: mod.name,
|
||||
id: mod.id,
|
||||
path: mod.path,
|
||||
versions: mod.versions,
|
||||
description: mod.description,
|
||||
hardDependencies: mod.hardDependencies,
|
||||
loadAfter: mod.loadAfter,
|
||||
loadBefore: mod.loadBefore,
|
||||
incompatabilities: mod.incompatabilities,
|
||||
enabled: activeMods.contains(
|
||||
mod.id,
|
||||
), // Set enabled based on config
|
||||
size: mod.size,
|
||||
isBaseGame: existingMod.isBaseGame,
|
||||
isExpansion: existingMod.isExpansion,
|
||||
);
|
||||
logger.info('Updated existing mod: ${mod.name} (ID: ${mod.id})');
|
||||
} else {
|
||||
mods[mod.id] = Mod(
|
||||
name: mod.name,
|
||||
id: mod.id,
|
||||
path: mod.path,
|
||||
versions: mod.versions,
|
||||
description: mod.description,
|
||||
hardDependencies: mod.hardDependencies,
|
||||
loadAfter: mod.loadAfter,
|
||||
loadBefore: mod.loadBefore,
|
||||
incompatabilities: mod.incompatabilities,
|
||||
enabled: activeMods.contains(
|
||||
mod.id,
|
||||
), // Set enabled based on config
|
||||
size: mod.size,
|
||||
isBaseGame: mod.isBaseGame,
|
||||
isExpansion: mod.isExpansion,
|
||||
);
|
||||
logger.info('Added new mod: ${mod.name} (ID: ${mod.id})');
|
||||
}
|
||||
|
||||
final modTime = stopwatch.elapsedMilliseconds - modStart;
|
||||
logger.info(
|
||||
'Loaded mod from directory: ${mod.name} (ID: ${mod.id}) in $modTime ms',
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Error loading mod from directory: $modDir');
|
||||
logger.error('Error: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stream<Mod> loadActive() async* {
|
||||
final logger = Logger.instance;
|
||||
final file = File(configPath);
|
||||
logger.info('Loading configuration from: $configPath');
|
||||
|
||||
try {
|
||||
final xmlString = file.readAsStringSync();
|
||||
logger.info('XML content read successfully.');
|
||||
|
||||
final xmlDocument = XmlDocument.parse(xmlString);
|
||||
logger.info('XML document parsed successfully.');
|
||||
|
||||
final modConfigData = xmlDocument.findElements("ModsConfigData").first;
|
||||
logger.info('Found ModsConfigData element.');
|
||||
|
||||
final modsElement = modConfigData.findElements("activeMods").first;
|
||||
logger.info('Found activeMods element.');
|
||||
|
||||
final modElements = modsElement.findElements("li");
|
||||
logger.info('Found ${modElements.length} active mods.');
|
||||
|
||||
// Get the list of known expansions
|
||||
final knownExpansionsElement =
|
||||
modConfigData.findElements("knownExpansions").firstOrNull;
|
||||
final knownExpansionIds =
|
||||
knownExpansionsElement != null
|
||||
? knownExpansionsElement
|
||||
.findElements("li")
|
||||
.map((e) => e.innerText.toLowerCase())
|
||||
.toList()
|
||||
: <String>[];
|
||||
|
||||
logger.info('Found ${knownExpansionIds.length} known expansions.');
|
||||
|
||||
// Clear and recreate the mods list
|
||||
for (final modElement in modElements) {
|
||||
final modId = modElement.innerText.toLowerCase();
|
||||
|
||||
// Check if this is a special Ludeon mod
|
||||
final isBaseGame = modId == 'ludeon.rimworld';
|
||||
final isExpansion =
|
||||
!isBaseGame &&
|
||||
modId.startsWith('ludeon.rimworld.') &&
|
||||
knownExpansionIds.contains(modId);
|
||||
|
||||
activeMods.add(modId);
|
||||
final mod = Mod(
|
||||
name:
|
||||
isBaseGame
|
||||
? "RimWorld"
|
||||
: isExpansion
|
||||
? "RimWorld ${_expansionNameFromId(modId)}"
|
||||
: modId,
|
||||
id: modId,
|
||||
path: '',
|
||||
versions: [],
|
||||
description:
|
||||
isBaseGame
|
||||
? "RimWorld base game"
|
||||
: isExpansion
|
||||
? "RimWorld expansion"
|
||||
: "",
|
||||
hardDependencies: [],
|
||||
loadAfter: isExpansion ? ['ludeon.rimworld'] : [],
|
||||
loadBefore: [],
|
||||
incompatabilities: [],
|
||||
enabled: true,
|
||||
size: 0,
|
||||
isBaseGame: isBaseGame,
|
||||
isExpansion: isExpansion,
|
||||
);
|
||||
if (mods.containsKey(modId)) {
|
||||
logger.warning('Mod $modId already exists in mods list, overwriting');
|
||||
}
|
||||
mods[modId] = mod;
|
||||
yield mod;
|
||||
}
|
||||
|
||||
logger.info('Loaded ${modElements.length} mods from config file.');
|
||||
} catch (e) {
|
||||
logger.error('Error loading configuration file: $e');
|
||||
throw Exception('Failed to load config file: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String _expansionNameFromId(String id) {
|
||||
final parts = id.split('.');
|
||||
if (parts.length < 3) return id;
|
||||
|
||||
final expansionPart = parts[2];
|
||||
return expansionPart.substring(0, 1).toUpperCase() +
|
||||
expansionPart.substring(1);
|
||||
}
|
Reference in New Issue
Block a user