Flooding proof of concept (Patreon)
Downloads
Content
Flooding is supposed to be one of the medium-sized features of 0.7. I’ve known that it was theoretically possible for a while, but it’s always good to have some proof of concept code to get things started.
This animation is the first stage in the process of developing flooding.
It’s recorded in real time running at 60ups, 50 tiles changed per tick, or 3000 tiles changed per second. The tide cycle wouldn’t be anywhere near this fast, but then the explored surface could be much larger so 3000 tiles per second is still a reasonable expectation. The tile changing performance is better than I was expecting so that’s a nice surprise.
The main bottleneck is actually not changing the tiles, it’s preparing all the data to make this happen.
The way it works currently is that when the game generates a chunk (32x32 tiles) it fires an event that the mod can pick up. When this happens I scan all the tiles in the chunk for tiles that I’ve designated as the correct type for coastline tiles. For now it’s just the shallow water tiles and they change to some random dirt tiles. These are just tiles for testing. It won’t be these tiles in the final version, there will be special tiles specifically for this. For the moment code like this is in Space Exploration, and the new tiles are in Alien Biomes V3, but the two aren’t compatible yet.
When the coastline tiles are found, I then calculate the elevation for those tiles based on some noise expressions, which you can read about here: https://factorio.com/blog/post/fff-390
The collected data (position, current tile type, and elevation) is then saved for that planet. The data is sorted by elevation, which means there is some sorting to do too.
When you create a new surface for a planet it tries to generate a lot of chunks quickly, and having to do all the data collection and sorting steps every time is really slowing the game down. When there’s only a few coastal tiles in the chunk it’s not noticeable, but when the chunk is mostly coastal tiles then it noticeably hangs the game for a split second. It’s probably only 0.1s but you still feel it, and it feels bad.
The current state would be completely unacceptable so that will have to change. There are a lot of ways to smooth out the problem, like saving some chunks for processing for later, only processing a quarter of a chunk at the time, maybe batching some of the calculations if that’s more efficient, using a different sorting algorithm, etc. The worst-case scenario is that if you explore the planet quickly it may take a while before some areas start flooding, but often that’s just a cosmetic consequence. It only really matters if you build there, and it wouldn't be too hard to prioritise areas you build around.
The next big step for this is to try to get flooding to work in a contiguous way. Right now it just floods the lowest area first even if that area isn’t connected to existing water. One of the things I wanted was the ability to use walls to make flood barriers. Currently the water can just appear behind the walls, which isn’t terrible but it feels less interactive that way.
Having the flooding work in a contiguous way will rely on a flood-fill algorithm (which is very appropriately named in this situation). It will make the code much more complicated and therefore slower, but the flooding part is still extremely quick. In my experience lua processing isn’t where things slow down, it’s the direct interaction with, and reading of, the game world.
It’s also worth pointing out that the only reason a mechanic like this is viable is because planets in Space Exploration have a limited radius. If a planet could be as big as vanilla Nauvis then it just wouldn’t work.
This is more of a technical post than usual. If you want to hear about the gameplay implications check out the post I did about Vitamelange planets (May 2023).