public static boolean areNodesConnecting(NetworkNode node1, NetworkNode node2) {
   for (Side side : SideBitFlag.getSides(node1.connectionSides)) {
     final ImmutableBlockLocation possibleConnectedLocation = node1.location.move(side);
     if (node2.location.equals(possibleConnectedLocation)
         && SideBitFlag.hasSide(node2.connectionSides, side.reverse())) return true;
   }
   return false;
 }
 private void updateAdjacentChunksReadyFieldOfAdjChunks(Chunk chunkInCenter) {
   Vector3i centerChunkPos = chunkInCenter.getPosition();
   for (Side side : Side.values()) {
     Vector3i adjChunkPos = side.getAdjacentPos(centerChunkPos);
     Chunk adjChunk = nearCache.get(adjChunkPos);
     if (adjChunk != null) {
       updateAdjacentChunksReadyFieldOf(adjChunk);
     }
   }
 }
 private boolean canConnectToNetworkingNode(NetworkNode networkNode) {
   for (Side connectingOnSide : SideBitFlag.getSides(networkNode.connectionSides)) {
     final ImmutableBlockLocation possibleConnectionLocation =
         networkNode.location.move(connectingOnSide);
     for (NetworkNode possibleConnectedNode : networkingNodes.get(possibleConnectionLocation)) {
       if (SideBitFlag.hasSide(possibleConnectedNode.connectionSides, connectingOnSide.reverse()))
         return true;
     }
   }
   return false;
 }
 private void listConnectedNotVisitedNetworkingNodes(
     Set<NetworkNode> visitedNodes, NetworkNode location, Collection<NetworkNode> result) {
   for (Side connectingOnSide : SideBitFlag.getSides(location.connectionSides)) {
     final ImmutableBlockLocation possibleConnectionLocation =
         location.location.move(connectingOnSide);
     for (NetworkNode possibleConnection : networkingNodes.get(possibleConnectionLocation)) {
       if (!visitedNodes.contains(possibleConnection)
           && SideBitFlag.hasSide(possibleConnection.connectionSides, connectingOnSide.reverse()))
         result.add(possibleConnection);
     }
   }
 }
 private boolean areAdjacentChunksReady(Chunk chunk) {
   Vector3i centerChunkPos = chunk.getPosition();
   for (Side side : Side.values()) {
     Vector3i adjChunkPos = side.getAdjacentPos(centerChunkPos);
     Chunk adjChunk = nearCache.get(adjChunkPos);
     boolean adjChunkReady = (adjChunk != null && adjChunk.isReady());
     if (!adjChunkReady) {
       return false;
     }
   }
   return true;
 }
  /**
   * Returns true if the side should be rendered adjacent to the second side provided.
   *
   * @param blockToCheck The block to check
   * @param currentBlock The current block
   * @return True if the side is visible for the given block types
   */
  private boolean isSideVisibleForBlockTypes(Block blockToCheck, Block currentBlock, Side side) {
    // Liquids can be transparent but there should be no visible adjacent faces
    if (currentBlock.isLiquid() && blockToCheck.isLiquid()) {
      return false;
    }

    return currentBlock.isWaving() != blockToCheck.isWaving()
        || blockToCheck.isInvisible()
        || !blockToCheck.isFullSide(side.reverse())
        || (!currentBlock.isTranslucent() && blockToCheck.isTranslucent());
  }
Exemple #7
0
 private void applyLoweredShape(Block block, BlockShape shape, Map<BlockPart, AssetUri> tileUris) {
   for (Side side : Side.values()) {
     BlockPart part = BlockPart.fromSide(side);
     BlockMeshPart meshPart =
         shape
             .getMeshPart(part)
             .rotate(Rotation.none().getQuat4f())
             .mapTexCoords(
                 atlas.getTexCoords(tileUris.get(part), true), atlas.getRelativeTileSize());
     block.setLoweredLiquidMesh(part.getSide(), meshPart);
   }
 }
    @Override
    public boolean isConnectingTo(
        Vector3i blockLocation,
        Side connectSide,
        WorldProvider worldProvider,
        BlockEntityRegistry blockEntityRegistry) {
      Vector3i neighborLocation = new Vector3i(blockLocation);
      neighborLocation.add(connectSide.getVector3i());

      EntityRef neighborEntity = blockEntityRegistry.getBlockEntityAt(neighborLocation);
      return neighborEntity != null && connectsToNeighbor(neighborEntity);
    }
  @Override
  public byte getLeafSidesInNetwork(NetworkNode networkNode) {
    if (!hasLeafNode(networkNode))
      throw new IllegalArgumentException("Cannot test nodes not in network");

    if (networkingNodes.size() == 0) {
      // Degenerated network
      for (Side connectingOnSide : SideBitFlag.getSides(networkNode.connectionSides)) {
        Vector3i possibleLocation = networkNode.location.toVector3i();
        possibleLocation.add(connectingOnSide.getVector3i());
        for (NetworkNode node : leafNodes.get(new ImmutableBlockLocation(possibleLocation))) {
          if (SideBitFlag.hasSide(node.connectionSides, connectingOnSide.reverse())) {
            return SideBitFlag.getSide(connectingOnSide);
          }
        }
      }

      return 0;
    } else {
      byte result = 0;
      for (Side connectingOnSide : SideBitFlag.getSides(networkNode.connectionSides)) {
        Vector3i possibleLocation = networkNode.location.toVector3i();
        possibleLocation.add(connectingOnSide.getVector3i());
        for (NetworkNode node : networkingNodes.get(new ImmutableBlockLocation(possibleLocation))) {
          if (SideBitFlag.hasSide(node.connectionSides, connectingOnSide.reverse())) {
            result += SideBitFlag.getSide(connectingOnSide);
          }
        }
      }

      return result;
    }
  }
