import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:wolf_3d_data/wolf_3d_data.dart'; import 'package:wolf_3d_data_types/wolf_3d_data_types.dart'; import 'package:wolf_dart/features/difficulty/difficulty_screen.dart'; class GameSelectScreen extends StatelessWidget { const GameSelectScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: loadData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); } if (!snapshot.hasData) { return Text("Unable to load data"); } final List loadedGames = snapshot.data!; if (loadedGames.length == 1) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DifficultyScreen(loadedGames.first), ), ); }); } return ListView.builder( itemCount: loadedGames.length, itemBuilder: (context, i) { final WolfensteinData data = loadedGames[i]; final GameVersion version = data.version; return Card( child: ListTile( title: Text(version.name), onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => DifficultyScreen(data), ), ); }, ), ); }, ); }, ), ); } Future tryLoad(String path) async { try { return await rootBundle.load(path); } catch (e) { debugPrint("Asset not found: $path"); return null; } } Future> loadData({String? directory}) async { final List loadedGames = []; // 1. Always attempt to load bundled assets first (works on ALL platforms) final versionsToTry = [ (version: GameVersion.retail, path: 'retail'), (version: GameVersion.shareware, path: 'shareware'), ]; for (final version in versionsToTry) { try { final ext = version.version.fileExtension; final folder = 'assets/${version.path}'; final data = WolfensteinLoader.loadFromBytes( version: version.version, vswap: await tryLoad('$folder/VSWAP.$ext'), mapHead: await tryLoad('$folder/MAPHEAD.$ext'), gameMaps: await tryLoad('$folder/GAMEMAPS.$ext'), vgaDict: await tryLoad('$folder/VGADICT.$ext'), vgaHead: await tryLoad('$folder/VGAHEAD.$ext'), vgaGraph: await tryLoad('$folder/VGAGRAPH.$ext'), audioHed: await tryLoad('$folder/AUDIOHED.$ext'), audioT: await tryLoad('$folder/AUDIOT.$ext'), ); loadedGames.add(data); } catch (e) { // The loader now provides the specific error: // "ArgumentError: Cannot load retail: Missing files: VSWAP.WL6, ..." debugPrint(e.toString()); } } // 2. On non-web, also check for external files in a specific "games" folder // if you want to support side-loading. if (!kIsWeb) { try { final externalGames = await WolfensteinLoader.discover( directoryPath: directory, recursive: true, ); for (var entry in externalGames.entries) { if (!loadedGames.any((g) => g.version == entry.key)) { loadedGames.add(entry.value); } } } catch (e) { debugPrint("External discovery failed: $e"); } } return loadedGames; } }