From 9b4711b686083da61fba9ef70f452ae02f4b352b Mon Sep 17 00:00:00 2001 From: Rodrigo Farinon Date: Fri, 11 Sep 2026 20:22:44 -0300 Subject: [PATCH] fix: handle DataFixer exceptions when decoding blockstates Prevent Voxy from crashing the game when the DataFixer fails while recovering an invalid or incompatible blockstate. On Minecraft 1.21.1, DataFixer can throw an `IllegalArgumentException` during the `BLOCK_STATE` update, for example when a required type is missing from the registry: ```text java.lang.IllegalArgumentException: Unknown type: block_state ``` This exception bypasses the `DataResult` error handling used by the BlockState codec and can therefore crash the game. The DataFixer update is now wrapped in exception handling, falling back to the original blockstate decode result when the update fails. If the blockstate remains invalid, Voxy continues with its normal behavior, using air for the affected entry instead of propagating the exception. This keeps corrupted or incompatible blockstate data from crashing Voxy during recovery. --- .../cortex/voxy/common/world/other/Mapper.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java index 456248751..709cbdf33 100644 --- a/src/main/java/me/cortex/voxy/common/world/other/Mapper.java +++ b/src/main/java/me/cortex/voxy/common/world/other/Mapper.java @@ -391,9 +391,21 @@ public static StateEntry deserialize(int id, byte[] data, boolean[] forceResave) var bsc = compound.getCompound("block_state").orElseThrow(); var state = BlockState.CODEC.parse(NbtOps.INSTANCE, bsc); if (state.isError()) { + var oldState = state; Logger.info("Could not decode blockstate, attempting fixes, error: "+ state.error().get().message()); - bsc = (CompoundTag) DataFixers.getDataFixer().update(References.BLOCK_STATE, new Dynamic<>(NbtOps.INSTANCE,bsc),0, SharedConstants.getCurrentVersion().dataVersion().version()).getValue(); - state = BlockState.CODEC.parse(NbtOps.INSTANCE, bsc); + // MC 1.21.1: WorldVersion.dataVersion() → getDataVersion(), version() → getVersion() + // Block State Compound CAN fail at version update when a block data type is missing from the game registry, with a java.lang.IllegalArgumentException: Unknown type: block_state being thrown. The following code + // will catch any exception coming from the bsc version update operation, and print it at the screen. When it broke without being catch, the Exception doesn't match the IOException expected, forcing voxy to crash the game. + try { + bsc = (CompoundTag) DataFixers.getDataFixer().update(References.BLOCK_STATE, new Dynamic<>(NbtOps.INSTANCE,bsc),0, SharedConstants.getCurrentVersion().getDataVersion().getVersion()).getValue(); + state = BlockState.CODEC.parse(NbtOps.INSTANCE, bsc); + } catch (IllegalArgumentException e) { + Logger.error("DataFixer could not update blockstate NBT, likely missing registry/type. Maybe a mod was removed? " + "Falling back to original decode result.", e); + state = oldState; + } catch (Exception e) { + Logger.error("Unexpected exception while updating blockstate NBT. " + "Falling back to original decode result. The game may be unstable from now on.", e); + state = oldState; + } if (state.isError()) { Logger.error("Could not decode blockstate setting to air. id:" + id + " error: " + state.error().get().message()); return new StateEntry(id, Blocks.AIR.defaultBlockState());