97 lines
2.8 KiB
Dart
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 }
|