diff --git a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/ItemStackMixinExpansion.java b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/ItemStackMixinExpansion.java index 33726d90e..11ef24099 100644 --- a/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/ItemStackMixinExpansion.java +++ b/src/main/java/com/cleanroommc/groovyscript/compat/vanilla/ItemStackMixinExpansion.java @@ -1,16 +1,15 @@ package com.cleanroommc.groovyscript.compat.vanilla; -import com.cleanroommc.groovyscript.api.GroovyBlacklist; -import com.cleanroommc.groovyscript.api.IIngredient; -import com.cleanroommc.groovyscript.api.INBTResourceStack; -import com.cleanroommc.groovyscript.api.INbtIngredient; +import com.cleanroommc.groovyscript.api.*; import com.cleanroommc.groovyscript.helper.ingredient.IngredientHelper; import com.cleanroommc.groovyscript.helper.ingredient.NbtHelper; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.oredict.OreDictionary; import org.jetbrains.annotations.Nullable; @@ -101,7 +100,7 @@ default ItemStack reuse() { return transform(self -> self); } - default ItemStack noreturn() { + default ItemStack noReturn() { return transform(self -> ItemStack.EMPTY); } @@ -111,7 +110,7 @@ default ItemStack transform(ItemStack stack) { default ItemStack transformDamage(int amount) { // reliably set itemDamage field of item stack - return transform(self -> of(self).withDamage(Math.min(32767, Items.DIAMOND.getDamage(self) + amount))); + return transform(self -> IngredientHelper.damageItem(self, amount)); } default ItemStack transformDamage() { @@ -129,7 +128,11 @@ default ItemStack transformNbt(UnaryOperator transformer) { default ItemStack applyTransform(ItemStack matchedInput) { if (grs$getTransformer() != null) { ItemStack result = grs$getTransformer().transform(matchedInput); - if (result == null) return ItemStack.EMPTY; + if (result == null || result.isEmpty()) return ItemStack.EMPTY; + if (result.isItemStackDamageable() && result.getMetadata() > result.getMaxDamage()) { + ForgeEventFactory.onPlayerDestroyItem(ForgeHooks.getCraftingPlayer(), result, null); + return ItemStack.EMPTY; + } return result.copy(); } return ForgeHooks.getContainerItem(matchedInput); @@ -220,6 +223,17 @@ default ItemStack withDamage(int meta) { return withMeta(meta); } + default ItemStack destroy() { + if (grs$getItemStack().isEmpty()) return ItemStack.EMPTY; + EntityPlayer player = ForgeHooks.getCraftingPlayer(); + if (player != null) { + ForgeEventFactory.onPlayerDestroyItem(player, grs$getItemStack(), null); + return ItemStack.EMPTY; + } + GroovyLog.get().error("Should only destroy item during crafting!"); + return grs$getItemStack(); + } + @Override default @Nullable String getMark() { return grs$getMark(); diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientBase.java b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientBase.java index a7c6538e6..4ed8ddca8 100644 --- a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientBase.java +++ b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientBase.java @@ -1,49 +1,80 @@ package com.cleanroommc.groovyscript.helper.ingredient; import com.cleanroommc.groovyscript.api.IIngredient; -import com.cleanroommc.groovyscript.sandbox.ClosureHelper; -import groovy.lang.Closure; +import com.cleanroommc.groovyscript.compat.vanilla.ItemStackMixinExpansion; +import com.cleanroommc.groovyscript.compat.vanilla.ItemStackTransformer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.event.ForgeEventFactory; import org.jetbrains.annotations.Nullable; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + public abstract class IngredientBase implements IIngredient { - protected Closure matchCondition; - protected Closure transformer; + protected Predicate matchCondition; + protected ItemStackTransformer transformer; protected String mark; - public IngredientBase when(Closure matchCondition) { + public IngredientBase when(Predicate matchCondition) { IngredientBase fresh = (IngredientBase) this.exactCopy(); fresh.matchCondition = matchCondition; return fresh; } - public IngredientBase transform(Closure transformer) { + public IngredientBase transform(ItemStackTransformer transformer) { IngredientBase fresh = (IngredientBase) this.exactCopy(); fresh.transformer = transformer; return fresh; } + public IngredientBase transformDamage(int amount) { + // reliably set itemDamage field of item stack + return transform(self -> IngredientHelper.damageItem(self, amount)); + } + + public IngredientBase transformDamage() { + return transformDamage(1); + } + + public IngredientBase transformNbt(UnaryOperator transformer) { + return transform(self -> { + ItemStackMixinExpansion.of(self).exactCopy().grs$getItemStack().setTagCompound(transformer.apply(self.getTagCompound())); + return self; + }); + } + public IngredientBase reuse() { - return transform(IngredientHelper.REUSE); + return transform(self -> self); } public IngredientBase noReturn() { - return transform(IngredientHelper.NO_RETURN); + return transform(self -> ItemStack.EMPTY); + } + + public IngredientBase transform(ItemStack stack) { + return transform(self -> stack); } @Override public boolean test(ItemStack itemStack) { - return (matchCondition == null || ClosureHelper.call(true, matchCondition, itemStack)) && matches(itemStack); + return (this.matchCondition == null || this.matchCondition.test(itemStack)) && matches(itemStack); } public abstract boolean matches(ItemStack itemStack); @Override public ItemStack applyTransform(ItemStack matchedInput) { - if (transformer != null) { - return ClosureHelper.call(ItemStack.EMPTY, transformer, matchedInput); + if (this.transformer != null) { + ItemStack result = this.transformer.transform(matchedInput); + if (result == null || result.isEmpty()) return ItemStack.EMPTY; + if (result.isItemStackDamageable() && result.getMetadata() > result.getMaxDamage()) { + ForgeEventFactory.onPlayerDestroyItem(ForgeHooks.getCraftingPlayer(), result, null); + return ItemStack.EMPTY; + } + return result.copy(); } return ForgeHooks.getContainerItem(matchedInput); } diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java index 3c4ef4688..a2f32bbef 100644 --- a/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java +++ b/src/main/java/com/cleanroommc/groovyscript/helper/ingredient/IngredientHelper.java @@ -2,9 +2,11 @@ import com.cleanroommc.groovyscript.GroovyScriptConfig; import com.cleanroommc.groovyscript.api.IIngredient; +import com.cleanroommc.groovyscript.compat.vanilla.ItemStackMixinExpansion; import com.cleanroommc.groovyscript.sandbox.expand.LambdaClosure; import groovy.lang.Closure; import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.Ingredient; import net.minecraft.nbt.NBTTagCompound; @@ -25,6 +27,12 @@ public class IngredientHelper { public static final Closure NO_RETURN = new LambdaClosure<>(args -> ItemStack.EMPTY); public static final Closure MATCH_NBT = new LambdaClosure<>(args -> ItemStack.EMPTY); + public static ItemStack damageItem(ItemStack stack, int damage) { + // Short.MAX_VALUE is meta wildcard + // Items.DIAMOND.getDamage(stack) is guaranteed to return the value of the damage field of stack + return ItemStackMixinExpansion.of(stack).withMeta(Math.min(Short.MAX_VALUE - 1, Items.DIAMOND.getDamage(stack) + damage)); + } + public static boolean isFluid(IIngredient ingredient) { return ingredient instanceof FluidStack; }