Added dynamic discovery of available game data
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
13
packages/wolf_3d_data/lib/src/classes/game_file.dart
Normal file
13
packages/wolf_3d_data/lib/src/classes/game_file.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
enum GameFile {
|
||||
vswap('VSWAP'),
|
||||
mapHead('MAPHEAD'),
|
||||
gameMaps('GAMEMAPS'),
|
||||
vgaDict('VGADICT'),
|
||||
vgaHead('VGAHEAD'),
|
||||
vgaGraph('VGAGRAPH')
|
||||
;
|
||||
|
||||
final String baseName;
|
||||
|
||||
const GameFile(this.baseName);
|
||||
}
|
||||
79
packages/wolf_3d_data/lib/src/io/discovery_io.dart
Normal file
79
packages/wolf_3d_data/lib/src/io/discovery_io.dart
Normal file
@@ -0,0 +1,79 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import '../classes/game_file.dart';
|
||||
import '../classes/game_version.dart';
|
||||
import '../classes/wolfenstein_data.dart';
|
||||
import '../wl_parser.dart';
|
||||
|
||||
/// dart:io implementation for directory discovery.
|
||||
Future<Map<GameVersion, WolfensteinData>> discoverInDirectory({
|
||||
String? directoryPath,
|
||||
bool recursive = false,
|
||||
}) async {
|
||||
final dir = Directory(directoryPath ?? Directory.current.path);
|
||||
if (!await dir.exists()) {
|
||||
print('Warning: Directory does not exist -> ${dir.path}');
|
||||
return {};
|
||||
}
|
||||
|
||||
final allFiles = await dir
|
||||
.list(recursive: recursive)
|
||||
.where((entity) => entity is File)
|
||||
.cast<File>()
|
||||
.toList();
|
||||
|
||||
final Map<GameVersion, WolfensteinData> loadedVersions = {};
|
||||
|
||||
for (final version in GameVersion.values) {
|
||||
final ext = version.fileExtension.toUpperCase();
|
||||
final Map<GameFile, File> foundFiles = {};
|
||||
|
||||
for (final requiredFile in GameFile.values) {
|
||||
final expectedName = '${requiredFile.baseName}.$ext';
|
||||
|
||||
final match = allFiles.where((file) {
|
||||
final fileName = file.uri.pathSegments.last.toUpperCase();
|
||||
return fileName == expectedName;
|
||||
}).firstOrNull;
|
||||
|
||||
if (match != null) {
|
||||
foundFiles[requiredFile] = match;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundFiles.isEmpty) continue;
|
||||
|
||||
if (foundFiles.length < GameFile.values.length) {
|
||||
final missingFiles = GameFile.values
|
||||
.where((f) => !foundFiles.containsKey(f))
|
||||
.map((f) => '${f.baseName}.$ext')
|
||||
.join(', ');
|
||||
print('Found partial data for ${version.name}. Missing: $missingFiles');
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
final data = WLParser.load(
|
||||
version: version,
|
||||
vswap: await _readFile(foundFiles[GameFile.vswap]!),
|
||||
mapHead: await _readFile(foundFiles[GameFile.mapHead]!),
|
||||
gameMaps: await _readFile(foundFiles[GameFile.gameMaps]!),
|
||||
vgaDict: await _readFile(foundFiles[GameFile.vgaDict]!),
|
||||
vgaHead: await _readFile(foundFiles[GameFile.vgaHead]!),
|
||||
vgaGraph: await _readFile(foundFiles[GameFile.vgaGraph]!),
|
||||
);
|
||||
|
||||
loadedVersions[version] = data;
|
||||
} catch (e) {
|
||||
print('Error parsing data for ${version.name}: $e');
|
||||
}
|
||||
}
|
||||
|
||||
return loadedVersions;
|
||||
}
|
||||
|
||||
Future<ByteData> _readFile(File file) async {
|
||||
final bytes = await file.readAsBytes();
|
||||
return bytes.buffer.asByteData();
|
||||
}
|
||||
13
packages/wolf_3d_data/lib/src/io/discovery_stub.dart
Normal file
13
packages/wolf_3d_data/lib/src/io/discovery_stub.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import '../classes/game_version.dart';
|
||||
import '../classes/wolfenstein_data.dart';
|
||||
|
||||
/// Web-safe stub for directory discovery.
|
||||
Future<Map<GameVersion, WolfensteinData>> discoverInDirectory({
|
||||
String? directoryPath,
|
||||
bool recursive = false,
|
||||
}) async {
|
||||
throw UnsupportedError(
|
||||
'Directory scanning is not supported on Web. '
|
||||
'Please load the files manually using WolfensteinLoader.loadFromBytes().',
|
||||
);
|
||||
}
|
||||
48
packages/wolf_3d_data/lib/src/wolfenstein_loader.dart
Normal file
48
packages/wolf_3d_data/lib/src/wolfenstein_loader.dart
Normal file
@@ -0,0 +1,48 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'classes/game_version.dart';
|
||||
import 'classes/wolfenstein_data.dart';
|
||||
// --- The Magic Conditional Import ---
|
||||
// If dart:io is available, use the real scanner. Otherwise, use the stub.
|
||||
import 'io/discovery_stub.dart'
|
||||
if (dart.library.io) 'io/discovery_io.dart'
|
||||
as platform;
|
||||
import 'wl_parser.dart';
|
||||
|
||||
class WolfensteinLoader {
|
||||
/// Scans a directory for Wolfenstein 3D data files and loads all available versions.
|
||||
///
|
||||
/// NOTE: This will throw an [UnsupportedError] on Web platforms.
|
||||
static Future<Map<GameVersion, WolfensteinData>> discover({
|
||||
String? directoryPath,
|
||||
bool recursive = false,
|
||||
}) {
|
||||
return platform.discoverInDirectory(
|
||||
directoryPath: directoryPath,
|
||||
recursive: recursive,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parses WolfensteinData directly from raw ByteData.
|
||||
/// This is 100% pure Dart and is safe to use on all platforms, including Web.
|
||||
static WolfensteinData loadFromBytes({
|
||||
required GameVersion version,
|
||||
required ByteData vswap,
|
||||
required ByteData mapHead,
|
||||
required ByteData gameMaps,
|
||||
required ByteData vgaDict,
|
||||
required ByteData vgaHead,
|
||||
required ByteData vgaGraph,
|
||||
}) {
|
||||
// We just act as a clean pass-through to the core parser
|
||||
return WLParser.load(
|
||||
version: version,
|
||||
vswap: vswap,
|
||||
mapHead: mapHead,
|
||||
gameMaps: gameMaps,
|
||||
vgaDict: vgaDict,
|
||||
vgaHead: vgaHead,
|
||||
vgaGraph: vgaGraph,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
/// More dartdocs go here.
|
||||
library;
|
||||
|
||||
export 'src/classes/game_file.dart' show GameFile;
|
||||
export 'src/classes/game_version.dart' show GameVersion;
|
||||
export 'src/classes/image.dart' show VgaImage;
|
||||
export 'src/classes/sound.dart' show PcmSound;
|
||||
@@ -10,3 +11,4 @@ export 'src/classes/sprite.dart' hide Matrix;
|
||||
export 'src/classes/wolf_level.dart' show WolfLevel;
|
||||
export 'src/classes/wolfenstein_data.dart' show WolfensteinData;
|
||||
export 'src/wl_parser.dart' show WLParser;
|
||||
export 'src/wolfenstein_loader.dart' show WolfensteinLoader;
|
||||
|
||||
Reference in New Issue
Block a user