This API is much more flexible than the old, allowing any arbitrary set of chunks to be ticked.
These changes also improve the performance of random chunk ticking by almost entirely eliminating the cost of chunk selection. Ticking chunks are now reevaluated when a player moves, instead of every tick.
The system also does not attempt to check the same chunks twice, leading to further improvements.
Overall, the overhead of random chunk selection is reduced anywhere from 80-96%. In practice, this can offer a 5-10% performance gain for servers with sparsely distributed players.
this simplifies usages of safe spawns, since the caller doesn't need to know which chunks will be needed for the spawn to be selected.
We'll need this in the future, because safe spawns may also get diverted horizontally as well as vertically, which might require loading adjacent chunks as well as the chunk the position is actually in.
in vanilla, it appears to behave as if the player always clicked on the up face if a block was replaced.
In PM, we were still using the original face, which caused bugs when, for example, placing a button next to a wall by clicking on the side of tallgrass. The button would replace the tallgrass, but stick to the wall, instead of placing itself on the ground like vanilla expects.
This may appear unusual to anyone who also happens to implement canBePlacedAt(), since the facing behaviour will be different. However, this behaviour appears to match vanilla, and even slabs (which I feared might break because of this change) work perfectly.
In the future, it may be desirable to pass some other value here, such as null, to indicate that the clicked block is being replaced. However, that's a BC break and therefore outside of the scope of a stable bug fix.
This reverts commit aebcfc516ff97492c58ee478a3944915a777a75e.
this has edge cases in the handling of adjacent chunk locks which I
didn't consider at the time. Once accounting for those edge cases, it
became significantly more complex to the point that I realized this
needed more planning.
the target chunk may no longer be loaded if it was unloaded during a previous chunk's tick (e.g. during BlockGrowEvent).
Since the parent function iterates over a pre-selected array of chunks, the chunk will still be present in the list even if it's no longer loaded by the time it's reached.
this is just wasting CPU time, since the effects aren't noticeable on such a small timescale anyway.
This reduces the CPU impact of chunk selection by 95%. However, this is the lesser part of chunk ticking, and the lion's share of the performance impact still comes from actually ticking the chunks.
WARNING: This WILL have a performance impact on larger servers, but that's the price to pay for having crops actually grow.
The old overengineered method for doing this was causing glacially slow crop growth, vanilla parity issues and really just didn't make much sense. This method is probably incorrect too, but it will at least produce visible results.
This required the following:
- A generation task (taskA) to already be running for any chunk (chunkA)
- A chunk (chunkB) is requested for generation, and the task (taskB) to do the generation
is commenced immediately
- chunkB generation promise is aborted (e.g. due to chunk unload) and
taskB is orphaned
- chunkB is subsequently re-requested, but ends up in the generation
queue because taskB is still running
- taskA completes and drains the generation queue
- chunkB attempts to be populated a second time, but taskB has not yet
been collected, resulting in an assertion failure.
This bug has been appearing intermittently ever since PM 4.0 release.
For most users there is no obvious effect since production servers don't
have assertions enabled; however, it's unclear what kind of weird side
effects this bug may have had.