Posting in the
sand physics thread gave me an idea about how fluid mechanics could be sped up to reduce cpu load, for even large fluid masses to next to nothing. This idea would also support having multiple fluids per tile.
A fluid level is a z-position in a tile of fluid(s) ranging from 1-7. Any fluid connected with the same fluid on the same level compose a fluid layer. A fluid layer has an external border and any number of internal borders (holes), consisting of the tiles that do not have fluid on all 8 adjacent tiles on the same z-level. A sub border is a border that lies in a layer directly beneath to which there is a path consisting of fluid with no same fluid in an upper layer. Each external border has one sub-border in the layer below, while each internal border can have any number of sub-borders below. All fluids move from a border to one of its sub borders. Air has borders as well, but only in relation to fluid bodies.
Fluid displacement will work as follows:
Horizontal displacement:
For each body of fluid,
For each layer border x
sum the lengths of adjacent borders of any displacable material (or keep this number for each layer border) including air, to each sub border.
If greater than the length of border x, all tiles displace 1/7 to the adjacent borders, spaced out evenly using something like Bresenham's line algorithm (may require some tweaking to handle irregular border problem, such as exclusion of already displaced border tiles until all have been displaced)
otherwise, displace only the number of tiles that fit into the borders using same algorithm to pick out which to move.
Update the borders.
Vertical displacement: If fluid is displaced, fluid of another type in the same tile drops, and creates a gap for potential fluid in the next z-level to drop into. this coordinate is put on an event vector. This also happens if fluid is displaced to a tile which has displaceable material below it.
The event vector is processed, by swapping fluids, which counts as displacement, thus allows bubbles to float up to its proper place after which they are removed from the event vector.
A note about displacability. If two fluids of different kind meet, one has the potential to displace the other if it does not react with it and has higher density, and there is space to displace it to, which is pushing it up, creating a new layer. This might need some resistance so that not all fluids of this kind are immediately displacable, but are sometimes not displacable.
Fluids can also destroy another fluid e.g. magma destroys sand, in which the above complication is not needed.
Fluid can also react with another to create either a third type of fluid or a solid natural rock of some kind.
If two fluids meet of the same kind, they will merge into one single body, and the external border of one will merge with the external or an internal border of the other.
Evaporation can cause bodies to split, and so perhaps the best way to handle it is not to count 1/7 tiles as fluid bodies, and fluid bodies are removed from memory if they reduce to a 1/7 layer (unless it is sandwiched with another kind of fluid on top) and is then treated as slowly evaporating fluid unless it comes in contact with a fluid that prevents this.
Cave ins, channeling, bridge retraction, hatch opening etc that cause two adjacent z tiles to be exposed to another, creates an event (pushes coordinate on event vector)
Pressurized fluids can move across different layers in the same body, in the same z level in an upper fluid level (U-teleportation) to one of its borders, or create a new layer on top if all borders are surrounded by solids.
There are probably more complications to it, but can't think of any at the moment, the basic (and major) improvement lies in how large masses of fluids move.