Initial flame_lua_runtime package
This commit is contained in:
80
lib/runtime/events/runtime_event_dispatcher.dart
Normal file
80
lib/runtime/events/runtime_event_dispatcher.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
lib/runtime/events/runtime_event_gate.dart
Normal file
47
lib/runtime/events/runtime_event_gate.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import '../lifecycle/runtime_session.dart';
|
||||
import '../models/runtime_event.dart';
|
||||
|
||||
class RuntimeEventGate {
|
||||
const RuntimeEventGate({
|
||||
required this.session,
|
||||
required bool Function(String id) isScopeAlive,
|
||||
bool Function(String id, int epoch)? isNodeEpochAlive,
|
||||
}) : _isScopeAlive = isScopeAlive,
|
||||
_isNodeEpochAlive = isNodeEpochAlive;
|
||||
|
||||
final RuntimeSession session;
|
||||
final bool Function(String id) _isScopeAlive;
|
||||
final bool Function(String id, int epoch)? _isNodeEpochAlive;
|
||||
|
||||
RuntimeEvent attachSession(RuntimeEvent event) {
|
||||
return event.withLifecycle(sessionId: event.sessionId ?? session.id);
|
||||
}
|
||||
|
||||
bool accepts(RuntimeEvent event) {
|
||||
final eventSessionId = event.sessionId;
|
||||
if (eventSessionId != null && !session.accepts(eventSessionId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final target = event.target;
|
||||
final targetEpoch = event.targetEpoch;
|
||||
final epochChecker = _isNodeEpochAlive;
|
||||
if (target != null && targetEpoch != null && epochChecker != null) {
|
||||
if (!epochChecker(target, targetEpoch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final scope = event.scope;
|
||||
if (scope != null && !_isScopeAlive(scope)) {
|
||||
return false;
|
||||
}
|
||||
final scopeEpoch = event.scopeEpoch;
|
||||
if (scope != null && scopeEpoch != null && epochChecker != null) {
|
||||
if (!epochChecker(scope, scopeEpoch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user