Add bidirectional host bridge

This commit is contained in:
gem
2026-06-09 16:26:37 +08:00
parent 7b3c5cb0f5
commit 0d4fbd030c
17 changed files with 632 additions and 3 deletions

View File

@@ -10,6 +10,7 @@ import '../commands/command_executor.dart';
import '../diagnostics/runtime_diagnostics.dart';
import '../events/runtime_event_dispatcher.dart';
import '../lifecycle/runtime_session.dart';
import '../host/runtime_host_bridge.dart';
import '../models/game_diff.dart';
import '../models/runtime_event.dart';
import '../network/runtime_network_manager.dart';
@@ -41,6 +42,7 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
this.audioMaxConcurrentLoads = 4,
this.audioSfxPoolSize = 8,
this.runtimeOptions = const RuntimeOptions(),
this.hostBridge = const RuntimeHostBridge(),
Locale? localeOverride,
}) : _bootstrapScriptEngine = scriptEngine,
_localeOverride = localeOverride,
@@ -62,6 +64,7 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
final int audioMaxConcurrentLoads;
final int audioSfxPoolSize;
final RuntimeOptions runtimeOptions;
final RuntimeHostBridge hostBridge;
final Locale? _localeOverride;
late final GameResourceManager _resources;
@@ -69,6 +72,7 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
late final RenderTreeController _renderTree;
late final PositionComponent _viewportRoot;
RuntimeNetworkManager? _network;
RuntimeHostBridgeManager? _hostBridgeManager;
RuntimeViewportConfig? _viewportConfig;
late final CommandExecutor _commands;
RuntimeSession? _session;
@@ -83,6 +87,28 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
String diagnosticsDumpText() => diagnostics.dumpText();
Future<Object?> callLua(
String method, {
Object? data,
Duration timeout = const Duration(seconds: 15),
}) {
final hostBridgeManager = _hostBridgeManager;
if (!_runtimeInitialized || hostBridgeManager == null) {
return Future<Object?>.error(
StateError('Lua runtime is not initialized'),
);
}
return hostBridgeManager.callLua(method, data: data, timeout: timeout);
}
bool notifyLua(String method, {Object? data}) {
final hostBridgeManager = _hostBridgeManager;
if (!_runtimeInitialized || hostBridgeManager == null) {
return false;
}
return hostBridgeManager.notifyLua(method, data: data);
}
Map<String, Object?> resourcesDebugJson() {
if (!_runtimeInitialized) {
return {'initialized': false};
@@ -110,6 +136,12 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
diagnostics: diagnostics,
);
_network = network;
final hostBridgeManager = RuntimeHostBridgeManager(
bridge: hostBridge,
eventSink: _emitEvent,
diagnostics: diagnostics,
);
_hostBridgeManager = hostBridgeManager;
final activation =
await PackageActivationController(
repository: _packageRepository,
@@ -119,7 +151,10 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
resourceManagerFactory: _createResourceManager,
audioManagerFactory: _createAudioManager,
scriptEngineFactory: _scriptEngineFactory,
scriptServices: RuntimeScriptServices(network: network),
scriptServices: RuntimeScriptServices(
network: network,
hostBridge: hostBridgeManager,
),
store: StablePackageStore(runtimeOptions: runtimeOptions),
assetFallback: AssetGamePackageRepository(
runtimeOptions: runtimeOptions,
@@ -168,6 +203,8 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
_runtimeInitialized = true;
_applyDiff(activation.initialDiff);
} catch (error) {
_hostBridgeManager?.dispose();
_hostBridgeManager = null;
_network?.dispose();
_network = null;
session.dispose();
@@ -347,6 +384,8 @@ class FlameLuaGame extends FlameGame with PanDetector, ScrollDetector {
_events?.dispose();
if (_runtimeInitialized) {
_commands.dispose();
_hostBridgeManager?.dispose();
_hostBridgeManager = null;
_network?.dispose();
_network = null;
_renderTree.clear();

View File

@@ -2,6 +2,7 @@ import 'package:flame/game.dart';
import 'package:flutter/widgets.dart';
import '../diagnostics/runtime_diagnostics.dart';
import '../host/runtime_host_bridge.dart';
import '../packages/game_package_repository.dart';
import '../scripting/lua_dardo_script_engine.dart';
import 'flame_lua_game.dart';
@@ -14,6 +15,7 @@ class LuaGameWidget extends StatelessWidget {
this.serverUrl,
this.localeOverride,
this.runtimeOptions = const RuntimeOptions(),
this.hostBridge = const RuntimeHostBridge(),
super.key,
});
@@ -22,6 +24,7 @@ class LuaGameWidget extends StatelessWidget {
final Uri? serverUrl;
final Locale? localeOverride;
final RuntimeOptions runtimeOptions;
final RuntimeHostBridge hostBridge;
@override
Widget build(BuildContext context) {
@@ -42,6 +45,7 @@ class LuaGameWidget extends StatelessWidget {
)),
gameId: gameId,
runtimeOptions: runtimeOptions,
hostBridge: hostBridge,
localeOverride: localeOverride,
),
);