use of org.terasology.world.block.Block in project Terasology by MovingBlocks.
the class MapWorldProvider method getBlock.
@Override
public Block getBlock(int x, int y, int z) {
Vector3i pos = new Vector3i(x, y, z);
Block block = blocks.get(pos);
if (block != null) {
return block;
}
// TODO block & biome manager
Vector3i chunkPos = ChunkMath.calcChunkPos(pos);
Chunk chunk = chunks.get(chunkPos);
if (chunk == null && worldGenerator != null) {
chunk = new ChunkImpl(chunkPos, blockManager, biomeManager);
worldGenerator.createChunk(chunk, entityBuffer);
chunks.put(chunkPos, chunk);
}
if (chunk != null) {
return chunk.getBlock(ChunkMath.calcBlockPos(pos.x, pos.y, pos.z));
}
return null;
}
use of org.terasology.world.block.Block in project Terasology by MovingBlocks.
the class BlockMeshGeneratorSingleShape method generateChunkMesh.
@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.getMeshGenerator() == null) {
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 (blockAppearance.getPart(BlockPart.fromSide(dir)) == null) {
// TODO: This would catch something like water blocks attempting to render with a "fixed" trimmedLoweredCube shape
// That shape has its top trimmed down a bit to let water sit slightly lower than land, however, underwater this shouldn't show
// Normally we would configure that shape with CENTER instead of TOP, that way the trimmed part wouldn't occlude in a stack
// But with that handling you don't get water blocks occluding tops underwater... and there's no TOP to retrieve below -> NPE
logger.debug("Cannot render side '{}' for a block - no stored block appearance for it. renderType {}, vertexFlag {}", dir, renderType, vertexFlag);
} else {
blockAppearance.getPart(BlockPart.fromSide(dir)).appendTo(chunkMesh, x, y, z, colorOffset, renderType, vertexFlag);
}
}
}
}
}
use of org.terasology.world.block.Block in project Terasology by MovingBlocks.
the class ChunkTessellator method generateMesh.
public ChunkMesh generateMesh(ChunkView chunkView, int meshHeight, int verticalOffset) {
PerformanceMonitor.startActivity("GenerateMesh");
ChunkMesh mesh = new ChunkMesh(bufferPool);
final Stopwatch watch = Stopwatch.createStarted();
for (int x = 0; x < ChunkConstants.SIZE_X; x++) {
for (int z = 0; z < ChunkConstants.SIZE_Z; z++) {
for (int y = verticalOffset; y < verticalOffset + meshHeight; y++) {
Block block = chunkView.getBlock(x, y, z);
if (block != null && block.getMeshGenerator() != null) {
block.getMeshGenerator().generateChunkMesh(chunkView, mesh, x, y, z);
}
}
}
}
watch.stop();
mesh.setTimeToGenerateBlockVertices((int) watch.elapsed(TimeUnit.MILLISECONDS));
watch.reset().start();
generateOptimizedBuffers(chunkView, mesh);
watch.stop();
mesh.setTimeToGenerateOptimizedBuffers((int) watch.elapsed(TimeUnit.MILLISECONDS));
statVertexArrayUpdateCount++;
PerformanceMonitor.endActivity();
return mesh;
}
use of org.terasology.world.block.Block in project Terasology by MovingBlocks.
the class BlockEntitySystem method defaultDropsHandling.
@ReceiveEvent(priority = EventPriority.PRIORITY_TRIVIAL)
public void defaultDropsHandling(CreateBlockDropsEvent event, EntityRef entity, ActAsBlockComponent blockComponent) {
if (blockComponent.block != null) {
if (entity.hasComponent(BlockRegionComponent.class)) {
BlockRegionComponent blockRegion = entity.getComponent(BlockRegionComponent.class);
if (blockComponent.dropBlocksInRegion) {
// loop through all the blocks in this region and drop them
for (Vector3i location : blockRegion.region) {
Block blockInWorld = worldProvider.getBlock(location);
commonDefaultDropsHandling(event, entity, location, blockInWorld.getBlockFamily().getArchetypeBlock());
}
} else {
// just drop the ActAsBlock block
Vector3i location = new Vector3i(blockRegion.region.center(), RoundingMode.HALF_UP);
commonDefaultDropsHandling(event, entity, location, blockComponent.block.getArchetypeBlock());
}
} else if (entity.hasComponent(LocationComponent.class)) {
LocationComponent locationComponent = entity.getComponent(LocationComponent.class);
Vector3i location = new Vector3i(locationComponent.getWorldPosition(), RoundingMode.HALF_UP);
commonDefaultDropsHandling(event, entity, location, blockComponent.block.getArchetypeBlock());
}
}
}
use of org.terasology.world.block.Block in project Terasology by MovingBlocks.
the class NeighbourBlockFamilyUpdateSystem method processUpdateForBlockLocation.
private void processUpdateForBlockLocation(Vector3i blockLocation) {
for (Side side : Side.values()) {
Vector3i neighborLocation = new Vector3i(blockLocation);
neighborLocation.add(side.getVector3i());
if (worldProvider.isBlockRelevant(neighborLocation)) {
Block neighborBlock = worldProvider.getBlock(neighborLocation);
final BlockFamily blockFamily = neighborBlock.getBlockFamily();
if (blockFamily instanceof UpdatesWithNeighboursFamily) {
UpdatesWithNeighboursFamily neighboursFamily = (UpdatesWithNeighboursFamily) blockFamily;
Block neighborBlockAfterUpdate = neighboursFamily.getBlockForNeighborUpdate(worldProvider, blockEntityRegistry, neighborLocation, neighborBlock);
if (neighborBlock != neighborBlockAfterUpdate) {
worldProvider.setBlock(neighborLocation, neighborBlockAfterUpdate);
}
}
}
}
}
Aggregations