App constructor
App({
- AccessConflictPolicy accessConflictPolicy = AccessConflictPolicy.warn,
- void onDiagnostic(
- String message
- AppDiagnostics diagnostics = const AppDiagnostics(),
Creates an app with the built-in schedules registered.
Implementation
App({
this.accessConflictPolicy = AccessConflictPolicy.warn,
this.onDiagnostic,
AppDiagnostics diagnostics = const AppDiagnostics(),
}) : profiler = _buildProfiler(diagnostics, onDiagnostic) {
for (final label in Schedules.all) {
_schedules[label] = Schedule(label);
}
// Lets systems dispatch a custom schedule through world.runSchedule
// without reaching the app.
world.resources.insert<ScheduleRunner>(ScheduleRunner(world, runSchedule));
// Built-in runtime behavior, like the state-scoped despawn walk: entities
// carrying DespawnAfter tick down each update and despawn at zero. Games
// order against it with before/after on DespawnAfterSystem.label. Gated
// on the store having rows so games that never use the component pay one
// map lookup per pass and see nothing in system profiles.
addSystemAdapter(
DespawnAfterSystem(),
schedule: Schedules.update,
label: DespawnAfterSystem.label,
runIf: (world) => world.ensureObjectStore<DespawnAfter>().length > 0,
);
final p = profiler;
if (p != null) world.resources.insert<SystemProfiler>(p);
final sink = onDiagnostic;
if (sink != null) {
// The accidental O(N×M) shape: a query iterated inside another
// query's `each` in the same system. Detection runs only in debug
// mode (the world's tracking sits inside asserts) and reports once
// per system.
world.onNestedQuery = sink;
// Report dropped unread events once per type.
world.onEventReaderSkip = (type, skipped) {
if (!_reportedEventSkips.add(type)) return;
sink(
'An EventReader<$type> fell behind: $skipped unread event(s) '
'expired past the channel retention window. This means a reader '
'went longer than the window without a turn — usually a system '
'gated by runIf, or a FIXED-step reader at a refresh rate high '
'enough that render frames carry zero fixed steps. Widen the '
'window with addEvent<$type>(retainedUpdates: ...) or pass null '
'to retain events until every reader consumes them. (Reported '
'once per event type.)',
);
};
}
}