Files
flutter_lua_runtime/lib/runtime/packages/game_package.dart
2026-06-07 22:53:58 +08:00

97 lines
2.8 KiB
Dart

import 'dart:io';
import 'package:flutter/services.dart';
import '../game/runtime_options.dart';
import 'game_package_manifest.dart';
class GamePackage {
const GamePackage.asset({
required this.rootPath,
required this.manifest,
this.runtimeLuaRoot = RuntimeOptions.defaultRuntimeLuaRoot,
}) : source = GamePackageSource.asset;
static const runtimeLuaPrefix = 'runtime:';
const GamePackage.file({
required this.rootPath,
required this.manifest,
this.runtimeLuaRoot = RuntimeOptions.defaultRuntimeLuaRoot,
}) : source = GamePackageSource.file;
final String rootPath;
final GamePackageSource source;
final GamePackageManifest manifest;
final String runtimeLuaRoot;
String get entryPath => _join(rootPath, manifest.entry);
bool get isAsset => source == GamePackageSource.asset;
Future<String> readText(String relativeOrAbsolutePath) async {
final runtimePath = _resolveRuntimeLuaPath(relativeOrAbsolutePath);
if (runtimePath != null) {
return rootBundle.loadString(runtimePath);
}
final path = _resolvePackagePath(relativeOrAbsolutePath);
if (isAsset) {
return rootBundle.loadString(path);
}
return File(path).readAsString();
}
Future<ByteData> readBytes(String relativeOrAbsolutePath) async {
final path = _resolvePackagePath(relativeOrAbsolutePath);
if (isAsset) {
return rootBundle.load(path);
}
final bytes = await File(path).readAsBytes();
return ByteData.sublistView(bytes);
}
String resolveResourcePath(String keyOrPath) {
final resource = manifest.resources[keyOrPath];
if (resource != null) {
return _join(rootPath, resource.path);
}
if (keyOrPath.startsWith(rootPath)) {
return keyOrPath;
}
if (keyOrPath.contains('/')) {
return _join(rootPath, keyOrPath);
}
return _join(_join(rootPath, manifest.assetsBase), keyOrPath);
}
String _resolvePackagePath(String relativeOrAbsolutePath) {
if (relativeOrAbsolutePath.startsWith(rootPath)) {
return relativeOrAbsolutePath;
}
return _join(rootPath, relativeOrAbsolutePath);
}
String? _resolveRuntimeLuaPath(String path) {
if (!path.startsWith(runtimeLuaPrefix)) {
return null;
}
final name = path.substring(runtimeLuaPrefix.length);
if (name.isEmpty || name.contains('/') || name.contains('..')) {
throw FormatException('Invalid runtime Lua module path: $path');
}
return _join(runtimeLuaRoot, name);
}
String _join(String left, String right) {
final normalizedLeft = left.endsWith('/')
? left.substring(0, left.length - 1)
: left;
final normalizedRight = right.startsWith('/') ? right.substring(1) : right;
return '$normalizedLeft/$normalizedRight';
}
}
enum GamePackageSource { asset, file }