Fixes https://github.com/FabricMC/fabric/issues/3669

Co-authored-by: Drex <nicknamedrex@gmail.com>
This commit is contained in:
modmuss 2024-03-27 19:26:14 +00:00 committed by GitHub
parent e78eae2df0
commit b21c00cb44
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 145 additions and 132 deletions
fabric-biome-api-v1/src/main/java/net/fabricmc/fabric/mixin/biome
fabric-convention-tags-v1/src/generated/resources/data/c/tags/items
fabric-data-attachment-api-v1/src/main/java/net/fabricmc/fabric
fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric
fabric-dimensions-v1/src
main/java/net/fabricmc/fabric
testmod/java/net/fabricmc/fabric/test/dimension
fabric-loot-api-v2/src/testmod/java/net/fabricmc/fabric/test/loot
fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric
api/object/builder/v1/entity
impl/object/builder
fabric-particles-v1/src/main/java/net/fabricmc/fabric/api/particle/v1
fabric-recipe-api-v1/src
main/java/net/fabricmc/fabric
testmod/java/net/fabricmc/fabric/test/recipe/ingredient
fabric-renderer-api-v1/src/client/java/net/fabricmc/fabric/mixin/renderer/client
fabric-rendering-v1/src/testmodClient/java/net/fabricmc/fabric/test/rendering/client
fabric-screen-handler-api-v1/src/main/java/net/fabricmc/fabric/impl/screenhandler
fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric
api/transfer/v1/storage/base
impl/transfer
fabric-transitive-access-wideners-v1
gradle.properties

View file

