114 lines
3.4 KiB
Dart
114 lines
3.4 KiB
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_types.dart';
|
|
import 'package:wolf_3d_dart/wolf_3d_engine.dart';
|
|
import 'package:wolf_3d_dart/wolf_3d_synth.dart';
|
|
|
|
class Wolf3d {
|
|
Wolf3d._();
|
|
static final Wolf3d _instance = Wolf3d._();
|
|
static Wolf3d get I => _instance;
|
|
|
|
// --- State ---
|
|
final List<WolfensteinData> availableGames = [];
|
|
WolfensteinData? _activeGame;
|
|
|
|
// --- Core Systems ---
|
|
final EngineAudio audio = WolfAudio();
|
|
|
|
// --- Getters ---
|
|
WolfensteinData get activeGame {
|
|
if (_activeGame == null) {
|
|
throw StateError("No active game selected. Call setActiveGame() first.");
|
|
}
|
|
return _activeGame!;
|
|
}
|
|
|
|
// --- Episode ---
|
|
int _activeEpisode = 0;
|
|
|
|
int get activeEpisode => _activeEpisode;
|
|
|
|
void setActiveEpisode(int episodeIndex) {
|
|
_activeEpisode = episodeIndex;
|
|
}
|
|
|
|
// Convenience getters for the active game's assets
|
|
List<WolfLevel> get levels => activeGame.episodes[activeEpisode].levels;
|
|
List<Sprite> get walls => activeGame.walls;
|
|
List<Sprite> get sprites => activeGame.sprites;
|
|
List<PcmSound> get sounds => activeGame.sounds;
|
|
List<PcmSound> get adLibSounds => activeGame.adLibSounds;
|
|
List<ImfMusic> get music => activeGame.music;
|
|
List<VgaImage> get vgaImages => activeGame.vgaImages;
|
|
|
|
// --- Actions ---
|
|
void setActiveGame(WolfensteinData game) {
|
|
_activeGame = game;
|
|
audio.activeGame = game;
|
|
}
|
|
|
|
/// Initializes the engine by loading available game data.
|
|
Future<void> init({String? directory}) async {
|
|
await audio.init();
|
|
availableGames.clear();
|
|
|
|
// 1. Bundle asset loading (migrated from GameSelectScreen)
|
|
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 folder = 'packages/wolf_3d_assets/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'),
|
|
);
|
|
|
|
availableGames.add(data);
|
|
} catch (e) {
|
|
debugPrint(e.toString());
|
|
}
|
|
}
|
|
|
|
// 2. External side-loading (non-web)
|
|
if (!kIsWeb) {
|
|
try {
|
|
final externalGames = await WolfensteinLoader.discover(
|
|
directoryPath: directory,
|
|
recursive: true,
|
|
);
|
|
for (var entry in externalGames.entries) {
|
|
if (!availableGames.any((g) => g.version == entry.key)) {
|
|
availableGames.add(entry.value);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
debugPrint("External discovery failed: $e");
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<ByteData?> _tryLoad(String path) async {
|
|
try {
|
|
return await rootBundle.load(path);
|
|
} catch (e) {
|
|
debugPrint("Asset not found: $path");
|
|
return null;
|
|
}
|
|
}
|
|
}
|