import 'dart:io'; const _commonPath = 'tool/lua_runtime_defs_common.lua'; const _runtimeMarker = 'runtime = runtime'; const _gamesRoot = 'assets/games'; void main(List args) { final checkOnly = args.contains('--check'); final commonFile = File(_commonPath); if (!commonFile.existsSync()) { stderr.writeln('Missing common Lua runtime defs template: $_commonPath'); exitCode = 1; return; } final common = _normalizeCommon(commonFile.readAsStringSync()); var changed = false; final targets = _runtimeDefTargets(); if (targets.isEmpty) { stderr.writeln('No Lua runtime defs targets found under $_gamesRoot'); exitCode = 1; return; } for (final target in targets) { final targetPath = target.path; final current = target.existsSync() ? target.readAsStringSync() : ''; final suffix = current.isEmpty ? '' : _gameSpecificSuffix(current, targetPath); final generated = suffix.isEmpty ? common : '$common\n$suffix'; if (current == generated) { stdout.writeln('up to date: $targetPath'); continue; } changed = true; if (checkOnly) { stderr.writeln('out of date: $targetPath'); } else { target.writeAsStringSync(generated); stdout.writeln('generated: $targetPath'); } } if (checkOnly && changed) { stderr.writeln( 'Lua runtime defs are out of date. Run: dart run tool/generate_lua_runtime_defs.dart', ); exitCode = 1; } } List _runtimeDefTargets() { final root = Directory(_gamesRoot); if (!root.existsSync()) { return const []; } final targets = []; for (final entity in root.listSync()) { if (entity is! Directory) { continue; } final scripts = Directory('${entity.path}/scripts'); if (!scripts.existsSync()) { continue; } targets.add(File('${scripts.path}/runtime_defs.lua')); } targets.sort((a, b) => a.path.compareTo(b.path)); return targets; } String _normalizeCommon(String source) { final text = source.replaceAll('\r\n', '\n').trimRight(); if (!text.contains(_runtimeMarker)) { throw const FormatException( 'Common template must contain runtime = runtime', ); } return '$text\n'; } String _gameSpecificSuffix(String source, String targetPath) { final text = source.replaceAll('\r\n', '\n'); final index = text.indexOf(_runtimeMarker); if (index < 0) { throw FormatException('$targetPath must contain $_runtimeMarker'); } final suffixStart = index + _runtimeMarker.length; return text.substring(suffixStart).trimLeft(); }