apply method
void
apply()
Applies and clears all pending commands. Must not be called while a query is iterating. A call made while applying returns at once; the running apply drains everything queued in the meantime.
Implementation
void apply() {
assert(
!_world.isQueryActive,
'Commands.apply() called while a query is iterating.',
);
if (_ops.isEmpty || _applying) return;
_applying = true;
_world.beginFlush();
// Counted before the command runs, and dropped in the `finally`: a
// command that throws is discarded with the ones before it, so a failed
// flush cannot replay work the world has already taken.
var consumed = 0;
var passes = 0;
try {
// Include observer-enqueued commands, with a limit on successive
// cascades rather than on the number of entities in a batch.
while (consumed < _ops.length) {
if (++passes > 64) {
throw StateError('Deferred commands did not settle after 64 passes.');
}
final end = _ops.length;
while (consumed < end) {
final index = consumed++;
final entity = _entities[index];
switch (_ops[index]) {
case _opInsert:
_world.insertNowByType(_types[index], entity, _payloads[index]);
case _opRemove:
_world.removeNowByType(_types[index], entity);
case _opDespawn:
// A second despawn queued for the same entity finds it already
// gone; skipping keeps deferred despawn idempotent (see [despawn]).
if (_world.isAlive(entity)) _world.despawnNow(entity);
case _opBundle:
(_payloads[index] as SceneDashBundle).insertInto(_world, entity);
case _opDeferred:
(_payloads[index] as void Function(World, Entity))(
_world,
entity,
);
}
}
}
} finally {
_ops.removeRange(0, consumed);
_entities.removeRange(0, consumed);
_payloads.removeRange(0, consumed);
_types.removeRange(0, consumed);
_applying = false;
_world.endFlush();
}
}