Skip to content

Commit

Permalink
Fix item transforms (#281)
Browse files Browse the repository at this point in the history
* add transform methods to `IngredientBase` & properly destroy items

* reviews

* review
  • Loading branch information
brachy84 authored Jan 17, 2025
1 parent 4a6cf12 commit de31ca1
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -101,7 +100,7 @@ default ItemStack reuse() {
return transform(self -> self);
}

default ItemStack noreturn() {
default ItemStack noReturn() {
return transform(self -> ItemStack.EMPTY);
}

Expand All @@ -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() {
Expand All @@ -129,7 +128,11 @@ default ItemStack transformNbt(UnaryOperator<NBTTagCompound> 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);
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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<Object> matchCondition;
protected Closure<Object> transformer;
protected Predicate<ItemStack> matchCondition;
protected ItemStackTransformer transformer;
protected String mark;

public IngredientBase when(Closure<Object> matchCondition) {
public IngredientBase when(Predicate<ItemStack> matchCondition) {
IngredientBase fresh = (IngredientBase) this.exactCopy();
fresh.matchCondition = matchCondition;
return fresh;
}

public IngredientBase transform(Closure<Object> 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<NBTTagCompound> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,6 +27,12 @@ public class IngredientHelper {
public static final Closure<Object> NO_RETURN = new LambdaClosure<>(args -> ItemStack.EMPTY);
public static final Closure<Object> 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;
}
Expand Down

0 comments on commit de31ca1

Please sign in to comment.