Exemple #10
0
 public static <T> void deserializeBlockPartMap(
     EnumMap<BlockPart, T> target,
     JsonObject jsonObj,
     Class<T> type,
     JsonDeserializationContext context) {
   if (jsonObj.has("all")) {
     T value = context.deserialize(jsonObj.get("all"), type);
     for (BlockPart part : BlockPart.values()) {
       target.put(part, value);
     }
   }
   if (jsonObj.has("sides")) {
     T value = context.deserialize(jsonObj.get("sides"), type);
     for (Side side : Side.horizontalSides()) {
       target.put(BlockPart.fromSide(side), value);
     }
   }
   if (jsonObj.has("topBottom")) {
     T value = context.deserialize(jsonObj.get("topBottom"), type);
     target.put(BlockPart.TOP, value);
     target.put(BlockPart.BOTTOM, value);
   }
   if (jsonObj.has("top")) {
     T value = context.deserialize(jsonObj.get("top"), type);
     target.put(BlockPart.TOP, value);
   }
   if (jsonObj.has("bottom")) {
     T value = context.deserialize(jsonObj.get("bottom"), type);
     target.put(BlockPart.BOTTOM, value);
   }
   if (jsonObj.has("front")) {
     T value = context.deserialize(jsonObj.get("front"), type);
     target.put(BlockPart.FRONT, value);
   }
   if (jsonObj.has("back")) {
     T value = context.deserialize(jsonObj.get("back"), type);
     target.put(BlockPart.BACK, value);
   }
   if (jsonObj.has("left")) {
     T value = context.deserialize(jsonObj.get("left"), type);
     target.put(BlockPart.LEFT, value);
   }
   if (jsonObj.has("right")) {
     T value = context.deserialize(jsonObj.get("right"), type);
     target.put(BlockPart.RIGHT, value);
   }
   if (jsonObj.has("center")) {
     T value = context.deserialize(jsonObj.get("center"), type);
     target.put(BlockPart.CENTER, value);
   }
 }
 /**
  * @param name The name for the block group.
  * @param blocks The set of blocks that make up the group. Front, Back, Left and Right must be
  *     provided - the rest is ignored.
  */
 public AlignToSurfaceFamily(String name, EnumMap<Side, Block> blocks) {
   _name = name;
   for (Side side : Side.values()) {
     Block block = blocks.get(side);
     if (block != null) {
       _blocks.put(side, block);
       block.withBlockFamily(this);
     }
   }
   if (_blocks.containsKey(Side.TOP)) {
     _archetype = _blocks.get(Side.TOP);
   } else {
     _archetype = _blocks.get(Side.FRONT);
   }
 }
  @Override
  protected void doReload(BlockShapeData data) {
    collisionShape.clear();
    displayName = data.getDisplayName();
    for (BlockPart part : BlockPart.values()) {
      this.meshParts.put(part, data.getMeshPart(part));
    }
    for (Side side : Side.values()) {
      this.fullSide.put(side, data.isBlockingSide(side));
    }
    this.baseCollisionShape = data.getCollisionShape();
    this.baseCollisionOffset.set(data.getCollisionOffset());
    collisionShape.put(Rotation.none(), baseCollisionShape);

    yawSymmetric = data.isYawSymmetric();
    pitchSymmetric = data.isPitchSymmetric();
    rollSymmetric = data.isRollSymmetric();
  }
  @Override
  public void generateChunkMesh(ChunkView view, ChunkMesh chunkMesh, int x, int y, int z) {
    Biome selfBiome = view.getBiome(x, y, z);
    Block selfBlock = view.getBlock(x, y, z);

    // TODO: Needs review - too much hardcoded special cases and corner cases resulting from this.
    ChunkVertexFlag vertexFlag = ChunkVertexFlag.NORMAL;
    if (selfBlock.isWater()) {
      if (view.getBlock(x, y + 1, z).isWater()) {
        vertexFlag = ChunkVertexFlag.WATER;
      } else {
        vertexFlag = ChunkVertexFlag.WATER_SURFACE;
      }
    } else if (selfBlock.isLava()) {
      vertexFlag = ChunkVertexFlag.LAVA;
    } else if (selfBlock.isWaving() && selfBlock.isDoubleSided()) {
      vertexFlag = ChunkVertexFlag.WAVING;
    } else if (selfBlock.isWaving()) {
      vertexFlag = ChunkVertexFlag.WAVING_BLOCK;
    }

    // Gather adjacent blocks
    Map<Side, Block> adjacentBlocks = Maps.newEnumMap(Side.class);
    for (Side side : Side.values()) {
      Vector3i offset = side.getVector3i();
      Block blockToCheck = view.getBlock(x + offset.x, y + offset.y, z + offset.z);
      adjacentBlocks.put(side, blockToCheck);
    }

    BlockAppearance blockAppearance = selfBlock.getAppearance(adjacentBlocks);

    /*
     * Determine the render process.
     */
    ChunkMesh.RenderType renderType = ChunkMesh.RenderType.TRANSLUCENT;

    if (!selfBlock.isTranslucent()) {
      renderType = ChunkMesh.RenderType.OPAQUE;
    }
    // TODO: Review special case, or alternatively compare uris.
    if (selfBlock.isWater() || selfBlock.isIce()) {
      renderType = ChunkMesh.RenderType.WATER_AND_ICE;
    }
    if (selfBlock.isDoubleSided()) {
      renderType = ChunkMesh.RenderType.BILLBOARD;
    }

    if (blockAppearance.getPart(BlockPart.CENTER) != null) {
      Vector4f colorOffset = selfBlock.calcColorOffsetFor(BlockPart.CENTER, selfBiome);
      blockAppearance
          .getPart(BlockPart.CENTER)
          .appendTo(chunkMesh, x, y, z, colorOffset, renderType, vertexFlag);
    }

    boolean[] drawDir = new boolean[6];

    for (Side side : Side.values()) {
      drawDir[side.ordinal()] =
          blockAppearance.getPart(BlockPart.fromSide(side)) != null
              && isSideVisibleForBlockTypes(adjacentBlocks.get(side), selfBlock, side);
    }

    // If the selfBlock is lowered, some more faces may have to be drawn
    if (selfBlock.isLiquid()) {
      Block bottomBlock = adjacentBlocks.get(Side.BOTTOM);
      // Draw horizontal sides if visible from below
      for (Side side : Side.horizontalSides()) {
        Vector3i offset = side.getVector3i();
        Block adjacentBelow = view.getBlock(x + offset.x, y - 1, z + offset.z);
        Block adjacent = adjacentBlocks.get(side);

        boolean visible =
            (blockAppearance.getPart(BlockPart.fromSide(side)) != null
                && isSideVisibleForBlockTypes(adjacentBelow, selfBlock, side)
                && !isSideVisibleForBlockTypes(bottomBlock, adjacent, side.reverse()));
        drawDir[side.ordinal()] |= visible;
      }

      // Draw the top if below a non-lowered selfBlock
      // TODO: Don't need to render the top if each side and the selfBlock above each side are
      // either liquid or opaque solids.
      Block blockToCheck = adjacentBlocks.get(Side.TOP);
      drawDir[Side.TOP.ordinal()] |= !blockToCheck.isLiquid();

      if (bottomBlock.isLiquid() || bottomBlock.isInvisible()) {
        for (Side dir : Side.values()) {
          if (drawDir[dir.ordinal()]) {
            Vector4f colorOffset = selfBlock.calcColorOffsetFor(BlockPart.fromSide(dir), selfBiome);
            selfBlock
                .getLoweredLiquidMesh(dir)
                .appendTo(chunkMesh, x, y, z, colorOffset, renderType, vertexFlag);
          }
        }
        return;
      }
    }

    for (Side dir : Side.values()) {
      if (drawDir[dir.ordinal()]) {
        Vector4f colorOffset = selfBlock.calcColorOffsetFor(BlockPart.fromSide(dir), selfBiome);
        // TODO: Needs review since the new per-vertex flags introduce a lot of special scenarios -
        // probably a per-side setting?
        if (selfBlock.isGrass() && dir != Side.TOP && dir != Side.BOTTOM) {
          blockAppearance
              .getPart(BlockPart.fromSide(dir))
              .appendTo(chunkMesh, x, y, z, colorOffset, renderType, ChunkVertexFlag.COLOR_MASK);
        } else {
          // if(dir == Side.TOP) logger.info("Generating: " + (new Vector3i(x, y, z)).toString() + "
          // " + view.getChunkRegion().toString() + " " + dir.toString());
          blockAppearance
              .getPart(BlockPart.fromSide(dir))
              .appendTo(chunkMesh, x, y, z, colorOffset, renderType, vertexFlag);
        }
      }
    }
  }
Exemple #14
0
 private void setBlockFullSides(Block block, BlockShape shape, Rotation rot) {
   for (Side side : Side.values()) {
     BlockPart targetPart = BlockPart.fromSide(rot.rotate(side));
     block.setFullSide(targetPart.getSide(), shape.isBlockingSide(side));
   }
 }