Remove WorldChunk because we just live better without that concept

This commit is contained in:
Blue (Lukas Rieger) 2020-01-05 19:45:44 +01:00
parent bfdf7fa7ce
commit c1bcd4733d
15 changed files with 64 additions and 303 deletions

View File

@ -67,6 +67,8 @@ public BlockIdConfig(ConfigurationNode node, ConfigurationLoader<? extends Confi
BlockIDMeta idmeta = new BlockIDMeta(blockId, blockMeta);
BlockState state = BlockState.fromString(value);
if (blockId == 0) state = BlockState.AIR; //use the static field to increase render speed (== comparison)
mappings.put(idmeta, state);
} catch (NumberFormatException ex) {
Logger.global.logWarning("Loading BlockIdConfig: Failed to parse blockid:meta from key '" + key + "'");

View File

@ -111,7 +111,7 @@ private BlockProperties mapNoCache(BlockState bs){
}
}
BlockProperties generated = BlockProperties.DEFAULT;
BlockProperties generated = BlockProperties.SOLID;
if (resourcePack != null) {
try {

View File

@ -121,6 +121,8 @@ public Biome getBiome(Vector3i pos) {
}
private class Section {
private static final String AIR_ID = "minecraft:air";
private int sectionY;
private byte[] blockLight;
private byte[] skyLight;
@ -143,7 +145,12 @@ public Section(CompoundTag sectionData) {
for (int i = 0; i < this.palette.length; i++) {
CompoundTag stateTag = paletteTag.get(i);
String id = stateTag.getString("Name");
String id = stateTag.getString("Name"); //shortcut to save time and memory
if (id.equals(AIR_ID)) {
palette[i] = BlockState.AIR;
continue;
}
Map<String, String> properties = new HashMap<>();
if (stateTag.containsKey("Properties")) {

View File

@ -63,7 +63,6 @@
import de.bluecolored.bluemap.core.mca.mapping.BiomeMapper;
import de.bluecolored.bluemap.core.mca.mapping.BlockIdMapper;
import de.bluecolored.bluemap.core.mca.mapping.BlockPropertiesMapper;
import de.bluecolored.bluemap.core.util.AABB;
import de.bluecolored.bluemap.core.world.Biome;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockProperties;
@ -71,7 +70,6 @@
import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException;
import de.bluecolored.bluemap.core.world.LightData;
import de.bluecolored.bluemap.core.world.World;
import de.bluecolored.bluemap.core.world.WorldChunk;
import net.querz.nbt.CompoundTag;
import net.querz.nbt.NBTUtil;
import net.querz.nbt.Tag;
@ -100,7 +98,6 @@ public class MCAWorld implements World {
private final UUID uuid;
private final Path worldFolder;
private String name;
private AABB boundaries;
private int seaLevel;
private Vector3i spawnPoint;
@ -122,7 +119,6 @@ private MCAWorld(
this.uuid = uuid;
this.worldFolder = worldFolder;
this.name = name;
this.boundaries = new AABB(new Vector3i(-10000000, 0, -10000000), new Vector3i(10000000, worldHeight, 10000000));
this.seaLevel = seaLevel;
this.spawnPoint = spawnPoint;
@ -145,6 +141,14 @@ public BlockState getBlockState(Vector3i pos) {
@Override
public Block getBlock(Vector3i pos) throws ChunkNotGeneratedException {
if (pos.getY() < getMinY()) {
return new MCABlock(this, BlockState.AIR, LightData.ZERO, Biome.DEFAULT, BlockProperties.SOLID, pos);
}
if (pos.getY() > getMaxY()) {
return new MCABlock(this, BlockState.AIR, LightData.FULL, Biome.DEFAULT, BlockProperties.TRANSPARENT, pos);
}
try {
Vector2i chunkPos = blockToChunk(pos);
@ -172,16 +176,6 @@ private BlockState getExtendedBlockState(Chunk chunk, Vector3i pos) throws Chunk
return blockState;
}
@Override
public AABB getBoundaries() {
return boundaries;
}
@Override
public WorldChunk getWorldChunk(AABB boundaries) {
return new MCAWorldChunk(this, boundaries);
}
public Chunk getChunk(Vector2i chunkPos) throws IOException, ChunkNotGeneratedException {
try {
Chunk chunk = CHUNK_CACHE.get(new WorldChunkHash(this, chunkPos), () -> this.loadChunk(chunkPos));

View File

@ -1,85 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.mca;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.util.AABB;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException;
import de.bluecolored.bluemap.core.world.World;
import de.bluecolored.bluemap.core.world.WorldChunk;
public class MCAWorldChunk implements WorldChunk {
private MCAWorld world;
private AABB boundaries, extendedBounds;
public MCAWorldChunk(MCAWorld world, AABB boundaries) {
this.world = world;
this.boundaries = boundaries;
this.extendedBounds = boundaries.expand(2, 2, 2);
}
@Override
public World getWorld() {
return world;
}
@Override
public Block getBlock(Vector3i pos) throws ChunkNotGeneratedException {
return world.getBlock(pos);
}
@Override
public AABB getBoundaries() {
return boundaries;
}
@Override
public WorldChunk getWorldChunk(AABB boundaries) {
return new MCAWorldChunk(world, boundaries);
}
@Override
public boolean isGenerated() {
//check one more block in every direction to make sure that extended block states can be generated!
Vector2i minChunk = MCAWorld.blockToChunk(extendedBounds.getMin().toInt());
Vector2i maxChunk = MCAWorld.blockToChunk(extendedBounds.getMax().toInt());
for (int x = minChunk.getX(); x <= maxChunk.getX(); x++) {
for (int z = minChunk.getY(); z <= maxChunk.getY(); z++) {
if (!world.isChunkGenerated(new Vector2i(x, z))) {
return false;
}
}
}
return true;
}
}

View File

@ -29,15 +29,12 @@
import java.util.UUID;
import com.flowpowered.math.vector.Vector2i;
import com.flowpowered.math.vector.Vector3d;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.util.AABB;
import de.bluecolored.bluemap.core.world.Biome;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockState;
import de.bluecolored.bluemap.core.world.World;
import de.bluecolored.bluemap.core.world.WorldChunk;
public class EmptyBlockContext implements ExtendedBlockContext {
@ -109,41 +106,11 @@ public Biome getBiome() {
private static class EmptyWorld implements World {
private AABB bounds;
public EmptyWorld() {
this.bounds = new AABB(Vector3d.from(Double.POSITIVE_INFINITY), Vector3d.from(Double.NEGATIVE_INFINITY));
}
public EmptyWorld(AABB bounds){
this.bounds = bounds;
}
@Override
public World getWorld() {
return this;
}
@Override
public Block getBlock(Vector3i pos) {
return new AirBlock();
}
@Override
public AABB getBoundaries() {
return bounds;
}
@Override
public WorldChunk getWorldChunk(AABB boundaries) {
return new EmptyWorld(boundaries);
}
@Override
public boolean isGenerated() {
return false;
}
@Override
public String getName() {
return "-empty-";

View File

@ -27,17 +27,17 @@
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.WorldChunk;
import de.bluecolored.bluemap.core.world.World;
public class SlicedWorldChunkBlockContext extends WorldChunkBlockContext {
public class SlicedWorldBlockContext extends WorldBlockContext {
private int sliceY;
/**
* Same as a {@link WorldChunkBlockContext} but if the requested Block is above the slice-value it will return air.
* Same as a {@link WorldBlockContext} but if the requested Block is above the slice-value it will return air.
*/
public SlicedWorldChunkBlockContext(WorldChunk worldChunk, Vector3i blockPos, int sliceY) {
super(worldChunk, blockPos);
public SlicedWorldBlockContext(World world, Vector3i blockPos, int sliceY) {
super(world, blockPos);
this.sliceY = sliceY;
}

View File

@ -28,12 +28,12 @@
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException;
import de.bluecolored.bluemap.core.world.WorldChunk;
import de.bluecolored.bluemap.core.world.World;
public class WorldChunkBlockContext implements ExtendedBlockContext {
public class WorldBlockContext implements ExtendedBlockContext {
private Vector3i blockPos;
private WorldChunk chunk;
private World world;
/**
* A BlockContext backed by a WorldChunk.
@ -41,9 +41,9 @@ public class WorldChunkBlockContext implements ExtendedBlockContext {
* This Context assumes that the world-chunk is generated around that block-position.
* If the given world chunk is not generated, using this context will result in a RuntimeException!
*/
public WorldChunkBlockContext(WorldChunk worldChunk, Vector3i blockPos) {
public WorldBlockContext(World world, Vector3i blockPos) {
this.blockPos = blockPos;
this.chunk = worldChunk;
this.world = world;
}
@Override
@ -64,15 +64,10 @@ public Block getRelativeBlock(Vector3i direction) {
}
protected Block getBlock(Vector3i position) {
if (!chunk.containsBlock(position)) {
return EmptyBlockContext.AIR_BLOCK;
}
try {
return chunk.getBlock(position);
} catch (ChunkNotGeneratedException e) {
//we assume the chunk being generated
throw new RuntimeException(e);
return world.getBlock(position);
} catch (ChunkNotGeneratedException ex) {
return EmptyBlockContext.AIR_BLOCK;
}
}

View File

@ -115,12 +115,12 @@ private void save(HiresModel model, String modelJson){
public AABB getTileRegion(WorldTile tile) {
Vector3i min = new Vector3i(
tile.getTile().getX() * tileSize.getX() + gridOrigin.getX(),
tile.getWorld().getBoundaries().getMin().getFloorY(),
0,
tile.getTile().getY() * tileSize.getY() + gridOrigin.getY()
);
Vector3i max = min.add(
tileSize.getX() - 1,
tile.getWorld().getBoundaries().getMax().getFloorY(),
255,
tileSize.getY() - 1
);
return new AABB(min, max);

View File

@ -32,7 +32,7 @@
import de.bluecolored.bluemap.core.render.RenderSettings;
import de.bluecolored.bluemap.core.render.WorldTile;
import de.bluecolored.bluemap.core.render.context.ExtendedBlockContext;
import de.bluecolored.bluemap.core.render.context.SlicedWorldChunkBlockContext;
import de.bluecolored.bluemap.core.render.context.SlicedWorldBlockContext;
import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModel;
import de.bluecolored.bluemap.core.render.hires.blockmodel.BlockStateModelFactory;
import de.bluecolored.bluemap.core.resourcepack.NoSuchResourceException;
@ -42,7 +42,7 @@
import de.bluecolored.bluemap.core.world.Block;
import de.bluecolored.bluemap.core.world.BlockState;
import de.bluecolored.bluemap.core.world.ChunkNotGeneratedException;
import de.bluecolored.bluemap.core.world.WorldChunk;
import de.bluecolored.bluemap.core.world.World;
public class HiresModelRenderer {
@ -63,9 +63,7 @@ public HiresModel render(WorldTile tile, AABB region, RenderSettings renderSetti
min = new Vector3i(min.getX(), Math.max(min.getY(), renderSettings.getMinY()), min.getZ());
max = new Vector3i(max.getX(), Math.min(max.getY(), Math.min(renderSettings.getMaxY(), renderSettings.getSliceY())), max.getZ());
WorldChunk chunk = tile.getWorld().getWorldChunk(region.expand(4, 0, 4));
if (!chunk.isGenerated()) throw new ChunkNotGeneratedException();
World world = tile.getWorld();
HiresModel model = new HiresModel(tile.getWorld().getUUID(), tile.getTile(), min, max);
@ -76,12 +74,12 @@ public HiresModel render(WorldTile tile, AABB region, RenderSettings renderSetti
Vector4f color = Vector4f.ZERO;
for (int y = min.getY(); y <= max.getY(); y++){
Block block = chunk.getBlock(x, y, z);
Block block = world.getBlock(x, y, z);
if (block.getBlock().getId().equals("air")) continue;
maxHeight = y;
if (!block.getBlock().equals(BlockState.AIR)) maxHeight = y;
ExtendedBlockContext context = new SlicedWorldChunkBlockContext(chunk, new Vector3i(x, y, z), renderSettings.getSliceY());
ExtendedBlockContext context = new SlicedWorldBlockContext(world, new Vector3i(x, y, z), renderSettings.getSliceY());
BlockStateModel blockModel;
try {

View File

@ -26,7 +26,8 @@
public class BlockProperties {
public static final BlockProperties DEFAULT = new BlockProperties(true, true, false);
public static final BlockProperties SOLID = new BlockProperties(true, true, false);
public static final BlockProperties TRANSPARENT = new BlockProperties(false, false, false);
private final boolean culling, occluding, flammable;

View File

@ -136,6 +136,8 @@ public BlockState with(String property, String value) {
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof BlockState)) return false;
BlockState b = (BlockState) obj;
if (!Objects.equals(getFullId(), b.getFullId())) return false;

View File

@ -1,43 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.world;
public class ChunkNotGeneratedException extends Exception {
private static final long serialVersionUID = 0L;
public ChunkNotGeneratedException() {}
public ChunkNotGeneratedException(Throwable e) {
super(e);
}
public ChunkNotGeneratedException(String message){
super(message);
}
public ChunkNotGeneratedException(String message, Throwable e) {
super(message, e);
}
}

View File

@ -35,7 +35,7 @@
* <br>
* <i>The implementation of this class has to be thread-save!</i><br>
*/
public interface World extends WorldChunk {
public interface World {
String getName();
@ -45,20 +45,28 @@ public interface World extends WorldChunk {
Vector3i getSpawnPoint();
/**
* Returns itself
*/
@Override
default World getWorld() {
return this;
default int getMaxY() {
return 255;
}
default int getMinY() {
return 0;
}
/**
* Always returns false
* Returns the Block on the specified position.<br>
* <br>
* <i>(The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)</i><br>
*/
@Override
default boolean isGenerated() {
return false;
Block getBlock(Vector3i pos) throws ChunkNotGeneratedException;
/**
* Returns the Block on the specified position.<br>
* <br>
* <i>(The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)</i><br>
*/
default Block getBlock(int x, int y, int z) throws ChunkNotGeneratedException {
return getBlock(new Vector3i(x, y, z));
}
/**

View File

@ -1,85 +0,0 @@
/*
* This file is part of BlueMap, licensed under the MIT License (MIT).
*
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package de.bluecolored.bluemap.core.world;
import com.flowpowered.math.vector.Vector3i;
import de.bluecolored.bluemap.core.util.AABB;
/**
* Represents a chunk of a world.<br>
* <br>
* <i>The implementation of this class has to be thread-save!</i><br>
*/
public interface WorldChunk {
/**
* Returns the top-level World of this WorldChunk,
* If this WorldChunk is already a World, the method returns the same instance (<code>return this;</code>).
*/
World getWorld();
/**
* Returns the Block on the specified position.<br>
* <br>
* <i>(The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)</i><br>
*/
Block getBlock(Vector3i pos) throws ChunkNotGeneratedException;
/**
* Returns the Block on the specified position.<br>
* <br>
* <i>(The implementation should not invoke the generation of new Terrain, it should rather throw a {@link ChunkNotGeneratedException} if a not generated block is requested)</i><br>
*/
default Block getBlock(int x, int y, int z) throws ChunkNotGeneratedException {
return getBlock(new Vector3i(x, y, z));
}
/**
* Returns true if this WorldChunk contains the given position.
*/
default boolean containsBlock(Vector3i pos){
return getBoundaries().contains(pos);
}
/**
* Returns the boundaries of the WorldChunk.<br>
*/
AABB getBoundaries();
/**
* Returns a smaller part of this WorldChunk<br>
* <br>
* This is used to give the implementation an easy way to optimize thread-save access to this world-chunk.<br>
* The {@link #getBlock} method is and should be used in favour to {@link World#getBlock}.<br>
*/
WorldChunk getWorldChunk(AABB boundaries);
/**
* Returns true if the complete WorldChunk is generated and populated by Minecraft.<br>
*/
boolean isGenerated();
}