Skip to content

fix block state mappings being replaced with random blocks - #690

Closed
derekcmoore wants to merge 1 commit into
MCRcortex:263from
derekcmoore:fix/mapping-store-corruption
Closed

derekcmoore wants to merge 1 commit into
MCRcortex:263from
derekcmoore:fix/mapping-store-corruption

Conversation

@derekcmoore

@derekcmoore derekcmoore commented Sep 22, 2026 •

Copy link
Copy Markdown

Every block state in an existing world fails to decode on 26.3, because the block state NBT keys were renamed: StateHolder.NAME_TAG/PROPERTIES_TAG went from Name/Properties to id/properties. The datafixer handles that rename correctly so vanilla blocks come back fine, but anything it cannot resolve, a block from a mod that is no longer installed being the usual case, decodes to air, and loadFromStorage then hands that id a random block state and force-resaves it. The original is gone from disk and reinstalling the mod does not bring it back. I think this is at least part of the CORRUPTS OLD WORLDS marker in 2c5698e, it is the piece I could reproduce.

Entries that cannot be decoded now keep their id but map to nothing and are never written back, so the stored bytes survive and the block returns on its own once it can be resolved again. Dropping that path also drops the block2stateEntry.put(...) inside it, which was overwriting a real entry's state to id mapping whenever the random pick collided with one already in the map.

Three smaller things in the same function: serialize records data_version so the datafixer can start from the right point instead of a hardcoded 0, it writes through FULL_CODEC because BlockState.CODEC on 26.3 collapses a default state down to a bare string and makes the shape on disk vary per state, and the datafixer call is wrapped since it throws rather than returning an error on a type it has no schema for, which is the same crash #670 is aimed at.

Checked with a harness that writes a mapping store in the pre-26.3 format and loads it back through Mapper on 26.3, using somemod:unobtainium_ore as a block whose mod is no longer installed.

Before:

id 6  expected somemod:unobtainium_ore  got minecraft:deepslate_tile_stairs[facing=east,half=bottom,shape=outer_right,waterlogged=false]
type 1 id 6  REWRITTEN  {id:"minecraft:deepslate_tile_stairs",properties:{facing:"east",...}}

After:

id 6  expected somemod:unobtainium_ore  got minecraft:air
id 6 bytes untouched : true
id 6 still says      : {Name:"somemod:unobtainium_ore"}

stone, dirt, short_grass, oak_log[axis=y] and oak_stairs[facing=east,..] round trip to the right state either way. Loading the same store a second time resolves every id identically and leaves the unresolved entry untouched.

@derekcmoore derekcmoore changed the title Stop replacing undecodable block state mappings with random blocks fix block state mappings being replaced with random blocks Sep 22, 2026
@derekcmoore
derekcmoore deleted the fix/mapping-store-corruption branch September 22, 2026 10:36
@derekcmoore

Copy link
Copy Markdown
Author

Closed by a branch rename on my fork, reopened as #691 with the same change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant