Replace blockLayers array with individual blockLayer and liquidLayer fields.
Update constructor and all usages throughout the codebase.
Deprecate getBlockLayers() method for backward compatibility.
having them be clean by default makes no sense. It only makes sense for them to be clean if they were loaded directly from disk without any alterations.
Default clean is a footgun.
This commit completely revamps the way that blocks are represented in memory at runtime.
Instead of being represented by legacy Mojang block IDs and metadata, which are dated, limited and unchangeable, we now use custom PM block IDs, which are generated from VanillaBlocks.
This means we have full control of how they are assigned, which opens the doors to finally addressing inconsistencies like glazed terracotta, stripped logs handling, etc.
To represent state, BlockDataReader and BlockDataWriter have been introduced, and are used by blocks with state information to pack said information into a binary form that can be stored on a chunk at runtime.
Conceptually it's pretty similar to legacy metadata, but the actual format shares no resemblance whatsoever to legacy metadata, and is fully controlled by PM.
This means that the 'state data' may change in serialization format at any time, so it should **NOT** be stored on disk or in a config.
In the future, this will be improved using more auto-generated code and attributes, instead of hand-baked decodeState() and encodeState(). For now, this opens the gateway to a significant expansion of features.
It's not ideal, but it's a big step forwards.
This reverts commit a5418a019dc2a83210084632130db8ce06f529ea.
The more I assessed this, the more I realized that this implementation
doesn't actually offer any value. Since modcounters don't persist after
chunk unload + reload, they can't be reliably used to detect changes in
chunks without additional event subscriptions.
For the purpose I actually intended to use them for (population task
cancellation) there's a) another solution, and b) modcounts are
unreliable for that too, because of the aforementioned potential for
chunks to get unloaded and reloaded.
For the case of detecting dirty chunks within PopulationTask itself,
they are also unnecessary, since the dirty flags are sufficient within
there, since FastChunkSerializer doesn't copy dirty flags.
In conclusion, this was a misbegotten addition with little real value,
but does impact performance in hot paths.
setPopulated() sets dirty flags on the chunk, causing the autosave sweep
to think they've been changed when they haven't. We now pass
terrainPopulated to the constructor to avoid this ambiguity recurring in
the future.
this allows entities to exist outside of generated chunks, with one caveat: they won't be saved in such cases.
Obviously, for player entities, this doesn't matter.
fixes#3947
instead, just ungate this and allow the provider to decide what to do.
Any chunk that contains entities or tiles is already always considered dirty, so the only thing the flags are good for is flagging chunks that previously had tiles and/or entities but no longer do.
In those cases, it's just removing keys from LevelDB anyway, so it's already very cheap.
Avoiding these redundant deletions is not worth the extra complexity and fragility of relying on flags to track this stuff.
a non-generated chunk is now always represented by NULL. This forces the case of ungenerated chunks to be handled by all code, which is necessary because ungenerated chunks cannot be interacted with or modified in any meaningful way.