Compare commits

...
23 changed files with 846 additions and 482 deletions

No files matched your search

@@ -19,6 +19,7 @@ import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.io.IOUtils;
@@ -184,27 +185,33 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
if (itemStack != null && this.grid.indexOf(groupId, itemStack, recipeId, false) == -1) {
final boolean existsRecipe = recipeId != null
&& this.grid.existsRecipe(recipeId, BookmarkGrid.DEFAULT_GROUP_ID);
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(itemStack);
long count = nbTag.getInteger("Count");
long factor = existsRecipe ? Math.max(count, 1) : 1;
final Recipe recipe = Recipe.of(recipeId);
final BookmarkItem.Builder builder;
if (recipe != null) {
builder = BookmarkItem.builder(groupId, itemStack, recipe, BookmarkItemType.RESULT);
} else {
builder = BookmarkItem.builder(groupId, itemStack).recipeId(recipeId)
.factor(StackInfo.getAmount(itemStack));
}
builder.multiplier(1);
if (existsRecipe) {
builder.type(BookmarkItemType.RESULT);
for (int i = 0; i < this.grid.size(); i++) {
if (this.grid.getBookmarkItem(i).equalsRecipe(recipeId, groupId)) {
count *= this.grid.getBookmarkItem(i).getMultiplier();
builder.multiplier(this.grid.getBookmarkItem(i).getMultiplier());
break;
}
}
} else {
builder.type(BookmarkItemType.ITEM);
}
this.grid.addItem(
BookmarkItem.of(
groupId,
StackInfo.withAmount(itemStack, count),
factor,
recipeId,
existsRecipe ? BookmarkItemType.RESULT : BookmarkItemType.ITEM),
true);
this.grid.addItem(builder.build(), true);
return true;
}
@@ -212,9 +219,11 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
}
public boolean addRecipe(Recipe recipe, int multiplier, int groupId) {
if (recipe == null) return false;
final RecipeId recipeId = recipe.getRecipeId();
if (recipe != null && this.grid.getGroup(groupId) != null && !this.grid.existsRecipe(recipeId, groupId)) {
if (this.grid.getGroup(groupId) != null && !this.grid.existsRecipe(recipeId, groupId)) {
this.grid.addRecipe(recipe, multiplier, groupId);
return true;
}
@@ -245,15 +254,22 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
ItemStack stack = recipeId.getResult();
if (stack != null && uniqueRecipe.add(recipeId)) {
this.grid.addItem(
BookmarkItem
.of(groupId, stack, StackInfo.getAmount(stack), recipeId, BookmarkItemType.ITEM),
true);
final Recipe recipe = Recipe.of(recipeId);
final BookmarkItem.Builder builder;
if (recipe != null) {
builder = BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.RESULT);
} else {
builder = BookmarkItem.builder(groupId, stack).recipeId(recipeId)
.factor(StackInfo.getAmount(stack));
}
this.grid.addItem(builder.multiplier(1).type(BookmarkItemType.ITEM).build(), true);
uniqueStack.add(stack);
}
} else {
ItemStack stack = extractItem(item);
final ItemStack stack = extractItem(item);
if (stack != null && !uniqueStack.contains(stack)) {
this.grid.addItem(BookmarkItem.of(groupId, stack), true);
@@ -925,6 +941,15 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
if (slot != null) {
if (slot.getBookmarkItem().chance != PositionedStack.CHANCE_FULL) {
currenttip.add(
1,
EnumChatFormatting.DARK_GRAY + NEIClientUtils.translate(
"recipe.chance",
NEIClientUtils.formatNumber(
slot.getBookmarkItem().chance * 100f / PositionedStack.CHANCE_FULL)));
}
if (slot.getType() == BookmarkItemType.INGREDIENT && slot.getRecipeId() != null
&& slot.getBookmarkItem().permutations.size() > 1) {
RecipeId recipeId = slot.getRecipeId();
@@ -1119,7 +1144,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
for (BookmarkItem item : math.initialItems) {
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
final long amount = item.amount - invStackSize * item.fluidCellAmount;
final long amount = item.getAmount() - invStackSize * item.fluidCellAmount;
if (amount > 0) {
pullItemStacks.add(item.getItemStack(amount));
}
@@ -1133,7 +1158,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
for (BookmarkItem item : math.initialItems) {
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
final long strStackSize = containerStorage.getOrDefault(item.itemStack, 0L);
final long amount = item.amount - invStackSize * item.fluidCellAmount
final long amount = item.getAmount() - invStackSize * item.fluidCellAmount
- strStackSize * item.fluidCellAmount;
if (amount > 0) {
@@ -126,7 +126,7 @@ public class NEIClientUtils extends NEIServerUtils {
});
}
public static String formatNumber(long aNumber) {
public static String formatNumber(Number aNumber) {
if (NEIModContainer.isGTNHLibLoaded()) {
return NumberFormatUtil.formatNumber(aNumber);
@@ -135,7 +135,7 @@ public class NEIClientUtils extends NEIServerUtils {
return getDecimalFormat().format(aNumber);
}
public static String formatFluid(long aNumber) {
public static String formatFluid(Number aNumber) {
if (NEIModContainer.isGTNHLibLoaded()) {
return NumberFormatUtil.formatFluid(aNumber);
@@ -526,6 +526,11 @@ public class NEIClientUtils extends NEIServerUtils {
}
}
public static String getTextColorOrDefault(String key, String defaultColor) {
final String translated = NEIClientUtils.translate(key); // Optional localization string for resource packs
return translated.startsWith("nei.") ? defaultColor : translated;
}
public static void drawRect(double left, double top, double width, double height, Color color) {
final boolean is2DTexture = GL11.glGetBoolean(GL11.GL_TEXTURE_2D);
final boolean isBlend = GL11.glGetBoolean(GL11.GL_BLEND);
@@ -21,12 +21,16 @@ import codechicken.nei.recipe.StackInfo;
*/
public class PositionedStack {
/** Maximum chance value representing 100% probability (1 unit = 0.01%). */
public static final int CHANCE_FULL = 10_000;
public int relx;
public int rely;
public ItemStack[] items;
// compatibility dummy
public ItemStack item;
protected int chance = CHANCE_FULL;
private boolean permutated = false;
public PositionedStack(Object object, int x, int y, boolean genPerms) {
@@ -82,6 +86,10 @@ public class PositionedStack {
for (ItemStack item : items) if (item.stackSize > i) item.stackSize = i;
}
public int getChance() {
return this.chance;
}
public PositionedStack copy() {
PositionedStack pStack = new PositionedStack(
Arrays.stream(this.items).map(ItemStack::copy).toArray(ItemStack[]::new),
@@ -89,6 +97,7 @@ public class PositionedStack {
rely,
false);
pStack.permutated = this.permutated;
pStack.chance = getChance();
return pStack;
}
@@ -694,13 +694,10 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
if (NEIClientConfig.subsetWidgetOnTop()) {
return NEIClientUtils.translate("inventory.item_subsets");
} else {
final String translated = NEIClientUtils.translate("gui.button.label.subset");
if (!translated.startsWith("nei.")) { // Optional localization string for resource packs
return translated;
}
return EnumChatFormatting.DARK_PURPLE + String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX))
+ EnumChatFormatting.RESET;
return NEIClientUtils.getTextColorOrDefault(
"gui.button.label.subset",
EnumChatFormatting.DARK_PURPLE
+ String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX)));
}
}
@@ -23,6 +23,7 @@ import codechicken.nei.ItemsGrid.ItemsGridSlot;
import codechicken.nei.LayoutManager;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.SearchField;
import codechicken.nei.bookmark.BookmarkGrid;
import codechicken.nei.bookmark.BookmarkGroup;
@@ -646,8 +647,10 @@ public abstract class ShortcutInputHandler {
final List<ItemStack> playerInventory = AutoCraftingManager.getInventoryItems(guiContainer).values();
final RecipeId rootRecipeId = math.createMasterRoot();
for (BookmarkItem item : math.recipeIngredients) {
if (item.amount > 0 && rootRecipeId.equals(item.recipeId)) {
for (int i = 0; i < math.recipeIngredients.size(); i++) {
final BookmarkItem item = math.recipeIngredients.get(i);
if (item.getAmount() > 0 && rootRecipeId.equals(item.recipeId)) {
long amount = 0;
for (ItemStack stack : playerInventory) {
@@ -656,8 +659,12 @@ public abstract class ShortcutInputHandler {
}
}
if (amount >= item.amount) {
item.factor = item.amount = amount + item.amount - (amount % item.amount);
if (amount >= item.getAmount()) {
math.recipeIngredients.set(
i,
BookmarkItem.builder(item).multiplier(1)
.factor(amount + item.getAmount() - (amount % item.getAmount()))
.chance(PositionedStack.CHANCE_FULL).build());
}
}
}
@@ -24,7 +24,7 @@ import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
import codechicken.nei.ItemPanels;
import codechicken.nei.ItemStackAmount;
import codechicken.nei.ItemStackSet;
import codechicken.nei.ItemsGrid;
import codechicken.nei.ItemsGrid.MouseContext;
import codechicken.nei.LayoutManager;
@@ -33,6 +33,7 @@ import codechicken.nei.NEIClientUtils;
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
import codechicken.nei.recipe.Recipe;
import codechicken.nei.recipe.Recipe.RecipeId;
import codechicken.nei.recipe.Recipe.RecipeIngredient;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.recipe.chain.RecipeChainMath;
@@ -139,17 +140,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
if (group.collapsedRecipes.contains(collapsedRecipeId)) {
for (BookmarkItem item : this.bookmarkItems) {
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId)
&& item.amount == item.factor) {
item.amount = 0;
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.multiplier == 1) {
item.multiplier = 0;
}
}
} else {
for (BookmarkItem item : this.bookmarkItems) {
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.amount == 0) {
item.amount = item.factor;
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.multiplier == 0) {
item.multiplier = 1;
}
}
@@ -627,15 +627,17 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
for (int itemIndex = 0; itemIndex < this.bookmarkItems.size(); itemIndex++) {
final BookmarkItem item = this.bookmarkItems.get(itemIndex);
if (item.groupId == groupId && (recipeRelations == null || recipeRelations.contains(item.recipeId))) {
long amount = item.amount;
if (recipeId != null && group.crafting != null
&& group.crafting.calculatedItems.containsKey(itemIndex)
&& recipeId.equals(item.recipeId)) {
amount = group.crafting.calculatedItems.get(itemIndex).getCalculatedAmount();
chainItems.add(
item.copyWithMultiplier(
group.crafting.calculatedItems.get(itemIndex).getCalculatedMultiplier()));
} else {
chainItems.add(item.copy());
}
chainItems.add(item.copyWithAmount(amount));
}
}
@@ -896,34 +898,28 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
}
public void addRecipe(Recipe recipe, int multiplier, int groupId) {
final RecipeId recipeId = recipe.getRecipeId();
final List<ItemStack> results = recipe.getResults().stream().map(res -> res.getItemStack())
.collect(Collectors.toList());
final List<ItemStack> ingredients = recipe.getIngredients().stream().map(ingr -> ingr.getItemStack())
.collect(Collectors.toList());
final ItemStackSet results = new ItemStackSet();
final ItemStackSet ingredients = new ItemStackSet();
for (ItemStack stack : ItemStackAmount.of(results).values()) {
long factor = StackInfo.getAmount(stack);
for (RecipeIngredient result : recipe.getResults()) {
results.add(result.getItemStack());
}
for (RecipeIngredient ingr : recipe.getIngredients()) {
ingredients.add(ingr.getItemStack());
}
for (ItemStack stack : results.values()) {
this.addItem(
BookmarkItem.of(
groupId,
StackInfo.withAmount(stack, factor * multiplier),
factor,
recipeId,
BookmarkItemType.RESULT),
BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.RESULT).multiplier(multiplier)
.build(),
true);
}
for (ItemStack stack : ItemStackAmount.of(ingredients).values()) {
long factor = StackInfo.getAmount(stack);
for (ItemStack stack : ingredients.values()) {
this.addItem(
BookmarkItem.of(
groupId,
StackInfo.withAmount(stack, factor * multiplier),
factor,
recipeId,
BookmarkItemType.INGREDIENT,
BookmarkItem.generatePermutations(stack, recipe)),
BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.INGREDIENT).multiplier(multiplier)
.build(),
true);
}
}
@@ -1133,8 +1129,8 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
final Set<Long> sizes = new HashSet<>();
for (BookmarkItem item : this.bookmarkItems) {
if (item.groupId == targetGroupId && item.amount > 0) {
sizes.add(Math.max(item.getStackSize(), item.factor / item.fluidCellAmount));
if (item.groupId == targetGroupId && item.getAmount() > 0) {
sizes.add(Math.max(item.getStackSize(), item.getStackSize(item.getAmount(1))));
items.add(item);
}
}
@@ -1143,14 +1139,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
long multiplier = Integer.MAX_VALUE;
for (BookmarkItem item : items) {
long customFactor = (long) Math.ceil(item.amount / (double) gcd);
long customMultiplier = (long) (customFactor > 0 ? Math.ceil(item.amount / (double) customFactor) : 0);
final long amount = item.getAmount();
final long customFactor = (amount + gcd - 1) / gcd;
final long customMultiplier = customFactor > 0 ? ((amount + customFactor - 1) / customFactor) : 0;
multiplier = Math.min(shiftMultiplier(customMultiplier, shift, 1), multiplier);
}
for (BookmarkItem item : items) {
long customFactor = (long) Math.ceil(item.amount / (double) gcd);
item.amount = customFactor * multiplier;
final long amount = item.getAmount();
final long customFactor = (amount + gcd - 1) / gcd;
item.multiplier = item.getMultiplierFromAmount(customFactor * multiplier);
}
} else {
final Map<RecipeId, Long> recipeMultipliers = new HashMap<>();
@@ -1158,7 +1156,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
final List<BookmarkItem> items = new ArrayList<>();
for (BookmarkItem item : this.bookmarkItems) {
if (item.factor > 0
if (!item.emptyFactor()
&& outputRecipes.stream().anyMatch(recipeId -> item.equalsRecipe(recipeId, targetGroupId))) {
final long multiplier = recipeMultipliers.getOrDefault(item.recipeId, (long) Integer.MAX_VALUE);
final boolean recipeInMiddle = group.crafting != null
@@ -1168,7 +1166,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
item.recipeId,
Math.min(
shiftMultiplier(
Math.max(recipeInMiddle ? 1 : 0, item.getMultiplier()),
Math.max(recipeInMiddle ? 1 : 0, item.multiplier),
shift,
recipeInMiddle ? 1 : 0),
multiplier));
@@ -1177,7 +1175,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
}
for (BookmarkItem item : items) {
item.amount = item.factor * recipeMultipliers.getOrDefault(item.recipeId, 0L);
item.multiplier = recipeMultipliers.getOrDefault(item.recipeId, 0L);
}
}
@@ -1197,10 +1195,10 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
long multiplier = Integer.MAX_VALUE;
for (BookmarkItem item : this.bookmarkItems) {
if (item.equalsRecipe(recipeId, targetItem.groupId) && item.factor > 0) {
if (item.equalsRecipe(recipeId, targetItem.groupId) && !item.emptyFactor()) {
multiplier = Math.min(
shiftMultiplier(
Math.max(recipeInMiddle ? 1 : 0, item.getMultiplier()),
Math.max(recipeInMiddle ? 1 : 0, item.multiplier),
shift,
recipeInMiddle ? 1 : 0),
multiplier);
@@ -1208,8 +1206,8 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
}
for (BookmarkItem item : this.bookmarkItems) {
if (item.equalsRecipe(recipeId, targetItem.groupId) && item.factor > 0) {
item.amount = item.factor * multiplier;
if (item.equalsRecipe(recipeId, targetItem.groupId) && !item.emptyFactor()) {
item.multiplier = multiplier;
}
}
@@ -1217,7 +1215,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
for (BookmarkItem item : this.bookmarkItems) {
if (targetItem.equals(item)) {
item.amount = item.factor * shiftMultiplier(item.getMultiplier(), shift, 0);
item.multiplier = shiftMultiplier(item.multiplier, shift, 0);
break;
}
}
@@ -189,13 +189,11 @@ public class BookmarkGridGenerator {
for (int shadowIndex : shadows) {
final boolean isIngredient = shadows.get(0) != shadowIndex
|| group.crafting.calculatedItems.get(shadowIndex).calculatedType == CalculatedType.INGREDIENT;
final BookmarkItem shadowBookmarkItem = BookmarkItem.of(
bookmarkItem.groupId,
bookmarkItem.itemStack,
1,
bookmarkItem.recipeId,
isIngredient ? BookmarkItemType.INGREDIENT : BookmarkItemType.RESULT,
Collections.emptyMap());
final BookmarkItem shadowBookmarkItem = BookmarkItem.builder(bookmarkItem.groupId, bookmarkItem.itemStack)
.multiplier(1).factor(StackInfo.getAmount(bookmarkItem.itemStack)).recipeId(bookmarkItem.recipeId)
.type(isIngredient ? BookmarkItemType.INGREDIENT : BookmarkItemType.RESULT)
.permutations(Collections.emptyMap()).build();
if ((absoluteSlotIndex = nextSlotIndex(
absoluteSlotIndex + 1,
@@ -320,7 +318,7 @@ public class BookmarkGridGenerator {
return group.crafting.calculatedItems.get(itemIndex);
} else {
BookmarkChainItem item = BookmarkChainItem.of(this.grid.getBookmarkItem(itemIndex));
item.setRealAmount(item.getShiftAmount());
item.setRealMultiplier(item.getItem().getMultiplierFromAmount(item.getShiftAmount()));
return item;
}
}
@@ -333,7 +331,7 @@ public class BookmarkGridGenerator {
return new BookmarksGridSlot(
slotIndex,
itemIndex,
chainItem.getRealAmount(),
chainItem.getRealMultiplier(),
0,
0,
chainItem.getItem(),
@@ -343,9 +341,9 @@ public class BookmarkGridGenerator {
return new BookmarksGridSlot(
slotIndex,
itemIndex,
chainItem.getRealAmount(),
chainItem.getRealMultiplier(),
chainItem.getShiftAmount(),
chainItem.getCalculatedAmount(),
chainItem.getCalculatedMultiplier(),
chainItem.getItem(),
chainItem.calculatedType,
group);
@@ -2,6 +2,7 @@ package codechicken.nei.bookmark;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -10,6 +11,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.recipe.Recipe;
import codechicken.nei.recipe.Recipe.RecipeId;
import codechicken.nei.recipe.Recipe.RecipeIngredient;
@@ -17,6 +19,140 @@ import codechicken.nei.recipe.StackInfo;
public class BookmarkItem {
public static class Builder {
private static Map<ItemStack, String> fuzzyPermutations = new HashMap<>();
private final int groupId;
private final ItemStack stack;
private long factor;
private long multiplier = -1;
private long chance = PositionedStack.CHANCE_FULL;
private RecipeId recipeId = null;
private Recipe recipe = null;
private BookmarkItemType type = BookmarkItemType.ITEM;
private Map<String, ItemStack> permutations = null;
private Builder(int groupId, ItemStack stack) {
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
this.groupId = groupId;
this.stack = stack;
this.factor = nbTag.hasKey("gtFluidName") ? Math.min(144, nbTag.getInteger("Count")) : 1;
}
public Builder factor(long factor) {
this.factor = factor;
return this;
}
public Builder multiplier(long multiplier) {
this.multiplier = multiplier;
return this;
}
public Builder chance(long chance) {
this.chance = chance;
return this;
}
public Builder recipe(Recipe recipe) {
this.recipe = recipe;
this.recipeId = null;
return this;
}
public Builder recipeId(RecipeId recipeId) {
this.recipeId = recipeId;
this.recipe = null;
return this;
}
public Builder type(BookmarkItemType type) {
this.type = type;
return this;
}
public Builder permutations(Map<String, ItemStack> permutations) {
this.permutations = permutations;
return this;
}
public BookmarkItem build() {
final Map<String, ItemStack> perms;
if (this.permutations != null) {
perms = this.permutations;
} else if (this.type == BookmarkItemType.INGREDIENT) {
if (this.recipe != null) {
perms = Builder.generatePermutations(this.stack, this.recipe);
} else if (this.recipeId != null) {
perms = Builder.generatePermutations(this.stack, Recipe.of(this.recipeId));
} else {
perms = Builder.generatePermutations(this.stack);
}
} else {
perms = Builder.generatePermutations(this.stack);
}
return new BookmarkItem(
this.groupId,
this.multiplier >= 0 ? this.multiplier : StackInfo.getAmount(this.stack) / this.factor,
this.factor,
this.chance,
this.stack,
perms,
this.recipeId != null ? this.recipeId : this.recipe != null ? this.recipe.getRecipeId() : null,
this.type);
}
public static Map<String, ItemStack> generatePermutations(ItemStack stack) {
return Collections.singletonMap(getItemGUID(stack), stack);
}
public static Map<String, ItemStack> generatePermutations(ItemStack stack, Recipe recipe) {
if (recipe != null) {
final RecipeIngredient ingr = recipe.getIngredients().stream()
.filter(ingredient -> ingredient.contains(stack)).findAny().orElse(null);
if (ingr != null) {
final Map<String, ItemStack> permutations = new HashMap<>();
for (ItemStack ingrStack : ingr.getPermutations()) {
permutations.put(getItemGUID(ingrStack), ingrStack);
}
return permutations;
}
}
return generatePermutations(stack);
}
private static synchronized String getItemGUID(ItemStack stack) {
final FluidStack fluidStack = StackInfo.getFluid(stack);
if (fluidStack != null) {
return fluidStack.getFluid().getName() + ":" + fluidStack.tag;
} else {
for (Map.Entry<ItemStack, String> entry : Builder.fuzzyPermutations.entrySet()) {
if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) {
Builder.fuzzyPermutations.put(stack, entry.getValue());
return entry.getValue();
}
}
final String stackGUID = StackInfo.getItemStackGUID(stack);
Builder.fuzzyPermutations.put(stack, stackGUID);
return stackGUID;
}
}
}
public enum BookmarkItemType {
INGREDIENT,
@@ -32,150 +168,128 @@ public class BookmarkItem {
}
}
private static Map<ItemStack, String> fuzzyPermutations = new HashMap<>();
public int groupId;
public long amount = 0L;
public final int fluidCellAmount;
public ItemStack itemStack;
public Map<String, ItemStack> permutations;
public long factor;
public RecipeId recipeId;
public BookmarkItemType type = BookmarkItemType.ITEM;
protected BookmarkItem(int groupId, long amount, int fluidCellAmount, ItemStack itemStack,
Map<String, ItemStack> permutations, long factor, RecipeId recipeId, BookmarkItemType type) {
public long multiplier = 1L;
public final long factor;
public final int fluidCellAmount;
public final long chance;
protected BookmarkItem(int groupId, long multiplier, long factor, long chance, ItemStack itemStack,
Map<String, ItemStack> permutations, RecipeId recipeId, BookmarkItemType type) {
final FluidStack fluidStack = StackInfo.getFluid(itemStack);
if (fluidStack != null) {
this.fluidCellAmount = Math.max(1, StackInfo.isFluidContainer(itemStack) ? fluidStack.amount : 1);
} else {
this.fluidCellAmount = 1;
}
this.groupId = groupId;
this.amount = amount;
this.fluidCellAmount = fluidCellAmount;
this.itemStack = itemStack;
this.permutations = permutations;
this.factor = factor;
this.recipeId = recipeId;
this.type = type == null ? BookmarkItemType.ITEM : type;
this.multiplier = multiplier;
this.factor = factor;
this.chance = chance;
}
public static BookmarkItem of(int groupId, ItemStack stack, long factor, RecipeId recipeId, BookmarkItemType type,
Map<String, ItemStack> permutations) {
final FluidStack fluidStack = StackInfo.getFluid(stack);
int fluidCellAmount = 1;
long amount;
public static Builder builder(int groupId, ItemStack stack) {
return new Builder(groupId, stack);
}
if (fluidStack != null) {
amount = fluidStack.amount * (long) Math.max(0, stack.stackSize);
fluidCellAmount = Math.max(1, StackInfo.isFluidContainer(stack) ? fluidStack.amount : 1);
} else {
amount = StackInfo.getAmount(stack);
public static Builder builder(BookmarkItem item) {
return new Builder(item.groupId, item.itemStack).factor(item.factor).multiplier(item.multiplier)
.chance(item.chance).recipeId(item.recipeId).type(item.type).permutations(item.permutations);
}
public static Builder builder(int groupId, ItemStack stack, Recipe recipe, BookmarkItemType type) {
final List<RecipeIngredient> items = type == BookmarkItemType.RESULT ? recipe.getResults()
: recipe.getIngredients();
final Builder builder = builder(groupId, stack).type(type).recipe(recipe);
long amount = 0;
for (RecipeIngredient res : items) {
if (res.contains(stack)) {
amount += res.getAmount() * res.getChance();
}
}
return new BookmarkItem(
groupId,
amount,
fluidCellAmount,
stack,
permutations,
factor * fluidCellAmount,
recipeId,
type);
}
if ((amount % PositionedStack.CHANCE_FULL) == 0) {
builder.factor(amount / PositionedStack.CHANCE_FULL);
} else {
builder.factor(1).chance(amount);
}
public static BookmarkItem of(int groupId, ItemStack stack, long factor, RecipeId recipeId, BookmarkItemType type) {
return of(
groupId,
stack,
factor,
recipeId,
type,
generatePermutations(stack, recipeId, type == BookmarkItemType.INGREDIENT));
return builder;
}
public static BookmarkItem of(int groupId, ItemStack stack) {
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
final long factor = nbTag.hasKey("gtFluidName") ? Math.min(144, nbTag.getInteger("Count")) : 1;
return BookmarkItem.of(
groupId,
stack,
factor,
null,
BookmarkItemType.ITEM,
Collections.singletonMap(getItemGUID(stack), stack));
return builder(groupId, stack).build();
}
public BookmarkItem copyWithAmount(long amount) {
public BookmarkItem copyWithMultiplier(long multiplier) {
return new BookmarkItem(
this.groupId,
amount,
this.fluidCellAmount,
multiplier,
this.factor,
this.chance,
this.itemStack,
this.permutations,
this.factor,
this.recipeId,
this.type);
}
public BookmarkItem copyWithAmount(long amount) {
return copyWithMultiplier(getMultiplierFromAmount(amount));
}
public BookmarkItem copy() {
return copyWithAmount(this.amount);
}
public static Map<String, ItemStack> generatePermutations(ItemStack stack, RecipeId recipeId,
boolean isIngredient) {
if (isIngredient && recipeId != null) {
return generatePermutations(stack, Recipe.of(recipeId));
}
return Collections.singletonMap(getItemGUID(stack), stack);
}
public static Map<String, ItemStack> generatePermutations(ItemStack stack, Recipe recipe) {
if (recipe != null) {
final RecipeIngredient ingr = recipe.getIngredients().stream()
.filter(ingredient -> ingredient.contains(stack)).findAny().orElse(null);
if (ingr != null) {
final Map<String, ItemStack> permutations = new HashMap<>();
for (ItemStack ingrStack : ingr.getPermutations()) {
permutations.put(getItemGUID(ingrStack), ingrStack);
}
return permutations;
}
}
return Collections.singletonMap(getItemGUID(stack), stack);
}
private static synchronized String getItemGUID(ItemStack stack) {
final FluidStack fluidStack = StackInfo.getFluid(stack);
if (fluidStack != null) {
return fluidStack.getFluid().getName() + ":" + fluidStack.tag;
} else {
for (Map.Entry<ItemStack, String> entry : BookmarkItem.fuzzyPermutations.entrySet()) {
if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) {
BookmarkItem.fuzzyPermutations.put(stack, entry.getValue());
return entry.getValue();
}
}
final String stackGUID = StackInfo.getItemStackGUID(stack);
BookmarkItem.fuzzyPermutations.put(stack, stackGUID);
return stackGUID;
}
return copyWithMultiplier(this.multiplier);
}
public boolean containsItems(BookmarkItem item) {
return this.permutations.keySet().stream().anyMatch(item.permutations::containsKey);
}
public long getAmount() {
return getAmount(this.multiplier);
}
public long getAmount(long multiplier) {
long amount = this.factor * multiplier;
if (this.fluidCellAmount > 1) {
amount = amount * this.fluidCellAmount;
}
if (this.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;
} else {
// For results, round down the expected amount to be conservative.
amount = (amount * this.chance) / PositionedStack.CHANCE_FULL;
}
}
return amount;
}
public ItemStack getItemStack() {
return getItemStack(this.amount);
return getItemStack(getAmount());
}
public ItemStack getItemStack(long amount) {
@@ -183,23 +297,34 @@ public class BookmarkItem {
}
public long getStackSize() {
return getStackSize(this.amount);
return getStackSize(getAmount());
}
public long getStackSize(long amount) {
return (long) (this.factor > 0 ? Math.ceil(amount / (double) this.fluidCellAmount) : 0);
if (this.fluidCellAmount > 1) {
amount = (amount + this.fluidCellAmount - 1) / this.fluidCellAmount;
}
return amount;
}
public long getMultiplierFromAmount(long amount) {
if (this.factor <= 0 || this.chance <= 0) return 0;
if (this.fluidCellAmount > 1) {
amount = (amount + this.fluidCellAmount - 1) / this.fluidCellAmount;
}
if (this.chance == PositionedStack.CHANCE_FULL) {
return (amount + this.factor - 1) / this.factor;
}
return (amount * PositionedStack.CHANCE_FULL + this.factor * this.chance - 1) / (this.factor * this.chance);
}
public long getMultiplier() {
return getMultiplier(this.amount);
}
public long getMultiplier(long amount) {
return (long) (this.factor > 0 ? Math.ceil(amount / (double) this.factor) : 0);
}
public long getFactor() {
return this.factor / this.fluidCellAmount;
return this.multiplier;
}
public boolean equalsRecipe(BookmarkItem meta) {
@@ -210,6 +335,10 @@ public class BookmarkItem {
return groupId == this.groupId && recipeId != null && recipeId.equals(this.recipeId);
}
public boolean emptyFactor() {
return this.factor <= 0 || this.chance <= 0;
}
@Override
public int hashCode() {
return Objects.hash(this.groupId, this.fluidCellAmount, this.type.toInt(), this.recipeId);
@@ -25,6 +25,7 @@ import com.google.gson.JsonSyntaxException;
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.PositionedStack;
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
import codechicken.nei.recipe.Recipe.RecipeId;
import codechicken.nei.recipe.StackInfo;
@@ -249,30 +250,36 @@ public class BookmarkStorage {
ItemStack itemStack = StackInfo.loadFromNBT(itemStackNBT);
if (itemStack != null) {
RecipeId recipeId = null;
boolean isFluid = itemStackNBT.hasKey("gtFluidName");
int groupId = jsonObject.has("groupId") ? jsonObject.get("groupId").getAsInt()
int groupId = jsonObject.has("groupId") && grid.groups.containsKey(jsonObject.get("groupId").getAsInt())
? jsonObject.get("groupId").getAsInt()
: BookmarkGrid.DEFAULT_GROUP_ID;
int factor = jsonObject.has("factor") ? Math.abs(jsonObject.get("factor").getAsInt()) : (isFluid ? 144 : 1);
BookmarkItemType type = jsonObject.has("type") ? BookmarkItemType.fromInt(jsonObject.get("type").getAsInt())
: null;
final BookmarkItem.Builder builder = BookmarkItem.builder(groupId, itemStack);
if (type == null) {
// old format
type = jsonObject.has("ingredient") && jsonObject.get("ingredient").getAsBoolean()
? BookmarkItemType.INGREDIENT
: BookmarkItemType.RESULT;
if (jsonObject.has("type")) {
builder.type(BookmarkItemType.fromInt(jsonObject.get("type").getAsInt()));
} else if (jsonObject.has("ingredient") && jsonObject.get("ingredient").getAsBoolean()) {
builder.type(BookmarkItemType.INGREDIENT);
} else {
builder.type(BookmarkItemType.RESULT);
}
if (jsonObject.has("multiplier")) {
builder.multiplier(jsonObject.get("multiplier").getAsInt());
}
if (jsonObject.has("factor")) {
builder.factor(jsonObject.get("factor").getAsInt());
}
if (jsonObject.has("chance")) {
builder.chance(jsonObject.get("chance").getAsInt());
}
if (jsonObject.get("recipeId") instanceof JsonObject recipeJson) {
recipeId = RecipeId.of(recipeJson);
builder.recipeId(RecipeId.of(recipeJson));
}
if (!grid.groups.containsKey(groupId)) {
groupId = BookmarkGrid.DEFAULT_GROUP_ID;
}
grid.addItem(BookmarkItem.of(groupId, itemStack, factor, recipeId, type), false);
grid.addItem(builder.build(), false);
}
return itemStack != null;
@@ -321,7 +328,8 @@ public class BookmarkStorage {
JsonObject row = new JsonObject();
row.add("item", NBTJson.toJsonObject(StackInfo.itemStackToNBT(item.getItemStack())));
row.add("factor", new JsonPrimitive(item.getFactor()));
row.add("multiplier", new JsonPrimitive(item.multiplier));
row.add("factor", new JsonPrimitive(item.factor));
row.add("type", new JsonPrimitive(item.type.toInt()));
if (item.groupId != BookmarkGrid.DEFAULT_GROUP_ID) {
@@ -332,6 +340,10 @@ public class BookmarkStorage {
row.add("recipeId", item.recipeId.toJsonObject());
}
if (item.chance != PositionedStack.CHANCE_FULL) {
row.add("chance", new JsonPrimitive(item.chance));
}
strings.add(NBTJson.toJson(row));
} catch (JsonSyntaxException e) {
NEIClientConfig.logger.error("Failed to stringify bookmarked ItemStack to json string");
@@ -14,6 +14,7 @@ import codechicken.nei.ItemsGrid.MouseContext;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIClientUtils.Alignment;
import codechicken.nei.PositionedStack;
import codechicken.nei.bookmark.BookmarkGrid.BookmarkMouseContext;
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
import codechicken.nei.bookmark.RecipeChainDetails.CalculatedType;
@@ -63,18 +64,18 @@ public class BookmarksGridSlot extends ItemsGridSlot {
protected final boolean isFirstOutput;
protected final int rowIndex;
public BookmarksGridSlot(int slotIndex, int itemIndex, long realAmount, long shiftAmount, long calculatedAmount,
BookmarkItem bookmarkItem, CalculatedType calculatedType, BookmarkGroup group) {
public BookmarksGridSlot(int slotIndex, int itemIndex, long realMultiplier, long shiftAmount,
long calculatedMultiplier, BookmarkItem bookmarkItem, CalculatedType calculatedType, BookmarkGroup group) {
super(
slotIndex,
itemIndex,
calculatedType != null ? bookmarkItem.getItemStack(calculatedAmount)
: bookmarkItem.getItemStack(realAmount));
calculatedType != null ? bookmarkItem.getItemStack(bookmarkItem.getAmount(calculatedMultiplier))
: bookmarkItem.getItemStack(bookmarkItem.getAmount(realMultiplier)));
this.emptyItemStack = bookmarkItem.getItemStack(0);
this.realAmount = realAmount;
this.realAmount = bookmarkItem.getAmount(realMultiplier);
this.shiftAmount = shiftAmount;
this.calculatedAmount = calculatedAmount;
this.calculatedAmount = calculatedType != null ? bookmarkItem.getAmount(calculatedMultiplier) : this.realAmount;
this.group = group;
this.calculatedType = calculatedType;
@@ -83,8 +84,8 @@ public class BookmarksGridSlot extends ItemsGridSlot {
this.isOutputRecipe = group.crafting != null && group.crafting.outputRecipes.contains(bookmarkItem.recipeId);
this.isFluidDisplay = StackInfo.itemStackToNBT(bookmarkItem.itemStack).hasKey("gtFluidName");
this.realMultiplier = bookmarkItem.getMultiplier(realAmount);
this.calculatedMultiplier = bookmarkItem.getMultiplier(calculatedAmount);
this.realMultiplier = realMultiplier;
this.calculatedMultiplier = calculatedMultiplier;
if (this.group.crafting != null && this.group.crafting.calculatedItems.containsKey(this.itemIndex)) {
this.realType = this.group.crafting.calculatedItems.get(this.itemIndex).calculatedType
@@ -355,9 +356,10 @@ public class BookmarksGridSlot extends ItemsGridSlot {
amount = this.shiftAmount;
}
if (amount > 0 || shownItemType == ShownItemType.REAL && this.bookmarkItem.factor > 0) {
if (amount > 0 || shownItemType == ShownItemType.REAL && !this.bookmarkItem.emptyFactor()) {
final float panelFactor = (rect.w - 2) / (DEFAULT_SLOT_SIZE - 2);
final long stackSize = this.bookmarkItem.getStackSize(amount);
int color = 0xFFFFFF;
String amountString = "";
if (stackSize < 10_000) {
@@ -370,11 +372,16 @@ public class BookmarksGridSlot extends ItemsGridSlot {
amountString += "L";
}
if (this.bookmarkItem.chance != PositionedStack.CHANCE_FULL) {
amountString = "~" + amountString;
color = 0xFFAA00;
}
NEIClientUtils.drawNEIOverlayText(
amountString,
new Rectangle4i(rect.x + 1, rect.y + 1, rect.w - 2, rect.h - 2),
panelFactor,
0xFFFFFF,
color,
true,
this.isFluidDisplay ? Alignment.BottomLeft : Alignment.BottomRight);
}
@@ -42,34 +42,35 @@ public class RecipeChainDetails {
private final BookmarkItem item;
private long realAmount = 0L;
private long realMultiplier = 0L;
private long shiftAmount = 0L;
private long calculatedAmount = 0L;
private long calculatedMultiplier = 0L;
public CalculatedType calculatedType;
protected BookmarkChainItem(BookmarkItem item, long shiftItem, long calculatedItem,
protected BookmarkChainItem(BookmarkItem item, long shiftItem, long calculatedMultiplier,
CalculatedType calculatedType) {
this.item = item.copy();
this.shiftAmount = shiftItem;
this.calculatedAmount = calculatedItem;
this.calculatedMultiplier = calculatedMultiplier;
this.calculatedType = calculatedType;
}
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, long calculatedAmount,
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, long calculatedMultiplier,
CalculatedType calculatedType) {
return new BookmarkChainItem(item, shiftItem, calculatedAmount, calculatedType);
return new BookmarkChainItem(item, shiftItem, calculatedMultiplier, calculatedType);
}
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, CalculatedType calculatedType) {
return new BookmarkChainItem(item, shiftItem, item.amount, calculatedType);
return new BookmarkChainItem(item, shiftItem, item.getMultiplier(), calculatedType);
}
public static BookmarkChainItem of(BookmarkItem item) {
final long amount = item.getAmount();
return new BookmarkChainItem(
item,
item.amount,
item.amount,
amount,
amount,
item.type == BookmarkItemType.INGREDIENT ? CalculatedType.INGREDIENT : CalculatedType.RESULT);
}
@@ -77,30 +78,34 @@ public class RecipeChainDetails {
return this.item.getItemStack(amount);
}
public void setRealAmount(long amount) {
this.realAmount = amount;
public void setRealMultiplier(long multiplier) {
this.realMultiplier = multiplier;
}
public long getRealAmount() {
return this.realAmount;
public long getRealMultiplier() {
return this.realMultiplier;
}
public void setCalculatedMultiplier(long multiplier) {
this.calculatedMultiplier = multiplier;
}
public long getCalculatedMultiplier() {
return this.calculatedMultiplier;
}
public long getShiftAmount() {
return this.shiftAmount;
}
public long getCalculatedAmount() {
return this.calculatedAmount;
}
public BookmarkItem getItem() {
return this.item;
}
public void append(long amount, long calculatedAmount) {
this.shiftAmount += amount;
this.calculatedAmount += calculatedAmount;
this.item.amount = this.calculatedAmount;
this.calculatedMultiplier += this.item.getMultiplierFromAmount(calculatedAmount);
this.item.multiplier = this.calculatedMultiplier;
}
}
@@ -180,10 +185,9 @@ public class RecipeChainDetails {
if (itemIndex >= 0 && this.calculatedItems.containsKey(itemIndex)) {
final BookmarkItem item = entry.getValue();
if (this.recipeInMiddle.contains(item.recipeId)) {
this.calculatedItems.get(itemIndex)
.setRealAmount(Math.max(0, item.factor * (item.getMultiplier() - 1)));
this.calculatedItems.get(itemIndex).setRealMultiplier(item.getMultiplier() - 1);
} else {
this.calculatedItems.get(itemIndex).setRealAmount(item.amount);
this.calculatedItems.get(itemIndex).setRealMultiplier(item.getMultiplier());
}
}
}
@@ -239,7 +243,7 @@ public class RecipeChainDetails {
for (BookmarkItem item : chainItems) {
if (recipeRelations.contains(item.recipeId)) {
subChainItems.add(item.copyWithAmount(recipeId.equals(item.recipeId) ? item.amount : 0));
subChainItems.add(item.copyWithMultiplier(recipeId.equals(item.recipeId) ? item.multiplier : 0));
}
}
@@ -258,7 +262,8 @@ public class RecipeChainDetails {
}
if (this.calculatedItems.containsKey(itemIndex)) {
this.calculatedItems.get(itemIndex).setRealAmount(value.getShiftAmount());
this.calculatedItems.get(itemIndex)
.setRealMultiplier(value.getItem().getMultiplierFromAmount(value.getShiftAmount()));
}
}
@@ -272,18 +277,19 @@ public class RecipeChainDetails {
for (RecipeId relRecipeId : recipeRelations) {
for (BookmarkItem item : math.recipeResults) {
if (item.recipeId.equals(relRecipeId)) {
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
if (item.recipeId.equals(recipeId)) {
multiplier.put(item.recipeId, item.getMultiplier());
items.computeIfAbsent(
StackInfo.getItemStackGUID(item.itemStack),
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT))
.append(amount, item.amount);
.append(amount, item.getAmount());
} else if (amount > 0) {
items.computeIfAbsent(
StackInfo.getItemStackGUID(item.itemStack),
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT)).append(amount, amount);
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT))
.append(amount, item.getAmount());
}
}
}
@@ -292,17 +298,17 @@ public class RecipeChainDetails {
if (item.recipeId.equals(relRecipeId)) {
final BookmarkItem prefItem = math.preferredItems.get(item);
final long amount = math.requiredAmount.containsKey(prefItem) ? 0
: math.requiredAmount.getOrDefault(item, item.amount);
: math.requiredAmount.getOrDefault(item, item.getAmount());
final long refAmount = prefItem != null && !topLevelRecipes.contains(prefItem.recipeId)
? math.requiredAmount.getOrDefault(prefItem, 0L)
: 0;
if (amount != 0 || item.amount > refAmount && math.requiredAmount.containsKey(prefItem)
if (amount != 0 || item.getAmount() > refAmount && math.requiredAmount.containsKey(prefItem)
|| recipeId.equals(item.recipeId) && multiplier.get(recipeId) == 0) {
items.computeIfAbsent(
StackInfo.getItemStackGUID(item.itemStack),
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.INGREDIENT))
.append(amount, item.amount - refAmount);
.append(amount, item.getAmount() - refAmount);
}
}
}
@@ -312,7 +318,7 @@ public class RecipeChainDetails {
}
private void generateResult(RecipeChainMath math, BookmarkItem item, int itemIndex) {
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
final CalculatedType calculatedType = math.outputRecipes.containsKey(item.recipeId) ? CalculatedType.RESULT
: CalculatedType.REMAINDER;
@@ -322,7 +328,7 @@ public class RecipeChainDetails {
private void generateIngredient(RecipeChainMath math, BookmarkItem item, int itemIndex) {
final BookmarkItem prefItem = math.preferredItems.get(item);
final long amount = math.requiredAmount.containsKey(prefItem) ? 0
: math.requiredAmount.getOrDefault(item, item.amount);
: math.requiredAmount.getOrDefault(item, item.getAmount());
this.calculatedItems.put(itemIndex, BookmarkChainItem.of(item, amount, CalculatedType.INGREDIENT));
}
@@ -103,6 +103,7 @@ public class IMCHandler {
info.setUseCustomScroll(tag.hasKey("useCustomScroll") && tag.getBoolean("useCustomScroll"));
info.setShowFavoritesButton(!tag.hasKey("showFavoritesButton") || tag.getBoolean("showFavoritesButton"));
info.setShowOverlayButton(!tag.hasKey("showOverlayButton") || tag.getBoolean("showOverlayButton"));
info.setShowChanceInfo(!tag.hasKey("showChanceInfo") || tag.getBoolean("showChanceInfo"));
GuiRecipeTab.handlerAdderFromIMC.remove(handler);
GuiRecipeTab.handlerAdderFromIMC.put(handler, info);
@@ -5,6 +5,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
@@ -23,7 +24,11 @@ import codechicken.nei.guihook.GuiContainerManager;
public class ItemPanelDumper extends DataDumper {
private static final int[] resolutions = new int[] { 16, 32, 48, 64, 128, 256 };
public static final int CSV = 0;
public static final int NBT = 1;
public static final int JSON = 2;
public static final int PNG = 3;
private static final Minecraft mc = Minecraft.getMinecraft();
public ItemPanelDumper(String name) {
super(name);
@@ -54,19 +59,29 @@ public class ItemPanelDumper extends DataDumper {
public int getRes() {
int i = renderTag(name + ".res").getIntValue(0);
if (i >= resolutions.length || i < 0) renderTag().setIntValue(i = 0);
return resolutions[i];
int size = 16 << i;
if (size >= getSmallerScreenAxisSize() || i < 0) {
getTag(name + ".res").setIntValue(0);
size = 16;
}
return size;
}
private int getSmallerScreenAxisSize() {
int width = mc.displayWidth;
int height = mc.displayHeight;
return Math.min(width, height);
}
public Rectangle4i resButtonSize() {
int width = 50;
int width = 60;
return new Rectangle4i(modeButtonSize().x - width - 6, 0, width, 20);
}
@Override
public void draw(int mousex, int mousey, float frame) {
super.draw(mousex, mousey, frame);
if (getMode() == 3) {
if (getMode() == PNG) {
int res = getRes();
drawButton(mousex, mousey, resButtonSize(), res + "x" + res);
}
@@ -74,23 +89,35 @@ public class ItemPanelDumper extends DataDumper {
@Override
public void mouseClicked(int mousex, int mousey, int button) {
if (getMode() == 3 && resButtonSize().contains(mousex, mousey)) {
if (getMode() != PNG) {
super.mouseClicked(mousex, mousey, button);
return;
}
if (resButtonSize().contains(mousex, mousey)) {
NEIClientUtils.playClickSound();
getTag(name + ".res").setIntValue((renderTag(name + ".res").getIntValue(0) + 1) % resolutions.length);
} else super.mouseClicked(mousex, mousey, button);
int current = renderTag(name + ".res").getIntValue(0);
int next;
// 31 - numberOfLeadingZeros(x) = floor(log2(x))
int max = 31 - Integer.numberOfLeadingZeros(getSmallerScreenAxisSize()) - 3;
if (button == 1) { // Right click to cycle backward
next = (current - 1 + max) % max;
} else { // Left click to cycle forward
next = (current + 1) % max;
}
getTag(name + ".res").setIntValue(next);
} else if (!dumpButtonSize().contains(mousex, mousey) || acknowledgedItemSizeWarning()) {
super.mouseClicked(mousex, mousey, button);
}
}
@Override
public String getFileExtension() {
switch (getMode()) {
case 0:
return ".csv";
case 1:
return ".nbt";
case 2:
return ".json";
}
return null;
return switch (getMode()) {
case CSV -> ".csv";
case NBT -> ".nbt";
case JSON -> ".json";
default -> null;
};
}
@Override
@@ -105,15 +132,29 @@ public class ItemPanelDumper extends DataDumper {
@Override
public void dumpFile() {
if (getMode() == 3) Minecraft.getMinecraft().displayGuiScreen(new GuiItemIconDumper(this, getRes()));
if (getMode() == PNG && acknowledgedItemSizeWarning())
mc.displayGuiScreen(new GuiItemIconDumper(this, getRes()));
else super.dumpFile();
}
private boolean acknowledgedItemSizeWarning() {
return !showItemSizeWarning() || NEIClientUtils.shiftKey();
}
private boolean showItemSizeWarning() {
int res = getRes();
// More than 4 items at 2048x2048, 16 items at 1024x1024, 64 at 512x512, etc.
int WARNING_SIZE = 16_777_216;
return ItemPanels.itemPanel.getItems().size() * res * res > WARNING_SIZE;
}
@Override
public void dumpTo(File file) throws IOException {
if (getMode() == 0) super.dumpTo(file);
else if (getMode() == 1) dumpNBT(file);
else dumpJson(file);
switch (getMode()) {
case CSV -> super.dumpTo(file);
case NBT -> dumpNBT(file);
default -> dumpJson(file);
}
}
public void dumpNBT(File file) throws IOException {
@@ -141,4 +182,22 @@ public class ItemPanelDumper extends DataDumper {
public int modeCount() {
return 4;
}
@Override
public List<String> handleTooltip(int mousex, int mousey, List<String> currenttip) {
if (getMode() == PNG && dumpButtonSize().contains(mousex, mousey) && showItemSizeWarning()) {
int res = getRes();
currenttip.add(
NEIClientUtils.translate(
"options.tools.dump.itempanel.icon.warning.1",
ItemPanels.itemPanel.getItems().size(),
res,
res));
currenttip.add(
NEIClientUtils.translate(
"options.tools.dump.itempanel.icon.warning.2",
NEIClientUtils.translate("key.shift")));
}
return currenttip;
}
}
@@ -91,7 +91,7 @@ public class AutoCraftingManager {
for (BookmarkItem item : math.initialItems) {
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
final long amount = Math.max(0, item.amount - invStackSize * item.fluidCellAmount);
final long amount = Math.max(0, item.getAmount() - invStackSize * item.fluidCellAmount);
if (amount > 0) {
initialItems.add(item.copyWithAmount(amount));
}
@@ -784,9 +784,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
public void forceRefreshPage() {
this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
final int currentPage = this.handlerPages.getCurrentPageIndex();
this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
this.recipetype = this.currenthandlers.indexOf(this.handler.original);
setRecipePage(this.recipetype);
this.handlerPages.changePage(currentPage);
@@ -898,12 +899,15 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
private String getHandlerTitleColorCode(boolean hovered) {
final String key = hovered ? "recipe.title.color.hover" : "recipe.title.color.normal";
final String translated = NEIClientUtils.translate(key);
if (!translated.startsWith("nei.")) { // Optional localization string for resource packs
return translated;
if (hovered) {
return NEIClientUtils
.getTextColorOrDefault("recipe.title.color.hover", EnumChatFormatting.YELLOW.toString());
} else {
return NEIClientUtils
.getTextColorOrDefault("recipe.title.color.normal", EnumChatFormatting.WHITE.toString());
}
return hovered ? EnumChatFormatting.YELLOW.toString() : EnumChatFormatting.WHITE.toString();
}
@Override
@@ -30,6 +30,7 @@ public class HandlerInfo {
private boolean multipleWidgetsAllowed = false;
private boolean showFavoritesButton = true;
private boolean showOverlayButton = true;
private boolean showChanceInfo = true;
private boolean useCustomScroll = false;
private ItemStack itemStack = null;
@@ -142,6 +143,14 @@ public class HandlerInfo {
this.showOverlayButton = showOverlayButton;
}
public boolean getShowChanceInfo() {
return this.showChanceInfo;
}
public void setShowChanceInfo(boolean showChanceInfo) {
this.showChanceInfo = showChanceInfo;
}
public boolean getUseCustomScroll() {
return this.useCustomScroll;
}
@@ -216,6 +225,11 @@ public class HandlerInfo {
return this;
}
public Builder setShowChanceInfo(boolean showChanceInfo) {
this.info.showChanceInfo = showChanceInfo;
return this;
}
@Deprecated
public Builder setMaxRecipesPerPage(int maxRecipesPerPage) {
this.info.multipleWidgetsAllowed = maxRecipesPerPage > 1;
@@ -1,6 +1,7 @@
package codechicken.nei.recipe;
import java.awt.Point;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -21,9 +22,11 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.FavoriteRecipes;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIClientUtils.Alignment;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.Widget;
@@ -37,9 +40,12 @@ import codechicken.nei.util.NEIMouseUtils;
public class NEIRecipeWidget extends Widget {
private static final DecimalFormat chanceFormat = new DecimalFormat("##0.##%");
protected AcceptsFollowingTooltipLineHandler acceptsFollowingTooltipLineHandler;
protected final Map<PositionedStack, Integer> favoriteIndexes = new WeakHashMap<>();
protected final Map<PositionedStack, List<ItemStack>> permutations = new WeakHashMap<>();
protected final Map<PositionedStack, String> chances = new WeakHashMap<>();
protected int chanceColor = 0xFDD835;
protected int favoriteRevision = -1;
protected boolean update = true;
protected int cycleticks = 0;
@@ -54,9 +60,20 @@ public class NEIRecipeWidget extends Widget {
public NEIRecipeWidget(RecipeHandlerRef handlerRef) {
this.handlerRef = handlerRef;
this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.handlerRef.handler);
this.chanceColor = getHexValue(
NEIClientUtils.getTextColorOrDefault("recipe.overlay.chance", "0xFDD835"),
this.chanceColor);
update();
}
private int getHexValue(String color, int defaultValue) {
try {
return (int) Long.parseLong(color.replace("0x", ""), 16);
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void setLocation(int x, int y) {
this.x = x;
this.y = y;
@@ -196,11 +213,7 @@ public class NEIRecipeWidget extends Widget {
updatePermutationsFor(pStack);
}
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
}
drawItem(pStack, mouseX, mouseY, yShift);
}
for (PositionedStack pStack : getCatalysts()) {
@@ -209,19 +222,11 @@ public class NEIRecipeWidget extends Widget {
updatePermutationsFor(pStack);
}
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
}
drawItem(pStack, mouseX, mouseY, yShift);
}
for (PositionedStack pStack : getOutputs()) {
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
}
drawItem(pStack, mouseX, mouseY, yShift);
}
GuiContainerManager.disableMatrixStackLogging();
@@ -255,6 +260,41 @@ public class NEIRecipeWidget extends Widget {
DebugHandlerWidget.instance.drawGuiPlaceholder(this);
}
protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift) {
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
if (this.handlerInfo.getShowChanceInfo()) {
final String chanceText = this.chances.computeIfAbsent(pStack, k -> getChanceText(k));
if (!chanceText.isEmpty()) {
NEIClientUtils.drawNEIOverlayText(
chanceText,
new Rectangle4i(pStack.relx, pStack.rely, 16, 16),
0.5f,
this.chanceColor,
true,
Alignment.TopLeft);
}
}
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
}
}
protected String getChanceText(PositionedStack pStack) {
if (StackInfo.getAmount(pStack.item) == 0) { // not consumed
return NEIClientUtils.translate("recipe.chance.nc");
} else if (pStack.getChance() == 0) { // not consumed parallel
return NEIClientUtils.translate("recipe.chance.ncp");
} else if (pStack.getChance() != PositionedStack.CHANCE_FULL) { // chance based
return chanceFormat.format(pStack.getChance() / (float) PositionedStack.CHANCE_FULL);
}
return "";
}
@Override
public boolean handleKeyPress(int keyID, char keyChar) {
@@ -282,17 +282,20 @@ public class Recipe {
protected final ItemStack[] items;
protected int activeIndex = 0;
protected int amount = 0;
protected int chance = PositionedStack.CHANCE_FULL;
protected int relx;
protected int rely;
public RecipeIngredient(int relx, int rely, List<ItemStack> items, int activeIndex) {
public RecipeIngredient(int relx, int rely, List<ItemStack> items, int chance, int activeIndex) {
this.items = items.stream().map(ItemStack::copy).toArray(size -> new ItemStack[size]);
this.amount = StackInfo.getAmount(this.items[activeIndex]);
this.activeIndex = activeIndex;
this.relx = relx;
this.rely = rely;
this.chance = chance;
}
public static RecipeIngredient of(PositionedStack positionedStack) {
@@ -311,17 +314,21 @@ public class Recipe {
}
}
return of(positionedStack.relx, positionedStack.rely, stacks, activeIndex);
return of(positionedStack.relx, positionedStack.rely, stacks, positionedStack.getChance(), activeIndex);
}
public static RecipeIngredient of(int relx, int rely, List<ItemStack> stacks, int activeIndex) {
return new RecipeIngredient(relx, rely, stacks, activeIndex);
public static RecipeIngredient of(int relx, int rely, List<ItemStack> stacks, int chance, int activeIndex) {
return new RecipeIngredient(relx, rely, stacks, chance, activeIndex);
}
public int getAmount() {
return this.amount;
}
public int getChance() {
return this.chance;
}
public ItemStack getItemStack() {
return this.items[this.activeIndex];
}
@@ -348,11 +355,16 @@ public class Recipe {
return this;
}
public void setChance(int chance) {
this.chance = chance;
}
public RecipeIngredient copy() {
return new RecipeIngredient(
this.relx,
this.rely,
getPermutations().stream().map(ItemStack::copy).collect(Collectors.toList()),
this.chance,
this.activeIndex);
}
}
@@ -435,7 +447,7 @@ public class Recipe {
}
if (item instanceof ItemStack stack) {
return RecipeIngredient.of(0, 0, Arrays.asList(stack), 0);
return RecipeIngredient.of(0, 0, Arrays.asList(stack), PositionedStack.CHANCE_FULL, 0);
}
if (item instanceof RecipeIngredient ingr) {
@@ -49,9 +49,9 @@ public class RecipeChainIterator implements Iterator<Map<RecipeId, Long>> {
final Set<RecipeId> skipRecipes = new HashSet<>();
final Map<RecipeId, Long> rootRecipes = new HashMap<>();
final HashMap<BookmarkItem, BookmarkItem> preferredItems = new HashMap<>(this.math.preferredItems);
preferredItems.values()
.removeIf(item -> item == null || item.amount == 0 || this.precessedRecipes.contains(item.recipeId));
preferredItems.keySet().removeIf(item -> item.amount == 0);
preferredItems.values().removeIf(
item -> item == null || item.getAmount() == 0 || this.precessedRecipes.contains(item.recipeId));
preferredItems.keySet().removeIf(item -> item.getAmount() == 0);
for (Map.Entry<BookmarkItem, BookmarkItem> entry : preferredItems.entrySet()) {
final BookmarkItem keyItem = entry.getKey();
@@ -14,6 +14,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import codechicken.nei.ItemStackAmount;
import codechicken.nei.ItemStackSet;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.bookmark.BookmarkItem;
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
@@ -48,6 +49,7 @@ public class RecipeChainMath {
public final List<BookmarkItem> recipeResults = new ArrayList<>();
public final Map<BookmarkItem, BookmarkItem> preferredItems = new HashMap<>();
public final Map<BookmarkItem, Long> requiredAmount = new HashMap<>();
public final List<ItemStack> containerItems = new ArrayList<>();
private final List<ItemStack> containerItemsBlacklist = new ArrayList<>();
@@ -59,9 +61,9 @@ public class RecipeChainMath {
if (item.recipeId == null || item.type == BookmarkItemType.ITEM) {
this.initialItems.add(item.copy());
} else if (item.type == BookmarkItemType.INGREDIENT) {
this.recipeIngredients.add(item.copyWithAmount(0));
this.recipeIngredients.add(item.copyWithMultiplier(0));
} else {
this.recipeResults.add(item.copyWithAmount(0));
this.recipeResults.add(item.copyWithMultiplier(0));
multipliers.put(
item.recipeId,
Math.max(multipliers.getOrDefault(item.recipeId, 0L), item.getMultiplier()));
@@ -129,17 +131,18 @@ public class RecipeChainMath {
visited.add(recipeId);
for (BookmarkItem ingrItem : this.recipeIngredients) {
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId) && !preferredItems.containsKey(ingrItem)) {
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId)
&& !preferredItems.containsKey(ingrItem)) {
BookmarkItem activeItem = null;
BookmarkItem prefItem = null;
for (BookmarkItem item : this.recipeResults) {
if (item.factor > 0 && !visited.contains(item.recipeId) && item.containsItems(ingrItem)) {
if (!item.emptyFactor() && !visited.contains(item.recipeId) && item.containsItems(ingrItem)) {
if ((activeItem == null || item.factor > activeItem.factor) && NEIClientUtils
if ((activeItem == null || item.getAmount(1) > activeItem.getAmount(1)) && NEIClientUtils
.areStacksSameTypeCraftingWithNBT(ingrItem.itemStack, item.itemStack)) {
activeItem = item;
} else if (prefItem == null || item.factor > prefItem.factor) {
} else if (prefItem == null || item.getAmount(1) > prefItem.getAmount(1)) {
prefItem = item;
}
@@ -164,7 +167,7 @@ public class RecipeChainMath {
int maxDepth = 0;
for (BookmarkItem ingrItem : preferredItems.keySet()) {
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId)) {
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId)) {
maxDepth = Math.max(maxDepth, getMaxDepth(preferredItems.get(ingrItem).recipeId, preferredItems) + 1);
}
}
@@ -176,7 +179,7 @@ public class RecipeChainMath {
visited.add(recipeId);
for (BookmarkItem ingrItem : this.recipeIngredients) {
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId) && preferredItems.containsKey(ingrItem)) {
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId) && preferredItems.containsKey(ingrItem)) {
BookmarkItem prefItem = preferredItems.get(ingrItem);
if (visited.contains(prefItem.recipeId)) {
@@ -184,6 +187,7 @@ public class RecipeChainMath {
} else {
removeLoop(prefItem.recipeId, preferredItems, visited);
}
}
}
@@ -195,22 +199,22 @@ public class RecipeChainMath {
for (BookmarkItem item : this.recipeResults) {
if (this.outputRecipes.containsKey(item.recipeId) && !ROOT_RECIPE_ID.equals(item.recipeId)) {
final long amount = item.factor * this.outputRecipes.get(item.recipeId);
final long multiplier = this.outputRecipes.get(item.recipeId);
final long amount = item.getAmount(multiplier);
rootIngredients.add(
BookmarkItem.of(
-1,
item.getItemStack(amount),
item.getStackSize(amount),
ROOT_RECIPE_ID,
BookmarkItemType.INGREDIENT,
BookmarkItem.generatePermutations(item.itemStack, null)));
BookmarkItem.builder(-1, item.getItemStack(amount)).factor(item.getStackSize(amount))
.permutations(BookmarkItem.Builder.generatePermutations(item.itemStack))
.recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.INGREDIENT).build());
}
}
this.outputRecipes.clear();
this.outputRecipes.put(ROOT_RECIPE_ID, 1L);
this.recipeResults.removeIf(item -> ROOT_RECIPE_ID.equals(item.recipeId));
this.recipeResults.add(BookmarkItem.of(-1, ROOT_ITEM, 1, ROOT_RECIPE_ID, BookmarkItemType.RESULT));
this.recipeResults.add(
BookmarkItem.builder(-1, ROOT_ITEM).factor(1).recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.RESULT)
.build());
this.recipeIngredients.addAll(rootIngredients);
return ROOT_RECIPE_ID;
@@ -226,24 +230,20 @@ public class RecipeChainMath {
public static RecipeChainMath of(Recipe recipe, long multiplier) {
final List<BookmarkItem> chainItems = new ArrayList<>();
final RecipeId recipeId = recipe.getRecipeId();
final ItemStack result = recipe.getResult();
final ItemStackSet ingredients = new ItemStackSet();
chainItems.add(BookmarkItem.of(-1, result, StackInfo.getAmount(result), recipeId, BookmarkItemType.RESULT));
chainItems
.add(BookmarkItem.builder(-1, result, recipe, BookmarkItemType.RESULT).multiplier(multiplier).build());
for (RecipeIngredient ingr : recipe.getIngredients()) {
chainItems.add(
BookmarkItem.of(
-1,
ingr.getItemStack(),
ingr.getAmount(),
recipeId,
BookmarkItemType.INGREDIENT,
BookmarkItem.generatePermutations(ingr.getItemStack(), recipe)));
ingredients.add(ingr.getItemStack());
}
for (BookmarkItem item : chainItems) {
item.amount *= multiplier;
for (ItemStack ingrStack : ingredients.values()) {
chainItems.add(
BookmarkItem.builder(-1, ingrStack, recipe, BookmarkItemType.INGREDIENT).multiplier(multiplier)
.build());
}
return new RecipeChainMath(chainItems, Collections.emptySet());
@@ -253,7 +253,7 @@ public class RecipeChainMath {
final ItemStackAmount missedItems = new ItemStackAmount();
for (BookmarkItem item : this.recipeResults) {
long amount = item.amount - this.requiredAmount.getOrDefault(item, 0L);
long amount = item.getAmount() - this.requiredAmount.getOrDefault(item, 0L);
if (amount > 0) {
missedItems.add(item.getItemStack(amount));
}
@@ -261,7 +261,7 @@ public class RecipeChainMath {
for (BookmarkItem item : this.recipeIngredients) {
long amount = this.requiredAmount.containsKey(this.preferredItems.get(item)) ? 0
: this.requiredAmount.getOrDefault(item, item.amount);
: this.requiredAmount.getOrDefault(item, item.getAmount());
if (amount > 0) {
missedItems.add(item.getItemStack(amount));
}
@@ -279,11 +279,11 @@ public class RecipeChainMath {
private void resetCalculation() {
for (BookmarkItem item : this.recipeIngredients) {
item.amount = 0;
item.multiplier = 0;
}
for (BookmarkItem item : this.recipeResults) {
item.amount = 0;
item.multiplier = 0;
}
this.preferredItems.clear();
@@ -313,8 +313,8 @@ public class RecipeChainMath {
}
for (BookmarkItem prefItem : this.recipeResults) {
if (prefItem.factor > 0 && this.outputRecipes.containsKey(prefItem.recipeId)) {
final long prefAmount = prefItem.factor * this.outputRecipes.get(prefItem.recipeId);
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)) {
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) {
this.containerItemsBlacklist.add(prefItem.itemStack);
@@ -327,9 +327,9 @@ public class RecipeChainMath {
}
for (BookmarkItem prefItem : this.recipeResults) {
if (prefItem.factor > 0 && this.outputRecipes.containsKey(prefItem.recipeId)
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)
&& this.requiredAmount.containsKey(prefItem)) {
final long prefAmount = prefItem.factor * this.outputRecipes.get(prefItem.recipeId);
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
this.requiredAmount.put(prefItem, this.requiredAmount.get(prefItem) - prefAmount);
}
}
@@ -338,14 +338,6 @@ public class RecipeChainMath {
return this;
}
private void prepareIngredients(RecipeId recipeId, long stepShift, List<RecipeId> visited) {
for (BookmarkItem item : this.recipeIngredients) {
if (item.factor > 0 && recipeId.equals(item.recipeId)) {
calculateSuitableRecipe(item, item.factor * stepShift, visited);
}
}
}
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited) {
final BookmarkItem prefItem = this.preferredItems.get(ingrItem);
@@ -366,7 +358,7 @@ public class RecipeChainMath {
if (ingrAmount > 0) {
for (BookmarkItem item : this.initialItems) {
if (item.containsItems(ingrItem)
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.amount)) == 0) {
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.getAmount())) == 0) {
break;
}
}
@@ -379,19 +371,27 @@ public class RecipeChainMath {
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
} else {
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
final long shift = (long) Math
.ceil((this.requiredAmount.get(prefItem) - prefItem.amount) / (double) prefItem.factor);
final long multiplier = Math
.max(0, prefItem.getMultiplierFromAmount(this.requiredAmount.get(prefItem)) - prefItem.multiplier);
if (shift > 0) {
addShift(prefItem.recipeId, shift);
if (multiplier > 0) {
addShift(prefItem.recipeId, multiplier);
visited.add(prefItem.recipeId);
prepareIngredients(prefItem.recipeId, shift, visited);
prepareIngredients(prefItem.recipeId, multiplier, visited);
visited.remove(prefItem.recipeId);
}
}
}
private void prepareIngredients(RecipeId recipeId, long multiplier, List<RecipeId> visited) {
for (BookmarkItem item : this.recipeIngredients) {
if (!item.emptyFactor() && recipeId.equals(item.recipeId)) {
calculateSuitableRecipe(item, item.getAmount(multiplier), visited);
}
}
}
private long addRequiredAmount(BookmarkItem prefItem, long ingrAmount, long maxAmount) {
long shiftAmount = this.requiredAmount.getOrDefault(prefItem, 0L);
@@ -489,7 +489,7 @@ public class RecipeChainMath {
final NBTTagCompound toolStats = tagCompound.getCompoundTag("GT.ToolStats");
final long maxDamage = toolStats.getLong("MaxDamage");
final long damage = toolStats.getLong("Damage");
final long leftSteps = (long) Math.ceil((maxDamage - damage) / (double) damagePerContainerCraft);
final long leftSteps = (maxDamage - damage + damagePerContainerCraft - 1) / damagePerContainerCraft;
final long availableSteps = Math.min(steps, Math.max(1, leftSteps));
steps -= availableSteps;
@@ -552,13 +552,13 @@ public class RecipeChainMath {
private void addShift(RecipeId recipeId, long shift) {
for (BookmarkItem item : this.recipeIngredients) {
if (recipeId.equals(item.recipeId)) {
item.amount += item.factor * shift;
item.multiplier += shift;
}
}
for (BookmarkItem item : this.recipeResults) {
if (recipeId.equals(item.recipeId)) {
item.amount += item.factor * shift;
item.multiplier += shift;
}
}
}
@@ -73,7 +73,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
if (!this.lastControlKey) {
final List<ItemStack> items = inventory.values();
for (BookmarkItem item : math.recipeResults) {
if (item.factor > 0 && this.math.outputRecipes.containsKey(item.recipeId)) {
if (!item.emptyFactor() && this.math.outputRecipes.containsKey(item.recipeId)) {
long amount = 0;
for (ItemStack stack : items) {
@@ -83,15 +83,18 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
}
}
if (amount >= item.amount) {
final long itemAmount = item.factor * this.math.outputRecipes.get(item.recipeId);
if (amount >= item.getAmount()) {
final long itemAmount = item.getAmount(this.math.outputRecipes.get(item.recipeId));
if (itemAmount > 0) {
amount += itemAmount - amount % itemAmount;
}
this.math.outputRecipes.put(
item.recipeId,
Math.max(this.math.outputRecipes.get(item.recipeId), amount / item.factor));
Math.max(
this.math.outputRecipes.get(item.recipeId),
item.getMultiplierFromAmount(amount)));
}
}
}
@@ -122,7 +125,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
for (BookmarkItem item : math.recipeIngredients) {
final long amount = math.requiredAmount.containsKey(math.preferredItems.get(item)) ? 0
: math.requiredAmount.getOrDefault(item, item.amount);
: math.requiredAmount.getOrDefault(item, item.getAmount());
if (amount > 0) {
inputs.add(item.getItemStack(amount));
@@ -130,7 +133,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
}
for (BookmarkItem item : math.recipeResults) {
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
if (amount > 0) {
if (math.outputRecipes.containsKey(item.recipeId)) {
@@ -155,12 +158,12 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
if (inventory.contains(item.itemStack)) {
final long invAmount = inventory.get(item.itemStack) * item.fluidCellAmount;
if ((item.amount - invAmount) > 0) {
inputs.add(item.getItemStack(item.amount - invAmount));
if ((item.getAmount() - invAmount) > 0) {
inputs.add(item.getItemStack(item.getAmount() - invAmount));
}
if (Math.min(item.amount, invAmount) > 0) {
available.add(item.getItemStack(Math.min(item.amount, invAmount)));
if (Math.min(item.getAmount(), invAmount) > 0) {
available.add(item.getItemStack(Math.min(item.getAmount(), invAmount)));
}
} else {
@@ -6,7 +6,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -18,6 +17,7 @@ import java.util.regex.Matcher;
import java.util.stream.Collectors;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.io.IOUtils;
import org.lwjgl.input.Keyboard;
@@ -25,6 +25,7 @@ import org.lwjgl.opengl.GL11;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.Button;
import codechicken.nei.ClientHandler;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
@@ -45,6 +46,7 @@ public class DebugHandlerWidget extends Widget {
private static class HandlerInfoRecord {
public HandlerInfo info;
public String handlerKey;
public int yShift;
public int width;
@@ -58,6 +60,7 @@ public class DebugHandlerWidget extends Widget {
private String csvLine;
public HandlerInfoRecord(String handlerKey, HandlerInfo info) {
this.info = info;
this.handlerKey = handlerKey;
this.yShift = info.getYShift();
this.width = info.getWidth();
@@ -70,33 +73,57 @@ public class DebugHandlerWidget extends Widget {
this.csvLine = toCsvLine();
}
public void applyTo(HandlerInfo info) {
info.setYShift(this.yShift);
info.setHandlerDimensions(this.width, this.height);
info.setMultipleWidgetsAllowed(this.multiWidgets);
info.setUseCustomScroll(this.useCustomScroll);
info.setShowFavoritesButton(this.showFavorites);
info.setShowOverlayButton(this.showOverlay);
public void apply() {
this.info.setYShift(this.yShift);
this.info.setHandlerDimensions(this.width, this.height);
this.info.setMultipleWidgetsAllowed(this.multiWidgets);
this.info.setUseCustomScroll(this.useCustomScroll);
this.info.setShowFavoritesButton(this.showFavorites);
this.info.setShowOverlayButton(this.showOverlay);
NEIClientConfig.handlerOrdering.put(this.handlerKey, this.order);
}
public void apply(String csvLine) {
final String[] parts = csvLine.split(",");
this.yShift = intOrDefault(parts[1], this.yShift);
this.height = intOrDefault(parts[2], this.height);
this.width = intOrDefault(parts[3], this.width);
this.multiWidgets = intOrDefault(parts[4], this.multiWidgets ? 1 : 0) == 1;
this.order = intOrDefault(parts[5], this.order);
this.useCustomScroll = intOrDefault(parts[6], this.useCustomScroll ? 1 : 0) == 1;
this.showFavorites = intOrDefault(parts[7], this.showFavorites ? 1 : 0) == 1;
this.showOverlay = intOrDefault(parts[8], this.showOverlay ? 1 : 0) == 1;
apply();
}
public String toCsvLine() {
return String.join(
",",
handlerKey,
String.valueOf(yShift),
String.valueOf(height),
String.valueOf(width),
String.valueOf(multiWidgets ? 1 : 0),
String.valueOf(order),
String.valueOf(useCustomScroll ? 1 : 0),
String.valueOf(showFavorites ? 1 : 0),
String.valueOf(showOverlay ? 1 : 0));
this.handlerKey,
String.valueOf(this.yShift),
String.valueOf(this.height),
String.valueOf(this.width),
String.valueOf(this.multiWidgets ? 1 : 0),
String.valueOf(this.order),
String.valueOf(this.useCustomScroll ? 1 : 0),
String.valueOf(this.showFavorites ? 1 : 0),
String.valueOf(this.showOverlay ? 1 : 0));
}
public boolean isUnmodified() {
return this.csvLine.equals(this.toCsvLine());
}
private int intOrDefault(String str, int defaultValue) {
if (str == null || str.isEmpty()) return defaultValue;
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return defaultValue;
}
}
}
private static final int WINDOW_WIDTH = 176;
@@ -114,12 +141,11 @@ public class DebugHandlerWidget extends Widget {
private final Map<String, IUpdatableWidget> values = new LinkedHashMap<>();
private Map<String, HandlerInfoRecord> patches = new HashMap<>();
private IRecipeHandler handler;
private HandlerInfo handlerInfo;
private HandlerInfoRecord record;
private Point dragPoint = null;
private boolean showWidget = false;
private Button resetButton;
private final DrawableResource BG_TEXTURE = new DrawableBuilder(
"nei:textures/gui/recipebg.png",
@@ -147,29 +173,19 @@ public class DebugHandlerWidget extends Widget {
y = addInfoWidget("HHack", y);
y = addInfoWidget("ModName", y);
y = addInfoWidget("ModId", y);
y = addInfoWidget("Override", y);
y = addOverrideInfoWidget("Override", y);
y = addTextFieldWidget("Order", 0, (field, oldText) -> {
if (field.getInteger() != record.order) {
record.order = field.getInteger();
saveHandlerInfoPatch();
}
record.order = field.getInteger();
saveHandlerInfoPatch();
}, y);
y = addTextFieldWidget("yShift", 0, (field, oldText) -> {
if (field.getInteger() != handlerInfo.getYShift()) {
handlerInfo.setYShift(field.getInteger());
record.yShift = field.getInteger();
saveHandlerInfoPatch();
}
record.yShift = field.getInteger();
saveHandlerInfoPatch();
}, y);
y = addCheckboxWidget("MultiWidgets", button -> {
handlerInfo.setMultipleWidgetsAllowed(button.value);
record.multiWidgets = button.value;
saveHandlerInfoPatch();
}, y);
@@ -182,39 +198,26 @@ public class DebugHandlerWidget extends Widget {
this.values.put("height_readonly", readonly);
y = addTextFieldWidget("Height", HandlerInfo.DEFAULT_HEIGHT, (field, oldText) -> {
if (field.getInteger() != handlerInfo.getHeight()) {
handlerInfo.setHandlerDimensions(handlerInfo.getWidth(), field.getInteger());
record.height = field.getInteger();
saveHandlerInfoPatch();
}
record.height = field.getInteger();
saveHandlerInfoPatch();
}, y);
y = addTextFieldWidget("Width", HandlerInfo.DEFAULT_WIDTH, (field, oldText) -> {
if (field.getInteger() != handlerInfo.getWidth()) {
handlerInfo.setHandlerDimensions(field.getInteger(), handlerInfo.getHeight());
record.width = field.getInteger();
saveHandlerInfoPatch();
}
record.width = field.getInteger();
saveHandlerInfoPatch();
}, y);
y = addCheckboxWidget("UseCustomScroll", button -> {
handlerInfo.setUseCustomScroll(button.value);
record.useCustomScroll = button.value;
saveHandlerInfoPatch();
}, y);
y = addCheckboxWidget("ShowFavorites", button -> {
handlerInfo.setShowFavoritesButton(button.value);
record.showFavorites = button.value;
saveHandlerInfoPatch();
}, y);
y = addCheckboxWidget("ShowOverlay", button -> {
handlerInfo.setShowOverlayButton(button.value);
record.showOverlay = button.value;
saveHandlerInfoPatch();
}, y);
@@ -278,10 +281,52 @@ public class DebugHandlerWidget extends Widget {
return y + value.h + 1;
}
private int addOverrideInfoWidget(String key, int y) {
final LabelWidget label = new LabelWidget(0x888888, false);
final LabelWidget value = new LabelWidget(0xffffff, true);
this.resetButton = new Button(NEIClientUtils.translate("debug.RecipeHandler.reset")) {
@Override
public boolean onButtonPress(boolean rightclick) {
if (record != null) {
record.apply(record.csvLine);
saveHandlerInfoPatch();
record = null;// force update of button state
}
return true;
}
@Override
public void draw(int mousex, int mousey) {
this.state = record != null && record.isUnmodified() ? 2 : 0;
super.draw(mousex, mousey);
}
};
this.resetButton.w = 58;
this.resetButton.h = 16;
this.resetButton.y = label.y = value.y = y;
this.resetButton.x = this.w - INLINE_PADDING * 2 - this.resetButton.w - 1;
label.w = LABEL_WIDTH;
value.x = LABEL_WIDTH + 5;
value.w = this.resetButton.x - value.x - 2;
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
this.container.addWidget(label);
this.container.addWidget(value);
this.values.put(key.toLowerCase(), value);
this.container.addWidget(this.resetButton);
return y + value.h + 1;
}
@Override
public void draw(int mx, int my) {
if (this.handler != null) {
if (this.record != null) {
GL11.glColor4f(1F, 1F, 1F, 1F);
GL11.glScaled(1, 1, 2f);
GL11.glDisable(GL11.GL_DEPTH_TEST);
@@ -318,24 +363,22 @@ public class DebugHandlerWidget extends Widget {
if (this.showWidget && gui instanceof GuiRecipe recipe) {
if (this.handler != recipe.getHandler()) {
this.handler = recipe.getHandler();
this.handlerInfo = GuiRecipeTab.getHandlerInfo(handler);
if (this.record == null || !this.record.handlerKey.equals(getHandlerID(recipe.getHandler()))) {
final IRecipeHandler handler = recipe.getHandler();
this.record = this.patches.computeIfAbsent(
getHandlerID(handler),
handlerKey -> new HandlerInfoRecord(handlerKey, handlerInfo));
handlerKey -> new HandlerInfoRecord(handlerKey, GuiRecipeTab.getHandlerInfo(handler)));
final boolean isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
.map(pattern -> pattern.matcher(this.handler.getHandlerId())).anyMatch(Matcher::matches);
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
this.values.get("name").updateValue(this.handler.getRecipeName());
this.values.get("id").updateValue(this.handler.getOverlayIdentifier());
this.values.get("key").updateValue(this.handler.getHandlerId());
this.values.get("name").updateValue(handler.getRecipeName());
this.values.get("id").updateValue(handler.getOverlayIdentifier());
this.values.get("key").updateValue(handler.getHandlerId());
this.values.get("hhack").updateValue(
isHeightHackApplied ? NEIClientUtils.translate("debug.RecipeHandler.yes")
: NEIClientUtils.translate("debug.RecipeHandler.no"));
this.values.get("modname").updateValue(this.handlerInfo.getModName());
this.values.get("modid").updateValue(this.handlerInfo.getModId());
this.values.get("modname").updateValue(this.record.info.getModName());
this.values.get("modid").updateValue(this.record.info.getModId());
this.values.get("order").updateValue(String.valueOf(this.record.order));
this.values.get("yshift").updateValue(String.valueOf(this.record.yShift));
@@ -349,9 +392,7 @@ public class DebugHandlerWidget extends Widget {
this.values.get("showfavorites").updateValue(String.valueOf(this.record.showFavorites));
this.values.get("showoverlay").updateValue(String.valueOf(this.record.showOverlay));
this.values.get("override").updateValue(
this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no")
: NEIClientUtils.translate("debug.RecipeHandler.yes"));
updateOverride();
this.container.removeIf(
widget -> this.values.get("height") == widget || this.values.get("height_readonly") == widget);
@@ -364,9 +405,7 @@ public class DebugHandlerWidget extends Widget {
}
} else {
this.handler = null;
this.record = null;
this.handlerInfo = null;
this.showWidget = false;
}
@@ -375,12 +414,12 @@ public class DebugHandlerWidget extends Widget {
@Override
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
return this.handler != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip;
return this.record != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip;
}
@Override
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
return this.handler != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys;
return this.record != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys;
}
@Override
@@ -390,7 +429,7 @@ public class DebugHandlerWidget extends Widget {
&& NEIClientUtils.shiftKey()) {
this.showWidget = !this.showWidget;
return true;
} else if (this.handler != null) {
} else if (this.record != null) {
if (this.container.handleKeyPress(keyID, keyChar)) {
return true;
@@ -406,7 +445,7 @@ public class DebugHandlerWidget extends Widget {
@Override
public void onGuiClick(int mx, int my) {
if (this.handler != null) {
if (this.record != null) {
this.container.onGuiClick(mx, my);
}
}
@@ -414,7 +453,7 @@ public class DebugHandlerWidget extends Widget {
@Override
public boolean handleClick(int mx, int my, int button) {
if (this.handler != null) {
if (this.record != null) {
if (new Rectangle4i(this.x + INLINE_PADDING, this.y + BORDER_PADDING, this.w - INLINE_PADDING * 2, 12)
.contains(mx, my)) {
@@ -424,19 +463,19 @@ public class DebugHandlerWidget extends Widget {
this.container.handleClick(mx, my, button);
}
return this.handler != null;
return this.record != null;
}
@Override
public boolean contains(int px, int py) {
return this.handler != null && super.contains(px, py);
return this.record != null && super.contains(px, py);
}
@Override
public void mouseUp(int mx, int my, int button) {
this.dragPoint = null;
if (this.handler != null) {
if (this.record != null) {
this.container.mouseUp(mx, my, button);
}
}
@@ -444,7 +483,7 @@ public class DebugHandlerWidget extends Widget {
@Override
public boolean onMouseWheel(int scrolled, int mousex, int mousey) {
if (this.handler != null && contains(mousex, mousey)) {
if (this.record != null && contains(mousex, mousey)) {
this.container.onMouseWheel(scrolled, mousex, mousey);
return true;
}
@@ -454,7 +493,7 @@ public class DebugHandlerWidget extends Widget {
@Override
public boolean handleClickExt(int mx, int my, int button) {
return this.handler != null && this.container.handleClickExt(mx, my, button);
return this.record != null && this.container.handleClickExt(mx, my, button);
}
@Override
@@ -542,24 +581,14 @@ public class DebugHandlerWidget extends Widget {
for (String line : lines.collect(Collectors.toCollection(HashSet::new))) {
if (HEADER.equals(line)) continue;
final String[] parts = Arrays.copyOf((line + ",null,null,null,null,null,null,null,null").split(","), 9);
final String handler = parts[0];
final String[] parts = (line).split(",");
final String handlerKey = parts[0];
if (GuiRecipeTab.handlerMap.containsKey(handler)) {
final HandlerInfo info = GuiRecipeTab.handlerMap.get(handler);
final HandlerInfoRecord record = patches
.computeIfAbsent(handler, handlerKey -> new HandlerInfoRecord(handler, info));
record.yShift = intOrDefault(parts[1], info.getYShift());
record.height = intOrDefault(parts[2], info.getHeight());
record.width = intOrDefault(parts[3], info.getWidth());
record.multiWidgets = intOrDefault(parts[4], info.isMultipleWidgetsAllowed() ? 1 : 0) == 1;
record.order = intOrDefault(parts[5], NEIClientConfig.handlerOrdering.getOrDefault(handler, 0));
record.useCustomScroll = intOrDefault(parts[6], info.getUseCustomScroll() ? 1 : 0) == 1;
record.showFavorites = intOrDefault(parts[7], info.getShowFavoritesButton() ? 1 : 0) == 1;
record.showOverlay = intOrDefault(parts[8], info.getShowOverlayButton() ? 1 : 0) == 1;
record.applyTo(info);
if (GuiRecipeTab.handlerMap.containsKey(handlerKey)) {
final HandlerInfoRecord record = patches.computeIfAbsent(
handlerKey,
key -> new HandlerInfoRecord(key, GuiRecipeTab.handlerMap.get(key)));
record.apply((line + ",null,null,null,null,null,null,null,null"));
}
}
@@ -585,9 +614,8 @@ public class DebugHandlerWidget extends Widget {
} catch (IOException e) {}
if (this.record != null) {
this.values.get("override").updateValue(
this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no")
: NEIClientUtils.translate("debug.RecipeHandler.yes"));
updateOverride();
record.apply();
}
if (NEIClientUtils.getGuiContainer() instanceof GuiRecipe<?>recipe) {
@@ -595,12 +623,15 @@ public class DebugHandlerWidget extends Widget {
}
}
private int intOrDefault(String str, int defaultValue) {
if (str == null || str.isEmpty()) return defaultValue;
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return defaultValue;
private void updateOverride() {
this.container.removeIf(widget -> widget == this.resetButton);
if (this.record.isUnmodified()) {
this.values.get("override").updateValue(NEIClientUtils.translate("debug.RecipeHandler.no"));
} else {
this.values.get("override")
.updateValue(EnumChatFormatting.RED + NEIClientUtils.translate("debug.RecipeHandler.yes"));
this.container.addWidget(this.resetButton);
}
}
@@ -519,6 +519,8 @@ nei.options.tools.dump.itempanel.mode.2=Json
nei.options.tools.dump.itempanel.mode.3=PNG
nei.options.tools.dump.itempanel.icon.dumped=Item Panel icons were dumped to %s
nei.options.tools.dump.itempanel.icon.cancelled=Dump cancelled
nei.options.tools.dump.itempanel.icon.warning.1=§cWARNING§r: You are about to dump %s items at %sx%s resolution
nei.options.tools.dump.itempanel.icon.warning.2=Hold %s while clicking this button to proceed
nei.options.tools.dump.handlers=NEI Handlers
nei.options.tools.dump.handlers.dumped=handlers were dumped to %s
nei.options.tools.dump.handlers.mode.0=CSV
@@ -545,6 +547,7 @@ nei.debug.RecipeHandler.checkbox.on=On
nei.debug.RecipeHandler.checkbox.off=Off
nei.debug.RecipeHandler.yes=Yes
nei.debug.RecipeHandler.no=No
nei.debug.RecipeHandler.reset=Reset
nei.recipe.page=Page %s/%s
nei.recipe.tooltip=Recipes
@@ -554,6 +557,10 @@ nei.recipe.shapeless=Shapeless Crafting
nei.recipe.furnace=Smelting
nei.recipe.fuel=Fuel
nei.recipe.fuel.smeltCount=Smelts %s items
nei.recipe.chance=Chance: %s%%
nei.recipe.chance.nc=NC
nei.recipe.chance.ncp=NC(P)
# Deprecated
nei.recipe.fuel.required=%s required
# Deprecated