mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-09-27 06:42:42 +02:00
Add option to use ocean-floor-heightmap to improve cave-detection
This commit is contained in:
parent
9a989149fc
commit
ff100e2656
@ -337,7 +337,7 @@ private ConfigTemplate createOverworldMapTemplate(String name, Path worldFolder)
|
||||
.setVariable("sky-color", "#7dabff")
|
||||
.setVariable("ambient-light", "0.1")
|
||||
.setVariable("world-sky-light", "15")
|
||||
.setVariable("remove-caves-below-y", "55")
|
||||
.setVariable("remove-caves-below-y", "-2")
|
||||
.setConditional("max-y-comment", true)
|
||||
.setVariable("max-y", "100");
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class MapConfig implements MapSettings {
|
||||
private int worldSkyLight = 15;
|
||||
|
||||
private int removeCavesBelowY = 55;
|
||||
|
||||
private int caveDetectionOceanFloor = 10000;
|
||||
private boolean caveDetectionUsesBlockLight = false;
|
||||
|
||||
private int minX = Integer.MIN_VALUE;
|
||||
@ -100,6 +100,10 @@ public boolean isCaveDetectionUsesBlockLight() {
|
||||
return caveDetectionUsesBlockLight;
|
||||
}
|
||||
|
||||
public int getCaveDetectionOceanFloor() {
|
||||
return caveDetectionOceanFloor;
|
||||
}
|
||||
|
||||
public Vector3i getMinPos() {
|
||||
if (min == null) min = new Vector3i(minX, minY, minZ);
|
||||
return min;
|
||||
|
@ -52,6 +52,13 @@ world-sky-light: ${world-sky-light}
|
||||
# Default is 55 (slightly below water-level)
|
||||
remove-caves-below-y: ${remove-caves-below-y}
|
||||
|
||||
# This is the amount of blocks relative to the "ocean-floor" heightmap that the cave-detection will start at.
|
||||
# Everything above that (heightmap-relative) y-level will not be removed.
|
||||
# Comment or set to a very high value to disable using the ocean-floor heightmap for cave-detection.
|
||||
# Changing this value requires a re-render of the map.
|
||||
# Defaults to 10000 (disabled)
|
||||
cave-detection-ocean-floor: -5
|
||||
|
||||
# With this value set to true, BlueMap uses the block-light value instead of the sky-light value to "detect caves".
|
||||
# (See: remove-caves-below-y)
|
||||
# Changing this value requires a re-render of the map.
|
||||
|
@ -36,6 +36,11 @@ public interface RenderSettings {
|
||||
*/
|
||||
int getRemoveCavesBelowY();
|
||||
|
||||
/**
|
||||
* The y-level relative to the ocean-floor heightmap below which caves will not be rendered
|
||||
*/
|
||||
int getCaveDetectionOceanFloor();
|
||||
|
||||
/**
|
||||
* If blocklight should be used instead of sky light to detect "caves"
|
||||
*/
|
||||
|
@ -71,6 +71,7 @@ public class LiquidModelBuilder {
|
||||
private BlockModel modelResource;
|
||||
private BlockModelView blockModel;
|
||||
private Color blockColor;
|
||||
private boolean isCave;
|
||||
|
||||
public LiquidModelBuilder(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||
this.resourcePack = resourcePack;
|
||||
@ -99,16 +100,17 @@ public void build(BlockNeighborhood<?> block, BlockState blockState, Variant var
|
||||
this.blockModel = blockModel;
|
||||
this.blockColor = color;
|
||||
|
||||
this.isCave =
|
||||
this.block.getY() < renderSettings.getRemoveCavesBelowY() &&
|
||||
this.block.getY() < block.getChunk().getOceanFloorY(block.getX(), block.getZ()) + renderSettings.getCaveDetectionOceanFloor();
|
||||
|
||||
build();
|
||||
}
|
||||
|
||||
private final Color tintcolor = new Color();
|
||||
private void build() {
|
||||
// filter out blocks that are in a "cave" that should not be rendered
|
||||
if (
|
||||
this.block.getY() < renderSettings.getRemoveCavesBelowY() &&
|
||||
(renderSettings.isCaveDetectionUsesBlockLight() ? block.getBlockLightLevel() : block.getSunLightLevel()) == 0f
|
||||
) return;
|
||||
if (this.isCave && (renderSettings.isCaveDetectionUsesBlockLight() ? block.getBlockLightLevel() : block.getSunLightLevel()) == 0f) return;
|
||||
|
||||
int level = blockState.getLiquidLevel();
|
||||
if (level < 8 && !(level == 0 && isSameLiquid(block.getNeighborBlock(0, 1, 0)))){
|
||||
|
@ -73,6 +73,7 @@ public class ResourceModelBuilder {
|
||||
private BlockModelView blockModel;
|
||||
private Color blockColor;
|
||||
private float blockColorOpacity;
|
||||
private boolean isCave;
|
||||
|
||||
public ResourceModelBuilder(ResourcePack resourcePack, TextureGallery textureGallery, RenderSettings renderSettings) {
|
||||
this.resourcePack = resourcePack;
|
||||
@ -93,6 +94,10 @@ public void build(BlockNeighborhood<?> block, Variant variant, BlockModelView bl
|
||||
this.variant = variant;
|
||||
this.modelResource = variant.getModel().getResource();
|
||||
|
||||
this.isCave =
|
||||
this.block.getY() < renderSettings.getRemoveCavesBelowY() &&
|
||||
this.block.getY() < block.getChunk().getOceanFloorY(block.getX(), block.getZ()) + renderSettings.getCaveDetectionOceanFloor();
|
||||
|
||||
this.tintColor.set(0, 0, 0, -1, true);
|
||||
|
||||
// render model
|
||||
@ -193,10 +198,7 @@ private void createElementFace(Element element, Direction faceDir, VectorM3f c0,
|
||||
int blockLight = Math.max(blockLightData.getBlockLight(), facedLightData.getBlockLight());
|
||||
|
||||
// filter out faces that are in a "cave" that should not be rendered
|
||||
if (
|
||||
this.block.getY() < renderSettings.getRemoveCavesBelowY() &&
|
||||
(renderSettings.isCaveDetectionUsesBlockLight() ? blockLight : sunLight) == 0f
|
||||
) return;
|
||||
if (isCave && (renderSettings.isCaveDetectionUsesBlockLight() ? blockLight : sunLight) == 0f) return;
|
||||
|
||||
// initialize the faces
|
||||
blockModel.initialize();
|
||||
|
@ -35,13 +35,19 @@
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class ChunkAnvil113 extends MCAChunk {
|
||||
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
private long inhabitedTime;
|
||||
private Section[] sections;
|
||||
private int[] biomes;
|
||||
|
||||
private long[] oceanFloorHeights = EMPTY_LONG_ARRAY;
|
||||
private long[] worldSurfaceHeights = EMPTY_LONG_ARRAY;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil113(MCAWorld world, CompoundTag chunkTag) {
|
||||
super(world, chunkTag);
|
||||
@ -58,6 +64,12 @@ public ChunkAnvil113(MCAWorld world, CompoundTag chunkTag) {
|
||||
isGenerated = !status.equals("empty");
|
||||
}
|
||||
|
||||
if (levelData.containsKey("Heightmaps")) {
|
||||
CompoundTag heightmapsTag = levelData.getCompoundTag("Heightmaps");
|
||||
this.worldSurfaceHeights = heightmapsTag.getLongArray("WORLD_SURFACE");
|
||||
this.oceanFloorHeights = heightmapsTag.getLongArray("OCEAN_FLOOR");
|
||||
}
|
||||
|
||||
sections = new Section[32]; //32 supports a max world-height of 512 which is the max that the hightmaps of Minecraft V1.13+ can store with 9 bits, i believe?
|
||||
if (levelData.containsKey("Sections")) {
|
||||
for (CompoundTag sectionTag : ((ListTag<CompoundTag>) levelData.getListTag("Sections"))) {
|
||||
@ -127,8 +139,7 @@ public LightData getLightData(int x, int y, int z, LightData target) {
|
||||
|
||||
@Override
|
||||
public String getBiome(int x, int y, int z) {
|
||||
x = x & 0xF; // Math.floorMod(pos.getX(), 16)
|
||||
z = z & 0xF;
|
||||
x &= 0xF; z &= 0xF;
|
||||
int biomeIntIndex = z * 16 + x;
|
||||
|
||||
if (biomeIntIndex >= this.biomes.length) return Biome.DEFAULT.getFormatted();
|
||||
@ -136,7 +147,23 @@ public String getBiome(int x, int y, int z) {
|
||||
return LegacyBiomes.idFor(biomes[biomeIntIndex]);
|
||||
}
|
||||
|
||||
private class Section {
|
||||
@Override
|
||||
public int getWorldSurfaceY(int x, int z) {
|
||||
if (this.worldSurfaceHeights.length < 36) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongStream(this.worldSurfaceHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOceanFloorY(int x, int z) {
|
||||
if (this.oceanFloorHeights.length < 36) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongStream(this.oceanFloorHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
private static class Section {
|
||||
private static final String AIR_ID = "minecraft:air";
|
||||
|
||||
private int sectionY;
|
||||
|
@ -35,13 +35,19 @@
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class ChunkAnvil115 extends MCAChunk {
|
||||
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
private long inhabitedTime;
|
||||
private Section[] sections;
|
||||
private int[] biomes;
|
||||
|
||||
private long[] oceanFloorHeights = EMPTY_LONG_ARRAY;
|
||||
private long[] worldSurfaceHeights = EMPTY_LONG_ARRAY;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil115(MCAWorld world, CompoundTag chunkTag) {
|
||||
super(world, chunkTag);
|
||||
@ -58,6 +64,12 @@ public ChunkAnvil115(MCAWorld world, CompoundTag chunkTag) {
|
||||
isGenerated = !status.equals("empty");
|
||||
}
|
||||
|
||||
if (levelData.containsKey("Heightmaps")) {
|
||||
CompoundTag heightmapsTag = levelData.getCompoundTag("Heightmaps");
|
||||
this.worldSurfaceHeights = heightmapsTag.getLongArray("WORLD_SURFACE");
|
||||
this.oceanFloorHeights = heightmapsTag.getLongArray("OCEAN_FLOOR");
|
||||
}
|
||||
|
||||
sections = new Section[32]; //32 supports a max world-height of 512 which is the max that the hightmaps of Minecraft V1.13+ can store with 9 bits, i believe?
|
||||
if (levelData.containsKey("Sections")) {
|
||||
for (CompoundTag sectionTag : ((ListTag<CompoundTag>) levelData.getListTag("Sections"))) {
|
||||
@ -138,6 +150,22 @@ public String getBiome(int x, int y, int z) {
|
||||
return LegacyBiomes.idFor(biomes[biomeIntIndex]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldSurfaceY(int x, int z) {
|
||||
if (this.worldSurfaceHeights.length < 36) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongStream(this.worldSurfaceHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOceanFloorY(int x, int z) {
|
||||
if (this.oceanFloorHeights.length < 36) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongStream(this.oceanFloorHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
private static class Section {
|
||||
private static final String AIR_ID = "minecraft:air";
|
||||
|
||||
|
@ -36,7 +36,10 @@
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class ChunkAnvil116 extends MCAChunk {
|
||||
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
|
||||
@ -47,6 +50,9 @@ public class ChunkAnvil116 extends MCAChunk {
|
||||
|
||||
private int[] biomes;
|
||||
|
||||
private long[] oceanFloorHeights = EMPTY_LONG_ARRAY;
|
||||
private long[] worldSurfaceHeights = EMPTY_LONG_ARRAY;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil116(MCAWorld world, CompoundTag chunkTag) {
|
||||
super(world, chunkTag);
|
||||
@ -63,6 +69,12 @@ public ChunkAnvil116(MCAWorld world, CompoundTag chunkTag) {
|
||||
isGenerated = !status.equals("empty");
|
||||
}
|
||||
|
||||
if (levelData.containsKey("Heightmaps")) {
|
||||
CompoundTag heightmapsTag = levelData.getCompoundTag("Heightmaps");
|
||||
this.worldSurfaceHeights = heightmapsTag.getLongArray("WORLD_SURFACE");
|
||||
this.oceanFloorHeights = heightmapsTag.getLongArray("OCEAN_FLOOR");
|
||||
}
|
||||
|
||||
if (levelData.containsKey("Sections")) {
|
||||
this.sectionMin = Integer.MAX_VALUE;
|
||||
this.sectionMax = Integer.MIN_VALUE;
|
||||
@ -166,6 +178,22 @@ public int getMaxY(int x, int z) {
|
||||
return sectionMax * 16 + 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldSurfaceY(int x, int z) {
|
||||
if (this.worldSurfaceHeights.length < 37) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongArray(this.worldSurfaceHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOceanFloorY(int x, int z) {
|
||||
if (this.oceanFloorHeights.length < 37) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongArray(this.oceanFloorHeights, z * 16 + x, 9);
|
||||
}
|
||||
|
||||
private Section getSection(int y) {
|
||||
y -= sectionMin;
|
||||
if (y < 0 || y >= this.sections.length) return null;
|
||||
|
@ -35,6 +35,10 @@
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class ChunkAnvil118 extends MCAChunk {
|
||||
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||
private static final BlockState[] EMPTY_BLOCK_STATE_ARRAY = new BlockState[0];
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private boolean isGenerated;
|
||||
private boolean hasLight;
|
||||
|
||||
@ -43,6 +47,9 @@ public class ChunkAnvil118 extends MCAChunk {
|
||||
private int sectionMin, sectionMax;
|
||||
private Section[] sections;
|
||||
|
||||
private long[] oceanFloorHeights = EMPTY_LONG_ARRAY;
|
||||
private long[] worldSurfaceHeights = EMPTY_LONG_ARRAY;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ChunkAnvil118(MCAWorld world, CompoundTag chunkTag) {
|
||||
super(world, chunkTag);
|
||||
@ -57,6 +64,12 @@ public ChunkAnvil118(MCAWorld world, CompoundTag chunkTag) {
|
||||
isGenerated = !status.equals("empty");
|
||||
}
|
||||
|
||||
if (chunkTag.containsKey("Heightmaps")) {
|
||||
CompoundTag heightmapsTag = chunkTag.getCompoundTag("Heightmaps");
|
||||
this.worldSurfaceHeights = heightmapsTag.getLongArray("WORLD_SURFACE");
|
||||
this.oceanFloorHeights = heightmapsTag.getLongArray("OCEAN_FLOOR");
|
||||
}
|
||||
|
||||
if (chunkTag.containsKey("sections")) {
|
||||
this.sectionMin = Integer.MAX_VALUE;
|
||||
this.sectionMax = Integer.MIN_VALUE;
|
||||
@ -136,6 +149,22 @@ public int getMaxY(int x, int z) {
|
||||
return sectionMax * 16 + 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldSurfaceY(int x, int z) {
|
||||
if (this.worldSurfaceHeights.length < 37) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongArray(this.worldSurfaceHeights, z * 16 + x, 9) - 64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOceanFloorY(int x, int z) {
|
||||
if (this.oceanFloorHeights.length < 37) return 0;
|
||||
|
||||
x &= 0xF; z &= 0xF;
|
||||
return (int) MCAMath.getValueFromLongArray(this.oceanFloorHeights, z * 16 + x, 9) - 64;
|
||||
}
|
||||
|
||||
private Section getSection(int y) {
|
||||
y -= sectionMin;
|
||||
if (y < 0 || y >= this.sections.length) return null;
|
||||
@ -143,10 +172,6 @@ private Section getSection(int y) {
|
||||
}
|
||||
|
||||
private static class Section {
|
||||
private static final long[] EMPTY_LONG_ARRAY = new long[0];
|
||||
private static final BlockState[] EMPTY_BLOCK_STATE_ARRAY = new BlockState[0];
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private int sectionY;
|
||||
private byte[] blockLight;
|
||||
private byte[] skyLight;
|
||||
|
@ -81,6 +81,12 @@ public int getMinY(int x, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWorldSurfaceY(int x, int z) { return 0; }
|
||||
|
||||
@Override
|
||||
public int getOceanFloorY(int x, int z) { return 0; }
|
||||
|
||||
protected MCAWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
@ -42,4 +42,8 @@ public interface Chunk {
|
||||
|
||||
int getMinY(int x, int z);
|
||||
|
||||
int getWorldSurfaceY(int x, int z);
|
||||
|
||||
int getOceanFloorY(int x, int z);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user