geforkt von Mirrors/Paper
New ChunkGenerator.generate api for block ids and avoiding magic values.
Dieser Commit ist enthalten in:
Ursprung
5e85956281
Commit
880a53248e
@ -48,6 +48,7 @@ import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
|||||||
import org.bukkit.conversations.Conversable;
|
import org.bukkit.conversations.Conversable;
|
||||||
import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
|
import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
|
||||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||||
|
import org.bukkit.craftbukkit.generator.CraftChunkData;
|
||||||
import org.bukkit.craftbukkit.help.SimpleHelpMap;
|
import org.bukkit.craftbukkit.help.SimpleHelpMap;
|
||||||
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
|
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
|
||||||
import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
|
import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
|
||||||
@ -1631,6 +1632,11 @@ public final class CraftServer implements Server {
|
|||||||
return console.getIdleTimeout();
|
return console.getIdleTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChunkGenerator.ChunkData createChunkData(World world) {
|
||||||
|
return new CraftChunkData(world);
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public UnsafeValues getUnsafe() {
|
public UnsafeValues getUnsafe() {
|
||||||
|
197
src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
Normale Datei
197
src/main/java/org/bukkit/craftbukkit/generator/CraftChunkData.java
Normale Datei
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.bukkit.craftbukkit.generator;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
import org.bukkit.material.MaterialData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to be used for the block types and data in a newly generated chunk.
|
||||||
|
*/
|
||||||
|
public final class CraftChunkData implements ChunkGenerator.ChunkData {
|
||||||
|
private final int maxHeight;
|
||||||
|
private final char[][] sections;
|
||||||
|
|
||||||
|
public CraftChunkData(World world) {
|
||||||
|
this(world.getMaxHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pp for tests */ CraftChunkData(int maxHeight) {
|
||||||
|
if (maxHeight > 256) {
|
||||||
|
throw new IllegalArgumentException("World height exceeded max chunk height");
|
||||||
|
}
|
||||||
|
this.maxHeight = maxHeight;
|
||||||
|
// Minecraft hardcodes this to 16 chunk sections.
|
||||||
|
sections = new char[16][];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxHeight() {
|
||||||
|
return maxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, Material material) {
|
||||||
|
setBlock(x, y, z, material.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, MaterialData material) {
|
||||||
|
setBlock(x, y, z, material.getItemTypeId(), material.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, Material material) {
|
||||||
|
setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, MaterialData material) {
|
||||||
|
setRegion(xMin, yMin, zMin, xMax, yMax, zMax, material.getItemTypeId(), material.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Material getType(int x, int y, int z) {
|
||||||
|
return Material.getMaterial(getTypeId(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaterialData getTypeAndData(int x, int y, int z) {
|
||||||
|
return getType(x, y, z).getNewData(getData(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, int blockId) {
|
||||||
|
setRegion(xMin, yMin, zMin, xMax, yMax, zMax, blockId, (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRegion(int xMin, int yMin, int zMin, int xMax, int yMax, int zMax, int blockId, int data) {
|
||||||
|
// Clamp to sane values.
|
||||||
|
if (xMin > 0xf || yMin >= maxHeight || zMin > 0xf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (xMin < 0) {
|
||||||
|
xMin = 0;
|
||||||
|
}
|
||||||
|
if (yMin < 0) {
|
||||||
|
yMin = 0;
|
||||||
|
}
|
||||||
|
if (zMin < 0) {
|
||||||
|
zMin = 0;
|
||||||
|
}
|
||||||
|
if (xMax > 0x10) {
|
||||||
|
xMax = 0x10;
|
||||||
|
}
|
||||||
|
if (yMax > maxHeight) {
|
||||||
|
yMax = maxHeight;
|
||||||
|
}
|
||||||
|
if (zMax > 0x10) {
|
||||||
|
zMax = 0x10;
|
||||||
|
}
|
||||||
|
if (xMin >= xMax || yMin >= yMax || zMin >= zMax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char typeChar = (char) (blockId << 4 | data);
|
||||||
|
if (xMin == 0 && xMax == 0x10) {
|
||||||
|
if (zMin == 0 && zMax == 0x10) {
|
||||||
|
for (int y = yMin & 0xf0; y < yMax; y += 0x10) {
|
||||||
|
char[] section = getChunkSection(y, true);
|
||||||
|
if (y <= yMin) {
|
||||||
|
if (y + 0x10 > yMax) {
|
||||||
|
// First and last chunk section
|
||||||
|
Arrays.fill(section, (yMin & 0xf) << 8, (yMax & 0xf) << 8, typeChar);
|
||||||
|
} else {
|
||||||
|
// First chunk section
|
||||||
|
Arrays.fill(section, (yMin & 0xf) << 8, 0x1000, typeChar);
|
||||||
|
}
|
||||||
|
} else if (y + 0x10 >= yMax) {
|
||||||
|
// Last chunk section
|
||||||
|
Arrays.fill(section, 0, (yMax & 0xf) << 8, typeChar);
|
||||||
|
} else {
|
||||||
|
// Full chunk section
|
||||||
|
Arrays.fill(section, 0, 0x1000, typeChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = yMin; y < yMax; y++) {
|
||||||
|
char[] section = getChunkSection(y, true);
|
||||||
|
int offsetBase = (y & 0xf) << 8;
|
||||||
|
int min = offsetBase | (zMin << 4);
|
||||||
|
int max = offsetBase | (zMax << 4);
|
||||||
|
Arrays.fill(section, min, max, typeChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = yMin; y < yMax; y++) {
|
||||||
|
char[] section = getChunkSection(y, true);
|
||||||
|
int offsetBase = (y & 0xf) << 8;
|
||||||
|
for (int z = zMin; z < zMax; z++) {
|
||||||
|
int offset = offsetBase | z << 4;
|
||||||
|
Arrays.fill(section, offset | xMin, offset | xMax, typeChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, int blockId) {
|
||||||
|
setBlock(x, y, z, blockId, (byte) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(int x, int y, int z, int blockId, byte data) {
|
||||||
|
setBlock(x, y, z, (char) (blockId << 4 | data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTypeId(int x, int y, int z) {
|
||||||
|
if (x != (x & 0xf) || y < 0 || y >= maxHeight || z != (z & 0xf)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char[] section = getChunkSection(y, false);
|
||||||
|
if (section == null) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return section[(y & 0xf) << 8 | z << 4 | x] >> 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getData(int x, int y, int z) {
|
||||||
|
if (x != (x & 0xf) || y < 0 || y >= maxHeight || z != (z & 0xf)) {
|
||||||
|
return (byte) 0;
|
||||||
|
}
|
||||||
|
char[] section = getChunkSection(y, false);
|
||||||
|
if (section == null) {
|
||||||
|
return (byte) 0;
|
||||||
|
} else {
|
||||||
|
return (byte) (section[(y & 0xf) << 8 | z << 4 | x] & 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBlock(int x, int y, int z, char type) {
|
||||||
|
if (x != (x & 0xf) || y < 0 || y >= maxHeight || z != (z & 0xf)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char[] section = getChunkSection(y, true);
|
||||||
|
section[(y & 0xf) << 8 | z << 4 | x] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private char[] getChunkSection(int y, boolean create) {
|
||||||
|
char[] section = sections[y >> 4];
|
||||||
|
if (create && section == null) {
|
||||||
|
sections[y >> 4] = section = new char[0x1000];
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[][] getRawChunkData() {
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,36 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||||||
biomegrid.biome = new BiomeBase[256];
|
biomegrid.biome = new BiomeBase[256];
|
||||||
world.getWorldChunkManager().getBiomeBlock(biomegrid.biome, x << 4, z << 4, 16, 16);
|
world.getWorldChunkManager().getBiomeBlock(biomegrid.biome, x << 4, z << 4, 16, 16);
|
||||||
|
|
||||||
|
// Try ChunkData method (1.8+)
|
||||||
|
CraftChunkData data = (CraftChunkData) generator.generateChunkData(this.world.getWorld(), random, x, z, biomegrid);
|
||||||
|
if (data != null) {
|
||||||
|
char[][] sections = data.getRawChunkData();
|
||||||
|
chunk = new Chunk(this.world, x, z);
|
||||||
|
|
||||||
|
ChunkSection[] csect = chunk.getSections();
|
||||||
|
int scnt = Math.min(csect.length, sections.length);
|
||||||
|
|
||||||
|
// Loop through returned sections
|
||||||
|
for (int sec = 0; sec < scnt; sec++) {
|
||||||
|
if(sections[sec] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char[] section = sections[sec];
|
||||||
|
char emptyTest = 0;
|
||||||
|
for (int i = 0; i < 4096; i++) {
|
||||||
|
// Filter invalid block id & data values.
|
||||||
|
if (Block.d.a(section[i]) == null) {
|
||||||
|
section[i] = 0;
|
||||||
|
}
|
||||||
|
emptyTest |= section[i];
|
||||||
|
}
|
||||||
|
// Build chunk section
|
||||||
|
if (emptyTest != 0) {
|
||||||
|
csect[sec] = new ChunkSection(sec << 4, true, section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
// Try extended block method (1.2+)
|
// Try extended block method (1.2+)
|
||||||
short[][] xbtypes = generator.generateExtBlockSections(this.world.getWorld(), this.random, x, z, biomegrid);
|
short[][] xbtypes = generator.generateExtBlockSections(this.world.getWorld(), this.random, x, z, biomegrid);
|
||||||
if (xbtypes != null) {
|
if (xbtypes != null) {
|
||||||
@ -138,6 +168,7 @@ public class CustomChunkGenerator extends InternalChunkGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Set biome grid
|
// Set biome grid
|
||||||
byte[] biomeIndex = chunk.getBiomeIndex();
|
byte[] biomeIndex = chunk.getBiomeIndex();
|
||||||
for (int i = 0; i < biomeIndex.length; i++) {
|
for (int i = 0; i < biomeIndex.length; i++) {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren