we don't usually add VanillaItems entries for blocks since they already exist in VanillaBlocks, but air has a special use case specifically as an itemstack, so we make an exception for this case.
this fixes many cases of corruption during disk-full situations - file_put_contents() would write an empty file, destroying the original data.
fixes#3152
this fixes a wide range of blocks with invalid blockstates becoming update! blocks on the client.
The most common occurrence of this was air with nonzero metadata left behind by world editors which set blockIDs but not block metadata. This caused large ghost structures of update! blocks to appear from nowhere.
The performance impact of this is very minimal (20 microseconds per chunk load in timings, compared to average 660 microseconds to load tiles).
this is not as good as phpstan/phpstan-src#769 (e.g. array_key_first()/array_key_last() aren't covered by this, nor is array_rand()) but it does eliminate the most infuriating cases where this usually crops up.
if the worker selected previously had a generator registered, but has since been shutdown, the workerStartHook that cleans up generatorRegisteredWorkers won't yet have been called.
This results in the worker being started by the submission of PopulationTask, and the generator doesn't get preemptively registered.
if this happened, the index would stay set in activeChunkPopulationTasks, eventually causing the generation queue to jam up completely and non-forced generation to come to a standstill.
When profiling this, I noticed that we spend a stupidly large amount of time creating useless Position objects in the case of update=true, because Vector3->sides() calls Position->getSide(), which calls Position::fromObject(parent::getSide()). This is stupid because the update logic doesn't require Positions anywhere (as evidenced by this change needing no other alterations.
A rough profile shows that this improves setBlock() performance by about 25% in the update=true case, which is a pretty big margin.
As an added bonus, it gets rid of some unrealized cyclic dependencies in World->changedBlocks.
if the request/cancel/re-request happens all in the time before the queue gets drained, chunk hashes may appear multiple times in the queue. We don't want to process them twice if this happens (although it's mostly harmless anyway).
this could happen if a plugin calls setPopulated(true) on a chunk after a request for its population landed in the queue, but before it actually got processed. In that case, the promise would never get fulfilled.
this does not indicate a failure; it indicates that the chunk has already been successfully populated.
In this case, we shouldn't be putting the task back on the queue.
This is skirting around the real bug, which is that requestChunkPopulation() doesn't check if the target chunk is already populated before it creates a new promise that it will be.
this allows chunks locked for population to be modified. If the PopulationTask detects that the chunk was modified during the onCompletion(), the result of the population will be discarded and rescheduled, so that it includes user modifications.
tiles may be deleted in the following circumstances:
1) the target block in the new chunk doesn't expect a tile
2) the target block in the new chunk expects a different type of tile (responsibility of the plugin developer to create the new tile)
3) there's already a tile in the target chunk which conflicts with the old one
In all other cases, the tile will be transferred.
This resolves a large number of unintentional bugs caused by world editors replacing chunks without setting the deleteTilesAndEntities parameter to false (even the core itself does it).
closes#4520
entities exist completely independently from chunks now, so there is no need to interact with them whatsoever.
As I wrote in #4520, there's no sense in deleting entities here, since a chunk replacement is essentially just a mass block update.
On that theme, it might be a good idea to call Entity->onNearbyBlockChange() for all entities in the target and adjacent chunks when replacing a chunk, to ensure that they get the proper movement updates.