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

@@ -3,6 +3,7 @@ import 'dart:async' as async;
import 'package:lua_dardo_plus/lua.dart';
import '../diagnostics/runtime_diagnostics.dart';
import '../host/runtime_host_bridge.dart';
import '../models/game_diff.dart';
import '../models/runtime_event.dart';
import '../network/runtime_network_manager.dart';
@@ -19,6 +20,7 @@ class LuaDardoScriptEngine implements ScriptEngine {
late final Map<String, String> _moduleScripts;
RuntimeScriptServices _services = const RuntimeScriptServices();
int _networkRequestCounter = 0;
int _hostCallCounter = 0;
final Set<String> _loadingModules = {};
@override
@@ -28,6 +30,7 @@ class LuaDardoScriptEngine implements ScriptEngine {
}) async {
_services = services;
_networkRequestCounter = 0;
_hostCallCounter = 0;
final script = await package.readText(package.manifest.entry);
_moduleScripts = {};
for (final entry in package.manifest.modules.entries) {
@@ -135,6 +138,15 @@ class LuaDardoScriptEngine implements ScriptEngine {
_lua.pushDartFunction(_wsClose);
_lua.setField(-2, 'ws_close');
_lua.pushDartFunction(_hostCall);
_lua.setField(-2, 'host_call');
_lua.pushDartFunction(_hostNotify);
_lua.setField(-2, 'host_notify');
_lua.pushDartFunction(_hostRespond);
_lua.setField(-2, 'host_respond');
_lua.setGlobal('runtime');
}
@@ -204,6 +216,56 @@ class LuaDardoScriptEngine implements ScriptEngine {
return 1;
}
int _hostCall(LuaState lua) {
final host = _requireHostBridge();
final options = _requiredMapArgument(1, 'runtime.host_call(options)');
final method = _requiredString(options, 'method');
final id = _optionalString(options, 'id') ?? _nextHostCallId();
async.unawaited(
host.callHost(
RuntimeHostCall(id: id, method: method, data: options['data']),
),
);
lua.pushString(id);
return 1;
}
int _hostNotify(LuaState lua) {
final host = _requireHostBridge();
final options = _requiredMapArgument(1, 'runtime.host_notify(options)');
final method = _requiredString(options, 'method');
lua.pushBoolean(
host.notifyHost(
RuntimeHostNotification(method: method, data: options['data']),
),
);
return 1;
}
int _hostRespond(LuaState lua) {
final host = _requireHostBridge();
final options = _requiredMapArgument(1, 'runtime.host_respond(options)');
final id = _requiredString(options, 'id');
final error = _optionalString(options, 'error');
lua.pushBoolean(
host.completeLuaCall(id, result: options['result'], error: error),
);
return 1;
}
RuntimeHostBridgeManager _requireHostBridge() {
final hostBridge = _services.hostBridge;
if (hostBridge == null) {
throw StateError('Runtime host bridge service is not installed');
}
return hostBridge;
}
String _nextHostCallId() {
_hostCallCounter += 1;
return 'lua:$_hostCallCounter';
}
RuntimeNetworkManager _requireNetwork() {
final network = _services.network;
if (network == null) {

View File

@@ -1,7 +1,9 @@
import '../host/runtime_host_bridge.dart';
import '../network/runtime_network_manager.dart';
class RuntimeScriptServices {
const RuntimeScriptServices({this.network});
const RuntimeScriptServices({this.network, this.hostBridge});
final RuntimeNetworkManager? network;
final RuntimeHostBridgeManager? hostBridge;
}