aternosorg / thanos

PHP library to automatically detect and remove unused chunks from Minecraft worlds.
https://packagist.org/packages/aternos/thanos
MIT License
221 stars 20 forks source link

Thanos' chunk trimming can be destructive to trees #20

Closed cyyynthia closed 9 months ago

cyyynthia commented 9 months ago

I doubt it's something that can be fixed easily, but I felt like I should at least report it considering I've seen it mentioned nowhere.

I've seen a lot of trees disfigured on Aternos while playing on a server with friends (especially when playing with biome mods which adds very large trees with organic shapes), which wasn't something I experienced on solo maps or on other servers. I made the hypothesis the optimization feature was the culprit, and after a bit of testing I confirmed this hypothesis.

Due to how Minecraft's generation works, blindly deleting a chunk can mess with certain parts of the generation, most notably trees. When they span across chunks, it doesn't actually matter for the game because neighboring chunks are already being generated, so it can just write to them and call it a day. However, if a chunk containing a tree was to be deleted, it would not be generated at the exact same spot again and the leaves that grew in the neighbor chunk would remain floating. Similarly, if a chunk containing leaves from another chunk's tree is removed, the tree will permanently lose those leaves.

One approach I imagine could help prevent this is making sure neighboring chunks aren't in a state where they may have generated things in the current chunk; but I'm pretty sure this would have quite a big impact on the effectiveness of the optimization.

cyyynthia commented 9 months ago

Here is a minimal reproduction map, generated on Minecraft 1.20.4 (vanilla), that hasn't been Thanos'd. The map has been generated by waiting for the generation to finish after spawning, running from spawn in a straight line for approx. 40 chunks, wait for generation to settle, and then save the world. To make the reproduction smaller I removed unnecessary region files; the reproduction chunks aren't near the boundaries anyway.

It happens to be a surprisingly good reproduction as it has both problems happening very closely to one another 😅

thanos_repro_map.zip

KurtThiemann commented 9 months ago

I've definitely noticed this before and can look into it some more, but it is very much possible that this is not a fixable issue. Hacks like checking if there are any leave blocks at the border to a chunk that isn't also deleted might work, but that would not really be a reliable solution and would slow down thanos to a point where it doesn't actually make sense to use it anymore. I got some hope that this might not be a general issue, but maybe only has something to do with partially generated chunks (proto-chunks)? The issue would probably be far more common if every single tree on a chunk border would break whenever thanos deletes a chunk.

I'll take a look at your example map tomorrow or Monday. What view distance setting do you use in your Minecraft client?

cyyynthia commented 9 months ago

I used 12 chunks for the render distance.

And yeah I think the unfortunate truth is that it's something that can't be fixed without either tanking the performance of the tool, or being overly conservative and not delete enough chunks for the tool to have a meaningful impact 😔

The cases I've pointed out both occur with fully generated chunks (both the chunk from where the tree is, and the chunk being removed by Thanos)

KurtThiemann commented 9 months ago

So I looked a bit into it and think I know what happens. If Minecraft generates a chunk that has structures that go inside another chunk, but that chunk has not been generated yet, a proto-chunk is created and information about the blocks that should be there is saved to the proto-chunk's block_tick list. image Once the chunk is actually needed, it is generated and the blocks from block_ticks are placed. If the chunk is deleted, there of course won't be a proto-chunk with a block_ticks list there, it will just be gone. Minecraft therefore doesn't place any additional blocks when the chunk is regenerated. This is a bit unfortunate, since it means the only two options would be to either not delete any chunks that may intersect trees from other chunks, or try to generate new block_tick information when a chunk is deleted. Both of those options aren't really viable.

Checking whether there are leaves at the edge of a chunk might be (kind of) possible without actually parsing all block data by comparing the MOTION_BLOCKING and MOTION_BLOCKING_NO_LEAVES height maps, but there are other structures that are also affected by the same issue (like large mushrooms) that can't be detected this way.

We'll discuss this issue internally, but I think the most likely outcome will be that we'll add a note to the readme and our help center article and close this as wontfix. Thanos is optional in Aternos, so it can be disabled by users who'd like to avoid these artifacts in trees.

cyyynthia commented 9 months ago

That's a very understandable, albeit sad, outcome. A mention in the help center is still a good thing, so at least there's an explanation for those quirks. I guess the only "proper" fix would be to perform this at the game logic level rather than externally, to collect/use extra metadata allowing to handle this seamlessly; but given how flexible Aternos is with server software that runs I doubt that's any easier...

Thanks for looking into it anyway!

KurtThiemann commented 9 months ago

I added a note to the README and our help center articles. Thanks for bringing this issue to our attention!