@ -22,7 +22,7 @@ import java.util.Set;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@ -49,7 +49,7 @@ public class TheEndBiomeSourceMixin extends BiomeSourceMixin {
@Shadow
@Mutable
@Final
static Codec<TheEndBiomeSource> CODEC;
static MapCodec<TheEndBiomeSource> CODEC;
@Unique
private Supplier<TheEndBiomeData.Overrides> overrides;
@ -66,7 +66,7 @@ public class TheEndBiomeSourceMixin extends BiomeSourceMixin {
*/
@Inject(method = "<clinit>", at = @At("TAIL"))
private static void modifyCodec(CallbackInfo ci) {
CODEC = RecordCodecBuilder.create((instance) -> {
CODEC = RecordCodecBuilder.mapCodec((instance) -> {
return instance.group(RegistryOps.getEntryLookupCodec(RegistryKeys.BIOME)).apply(instance, instance.stable(TheEndBiomeSource::createVanilla));
});
}

View file

@ -39,6 +39,7 @@
"minecraft:suspicious_stew",
"minecraft:sweet_berries",
"minecraft:glow_berries",
"minecraft:honey_bottle"
"minecraft:honey_bottle",
"minecraft:ominous_bottle"
]
}

View file

@ -52,12 +52,11 @@ public class AttachmentSerializingImpl {
if (codec != null) {
RegistryOps<NbtElement> registryOps = wrapperLookup.getOps(NbtOps.INSTANCE);
codec.encodeStart(registryOps, entry.getValue())
.get()
.ifRight(partial -> {
.ifError(partial -> {
LOGGER.warn("Couldn't serialize attachment " + type.identifier() + ", skipping. Error:");
LOGGER.warn(partial.message());
})
.ifLeft(serialized -> compound.put(type.identifier().toString(), serialized));
.ifSuccess(serialized -> compound.put(type.identifier().toString(), serialized));
}
}
@ -83,12 +82,11 @@ public class AttachmentSerializingImpl {
if (codec != null) {
RegistryOps<NbtElement> registryOps = wrapperLookup.getOps(NbtOps.INSTANCE);
codec.parse(registryOps, compound.get(key))
.get()
.ifRight(partial -> {
.ifError(partial -> {
LOGGER.warn("Couldn't deserialize attachment " + type.identifier() + ", skipping. Error:");
LOGGER.warn(partial.message());
})
.ifLeft(
.ifSuccess(
deserialized -> attachments.put(type, deserialized)
);
}

View file

@ -31,7 +31,7 @@ import net.fabricmc.fabric.impl.attachment.AttachmentTargetImpl;
abstract class BlockEntityMixin implements AttachmentTargetImpl {
@Inject(
method = "method_17897", // lambda body in BlockEntity#createFromNbt
at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;readNbt(Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)V")
at = @At(value = "INVOKE", target = "Lnet/minecraft/block/entity/BlockEntity;method_58690(Lnet/minecraft/nbt/NbtCompound;Lnet/minecraft/registry/RegistryWrapper$WrapperLookup;)V")
)
private static void readBlockEntityAttachments(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup, String string, BlockEntity blockEntity, CallbackInfoReturnable<BlockEntity> cir) {
((AttachmentTargetImpl) blockEntity).fabric_readAttachmentsFromNbt(nbt, wrapperLookup);

View file

@ -37,7 +37,6 @@ import net.minecraft.data.DataWriter;
import net.minecraft.registry.RegistryOps;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
@ -94,7 +93,7 @@ public abstract class FabricAdvancementProvider implements DataProvider {
throw new IllegalStateException("Duplicate advancement " + advancement.id());
}
JsonObject advancementJson = Util.getResult(Advancement.CODEC.encodeStart(ops, advancement.value()), IllegalStateException::new).getAsJsonObject();
JsonObject advancementJson = Advancement.CODEC.encodeStart(ops, advancement.value()).getOrThrow(IllegalStateException::new).getAsJsonObject();
ConditionJsonProvider.write(advancementJson, FabricDataGenHelper.consumeConditions(advancement));
futures.add(DataProvider.writeToPath(writer, advancementJson, getOutputPath(advancement)));
}

View file

@ -84,9 +84,9 @@ public abstract class FabricCodecDataProvider<T> implements DataProvider {
private JsonElement convert(Identifier id, T value, DynamicOps<JsonElement> ops) {
DataResult<JsonElement> dataResult = this.codec.encodeStart(ops, value);
return dataResult.get()
.mapRight(partial -> "Invalid entry %s: %s".formatted(id, partial.message()))
.orThrow();
return dataResult
.mapError(message -> "Invalid entry %s: %s".formatted(id, message))
.getOrThrow();
}
private CompletableFuture<?> write(DataWriter writer, Map<Identifier, JsonElement> entries) {

View file

@ -41,7 +41,6 @@ import net.minecraft.recipe.Recipe;
import net.minecraft.registry.RegistryOps;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
@ -100,14 +99,14 @@ public abstract class FabricRecipeProvider extends RecipeProvider {
}
RegistryOps<JsonElement> registryOps = wrapperLookup.getOps(JsonOps.INSTANCE);
JsonObject recipeJson = Util.getResult(Recipe.CODEC.encodeStart(registryOps, recipe), IllegalStateException::new).getAsJsonObject();
JsonObject recipeJson = Recipe.CODEC.encodeStart(registryOps, recipe).getOrThrow(IllegalStateException::new).getAsJsonObject();
ConditionJsonProvider[] conditions = FabricDataGenHelper.consumeConditions(recipe);
ConditionJsonProvider.write(recipeJson, conditions);
list.add(DataProvider.writeToPath(writer, recipeJson, recipesPathResolver.resolveJson(identifier)));
if (advancement != null) {
JsonObject advancementJson = Util.getResult(Advancement.CODEC.encodeStart(registryOps, advancement.value()), IllegalStateException::new).getAsJsonObject();
JsonObject advancementJson = Advancement.CODEC.encodeStart(registryOps, advancement.value()).getOrThrow(IllegalStateException::new).getAsJsonObject();
ConditionJsonProvider.write(advancementJson, conditions);
list.add(DataProvider.writeToPath(writer, advancementJson, advancementsPathResolver.resolveJson(getRecipeIdentifier(advancement.id()))));
}

View file

@ -36,7 +36,6 @@ import net.minecraft.loot.context.LootContextType;
import net.minecraft.registry.RegistryOps;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider;
@ -72,7 +71,7 @@ public final class FabricLootTableProviderImpl {
final List<CompletableFuture<?>> futures = new ArrayList<>();
for (Map.Entry<Identifier, LootTable> entry : builders.entrySet()) {
JsonObject tableJson = (JsonObject) Util.getResult(LootTable.CODEC.encodeStart(ops, entry.getValue()), IllegalStateException::new);
JsonObject tableJson = (JsonObject) LootTable.CODEC.encodeStart(ops, entry.getValue()).getOrThrow(IllegalStateException::new);
ConditionJsonProvider.write(tableJson, conditionMap.remove(entry.getKey()));
futures.add(DataProvider.writeToPath(writer, tableJson, getOutputPath(fabricDataOutput, entry.getKey())));
}

View file

@ -17,6 +17,7 @@
package net.fabricmc.fabric.impl.dimension;
import java.util.Map;
import java.util.Optional;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
@ -65,15 +66,19 @@ public record FailSoftMapCodec<K, V>(Codec<K> keyCodec, Codec<V> elementCodec) i
final DataResult<K> k = keyCodec().parse(ops, pair.getFirst());
final DataResult<V> v = elementCodec().parse(ops, pair.getSecond());
k.get().ifRight(kPartialResult -> {
LOGGER.error("Failed to decode key {} from {} {}", k, pair, kPartialResult);
});
v.get().ifRight(vPartialResult -> {
LOGGER.error("Failed to decode value {} from {} {}", v, pair, vPartialResult);
});
Optional<K> optionalK = k.result();
Optional<V> optionalV = v.result();
if (k.get().left().isPresent() && v.get().left().isPresent()) {
builder.put(k.get().left().get(), v.get().left().get());
if (optionalK.isEmpty()) {
LOGGER.error("Failed to decode key {} from {} {}", k, pair, k.resultOrPartial());
}
if (optionalV.isEmpty()) {
LOGGER.error("Failed to decode value {} from {} {}", k, pair, v.resultOrPartial());
}
if (optionalK.isPresent() && optionalV.isPresent()) {
builder.put(optionalK.get(), optionalV.get());
} else {
// ignore failure
}

View file

@ -51,7 +51,7 @@ public class TaggedChoiceTypeMixin<K> implements TaggedChoiceTypeExtension {
* This will avoid deserialization failure from DFU when upgrading level.dat that contains mod custom generator types.
*/
@Inject(
method = "getCodec", at = @At("HEAD"), cancellable = true, remap = false
method = "getMapCodec", at = @At("HEAD"), cancellable = true, remap = false
)
private void onGetCodec(K k, CallbackInfoReturnable<DataResult<? extends Codec<?>>> cir) {
if (failSoft) {

View file

@ -20,7 +20,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BlockState;
@ -44,7 +44,7 @@ import net.minecraft.world.gen.chunk.VerticalBlockSample;
import net.minecraft.world.gen.noise.NoiseConfig;
public class VoidChunkGenerator extends ChunkGenerator {
public static final Codec<VoidChunkGenerator> CODEC = RecordCodecBuilder.create((instance) ->
public static final MapCodec<VoidChunkGenerator> CODEC = RecordCodecBuilder.mapCodec((instance) ->
instance.group(RegistryOps.getEntryLookupCodec(RegistryKeys.BIOME))
.apply(instance, instance.stable(VoidChunkGenerator::new)));
@ -53,7 +53,7 @@ public class VoidChunkGenerator extends ChunkGenerator {
}
@Override
protected Codec<? extends ChunkGenerator> getCodec() {
protected MapCodec<? extends ChunkGenerator> getCodec() {
return CODEC;
}

View file

@ -75,7 +75,7 @@ public class LootTest implements ModInitializer {
LootPool pool = LootPool.builder()
.with(ItemEntry.builder(Items.GOLD_INGOT).build())
.conditionally(SurvivesExplosionLootCondition.builder().build())
.apply(SetNameLootFunction.builder(Text.literal("Gold from White Wool")).build())
.apply(SetNameLootFunction.builder(Text.literal("Gold from White Wool"), SetNameLootFunction.class_9475.CUSTOM_NAME).build())
.build();
tableBuilder.pool(pool);

View file

@ -275,7 +275,8 @@ public class FabricEntityTypeBuilder<T extends Entity> {
public EntityType<T> build() {
// Modded DFU is a dream, currently not possible without screwing it up.
return new FabricEntityType<>(this.factory, this.spawnGroup, this.saveable, this.summonable, this.fireImmune, this.spawnableFarFromPlayer, this.specificSpawnBlocks, dimensions, trackRange, trackedUpdateRate, forceTrackedVelocityUpdates, this.requiredFeatures);
//TODO 1.20.5, new field
return new FabricEntityType<>(this.factory, this.spawnGroup, this.saveable, this.summonable, this.fireImmune, this.spawnableFarFromPlayer, this.specificSpawnBlocks, dimensions, 1, trackRange, trackedUpdateRate, forceTrackedVelocityUpdates, this.requiredFeatures);
}
/**

View file

@ -28,8 +28,8 @@ import net.minecraft.resource.featuretoggle.FeatureSet;
public class FabricEntityType<T extends Entity> extends EntityType<T> {
private final Boolean alwaysUpdateVelocity;
public FabricEntityType(EntityType.EntityFactory<T> factory, SpawnGroup spawnGroup, boolean bl, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet<Block> spawnBlocks, EntityDimensions entityDimensions, int maxTrackDistance, int trackTickInterval, Boolean alwaysUpdateVelocity, FeatureSet featureSet) {
super(factory, spawnGroup, bl, summonable, fireImmune, spawnableFarFromPlayer, spawnBlocks, entityDimensions, maxTrackDistance, trackTickInterval, featureSet);
public FabricEntityType(EntityType.EntityFactory<T> factory, SpawnGroup spawnGroup, boolean bl, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet<Block> spawnBlocks, EntityDimensions entityDimensions, float field_50125, int maxTrackDistance, int trackTickInterval, Boolean alwaysUpdateVelocity, FeatureSet featureSet) {
super(factory, spawnGroup, bl, summonable, fireImmune, spawnableFarFromPlayer, spawnBlocks, entityDimensions, field_50125, maxTrackDistance, trackTickInterval, featureSet);
this.alwaysUpdateVelocity = alwaysUpdateVelocity;
}

View file

@ -19,6 +19,7 @@ package net.fabricmc.fabric.api.particle.v1;
import java.util.function.Function;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
@ -69,7 +70,7 @@ public final class FabricParticleTypes {
* @param codec The codec for serialization.
* @param packetCodec The packet codec for network serialization.
*/
public static <T extends ParticleEffect> ParticleType<T> complex(ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, Codec<T>> codecGetter, final Codec<T> codec, final PacketCodec<? super RegistryByteBuf, T> packetCodec) {
public static <T extends ParticleEffect> ParticleType<T> complex(ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, Codec<T>> codecGetter, final MapCodec<T> codec, final PacketCodec<? super RegistryByteBuf, T> packetCodec) {
return complex(false, factory, codec, packetCodec);
}
@ -81,10 +82,10 @@ public final class FabricParticleTypes {
* @param codec The codec for serialization.
* @param packetCodec The packet codec for network serialization.
*/
public static <T extends ParticleEffect> ParticleType<T> complex(boolean alwaysSpawn, ParticleEffect.Factory<T> factory, final Codec<T> codec, final PacketCodec<? super RegistryByteBuf, T> packetCodec) {
public static <T extends ParticleEffect> ParticleType<T> complex(boolean alwaysSpawn, ParticleEffect.Factory<T> factory, final MapCodec<T> codec, final PacketCodec<? super RegistryByteBuf, T> packetCodec) {
return new ParticleType<T>(alwaysSpawn, factory) {
@Override
public Codec<T> getCodec() {
public MapCodec<T> getCodec() {
return codec;
}
@ -103,7 +104,7 @@ public final class FabricParticleTypes {
* @param codecGetter A function that, given the newly created type, returns the codec for serialization.
* @param packetCodecGetter A function that, given the newly created type, returns the packet codec for network serialization.
*/
public static <T extends ParticleEffect> ParticleType<T> complex(ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, Codec<T>> codecGetter, final Function<ParticleType<T>, PacketCodec<? super RegistryByteBuf, T>> packetCodecGetter) {
public static <T extends ParticleEffect> ParticleType<T> complex(ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, MapCodec<T>> codecGetter, final Function<ParticleType<T>, PacketCodec<? super RegistryByteBuf, T>> packetCodecGetter) {
return complex(false, factory, codecGetter, packetCodecGetter);
}
@ -116,10 +117,10 @@ public final class FabricParticleTypes {
* @param codecGetter A function that, given the newly created type, returns the codec for serialization.
* @param packetCodecGetter A function that, given the newly created type, returns the packet codec for network serialization.
*/
public static <T extends ParticleEffect> ParticleType<T> complex(boolean alwaysSpawn, ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, Codec<T>> codecGetter, final Function<ParticleType<T>, PacketCodec<? super RegistryByteBuf, T>> packetCodecGetter) {
public static <T extends ParticleEffect> ParticleType<T> complex(boolean alwaysSpawn, ParticleEffect.Factory<T> factory, final Function<ParticleType<T>, MapCodec<T>> codecGetter, final Function<ParticleType<T>, PacketCodec<? super RegistryByteBuf, T>> packetCodecGetter) {
return new ParticleType<T>(alwaysSpawn, factory) {
@Override
public Codec<T> getCodec() {
public MapCodec<T> getCodec() {
return codecGetter.apply(this);
}

View file

@ -16,7 +16,7 @@
package net.fabricmc.fabric.api.recipe.v1.ingredient;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import org.jetbrains.annotations.Nullable;
import net.minecraft.network.RegistryByteBuf;
@ -64,7 +64,7 @@ public interface CustomIngredientSerializer<T extends CustomIngredient> {
* @see Ingredient#ALLOW_EMPTY_CODEC
* @see Ingredient#DISALLOW_EMPTY_CODEC
*/
Codec<T> getCodec(boolean allowEmpty);
MapCodec<T> getCodec(boolean allowEmpty);
/**
* {@return the packet codec for serializing this ingredient}.

View file

@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.List;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
@ -29,15 +30,14 @@ import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
public class AllIngredient extends CombinedIngredient {
private static final Codec<AllIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final Codec<AllIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final MapCodec<AllIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final MapCodec<AllIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static Codec<AllIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
private static MapCodec<AllIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return ingredientCodec
.listOf()
.fieldOf("ingredients")
.xmap(AllIngredient::new, AllIngredient::getIngredients)
.codec();
.xmap(AllIngredient::new, AllIngredient::getIngredients);
}
public static final CustomIngredientSerializer<AllIngredient> SERIALIZER =

View file

@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.List;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.Ingredient;
@ -29,15 +30,14 @@ import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
public class AnyIngredient extends CombinedIngredient {
private static final Codec<AnyIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final Codec<AnyIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final MapCodec<AnyIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final MapCodec<AnyIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static Codec<AnyIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
private static MapCodec<AnyIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return ingredientCodec
.listOf()
.fieldOf("ingredients")
.xmap(AnyIngredient::new, AnyIngredient::getIngredients)
.codec();
.xmap(AnyIngredient::new, AnyIngredient::getIngredients);
}
public static final CustomIngredientSerializer<AnyIngredient> SERIALIZER =

View file

@ -19,7 +19,7 @@ package net.fabricmc.fabric.impl.recipe.ingredient.builtin;
import java.util.List;
import java.util.function.Function;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
@ -61,11 +61,11 @@ abstract class CombinedIngredient implements CustomIngredient {
static class Serializer<I extends CombinedIngredient> implements CustomIngredientSerializer<I> {
private final Identifier identifier;
private final Codec<I> allowEmptyCodec;
private final Codec<I> disallowEmptyCodec;
private final MapCodec<I> allowEmptyCodec;
private final MapCodec<I> disallowEmptyCodec;
private final PacketCodec<RegistryByteBuf, I> packetCodec;
Serializer(Identifier identifier, Function<List<Ingredient>, I> factory, Codec<I> allowEmptyCodec, Codec<I> disallowEmptyCodec) {
Serializer(Identifier identifier, Function<List<Ingredient>, I> factory, MapCodec<I> allowEmptyCodec, MapCodec<I> disallowEmptyCodec) {
this.identifier = identifier;
this.allowEmptyCodec = allowEmptyCodec;
this.disallowEmptyCodec = disallowEmptyCodec;
@ -79,7 +79,7 @@ abstract class CombinedIngredient implements CustomIngredient {
}
@Override
public Codec<I> getCodec(boolean allowEmpty) {
public MapCodec<I> getCodec(boolean allowEmpty) {
return allowEmpty ? allowEmptyCodec : disallowEmptyCodec;
}

View file

@ -23,6 +23,7 @@ import java.util.Objects;
import java.util.Optional;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.jetbrains.annotations.Nullable;
@ -116,16 +117,16 @@ public class ComponentsIngredient implements CustomIngredient {
private static class Serializer implements CustomIngredientSerializer<ComponentsIngredient> {
private static final Identifier ID = new Identifier("fabric", "components");
private static final Codec<ComponentsIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final Codec<ComponentsIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final MapCodec<ComponentsIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final MapCodec<ComponentsIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final PacketCodec<RegistryByteBuf, ComponentsIngredient> PACKET_CODEC = PacketCodec.tuple(
Ingredient.PACKET_CODEC, ComponentsIngredient::getBase,
ComponentChanges.PACKET_CODEC, ComponentsIngredient::getComponents,
ComponentsIngredient::new
);
private static Codec<ComponentsIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.create(instance ->
private static MapCodec<ComponentsIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.mapCodec(instance ->
instance.group(
ingredientCodec.fieldOf("base").forGetter(ComponentsIngredient::getBase),
ComponentChanges.CODEC.fieldOf("components").forGetter(ComponentsIngredient::getComponents)
@ -139,7 +140,7 @@ public class ComponentsIngredient implements CustomIngredient {
}
@Override
public Codec<ComponentsIngredient> getCodec(boolean allowEmpty) {
public MapCodec<ComponentsIngredient> getCodec(boolean allowEmpty) {
return allowEmpty ? ALLOW_EMPTY_CODEC : DISALLOW_EMPTY_CODEC;
}

View file

@ -23,6 +23,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.component.DataComponentTypes;
@ -35,7 +36,6 @@ import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.recipe.Ingredient;
import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.Codecs;
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredient;
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer;
@ -95,7 +95,7 @@ public class CustomDataIngredient implements CustomIngredient {
private static final Identifier ID = new Identifier("fabric", "custom_data");
// Supports decoding the NBT as a string as well as the object.
private static final Codec<NbtCompound> NBT_CODEC = Codecs.xor(
private static final Codec<NbtCompound> NBT_CODEC = Codec.xor(
Codec.STRING, NbtCompound.CODEC
).flatXmap(either -> either.map(s -> {
try {
@ -105,8 +105,8 @@ public class CustomDataIngredient implements CustomIngredient {
}
}, DataResult::success), nbtCompound -> DataResult.success(Either.left(nbtCompound.asString())));
private static final Codec<CustomDataIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final Codec<CustomDataIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final MapCodec<CustomDataIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final MapCodec<CustomDataIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final PacketCodec<RegistryByteBuf, CustomDataIngredient> PACKET_CODEC = PacketCodec.tuple(
Ingredient.PACKET_CODEC, CustomDataIngredient::getBase,
@ -114,8 +114,8 @@ public class CustomDataIngredient implements CustomIngredient {
CustomDataIngredient::new
);
private static Codec<CustomDataIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.create(instance ->
private static MapCodec<CustomDataIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.mapCodec(instance ->
instance.group(
ingredientCodec.fieldOf("base").forGetter(CustomDataIngredient::getBase),
NBT_CODEC.fieldOf("nbt").forGetter(CustomDataIngredient::getNbt)
@ -129,7 +129,7 @@ public class CustomDataIngredient implements CustomIngredient {
}
@Override
public Codec<CustomDataIngredient> getCodec(boolean allowEmpty) {
public MapCodec<CustomDataIngredient> getCodec(boolean allowEmpty) {
return allowEmpty ? ALLOW_EMPTY_CODEC : DISALLOW_EMPTY_CODEC;
}

View file

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.item.ItemStack;
@ -74,16 +75,16 @@ public class DifferenceIngredient implements CustomIngredient {
private static class Serializer implements CustomIngredientSerializer<DifferenceIngredient> {
private static final Identifier ID = new Identifier("fabric", "difference");
private static final Codec<DifferenceIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final Codec<DifferenceIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final MapCodec<DifferenceIngredient> ALLOW_EMPTY_CODEC = createCodec(Ingredient.ALLOW_EMPTY_CODEC);
private static final MapCodec<DifferenceIngredient> DISALLOW_EMPTY_CODEC = createCodec(Ingredient.DISALLOW_EMPTY_CODEC);
private static final PacketCodec<RegistryByteBuf, DifferenceIngredient> PACKET_CODEC = PacketCodec.tuple(
Ingredient.PACKET_CODEC, DifferenceIngredient::getBase,
Ingredient.PACKET_CODEC, DifferenceIngredient::getSubtracted,
DifferenceIngredient::new
);
private static Codec<DifferenceIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.create(instance ->
private static MapCodec<DifferenceIngredient> createCodec(Codec<Ingredient> ingredientCodec) {
return RecordCodecBuilder.mapCodec(instance ->
instance.group(
ingredientCodec.fieldOf("base").forGetter(DifferenceIngredient::getBase),
ingredientCodec.fieldOf("subtracted").forGetter(DifferenceIngredient::getSubtracted)
@ -97,7 +98,7 @@ public class DifferenceIngredient implements CustomIngredient {
}
@Override
public Codec<DifferenceIngredient> getCodec(boolean allowEmpty) {
public MapCodec<DifferenceIngredient> getCodec(boolean allowEmpty) {
return allowEmpty ? ALLOW_EMPTY_CODEC : DISALLOW_EMPTY_CODEC;
}

View file

@ -27,7 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.recipe.Ingredient;
import net.minecraft.util.dynamic.Codecs;
import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredient;
import net.fabricmc.fabric.api.recipe.v1.ingredient.FabricIngredient;
@ -43,7 +42,7 @@ public class IngredientMixin implements FabricIngredient {
CustomIngredient::getSerializer,
serializer -> serializer.getCodec(allowEmpty));
cir.setReturnValue(Codecs.either(customIngredientCodec, cir.getReturnValue()).xmap(
cir.setReturnValue(Codec.either(customIngredientCodec, cir.getReturnValue()).xmap(
either -> either.map(CustomIngredient::toVanilla, ingredient -> ingredient),
ingredient -> {
CustomIngredient customIngredient = ingredient.getCustomIngredient();

View file

@ -30,7 +30,6 @@ import net.minecraft.recipe.Ingredient;
import net.minecraft.test.GameTest;
import net.minecraft.test.GameTestException;
import net.minecraft.test.TestContext;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
import net.fabricmc.fabric.api.recipe.v1.ingredient.DefaultCustomIngredients;
@ -58,7 +57,7 @@ public class SerializationTests {
JsonElement json = JsonParser.parseString(ingredientJson);
try {
Util.getResult(Ingredient.DISALLOW_EMPTY_CODEC.parse(JsonOps.INSTANCE, json), JsonParseException::new);
Ingredient.DISALLOW_EMPTY_CODEC.parse(JsonOps.INSTANCE, json).getOrThrow(JsonParseException::new);
throw new GameTestException("Using a custom ingredient inside an array ingredient should have failed.");
} catch (JsonParseException e) {
context.complete();
@ -79,12 +78,10 @@ public class SerializationTests {
Ingredient.ofItems(Items.STONE)
);
Codec<Ingredient> ingredientCodec = allowEmpty ? Ingredient.ALLOW_EMPTY_CODEC : Ingredient.DISALLOW_EMPTY_CODEC;
JsonObject json = Util.getResult(ingredientCodec.encodeStart(JsonOps.INSTANCE, ingredient), IllegalStateException::new).getAsJsonObject();
JsonObject json = ingredientCodec.encodeStart(JsonOps.INSTANCE, ingredient).getOrThrow(IllegalStateException::new).getAsJsonObject();
context.assertTrue(json.toString().equals(ingredientJson), "Unexpected json: " + json);
// Make sure that we can deserialize it
Ingredient deserialized = Util.getResult(
ingredientCodec.parse(JsonOps.INSTANCE, json), JsonParseException::new
);
Ingredient deserialized = ingredientCodec.parse(JsonOps.INSTANCE, json).getOrThrow(JsonParseException::new);
context.assertTrue(deserialized.getCustomIngredient() != null, "Custom ingredient was not deserialized");
context.assertTrue(deserialized.getCustomIngredient().getSerializer() == ingredient.getCustomIngredient().getSerializer(), "Serializer did not match");
}

View file

@ -54,7 +54,7 @@ public class WeightedBakedModelMixin implements FabricBakedModel {
@Inject(at = @At("RETURN"), method = "<init>")
private void onInit(List<Weighted.Present<BakedModel>> models, CallbackInfo cb) {
for (int i = 0; i < models.size(); i++) {
if (!models.get(i).getData().isVanillaAdapter()) {
if (!models.get(i).data().isVanillaAdapter()) {
isVanilla = false;
break;
}
@ -71,7 +71,7 @@ public class WeightedBakedModelMixin implements FabricBakedModel {
Weighted.Present<BakedModel> selected = Weighting.getAt(this.models, Math.abs((int) randomSupplier.get().nextLong()) % this.totalWeight).orElse(null);
if (selected != null) {
selected.getData().emitBlockQuads(blockView, state, pos, () -> {
selected.data().emitBlockQuads(blockView, state, pos, () -> {
Random random = randomSupplier.get();
random.nextLong(); // Imitate vanilla modifying the random before passing it to the submodel
return random;
@ -84,7 +84,7 @@ public class WeightedBakedModelMixin implements FabricBakedModel {
Weighted.Present<BakedModel> selected = Weighting.getAt(this.models, Math.abs((int) randomSupplier.get().nextLong()) % this.totalWeight).orElse(null);
if (selected != null) {
selected.getData().emitItemQuads(stack, () -> {
selected.data().emitItemQuads(stack, () -> {
Random random = randomSupplier.get();
random.nextLong(); // Imitate vanilla modifying the random before passing it to the submodel
return random;

View file

@ -21,7 +21,7 @@ import java.io.InputStream;
import java.util.Optional;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import org.slf4j.Logger;
@ -49,7 +49,7 @@ public class CustomAtlasSourcesTest implements ClientModInitializer {
private static class DoubleAtlasSource implements AtlasSource {
private static final Logger LOGGER = LogUtils.getLogger();
public static final Codec<DoubleAtlasSource> CODEC = RecordCodecBuilder.create(instance -> instance.group(
public static final MapCodec<DoubleAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Identifier.CODEC.fieldOf("resource").forGetter(source -> source.resource),
Identifier.CODEC.fieldOf("sprite").forGetter(source -> source.sprite)
).apply(instance, DoubleAtlasSource::new));

View file

@ -19,6 +19,7 @@ package net.fabricmc.fabric.impl.screenhandler;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -27,6 +28,7 @@ import net.minecraft.network.RegistryByteBuf;
import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.packet.CustomPayload;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
@ -81,13 +83,25 @@ public final class Networking implements ModInitializer {
@Override
public void onInitialize() {
PayloadTypeRegistry.playS2C().register(OpenScreenPayload.ID, OpenScreenPayload.CODEC);
RegistryEntryAddedCallback.event(Registries.SCREEN_HANDLER).register((rawId, id, type) -> {
forEachEntry(Registries.SCREEN_HANDLER, (type, id) -> {
if (type instanceof ExtendedScreenHandlerType<?, ?> extended) {
CODEC_BY_ID.put(id, extended.getPacketCodec());
}
});
}
// Calls the consumer for each registry entry that has been registered or will be registered.
private static <T> void forEachEntry(Registry<T> registry, BiConsumer<T, Identifier> consumer) {
for (T type : registry) {
consumer.accept(type, registry.getId(type));
}
RegistryEntryAddedCallback.event(registry).register((rawId, id, type) -> {
consumer.accept(type, id);
});
}
public record OpenScreenPayload<D>(Identifier identifier, int syncId, Text title, PacketCodec<RegistryByteBuf, D> innerCodec, D data) implements CustomPayload {
public static final PacketCodec<RegistryByteBuf, OpenScreenPayload<?>> CODEC = CustomPayload.codecOf(OpenScreenPayload::write, OpenScreenPayload::fromBuf);
public static final CustomPayload.Id<OpenScreenPayload<?>> ID = new Id<>(OPEN_ID);

View file

@ -28,7 +28,6 @@ import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.registry.RegistryOps;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Util;
import net.fabricmc.fabric.api.transfer.v1.storage.StoragePreconditions;
import net.fabricmc.fabric.api.transfer.v1.storage.TransferVariant;
@ -198,7 +197,7 @@ public abstract class SingleVariantStorage<T extends TransferVariant<?>> extends
*/
public static <T extends TransferVariant<?>> void writeNbt(SingleVariantStorage<T> storage, Codec<T> codec, NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
final RegistryOps<NbtElement> ops = wrapperLookup.getOps(NbtOps.INSTANCE);
nbt.put("variant", Util.getResult(codec.encodeStart(ops, storage.variant), RuntimeException::new));
nbt.put("variant", codec.encode(storage.variant, ops, nbt).getOrThrow(RuntimeException::new));
nbt.putLong("amount", storage.amount);
}
}

View file

@ -25,7 +25,6 @@ import net.minecraft.network.codec.PacketCodec;
import net.minecraft.network.codec.PacketCodecs;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.dynamic.Codecs;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
@ -35,7 +34,7 @@ import net.fabricmc.fabric.impl.transfer.item.ItemVariantImpl;
public class VariantCodecs {
public static final Codec<ItemVariant> ITEM_CODEC = RecordCodecBuilder.create(instance -> instance.group(
Registries.ITEM.getEntryCodec().fieldOf("item").forGetter(ItemVariant::getRegistryEntry),
Codecs.createStrictOptionalFieldCodec(ComponentChanges.CODEC, "components", ComponentChanges.EMPTY).forGetter(ItemVariant::getComponents)
ComponentChanges.CODEC.optionalFieldOf("components", ComponentChanges.EMPTY).forGetter(ItemVariant::getComponents)
).apply(instance, ItemVariantImpl::of)
);
public static final PacketCodec<RegistryByteBuf, ItemVariant> ITEM_PACKET_CODEC = PacketCodec.tuple(
@ -46,7 +45,7 @@ public class VariantCodecs {
public static final Codec<FluidVariant> FLUID_CODEC = RecordCodecBuilder.create(instance -> instance.group(
Registries.FLUID.getEntryCodec().fieldOf("fluid").forGetter(FluidVariant::getRegistryEntry),
Codecs.createStrictOptionalFieldCodec(ComponentChanges.CODEC, "components", ComponentChanges.EMPTY).forGetter(FluidVariant::getComponents)
ComponentChanges.CODEC.optionalFieldOf("components", ComponentChanges.EMPTY).forGetter(FluidVariant::getComponents)
).apply(instance, FluidVariantImpl::of)
);
public static final PacketCodec<RegistryByteBuf, FluidVariant> FLUID_PACKET_CODEC = PacketCodec.tuple(

View file

@ -102,7 +102,7 @@ transitive-accessible method net/minecraft/sound/SoundEvent of (Lnet/minecraft/u
transitive-accessible method net/minecraft/sound/SoundEvent of (Lnet/minecraft/util/Identifier;)Lnet/minecraft/sound/SoundEvent;
# Creating BlockStateProviderTypes
transitive-accessible method net/minecraft/world/gen/stateprovider/BlockStateProviderType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/stateprovider/BlockStateProviderType <init> (Lcom/mojang/serialization/MapCodec;)V
# Creating custom biomes
transitive-accessible method net/minecraft/world/biome/OverworldBiomeCreator getSkyColor (F)I
@ -111,10 +111,10 @@ transitive-accessible method net/minecraft/world/biome/OverworldBiomeCreator get
transitive-accessible field net/minecraft/structure/processor/StructureProcessorLists EMPTY Lnet/minecraft/registry/RegistryKey;
# Creating custom trees
transitive-accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/treedecorator/TreeDecoratorType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/trunk/TrunkPlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/root/RootPlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/treedecorator/TreeDecoratorType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/trunk/TrunkPlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/root/RootPlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
# Working with custom damage sources
transitive-accessible field net/minecraft/entity/damage/DamageSources registry Lnet/minecraft/registry/Registry;

View file

@ -97,7 +97,7 @@ transitive-accessible method net/minecraft/sound/SoundEvent of (Lnet/minecraft/u
transitive-accessible method net/minecraft/sound/SoundEvent of (Lnet/minecraft/util/Identifier;)Lnet/minecraft/sound/SoundEvent;
# Creating BlockStateProviderTypes
transitive-accessible method net/minecraft/world/gen/stateprovider/BlockStateProviderType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/stateprovider/BlockStateProviderType <init> (Lcom/mojang/serialization/MapCodec;)V
# Creating custom biomes
transitive-accessible method net/minecraft/world/biome/OverworldBiomeCreator getSkyColor (F)I
@ -106,10 +106,10 @@ transitive-accessible method net/minecraft/world/biome/OverworldBiomeCreator get
transitive-accessible field net/minecraft/structure/processor/StructureProcessorLists EMPTY Lnet/minecraft/registry/RegistryKey;
# Creating custom trees
transitive-accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/treedecorator/TreeDecoratorType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/trunk/TrunkPlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/root/RootPlacerType <init> (Lcom/mojang/serialization/Codec;)V
transitive-accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/treedecorator/TreeDecoratorType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/trunk/TrunkPlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
transitive-accessible method net/minecraft/world/gen/root/RootPlacerType <init> (Lcom/mojang/serialization/MapCodec;)V
# Working with custom damage sources
transitive-accessible field net/minecraft/entity/damage/DamageSources registry Lnet/minecraft/registry/Registry;

View file

@ -2,9 +2,9 @@ org.gradle.jvmargs=-Xmx2560M
org.gradle.parallel=true
fabric.loom.multiProjectOptimisation=true
version=0.96.12
minecraft_version=24w12a
yarn_version=+build.5
version=0.96.13
minecraft_version=24w13a
yarn_version=+build.2
loader_version=0.15.6
installer_version=0.11.1
@ -13,51 +13,51 @@ curseforge_minecraft_version=1.20.5-Snapshot
# Do not manually update, use the bumpversions task:
fabric-api-base-version=0.4.38
fabric-api-lookup-api-v1-version=1.6.56
fabric-biome-api-v1-version=13.0.20
fabric-api-lookup-api-v1-version=1.6.57
fabric-biome-api-v1-version=13.0.21
fabric-block-api-v1-version=1.0.18
fabric-block-view-api-v2-version=1.0.6
fabric-blockrenderlayer-v1-version=1.1.48
fabric-command-api-v1-version=1.2.43
fabric-command-api-v2-version=2.2.22
fabric-commands-v0-version=0.2.60
fabric-content-registries-v0-version=6.0.14
fabric-content-registries-v0-version=6.0.15
fabric-crash-report-info-v1-version=0.2.25
fabric-data-attachment-api-v1-version=1.1.9
fabric-data-generation-api-v1-version=18.0.0
fabric-dimensions-v1-version=2.1.64
fabric-data-attachment-api-v1-version=1.1.10
fabric-data-generation-api-v1-version=18.0.1
fabric-dimensions-v1-version=2.1.65
fabric-entity-events-v1-version=1.6.6
fabric-events-interaction-v0-version=0.7.4
fabric-events-lifecycle-v0-version=0.2.84
fabric-events-lifecycle-v0-version=0.2.85
fabric-game-rule-api-v1-version=1.0.48
fabric-gametest-api-v1-version=1.3.11
fabric-item-api-v1-version=6.0.0
fabric-item-api-v1-version=6.0.1
fabric-item-group-api-v1-version=4.0.33
fabric-key-binding-api-v1-version=1.0.43
fabric-keybindings-v0-version=0.2.41
fabric-lifecycle-events-v1-version=2.3.1
fabric-loot-api-v2-version=2.1.13
fabric-lifecycle-events-v1-version=2.3.2
fabric-loot-api-v2-version=2.1.14
fabric-message-api-v1-version=6.0.8
fabric-model-loading-api-v1-version=1.0.10
fabric-models-v0-version=0.4.9
fabric-networking-api-v1-version=4.0.5
fabric-object-builder-api-v1-version=15.0.0
fabric-particles-v1-version=2.0.0
fabric-recipe-api-v1-version=4.1.1
fabric-registry-sync-v0-version=5.0.10
fabric-renderer-api-v1-version=3.2.9
fabric-renderer-indigo-version=1.5.9
fabric-renderer-registries-v1-version=3.2.58
fabric-object-builder-api-v1-version=15.0.1
fabric-particles-v1-version=2.0.1
fabric-recipe-api-v1-version=5.0.0
fabric-registry-sync-v0-version=5.0.11
fabric-renderer-api-v1-version=3.2.10
fabric-renderer-indigo-version=1.5.10
fabric-renderer-registries-v1-version=3.2.59
fabric-rendering-data-attachment-v1-version=0.3.44
fabric-rendering-fluids-v1-version=3.1.1
fabric-rendering-v0-version=1.1.61
fabric-rendering-v1-version=4.2.1
fabric-rendering-v0-version=1.1.62
fabric-rendering-v1-version=4.2.2
fabric-resource-conditions-api-v1-version=3.0.0
fabric-resource-loader-v0-version=1.0.0
fabric-screen-api-v1-version=2.0.19
fabric-screen-handler-api-v1-version=1.3.67
fabric-screen-handler-api-v1-version=1.3.68
fabric-sound-api-v1-version=1.0.19
fabric-transfer-api-v1-version=5.1.2
fabric-transitive-access-wideners-v1-version=6.0.6
fabric-convention-tags-v1-version=1.5.14
fabric-transfer-api-v1-version=5.1.3
fabric-transitive-access-wideners-v1-version=6.0.7
fabric-convention-tags-v1-version=1.5.15
fabric-client-tags-api-v1-version=1.1.9