All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.level.generator.task.PopulationTask Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
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