diff --git a/build.gradle b/build.gradle index 5b2cf8021..6bd9f6a7f 100644 --- a/build.gradle +++ b/build.gradle @@ -249,6 +249,8 @@ allprojects { minecraft "com.mojang:minecraft:$rootProject.minecraft_version" mappings "net.fabricmc:yarn:${rootProject.minecraft_version}${project.yarn_version}:v2" forge "net.minecraftforge:forge:${rootProject.forge_version}" + compileOnly annotationProcessor('io.github.llamalad7:mixinextras-common:0.4.1') + implementation(include("io.github.llamalad7:mixinextras-forge:0.4.1")) testmodImplementation sourceSets.main.output // testmodClientImplementation sourceSets.main.output diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin.java index df6856937..62cffeef4 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin.java @@ -18,16 +18,13 @@ import java.util.stream.Stream; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Cancellable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import net.minecraft.entity.Entity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.random.Random; import net.minecraft.registry.DefaultedRegistry; import net.minecraft.village.TradeOffer; import net.minecraft.village.TradeOffers; @@ -47,12 +44,18 @@ private Stream disableVanillaCheck(DefaultedRegistry instan } /** - * To prevent "item" -> "air" trades, if the result of a type aware trade is air, make sure no offer is created. + * https://github.com/FabricMC/fabric/commit/e35120df0e113211c3e6928fa446efe6f387b085#diff-3f36fa41b6959de14a21137b631ecff47f27ed73845fa4c15ce77fac6cdad012R50 + * To prevent crashes due to passing a {@code null} item to a {@link TradeOffer}, return a {@code null} trade offer + * early before {@code null} is passed to the constructor. */ - @Inject(method = "create", at = @At(value = "NEW", target = "net/minecraft/village/TradeOffer"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true, require = 0) - private void failOnNullItem(Entity entity, Random random, CallbackInfoReturnable cir, ItemStack buyingItem) { - if (buyingItem.isEmpty()) { // Will return true for an "empty" item stack that had null passed in the ctor - cir.setReturnValue(null); // Return null to prevent creation of empty trades + @ModifyExpressionValue( + method = "create", + at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;") + ) + private Object failOnNullItem(Object item, @Cancellable CallbackInfoReturnable cir) { + if (item == null) { + cir.setReturnValue(null); } + return item; } }