@Override
  public void generate(
      AxionElementGenerationCallback callback,
      Vector3f position,
      Matrix4f rotation,
      String axionParameter) {
    Vector3f workVector = new Vector3f();

    callback.setMainBlock(position, baseBlock);
    int rangeInt = (int) range;
    for (int x = -rangeInt; x <= rangeInt; x++) {
      for (int y = -rangeInt; y <= rangeInt; y++) {
        for (int z = -rangeInt; z <= Math.min(rangeInt, maxZ); z++) {
          double distanceSquare = x * x + y * y + z * z;
          if (distanceSquare < innerRangeSquare) {
            workVector.set(x, y, z);
            rotation.transformVector(workVector);
            workVector.add(position);
            callback.setAdditionalBlock(workVector, baseBlock);
          } else if (distanceSquare < rangeSquare) {
            workVector.set(x, y, z);
            rotation.transformVector(workVector);
            workVector.add(position);
            callback.setAdditionalBlock(workVector, surroundBlock);
          }
        }
      }
    }

    callback.advance(advance);
  }
  public 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());
    extrapolateLocationComponent(entity, state, newPos);

    extrapolateCharacterMovementComponent(entity, state);

    extrapolateCharacterComponent(entity, state);
    setPhysicsLocation(entity, newPos);
  }
