diff --git a/src/main/java/codechicken/nei/BookmarkPanel.java b/src/main/java/codechicken/nei/BookmarkPanel.java index c6529ce3..9e37ae48 100644 --- a/src/main/java/codechicken/nei/BookmarkPanel.java +++ b/src/main/java/codechicken/nei/BookmarkPanel.java @@ -942,12 +942,14 @@ public class BookmarkPanel extends PanelWidget { if (slot != null) { if (slot.getBookmarkItem().chance != PositionedStack.CHANCE_FULL) { + final String chanceText = NEIClientUtils + .formatChance(slot.getBookmarkItem().chance / (float) PositionedStack.CHANCE_FULL); currenttip.add( 1, - EnumChatFormatting.DARK_GRAY + NEIClientUtils.translate( - "recipe.chance", - NEIClientUtils.formatNumber( - slot.getBookmarkItem().chance * 100f / PositionedStack.CHANCE_FULL))); + EnumChatFormatting.GRAY + NEIClientUtils.translate( + slot.getType() == BookmarkItemType.INGREDIENT ? "recipe.badge.chance.consume" + : "recipe.badge.chance.output", + chanceText)); } if (slot.getType() == BookmarkItemType.INGREDIENT && slot.getRecipeId() != null diff --git a/src/main/java/codechicken/nei/NEIClientUtils.java b/src/main/java/codechicken/nei/NEIClientUtils.java index 59ec14d2..e4a405e4 100644 --- a/src/main/java/codechicken/nei/NEIClientUtils.java +++ b/src/main/java/codechicken/nei/NEIClientUtils.java @@ -95,6 +95,7 @@ public class NEIClientUtils extends NEIServerUtils { /** Formats a number with group separator and at most 2 fraction digits. */ private static final Map decimalFormatters = new HashMap<>(); + private static final DecimalFormat CHANCE_FORMAT = new DecimalFormat("##0.##%"); public static final int ALT_HASH = NEIKeyboardUtils.ALT_HASH; public static final int SHIFT_HASH = NEIKeyboardUtils.SHIFT_HASH; @@ -144,6 +145,10 @@ public class NEIClientUtils extends NEIServerUtils { return getDecimalFormat().format(aNumber) + " L"; } + public static String formatChance(float chance) { + return CHANCE_FORMAT.format(chance); + } + public static void deleteHeldItem() { deleteSlotStack(-999); } diff --git a/src/main/java/codechicken/nei/PositionedStack.java b/src/main/java/codechicken/nei/PositionedStack.java index 53f26713..a4384344 100644 --- a/src/main/java/codechicken/nei/PositionedStack.java +++ b/src/main/java/codechicken/nei/PositionedStack.java @@ -86,6 +86,10 @@ public class PositionedStack { for (ItemStack item : items) if (item.stackSize > i) item.stackSize = i; } + public String getCustomBadge() { + return null; + } + public int getChance() { return this.chance; } @@ -97,7 +101,7 @@ public class PositionedStack { rely, false); pStack.permutated = this.permutated; - pStack.chance = getChance(); + pStack.chance = this.chance; return pStack; } diff --git a/src/main/java/codechicken/nei/bookmark/BookmarkGridGenerator.java b/src/main/java/codechicken/nei/bookmark/BookmarkGridGenerator.java index 858bd7e1..8e9f23fa 100644 --- a/src/main/java/codechicken/nei/bookmark/BookmarkGridGenerator.java +++ b/src/main/java/codechicken/nei/bookmark/BookmarkGridGenerator.java @@ -318,7 +318,7 @@ public class BookmarkGridGenerator { return group.crafting.calculatedItems.get(itemIndex); } else { BookmarkChainItem item = BookmarkChainItem.of(this.grid.getBookmarkItem(itemIndex)); - item.setRealMultiplier(item.getItem().getMultiplierFromAmount(item.getShiftAmount())); + item.setRealMultiplier(item.getCalculatedMultiplier()); return item; } } diff --git a/src/main/java/codechicken/nei/bookmark/BookmarkItem.java b/src/main/java/codechicken/nei/bookmark/BookmarkItem.java index 4be3defc..64dd00ae 100644 --- a/src/main/java/codechicken/nei/bookmark/BookmarkItem.java +++ b/src/main/java/codechicken/nei/bookmark/BookmarkItem.java @@ -221,7 +221,7 @@ public class BookmarkItem { for (RecipeIngredient res : items) { if (res.contains(stack)) { - amount += res.getAmount() * res.getChance(); + amount += 1L * res.getAmount() * res.getChance(); } } diff --git a/src/main/java/codechicken/nei/bookmark/BookmarksGridSlot.java b/src/main/java/codechicken/nei/bookmark/BookmarksGridSlot.java index 6d0568ec..957ce002 100644 --- a/src/main/java/codechicken/nei/bookmark/BookmarksGridSlot.java +++ b/src/main/java/codechicken/nei/bookmark/BookmarksGridSlot.java @@ -348,15 +348,19 @@ public class BookmarksGridSlot extends ItemsGridSlot { } protected void drawStackSize(Rectangle4i rect, ShownItemType shownItemType) { + boolean drawChance = this.calculatedMultiplier > 0; long amount = this.calculatedAmount; if (shownItemType == null || shownItemType == ShownItemType.REAL || this.calculatedType == null) { amount = this.realAmount; + drawChance = this.realMultiplier > 0; } else if (shownItemType == ShownItemType.SHIFT) { amount = this.shiftAmount; + drawChance = false; } - if (amount > 0 || shownItemType == ShownItemType.REAL && !this.bookmarkItem.emptyFactor()) { + if (amount > 0 || this.bookmarkItem.chance != PositionedStack.CHANCE_FULL && drawChance + || 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; diff --git a/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java b/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java index 63bd24ff..bfc06246 100644 --- a/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java +++ b/src/main/java/codechicken/nei/bookmark/RecipeChainDetails.java @@ -70,7 +70,7 @@ public class RecipeChainDetails { return new BookmarkChainItem( item, amount, - amount, + item.getMultiplier(), item.type == BookmarkItemType.INGREDIENT ? CalculatedType.INGREDIENT : CalculatedType.RESULT); } diff --git a/src/main/java/codechicken/nei/config/IMCHandler.java b/src/main/java/codechicken/nei/config/IMCHandler.java index 6b62a2f0..5ebaa777 100644 --- a/src/main/java/codechicken/nei/config/IMCHandler.java +++ b/src/main/java/codechicken/nei/config/IMCHandler.java @@ -103,7 +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")); + info.setShowBadge(!tag.hasKey("showBadge") || tag.getBoolean("showBadge")); GuiRecipeTab.handlerAdderFromIMC.remove(handler); GuiRecipeTab.handlerAdderFromIMC.put(handler, info); diff --git a/src/main/java/codechicken/nei/recipe/HandlerInfo.java b/src/main/java/codechicken/nei/recipe/HandlerInfo.java index f8d7b67f..11d8286f 100644 --- a/src/main/java/codechicken/nei/recipe/HandlerInfo.java +++ b/src/main/java/codechicken/nei/recipe/HandlerInfo.java @@ -30,7 +30,7 @@ public class HandlerInfo { private boolean multipleWidgetsAllowed = false; private boolean showFavoritesButton = true; private boolean showOverlayButton = true; - private boolean showChanceInfo = true; + private boolean showBadge = true; private boolean useCustomScroll = false; private ItemStack itemStack = null; @@ -143,12 +143,12 @@ public class HandlerInfo { this.showOverlayButton = showOverlayButton; } - public boolean getShowChanceInfo() { - return this.showChanceInfo; + public boolean getShowBadge() { + return this.showBadge; } - public void setShowChanceInfo(boolean showChanceInfo) { - this.showChanceInfo = showChanceInfo; + public void setShowBadge(boolean showBadge) { + this.showBadge = showBadge; } public boolean getUseCustomScroll() { @@ -225,8 +225,8 @@ public class HandlerInfo { return this; } - public Builder setShowChanceInfo(boolean showChanceInfo) { - this.info.showChanceInfo = showChanceInfo; + public Builder setShowBadge(boolean showBadge) { + this.info.showBadge = showBadge; return this; } diff --git a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java index 9388fc0a..504ef06d 100644 --- a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java +++ b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java @@ -1,7 +1,6 @@ package codechicken.nei.recipe; import java.awt.Point; -import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -16,6 +15,7 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.common.MinecraftForge; import org.lwjgl.opengl.GL11; @@ -40,12 +40,81 @@ import codechicken.nei.util.NEIMouseUtils; public class NEIRecipeWidget extends Widget { - private static final DecimalFormat chanceFormat = new DecimalFormat("##0.##%"); + private static class Badge { + + protected final String text; + protected final String tooltip; + protected int badgeTextColor = 0xFDD835; + + public Badge(String text, String tooltip, int badgeTextColor) { + this.text = text; + this.tooltip = tooltip; + this.badgeTextColor = badgeTextColor; + } + + public Badge(String text, String tooltip) { + this( + text, + tooltip, + getHexValue(NEIClientUtils.getTextColorOrDefault("recipe.badge.color", "0xFFAA00"), 0xFFAA00)); + } + + public String getText() { + return this.text; + } + + public String getTooltip() { + return this.tooltip; + } + + public int getColor() { + return this.badgeTextColor; + } + + private static int getHexValue(String color, int defaultValue) { + try { + return (int) Long.parseLong(color.replace("0x", ""), 16); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public static Badge of(PositionedStack pStack, boolean input) { + final String badge = pStack.getCustomBadge(); + + if (badge != null) { + return badge.isEmpty() ? null : new Badge(badge, ""); + } + + if (input) { + if (StackInfo.getAmount(pStack.item) == 0) { + return new Badge( + NEIClientUtils.translate("recipe.badge.nc"), + NEIClientUtils.translate("recipe.badge.nc.tooltip")); + } else if (pStack.getChance() == 0) { + return new Badge( + NEIClientUtils.translate("recipe.badge.ncp"), + NEIClientUtils.translate("recipe.badge.ncp.tooltip")); + } else if (pStack.getChance() != PositionedStack.CHANCE_FULL) { + final String chanceText = NEIClientUtils + .formatChance(pStack.getChance() / (float) PositionedStack.CHANCE_FULL); + return new Badge(chanceText, NEIClientUtils.translate("recipe.badge.chance.consume", chanceText)); + } + } else if (pStack.getChance() != PositionedStack.CHANCE_FULL) { + final String chanceText = NEIClientUtils + .formatChance(pStack.getChance() / (float) PositionedStack.CHANCE_FULL); + return new Badge(chanceText, NEIClientUtils.translate("recipe.badge.chance.output", chanceText)); + } + + return null; + } + + } + protected AcceptsFollowingTooltipLineHandler acceptsFollowingTooltipLineHandler; protected final Map favoriteIndexes = new WeakHashMap<>(); protected final Map> permutations = new WeakHashMap<>(); - protected final Map chances = new WeakHashMap<>(); - protected int chanceColor = 0xFDD835; + protected final Map badgeCache = new WeakHashMap<>(); protected int favoriteRevision = -1; protected boolean update = true; protected int cycleticks = 0; @@ -60,20 +129,9 @@ 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; @@ -213,7 +271,7 @@ public class NEIRecipeWidget extends Widget { updatePermutationsFor(pStack); } - drawItem(pStack, mouseX, mouseY, yShift); + drawItem(pStack, mouseX, mouseY, yShift, true); } for (PositionedStack pStack : getCatalysts()) { @@ -222,11 +280,11 @@ public class NEIRecipeWidget extends Widget { updatePermutationsFor(pStack); } - drawItem(pStack, mouseX, mouseY, yShift); + drawItem(pStack, mouseX, mouseY, yShift, true); } for (PositionedStack pStack : getOutputs()) { - drawItem(pStack, mouseX, mouseY, yShift); + drawItem(pStack, mouseX, mouseY, yShift, false); } GuiContainerManager.disableMatrixStackLogging(); @@ -260,21 +318,11 @@ public class NEIRecipeWidget extends Widget { DebugHandlerWidget.instance.drawGuiPlaceholder(this); } - protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift) { + protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift, boolean input) { 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 (this.handlerInfo.getShowBadge()) { + drawBadge(pStack, input); } if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) { @@ -282,17 +330,18 @@ public class NEIRecipeWidget extends Widget { } } - protected String getChanceText(PositionedStack pStack) { + protected void drawBadge(PositionedStack pStack, boolean input) { + final Badge badge = this.badgeCache.computeIfAbsent(pStack, k -> Badge.of(k, input)); - 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); + if (badge != null && !badge.getText().isEmpty()) { + NEIClientUtils.drawNEIOverlayText( + badge.getText(), + new Rectangle4i(pStack.relx, pStack.rely, 16, 16), + 0.5f, + badge.getColor(), + true, + Alignment.TopLeft); } - - return ""; } @Override @@ -406,27 +455,21 @@ public class NEIRecipeWidget extends Widget { tooltip = this.handlerRef.handler.handleItemTooltip(guiRecipe, itemstack, tooltip, this.handlerRef.recipeIndex); - if (NEIClientConfig.showCycledIngredientsTooltip() && itemstack != null) { - final int yShift = this.handlerInfo.getYShift(); - PositionedStack hovered = null; + if (itemstack != null) { + final PositionedStack hovered = getPositionedStackMouseOver(mousex, mousey); - for (PositionedStack pStack : getInputs()) { - if (pStack.contains(mousex - this.x, mousey - this.y - yShift)) { - hovered = pStack; - break; + if (hovered != null && this.handlerInfo.getShowBadge()) { + final Badge badge = this.badgeCache + .computeIfAbsent(hovered, k -> Badge.of(k, getOutputs().indexOf(k) == -1)); + + if (badge != null && !badge.getTooltip().isEmpty()) { + tooltip.add(EnumChatFormatting.GRAY + badge.getTooltip()); } } - if (hovered == null) { - for (PositionedStack pStack : getCatalysts()) { - if (pStack.contains(mousex - this.x, mousey - this.y - yShift)) { - hovered = pStack; - break; - } - } - } - - if (hovered == null || this.permutations.getOrDefault(hovered, Collections.emptyList()).size() <= 1) { + if (hovered == null || !NEIClientConfig.showCycledIngredientsTooltip() + || this.permutations.getOrDefault(hovered, Collections.emptyList()).size() <= 1 + || getOutputs().indexOf(hovered) != -1) { this.acceptsFollowingTooltipLineHandler = null; } else if (this.acceptsFollowingTooltipLineHandler == null || this.acceptsFollowingTooltipLineHandler.tooltipGUID != hovered) { @@ -608,6 +651,7 @@ public class NEIRecipeWidget extends Widget { this.acceptsFollowingTooltipLineHandler = null; this.favoriteIndexes.clear(); this.permutations.clear(); + this.badgeCache.clear(); } for (PositionedStack pStack : getInputs()) { diff --git a/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java b/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java index 62d87ea1..ea6a5775 100644 --- a/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java +++ b/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java @@ -56,6 +56,7 @@ public class DebugHandlerWidget extends Widget { public boolean useCustomScroll; public boolean showFavorites; public boolean showOverlay; + public boolean showBadge; private String csvLine; @@ -70,6 +71,7 @@ public class DebugHandlerWidget extends Widget { this.useCustomScroll = info.getUseCustomScroll(); this.showFavorites = info.getShowFavoritesButton(); this.showOverlay = info.getShowOverlayButton(); + this.showBadge = info.getShowBadge(); this.csvLine = toCsvLine(); } @@ -80,6 +82,7 @@ public class DebugHandlerWidget extends Widget { this.info.setUseCustomScroll(this.useCustomScroll); this.info.setShowFavoritesButton(this.showFavorites); this.info.setShowOverlayButton(this.showOverlay); + this.info.setShowBadge(this.showBadge); NEIClientConfig.handlerOrdering.put(this.handlerKey, this.order); } @@ -94,6 +97,7 @@ public class DebugHandlerWidget extends Widget { 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; + this.showBadge = intOrDefault(parts[9], this.showBadge ? 1 : 0) == 1; apply(); } @@ -109,7 +113,8 @@ public class DebugHandlerWidget extends Widget { String.valueOf(this.order), String.valueOf(this.useCustomScroll ? 1 : 0), String.valueOf(this.showFavorites ? 1 : 0), - String.valueOf(this.showOverlay ? 1 : 0)); + String.valueOf(this.showOverlay ? 1 : 0), + String.valueOf(this.showBadge ? 1 : 0)); } public boolean isUnmodified() { @@ -132,7 +137,7 @@ public class DebugHandlerWidget extends Widget { private static final int LABEL_WIDTH = 50; private static final String TOOLTIP_PREFIX = "debug.RecipeHandler."; - private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,UseCustomScroll,ShowFavorites,ShowOverlay"; + private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,UseCustomScroll,ShowFavorites,ShowOverlay,ShowBadge"; private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 }; public static DebugHandlerWidget instance = new DebugHandlerWidget(); @@ -222,6 +227,11 @@ public class DebugHandlerWidget extends Widget { saveHandlerInfoPatch(); }, y); + y = addCheckboxWidget("ShowBadge", button -> { + record.showBadge = button.value; + saveHandlerInfoPatch(); + }, y); + this.h = 10 + LINE_HEIGHT + y; this.container.h = this.h - INLINE_PADDING * 2 - LINE_HEIGHT; } @@ -391,6 +401,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("showbadge").updateValue(String.valueOf(this.record.showBadge)); updateOverride(); @@ -588,7 +599,7 @@ public class DebugHandlerWidget extends Widget { 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")); + record.apply((line + ",null,null,null,null,null,null,null,null,null")); } } diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index d5689aa4..cbcf2db7 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -541,6 +541,7 @@ nei.debug.RecipeHandler.Height=Height nei.debug.RecipeHandler.Width=Width nei.debug.RecipeHandler.ShowFavorites=Show Favorites nei.debug.RecipeHandler.ShowOverlay=Show Overlays +nei.debug.RecipeHandler.ShowBadge=Show Badge nei.debug.RecipeHandler.UseCustomScroll=Use Custom Scroll nei.debug.RecipeHandler.Override=Override nei.debug.RecipeHandler.checkbox.on=On @@ -557,9 +558,15 @@ 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) + +nei.recipe.badge.nc=NC +nei.recipe.badge.nc.tooltip=Does not get consumed in the process + +nei.recipe.badge.ncp=NC(P) +nei.recipe.badge.ncp.tooltip=Considered in parallel calculation, but not get consumed + +nei.recipe.badge.chance.consume=Consume Chance: %s +nei.recipe.badge.chance.output=Output Chance: %s # Deprecated nei.recipe.fuel.required=%s required