Skip to content

Commit

Permalink
Initial 3d biomes implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Barteks2x committed Jan 1, 2023
1 parent f17a2ff commit d941df7
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ public class Chunk16Virtual extends AbstractNBTItem implements Chunk {
private static final boolean DEBUG = System.getProperty("cubicchunks.debug", "false").equalsIgnoreCase("true");
private static final Logger LOGGER = LoggerFactory.getLogger(Chunk16Virtual.class);

private int columnX;
private int columnZ;
private final int columnX;
private final int columnZ;
private final CubeMap cubes;

private int[] yMax = new int[Coords.CUBE_SIZE * Coords.CUBE_SIZE];
private final int[] yMax = new int[Coords.CUBE_SIZE * Coords.CUBE_SIZE];

private byte[] biomes = new byte[Coords.CUBE_SIZE * Coords.CUBE_SIZE];
private boolean storing3dBiomes = false;

private final List<Entity> entities = new ArrayList<>();
private final List<TileEntity> tileEntities = new ArrayList<>();
Expand Down Expand Up @@ -154,7 +155,19 @@ public CompoundTag toNBT() {

setLong("InhabitedTime", getInhabitedTime());

if (biomes != null) {
if (storing3dBiomes) {
byte[] newBiomes = biomes.clone();
for (int i = 0; i < this.yMax.length; i++) {
int biome = getOrMakeSection(yMax[i] + 1).getBiome(
Coords.blockToBiome3d(Coords.index2dToX(i)),
Coords.blockToLocalBiome3d(yMax[i] + 1),
Coords.blockToBiome3d(Coords.index2dToZ(i)));
if (biome != 255) {
newBiomes[i] = (byte) biome;
}
}
setByteArray("Biomes", newBiomes);
} else if (biomes != null) {
setByteArray("Biomes", biomes);
}

Expand Down Expand Up @@ -338,17 +351,17 @@ public int getMaxHeight() {

@Override
public boolean isBiomesSupported() {
return true;
return false; // if we say we support 2d biomes, WP won't attempt to set 3d biomes
}

@Override
public boolean isBiomesAvailable() {
return biomes != null;
return storing3dBiomes || biomes != null;
}

@Override
public boolean is3DBiomesSupported() {
return false; // NOTE: 3d biomes are non-trivial to support with how CC uses them, as 2d biomes are also required
return true;
}

/**
Expand All @@ -359,7 +372,7 @@ public boolean is3DBiomesSupported() {
*/
@Override
public boolean is3DBiomesAvailable() {
return false;
return storing3dBiomes;
}

@Override
Expand All @@ -378,6 +391,20 @@ public void setBiome(int blockX, int blockZ, int biome) {
biomes[Coords.index(blockX, blockZ)] = (byte) biome;
}

@Override
public int get3DBiome(int xSegment, int ySegment, int zSegment) {
if (!storing3dBiomes) {
return getBiome(xSegment * 4, zSegment * 4);
}
return getOrMakeSection(ySegment * 4).getBiome(xSegment, ySegment, zSegment);
}

@Override
public void set3DBiome(int xSegment, int ySegment, int zSegment, int biome) {
storing3dBiomes = true;
getOrMakeSection(ySegment * 4).setBiome(xSegment, ySegment, zSegment, biome);
}

@Override
public boolean isReadOnly() {
return readOnly;
Expand Down Expand Up @@ -476,6 +503,7 @@ public static class Cube16 extends AbstractNBTItem {
private AbstractNBTItem sectionNbtPlaceholder;

private static final long serialVersionUID = 1L;
private byte[] biomes;

{
id2material.add(Material.AIR);
Expand Down Expand Up @@ -770,6 +798,21 @@ int getY() {
return yPos;
}

public int getBiome(int xSegment, int ySegment, int zSegment) {
if (biomes == null) {
return parent.getBiome(Coords.biome3dToMinBlock(xSegment), Coords.biome3dToMinBlock(zSegment));
}
return biomes[Coords.getBiomeAddress3d(xSegment & 3, ySegment & 3, zSegment & 3)] & 0xFF;
}

public void setBiome(int xSegment, int ySegment, int zSegment, int biome) {
if (biomes == null) {
biomes = new byte[Coords.BIOMES_PER_CUBE];
Arrays.fill(biomes, (byte) -1);
}
biomes[Coords.getBiomeAddress3d(xSegment & 3, ySegment & 3, zSegment & 3)] = (byte) biome;
}

private class PlaceholderNBT extends AbstractNBTItem {
PlaceholderNBT(boolean load) {
super(Cube16.this.getSectionTag());
Expand Down Expand Up @@ -806,6 +849,30 @@ private class PlaceholderNBT extends AbstractNBTItem {

skyLight = getByteArray("SkyLight");
blockLight = getByteArray("BlockLight");
if (containsTag("Biomes3D")) {
biomes = getByteArray("Biomes3D");
} else if (containsTag("Biomes")) {
biomes = toNewBiomes(getByteArray("Biomes"));
}
}

private byte[] toNewBiomes(byte[] biomes) {
byte[] newBiomes = new byte[4 * 4 * 4];
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
// NOTE: spread the biomes from 4 2x2 segments into the 4 vertical 4x4x4 segments
// this ensures that no biome data has been lost, but some of it may get arranged weirdly
newBiomes[Coords.getBiomeAddress3d(x, y, z)] =
biomes[getOldBiomeAddress(x << 1 | (y & 1), z << 1 | ((y >> 1) & 1))];
}
}
}
return newBiomes;
}

private int getOldBiomeAddress(int biomeX, int biomeZ) {
return biomeX << 3 | biomeZ;
}

@Override
Expand Down Expand Up @@ -844,8 +911,24 @@ public CompoundTag toNBT() {

setByteArray("SkyLight", skyLight == null ? PLACEHOLDER_WRITE_SKYLIGHT : skyLight);
setByteArray("BlockLight", blockLight == null ? PLACEHOLDER_WRITE : blockLight);
if (biomes != null) {
setByteArray("Biomes3D", biomes);
setByteArray("Biomes", toOldBiomeArray(biomes));
}
return super.toNBT();
}

private byte[] toOldBiomeArray(byte[] biomes) {
byte[] old = new byte[8*8];
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
for (int z = 0; z < 4; z++) {
old[getOldBiomeAddress(x << 1 | (y & 1), z << 1 | ((y >> 1) & 1))] = biomes[Coords.getBiomeAddress3d(x, y, z)];
}
}
}
return old;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class Coords {
public static final int CUBE_SIZE = 16;
public static final int NO_HEIGHT = Integer.MIN_VALUE + 32;

public static final int BIOMES_PER_CUBE = 4 * 4 * 4;

public static int index(int x, int y, int z) {
return blockToLocal(x) | blockToLocal(z) << 4 | blockToLocal(y) << 8;
}
Expand All @@ -38,6 +40,19 @@ public static int index(int x, int z) {
return blockToLocal(x) | blockToLocal(z) << 4;
}

public static int index2dToX(int index) {
return index & 0xF;
}


public static int index2dToZ(int index) {
return (index >> 4) & 0xF;
}

public static int getBiomeAddress3d(int biomeLocalX, int biomeLocalY, int biomeLocalZ) {
return biomeLocalX | biomeLocalY << 2 | biomeLocalZ << 4;
}

public static int blockToLocal(int val) {
return val & 0xf;
}
Expand All @@ -50,10 +65,31 @@ public static int blockCeilToCube(int val) {
return -((-val) >> 4);
}


/**
* @deprecated Use {@link #blockToLocalBiome3d(int)}
*/
@Deprecated
public static int blockToBiome(int val) {
return (val & 14) >> 1;
}

public static int blockToLocalBiome3d(int val) {
return (val & 15) >> 2;
}

public static int blockToBiome3d(int val) {
return val >> 2;
}

public static int biome3dToMinBlock(int val) {
return val << 2;
}

public static int biome3dToBlock(int val, int localBlock) {
return val << 2 | localBlock;
}

public static int localToBlock(int cubeVal, int localVal) {
return cubeToMinBlock(cubeVal) + localVal;
}
Expand All @@ -67,7 +103,7 @@ public static int cubeToMaxBlock(int val) {
}

public static int cubeToCenterBlock(int cubeVal) {
return localToBlock(cubeVal, 16 / 2);
return localToBlock(cubeVal, CUBE_SIZE / 2);
}

/**
Expand All @@ -77,16 +113,16 @@ public static int cubeToCenterBlock(int cubeVal) {
* @return the minimum coordinate for population area
*/
public static int getMinCubePopulationPos(int coord) {
return localToBlock(blockToCube(coord), 16 / 2);
return localToBlock(blockToCube(coord - CUBE_SIZE / 2), CUBE_SIZE / 2);
}

/**
* Return a seed for random number generation, based on initial seed and 3 coordinates.
*
* @param seed the world seed
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return A seed value based on world seed, x, y and z coordinates
*/
public static long coordsSeedHash(long seed, int x, int y, int z) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
import static io.github.opencubicchunks.worldpainterplugin.Version.VERSION;
import static java.util.Collections.singletonList;
import static org.pepsoft.worldpainter.Constants.*;
import static org.pepsoft.worldpainter.GameType.ADVENTURE;
import static org.pepsoft.worldpainter.GameType.CREATIVE;
import static org.pepsoft.worldpainter.GameType.HARDCORE;
import static org.pepsoft.worldpainter.GameType.SURVIVAL;
import static org.pepsoft.worldpainter.Generator.AMPLIFIED;
import static org.pepsoft.worldpainter.Generator.CUSTOM;
import static org.pepsoft.worldpainter.Generator.DEFAULT;
import static org.pepsoft.worldpainter.Generator.END;
import static org.pepsoft.worldpainter.Generator.FLAT;
import static org.pepsoft.worldpainter.Generator.LARGE_BIOMES;
import static org.pepsoft.worldpainter.Generator.NETHER;
import static org.pepsoft.worldpainter.Platform.Capability.*;

import org.jnbt.ByteTag;
Expand Down Expand Up @@ -216,14 +224,14 @@ public Node getMapNode(File mapDir) {
}

static final Platform CUBICCHUNKS = new Platform(
"org.pepsoft.cubicchunks",
"Cubic Chunks (1.10.2 - 1.12.2)",
256,
8192,
Math.min(Constants.MAX_HEIGHT, Integer.MAX_VALUE / 2),
Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE,
Arrays.asList(SURVIVAL, CREATIVE),
singletonList(DEFAULT),
Arrays.asList(DIM_NORMAL, DIM_NETHER, DIM_END),
EnumSet.of(BLOCK_BASED, BIOMES, PRECALCULATED_LIGHT, SET_SPAWN_POINT, SEED, POPULATE));
"org.pepsoft.cubicchunks",
"Cubic Chunks (1.10.2 - 1.12.2)",
256,
8192,
Math.min(Constants.MAX_HEIGHT, Integer.MAX_VALUE / 2),
Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE,
Arrays.asList(SURVIVAL, CREATIVE, ADVENTURE, HARDCORE),
Arrays.asList(DEFAULT, FLAT, LARGE_BIOMES, AMPLIFIED, CUSTOM, NETHER, END),
Arrays.asList(DIM_NORMAL, DIM_NETHER, DIM_END),
EnumSet.of(BIOMES_3D, PRECALCULATED_LIGHT, SET_SPAWN_POINT, BLOCK_BASED, SEED, POPULATE));
}

0 comments on commit d941df7

Please sign in to comment.