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

81 lines
2.3 KiB
Dart

import '../diagnostics/runtime_diagnostics.dart';
import '../lifecycle/runtime_serial_queue.dart';
import '../lifecycle/runtime_session.dart';
import '../models/game_diff.dart';
import '../models/runtime_event.dart';
import '../scripting/script_engine.dart';
import 'runtime_event_gate.dart';
class RuntimeEventDispatcher {
RuntimeEventDispatcher({
required RuntimeSession session,
required ScriptEngine scriptEngine,
required bool Function(String id) isScopeAlive,
bool Function(String id, int epoch)? isNodeEpochAlive,
required void Function(GameDiff diff) applyDiff,
RuntimeDiagnostics? diagnostics,
void Function(Object error)? onError,
}) : _scriptEngine = scriptEngine,
_applyDiff = applyDiff,
_diagnostics = diagnostics,
_onError = onError,
_gate = RuntimeEventGate(
session: session,
isScopeAlive: isScopeAlive,
isNodeEpochAlive: isNodeEpochAlive,
) {
_queue = RuntimeSerialQueue<RuntimeEvent>(
shouldContinue: () => !_disposed && session.isActive,
onItem: _dispatch,
);
}
final ScriptEngine _scriptEngine;
final void Function(GameDiff diff) _applyDiff;
final RuntimeDiagnostics? _diagnostics;
final void Function(Object error)? _onError;
final RuntimeEventGate _gate;
late final RuntimeSerialQueue<RuntimeEvent> _queue;
bool _disposed = false;
int get pendingEventCount => _queue.pendingCount;
void enqueue(RuntimeEvent event) {
if (_disposed || !_gate.session.isActive) {
return;
}
_queue.enqueue(_gate.attachSession(event));
}
void dispose() {
_disposed = true;
_queue.dispose();
}
void _dispatch(RuntimeEvent event) {
if (!_gate.accepts(event)) {
return;
}
try {
final diff = _scriptEngine.dispatchEvent(event);
if (_disposed || !_gate.session.isActive || !_gate.accepts(event)) {
return;
}
_applyDiff(diff);
} catch (error) {
_diagnostics?.record(
type: RuntimeDiagnosticType.luaEventError,
message: 'Lua event dispatch failed',
error: error,
context: {
'eventType': event.type,
if (event.target != null) 'target': event.target,
if (event.handler != null) 'handler': event.handler,
},
);
_onError?.call(error);
}
}
}