Skip to content

Commit

Permalink
Realign ICustomIngredient (add display(), change stacks() -> items())
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n committed Oct 13, 2024
1 parent 318af87 commit 3e993b1
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 127 deletions.
59 changes: 15 additions & 44 deletions patches/net/minecraft/world/item/crafting/Ingredient.java.patch
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- a/net/minecraft/world/item/crafting/Ingredient.java
+++ b/net/minecraft/world/item/crafting/Ingredient.java
@@ -24,18 +_,22 @@
@@ -24,18 +_,20 @@
import net.minecraft.world.level.ItemLike;

public final class Ingredient implements Predicate<ItemStack> {
Expand All @@ -23,13 +23,11 @@
@Nullable
private List<Holder<Item>> items;
+ @Nullable
+ private List<ItemStack> stacks;
+ @Nullable
+ private net.neoforged.neoforge.common.crafting.ICustomIngredient customIngredient = null;

private Ingredient(HolderSet<Item> p_365027_) {
p_365027_.unwrap().ifRight(p_360057_ -> {
@@ -48,19 +_,50 @@
@@ -48,19 +_,32 @@
this.values = p_365027_;
}

Expand All @@ -42,13 +40,12 @@
return p_362504_.<Boolean>map(p_360060_ -> p_360060_.test(p_363604_)).orElseGet(p_363604_::isEmpty);
}

+ /** @deprecated Neo: Prefer {@link #stacks}. */
+ @Deprecated
+
public List<Holder<Item>> items() {
if (this.items == null) {
- this.items = ImmutableList.copyOf(this.values);
+ if (this.customIngredient != null) {
+ this.items = this.customIngredient.stacks().map(ItemStack::getItemHolder).distinct().toList();
+ this.items = this.customIngredient.items().toList();
+ } else {
+ this.items = ImmutableList.copyOf(this.values);
+ }
Expand All @@ -57,51 +54,15 @@
return this.items;
}

+ /**
+ * NBT-aware version of {@link #items}.
+ *
+ * @see net.neoforged.neoforge.common.crafting.ICustomIngredient#stacks
+ */
+ public List<ItemStack> stacks() {
+ if (this.stacks == null) {
+ if (this.customIngredient != null) {
+ this.stacks = this.customIngredient.stacks().toList();
+ } else {
+ this.stacks = this.values.stream().map(ItemStack::new).toList();
+ }
+ }
+
+ return this.stacks;
+ }
+
public boolean test(ItemStack p_43914_) {
+ if (this.customIngredient != null) {
+ return this.customIngredient.test(p_43914_);
+ }
List<Holder<Item>> list = this.items();

for (int i = 0; i < list.size(); i++) {
@@ -72,9 +_,68 @@
return false;
}
@@ -74,7 +_,49 @@

+ /**
+ * Returns {@code true} if this ingredient has an empty stack list.
+ * This will catch "accidentally empty" ingredients, for example a tag ingredient that has an empty tag.
+ */
+ // TODO 1.21.2: Do we want to keep this?
+ public boolean hasNoItems() {
+ var stacks = stacks();
+ if (stacks.isEmpty())
+ return true;
+ if (stacks.size() == 1) {
+ // If we potentially added a barrier due to the ingredient being an empty tag, try and check if it is the stack we added
+ ItemStack stack = stacks.getFirst();
+ return stack.getItem() == net.minecraft.world.item.Items.BARRIER && stack.getHoverName() instanceof net.minecraft.network.chat.MutableComponent hoverName && hoverName.getString().startsWith("Empty Tag: ");
+ }
+ return false;
+ }
+
@Override
public boolean equals(Object p_301003_) {
- return p_301003_ instanceof Ingredient ingredient ? Objects.equals(this.values, ingredient.values) : false;
Expand Down Expand Up @@ -151,3 +112,13 @@
}

public static Ingredient of(ItemLike p_364285_) {
@@ -94,6 +_,9 @@
}

public SlotDisplay display() {
+ if (this.customIngredient != null) {
+ return this.customIngredient.display();
+ }
return (SlotDisplay)this.values
.unwrap()
.map(SlotDisplay.TagSlotDisplay::new, p_380837_ -> new SlotDisplay.Composite(p_380837_.stream().map(Ingredient::displayForSingleItem).toList()));

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.HolderSet;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.neoforged.neoforge.common.NeoForgeMod;
import org.jetbrains.annotations.Nullable;

Expand All @@ -36,51 +37,38 @@ public class BlockTagIngredient implements ICustomIngredient {
protected final TagKey<Block> tag;

@Nullable
protected ItemStack[] itemStacks;
protected HolderSet<Item> items;

public BlockTagIngredient(TagKey<Block> tag) {
this.tag = tag;
}

protected void dissolve() {
if (itemStacks == null) {
List<ItemStack> list = new ArrayList<>();
protected HolderSet<Item> dissolve() {
if (items == null) {
List<Holder<Item>> list = new ArrayList<>();
for (Holder<Block> block : BuiltInRegistries.BLOCK.getTagOrEmpty(tag)) {
ItemStack stack = new ItemStack(block.value());
if (!stack.isEmpty()) {
list.add(stack);
var item = block.value().asItem();
if (item != Items.AIR) {
list.add(item.builtInRegistryHolder());
}
}

if (list.isEmpty()) {
ItemStack itemStack = new ItemStack(Blocks.BARRIER);
itemStack.set(DataComponents.CUSTOM_NAME, Component.literal("Empty Tag: " + this.tag.location()));
list.add(itemStack);
}

itemStacks = list.toArray(ItemStack[]::new);
items = HolderSet.direct(list);
}
return items;
}

@Override
public Stream<ItemStack> stacks() {
dissolve();
return Stream.of(itemStacks);
public Stream<Holder<Item>> items() {
return dissolve().stream();
}

@Override
public boolean test(@Nullable ItemStack stack) {
if (stack == null)
return false;

dissolve();
for (ItemStack itemStack : itemStacks) {
if (itemStack.is(stack.getItem())) {
return true;
}
}

return false;
return dissolve().contains(stack.getItemHolder());
}

public TagKey<Block> getTag() {
Expand All @@ -97,6 +85,13 @@ public IngredientType<?> getType() {
return NeoForgeMod.BLOCK_TAG_INGREDIENT.get();
}

@Override
public SlotDisplay display() {
return new SlotDisplay.Composite(dissolve().stream()
.map(Ingredient::displayForSingleItem)
.toList());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import com.mojang.serialization.MapCodec;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.neoforged.neoforge.common.NeoForgeMod;
import net.neoforged.neoforge.common.util.NeoForgeExtraCodecs;

Expand All @@ -33,8 +36,8 @@ public static Ingredient of(Ingredient... children) {
}

@Override
public Stream<ItemStack> stacks() {
return children.stream().flatMap(child -> child.stacks().stream());
public Stream<Holder<Item>> items() {
return children.stream().flatMap(child -> child.items().stream());
}

@Override
Expand All @@ -61,4 +64,9 @@ public boolean isSimple() {
public IngredientType<?> getType() {
return NeoForgeMod.COMPOUND_INGREDIENT_TYPE.get();
}

@Override
public SlotDisplay display() {
return new SlotDisplay.Composite(children.stream().map(Ingredient::display).toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.minecraft.world.level.ItemLike;
import net.neoforged.neoforge.common.NeoForgeMod;

Expand All @@ -35,7 +36,7 @@ public class DataComponentIngredient implements ICustomIngredient {
public static final MapCodec<DataComponentIngredient> CODEC = RecordCodecBuilder.mapCodec(
builder -> builder
.group(
HolderSetCodec.create(Registries.ITEM, BuiltInRegistries.ITEM.holderByNameCodec(), false).fieldOf("items").forGetter(DataComponentIngredient::items),
HolderSetCodec.create(Registries.ITEM, BuiltInRegistries.ITEM.holderByNameCodec(), false).fieldOf("items").forGetter(DataComponentIngredient::itemSet),
DataComponentPredicate.CODEC.fieldOf("components").forGetter(DataComponentIngredient::components),
Codec.BOOL.optionalFieldOf("strict", false).forGetter(DataComponentIngredient::isStrict))
.apply(builder, DataComponentIngredient::new));
Expand Down Expand Up @@ -67,8 +68,8 @@ public boolean test(ItemStack stack) {
}

@Override
public Stream<ItemStack> stacks() {
return Stream.of(stacks);
public Stream<Holder<Item>> items() {
return items.stream();
}

@Override
Expand All @@ -81,7 +82,23 @@ public IngredientType<?> getType() {
return NeoForgeMod.DATA_COMPONENT_INGREDIENT_TYPE.get();
}

public HolderSet<Item> items() {
@Override
public SlotDisplay display() {
return new SlotDisplay.Composite(Stream.of(stacks)
.map(stack -> {
SlotDisplay display = new SlotDisplay.ItemStackSlotDisplay(stack);
ItemStack remainder = stack.getCraftingRemainder();
if (!remainder.isEmpty()) {
SlotDisplay remainderDisplay = new SlotDisplay.ItemStackSlotDisplay(remainder);
return new SlotDisplay.WithRemainder(display, remainderDisplay);
} else {
return display;
}
})
.toList());
}

public HolderSet<Item> itemSet() {
return items;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.display.SlotDisplay;
import net.neoforged.neoforge.common.NeoForgeMod;

/** Ingredient that matches everything from the first ingredient that is not included in the second ingredient */
Expand All @@ -22,8 +25,8 @@ public record DifferenceIngredient(Ingredient base, Ingredient subtracted) imple
.apply(builder, DifferenceIngredient::new));

@Override
public Stream<ItemStack> stacks() {
return base.stacks().stream().filter(subtracted.negate());
public Stream<Holder<Item>> items() {
return base.items().stream().filter(i -> !subtracted.test(i.value().getDefaultInstance()));
}

@Override
Expand All @@ -36,6 +39,14 @@ public boolean isSimple() {
return base.isSimple() && subtracted.isSimple();
}

@Override
public SlotDisplay display() {
// TODO: better handling in case the subingredients are not simple?
return new SlotDisplay.Composite(items()
.map(Ingredient::displayForSingleItem)
.toList());
}

@Override
public IngredientType<?> getType() {
return NeoForgeMod.DIFFERENCE_INGREDIENT_TYPE.get();
Expand Down
Loading

0 comments on commit 3e993b1

Please sign in to comment.