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();
  }
}