use of cn.nukkit.level.format.FullChunk in project Nukkit by Nukkit.
the class LevelProviderConverter method perform.
LevelProvider perform() throws IOException {
new File(path).mkdir();
File dat = new File(provider.getPath(), "level.dat.old");
new File(provider.getPath(), "level.dat").renameTo(dat);
Utils.copyFile(dat, new File(path, "level.dat"));
LevelProvider result;
try {
if (provider instanceof LevelDB) {
try (FileInputStream stream = new FileInputStream(path + "level.dat")) {
stream.skip(8);
CompoundTag levelData = NBTIO.read(stream, ByteOrder.LITTLE_ENDIAN);
if (levelData != null) {
NBTIO.writeGZIPCompressed(new CompoundTag().putCompound("Data", levelData), new FileOutputStream(path + "level.dat"));
} else {
throw new IOException("LevelData can not be null");
}
} catch (IOException e) {
throw new LevelException("Invalid level.dat");
}
}
result = toClass.getConstructor(Level.class, String.class).newInstance(level, path);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (toClass == Anvil.class) {
if (provider instanceof McRegion) {
new File(path, "region").mkdir();
for (File file : new File(provider.getPath() + "region/").listFiles()) {
Matcher m = Pattern.compile("-?\\d+").matcher(file.getName());
int regionX, regionZ;
try {
if (m.find()) {
regionX = Integer.parseInt(m.group());
} else
continue;
if (m.find()) {
regionZ = Integer.parseInt(m.group());
} else
continue;
} catch (NumberFormatException e) {
continue;
}
RegionLoader region = new RegionLoader(provider, regionX, regionZ);
for (Integer index : region.getLocationIndexes()) {
int chunkX = index & 0x1f;
int chunkZ = index >> 5;
BaseFullChunk old = region.readChunk(chunkX, chunkZ);
if (old == null)
continue;
int x = (regionX << 5) | chunkX;
int z = (regionZ << 5) | chunkZ;
FullChunk chunk = new ChunkConverter(result).from(old).to(Chunk.class).perform();
result.saveChunk(x, z, chunk);
}
region.close();
}
}
if (provider instanceof LevelDB) {
new File(path, "region").mkdir();
for (byte[] key : ((LevelDB) provider).getTerrainKeys()) {
int x = getChunkX(key);
int z = getChunkZ(key);
BaseFullChunk old = ((LevelDB) provider).readChunk(x, z);
FullChunk chunk = new ChunkConverter(result).from(old).to(Chunk.class).perform();
result.saveChunk(x, z, chunk);
}
}
result.doGarbageCollection();
}
return result;
}
use of cn.nukkit.level.format.FullChunk in project Nukkit by Nukkit.
the class Nether method generateChunk.
@Override
public void generateChunk(int chunkX, int chunkZ) {
this.nukkitRandom.setSeed(chunkX * localSeed1 ^ chunkZ * localSeed2 ^ this.level.getSeed());
double[][][] noise = Generator.getFastNoise3D(this.noiseBase, 16, 128, 16, 4, 8, 4, chunkX * 16, 0, chunkZ * 16);
FullChunk chunk = this.level.getChunk(chunkX, chunkZ);
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
Biome biome = Biome.getBiome(Biome.HELL);
chunk.setBiomeId(x, z, Biome.HELL);
int biomecolor = biome.getColor();
chunk.setBiomeColor(x, z, (biomecolor >> 16), (biomecolor >> 8) & 0xff, (biomecolor & 0xff));
chunk.setBlockId(x, 0, z, Block.BEDROCK);
chunk.setBlockId(x, 127, z, Block.BEDROCK);
for (int y = 1; y <= bedrockDepth; y++) {
if (nukkitRandom.nextRange(1, 5) == 1) {
chunk.setBlockId(x, y, z, Block.BEDROCK);
chunk.setBlockId(x, 127 - y, z, Block.BEDROCK);
}
}
for (int y = 1; y < 127; ++y) {
double noiseValue = (Math.abs(this.emptyHeight - y) / this.emptyHeight) * this.emptyAmplitude - noise[x][z][y];
noiseValue -= 1 - this.density;
if (noiseValue > 0) {
chunk.setBlockId(x, y, z, Block.NETHERRACK);
} else if (y <= this.waterHeight) {
chunk.setBlockId(x, y, z, Block.STILL_LAVA);
chunk.setBlockLight(x, y + 1, z, 15);
}
}
}
}
for (Populator populator : this.generationPopulators) {
populator.populate(this.level, chunkX, chunkZ, this.nukkitRandom);
}
}
use of cn.nukkit.level.format.FullChunk in project Nukkit by Nukkit.
the class Normal method generateChunk.
@Override
public void generateChunk(int chunkX, int chunkZ) {
this.nukkitRandom.setSeed(chunkX * localSeed1 ^ chunkZ * localSeed2 ^ this.level.getSeed());
double[][] seaFloorNoise = Generator.getFastNoise2D(this.noiseSeaFloor, 16, 16, 4, chunkX * 16, 0, chunkZ * 16);
double[][] landNoise = Generator.getFastNoise2D(this.noiseLand, 16, 16, 4, chunkX * 16, 0, chunkZ * 16);
double[][] mountainNoise = Generator.getFastNoise2D(this.noiseMountains, 16, 16, 4, chunkX * 16, 0, chunkZ * 16);
double[][] baseNoise = Generator.getFastNoise2D(this.noiseBaseGround, 16, 16, 4, chunkX * 16, 0, chunkZ * 16);
double[][] riverNoise = Generator.getFastNoise2D(this.noiseRiver, 16, 16, 4, chunkX * 16, 0, chunkZ * 16);
FullChunk chunk = this.level.getChunk(chunkX, chunkZ);
for (int genx = 0; genx < 16; genx++) {
for (int genz = 0; genz < 16; genz++) {
Biome biome;
boolean canBaseGround = false;
boolean canRiver = true;
// using a quadratic function which smooth the world
// y = (2.956x)^2 - 0.6, (0 <= x <= 2)
double landHeightNoise = landNoise[genx][genz] + 1F;
landHeightNoise *= 2.956;
landHeightNoise = landHeightNoise * landHeightNoise;
landHeightNoise = landHeightNoise - 0.6F;
landHeightNoise = landHeightNoise > 0 ? landHeightNoise : 0;
// generate mountains
double mountainHeightGenerate = mountainNoise[genx][genz] - 0.2F;
mountainHeightGenerate = mountainHeightGenerate > 0 ? mountainHeightGenerate : 0;
int mountainGenerate = (int) (mountainHeight * mountainHeightGenerate);
int landHeightGenerate = (int) (landHeightRange * landHeightNoise);
if (landHeightGenerate > landHeightRange) {
if (landHeightGenerate > landHeightRange) {
canBaseGround = true;
}
landHeightGenerate = landHeightRange;
}
int genyHeight = seaFloorHeight + landHeightGenerate;
genyHeight += mountainGenerate;
// prepare for generate ocean, desert, and land
if (genyHeight < beathStartHeight) {
if (genyHeight < beathStartHeight - 5) {
genyHeight += (int) (seaFloorGenerateRange * seaFloorNoise[genx][genz]);
}
biome = Biome.getBiome(Biome.OCEAN);
if (genyHeight < seaFloorHeight - seaFloorGenerateRange) {
genyHeight = seaFloorHeight;
}
canRiver = false;
} else if (genyHeight <= beathStopHeight && genyHeight >= beathStartHeight) {
biome = Biome.getBiome(Biome.BEACH);
} else {
biome = this.pickBiome(chunkX * 16 + genx, chunkZ * 16 + genz);
if (canBaseGround) {
int baseGroundHeight = (int) (landHeightRange * landHeightNoise) - landHeightRange;
int baseGroundHeight2 = (int) (basegroundHeight * (baseNoise[genx][genz] + 1F));
if (baseGroundHeight2 > baseGroundHeight)
baseGroundHeight2 = baseGroundHeight;
if (baseGroundHeight2 > mountainGenerate)
baseGroundHeight2 = baseGroundHeight2 - mountainGenerate;
else
baseGroundHeight2 = 0;
genyHeight += baseGroundHeight2;
}
}
if (canRiver && genyHeight <= seaHeight - 5) {
canRiver = false;
}
// generate river
if (canRiver) {
double riverGenerate = riverNoise[genx][genz];
if (riverGenerate > -0.25F && riverGenerate < 0.25F) {
riverGenerate = riverGenerate > 0 ? riverGenerate : -riverGenerate;
riverGenerate = 0.25F - riverGenerate;
// y=x^2 * 4 - 0.0000001
riverGenerate = riverGenerate * riverGenerate * 4F;
// smooth again
riverGenerate = riverGenerate - 0.0000001F;
riverGenerate = riverGenerate > 0 ? riverGenerate : 0;
genyHeight -= riverGenerate * 64;
if (genyHeight < seaHeight) {
biome = Biome.getBiome(Biome.RIVER);
// to generate river floor
if (genyHeight <= seaHeight - 8) {
int genyHeight1 = seaHeight - 9 + (int) (basegroundHeight * (baseNoise[genx][genz] + 1F));
int genyHeight2 = genyHeight < seaHeight - 7 ? seaHeight - 7 : genyHeight;
genyHeight = genyHeight1 > genyHeight2 ? genyHeight1 : genyHeight2;
}
}
}
}
chunk.setBiomeId(genx, genz, biome.getId());
// biome color
// todo: smooth chunk color
int biomecolor = biome.getColor();
chunk.setBiomeColor(genx, genz, (biomecolor >> 16), (biomecolor >> 8) & 0xff, (biomecolor & 0xff));
// generating
int generateHeight = genyHeight > seaHeight ? genyHeight : seaHeight;
for (int geny = 0; geny <= generateHeight; geny++) {
if (geny <= bedrockDepth && (geny == 0 || nukkitRandom.nextRange(1, 5) == 1)) {
chunk.setBlock(genx, geny, genz, Block.BEDROCK);
} else if (geny > genyHeight) {
if ((biome.getId() == Biome.ICE_PLAINS || biome.getId() == Biome.TAIGA) && geny == seaHeight) {
chunk.setBlock(genx, geny, genz, Block.ICE);
} else {
chunk.setBlock(genx, geny, genz, Block.STILL_WATER);
}
} else {
chunk.setBlock(genx, geny, genz, Block.STONE);
}
}
}
}
// populator chunk
for (Populator populator : this.generationPopulators) {
populator.populate(this.level, chunkX, chunkZ, this.nukkitRandom);
}
}
use of cn.nukkit.level.format.FullChunk in project Nukkit by Nukkit.
the class PopulatorGroundCover method populate.
@Override
public void populate(ChunkManager level, int chunkX, int chunkZ, NukkitRandom random) {
FullChunk chunk = level.getChunk(chunkX, chunkZ);
for (int x = 0; x < 16; ++x) {
for (int z = 0; z < 16; ++z) {
Biome biome = Biome.getBiome(chunk.getBiomeId(x, z));
Block[] cover = biome.getGroundCover();
if (cover != null && cover.length > 0) {
int diffY = 0;
if (!cover[0].isSolid()) {
diffY = 1;
}
int height = chunk.getHeightMap(x, z);
if (height == 0 || height == 255)
height = 126;
int y;
for (y = height + 1; y > 0; --y) {
int fullId = chunk.getFullBlock(x, y, z);
if (fullId != 0 && !Block.get(fullId >> 4).isTransparent()) {
break;
}
}
int startY = Math.min(127, y + diffY);
int endY = startY - cover.length;
for (y = startY; y > endY && y >= 0; --y) {
Block b = cover[startY - y];
int blockId = chunk.getBlockId(x, y, z);
if (blockId == 0 && b.isSolid()) {
break;
}
if (b.getDamage() == 0) {
chunk.setBlockId(x, y, z, b.getId());
} else {
chunk.setBlock(x, y, z, b.getId(), b.getDamage());
}
}
}
}
}
}
use of cn.nukkit.level.format.FullChunk in project Nukkit by Nukkit.
the class Level method doChunkGarbageCollection.
public void doChunkGarbageCollection() {
this.timings.doChunkGC.startTiming();
// remove all invaild block entities.
List<BlockEntity> toClose = new ArrayList<>();
if (!blockEntities.isEmpty()) {
Iterator<Map.Entry<Long, BlockEntity>> iter = blockEntities.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, BlockEntity> entry = iter.next();
BlockEntity aBlockEntity = entry.getValue();
if (aBlockEntity != null) {
if (!aBlockEntity.isValid()) {
iter.remove();
aBlockEntity.close();
}
} else {
iter.remove();
}
}
}
for (Map.Entry<Long, ? extends FullChunk> entry : provider.getLoadedChunks().entrySet()) {
long index = entry.getKey();
if (!this.unloadQueue.containsKey(index)) {
FullChunk chunk = entry.getValue();
int X = chunk.getX();
int Z = chunk.getZ();
if (!this.isSpawnChunk(X, Z)) {
this.unloadChunkRequest(X, Z, true);
}
}
}
this.provider.doGarbageCollection();
this.timings.doChunkGC.stopTiming();
}
Aggregations