Why biomes aren't updating?

maksim2498

New member
May 7, 2023
2
0
1
22
Moscow, Russia
I'm writing a PaperMC plugin that should restore all biomes in the world within a specified radius.
The issue here is that biomes aren't restoring.

Can someone please tell me what am i doing wrong?

I've tested this code on PaperMC 1.19.0-1.19.4

Here is a full plugin code:

Java:
package ru.fominmv.biome_fixer;

import org.bukkit.Chunk;
import org.bukkit.plugin.java.JavaPlugin;

public class BiomeFixer extends JavaPlugin {
    @Override
    public void onEnable() {
        final int MIN_X        = -4000;
        final int MAX_X        =  4000;

        final int MIN_Z        = -4000;
        final int MAX_Z        =  4000;

        final int TOTAL_CHUNKS =  (int) Math.ceil((float) (MAX_X - MIN_X) / 16.f)
                               *  (int) Math.ceil((float) (MAX_Z - MIN_Z) / 16.f);

        final int INIT_DELAY   =  20 * 15;
        final int DELAY        =  2;

        final var server       =  getServer();
        final var logger       =  server.getLogger();
        final var scheduler    =  server.getScheduler();
        final var world        =  server.getWorld("world");

        assert world != null;

        final var s = new Object() {
            Runnable step;

            int chunksProcessed = 0;

            int x = MIN_X;
            int z = MIN_Z;
        };

        s.step = () -> {
            if (world.isChunkGenerated(s.x, s.z)) {
                final var chunk = world.getChunkAt(s.x, s.z);
                fixChunk(chunk);
            }

            ++s.chunksProcessed;

            final var message = String.format("%d/%d chunks processed", s.chunksProcessed, TOTAL_CHUNKS);
            logger.info((message));

            s.x += 16;

            if (s.x >= MAX_X) {
                s.x  = MIN_X;
                s.z += 16;
            }

            if (s.z >= MAX_Z) {
                logger.info("Biome recovery is done");
                return;
            }

            scheduler.scheduleSyncDelayedTask(this, s.step, DELAY);
        };

        final var message = String.format("Biome recovery will be started in %d secods...", INIT_DELAY / 20);

        logger.info(message);

        scheduler.scheduleSyncDelayedTask(this, () -> {
            logger.info("Biome recovery has started");
            s.step.run();
        }, INIT_DELAY);
    }

    private void fixChunk(final Chunk chunk) {
        final var server = getServer();
        final var logger = server.getLogger();

        if (!chunk.isLoaded() && !chunk.load()) {
            logger.info("Chunk loading failed");
            return;
        }

        final var world         = chunk.getWorld();
        final var biomeProvider = world.vanillaBiomeProvider();

        assert biomeProvider != null;

        for (int x = 0; x < 16; x += 4)
            for (int z = 0; z < 16; z += 4)
                for (int y = world.getMinHeight(); y < world.getMaxHeight(); y += 4) {
                    final var block = chunk.getBlock(x, y, z);
                    final var biome = biomeProvider.getBiome(world, block.getX(), block.getY(), block.getZ());

                    block.setBiome(biome);
                }


        if (!chunk.unload(true))
            logger.info("Chunk unloading failed");
    }
}
 
Last edited:

maksim2498

New member
May 7, 2023
2
0
1
22
Moscow, Russia
The issue is solved. The problem was that in world.getBiome(x, z) x and z aren't the same as block coordinates. They are a factor of 16, i.e. a number of chunk rather than a coordinate within it