Skip to content

Incremental World Generation #59

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions