@Override
  public CharacterStateEvent step(
      CharacterStateEvent initial, CharacterMoveInputEvent input, EntityRef entity) {
    CharacterMovementComponent characterMovementComponent =
        entity.getComponent(CharacterMovementComponent.class);
    CharacterStateEvent result = new CharacterStateEvent(initial);
    result.setSequenceNumber(input.getSequenceNumber());
    if (worldProvider.isBlockRelevant(initial.getPosition())) {
      updatePosition(characterMovementComponent, result, input, entity);

      if (input.isFirstRun()) {
        checkBlockEntry(
            entity,
            new Vector3i(initial.getPosition(), 0.5f),
            new Vector3i(result.getPosition(), 0.5f),
            characterMovementComponent.height);
      }

      if (result.getMode() != MovementMode.GHOSTING && result.getMode() != MovementMode.NONE) {
        checkMode(characterMovementComponent, result, initial, entity, input.isFirstRun());
      }
    }
    result.setTime(initial.getTime() + input.getDeltaMs());
    updateRotation(characterMovementComponent, result, input);
    result.setPitch(input.getPitch());
    result.setYaw(input.getYaw());
    input.runComplete();
    return result;
  }