mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-02 04:56:50 +01:00
[Bleeding] Add updated interfaces for custom chunk generation. Addresses BUKKIT-874
This commit is contained in:
parent
796a9ba8fd
commit
97669f8d90
2 changed files with 144 additions and 4 deletions
|
@ -19,6 +19,20 @@ public class ChunkSection {
|
|||
this.g = new NibbleArray(this.d.length, 4);
|
||||
}
|
||||
|
||||
// CraftBukkit start
|
||||
public ChunkSection(int y, byte[] blkData, byte[] extBlkData) {
|
||||
this.a = y;
|
||||
this.d = blkData;
|
||||
if (extBlkData != null) {
|
||||
this.e = new NibbleArray(extBlkData, 4);
|
||||
}
|
||||
this.f = new NibbleArray(this.d.length, 4);
|
||||
this.h = new NibbleArray(this.d.length, 4);
|
||||
this.g = new NibbleArray(this.d.length, 4);
|
||||
this.d();
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
public int a(int i, int j, int k) {
|
||||
int l = this.d[j << 8 | k << 4 | i] & 255;
|
||||
|
||||
|
|
|
@ -5,18 +5,19 @@ import java.util.Random;
|
|||
|
||||
import net.minecraft.server.BiomeBase;
|
||||
import net.minecraft.server.Chunk;
|
||||
import net.minecraft.server.ChunkCoordIntPair;
|
||||
import net.minecraft.server.ChunkPosition;
|
||||
import net.minecraft.server.ChunkSection;
|
||||
import net.minecraft.server.EnumCreatureType;
|
||||
import net.minecraft.server.IChunkProvider;
|
||||
import net.minecraft.server.IProgressUpdate;
|
||||
import net.minecraft.server.World;
|
||||
import net.minecraft.server.WorldChunkManager;
|
||||
import net.minecraft.server.WorldGenStronghold;
|
||||
import net.minecraft.server.WorldServer;
|
||||
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
|
||||
public class CustomChunkGenerator extends InternalChunkGenerator {
|
||||
private final ChunkGenerator generator;
|
||||
|
@ -24,6 +25,18 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||
private final Random random;
|
||||
private final WorldGenStronghold strongholdGen = new WorldGenStronghold();
|
||||
|
||||
private static class CustomBiomeGrid implements BiomeGrid {
|
||||
BiomeBase[] biome;
|
||||
|
||||
public Biome getBiome(int x, int z) {
|
||||
return CraftBlock.biomeBaseToBiome(biome[(z << 4) | x]);
|
||||
}
|
||||
|
||||
public void setBiome(int x, int z, Biome bio) {
|
||||
biome[(z << 4) | x] = CraftBlock.biomeToBiomeBase(bio);
|
||||
}
|
||||
}
|
||||
|
||||
public CustomChunkGenerator(World world, long seed, ChunkGenerator generator) {
|
||||
this.world = (WorldServer) world;
|
||||
this.generator = generator;
|
||||
|
@ -37,10 +50,114 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||
|
||||
public Chunk getOrCreateChunk(int x, int z) {
|
||||
random.setSeed((long) x * 341873128712L + (long) z * 132897987541L);
|
||||
byte[] types = generator.generate(world.getWorld(), random, x, z);
|
||||
|
||||
Chunk chunk = new Chunk(world, types, x, z);
|
||||
Chunk chunk;
|
||||
|
||||
// Get default biome data for chunk
|
||||
CustomBiomeGrid biomegrid = new CustomBiomeGrid();
|
||||
biomegrid.biome = new BiomeBase[256];
|
||||
world.getWorldChunkManager().getBiomeBlock(biomegrid.biome, x << 4, z << 4, 16, 16);
|
||||
|
||||
// Try extended block method (1.2+)
|
||||
short[][] xbtypes = generator.generateExtBlockSections(this.world.getWorld(), this.random, x, z, biomegrid);
|
||||
if (xbtypes != null) {
|
||||
chunk = new Chunk(this.world, x, z);
|
||||
|
||||
ChunkSection[] csect = chunk.h();
|
||||
int scnt = Math.min(csect.length, xbtypes.length);
|
||||
|
||||
// Loop through returned sections
|
||||
for (int sec = 0; sec < scnt; sec++) {
|
||||
if (xbtypes[sec] == null) {
|
||||
continue;
|
||||
}
|
||||
byte[] secBlkID = new byte[4096]; // Allocate blk ID bytes
|
||||
byte[] secExtBlkID = (byte[]) null; // Delay getting extended ID nibbles
|
||||
short[] bdata = xbtypes[sec];
|
||||
// Loop through data, 2 blocks at a time
|
||||
for (int i = 0, j = 0; i < bdata.length; i += 2, j++) {
|
||||
short b1 = bdata[i];
|
||||
short b2 = bdata[i + 1];
|
||||
byte extb = (byte) ((b1 >> 8) | ((b2 >> 4) & 0xF0));
|
||||
|
||||
secBlkID[i] = (byte) b1;
|
||||
secBlkID[(i + 1)] = (byte) b2;
|
||||
|
||||
if (extb != 0) { // If extended block ID data
|
||||
if (secExtBlkID == null) { // Allocate if needed
|
||||
secExtBlkID = new byte[2048];
|
||||
}
|
||||
secExtBlkID[j] = extb;
|
||||
}
|
||||
}
|
||||
// Build chunk section
|
||||
csect[sec] = new ChunkSection(sec << 4, secBlkID, secExtBlkID);
|
||||
}
|
||||
}
|
||||
else { // Else check for byte-per-block section data
|
||||
byte[][] btypes = generator.generateBlockSections(this.world.getWorld(), this.random, x, z, biomegrid);
|
||||
|
||||
if (btypes != null) {
|
||||
chunk = new Chunk(this.world, x, z);
|
||||
|
||||
ChunkSection[] csect = chunk.h();
|
||||
int scnt = Math.min(csect.length, btypes.length);
|
||||
|
||||
for (int sec = 0; sec < scnt; sec++) {
|
||||
if (btypes[sec] == null) {
|
||||
continue;
|
||||
}
|
||||
csect[sec] = new ChunkSection(sec << 4, btypes[sec], null);
|
||||
}
|
||||
}
|
||||
else { // Else, fall back to pre 1.2 method
|
||||
@SuppressWarnings("deprecation")
|
||||
byte[] types = generator.generate(this.world.getWorld(), this.random, x, z);
|
||||
int ydim = types.length / 256;
|
||||
int scnt = ydim / 16;
|
||||
|
||||
chunk = new Chunk(this.world, x, z); // Create empty chunk
|
||||
|
||||
ChunkSection[] csect = chunk.h();
|
||||
|
||||
scnt = Math.min(scnt, csect.length);
|
||||
// Loop through sections
|
||||
for (int sec = 0; sec < scnt; sec++) {
|
||||
ChunkSection cs = null; // Add sections when needed
|
||||
byte[] csbytes = (byte[]) null;
|
||||
|
||||
for (int cy = 0; cy < 16; cy++) {
|
||||
int cyoff = cy | (sec << 4);
|
||||
|
||||
for (int cx = 0; cx < 16; cx++) {
|
||||
int cxyoff = (cx * ydim * 16) + cyoff;
|
||||
|
||||
for (int cz = 0; cz < 16; cz++) {
|
||||
byte blk = types[cxyoff + (cz * ydim)];
|
||||
|
||||
if (blk != 0) { // If non-empty
|
||||
if (cs == null) { // If no section yet, get one
|
||||
cs = csect[sec] = new ChunkSection(sec << 4);
|
||||
csbytes = cs.g();
|
||||
}
|
||||
csbytes[(cy << 8) | (cz << 4) | cx] = blk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If section built, finish prepping its state
|
||||
if (cs != null) {
|
||||
cs.d();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set biome grid
|
||||
byte[] biomeIndex = chunk.l();
|
||||
for (int i = 0; i < biomeIndex.length; i++) {
|
||||
biomeIndex[i] = (byte) (biomegrid.biome[i].id & 0xFF);
|
||||
}
|
||||
// Initialize lighting
|
||||
chunk.initLighting();
|
||||
|
||||
return chunk;
|
||||
|
@ -62,10 +179,19 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public byte[] generate(org.bukkit.World world, Random random, int x, int z) {
|
||||
return generator.generate(world, random, x, z);
|
||||
}
|
||||
|
||||
public byte[][] generateBlockSections(org.bukkit.World world, Random random, int x, int z, BiomeGrid biomes) {
|
||||
return generator.generateBlockSections(world, random, x, z, biomes);
|
||||
}
|
||||
|
||||
public short[][] generateExtBlockSections(org.bukkit.World world, Random random, int x, int z, BiomeGrid biomes) {
|
||||
return generator.generateExtBlockSections(world, random, x, z, biomes);
|
||||
}
|
||||
|
||||
public Chunk getChunkAt(int x, int z) {
|
||||
return getOrCreateChunk(x, z);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue