cn.nukkit.level.generator.task.PopulationTask Maven / Gradle / Ivy
package cn.nukkit.level.generator.task;
import cn.nukkit.Server;
import cn.nukkit.level.DimensionData;
import cn.nukkit.level.Level;
import cn.nukkit.level.format.generic.BaseFullChunk;
import cn.nukkit.level.generator.Generator;
import cn.nukkit.level.generator.SimpleChunkManager;
import cn.nukkit.scheduler.AsyncTask;
/**
* @author MagicDroidX (Nukkit Project)
*/
public class PopulationTask extends AsyncTask {
public final BaseFullChunk[] chunks = new BaseFullChunk[9];
private final long seed;
private final Level level;
private boolean state;
private BaseFullChunk centerChunk;
private boolean isPopulated;
public PopulationTask(Level level, BaseFullChunk chunk) {
this.state = true;
this.level = level;
this.centerChunk = chunk;
this.seed = level.getSeed();
chunks[4] = chunk;
int i = 0;
for (int z = -1; z <= 1; z++) {
for (int x = -1; x <= 1; x++, i++) {
if (i == 4) continue;
BaseFullChunk ck = level.getChunk(chunk.getX() + x, chunk.getZ() + z, true);
this.chunks[i] = ck;
}
}
}
@Override
public void onRun() {
syncGen(0);
}
private void syncGen(int i) {
if (i == chunks.length) {
generationTask();
} else {
BaseFullChunk chunk = chunks[i];
if (chunk != null) {
synchronized (chunk) {
syncGen(i + 1);
}
}
}
}
private void generationTask() {
this.state = false;
Generator generator = level.getGenerator();
if (generator == null) {
return;
}
SimpleChunkManager manager = (SimpleChunkManager) generator.getChunkManager();
if (manager == null) {
this.state = false;
return;
}
synchronized (manager) {
try {
manager.cleanChunks(this.seed);
BaseFullChunk centerChunk = this.centerChunk;
if (centerChunk == null) {
return;
}
int index = 0;
for (int x = -1; x < 2; x++) {
for (int z = -1; z < 2; z++, index++) {
BaseFullChunk ck = this.chunks[index];
if (ck == centerChunk) continue;
if (ck == null) {
try {
this.chunks[index] = (BaseFullChunk) centerChunk.getClass().getMethod("getEmptyChunk", int.class, int.class, DimensionData.class).invoke(null, centerChunk.getX() + x, centerChunk.getZ() + z, level.getDimensionData());
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
this.chunks[index] = ck;
}
}
}
for (BaseFullChunk chunk : this.chunks) {
manager.setChunk(chunk.getX(), chunk.getZ(), chunk);
if (!chunk.isGenerated()) {
generator.generateChunk(chunk.getX(), chunk.getZ());
BaseFullChunk newChunk = manager.getChunk(chunk.getX(), chunk.getZ());
newChunk.setGenerated();
if (newChunk != chunk) manager.setChunk(chunk.getX(), chunk.getZ(), newChunk);
}
}
isPopulated = centerChunk.isPopulated();
if (!isPopulated) {
generator.populateChunk(centerChunk.getX(), centerChunk.getZ());
centerChunk = manager.getChunk(centerChunk.getX(), centerChunk.getZ());
centerChunk.setPopulated();
centerChunk.recalculateHeightMap();
centerChunk.populateSkyLight();
centerChunk.setLightPopulated();
this.centerChunk = centerChunk;
}
manager.setChunk(centerChunk.getX(), centerChunk.getZ());
index = 0;
for (int x = -1; x < 2; x++) {
for (int z = -1; z < 2; z++, index++) {
chunks[index] = null;
BaseFullChunk newChunk = manager.getChunk(centerChunk.getX() + x, centerChunk.getZ() + z);
if (newChunk != null) {
if (newChunk.hasChanged()) {
chunks[index] = newChunk;
}
}
}
}
this.state = true;
} finally {
manager.cleanChunks(this.seed);
}
}
}
@Override
public void onCompletion(Server server) {
if (level != null) {
if (!this.state) {
return;
}
BaseFullChunk centerChunk = this.centerChunk;
if (centerChunk == null) {
return;
}
for (BaseFullChunk chunk : this.chunks) {
if (chunk != null) {
level.generateChunkCallback(chunk.getX(), chunk.getZ(), chunk);
}
}
level.generateChunkCallback(centerChunk.getX(), centerChunk.getZ(), centerChunk, isPopulated);
//需要在全部地形生成完毕后再尝试生成结构
//todo: 不应该写在这里,往前放更合理,但是会有NPE:(
var generator = level.getGenerator();
if (generator.shouldGenerateStructures()) {
generator.populateStructure(centerChunk.getX(), centerChunk.getZ());
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy