Cook up proper logging
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rimworld_modman/modloader.dart';
|
||||
import 'dart:io';
|
||||
import 'package:rimworld_modman/modloader.dart';
|
||||
|
||||
// Global variable to store loaded mods for access across the app
|
||||
late ModList modManager;
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Get a reference to the logger (now auto-initializes)
|
||||
final logger = Logger.instance;
|
||||
logger.info('Rimworld Mod Manager starting...');
|
||||
|
||||
// Initialize the mod manager
|
||||
modManager = ModList(path: modsRoot);
|
||||
|
||||
|
@@ -1,11 +1,83 @@
|
||||
import 'dart:io';
|
||||
import 'dart:async';
|
||||
import 'package:xml/xml.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
const root = r'C:/Users/Administrator/Seafile/Games-Rimworld';
|
||||
const modsRoot = '$root/294100';
|
||||
const configRoot = '$root/AppData/RimWorld by Ludeon Studios/Config';
|
||||
const configPath = '$configRoot/ModsConfig.xml';
|
||||
const logsPath = '$root/ModManager';
|
||||
|
||||
// Logger class for writing logs to console and file
|
||||
class Logger {
|
||||
static final Logger _instance = Logger._internal();
|
||||
static Logger get instance => _instance;
|
||||
|
||||
File? _logFile;
|
||||
IOSink? _logSink;
|
||||
|
||||
Logger._internal() {
|
||||
_initLogFile();
|
||||
}
|
||||
|
||||
void _initLogFile() {
|
||||
try {
|
||||
// Use system temp directory
|
||||
final tempDir = Directory.systemTemp;
|
||||
final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-').substring(0, 19);
|
||||
final logFileName = 'rimworld_modman_$timestamp.log';
|
||||
|
||||
_logFile = File('${tempDir.path}${Platform.pathSeparator}$logFileName');
|
||||
_logSink = _logFile!.openWrite(mode: FileMode.writeOnly);
|
||||
|
||||
info('Logging initialized. Log file: ${_logFile!.path}');
|
||||
} catch (e) {
|
||||
print('Failed to initialize log file: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _log(String message, String level) {
|
||||
final timestamp = DateTime.now().toIso8601String();
|
||||
final formattedMessage = '[$timestamp] [$level] $message';
|
||||
|
||||
// Always print to console
|
||||
print(formattedMessage);
|
||||
|
||||
// Write to file if initialized
|
||||
if (_logSink != null) {
|
||||
try {
|
||||
_logSink!.writeln(formattedMessage);
|
||||
} catch (e) {
|
||||
print('Error writing to log file: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void info(String message) {
|
||||
_log(message, 'INFO');
|
||||
}
|
||||
|
||||
void warning(String message) {
|
||||
_log(message, 'WARN');
|
||||
}
|
||||
|
||||
void error(String message) {
|
||||
_log(message, 'ERROR');
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (_logSink != null) {
|
||||
try {
|
||||
_logSink!.flush();
|
||||
_logSink!.close();
|
||||
} catch (e) {
|
||||
print('Error closing log file: $e');
|
||||
}
|
||||
_logSink = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XmlElement findCaseInsensitive(XmlElement element, String name) {
|
||||
return element.childElements.firstWhere(
|
||||
@@ -52,6 +124,7 @@ class Mod {
|
||||
});
|
||||
|
||||
static Mod fromDirectory(String path, {bool skipFileCount = false}) {
|
||||
final logger = Logger.instance;
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
final aboutFile = File('$path/About/About.xml');
|
||||
@@ -196,8 +269,8 @@ class Mod {
|
||||
stopwatch.elapsedMilliseconds - metadataTime - xmlTime;
|
||||
final totalTime = stopwatch.elapsedMilliseconds;
|
||||
|
||||
// Uncomment for detailed timing
|
||||
print(
|
||||
// Log detailed timing information
|
||||
logger.info(
|
||||
'Mod $name timing: XML=${xmlTime}ms, Metadata=${metadataTime}ms, FileCount=${fileCountTime}ms, Total=${totalTime}ms',
|
||||
);
|
||||
|
||||
@@ -231,6 +304,8 @@ class ModList {
|
||||
|
||||
// Simplified loading with config file first
|
||||
Future<void> loadWithConfig({bool skipFileCount = false}) async {
|
||||
final logger = Logger.instance;
|
||||
|
||||
// Clear existing state if reloading
|
||||
if (modsLoaded) {
|
||||
mods.clear();
|
||||
@@ -241,7 +316,7 @@ class ModList {
|
||||
loadingStatus = 'Loading active mods from config...';
|
||||
|
||||
final stopwatch = Stopwatch()..start();
|
||||
print('Loading configuration from config file: $configPath');
|
||||
logger.info('Loading configuration from config file: $configPath');
|
||||
|
||||
try {
|
||||
// First, load the config file to get the list of active mods
|
||||
@@ -287,7 +362,7 @@ class ModList {
|
||||
|
||||
if (!directory.existsSync()) {
|
||||
loadingStatus = 'Error: Mods root directory does not exist: $path';
|
||||
print(loadingStatus);
|
||||
logger.error(loadingStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -297,7 +372,7 @@ class ModList {
|
||||
|
||||
totalModsFound = modDirectories.length;
|
||||
loadingStatus = 'Found $totalModsFound mod directories. Loading...';
|
||||
print('Found ${modDirectories.length} mod directories (${stopwatch.elapsedMilliseconds}ms)');
|
||||
logger.info('Found ${modDirectories.length} mod directories (${stopwatch.elapsedMilliseconds}ms)');
|
||||
|
||||
for (final modDir in modDirectories) {
|
||||
try {
|
||||
@@ -351,21 +426,21 @@ class ModList {
|
||||
loadingStatus = 'Loaded $loadedModsCount/$totalModsFound mods...';
|
||||
|
||||
if (loadedModsCount % 50 == 0 || loadedModsCount == totalModsFound) {
|
||||
print('Progress: Loaded $loadedModsCount mods (${stopwatch.elapsedMilliseconds}ms)');
|
||||
logger.info('Progress: Loaded $loadedModsCount mods (${stopwatch.elapsedMilliseconds}ms)');
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error loading mod from directory: $modDir');
|
||||
print('Error: $e');
|
||||
logger.error('Error loading mod from directory: $modDir');
|
||||
logger.error('Error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
modsLoaded = true;
|
||||
final totalTime = stopwatch.elapsedMilliseconds;
|
||||
loadingStatus = 'Completed! Loaded $loadedModsCount mods in ${totalTime}ms.';
|
||||
print('Loading complete! Loaded ${mods.length} mods in ${totalTime}ms');
|
||||
logger.info('Loading complete! Loaded ${mods.length} mods in ${totalTime}ms');
|
||||
} catch (e) {
|
||||
loadingStatus = 'Error loading mods: $e';
|
||||
print(loadingStatus);
|
||||
logger.error(loadingStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,24 +765,25 @@ class ConfigFile {
|
||||
ConfigFile({required this.path, this.mods = const []});
|
||||
|
||||
Future<void> load() async {
|
||||
final logger = Logger.instance;
|
||||
final file = File(path);
|
||||
print('Loading configuration from: $path');
|
||||
logger.info('Loading configuration from: $path');
|
||||
|
||||
try {
|
||||
final xmlString = file.readAsStringSync();
|
||||
print('XML content read successfully.');
|
||||
logger.info('XML content read successfully.');
|
||||
|
||||
final xmlDocument = XmlDocument.parse(xmlString);
|
||||
print('XML document parsed successfully.');
|
||||
logger.info('XML document parsed successfully.');
|
||||
|
||||
final modConfigData = xmlDocument.findElements("ModsConfigData").first;
|
||||
print('Found ModsConfigData element.');
|
||||
logger.info('Found ModsConfigData element.');
|
||||
|
||||
final modsElement = modConfigData.findElements("activeMods").first;
|
||||
print('Found activeMods element.');
|
||||
logger.info('Found activeMods element.');
|
||||
|
||||
final modElements = modsElement.findElements("li");
|
||||
print('Found ${modElements.length} active mods.');
|
||||
logger.info('Found ${modElements.length} active mods.');
|
||||
|
||||
// Get the list of known expansions
|
||||
final knownExpansionsElement = modConfigData.findElements("knownExpansions").firstOrNull;
|
||||
@@ -715,7 +791,7 @@ class ConfigFile {
|
||||
? knownExpansionsElement.findElements("li").map((e) => e.innerText.toLowerCase()).toList()
|
||||
: <String>[];
|
||||
|
||||
print('Found ${knownExpansionIds.length} known expansions.');
|
||||
logger.info('Found ${knownExpansionIds.length} known expansions.');
|
||||
|
||||
// Clear and recreate the mods list
|
||||
mods = [];
|
||||
@@ -749,9 +825,9 @@ class ConfigFile {
|
||||
);
|
||||
}
|
||||
|
||||
print('Loaded ${mods.length} mods from config file.');
|
||||
logger.info('Loaded ${mods.length} mods from config file.');
|
||||
} catch (e) {
|
||||
print('Error loading configuration file: $e');
|
||||
logger.error('Error loading configuration file: $e');
|
||||
throw Exception('Failed to load config file: $e');
|
||||
}
|
||||
}
|
||||
@@ -767,13 +843,14 @@ class ConfigFile {
|
||||
|
||||
// Save the current mod order back to the config file
|
||||
void save() {
|
||||
final logger = Logger.instance;
|
||||
final file = File(path);
|
||||
print('Saving configuration to: $path');
|
||||
logger.info('Saving configuration to: $path');
|
||||
|
||||
// Create a backup just in case
|
||||
final backupPath = '$path.bak';
|
||||
file.copySync(backupPath);
|
||||
print('Created backup at: $backupPath');
|
||||
logger.info('Created backup at: $backupPath');
|
||||
|
||||
try {
|
||||
// Load the existing XML
|
||||
@@ -798,16 +875,17 @@ class ConfigFile {
|
||||
|
||||
// Write the updated XML back to the file
|
||||
file.writeAsStringSync(xmlDocument.toXmlString(pretty: true));
|
||||
print('Configuration saved successfully with ${mods.length} mods.');
|
||||
logger.info('Configuration saved successfully with ${mods.length} mods.');
|
||||
} catch (e) {
|
||||
print('Error saving configuration: $e');
|
||||
print('Original configuration preserved at: $backupPath');
|
||||
logger.error('Error saving configuration: $e');
|
||||
logger.info('Original configuration preserved at: $backupPath');
|
||||
}
|
||||
}
|
||||
|
||||
// Fix the load order of mods according to dependencies
|
||||
void fixLoadOrder(ModList modList) {
|
||||
print("Fixing mod load order...");
|
||||
final logger = Logger.instance;
|
||||
logger.info("Fixing mod load order...");
|
||||
|
||||
// Get the ordered mod IDs from the mod list
|
||||
final orderedIds = modList.sortMods();
|
||||
@@ -836,7 +914,7 @@ class ConfigFile {
|
||||
// Replace the current mods list with the ordered one
|
||||
mods = orderedMods;
|
||||
|
||||
print(
|
||||
logger.info(
|
||||
"Load order fixed. ${mods.length} mods are now in dependency-sorted order.",
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user