mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-22 08:57:35 +01:00
SPIGOT-5422: Add support for 3-dimensional biomes
This commit is contained in:
parent
4633e6c5c7
commit
db0dafb17c
@ -5,8 +5,10 @@ import java.lang.ref.WeakReference;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import net.minecraft.server.BiomeBase;
|
import net.minecraft.server.BiomeBase;
|
||||||
|
import net.minecraft.server.BiomeStorage;
|
||||||
import net.minecraft.server.BlockPosition;
|
import net.minecraft.server.BlockPosition;
|
||||||
import net.minecraft.server.Blocks;
|
import net.minecraft.server.Blocks;
|
||||||
|
import net.minecraft.server.ChunkCoordIntPair;
|
||||||
import net.minecraft.server.ChunkSection;
|
import net.minecraft.server.ChunkSection;
|
||||||
import net.minecraft.server.DataPaletteBlock;
|
import net.minecraft.server.DataPaletteBlock;
|
||||||
import net.minecraft.server.EnumSkyBlock;
|
import net.minecraft.server.EnumSkyBlock;
|
||||||
@ -282,55 +284,22 @@ public class CraftChunk implements Chunk {
|
|||||||
hmap.a(chunk.heightMap.get(HeightMap.Type.MOTION_BLOCKING).a());
|
hmap.a(chunk.heightMap.get(HeightMap.Type.MOTION_BLOCKING).a());
|
||||||
}
|
}
|
||||||
|
|
||||||
BiomeBase[] biome = null;
|
BiomeStorage biome = null;
|
||||||
double[] biomeTemp = null;
|
|
||||||
|
|
||||||
if (includeBiome || includeBiomeTempRain) {
|
if (includeBiome|| includeBiomeTempRain) {
|
||||||
WorldChunkManager wcm = worldServer.getChunkProvider().getChunkGenerator().getWorldChunkManager();
|
biome = chunk.getBiomeIndex().b();
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World world = getWorld();
|
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) {
|
public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world, boolean includeBiome, boolean includeBiomeTempRain) {
|
||||||
BiomeBase[] biome = null;
|
BiomeStorage biome = null;
|
||||||
double[] biomeTemp = null;
|
|
||||||
|
|
||||||
if (includeBiome || includeBiomeTempRain) {
|
if (includeBiome || includeBiomeTempRain) {
|
||||||
WorldChunkManager wcm = world.getHandle().getChunkProvider().getChunkGenerator().getWorldChunkManager();
|
WorldChunkManager wcm = world.getHandle().getChunkProvider().getChunkGenerator().getWorldChunkManager();
|
||||||
|
biome = new BiomeStorage(new ChunkCoordIntPair(x, z), wcm);
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill with empty data */
|
/* Fill with empty data */
|
||||||
@ -347,23 +316,7 @@ public class CraftChunk implements Chunk {
|
|||||||
empty[i] = true;
|
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);
|
return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, skyLight, emitLight, empty, new HeightMap(null, HeightMap.Type.MOTION_BLOCKING), biome);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void validateChunkCoordinates(int x, int y, int z) {
|
static void validateChunkCoordinates(int x, int y, int z) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package org.bukkit.craftbukkit;
|
package org.bukkit.craftbukkit;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
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.DataPaletteBlock;
|
||||||
import net.minecraft.server.HeightMap;
|
import net.minecraft.server.HeightMap;
|
||||||
import net.minecraft.server.IBlockData;
|
import net.minecraft.server.IBlockData;
|
||||||
@ -26,10 +27,9 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
|||||||
private final boolean[] empty;
|
private final boolean[] empty;
|
||||||
private final HeightMap hmap; // Height map
|
private final HeightMap hmap; // Height map
|
||||||
private final long captureFulltime;
|
private final long captureFulltime;
|
||||||
private final BiomeBase[] biome;
|
private final BiomeStorage biome;
|
||||||
private final double[] biomeTemp;
|
|
||||||
|
|
||||||
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.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.worldname = wname;
|
this.worldname = wname;
|
||||||
@ -40,7 +40,6 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
|||||||
this.empty = sectionEmpty;
|
this.empty = sectionEmpty;
|
||||||
this.hmap = hmap;
|
this.hmap = hmap;
|
||||||
this.biome = biome;
|
this.biome = biome;
|
||||||
this.biomeTemp = biomeTemp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -119,18 +118,28 @@ public class CraftChunkSnapshot implements ChunkSnapshot {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Biome getBiome(int x, int z) {
|
public final Biome getBiome(int x, int z) {
|
||||||
Preconditions.checkState(biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
|
return getBiome(x, 0, z);
|
||||||
CraftChunk.validateChunkCoordinates(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
|
@Override
|
||||||
public final double getRawBiomeTemperature(int x, int z) {
|
public final double getRawBiomeTemperature(int x, int z) {
|
||||||
Preconditions.checkState(biomeTemp != null, "ChunkSnapshot created without biome temperatures. Please call getSnapshot with includeBiomeTempRain=true");
|
return getRawBiomeTemperature(x, 0, z);
|
||||||
CraftChunk.validateChunkCoordinates(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
|
@Override
|
||||||
|
@ -894,17 +894,30 @@ public class CraftWorld implements World {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int z) {
|
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
|
@Override
|
||||||
public void setBiome(int x, int z, Biome bio) {
|
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);
|
BiomeBase bb = CraftBlock.biomeToBiomeBase(bio);
|
||||||
if (this.world.isLoaded(new BlockPosition(x, 0, z))) {
|
BlockPosition pos = new BlockPosition(x, 0, z);
|
||||||
net.minecraft.server.Chunk chunk = this.world.getChunkAtWorldCoords(new BlockPosition(x, 0, z));
|
if (this.world.isLoaded(pos)) {
|
||||||
|
net.minecraft.server.Chunk chunk = this.world.getChunkAtWorldCoords(pos);
|
||||||
|
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
chunk.getBiomeIndex().setBiome(x, 0, z, bb);
|
chunk.getBiomeIndex().setBiome(x, y, z, bb);
|
||||||
|
|
||||||
chunk.markDirty(); // SPIGOT-2890
|
chunk.markDirty(); // SPIGOT-2890
|
||||||
}
|
}
|
||||||
@ -913,12 +926,23 @@ public class CraftWorld implements World {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTemperature(int x, int z) {
|
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
|
@Override
|
||||||
public double getHumidity(int x, int z) {
|
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
|
@Override
|
||||||
|
@ -473,12 +473,12 @@ public class CraftBlock implements Block {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome() {
|
public Biome getBiome() {
|
||||||
return getWorld().getBiome(getX(), getZ());
|
return getWorld().getBiome(getX(), getY(), getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBiome(Biome bio) {
|
public void setBiome(Biome bio) {
|
||||||
getWorld().setBiome(getX(), getZ(), bio);
|
getWorld().setBiome(getX(), getY(), getZ(), bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Biome biomeBaseToBiome(BiomeBase base) {
|
public static Biome biomeBaseToBiome(BiomeBase base) {
|
||||||
@ -504,7 +504,7 @@ public class CraftBlock implements Block {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getHumidity() {
|
public double getHumidity() {
|
||||||
return getWorld().getHumidity(getX(), getZ());
|
return getWorld().getHumidity(getX(), getY(), getZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,16 +45,33 @@ public class CustomChunkGenerator extends InternalChunkGenerator<GeneratorSettin
|
|||||||
private final MobSpawnerCat mobSpawnerCat = new MobSpawnerCat();
|
private final MobSpawnerCat mobSpawnerCat = new MobSpawnerCat();
|
||||||
private final VillageSiege villageSiege = new VillageSiege();
|
private final VillageSiege villageSiege = new VillageSiege();
|
||||||
|
|
||||||
private static class CustomBiomeGrid implements BiomeGrid {
|
private class CustomBiomeGrid implements BiomeGrid {
|
||||||
BiomeStorage biome;
|
|
||||||
|
private final BiomeStorage biome;
|
||||||
|
|
||||||
|
public CustomBiomeGrid(BiomeStorage biome) {
|
||||||
|
this.biome = biome;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome getBiome(int x, int z) {
|
public Biome getBiome(int x, int z) {
|
||||||
return CraftBlock.biomeBaseToBiome(biome.getBiome(x, 0, z));
|
return getBiome(x, 0, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBiome(int x, int z, Biome bio) {
|
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));
|
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);
|
random.setSeed((long) x * 341873128712L + (long) z * 132897987541L);
|
||||||
|
|
||||||
// Get default biome data for chunk
|
// Get default biome data for chunk
|
||||||
CustomBiomeGrid biomegrid = new CustomBiomeGrid();
|
CustomBiomeGrid biomegrid = new CustomBiomeGrid(new BiomeStorage(ichunkaccess.getPos(), this.getWorldChunkManager()));
|
||||||
biomegrid.biome = new BiomeStorage(ichunkaccess.getPos(), this.getWorldChunkManager());
|
|
||||||
|
|
||||||
ChunkData data;
|
ChunkData data;
|
||||||
if (generator.isParallelCapable()) {
|
if (generator.isParallelCapable()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user