/// CLI entry point for the terminal Wolf3D host. /// /// This executable locates bundled retail assets, constructs a [WolfEngine] /// configured for terminal rendering, and then hands control to [CliGameLoop]. library; import 'dart:io'; import 'package:wolf_3d_cli/cli_game_loop.dart'; import 'package:wolf_3d_dart/wolf_3d_data.dart'; import 'package:wolf_3d_dart/wolf_3d_data_types.dart'; import 'package:wolf_3d_dart/wolf_3d_engine.dart'; import 'package:wolf_3d_dart/wolf_3d_input.dart'; /// Restores terminal state before exiting the process with [code]. void exitCleanly(int code) { stdout.write('\x1b[0m'); // Reset color stdout.write('\x1b[2J\x1b[H'); // Clear screen stdout.write('\x1b[?25h'); // SHOW the cursor again exit(code); } /// Launches the CLI renderer against the bundled retail asset set. void main() async { stdout.write("Discovering game data..."); // Resolve the asset package relative to this executable so the CLI can run // from the repo without additional configuration. final scriptUri = Platform.script; final targetUri = scriptUri.resolve( '../../../packages/wolf_3d_assets/assets/retail', ); final targetPath = targetUri.toFilePath(); final availableGames = await WolfensteinLoader.discover( directoryPath: targetPath, recursive: true, ); if (availableGames.isEmpty) { stderr.writeln('\nNo Wolf3D game files were found at: $targetPath'); stderr.writeln( 'Please provide valid game data files before starting the CLI host.', ); exitCleanly(1); } CliGameLoop? gameLoop; void stopAndExit(int code) { gameLoop?.stop(); exitCleanly(code); } final engine = WolfEngine( availableGames: availableGames.values.toList(growable: false), startingEpisode: 0, frameBuffer: FrameBuffer( stdout.terminalColumns, stdout.terminalLines, ), input: CliInput(), onGameWon: () => stopAndExit(0), ); engine.init(); gameLoop = CliGameLoop( engine: engine, onExit: stopAndExit, ); await gameLoop.start(); }