Bookmarks: Fix Permutations with different amount (#1000)

This commit is contained in:
slprime authored and GitHub committed 2026-08-12 22:45:39 +03:00
1 parent 5a533c8994
commit c6170f9795
5 files changed
+104 -29

No files matched your search

@@ -1094,10 +1094,13 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
}
activeStack = items.get((items.size() - shift + stackIndex) % items.size());
this.acceptsFollowingTooltipLineHandler.setActiveStack(activeStack);
this.grid.getBookmarkItem(Math.abs(itemIndex)).itemStack = activeStack;
this.grid.onItemsChanged();
final int targetItemIndex = Math.abs(itemIndex);
final BookmarkItem oldItem = this.grid.getBookmarkItem(targetItemIndex);
final BookmarkItem newItem = oldItem.copyWithPerm(activeStack);
this.grid.replaceBookmarkItem(targetItemIndex, newItem);
}
return true;
@@ -879,6 +879,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
return this.bookmarkItems.get(itemIndex);
}
public void replaceBookmarkItem(int itemIndex, BookmarkItem newItem) {
if (itemIndex < 0 || itemIndex >= this.bookmarkItems.size()) {
return;
}
this.bookmarkItems.set(itemIndex, newItem);
onItemsChanged();
}
public int getAbsoluteSlotIndex(int itemIndex) {
return this.gridGenerator.itemToSlot.getOrDefault(itemIndex, -1);
}
@@ -228,11 +228,15 @@ public class BookmarkItem {
final List<RecipeIngredient> items = type == BookmarkItemType.RESULT ? recipe.getResults()
: recipe.getIngredients();
final Builder builder = builder(groupId, stack).type(type).recipe(recipe);
final ItemStack emptyStack = StackInfo.withAmount(stack, 0);
long amount = 0;
for (RecipeIngredient res : items) {
if (res.contains(stack)) {
amount += 1L * res.getAmount() * res.getChance();
for (ItemStack perm : res.getPermutations()) {
if (NEIClientUtils.areStacksSameTypeWithNBT(emptyStack, StackInfo.withAmount(perm, 0))) {
amount += 1L * StackInfo.getAmount(perm) * res.getChance();
break;
}
}
}
@@ -308,6 +312,47 @@ public class BookmarkItem {
return copyWithMultiplier(this.multiplier);
}
public BookmarkItem copyWithPerm(ItemStack stack) {
if (this.recipeId != null
&& !NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(stack, 0), this.getItemStack(0))) {
final ItemStack oldPerm = findPermutation(this.itemStack);
final ItemStack newPerm = findPermutation(stack);
if (oldPerm != null && newPerm != null) {
final long oldAmount = StackInfo.getAmount(oldPerm);
final long amount = oldAmount > 0 ? this.factor * this.chance * StackInfo.getAmount(newPerm) / oldAmount
: 0;
final long factor = (amount % PositionedStack.CHANCE_FULL) == 0 ? amount / PositionedStack.CHANCE_FULL
: 1;
final long chance = factor == 1 ? amount : PositionedStack.CHANCE_FULL;
return new BookmarkItem(
this.groupId,
this.multiplier,
factor,
chance,
newPerm,
this.permutations,
this.recipeId,
this.type);
}
}
return copy();
}
private ItemStack findPermutation(ItemStack stack) {
for (ItemStack itemStack : this.permutations.values()) {
if (StackInfo.equalItemAndNBT(stack, itemStack, true)) {
return itemStack;
}
}
return null;
}
public boolean containsItems(BookmarkItem item) {
return this.permutations.keySet().stream().anyMatch(item.permutations::containsKey);
}
@@ -316,21 +361,47 @@ public class BookmarkItem {
return getAmount(this.multiplier);
}
public long getAmount(long multiplier, ItemStack perm) {
if (this.recipeId != null && perm != null
&& !NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(perm, 0), this.getItemStack(0))) {
final ItemStack oldPerm = findPermutation(this.itemStack);
final ItemStack newPerm = findPermutation(perm);
if (oldPerm != null && newPerm != null) {
final long oldAmount = StackInfo.getAmount(oldPerm);
final long amount = oldAmount > 0 ? this.factor * this.chance * StackInfo.getAmount(newPerm) / oldAmount
: 0;
final long factor = (amount % PositionedStack.CHANCE_FULL) == 0 ? amount / PositionedStack.CHANCE_FULL
: 1;
final long chance = factor == 1 ? amount : PositionedStack.CHANCE_FULL;
return getAmount(multiplier, factor, chance);
}
}
return getAmount(multiplier);
}
public long getAmount(long multiplier) {
long amount = this.factor * multiplier;
return getAmount(multiplier, this.factor, this.chance);
}
protected long getAmount(long multiplier, long factor, long chance) {
long amount = factor * multiplier;
if (this.fluidCellAmount > 1) {
amount = amount * this.fluidCellAmount;
}
if (this.chance != PositionedStack.CHANCE_FULL) {
if (chance != PositionedStack.CHANCE_FULL) {
if (this.type == BookmarkItemType.INGREDIENT) {
// For ingredients, round up the expected amount to be conservative.
amount = (amount * this.chance + PositionedStack.CHANCE_FULL - 1) / PositionedStack.CHANCE_FULL;
return (amount * chance + PositionedStack.CHANCE_FULL - 1) / PositionedStack.CHANCE_FULL;
} else {
// For results, round down the expected amount to be conservative.
amount = (amount * this.chance) / PositionedStack.CHANCE_FULL;
return (amount * chance) / PositionedStack.CHANCE_FULL;
}
}
@@ -335,30 +335,19 @@ public class Recipe {
public void setActiveIndex(int activeIndex) {
this.activeIndex = Math.max(0, Math.min(activeIndex, this.items.length - 1));
this.amount = StackInfo.getAmount(this.items[this.activeIndex]);
}
public boolean contains(ItemStack stackA) {
return getPermutations().stream()
.anyMatch(stackB -> NEIClientUtils.areStacksSameTypeWithNBT(stackB, stackA));
final ItemStack stack = StackInfo.withAmount(stackA, 0);
return getPermutations().stream().anyMatch(
stackB -> NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(stackB, 0), stack));
}
public List<ItemStack> getPermutations() {
return Arrays.asList(this.items);
}
public RecipeIngredient setAmount(int amount) {
for (int index = 0; index < this.items.length; index++) {
this.items[index] = StackInfo.withAmount(this.items[index], amount);
}
return this;
}
public void setChance(int chance) {
this.chance = chance;
}
public RecipeIngredient copy() {
return new RecipeIngredient(
this.relx,
@@ -233,7 +233,7 @@ public class RecipeChainMath {
final long amount = item.getAmount(multiplier);
rootIngredients.add(
BookmarkItem.builder(-1, item.getItemStack(amount)).factor(item.getStackSize(amount))
.permutations(BookmarkItem.Builder.generatePermutations(item.itemStack))
.permutations(BookmarkItem.Builder.generatePermutations(item.getItemStack(amount)))
.recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.INGREDIENT).build());
}
@@ -348,14 +348,14 @@ public class RecipeChainMath {
for (BookmarkItem prefItem : this.recipeResults) {
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)) {
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
final long prefMultiplier = this.outputRecipes.get(prefItem.recipeId);
if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) {
this.containerItemsBlacklist.add(prefItem.itemStack);
}
this.preferredItems.put(prefItem, prefItem);
calculateSuitableRecipe(prefItem, prefAmount, new ArrayList<>(), visitor);
calculateSuitableRecipe(prefItem, prefMultiplier, new ArrayList<>(), visitor);
this.preferredItems.remove(prefItem);
}
}
@@ -372,9 +372,11 @@ public class RecipeChainMath {
return this;
}
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited,
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrMultiplier, List<RecipeId> visited,
ChainVisitor visitor) {
final BookmarkItem prefItem = this.preferredItems.get(ingrItem);
long ingrAmount = ingrItem
.getAmount(ingrMultiplier, prefItem != null ? prefItem.itemStack : ingrItem.itemStack);
visitor.addIngredient(prefItem != null ? prefItem : ingrItem, ingrAmount);
@@ -426,7 +428,7 @@ public class RecipeChainMath {
for (BookmarkItem item : this.recipeIngredients) {
if (!item.emptyFactor() && recipeId.equals(item.recipeId)) {
calculateSuitableRecipe(item, item.getAmount(multiplier), visited, visitor);
calculateSuitableRecipe(item, multiplier, visited, visitor);
}
}