mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-27 21:19:00 +01:00
[Bleeding] Add updated interfaces for custom chunk generation. Addresses BUKKIT-874
This commit is contained in:
parent
796a9ba8fd
commit
97669f8d90
@ -19,6 +19,20 @@ public class ChunkSection {
|
|||||||
this.g = new NibbleArray(this.d.length, 4);
|
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) {
|
public int a(int i, int j, int k) {
|
||||||
int l = this.d[j << 8 | k << 4 | i] & 255;
|
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.BiomeBase;
|
||||||
import net.minecraft.server.Chunk;
|
import net.minecraft.server.Chunk;
|
||||||
import net.minecraft.server.ChunkCoordIntPair;
|
|
||||||
import net.minecraft.server.ChunkPosition;
|
import net.minecraft.server.ChunkPosition;
|
||||||
|
import net.minecraft.server.ChunkSection;
|
||||||
import net.minecraft.server.EnumCreatureType;
|
import net.minecraft.server.EnumCreatureType;
|
||||||
import net.minecraft.server.IChunkProvider;
|
import net.minecraft.server.IChunkProvider;
|
||||||
import net.minecraft.server.IProgressUpdate;
|
import net.minecraft.server.IProgressUpdate;
|
||||||
import net.minecraft.server.World;
|
import net.minecraft.server.World;
|
||||||
import net.minecraft.server.WorldChunkManager;
|
|
||||||
import net.minecraft.server.WorldGenStronghold;
|
import net.minecraft.server.WorldGenStronghold;
|
||||||
import net.minecraft.server.WorldServer;
|
import net.minecraft.server.WorldServer;
|
||||||
|
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.generator.BlockPopulator;
|
import org.bukkit.generator.BlockPopulator;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||||
|
|
||||||
public class CustomChunkGenerator extends InternalChunkGenerator {
|
public class CustomChunkGenerator extends InternalChunkGenerator {
|
||||||
private final ChunkGenerator generator;
|
private final ChunkGenerator generator;
|
||||||
@ -24,6 +25,18 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||||||
private final Random random;
|
private final Random random;
|
||||||
private final WorldGenStronghold strongholdGen = new WorldGenStronghold();
|
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) {
|
public CustomChunkGenerator(World world, long seed, ChunkGenerator generator) {
|
||||||
this.world = (WorldServer) world;
|
this.world = (WorldServer) world;
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
@ -37,10 +50,114 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||||||
|
|
||||||
public Chunk getOrCreateChunk(int x, int z) {
|
public Chunk getOrCreateChunk(int x, int z) {
|
||||||
random.setSeed((long) x * 341873128712L + (long) z * 132897987541L);
|
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();
|
chunk.initLighting();
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
@ -62,10 +179,19 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public byte[] generate(org.bukkit.World world, Random random, int x, int z) {
|
public byte[] generate(org.bukkit.World world, Random random, int x, int z) {
|
||||||
return generator.generate(world, random, x, 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) {
|
public Chunk getChunkAt(int x, int z) {
|
||||||
return getOrCreateChunk(x, z);
|
return getOrCreateChunk(x, z);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user