feat: Implement packaged games loading and update engine initialization to support seeded games
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -2,15 +2,18 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
|
||||
|
||||
import 'packaged_games_loader.dart';
|
||||
import 'wolf3d_gui_app.dart';
|
||||
|
||||
/// Creates the application shell after loading available Wolf3D data sets.
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final seededGames = await loadPackagedGames();
|
||||
|
||||
final Wolf3dFlutterEngine wolf3d = await Wolf3dFlutterEngine(
|
||||
debug: kDebugMode,
|
||||
).init();
|
||||
).init(seededGames: seededGames);
|
||||
|
||||
if (kDebugMode) {
|
||||
wolf3d.enableMenuHeaderBandDebugLogging(prefix: '[wolf_3d_gui]');
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
|
||||
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
|
||||
|
||||
typedef PackagedGameDataLoader =
|
||||
Future<WolfensteinData> Function({
|
||||
required GameVersion version,
|
||||
required String assetDirectory,
|
||||
});
|
||||
|
||||
Future<List<WolfensteinData>> loadPackagedGames({
|
||||
PackagedGameDataLoader? loader,
|
||||
}) async {
|
||||
final PackagedGameDataLoader effectiveLoader =
|
||||
loader ??
|
||||
({required version, required assetDirectory}) =>
|
||||
Wolf3dFlutterEngine.loadGameDataFromAssets(
|
||||
version: version,
|
||||
packageName: 'wolf_3d_assets',
|
||||
assetDirectory: assetDirectory,
|
||||
);
|
||||
|
||||
final List<WolfensteinData> games = [];
|
||||
|
||||
Future<void> tryLoad({
|
||||
required GameVersion version,
|
||||
required String assetDirectory,
|
||||
}) async {
|
||||
try {
|
||||
games.add(
|
||||
await effectiveLoader(
|
||||
version: version,
|
||||
assetDirectory: assetDirectory,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint(
|
||||
'Packaged game load skipped for ${version.label} ($assetDirectory): $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await tryLoad(version: GameVersion.retail, assetDirectory: 'assets/retail');
|
||||
await tryLoad(
|
||||
version: GameVersion.shareware,
|
||||
assetDirectory: 'assets/shareware',
|
||||
);
|
||||
await tryLoad(
|
||||
version: GameVersion.spearOfDestinyDemo,
|
||||
assetDirectory: 'assets/sod/shareware',
|
||||
);
|
||||
|
||||
return games;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ dependencies:
|
||||
file_selector: ^1.0.3
|
||||
wolf_3d_flutter:
|
||||
wolf_3d_dart:
|
||||
wolf_3d_assets:
|
||||
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
@@ -53,6 +53,7 @@ class _RecordingEngine extends Wolf3dFlutterEngine {
|
||||
Future<Wolf3dFlutterEngine> init({
|
||||
String? directory,
|
||||
Iterable<String>? additionalDirectories,
|
||||
Iterable<WolfensteinData>? seededGames,
|
||||
}) async {
|
||||
initCallCount++;
|
||||
lastDirectory = directory;
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:wolf_3d_dart/wolf_3d_data_types.dart';
|
||||
import 'package:wolf_3d_gui/packaged_games_loader.dart';
|
||||
|
||||
void main() {
|
||||
group('loadPackagedGames', () {
|
||||
test('loads known packaged directories in order', () async {
|
||||
final requested = <(GameVersion, String)>[];
|
||||
|
||||
final games = await loadPackagedGames(
|
||||
loader: ({required version, required assetDirectory}) async {
|
||||
requested.add((version, assetDirectory));
|
||||
return _buildTestData(version);
|
||||
},
|
||||
);
|
||||
|
||||
expect(requested, <(GameVersion, String)>[
|
||||
(GameVersion.retail, 'assets/retail'),
|
||||
(GameVersion.shareware, 'assets/shareware'),
|
||||
(GameVersion.spearOfDestinyDemo, 'assets/sod/shareware'),
|
||||
]);
|
||||
expect(games.map((g) => g.version), <GameVersion>[
|
||||
GameVersion.retail,
|
||||
GameVersion.shareware,
|
||||
GameVersion.spearOfDestinyDemo,
|
||||
]);
|
||||
});
|
||||
|
||||
test('skips failing packaged loads and keeps successful ones', () async {
|
||||
final games = await loadPackagedGames(
|
||||
loader: ({required version, required assetDirectory}) async {
|
||||
if (version == GameVersion.shareware) {
|
||||
throw Exception('shareware unavailable');
|
||||
}
|
||||
return _buildTestData(version);
|
||||
},
|
||||
);
|
||||
|
||||
expect(games.map((g) => g.version), <GameVersion>[
|
||||
GameVersion.retail,
|
||||
GameVersion.spearOfDestinyDemo,
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
WolfensteinData _buildTestData(GameVersion version) {
|
||||
final wallGrid = List.generate(64, (_) => List.filled(64, 0));
|
||||
final objectGrid = List.generate(64, (_) => List.filled(64, 0));
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
wallGrid[0][i] = 2;
|
||||
wallGrid[63][i] = 2;
|
||||
wallGrid[i][0] = 2;
|
||||
wallGrid[i][63] = 2;
|
||||
}
|
||||
objectGrid[2][2] = MapObject.playerEast;
|
||||
|
||||
return WolfensteinData(
|
||||
version: version,
|
||||
dataVersion: DataVersion.unknown,
|
||||
registry: version == GameVersion.shareware
|
||||
? SharewareAssetRegistry()
|
||||
: RetailAssetRegistry(),
|
||||
walls: <Sprite>[_sprite(1), _sprite(1), _sprite(2), _sprite(2)],
|
||||
sprites: List<Sprite>.generate(436, (_) => _sprite(255)),
|
||||
sounds: List<PcmSound>.generate(200, (_) => PcmSound(Uint8List(1))),
|
||||
adLibSounds: const <PcmSound>[],
|
||||
music: const <ImfMusic>[],
|
||||
vgaImages: const <VgaImage>[],
|
||||
episodes: <Episode>[
|
||||
Episode(
|
||||
name: 'Test Episode',
|
||||
levels: <WolfLevel>[
|
||||
WolfLevel(
|
||||
name: 'Test Level',
|
||||
wallGrid: wallGrid,
|
||||
areaGrid: List.generate(64, (_) => List.filled(64, -1)),
|
||||
objectGrid: objectGrid,
|
||||
music: Music.level01,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Sprite _sprite(int color) =>
|
||||
Sprite(Uint8List.fromList(List<int>.filled(64 * 64, color)));
|
||||
@@ -88,6 +88,7 @@ class _RecordingEngine extends Wolf3dFlutterEngine {
|
||||
Future<Wolf3dFlutterEngine> init({
|
||||
String? directory,
|
||||
Iterable<String>? additionalDirectories,
|
||||
Iterable<WolfensteinData>? seededGames,
|
||||
}) async {
|
||||
initCallCount++;
|
||||
availableGames
|
||||
|
||||
Reference in New Issue
Block a user