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:flutter/material.dart';
|
||||||
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
|
import 'package:wolf_3d_flutter/wolf_3d_flutter.dart';
|
||||||
|
|
||||||
|
import 'packaged_games_loader.dart';
|
||||||
import 'wolf3d_gui_app.dart';
|
import 'wolf3d_gui_app.dart';
|
||||||
|
|
||||||
/// Creates the application shell after loading available Wolf3D data sets.
|
/// Creates the application shell after loading available Wolf3D data sets.
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
final seededGames = await loadPackagedGames();
|
||||||
|
|
||||||
final Wolf3dFlutterEngine wolf3d = await Wolf3dFlutterEngine(
|
final Wolf3dFlutterEngine wolf3d = await Wolf3dFlutterEngine(
|
||||||
debug: kDebugMode,
|
debug: kDebugMode,
|
||||||
).init();
|
).init(seededGames: seededGames);
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
wolf3d.enableMenuHeaderBandDebugLogging(prefix: '[wolf_3d_gui]');
|
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
|
file_selector: ^1.0.3
|
||||||
wolf_3d_flutter:
|
wolf_3d_flutter:
|
||||||
wolf_3d_dart:
|
wolf_3d_dart:
|
||||||
|
wolf_3d_assets:
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class _RecordingEngine extends Wolf3dFlutterEngine {
|
|||||||
Future<Wolf3dFlutterEngine> init({
|
Future<Wolf3dFlutterEngine> init({
|
||||||
String? directory,
|
String? directory,
|
||||||
Iterable<String>? additionalDirectories,
|
Iterable<String>? additionalDirectories,
|
||||||
|
Iterable<WolfensteinData>? seededGames,
|
||||||
}) async {
|
}) async {
|
||||||
initCallCount++;
|
initCallCount++;
|
||||||
lastDirectory = directory;
|
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({
|
Future<Wolf3dFlutterEngine> init({
|
||||||
String? directory,
|
String? directory,
|
||||||
Iterable<String>? additionalDirectories,
|
Iterable<String>? additionalDirectories,
|
||||||
|
Iterable<WolfensteinData>? seededGames,
|
||||||
}) async {
|
}) async {
|
||||||
initCallCount++;
|
initCallCount++;
|
||||||
availableGames
|
availableGames
|
||||||
|
|||||||
@@ -39,7 +39,30 @@ final Wolf3dFlutterEngine engine = await Wolf3dFlutterEngine(
|
|||||||
).init();
|
).init();
|
||||||
```
|
```
|
||||||
|
|
||||||
`init()` handles platform setup, audio init, and configured game-data discovery.
|
`init()` handles platform setup, audio init, configured external discovery, and
|
||||||
|
optional seeded game injection.
|
||||||
|
|
||||||
|
To load packaged game data from `wolf_3d_assets`, use
|
||||||
|
`Wolf3dFlutterEngine.loadGameDataFromAssets(...)` and pass the result via
|
||||||
|
`seededGames`:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final retail = await Wolf3dFlutterEngine.loadGameDataFromAssets(
|
||||||
|
version: GameVersion.retail,
|
||||||
|
packageName: 'wolf_3d_assets',
|
||||||
|
assetDirectory: 'assets/retail',
|
||||||
|
);
|
||||||
|
|
||||||
|
final shareware = await Wolf3dFlutterEngine.loadGameDataFromAssets(
|
||||||
|
version: GameVersion.shareware,
|
||||||
|
packageName: 'wolf_3d_assets',
|
||||||
|
assetDirectory: 'assets/shareware',
|
||||||
|
);
|
||||||
|
|
||||||
|
final Wolf3dFlutterEngine engine = await Wolf3dFlutterEngine(
|
||||||
|
debug: kDebugMode,
|
||||||
|
).init(seededGames: [retail, shareware]);
|
||||||
|
```
|
||||||
|
|
||||||
The facade itself lives in `lib/engine/wolf3d_flutter_engine.dart` and is re-exported
|
The facade itself lives in `lib/engine/wolf3d_flutter_engine.dart` and is re-exported
|
||||||
through the package barrel at `lib/wolf_3d_flutter.dart`. External consumers
|
through the package barrel at `lib/wolf_3d_flutter.dart`. External consumers
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
library;
|
library;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:wolf_3d_dart/wolf_3d_data.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_data_types.dart';
|
||||||
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
|
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
|
||||||
@@ -11,6 +12,8 @@ import 'package:wolf_3d_flutter/managers/desktop_windowing_support.dart'
|
|||||||
as desktop_windowing_support;
|
as desktop_windowing_support;
|
||||||
import 'package:wolf_3d_flutter/managers/game_data_directory_persistence.dart';
|
import 'package:wolf_3d_flutter/managers/game_data_directory_persistence.dart';
|
||||||
|
|
||||||
|
typedef Wolf3dAssetByteLoader = Future<ByteData> Function(String assetKey);
|
||||||
|
|
||||||
/// Flutter-specific host facade built on top of [Wolf3dEngine].
|
/// Flutter-specific host facade built on top of [Wolf3dEngine].
|
||||||
///
|
///
|
||||||
/// This type keeps platform-neutral session and engine state in
|
/// This type keeps platform-neutral session and engine state in
|
||||||
@@ -51,12 +54,105 @@ class Wolf3dFlutterEngine extends Wolf3dEngine {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Routes shared menu header band diagnostics to [logger].
|
||||||
|
///
|
||||||
|
/// Pass `null` to disable menu header band diagnostics.
|
||||||
|
@override
|
||||||
|
Wolf3dFlutterEngine setMenuHeaderBandDebugLogger(
|
||||||
|
void Function(String message)? logger,
|
||||||
|
) {
|
||||||
|
super.setMenuHeaderBandDebugLogger(logger);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables menu header band diagnostics with an optional [prefix].
|
||||||
|
@override
|
||||||
|
Wolf3dFlutterEngine enableMenuHeaderBandDebugLogging({
|
||||||
|
String prefix = '[MENU_HEADER_BAND]',
|
||||||
|
}) {
|
||||||
|
super.enableMenuHeaderBandDebugLogging(prefix: prefix);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disables menu header band diagnostics.
|
||||||
|
@override
|
||||||
|
Wolf3dFlutterEngine disableMenuHeaderBandDebugLogging() {
|
||||||
|
super.disableMenuHeaderBandDebugLogging();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads a game data set from Flutter packaged assets.
|
||||||
|
///
|
||||||
|
/// Intended for loading from dependency asset packages such as
|
||||||
|
/// `wolf_3d_assets` by passing [packageName] and [assetDirectory], then
|
||||||
|
/// supplying the result to [init] via [seededGames].
|
||||||
|
static Future<WolfensteinData> loadGameDataFromAssets({
|
||||||
|
required GameVersion version,
|
||||||
|
required String assetDirectory,
|
||||||
|
String? packageName = 'wolf_3d_assets',
|
||||||
|
AssetRegistry? registryOverride,
|
||||||
|
Wolf3dAssetByteLoader? assetLoader,
|
||||||
|
}) async {
|
||||||
|
final String ext = version.fileExtension;
|
||||||
|
final Wolf3dAssetByteLoader loader = assetLoader ?? rootBundle.load;
|
||||||
|
|
||||||
|
final String normalizedDirectory = assetDirectory.trim().replaceAll(
|
||||||
|
RegExp(r'^/+|/+$'),
|
||||||
|
'',
|
||||||
|
);
|
||||||
|
if (normalizedDirectory.isEmpty) {
|
||||||
|
throw ArgumentError.value(
|
||||||
|
assetDirectory,
|
||||||
|
'assetDirectory',
|
||||||
|
'Must not be empty.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String keyFor(String fileName) {
|
||||||
|
final path = '$normalizedDirectory/$fileName';
|
||||||
|
final String? normalizedPackage = packageName?.trim();
|
||||||
|
if (normalizedPackage == null || normalizedPackage.isEmpty) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
return 'packages/$normalizedPackage/$path';
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ByteData> loadRequired(String fileName) {
|
||||||
|
return loader(keyFor(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ByteData> loadWithFallback(
|
||||||
|
String primaryName,
|
||||||
|
String fallbackName,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
return await loadRequired(primaryName);
|
||||||
|
} catch (_) {
|
||||||
|
return loadRequired(fallbackName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WolfensteinLoader.loadFromBytes(
|
||||||
|
version: version,
|
||||||
|
vswap: await loadRequired('VSWAP.$ext'),
|
||||||
|
mapHead: await loadRequired('MAPHEAD.$ext'),
|
||||||
|
gameMaps: await loadWithFallback('GAMEMAPS.$ext', 'MAPTEMP.$ext'),
|
||||||
|
vgaDict: await loadRequired('VGADICT.$ext'),
|
||||||
|
vgaHead: await loadRequired('VGAHEAD.$ext'),
|
||||||
|
vgaGraph: await loadRequired('VGAGRAPH.$ext'),
|
||||||
|
audioHed: await loadRequired('AUDIOHED.$ext'),
|
||||||
|
audioT: await loadRequired('AUDIOT.$ext'),
|
||||||
|
registryOverride: registryOverride,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Initializes the engine by loading available game data.
|
/// Initializes the engine by loading available game data.
|
||||||
///
|
///
|
||||||
/// If [directory] is provided, it is persisted and treated as the primary
|
/// If [directory] is provided, it is persisted and treated as the primary
|
||||||
/// external search root. If omitted, a previously persisted directory is
|
/// external search root. If omitted, a previously persisted directory is
|
||||||
/// used when available. [additionalDirectories] are scanned after the
|
/// used when available. [additionalDirectories] are scanned after the
|
||||||
/// primary directory and are not persisted.
|
/// primary directory and are not persisted. [seededGames] are merged first,
|
||||||
|
/// enabling hosts to inject data from packaged assets.
|
||||||
///
|
///
|
||||||
/// This method scans only configured external directories, deduplicating
|
/// This method scans only configured external directories, deduplicating
|
||||||
/// discovered versions by [GameVersion]. Shared package code does not bundle
|
/// discovered versions by [GameVersion]. Shared package code does not bundle
|
||||||
@@ -64,10 +160,12 @@ class Wolf3dFlutterEngine extends Wolf3dEngine {
|
|||||||
Future<Wolf3dFlutterEngine> init({
|
Future<Wolf3dFlutterEngine> init({
|
||||||
String? directory,
|
String? directory,
|
||||||
Iterable<String>? additionalDirectories,
|
Iterable<String>? additionalDirectories,
|
||||||
|
Iterable<WolfensteinData>? seededGames,
|
||||||
}) async {
|
}) async {
|
||||||
await desktop_windowing_support.ensureDesktopWindowingInitialized();
|
await desktop_windowing_support.ensureDesktopWindowingInitialized();
|
||||||
await audio.init();
|
await audio.init();
|
||||||
availableGames.clear();
|
availableGames.clear();
|
||||||
|
_addUniqueGames(seededGames);
|
||||||
|
|
||||||
final String? requestedDirectory = directory?.trim();
|
final String? requestedDirectory = directory?.trim();
|
||||||
final String? resolvedDirectory =
|
final String? resolvedDirectory =
|
||||||
@@ -103,14 +201,7 @@ class Wolf3dFlutterEngine extends Wolf3dEngine {
|
|||||||
directoryPath: directoryPath,
|
directoryPath: directoryPath,
|
||||||
recursive: true,
|
recursive: true,
|
||||||
);
|
);
|
||||||
for (final MapEntry<GameVersion, WolfensteinData> entry
|
_addUniqueGames(externalGames.values);
|
||||||
in externalGames.entries) {
|
|
||||||
if (!availableGames.any(
|
|
||||||
(WolfensteinData g) => g.version == entry.key,
|
|
||||||
)) {
|
|
||||||
availableGames.add(entry.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint('External discovery failed: $e');
|
debugPrint('External discovery failed: $e');
|
||||||
}
|
}
|
||||||
@@ -119,4 +210,15 @@ class Wolf3dFlutterEngine extends Wolf3dEngine {
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _addUniqueGames(Iterable<WolfensteinData>? games) {
|
||||||
|
if (games == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (final WolfensteinData game in games) {
|
||||||
|
if (!availableGames.any((g) => g.version == game.version)) {
|
||||||
|
availableGames.add(game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,57 @@ void main() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test('init can seed available games from host-provided data', () async {
|
||||||
|
final tempDir = await Directory.systemTemp.createTemp(
|
||||||
|
'wolf3d-seeded-games-',
|
||||||
|
);
|
||||||
|
addTearDown(() async {
|
||||||
|
if (await tempDir.exists()) {
|
||||||
|
await tempDir.delete(recursive: true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final persistence = DefaultGameDataDirectoryPersistence(
|
||||||
|
filePath: '${tempDir.path}/settings.json',
|
||||||
|
);
|
||||||
|
final wolf3d = Wolf3dFlutterEngine(
|
||||||
|
audioBackend: _NoopAudio(),
|
||||||
|
dataDirectoryPersistence: persistence,
|
||||||
|
);
|
||||||
|
final retail = _buildTestData(version: GameVersion.retail);
|
||||||
|
final shareware = _buildTestData(version: GameVersion.shareware);
|
||||||
|
|
||||||
|
await wolf3d.init(seededGames: [retail, shareware]);
|
||||||
|
|
||||||
|
expect(wolf3d.availableGames, hasLength(2));
|
||||||
|
expect(
|
||||||
|
wolf3d.availableGames.map((g) => g.version),
|
||||||
|
containsAll([GameVersion.retail, GameVersion.shareware]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('loadGameDataFromAssets prefixes keys for package assets', () async {
|
||||||
|
final requestedKeys = <String>[];
|
||||||
|
|
||||||
|
await expectLater(
|
||||||
|
() => Wolf3dFlutterEngine.loadGameDataFromAssets(
|
||||||
|
version: GameVersion.retail,
|
||||||
|
assetDirectory: 'assets/retail',
|
||||||
|
packageName: 'wolf_3d_assets',
|
||||||
|
assetLoader: (String key) async {
|
||||||
|
requestedKeys.add(key);
|
||||||
|
throw Exception('Expected test stop after first key.');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
throwsException,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
requestedKeys,
|
||||||
|
contains('packages/wolf_3d_assets/assets/retail/VSWAP.WL6'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('GameScreen hides debug FAB when debug mode is disabled', (
|
testWidgets('GameScreen hides debug FAB when debug mode is disabled', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
@@ -168,7 +219,9 @@ class _TestWolf3d extends Wolf3dFlutterEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WolfensteinData _buildTestData() {
|
WolfensteinData _buildTestData({
|
||||||
|
GameVersion version = GameVersion.retail,
|
||||||
|
}) {
|
||||||
final wallGrid = List.generate(64, (_) => List.filled(64, 0));
|
final wallGrid = List.generate(64, (_) => List.filled(64, 0));
|
||||||
final objectGrid = List.generate(64, (_) => List.filled(64, 0));
|
final objectGrid = List.generate(64, (_) => List.filled(64, 0));
|
||||||
|
|
||||||
@@ -181,9 +234,11 @@ WolfensteinData _buildTestData() {
|
|||||||
objectGrid[2][2] = MapObject.playerEast;
|
objectGrid[2][2] = MapObject.playerEast;
|
||||||
|
|
||||||
return WolfensteinData(
|
return WolfensteinData(
|
||||||
version: GameVersion.retail,
|
version: version,
|
||||||
dataVersion: DataVersion.unknown,
|
dataVersion: DataVersion.unknown,
|
||||||
registry: RetailAssetRegistry(),
|
registry: version == GameVersion.shareware
|
||||||
|
? SharewareAssetRegistry()
|
||||||
|
: RetailAssetRegistry(),
|
||||||
walls: [_sprite(1), _sprite(1), _sprite(2), _sprite(2)],
|
walls: [_sprite(1), _sprite(1), _sprite(2), _sprite(2)],
|
||||||
sprites: List.generate(436, (_) => _sprite(255)),
|
sprites: List.generate(436, (_) => _sprite(255)),
|
||||||
sounds: List.generate(200, (_) => PcmSound(Uint8List(1))),
|
sounds: List.generate(200, (_) => PcmSound(Uint8List(1))),
|
||||||
|
|||||||
Reference in New Issue
Block a user