SPIGOT-5422: Add support for 3-dimensional biomes

This commit is contained in:
md_5 2019-12-11 15:28:37 +11:00
parent 4633e6c5c7
commit db0dafb17c
5 changed files with 83 additions and 81 deletions

View File

@ -5,8 +5,10 @@ import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collection;
import net.minecraft.server.BiomeBase;
import net.minecraft.server.BiomeStorage;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.Blocks;
import net.minecraft.server.ChunkCoordIntPair;
import net.minecraft.server.ChunkSection;
import net.minecraft.server.DataPaletteBlock;
import net.minecraft.server.EnumSkyBlock;
@ -282,55 +284,22 @@ public class CraftChunk implements Chunk {
hmap.a(chunk.heightMap.get(HeightMap.Type.MOTION_BLOCKING).a());
}
BiomeBase[] biome = null;
double[] biomeTemp = null;
BiomeStorage biome = null;
if (includeBiome|| includeBiomeTempRain) {
WorldChunkManager wcm = worldServer.getChunkProvider().getChunkGenerator().getWorldChunkManager();
if (includeBiome) {
biome = new BiomeBase[256];
for (int i = 0; i < 256; i++) {
biome[i] = chunk.getBiomeIndex().getBiome(i & 0xF, 0, i >> 4);
}
}
if (includeBiomeTempRain) {
biomeTemp = new double[256];
float[] dat = getTemperatures(wcm, getX() << 4, getZ() << 4);
for (int i = 0; i < 256; i++) {
biomeTemp[i] = dat[i];
}
}
biome = chunk.getBiomeIndex().b();
}
World world = getWorld();
return new CraftChunkSnapshot(getX(), getZ(), world.getName(), world.getFullTime(), sectionBlockIDs, sectionSkyLights, sectionEmitLights, sectionEmpty, hmap, biome, biomeTemp);
return new CraftChunkSnapshot(getX(), getZ(), world.getName(), world.getFullTime(), sectionBlockIDs, sectionSkyLights, sectionEmitLights, sectionEmpty, hmap, biome);
}
public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world, boolean includeBiome, boolean includeBiomeTempRain) {
BiomeBase[] biome = null;
double[] biomeTemp = null;
BiomeStorage biome = null;
if (includeBiome || includeBiomeTempRain) {
WorldChunkManager wcm = world.getHandle().getChunkProvider().getChunkGenerator().getWorldChunkManager();
if (includeBiome) {
biome = new BiomeBase[256];
for (int i = 0; i < 256; i++) {
biome[i] = world.getHandle().getBiome(new BlockPosition((x << 4) + (i & 0xF), 0, (z << 4) + (i >> 4)));
}
}
if (includeBiomeTempRain) {
biomeTemp = new double[256];
float[] dat = getTemperatures(wcm, x << 4, z << 4);
for (int i = 0; i < 256; i++) {
biomeTemp[i] = dat[i];
}
}
biome = new BiomeStorage(new ChunkCoordIntPair(x, z), wcm);
}
/* Fill with empty data */
@ -347,23 +316,7 @@ public class CraftChunk implements Chunk {
empty[i] = true;
}
return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, skyLight, emitLight, empty, new HeightMap(null, HeightMap.Type.MOTION_BLOCKING), biome, biomeTemp);
}
private static float[] getTemperatures(WorldChunkManager chunkmanager, int chunkX, int chunkZ) {
float[] temps = new float[256];
for (int i = 0; i < 256; i++) {
float temp = chunkmanager.getBiome((chunkX << 4) + (i & 0xF), 0, (chunkZ << 4) + (i >> 4)).getTemperature(); // Vanilla of olde: ((int) biomes[i].temperature * 65536.0F) / 65536.0F
if (temp > 1F) {
temp = 1F;
}
temps[i] = temp;
}
return temps;
return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, skyLight, emitLight, empty, new HeightMap(null, HeightMap.Type.MOTION_BLOCKING), biome);
}
static void validateChunkCoordinates(int x, int y, int z) {

View File

@ -1,7 +1,8 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import net.minecraft.server.BiomeBase;
import net.minecraft.server.BiomeStorage;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.DataPaletteBlock;
import net.minecraft.server.HeightMap;
import net.minecraft.server.IBlockData;
@ -26,10 +27,9 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
private final boolean[] empty;
private final HeightMap hmap; // Height map
private final long captureFulltime;
private final BiomeBase[] biome;
private final double[] biomeTemp;
private final BiomeStorage biome;
CraftChunkSnapshot(int x, int z, String wname, long wtime, DataPaletteBlock<IBlockData>[] sectionBlockIDs, byte[][] sectionSkyLights, byte[][] sectionEmitLights, boolean[] sectionEmpty, HeightMap hmap, BiomeBase[] biome, double[] biomeTemp) {
CraftChunkSnapshot(int x, int z, String wname, long wtime, DataPaletteBlock<IBlockData>[] sectionBlockIDs, byte[][] sectionSkyLights, byte[][] sectionEmitLights, boolean[] sectionEmpty, HeightMap hmap, BiomeStorage biome) {
this.x = x;
this.z = z;
this.worldname = wname;
@ -40,7 +40,6 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
this.empty = sectionEmpty;
this.hmap = hmap;
this.biome = biome;
this.biomeTemp = biomeTemp;
}
@Override
@ -119,18 +118,28 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
@Override
public final Biome getBiome(int x, int z) {
Preconditions.checkState(biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
CraftChunk.validateChunkCoordinates(x, 0, z);
return getBiome(x, 0, z);
}
return CraftBlock.biomeBaseToBiome(biome[z << 4 | x]);
@Override
public final Biome getBiome(int x, int y, int z) {
Preconditions.checkState(biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
CraftChunk.validateChunkCoordinates(x, y, z);
return CraftBlock.biomeBaseToBiome(biome.getBiome(x, y, z));
}
@Override
public final double getRawBiomeTemperature(int x, int z) {
Preconditions.checkState(biomeTemp != null, "ChunkSnapshot created without biome temperatures. Please call getSnapshot with includeBiomeTempRain=true");
CraftChunk.validateChunkCoordinates(x, 0, z);
return getRawBiomeTemperature(x, 0, z);
}
return biomeTemp[z << 4 | x];
@Override
public final double getRawBiomeTemperature(int x, int y, int z) {
Preconditions.checkState(biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
CraftChunk.validateChunkCoordinates(x, y, z);
return biome.getBiome(x, y, z).getAdjustedTemperature(new BlockPosition((this.x << 4) | x, y, (this.z << 4) | z));
}
@Override

View File

@ -894,17 +894,30 @@ public class CraftWorld implements World {
@Override
public Biome getBiome(int x, int z) {
return CraftBlock.biomeBaseToBiome(this.world.getBiome(new BlockPosition(x, 0, z)));
return getBiome(x, 0, z);
}
@Override
public Biome getBiome(int x, int y, int z) {
return CraftBlock.biomeBaseToBiome(this.world.getBiome(new BlockPosition(x, y, z)));
}
@Override
public void setBiome(int x, int z, Biome bio) {
for (int y = 0; y < getMaxHeight(); y++) {
setBiome(x, y, z, bio);
}
}
@Override
public void setBiome(int x, int y, int z, Biome bio) {
BiomeBase bb = CraftBlock.biomeToBiomeBase(bio);
if (this.world.isLoaded(new BlockPosition(x, 0, z))) {
net.minecraft.server.Chunk chunk = this.world.getChunkAtWorldCoords(new BlockPosition(x, 0, z));
BlockPosition pos = new BlockPosition(x, 0, z);
if (this.world.isLoaded(pos)) {
net.minecraft.server.Chunk chunk = this.world.getChunkAtWorldCoords(pos);
if (chunk != null) {
chunk.getBiomeIndex().setBiome(x, 0, z, bb);
chunk.getBiomeIndex().setBiome(x, y, z, bb);
chunk.markDirty(); // SPIGOT-2890
}
@ -913,12 +926,23 @@ public class CraftWorld implements World {
@Override
public double getTemperature(int x, int z) {
return this.world.getBiome(new BlockPosition(x, 0, z)).getTemperature();
return getTemperature(x, 0, z);
}
@Override
public double getTemperature(int x, int y, int z) {
BlockPosition pos = new BlockPosition(x, y, z);
return this.world.getBiome(pos).getAdjustedTemperature(pos);
}
@Override
public double getHumidity(int x, int z) {
return this.world.getBiome(new BlockPosition(x, 0, z)).getHumidity();
return getHumidity(x, 0, z);
}
@Override
public double getHumidity(int x, int y, int z) {
return this.world.getBiome(new BlockPosition(x, y, z)).getHumidity();
}
@Override

View File

@ -473,12 +473,12 @@ public class CraftBlock implements Block {
@Override
public Biome getBiome() {
return getWorld().getBiome(getX(), getZ());
return getWorld().getBiome(getX(), getY(), getZ());
}
@Override
public void setBiome(Biome bio) {
getWorld().setBiome(getX(), getZ(), bio);
getWorld().setBiome(getX(), getY(), getZ(), bio);
}
public static Biome biomeBaseToBiome(BiomeBase base) {
@ -504,7 +504,7 @@ public class CraftBlock implements Block {
@Override
public double getHumidity() {
return getWorld().getHumidity(getX(), getZ());
return getWorld().getHumidity(getX(), getY(), getZ());
}
@Override

View File

@ -45,16 +45,33 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
private final MobSpawnerCat mobSpawnerCat = new MobSpawnerCat();
private final VillageSiege villageSiege = new VillageSiege();
private static class CustomBiomeGrid implements BiomeGrid {
BiomeStorage biome;
private class CustomBiomeGrid implements BiomeGrid {
private final BiomeStorage biome;
public CustomBiomeGrid(BiomeStorage biome) {
this.biome = biome;
}
@Override
public Biome getBiome(int x, int z) {
return CraftBlock.biomeBaseToBiome(biome.getBiome(x, 0, z));
return getBiome(x, 0, z);
}
@Override
public void setBiome(int x, int z, Biome bio) {
for (int y = 0; y < world.getWorld().getMaxHeight(); y++) {
setBiome(x, y, z, bio);
}
}
@Override
public Biome getBiome(int x, int y, int z) {
return CraftBlock.biomeBaseToBiome(biome.getBiome(x, 0, z));
}
@Override
public void setBiome(int x, int y, int z, Biome bio) {
biome.setBiome(x, 0, z, CraftBlock.biomeToBiomeBase(bio));
}
}
@ -75,8 +92,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
random.setSeed((long) x * 341873128712L + (long) z * 132897987541L);
// Get default biome data for chunk
CustomBiomeGrid biomegrid = new CustomBiomeGrid();
biomegrid.biome = new BiomeStorage(ichunkaccess.getPos(), this.getWorldChunkManager());
CustomBiomeGrid biomegrid = new CustomBiomeGrid(new BiomeStorage(ichunkaccess.getPos(), this.getWorldChunkManager()));
ChunkData data;
if (generator.isParallelCapable()) {