Skip to content

Incremental World Generation #59

@Ifiht

Description

@Ifiht

Hey - first of all thank you for the per-world ticking patch, it's been great on my server

I wanted to let you know I found a way to not hang on new world generation by refactoring all the world init stuff into ServerLevel.java and executing off-main, it's all in my version of the parallel-world-tick patch

Basically the ServerLevel tick now starts like this:

public void tick(BooleanSupplier hasTimeLeft) {
        // Aincrad start - atomize world init across ticks
        if (this.isInitializingLevel) {
            net.minecraft.server.level.ServerChunkCache chunkSource = this.getChunkSource();
            switch(initializationStage) {
                case 0: // add small block-lvl sub-generators ("populators")
                    if (this.generator != null) {
                        this.getWorld().getPopulators().addAll(this.generator.getDefaultPopulators(this.getWorld()));
                    }
                    break;
                case 1: // set the world border
                    net.minecraft.world.level.border.WorldBorder worldborder = this.getWorldBorder();
                    worldborder.applySettings(serverLevelData.getWorldBorder());
                    break;
                case 2: // allow plugins to respond to world generation before any chunk generation
                    org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldInitEvent(this.getWorld()));
                    break;
                //== Chunk Map (X,Z): ==
                //  -1,1    0,1    1,1
                //  -1,0    0,0    1,0
                //  -1,-1   0,-1   1,-1
                case 3: // generate & load the origin chunk
                    chunkSource.getChunk(0, 0, ChunkStatus.FULL, true);
                    break;
                case 4: // generate chunk VERT
                    chunkSource.getChunk(0, 1, ChunkStatus.FULL, true);
                    chunkSource.getChunk(0, -1, ChunkStatus.FULL, true);
                    break;
                case 5: // generate chunk HORZ
                    chunkSource.getChunk(1, 0, ChunkStatus.FULL, true);
                    chunkSource.getChunk(-1, 0, ChunkStatus.FULL, true);
                    break;
                case 6: // generate chunk X
                    chunkSource.getChunk(1, 1, ChunkStatus.FULL, true);
                    chunkSource.getChunk(1, -1, ChunkStatus.FULL, true);
                    chunkSource.getChunk(-1, 1, ChunkStatus.FULL, true);
                    chunkSource.getChunk(-1, -1, ChunkStatus.FULL, true);
                    break;
                case 7: // generate chunk t
                    chunkSource.getChunk(0, 2, ChunkStatus.FULL, true);
                    chunkSource.getChunk(0, -2, ChunkStatus.FULL, true);
                    chunkSource.getChunk(2, 0, ChunkStatus.FULL, true);
                    chunkSource.getChunk(-2, 0, ChunkStatus.FULL, true);
                    break;
                case 8: // set the spawn location
                    try {
                        setInitialSpawn(isDebugWorld);
                        //serverLevelData.setInitialized(true);
                        if (isDebugWorld) {
                            this.setupDebugLevel(this.server.getWorldData());
                        }
                    } catch (Throwable var23) {
                        net.minecraft.CrashReport crashReport = net.minecraft.CrashReport.forThrowable(var23, "Exception initializing level");
                        try {
                            this.fillReportDetails(crashReport);
                        } catch (Throwable var22) {
                        }
                        throw new net.minecraft.ReportedException(crashReport);
                    }
                    break;
                case 9: // prepare the start region, should be quick since the chunks are loaded
                    server.forceTicks = true;
                    this.prepareLevel();
                    server.forceTicks = false;
                    break;
                case 10: // declare the world initialized
                    serverLevelData.setInitialized(true);
                    this.isInitializingLevel = false;
                    LOGGER.info("Done preparing level \"{}\"!", this.dimension().location());
                    break;
                default: // break out by default
                    this.isInitializingLevel = false;
                    break;
            }
            initializationStage++;
            return;
        }
        // Aincrad end

Anyway, not sure if that helps u or not, but I don't think there r many ppl using per-world ticking in Minecraft, so those of us who do should collab if we can ¯_(ツ)_/¯

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions