Fabric API

Fabric API

106M Downloads

Allow datapacks to work with evolving state properties

kvverti opened this issue ยท 1 comments

commented

The vanilla State<S> codec requires one to specify every property. This means that evolving a block state by adding a property is a breaking change, and also means that mods cannot add properties to vanilla states without breaking data packs that use the blocks. This simple mixin should make the decoder fall back to the corresponding property of the default state if a property is absent.

@Mixin(StateManager.class)
public class StateManagerMixin {

    @Redirect(
        method = "method_30040",
        at = @At(
            value = "INVOKE",
            target = "Lcom/mojang/serialization/Codec;fieldOf(Ljava/lang/String;)Lcom/mojang/serialization/MapCodec;",
            remap = false
        )
    )
    private static <S extends State<?, S>, T extends Comparable<T>> MapCodec<Property.Value<T>> proxyPropertyCodec(
        Codec<Property.Value<T>> codec,
        String name,
        MapCodec<S> accumulatingCodec,
        Supplier<S> defaultState,
        String nameCopy,
        Property<T> property) {
        return Codec.optionalField(name, codec)
            .xmap(
                // fall back to the corresponding properly in the default state
                opt -> opt.orElse(property.createValue(defaultState.get())),
                // always persist, to be compatible with vanilla potentially reading it back in
                Optional::of
            );
    }
}

I give permission for this code to be included or adapted for FAPI under FAPI's license.

commented

This seems out of scope for Fabric, as it's likely to cause various compatibility issues, and require further workarounds.