Skip to content

Commit

Permalink
fix: fix bio-forge not counting ingredients with nbt data correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
Elenterius committed Oct 1, 2024
1 parent bed3c38 commit 333e8a3
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.github.elenterius.biomancy.menu.BioForgeTab;
import com.github.elenterius.biomancy.mixin.accessor.RecipeCollectionAccessor;
import com.github.elenterius.biomancy.network.ModNetworkHandler;
import com.github.elenterius.biomancy.util.ItemStackCounter;
import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;
Expand All @@ -23,7 +24,6 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.stats.RecipeBook;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.StackedContents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;

Expand All @@ -40,7 +40,7 @@ class BioForgeScreenController {
return b.sortPriority() - a.sortPriority();
};
private static RecipeSelection recipeSelection = RecipeSelection.EMPTY; //volatile client cache
private final StackedContents itemCounter;
private final ItemStackCounter itemCounter;
private final List<BioForgeTab> tabs;
private final Minecraft minecraft;
private final BioForgeMenu menu;
Expand All @@ -59,8 +59,8 @@ public BioForgeScreenController(Minecraft minecraft, BioForgeMenu menu) {
tabs = ModBioForgeTabs.REGISTRY.get().getValues().stream().sorted(CATEGORY_COMPARATOR).toList();

playerInvChanges = getPlayer().getInventory().getTimesChanged();
itemCounter = new StackedContents();
getPlayer().getInventory().fillStackedContents(itemCounter);
itemCounter = new ItemStackCounter();
itemCounter.accountStacks(getPlayer().getInventory().items);

//restore selected recipe from volatile client cache
if (recipeSelection != RecipeSelection.EMPTY && menu.getSelectedRecipe() == null && recipeSelection.recipe != null) {
Expand Down Expand Up @@ -145,8 +145,7 @@ public BioForgeRecipe getRecipeByGrid(int gridIndex) {
}

public int getTotalItemCountInPlayerInv(ItemStack stack) {
int index = StackedContents.getStackingIndex(stack);
return itemCounter.contents.get(index);
return itemCounter.getCount(stack);
}

public boolean hasSufficientIngredientCount(IngredientStack ingredientStack) {
Expand Down Expand Up @@ -236,7 +235,7 @@ public void trackPlayerInvChanges() {

private void countPlayerInvItems() {
itemCounter.clear();
getPlayer().getInventory().fillStackedContents(itemCounter);
itemCounter.accountStacks(getPlayer().getInventory().items);
updateAndSearchRecipes();
}

Expand All @@ -247,7 +246,7 @@ public void updateSearchString(String searchString) {
currentSearchString = searchString;
}

private static void canCraftRecipe(RecipeCollection recipeCollection, StackedContents handler, RecipeBook book, boolean isCreativePlayer) {
private static void canCraftRecipe(RecipeCollection recipeCollection, ItemStackCounter itemCounter, RecipeBook book, boolean isCreativePlayer) {
RecipeCollectionAccessor accessor = (RecipeCollectionAccessor) recipeCollection;
Set<Recipe<?>> fitDimensions = accessor.biomancy$getFitDimensions();
Set<Recipe<?>> craftable = accessor.biomancy$getCraftable();
Expand All @@ -263,8 +262,13 @@ private static void canCraftRecipe(RecipeCollection recipeCollection, StackedCon
fitDimensions.remove(recipe);
}

if (canCraftRecipe && handler.canCraft(recipe, null)) {
craftable.add(recipe);
if (recipe instanceof BioForgeRecipe bioForgeRecipe) {
if (canCraftRecipe && bioForgeRecipe.isCraftable(itemCounter)) {
craftable.add(recipe);
}
else {
craftable.remove(recipe);
}
}
else {
craftable.remove(recipe);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.github.elenterius.biomancy.init.ModItems;
import com.github.elenterius.biomancy.init.ModRecipes;
import com.github.elenterius.biomancy.menu.BioForgeTab;
import com.github.elenterius.biomancy.util.ItemStackCounter;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
Expand Down Expand Up @@ -76,6 +77,36 @@ public boolean isCraftable(StackedContents itemCounter) {
return true;
}

public boolean isCraftable(ItemStackCounter itemCounter) {
int[] residuals = new int[ingredients.size()];
int totalResidual = 0;
for (int i = 0; i < ingredients.size(); i++) {
int count = ingredients.get(i).count();
residuals[i] = count;
totalResidual += count;
}

for (ItemStackCounter.CountedItem countedItem : itemCounter.getItemCounts()) {
if (totalResidual <= 0) return true;

int available = countedItem.amount();

for (int i = 0; i < ingredients.size(); i++) {
if (available <= 0) break;

final int residual = residuals[i];
if (residual > 0 && ingredients.get(i).testItem(countedItem.stack())) {
final int amount = Math.min(residual, available);
residuals[i] -= amount;
available -= amount;
totalResidual -= amount;
}
}
}

return totalResidual <= 0;
}

@Override
public boolean matches(Container inv, Level level) {
int[] countedIngredients = new int[ingredients.size()];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.elenterius.biomancy.crafting.recipe;

import com.github.elenterius.biomancy.util.ItemStackCounter;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.IntList;
Expand Down Expand Up @@ -38,6 +39,18 @@ public boolean hasSufficientCount(StackedContents itemCounter) {
return false;
}

public boolean hasSufficientCount(ItemStackCounter itemCounter) {
List<ItemStackCounter.CountedItem> itemCounts = itemCounter.getItemCounts();

int n = 0;
for (ItemStackCounter.CountedItem countedItem : itemCounts) {
if (ingredient.test(countedItem.stack())) n += countedItem.amount();
if (n >= count) return true;
}

return false;
}

public List<ItemStack> getItemsWithCount() {
if (count == 1) return List.of(ingredient.getItems());
return Arrays.stream(ingredient.getItems()).map(this::copyItemStackWithCount).toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.github.elenterius.biomancy.menu.slot.FuelSlot;
import com.github.elenterius.biomancy.menu.slot.ISlotZone;
import com.github.elenterius.biomancy.menu.slot.OutputSlot;
import com.github.elenterius.biomancy.util.ItemStackCounter;
import com.github.elenterius.biomancy.util.SoundUtil;
import com.github.elenterius.biomancy.util.fuel.FuelHandler;
import net.minecraft.network.FriendlyByteBuf;
Expand All @@ -20,7 +21,6 @@
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.player.StackedContents;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.ResultContainer;
import net.minecraft.world.inventory.Slot;
Expand All @@ -37,7 +37,7 @@ public class BioForgeMenu extends PlayerContainerMenu {
private final BehavioralInventory<?> fuelInventory;
private final BioForgeStateData stateData;
private int playerInvChanges;
private final StackedContents itemCounter = new StackedContents();
private final ItemStackCounter itemCounter = new ItemStackCounter();
@Nullable
private BioForgeRecipe selectedRecipe;

Expand Down Expand Up @@ -97,15 +97,15 @@ private void trackPlayerInvChanges(ServerPlayer serverPlayer, Inventory inventor

private void countPlayerInvItems(ServerPlayer serverPlayer, Inventory inventory) {
itemCounter.clear();
inventory.fillStackedContents(itemCounter);
itemCounter.accountStacks(inventory.items);
updateResultSlot(serverPlayer);
}

private void updateResultSlot(ServerPlayer serverPlayer) {
ItemStack resultStack = ItemStack.EMPTY;

BioForgeRecipe recipe = getSelectedRecipe();
if (recipe != null && resultContainer.setRecipeUsed(serverPlayer.level(), serverPlayer, recipe) && canCraft(serverPlayer, recipe)) {
if (recipe != null && resultContainer.setRecipeUsed(serverPlayer.level(), serverPlayer, recipe) && canCraft(recipe)) {
resultStack = recipe.getResultItem(serverPlayer.level().registryAccess()).copy();
}

Expand Down Expand Up @@ -312,33 +312,8 @@ public void onTake(Player player, ItemStack stack) {

}

private boolean canCraft(Player player, @Nullable BioForgeRecipe recipe) {
if (recipe == null || getFuelAmount() < recipe.getCraftingCostNutrients() || !recipe.isCraftable(itemCounter)) return false;

Inventory inventory = player.getInventory();

//count available ingredients
List<IngredientStack> ingredients = recipe.getIngredientQuantities();
int[] countedIngredients = new int[ingredients.size()];
for (int idx = 0; idx < inventory.items.size(); idx++) {
ItemStack foundStack = inventory.items.get(idx);
if (!foundStack.isEmpty()) {
for (int i = 0; i < ingredients.size(); i++) {
if (ingredients.get(i).testItem(foundStack)) {
countedIngredients[i] += foundStack.getCount();
break;
}
}
}
}

//check that all requirements are fulfilled
for (int i = 0; i < ingredients.size(); i++) {
int requiredCount = ingredients.get(i).count();
if (countedIngredients[i] < requiredCount) return false;
}

return true;
private boolean canCraft(@Nullable BioForgeRecipe recipe) {
return recipe != null && getFuelAmount() >= recipe.getCraftingCostNutrients() && recipe.isCraftable(itemCounter);
}

private void consumeCraftingIngredients(Player player, BioForgeRecipe recipe) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import it.unimi.dsi.fastutil.ints.IntComparators;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
Expand Down Expand Up @@ -59,19 +60,13 @@ record EntryKey(int hash, ItemStack stack) implements HashKey {

public EntryKey(int hash, ItemStack stack) {
this.hash = hash;
this.stack = copyWithMinCount(stack);
this.stack = stack.copyWithCount(1);
}

EntryKey(ItemStack stack) {
this(Objects.hash(ForgeRegistries.ITEMS.getKey(stack.getItem()), stack.getTag()), stack);
}

private static ItemStack copyWithMinCount(ItemStack stack) {
ItemStack copy = stack.copy();
copy.setCount(1);
return copy;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
Expand All @@ -87,9 +82,21 @@ public int hashCode() {
}

private final Object2IntMap<HashKey> countedItemStacks = new Object2IntOpenHashMap<>();
private List<CountedItem> countedItems = null;

public record CountedItem(ItemStack stack, int amount) {}

public List<CountedItem> getItemCounts() {
if (countedItems != null) return countedItems;

countedItems = countedItemStacks.object2IntEntrySet().stream()
.sorted((a, b) -> IntComparators.OPPOSITE_COMPARATOR.compare(a.getIntValue(), b.getIntValue()))
.map(entry -> new CountedItem(entry.getKey().stack(), entry.getIntValue()))
.toList();

return countedItems;
}

public List<CountedItem> getItemCountSorted(int limit, boolean ascending) {
IntComparator comparator = ascending ? IntComparators.NATURAL_COMPARATOR : IntComparators.OPPOSITE_COMPARATOR;
return countedItemStacks.object2IntEntrySet().stream()
Expand All @@ -107,6 +114,12 @@ public void accountStack(ItemStack stack) {
accountStack(stack, stack.getCount());
}

public void accountStacks(NonNullList<ItemStack> stacks) {
for (ItemStack stack : stacks) {
accountStack(stack);
}
}

public void accountStacks(Container container) {
for (int i = 0; i < container.getContainerSize(); i++) {
accountStack(container.getItem(i));
Expand All @@ -132,6 +145,8 @@ private void put(ItemStack template, int amount) {
EntryKey entryKey = new EntryKey(key.hash(), template);
countedItemStacks.put(entryKey, amount);
}

countedItems = null;
}

public boolean has(ItemStack template) {
Expand All @@ -144,6 +159,7 @@ public int getCount(ItemStack template) {

public void clear() {
countedItemStacks.clear();
countedItems = null;
}

}

0 comments on commit 333e8a3

Please sign in to comment.