feat: Add tests for Wolf3dGuiApp and refactor game data picker management

- Introduced unit tests for the Wolf3dGuiApp to ensure proper directory configuration and audio management.
- Refactored the GameDataPickerManager to streamline directory and file selection processes.
- Removed obsolete GameDataPickerManager and Wolf3dAppManager classes to simplify the architecture.
- Enhanced the Wolf3dFlutterEngine to improve game version handling during save loading.
- Updated existing tests to reflect changes in the game data management structure.
- Removed unnecessary dependencies and cleaned up the codebase for better maintainability.

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-24 14:35:20 +01:00
parent b980174905
commit ce4dd8d61d
18 changed files with 1919 additions and 810 deletions
@@ -330,17 +330,21 @@ class WolfEngine {
final SaveGameFile file = saveGameCodec.decode(bytes);
GameSessionSnapshot snapshot = file.snapshot;
int gameIndex = snapshot.currentGameIndex;
if (gameIndex < 0 || gameIndex >= _availableGames.length) {
int gameIndex = _availableGames.indexWhere(
(game) =>
game.version == file.gameVersion &&
game.dataVersion.name == file.dataVersionName,
);
if (gameIndex < 0) {
gameIndex = _availableGames.indexWhere(
(game) =>
game.version == file.gameVersion &&
game.dataVersion.name == file.dataVersionName,
(game) => game.version == file.gameVersion,
);
if (gameIndex < 0) {
gameIndex = _availableGames.indexWhere(
(game) => game.version == file.gameVersion,
);
}
if (gameIndex < 0) {
final int snapshotGameIndex = snapshot.currentGameIndex;
if (snapshotGameIndex >= 0 &&
snapshotGameIndex < _availableGames.length) {
gameIndex = snapshotGameIndex;
}
}
@@ -444,9 +444,90 @@ void main() {
expect(retailEngine.hasLoadableSave, isFalse);
expect(sharewareEngine.hasLoadableSave, isTrue);
});
test(
'loadFromSlot prefers save metadata over stale snapshot game index',
() async {
final input = _TestInput();
final persistence = _InMemorySaveGamePersistence();
final engine = _buildMultiGameEngine(
input: input,
difficulty: Difficulty.medium,
saveGamePersistence: persistence,
);
engine.init();
final GameSessionSnapshot retailSnapshot = engine.captureSaveState();
final GameSessionSnapshot staleIndexSnapshot =
_copySnapshotWithGameIndex(
retailSnapshot,
1,
);
final SaveGameFile mismatchedFile = SaveGameFile(
slot: 0,
gameVersion: GameVersion.retail,
dataVersionName: DataVersion.unknown.name,
description: 'Retail save with stale snapshot index',
createdAtMs: DateTime.now().millisecondsSinceEpoch,
snapshot: staleIndexSnapshot,
checksum: 0,
);
await persistence.save(
slot: 0,
version: GameVersion.retail,
bytes: engine.saveGameCodec.encode(mismatchedFile),
);
final bool loaded = await engine.loadFromSlot(0);
expect(loaded, isTrue);
expect(engine.data.version, GameVersion.retail);
expect(engine.currentGameIndex, 0);
final bool saved = await engine.saveToSlot(
1,
description: 'After load',
);
expect(saved, isTrue);
expect(
await persistence.exists(slot: 1, version: GameVersion.retail),
isTrue,
);
expect(
await persistence.exists(slot: 1, version: GameVersion.shareware),
isFalse,
);
},
);
});
}
GameSessionSnapshot _copySnapshotWithGameIndex(
GameSessionSnapshot snapshot,
int gameIndex,
) {
return GameSessionSnapshot(
currentGameIndex: gameIndex,
currentEpisodeIndex: snapshot.currentEpisodeIndex,
currentLevelIndex: snapshot.currentLevelIndex,
returnLevelIndex: snapshot.returnLevelIndex,
difficulty: snapshot.difficulty,
timeAliveMs: snapshot.timeAliveMs,
lastAcousticAlertTime: snapshot.lastAcousticAlertTime,
isMapOverlayVisible: snapshot.isMapOverlayVisible,
isMenuOverlayVisible: snapshot.isMenuOverlayVisible,
player: snapshot.player,
currentLevel: snapshot.currentLevel,
areaGrid: snapshot.areaGrid,
areasByPlayer: snapshot.areasByPlayer,
entities: snapshot.entities,
doors: snapshot.doors,
pushwalls: snapshot.pushwalls,
);
}
WolfEngine _buildMultiGameEngine({
required _TestInput input,
required Difficulty? difficulty,