public void setToInterpolateState(
      EntityRef entity, CharacterStateEvent a, CharacterStateEvent b, long time) {
    float t = (float) (time - a.getTime()) / (b.getTime() - a.getTime());
    Vector3f newPos = BaseVector3f.lerp(a.getPosition(), b.getPosition(), t);
    Quat4f newRot = BaseQuat4f.interpolate(a.getRotation(), b.getRotation(), t);
    LocationComponent location = entity.getComponent(LocationComponent.class);
    location.setWorldPosition(newPos);
    location.setWorldRotation(newRot);
    entity.saveComponent(location);

    CharacterMovementComponent movementComponent =
        entity.getComponent(CharacterMovementComponent.class);
    movementComponent.mode = a.getMode();
    movementComponent.setVelocity(a.getVelocity());
    movementComponent.grounded = a.isGrounded();
    if (b.getFootstepDelta() < a.getFootstepDelta()) {
      movementComponent.footstepDelta =
          t * (1 + b.getFootstepDelta() - a.getFootstepDelta()) + a.getFootstepDelta();
      if (movementComponent.footstepDelta > 1) {
        movementComponent.footstepDelta -= 1;
      }
    } else {
      movementComponent.footstepDelta =
          t * (b.getFootstepDelta() - a.getFootstepDelta()) + a.getFootstepDelta();
    }
    entity.saveComponent(movementComponent);

    extrapolateCharacterComponent(entity, b);
    setPhysicsLocation(entity, newPos);
  }
  /**
   * Transforms a block entity with the change of block type. This is driven from the delta between
   * the old and new block type prefabs, but takes into account changes made to the block entity.
   *
   * @param blockEntity The entity to update
   * @param oldType The previous type of the block
   * @param type The new type of the block
   */
  private void updateBlockEntityComponents(
      EntityRef blockEntity,
      Block oldType,
      Block type,
      Set<Class<? extends Component>> retainComponents) {
    BlockComponent blockComponent = blockEntity.getComponent(BlockComponent.class);

    Optional<Prefab> oldPrefab = oldType.getPrefab();
    EntityBuilder oldEntityBuilder = entityManager.newBuilder(oldPrefab.orElse(null));
    oldEntityBuilder.addComponent(
        new BlockComponent(oldType, new Vector3i(blockComponent.getPosition())));
    BeforeEntityCreated oldEntityEvent =
        new BeforeEntityCreated(oldPrefab.orElse(null), oldEntityBuilder.iterateComponents());
    blockEntity.send(oldEntityEvent);
    for (Component comp : oldEntityEvent.getResultComponents()) {
      oldEntityBuilder.addComponent(comp);
    }

    Optional<Prefab> newPrefab = type.getPrefab();
    EntityBuilder newEntityBuilder = entityManager.newBuilder(newPrefab.orElse(null));
    newEntityBuilder.addComponent(
        new BlockComponent(type, new Vector3i(blockComponent.getPosition())));
    BeforeEntityCreated newEntityEvent =
        new BeforeEntityCreated(newPrefab.orElse(null), newEntityBuilder.iterateComponents());
    blockEntity.send(newEntityEvent);
    for (Component comp : newEntityEvent.getResultComponents()) {
      newEntityBuilder.addComponent(comp);
    }

    for (Component component : blockEntity.iterateComponents()) {
      if (!COMMON_BLOCK_COMPONENTS.contains(component.getClass())
          && !entityManager
              .getComponentLibrary()
              .getMetadata(component.getClass())
              .isRetainUnalteredOnBlockChange()
          && !newEntityBuilder.hasComponent(component.getClass())
          && !retainComponents.contains(component.getClass())) {
        blockEntity.removeComponent(component.getClass());
      }
    }

    blockComponent.setBlock(type);
    blockEntity.saveComponent(blockComponent);

    HealthComponent health = blockEntity.getComponent(HealthComponent.class);
    if (health == null && type.isDestructible()) {
      blockEntity.addComponent(
          new HealthComponent(type.getHardness(), type.getHardness() / BLOCK_REGEN_SECONDS, 1.0f));
    } else if (health != null && !type.isDestructible()) {
      blockEntity.removeComponent(HealthComponent.class);
    } else if (health != null && type.isDestructible()) {
      health.maxHealth = type.getHardness();
      health.currentHealth = Math.min(health.currentHealth, health.maxHealth);
      blockEntity.saveComponent(health);
    }

    for (Component comp : newEntityBuilder.iterateComponents()) {
      copyIntoPrefab(blockEntity, comp, retainComponents);
    }
  }
 private boolean processOutputForSetResetGate(EntityRef blockEntity) {
   SignalConsumerAdvancedStatusComponent consumerAdvancedStatusComponent =
       blockEntity.getComponent(SignalConsumerAdvancedStatusComponent.class);
   EnumSet<Side> signals = SideBitFlag.getSides(consumerAdvancedStatusComponent.sidesWithSignals);
   SignalProducerComponent producerComponent =
       blockEntity.getComponent(SignalProducerComponent.class);
   int resultSignal = producerComponent.signalStrength;
   if (signals.contains(Side.TOP) || signals.contains(Side.BOTTOM)) {
     resultSignal = 0;
   } else if (signals.size() > 0) {
     resultSignal = -1;
   }
   if (producerComponent.signalStrength != resultSignal) {
     producerComponent.signalStrength = resultSignal;
     blockEntity.saveComponent(producerComponent);
     if (resultSignal != 0) {
       if (!blockEntity.hasComponent(SignalProducerModifiedComponent.class)) {
         blockEntity.addComponent(new SignalProducerModifiedComponent());
       }
     } else if (blockEntity.hasComponent(SignalProducerModifiedComponent.class)) {
       blockEntity.removeComponent(SignalProducerModifiedComponent.class);
     }
     return true;
   }
   return false;
 }
  private EntityRef createResultItem(String itemResult) {
    String resultText = itemResult;
    int count = 1;
    int starIndex = resultText.indexOf("*");
    if (starIndex > -1) {
      count = Integer.parseInt(resultText.substring(0, starIndex));
      resultText = resultText.substring(starIndex + 1);
    }

    EntityManager entityManager = CoreRegistry.get(EntityManager.class);
    BlockManager blockManager = CoreRegistry.get(BlockManager.class);
    PrefabManager prefabManager = CoreRegistry.get(PrefabManager.class);
    Prefab prefab = prefabManager.getPrefab(resultText);

    EntityRef result;
    if (prefab != null) {
      result = entityManager.create(prefab);
      ItemComponent item = result.getComponent(ItemComponent.class);
      item.stackCount = (byte) count;
      result.saveComponent(item);
    } else {
      BlockItemFactory blockItemFactory = new BlockItemFactory(entityManager);
      BlockFamily blockFamily = blockManager.getBlockFamily(resultText);
      result = blockItemFactory.newInstance(blockFamily, count);
    }
    return result;
  }
 private void doDamage(
     EntityRef entity,
     int damageAmount,
     Prefab damageType,
     EntityRef instigator,
     EntityRef directCause) {
   HealthComponent health = entity.getComponent(HealthComponent.class);
   CharacterMovementComponent characterMovementComponent =
       entity.getComponent(CharacterMovementComponent.class);
   boolean ghost = false;
   if (characterMovementComponent != null) {
     ghost = (characterMovementComponent.mode == MovementMode.GHOSTING);
   }
   if ((health != null) && !ghost) {
     int damagedAmount = health.currentHealth - Math.max(health.currentHealth - damageAmount, 0);
     health.currentHealth -= damagedAmount;
     health.nextRegenTick =
         time.getGameTimeInMs() + TeraMath.floorToInt(health.waitBeforeRegen * 1000);
     entity.saveComponent(health);
     entity.send(new OnDamagedEvent(damageAmount, damagedAmount, damageType, instigator));
     if (health.currentHealth == 0 && health.destroyEntityOnNoHealth) {
       entity.send(new DestroyEvent(instigator, directCause, damageType));
     }
   }
 }
  @ReceiveEvent
  public void onDamaged(
      OnDamagedEvent event, EntityRef entity, CharacterSoundComponent characterSounds) {
    if (characterSounds.lastSoundTime + CharacterSoundSystem.MIN_TIME < time.getGameTimeInMs()) {

      // play the sound of damage hitting the character for everyone
      DamageSoundComponent damageSounds = event.getType().getComponent(DamageSoundComponent.class);
      if (damageSounds != null && !damageSounds.sounds.isEmpty()) {
        StaticSound sound = random.nextItem(damageSounds.sounds);
        if (sound != null) {
          entity.send(new PlaySoundEvent(sound, 1f));
        }
      }

      // play the sound of a client's character being damaged to the client
      if (!characterSounds.damageSounds.isEmpty()) {
        StaticSound sound = random.nextItem(characterSounds.damageSounds);
        if (sound != null) {
          entity.send(new PlaySoundForOwnerEvent(sound, characterSounds.damageVolume));
        }
      }

      characterSounds.lastSoundTime = time.getGameTimeInMs();
      entity.saveComponent(characterSounds);
    }
  }
 private void extrapolateLocationComponent(
     EntityRef entity, CharacterStateEvent state, Vector3f newPos) {
   LocationComponent location = entity.getComponent(LocationComponent.class);
   location.setWorldPosition(newPos);
   location.setWorldRotation(state.getRotation());
   entity.saveComponent(location);
 }
  private void cleanUpTemporaryEntity(EntityRef entity) {
    Prefab prefab = entity.getParentPrefab();

    for (Component comp : entity.iterateComponents()) {
      if (!COMMON_BLOCK_COMPONENTS.contains(comp.getClass())
          && (prefab == null || !prefab.hasComponent(comp.getClass()))) {
        entity.removeComponent(comp.getClass());
      }
    }
    entity.removeComponent(NetworkComponent.class);

    if (prefab != null) {
      for (Component comp : prefab.iterateComponents()) {
        Component currentComp = entity.getComponent(comp.getClass());
        if (currentComp == null) {
          entity.addComponent(entityManager.getComponentLibrary().copy(comp));
        } else {
          ComponentMetadata<?> metadata =
              entityManager.getComponentLibrary().getMetadata(comp.getClass());
          boolean changed = false;
          for (FieldMetadata field : metadata.getFields()) {
            Object expected = field.getValue(comp);
            if (!Objects.equal(expected, field.getValue(currentComp))) {
              field.setValue(currentComp, expected);
              changed = true;
            }
          }
          if (changed) {
            entity.saveComponent(currentComp);
          }
        }
      }
    }
    entityManager.destroyEntityWithoutEvents(entity);
  }
 private void extrapolateCharacterMovementComponent(EntityRef entity, CharacterStateEvent state) {
   CharacterMovementComponent movementComponent =
       entity.getComponent(CharacterMovementComponent.class);
   movementComponent.mode = state.getMode();
   movementComponent.setVelocity(state.getVelocity());
   movementComponent.grounded = state.isGrounded();
   entity.saveComponent(movementComponent);
 }
 private boolean startProducingSignal(EntityRef entity, int signalStrength) {
   final SignalProducerComponent producer = entity.getComponent(SignalProducerComponent.class);
   if (producer.signalStrength != signalStrength) {
     producer.signalStrength = signalStrength;
     entity.saveComponent(producer);
     entity.addComponent(new SignalProducerModifiedComponent());
     return true;
   }
   return false;
 }
 private boolean stopProducingSignal(EntityRef entity) {
   SignalProducerComponent producer = entity.getComponent(SignalProducerComponent.class);
   if (producer.signalStrength != 0) {
     producer.signalStrength = 0;
     entity.saveComponent(producer);
     entity.removeComponent(SignalProducerModifiedComponent.class);
     return true;
   }
   return false;
 }
 /**
  * Sets the state of the given entity to the state represented by the CharacterStateEvent. The
  * state of the entity is determined by its LocationComponent (location and orientation of physics
  * body), CharacterMovementComponent (velocity and various movement state variables) and
  * CharacterComponent for pitch and yaw (used for the camera).
  *
  * @param entity
  * @param state
  */
 public void setToState(EntityRef entity, CharacterStateEvent state) {
   LocationComponent location = entity.getComponent(LocationComponent.class);
   CharacterMovementComponent movementComp = entity.getComponent(CharacterMovementComponent.class);
   CharacterComponent characterComponent = entity.getComponent(CharacterComponent.class);
   if (location == null || movementComp == null || characterComponent == null) {
     return;
   }
   location.setWorldPosition(state.getPosition());
   location.setWorldRotation(state.getRotation());
   entity.saveComponent(location);
   movementComp.mode = state.getMode();
   movementComp.setVelocity(state.getVelocity());
   movementComp.grounded = state.isGrounded();
   movementComp.footstepDelta = state.getFootstepDelta();
   entity.saveComponent(movementComp);
   characterComponent.pitch = state.getPitch();
   characterComponent.yaw = state.getYaw();
   entity.saveComponent(characterComponent);
   setPhysicsLocation(entity, state.getPosition());
 }
 private void doHeal(EntityRef entity, int healAmount, EntityRef instigator) {
   HealthComponent health = entity.getComponent(HealthComponent.class);
   if (health != null) {
     int healedAmount =
         Math.min(health.currentHealth + healAmount, health.maxHealth) - health.currentHealth;
     health.currentHealth += healedAmount;
     entity.saveComponent(health);
     entity.send(new OnHealedEvent(healAmount, healedAmount, instigator));
     if (health.currentHealth == health.maxHealth) {
       entity.send(new FullHealthEvent(instigator));
     }
   }
 }
  public static void setToExtrapolateState(EntityRef entity, CharacterStateEvent state, long time) {
    float t = (time - state.getTime()) * 0.0001f;
    Vector3f newPos = new Vector3f(state.getVelocity());
    newPos.scale(t);
    newPos.add(state.getPosition());
    LocationComponent location = entity.getComponent(LocationComponent.class);
    location.setWorldPosition(newPos);
    location.setWorldRotation(state.getRotation());
    entity.saveComponent(location);

    CharacterMovementComponent movementComponent =
        entity.getComponent(CharacterMovementComponent.class);
    movementComponent.mode = state.getMode();
    movementComponent.setVelocity(state.getVelocity());
    movementComponent.grounded = state.isGrounded();
    entity.saveComponent(movementComponent);

    CharacterComponent characterComponent = entity.getComponent(CharacterComponent.class);
    characterComponent.pitch = state.pitch;
    characterComponent.yaw = state.yaw;
    entity.saveComponent(characterComponent);
    setPhysicsLocation(entity, newPos);
  }
  @ReceiveEvent(components = {BlockComponent.class, SignalTimeDelayComponent.class})
  public void configureTimeDelay(SetSignalDelayEvent event, EntityRef entity) {
    SignalTimeDelayComponent timeDelayComponent =
        entity.getComponent(SignalTimeDelayComponent.class);
    timeDelayComponent.delaySetting = Math.min(500, event.getTime());

    entity.saveComponent(timeDelayComponent);
    if (timeDelayComponent.delaySetting == 1000
        && entity.hasComponent(SignalTimeDelayModifiedComponent.class)) {
      entity.removeComponent(SignalTimeDelayModifiedComponent.class);
    } else if (!entity.hasComponent(SignalTimeDelayModifiedComponent.class)) {
      entity.addComponent(new SignalTimeDelayModifiedComponent());
    }
  }
  @Test
  public void testChangedComponentsRevertedBeforeCleanUp() {
    worldStub.setBlock(Vector3i.zero(), blockWithString);
    EntityRef entity = worldProvider.getBlockEntityAt(new Vector3i(0, 0, 0));
    StringComponent comp = entity.getComponent(StringComponent.class);
    comp.value = "Moo";
    entity.saveComponent(comp);

    LifecycleEventChecker checker =
        new LifecycleEventChecker(entityManager.getEventSystem(), StringComponent.class);

    worldProvider.update(1.0f);
    assertEquals(
        Lists.newArrayList(new EventInfo(OnChangedComponent.newInstance(), entity)),
        checker.receivedEvents);
  }
 private <T extends Component> void updateComponent(
     EntityRef blockEntity, ComponentMetadata<T> metadata, T targetComponent) {
   T currentComp = blockEntity.getComponent(metadata.getType());
   if (currentComp != null) {
     boolean changed = false;
     for (FieldMetadata<T, ?> field : metadata.getFields()) {
       Object newVal = field.getValue(targetComponent);
       if (!Objects.equal(field.getValue(currentComp), newVal)) {
         field.setValue(currentComp, newVal);
         changed = true;
       }
     }
     if (changed) {
       blockEntity.saveComponent(currentComp);
     }
   }
 }
  @ReceiveEvent
  public void onCrash(
      HorizontalCollisionEvent event,
      EntityRef entity,
      CharacterSoundComponent characterSounds,
      HealthComponent healthComponent) {
    Vector3f horizVelocity = new Vector3f(event.getVelocity());
    horizVelocity.y = 0;
    float velocity = horizVelocity.length();

    if (velocity > healthComponent.horizontalDamageSpeedThreshold) {
      if (characterSounds.lastSoundTime + CharacterSoundSystem.MIN_TIME < time.getGameTimeInMs()) {
        StaticSound sound = random.nextItem(characterSounds.landingSounds);
        if (sound != null) {
          entity.send(new PlaySoundEvent(sound, characterSounds.landingVolume));
          characterSounds.lastSoundTime = time.getGameTimeInMs();
          entity.saveComponent(characterSounds);
        }
      }
    }
  }
  @Override
  public void applyEffect(EntityRef instigator, EntityRef entity, float magnitude, long duration) {
    boolean add = false;
    WalkSpeedComponent walkSpeed = entity.getComponent(WalkSpeedComponent.class);
    if (walkSpeed == null) {
      add = true;
      walkSpeed = new WalkSpeedComponent();
    }
    walkSpeed.multiplier = magnitude;

    if (add) {
      entity.addComponent(walkSpeed);
    } else {
      entity.saveComponent(walkSpeed);
    }

    CoreRegistry.get(DelayManager.class)
        .addDelayedAction(
            entity,
            AlterationEffects.EXPIRE_TRIGGER_PREFIX + AlterationEffects.WALK_SPEED,
            duration);
  }
 private void extrapolateCharacterComponent(EntityRef entity, CharacterStateEvent state) {
   CharacterComponent characterComponent = entity.getComponent(CharacterComponent.class);
   characterComponent.pitch = state.getPitch();
   characterComponent.yaw = state.getYaw();
   entity.saveComponent(characterComponent);
 }
 private void checkHealed(EntityRef entity, HealthComponent health, int healAmount) {
   if (healAmount > 0) {
     checkHeal(entity, healAmount, entity);
     entity.saveComponent(health);
   }
 }