Initial flame_lua_runtime package

This commit is contained in:
gem
2026-06-07 22:53:58 +08:00
commit 733b2fb798
262 changed files with 28439 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
part of 'runtime_audio_manager.dart';
extension _RuntimeAudioManagerLoading on RuntimeAudioManager {
Future<Uint8List?> _loadAudio(
String? keyOrPath, {
required bool failOnError,
}) {
if (keyOrPath == null || keyOrPath.isEmpty) {
return Future.value(null);
}
final requestToken = _asyncGate.token;
final requestGeneration = requestToken.generation;
final path = _tryResolve(keyOrPath);
if (path == null) {
return Future.value(null);
}
final existing = _audios[path];
if (existing != null) {
final bytes = existing.bytes;
if (existing.generation == requestGeneration &&
existing.state == GameResourceState.ready &&
bytes != null) {
_touch(existing);
return Future.value(bytes);
}
final inflight = existing.inflight;
if (existing.generation == requestGeneration && inflight != null) {
return failOnError
? _throwIfNull(inflight, keyOrPath)
: inflight.catchError((_) => null);
}
}
final record = _AudioResourceRecord(generation: requestGeneration)
..state = GameResourceState.loading;
_audios[path] = record;
final future = _readAudio(path, record, requestToken);
record.inflight = future;
return failOnError ? _throwIfNull(future, keyOrPath) : future;
}
Future<Uint8List?> _throwIfNull(
Future<Uint8List?> future,
String keyOrPath,
) async {
final bytes = await future;
if (bytes == null) {
throw ResourceLoadException('Required audio resource failed: $keyOrPath');
}
return bytes;
}
Future<Uint8List?> _readAudio(
String path,
_AudioResourceRecord record,
RuntimeAsyncToken requestToken,
) async {
try {
final activePackage = _package;
if (activePackage == null) {
throw StateError('RuntimeAudioManager has no active package');
}
final ownedBytes = await _loadLimiter.run(() async {
final data = await activePackage.readBytes(path);
final bytes = data.buffer.asUint8List(
data.offsetInBytes,
data.lengthInBytes,
);
return Uint8List.fromList(bytes);
});
record.inflight = null;
if (_disposed ||
!_asyncGate.accepts(requestToken) ||
_audios[path] != record) {
record.state = GameResourceState.disposed;
return null;
}
record
..bytes = ownedBytes
..state = GameResourceState.ready
..lastError = null;
_cacheBytes += ownedBytes.length;
_touch(record);
_enforceAudioBudget();
return ownedBytes;
} catch (error) {
record.inflight = null;
if (_disposed ||
!_asyncGate.accepts(requestToken) ||
_audios[path] != record) {
record.state = GameResourceState.disposed;
return null;
}
record
..state = GameResourceState.failed
..lastError = error;
_diagnostics?.record(
type: RuntimeDiagnosticType.resourceLoadError,
message: 'Audio resource failed to load',
error: error,
context: {'path': path, 'generation': requestToken.generation},
);
return null;
}
}
String? _tryResolve(String keyOrPath) {
try {
final activePackage = _package;
if (activePackage == null) {
return null;
}
return activePackage.resolveResourcePath(keyOrPath);
} catch (_) {
return null;
}
}
}