rutgerkok / WorldGeneratorApi

Minecraft Spigot plugin that enables other plugins to customize world generation
MIT License
95 stars 9 forks source link

How would biomes be implemented? #7

Closed 19lmyers closed 4 years ago

19lmyers commented 4 years ago

This is more of a question, as I didn't see anything mentioned about it in any of the tutorials, but how would one implement biomes for a custom world generator?

Alternatively, how does the vanilla implementation / the API with the default settings enabled implement biomes?

rutgerkok commented 4 years ago

Currently, it's not possible: see https://github.com/rutgerkok/WorldGeneratorApi#limitations . As a workaround, you can let the BaseTerrainGenerator modify the BiomeGrid for that chunk, but then structures like villages will still see the vanilla biomes. So I would only use this for prototyping purposes.

By default, the biome generator is stored in WorldServer.getChunkProvider() .getChunkGenerator().getWorldChunkManager(). (Here, WorldServer is the internal Minecraft class, not the Bukkit World.)

If you're interested, I can add a setBiomeGenerator method to the WorldGenerator class, so that you can properly inject your biome generator.

19lmyers commented 4 years ago

That probably would be helpful, thanks. I'm a bit new to all this, but I'll play around with it some more and see what the limitations are.

I'm assuming injecting a custom biome generator would break structures like villages?

rutgerkok commented 4 years ago

Changing the biome generator shouldn't break structures, provided I implement it properly. Right now, I'm a bit puzzled by a set of biomes that a biome generator apparantly needs to provide, which seems to decide where the structures can and cannot go. I hope to have it implemented in a few days.

rutgerkok commented 4 years ago

I've added this to the development version. You can compile WorldGeneratorApi yourself and build against it, and then you're able to use worldGenerator.setBiomeGenerator(...). For the BiomeGenerator interface you just need to implement a single method (getZoomedOutBiome(x, y, z)) and then everything should work.

If you want, I can also updated this snapshot to rutgerkok.nl/repo so that it's easier to access.

19lmyers commented 4 years ago

I have a follow up question. Do you know how Minecraft implements getZoomedOutBiome() internally? I've been struggling to make my own biome generator and am curious how the game does it.

rutgerkok commented 4 years ago

It's complex.

Basically, biome generation starts on an enormous scale (1 px = huge number of blocks), and then zooms in 2 times using some fractal zoom algorithm, adds some more details, then zooms in again, then adds more details, and after doing that for 12 times or so in total you end up with a representation where 1 px = 4 by 4 blocks.

If you paint a single pixel and then zoom in 5 times, then that pixel will become 2^5 blocks in length. So you add a single pixel at an early point to define where the continents and the oceans will be, and then you zoom in. Then you define where the climate zones will be, and you zoom in again. Then you decide where the biomes will be, and then you zoom in a few more times and there's your world.

Rivers start off as single pixels at the edge of two biomes. "Isle biomes" (mushroom islands, or biomes like Forest Hills which is an "island" in the forest biome) start of as single pixels in other biomes.

Someone made an example implementation over here: https://github.com/valoeghese/FractalBiomeGeneration/blob/master/src/tk/valoeghese/world/gen/fractal/util/BiomeFractals.java

Alternatively, you can do like Minecraft Beta 1.7, and use two 2D noise generators (temperature and wetness) and decide the biome based on that. But that is less flexible, and you can't have rivers.