Ejemplo n.º 3
0
  @ReceiveEvent
  public void onActivate(
      ActivateEvent event, EntityRef entity, TunnelActionComponent tunnelActionComponent) {

    Vector3f dir = new Vector3f(event.getDirection());
    dir.scale(4.0f);
    Vector3f origin = new Vector3f(event.getOrigin());
    origin.add(dir);
    Vector3i blockPos = new Vector3i();

    int particleEffects = 0;
    int blockCounter = tunnelActionComponent.maxDestroyedBlocks;
    for (int s = 0; s <= tunnelActionComponent.maxTunnelDepth; s++) {
      origin.add(dir);
      if (!worldProvider.isBlockRelevant(origin)) {
        break;
      }

      for (int i = 0; i < tunnelActionComponent.maxRaysCast; i++) {
        Vector3f direction = random.nextVector3f();
        Vector3f impulse = new Vector3f(direction);
        impulse.scale(tunnelActionComponent.explosiveForce);

        for (int j = 0; j < 3; j++) {
          Vector3f target = new Vector3f(origin);

          target.x += direction.x * j;
          target.y += direction.y * j;
          target.z += direction.z * j;

          blockPos.set((int) target.x, (int) target.y, (int) target.z);

          Block currentBlock = worldProvider.getBlock(blockPos);

          if (currentBlock.isDestructible()) {
            if (particleEffects < tunnelActionComponent.maxParticalEffects) {
              EntityBuilder builder = entityManager.newBuilder("engine:smokeExplosion");
              builder.getComponent(LocationComponent.class).setWorldPosition(target);
              builder.build();
              particleEffects++;
            }
            if (random.nextFloat() < tunnelActionComponent.thoroughness) {
              EntityRef blockEntity = blockEntityRegistry.getEntityAt(blockPos);
              blockEntity.send(
                  new DoDamageEvent(
                      tunnelActionComponent.damageAmount, tunnelActionComponent.damageType));
            }

            blockCounter--;
          }

          if (blockCounter <= 0) {
            return;
          }
        }
      }
    }
    // No blocks were destroyed, so cancel the event
    if (blockCounter == tunnelActionComponent.maxDestroyedBlocks) {
      event.consume();
    }
  }
  private boolean moveHorizontal(
      Vector3f horizMove,
      CharacterCollider collider,
      Vector3f position,
      float slopeFactor,
      float stepHeight) {
    float remainingFraction = 1.0f;
    float dist = horizMove.length();
    if (dist < physics.getEpsilon()) {
      return false;
    }
    boolean horizontalHit = false;
    Vector3f normalizedDir = Vector3fUtil.safeNormalize(horizMove, new Vector3f());

    if (collider == null) {
      // ignore collision
      normalizedDir.scale(dist);
      position.add(normalizedDir);
      return false;
    }

    Vector3f targetPos = new Vector3f(normalizedDir);
    targetPos.scale(dist + HORIZONTAL_PENETRATION_LEEWAY);
    targetPos.add(position);
    int iteration = 0;
    Vector3f lastHitNormal = new Vector3f(0, 1, 0);
    while (remainingFraction >= 0.01f && iteration++ < 10) {
      SweepCallback callback =
          collider.sweep(position, targetPos, HORIZONTAL_PENETRATION, slopeFactor);

      /* Note: this isn't quite correct (after the first iteration the closestHitFraction is only for part of the moment)
      but probably close enough */
      float actualDist =
          Math.max(
              0,
              (dist + HORIZONTAL_PENETRATION_LEEWAY) * callback.getClosestHitFraction()
                  - HORIZONTAL_PENETRATION_LEEWAY);
      if (actualDist != 0) {
        remainingFraction -= actualDist / dist;
      }
      if (callback.hasHit()) {
        if (actualDist > physics.getEpsilon()) {
          Vector3f actualMove = new Vector3f(normalizedDir);
          actualMove.scale(actualDist);
          position.add(actualMove);
        }
        dist -= actualDist;
        Vector3f newDir = new Vector3f(normalizedDir);
        newDir.scale(dist);
        float slope = callback.getHitNormalWorld().dot(new Vector3f(0, 1, 0));

        // We step up if we're hitting a big slope, or if we're grazing
        // the ground, otherwise we move up a shallow slope.
        if (slope < slopeFactor || 1 - slope < physics.getEpsilon()) {
          boolean stepping =
              checkStep(collider, position, newDir, callback, slopeFactor, stepHeight);
          if (!stepping) {
            horizontalHit = true;
            Vector3f newHorizDir = new Vector3f(newDir.x, 0, newDir.z);
            Vector3f horizNormal =
                new Vector3f(callback.getHitNormalWorld().x, 0, callback.getHitNormalWorld().z);
            if (horizNormal.lengthSquared() > physics.getEpsilon()) {
              horizNormal.normalize();
              if (lastHitNormal.dot(horizNormal) > physics.getEpsilon()) {
                break;
              }
              lastHitNormal.set(horizNormal);
              extractResidualMovement(horizNormal, newHorizDir);
            }
            newDir.set(newHorizDir);
          }
        } else {
          // Hitting a shallow slope, move up it
          Vector3f newHorizDir = new Vector3f(newDir.x, 0, newDir.z);
          extractResidualMovement(callback.getHitNormalWorld(), newDir);
          Vector3f modHorizDir = new Vector3f(newDir);
          modHorizDir.y = 0;
          newDir.scale(newHorizDir.length() / modHorizDir.length());
        }
        float sqrDist = newDir.lengthSquared();
        if (sqrDist > physics.getEpsilon()) {
          newDir.normalize();
          if (newDir.dot(normalizedDir) <= 0.0f) {
            break;
          }
        } else {
          break;
        }
        dist = (float) Math.sqrt(sqrDist);
        normalizedDir.set(newDir);
        targetPos.set(normalizedDir);
        targetPos.scale(dist + HORIZONTAL_PENETRATION_LEEWAY);
        targetPos.add(position);
      } else {
        normalizedDir.scale(dist);
        position.add(normalizedDir);
        break;
      }
    }
    return horizontalHit;
  }
  private boolean moveDown(
      float dist, float slopeFactor, CharacterCollider collider, Vector3f position) {
    if (collider == null) {
      position.y += dist;
      return false;
    }

    float remainingDist = -dist;
    Vector3f targetPos = new Vector3f(position);
    targetPos.y -= remainingDist + VERTICAL_PENETRATION_LEEWAY;
    Vector3f normalizedDir = new Vector3f(0, -1, 0);
    boolean hit = false;
    int iteration = 0;
    while (remainingDist > physics.getEpsilon() && iteration++ < 10) {
      SweepCallback callback = collider.sweep(position, targetPos, VERTICAL_PENETRATION, -1.0f);
      float actualDist =
          Math.max(
              0,
              (remainingDist + VERTICAL_PENETRATION_LEEWAY) * callback.getClosestHitFraction()
                  - VERTICAL_PENETRATION_LEEWAY);
      Vector3f expectedMove = new Vector3f(targetPos);
      expectedMove.sub(position);
      if (expectedMove.lengthSquared() > physics.getEpsilon()) {
        expectedMove.normalize();
        expectedMove.scale(actualDist);
        position.add(expectedMove);
      }
      remainingDist -= actualDist;
      if (remainingDist < physics.getEpsilon()) {
        break;
      }
      if (callback.hasHit()) {
        float originalSlope = callback.getHitNormalWorld().dot(new Vector3f(0, 1, 0));
        if (originalSlope < slopeFactor) {
          float slope = callback.calculateAverageSlope(originalSlope, CHECK_FORWARD_DIST);
          if (slope < slopeFactor) {
            remainingDist -= actualDist;
            expectedMove.set(targetPos);
            expectedMove.sub(position);
            extractResidualMovement(callback.getHitNormalWorld(), expectedMove);
            float sqrDist = expectedMove.lengthSquared();
            if (sqrDist > physics.getEpsilon()) {
              expectedMove.normalize();
              if (expectedMove.dot(normalizedDir) <= 0.0f) {
                hit = true;
                break;
              }
            } else {
              hit = true;
              break;
            }
            if (expectedMove.y > -physics.getEpsilon()) {
              hit = true;
              break;
            }
            normalizedDir.set(expectedMove);
            expectedMove.scale(-remainingDist / expectedMove.y + HORIZONTAL_PENETRATION_LEEWAY);
            targetPos.set(position);
            targetPos.add(expectedMove);
          } else {
            hit = true;
            break;
          }
        } else {
          hit = true;
          break;
        }
      } else {
        break;
      }
    }
    if (iteration >= 10) {
      hit = true;
    }
    return hit;
  }