feat: add Lua runtime storage API

This commit is contained in:
gem
2026-06-10 11:31:17 +08:00
parent 8ddc3be3a7
commit 6608d0a975
5 changed files with 162 additions and 1 deletions

View File

@@ -0,0 +1,94 @@
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
class RuntimeStorageManager {
RuntimeStorageManager._(this._file, this._values);
final File _file;
final Map<String, Object?> _values;
static Future<RuntimeStorageManager> create({required String gameId}) async {
final root = await getApplicationSupportDirectory();
final directory = Directory(p.join(root.path, 'flame_lua_storage'));
if (!directory.existsSync()) {
directory.createSync(recursive: true);
}
final file = File(p.join(directory.path, '$gameId.json'));
if (!file.existsSync()) {
return RuntimeStorageManager._(file, <String, Object?>{});
}
try {
final raw = jsonDecode(file.readAsStringSync());
if (raw is Map) {
return RuntimeStorageManager._(
file,
Map<String, Object?>.from(raw),
);
}
} catch (_) {
// Corrupt storage should not prevent a game from loading.
}
return RuntimeStorageManager._(file, <String, Object?>{});
}
Object? getValue(String key, [Object? defaultValue]) {
if (!_values.containsKey(key)) {
return defaultValue;
}
return _values[key];
}
bool setValue(String key, Object? value) {
_values[key] = _normalize(value);
_flush();
return true;
}
bool remove(String key) {
final removed = _values.remove(key) != null;
if (removed) {
_flush();
}
return removed;
}
bool clear() {
if (_values.isEmpty) {
return false;
}
_values.clear();
_flush();
return true;
}
Map<String, Object?> debugJson() => Map<String, Object?>.from(_values);
Object? _normalize(Object? value) {
if (value == null || value is bool || value is num || value is String) {
return value;
}
if (value is List) {
return value.map(_normalize).toList(growable: false);
}
if (value is Map) {
return {
for (final entry in value.entries) entry.key.toString(): _normalize(entry.value),
};
}
return value.toString();
}
void _flush() {
final parent = _file.parent;
if (!parent.existsSync()) {
parent.createSync(recursive: true);
}
_file.writeAsStringSync(jsonEncode(_values));
}
}