From 72ad8aa2e708f98e99524d180186ed7c74cfda10 Mon Sep 17 00:00:00 2001 From: slprime <31038811+slprime@users.noreply.github.com> Date: Sat, 17 Aug 2024 23:24:27 +0300 Subject: [PATCH] More QOL (#510) * ItemZoom, hotkeys & more tooltips * fix tooltips * fix hover crash to unnamed item * fix bookmark group with groupIds bigger than 127 --------- Co-authored-by: slprime Co-authored-by: Martin Robertz --- .../java/codechicken/nei/AutoFocusWidget.java | 125 ++ .../nei/BookmarkCraftingChain.java | 18 +- .../java/codechicken/nei/BookmarkPanel.java | 1231 ++++++++++++----- .../java/codechicken/nei/ClientHandler.java | 4 +- .../codechicken/nei/CollapsibleItems.java | 168 ++- .../nei/GuiExtendedCreativeInv.java | 2 +- .../java/codechicken/nei/HeldItemHandler.java | 119 ++ .../codechicken/nei/ItemHistoryPanel.java | 23 +- src/main/java/codechicken/nei/ItemList.java | 6 +- src/main/java/codechicken/nei/ItemPanel.java | 29 +- src/main/java/codechicken/nei/ItemZoom.java | 249 ++++ src/main/java/codechicken/nei/ItemsGrid.java | 4 +- .../nei/ItemsTooltipLineHandler.java | 149 ++ .../java/codechicken/nei/LayoutManager.java | 112 +- .../codechicken/nei/LayoutStyleMinecraft.java | 2 + .../java/codechicken/nei/NEIClientConfig.java | 218 +-- .../java/codechicken/nei/NEIClientUtils.java | 17 +- .../java/codechicken/nei/PanelWidget.java | 48 +- .../nei/api/DefaultOverlayRenderer.java | 22 +- .../nei/api/INEIAutoFocusSearchEnable.java | 8 - .../codechicken/nei/api/IOverlayHandler.java | 35 + .../nei/api/ShortcutInputHandler.java | 2 +- .../nei/config/preset/GuiPresetList.java | 35 +- .../nei/guihook/GuiContainerManager.java | 168 ++- .../nei/guihook/IContainerTooltipHandler.java | 19 +- .../nei/recipe/GuiCraftingRecipe.java | 2 +- .../nei/recipe/GuiOverlayButton.java | 331 +++++ .../codechicken/nei/recipe/GuiRecipe.java | 417 +++--- .../nei/recipe/GuiUsageRecipe.java | 2 +- .../nei/recipe/TemplateRecipeHandler.java | 31 +- src/main/resources/assets/nei/lang/cs_CZ.lang | 6 +- src/main/resources/assets/nei/lang/de_DE.lang | 6 +- src/main/resources/assets/nei/lang/en_US.lang | 176 ++- src/main/resources/assets/nei/lang/et_EE.lang | 6 +- src/main/resources/assets/nei/lang/fr_FR.lang | 6 +- src/main/resources/assets/nei/lang/it_IT.lang | 6 +- src/main/resources/assets/nei/lang/ko_KR.lang | 6 +- src/main/resources/assets/nei/lang/pl_PL.lang | 6 +- src/main/resources/assets/nei/lang/pt_BR.lang | 4 +- src/main/resources/assets/nei/lang/sk_SK.lang | 6 +- src/main/resources/assets/nei/lang/tr_TR.lang | 6 +- src/main/resources/assets/nei/lang/zh_CN.lang | 57 +- src/main/resources/assets/nei/lang/zh_TW.lang | 6 +- 43 files changed, 2895 insertions(+), 998 deletions(-) create mode 100644 src/main/java/codechicken/nei/AutoFocusWidget.java create mode 100644 src/main/java/codechicken/nei/HeldItemHandler.java create mode 100644 src/main/java/codechicken/nei/ItemZoom.java create mode 100644 src/main/java/codechicken/nei/ItemsTooltipLineHandler.java delete mode 100644 src/main/java/codechicken/nei/api/INEIAutoFocusSearchEnable.java create mode 100644 src/main/java/codechicken/nei/recipe/GuiOverlayButton.java diff --git a/src/main/java/codechicken/nei/AutoFocusWidget.java b/src/main/java/codechicken/nei/AutoFocusWidget.java new file mode 100644 index 000000000..e0b553ef7 --- /dev/null +++ b/src/main/java/codechicken/nei/AutoFocusWidget.java @@ -0,0 +1,125 @@ +package codechicken.nei; + +import static codechicken.lib.gui.GuiDraw.getMousePosition; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.settings.GameSettings; + +import org.lwjgl.input.Keyboard; + +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerInputHandler; + +public class AutoFocusWidget implements IContainerInputHandler { + + /** + * Implement this interface on a GuiContainer to enable the autofocus search in NEI (if the autofocus option is + * enabled) without needing to add the classname to the config file . + */ + public interface INEIAutoFocusSearchEnable { + } + + public static AutoFocusWidget instance = new AutoFocusWidget(); + + public static List enableAutoFocusPrefixes = new ArrayList<>(); + + protected boolean autofocus = false; + protected Point mouse; + + public AutoFocusWidget() { + GuiContainerManager.addInputHandler(this); + } + + public void load(GuiContainer gui) { + this.autofocus = LayoutManager.searchField.isVisible() && NEIClientConfig.searchWidgetAutofocus() != 0 + && isAllowedGuiAutoSearchFocus(gui); + this.mouse = getMousePosition(); + } + + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { + + if (this.autofocus) { + this.autofocus = false; + + if (!this.mouse.equals(getMousePosition())) { + return false; + } + + if (NEIClientConfig.searchWidgetAutofocus() == 2 + && GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindInventory)) { + return false; + } + + if (keyCode == Keyboard.KEY_RETURN || keyCode == Keyboard.KEY_NUMPADENTER + || keyCode == Keyboard.KEY_ESCAPE) { + return false; + } + + LayoutManager.searchField.setFocus(true); + LayoutManager.searchField.handleKeyPress(keyCode, keyChar); + return true; + } + + return false; + } + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { + return false; + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + this.autofocus = false; + return false; + } + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + this.autofocus = false; + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {} + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + this.autofocus = false; + } + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) { + this.autofocus = false; + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + this.autofocus = false; + } + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) { + this.autofocus = false; + } + + protected boolean isAllowedGuiAutoSearchFocus(GuiContainer gui) { + if (gui instanceof INEIAutoFocusSearchEnable) { + return true; + } + String guiClassName = gui.getClass().getName(); + for (String prefix : enableAutoFocusPrefixes) { + if (guiClassName.startsWith(prefix)) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/codechicken/nei/BookmarkCraftingChain.java b/src/main/java/codechicken/nei/BookmarkCraftingChain.java index 6e5ffaa24..5ebd3fe13 100644 --- a/src/main/java/codechicken/nei/BookmarkCraftingChain.java +++ b/src/main/java/codechicken/nei/BookmarkCraftingChain.java @@ -19,6 +19,7 @@ public class BookmarkCraftingChain { public HashMap inputs = new HashMap<>(); public HashMap outputs = new HashMap<>(); + public HashMap remainder = new HashMap<>(); public HashMap intermediate = new HashMap<>(); protected static class CraftingChainItem { @@ -206,6 +207,7 @@ public void refresh(List items, List metadata) { this.inputs.clear(); this.outputs.clear(); + this.remainder.clear(); this.intermediate.clear(); this.calculatedItems.clear(); this.multiplier.clear(); @@ -245,18 +247,20 @@ public void refresh(List items, List metadata) { } } else { // output - long iCount = calculateCount(request, request.inputs.get(item.stackIndex)) - - iShift.getOrDefault(item.stackIndex, 0L); + long iCalcCount = calculateCount(request, request.inputs.get(item.stackIndex)); + long iCount = iCalcCount - iShift.getOrDefault(item.stackIndex, 0L); this.multiplier.put(item.stack, item.factor > 0 ? (int) (count / item.factor) : 0); - if (iCount < count) { - this.outputs.put(item.stack, item.getItemStack(count - iCount)); - iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount); - } else if (iCount >= count) { + if (iCount >= count) { this.intermediate.put(item.stack, item.getItemStack(0)); iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count); + } else if (iCalcCount > 0) { + this.remainder.put(item.stack, item.getItemStack(count - iCount)); + iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount); + } else { + this.outputs.put(item.stack, item.getItemStack(count - iCount)); + iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount); } - } } diff --git a/src/main/java/codechicken/nei/BookmarkPanel.java b/src/main/java/codechicken/nei/BookmarkPanel.java index 67fe6bc00..020c5a360 100644 --- a/src/main/java/codechicken/nei/BookmarkPanel.java +++ b/src/main/java/codechicken/nei/BookmarkPanel.java @@ -1,10 +1,12 @@ package codechicken.nei; import static codechicken.lib.gui.GuiDraw.drawRect; +import static codechicken.lib.gui.GuiDraw.fontRenderer; import static codechicken.lib.gui.GuiDraw.getMousePosition; import static codechicken.nei.NEIClientUtils.getGuiContainer; import static codechicken.nei.NEIClientUtils.translate; +import java.awt.Dimension; import java.awt.Point; import java.io.File; import java.io.FileInputStream; @@ -18,21 +20,22 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.WeakHashMap; +import java.util.stream.Collectors; import javax.annotation.Nullable; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; import org.apache.commons.io.IOUtils; import org.lwjgl.opengl.GL11; @@ -45,6 +48,8 @@ import com.google.gson.JsonSyntaxException; import codechicken.core.CommonUtils; +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.gui.GuiDraw.ITooltipLineHandler; import codechicken.lib.vec.Rectangle4i; import codechicken.nei.ItemPanel.ItemPanelSlot; import codechicken.nei.api.IBookmarkContainerHandler; @@ -61,7 +66,10 @@ public class BookmarkPanel extends PanelWidget { protected File bookmarkFile; protected BookmarkLoadingState bookmarksState; protected SortableItem sortableItem; + protected SortableGroup sortableGroup; protected GroupingItem groupingItem; + protected RecipeTooltipLineHandler recipeTooltipLineHandler; + protected CraftingChainTooltipLineHandler craftingChainTooltipLineHandler; public Button namespacePrev; public Button namespaceNext; @@ -76,6 +84,9 @@ protected static class SortableItem { public List items = new ArrayList<>(); public List metadata = new ArrayList<>(); + public int shiftX = 0; + public int shiftY = 0; + public SortableItem(List items, List metadata) { this.items = items; this.metadata = metadata; @@ -83,19 +94,52 @@ public SortableItem(List items, List metadata) { } + protected static class SortableGroup { + + public int groupId; + + public int shiftX = 0; + public int shiftY = 0; + + public SortableGroup(int groupId) { + this.groupId = groupId; + } + } + protected static class GroupingItem { public boolean ungroup; - public int rowIndexA; - public int rowIndexB = -1; - public GroupingItem(boolean ungroup, int rowIndexA) { + protected int startRowIndex; + protected int startItemIndexTop; + protected int startItemIndexBottom; + + protected int endRowIndex = Integer.MIN_VALUE; + protected int endItemIndexTop; + protected int endItemIndexBottom; + + public GroupingItem(BookmarkGrid BGrid, boolean ungroup, int rowIndex) { this.ungroup = ungroup; - this.rowIndexA = rowIndexA; + setStartRowIndex(BGrid, rowIndex); } - public int getTopRowIndex(BookmarkGrid BGrid) { - int topRowIndex = Math.min(this.rowIndexA, this.rowIndexB); + public void setStartRowIndex(BookmarkGrid BGrid, int rowIndex) { + this.startRowIndex = rowIndex; + this.startItemIndexTop = getTopItemIndex(BGrid, rowIndex); + this.startItemIndexBottom = getBottomItemIndex(BGrid, rowIndex); + } + + public void setEndRowIndex(BookmarkGrid BGrid, int rowIndex) { + this.endRowIndex = rowIndex; + this.endItemIndexTop = getTopItemIndex(BGrid, rowIndex); + this.endItemIndexBottom = getBottomItemIndex(BGrid, rowIndex); + } + + public boolean hasEndRow() { + return this.endRowIndex != Integer.MIN_VALUE; + } + + protected int getTopItemIndex(BookmarkGrid BGrid, int topRowIndex) { int topItemIndex = BGrid.getRowItemIndex(topRowIndex, true); ItemStackMetadata meta = topItemIndex >= 0 ? BGrid.metadata.get(topItemIndex) : null; @@ -103,16 +147,12 @@ public int getTopRowIndex(BookmarkGrid BGrid) { while (topItemIndex > 0 && meta.equalsRecipe(BGrid.metadata.get(topItemIndex - 1))) { topItemIndex--; } - - int index = BGrid.getMask().indexOf(topItemIndex); - topRowIndex = index == -1 ? 0 : index / BGrid.columns; } - return topRowIndex; + return topItemIndex; } - public int getBottomRowIndex(BookmarkGrid BGrid) { - int bottomRowIndex = Math.max(this.rowIndexA, this.rowIndexB); + protected int getBottomItemIndex(BookmarkGrid BGrid, int bottomRowIndex) { int bottomItemIndex = BGrid.getRowItemIndex(bottomRowIndex, false); ItemStackMetadata meta = bottomItemIndex >= 0 ? BGrid.metadata.get(bottomItemIndex) : null; @@ -122,24 +162,45 @@ public int getBottomRowIndex(BookmarkGrid BGrid) { while (bottomItemIndex < size - 1 && meta.equalsRecipe(BGrid.metadata.get(bottomItemIndex + 1))) { bottomItemIndex++; } + } + + return bottomItemIndex; + } + + public int getTopRowIndex(BookmarkGrid BGrid) { + final List mask = BGrid.getMask(); + final int topItemIndex = Math.min(this.startItemIndexTop, this.endItemIndexTop); + int index = mask.indexOf(topItemIndex); - int index = BGrid.getMask().indexOf(bottomItemIndex); - bottomRowIndex = index == -1 ? BGrid.getLastRowIndex() : index / BGrid.columns; + if (index != -1) { + return index == -1 ? 0 : index / BGrid.columns; } - return bottomRowIndex; + return 0; + } + + public int getBottomRowIndex(BookmarkGrid BGrid) { + final List mask = BGrid.getMask(); + final int bottomItemIndex = Math.max(this.startItemIndexBottom, this.endItemIndexBottom); + int index = mask.indexOf(bottomItemIndex); + + if (index != -1) { + return index == -1 ? BGrid.getLastRowIndex() : index / BGrid.columns; + } + + return BGrid.getLastRowIndex(); } } protected static class ItemStackMetadata { public int factor; - public Integer groupId; + public int groupId; public BookmarkRecipeId recipeId; public boolean ingredient = false; public boolean fluidDisplay = false; - public ItemStackMetadata(BookmarkRecipeId recipeId, int factor, boolean ingredient, Integer groupId, + public ItemStackMetadata(BookmarkRecipeId recipeId, int factor, boolean ingredient, int groupId, boolean fluidDisplay) { this.recipeId = recipeId; this.factor = factor; @@ -148,7 +209,7 @@ public ItemStackMetadata(BookmarkRecipeId recipeId, int factor, boolean ingredie this.fluidDisplay = fluidDisplay; } - public ItemStackMetadata(BookmarkRecipeId recipeId, NBTTagCompound nbTag, boolean ingredient, Integer groupId) { + public ItemStackMetadata(BookmarkRecipeId recipeId, NBTTagCompound nbTag, boolean ingredient, int groupId) { this(recipeId, nbTag.getInteger("Count"), ingredient, groupId, nbTag.hasKey("gtFluidName")); } @@ -180,6 +241,7 @@ public static class BookmarkRecipe { public String handlerName = ""; public List result = new ArrayList<>(); public List ingredients = new ArrayList<>(); + public BookmarkRecipeId recipeId = null; public BookmarkRecipe(ItemStack... result) { this.result.addAll(Arrays.asList(result)); @@ -187,11 +249,11 @@ public BookmarkRecipe(ItemStack... result) { public BookmarkRecipeId getRecipeId() { - if (!handlerName.isEmpty() && !ingredients.isEmpty()) { - return new BookmarkRecipeId(handlerName, ingredients); + if (!handlerName.isEmpty() && !ingredients.isEmpty() && recipeId == null) { + recipeId = new BookmarkRecipeId(handlerName, ingredients); } - return null; + return recipeId; } } @@ -238,7 +300,6 @@ public static class BookmarkGrid extends ItemsGrid { protected List metadata = new ArrayList<>(); protected WeakHashMap animation = new WeakHashMap<>(); - protected RecipeTooltipRenderer recipeTooltipRenderer = null; protected Map groups = new HashMap<>(); protected List gridGroupMask = new ArrayList<>(); @@ -247,15 +308,6 @@ public static class BookmarkGrid extends ItemsGrid { protected int focusedGroupId = -1; protected int pageCount = 0; - private static class RecipeTooltipRenderer { - - public ItemStack stack = null; - public BookmarkRecipeId recipeId = null; - - public GuiRecipe gui = null; - public Runnable createRecipeGui = null; - } - public BookmarkGrid() { this.groups.put(DEFAULT_GROUP_ID, new BookmarkGroup(BookmarkViewMode.DEFAULT)); } @@ -403,7 +455,8 @@ protected int getRowGroupId(int rowIndex) { getMask(); } - return rowIndex < this.gridGroupMask.size() ? this.gridGroupMask.get(rowIndex) : DEFAULT_GROUP_ID; + return rowIndex != -1 && rowIndex < this.gridGroupMask.size() ? this.gridGroupMask.get(rowIndex) + : DEFAULT_GROUP_ID; } protected int getRowItemIndex(int rowIndex, boolean dir) { @@ -458,41 +511,68 @@ public void draw(int mousex, int mousey) { return; } - final int focusedRowIndex = getHoveredRowIndex(true); - - if (focusedRowIndex != -1) { - drawRect( - marginLeft + paddingLeft - GROUP_PANEL_WIDTH, - marginTop + focusedRowIndex * SLOT_SIZE, - GROUP_PANEL_WIDTH, - SLOT_SIZE, - 0xee555555); - } - - final GroupingItem groupingItem = LayoutManager.bookmarkPanel.groupingItem; List groupMask = this.gridGroupMask; - int groupStartIndex = -2; + final GroupingItem groupingItem = LayoutManager.bookmarkPanel.groupingItem; + final int sortableGroupId = LayoutManager.bookmarkPanel.sortableGroup != null + ? LayoutManager.bookmarkPanel.sortableGroup.groupId + : -3; + int previousPageGroupId = this.previousPageGroupId; + int nextPageGroupId = this.nextPageGroupId; int previoudGroupId = DEFAULT_GROUP_ID; + int groupStartIndex = -2; - if (groupingItem != null && groupingItem.rowIndexB != -1) { + if (sortableGroupId != -3) { + for (int rowIndex = 0; rowIndex < groupMask.size(); rowIndex++) { + if (groupMask.get(rowIndex) == sortableGroupId) { + drawRect( + marginLeft + paddingLeft - GROUP_PANEL_WIDTH, + marginTop + rowIndex * SLOT_SIZE, + GROUP_PANEL_WIDTH, + SLOT_SIZE, + 0x66555555); + } + } + } else { + final int focusedRowIndex = getHoveredRowIndex(true); + + if (focusedRowIndex != -1) { + drawRect( + marginLeft + paddingLeft - GROUP_PANEL_WIDTH, + marginTop + focusedRowIndex * SLOT_SIZE, + GROUP_PANEL_WIDTH, + SLOT_SIZE, + 0xee555555); + } + } + + if (groupingItem != null && groupingItem.hasEndRow()) { + final List mask = this.getMask(); int topRowIndex = groupingItem.getTopRowIndex(this); int bottomRowIndex = groupingItem.getBottomRowIndex(this); - int groupIdA = groupMask.get(groupingItem.rowIndexA); + int groupIdA = this.metadata.get(groupingItem.startItemIndexTop).groupId; int groupId = groupingItem.ungroup ? DEFAULT_GROUP_ID : (groupIdA == DEFAULT_GROUP_ID ? -1 : groupIdA); groupMask = new ArrayList<>(groupMask); + if (mask.indexOf(Math.min(groupingItem.startItemIndexTop, groupingItem.endItemIndexTop)) == -1) { + previousPageGroupId = groupId; + } + + if (mask.indexOf(Math.max(groupingItem.startItemIndexBottom, groupingItem.endItemIndexBottom)) == -1) { + nextPageGroupId = groupId; + } + for (int rowIndex = topRowIndex; rowIndex <= bottomRowIndex; rowIndex++) { groupMask.set(rowIndex, groupId); } if (groupIdA != DEFAULT_GROUP_ID && !groupingItem.ungroup - && groupingItem.rowIndexA != groupingItem.rowIndexB) { - if (groupingItem.rowIndexB < groupingItem.rowIndexA) { + && groupingItem.startItemIndexTop != groupingItem.endItemIndexTop) { + if (groupingItem.endItemIndexTop < groupingItem.startItemIndexTop) { for (int rowIndex = topRowIndex - 1; rowIndex >= 0 && groupMask.get(rowIndex) == groupIdA; rowIndex--) { groupMask.set(rowIndex, DEFAULT_GROUP_ID); } - } else if (groupingItem.rowIndexB > groupingItem.rowIndexA) { + } else if (groupingItem.endItemIndexTop > groupingItem.startItemIndexTop) { for (int rowIndex = bottomRowIndex + 1; rowIndex < groupMask.size() && groupMask.get(rowIndex) == groupIdA; rowIndex++) { groupMask.set(rowIndex, DEFAULT_GROUP_ID); @@ -502,8 +582,8 @@ public void draw(int mousex, int mousey) { } - if (this.previousPageGroupId != DEFAULT_GROUP_ID && this.previousPageGroupId == groupMask.get(0)) { - previoudGroupId = this.previousPageGroupId; + if (previousPageGroupId != DEFAULT_GROUP_ID && previousPageGroupId == groupMask.get(0)) { + previoudGroupId = previousPageGroupId; groupStartIndex = -1; } @@ -511,7 +591,9 @@ public void draw(int mousex, int mousey) { int groupId = groupMask.get(rowIndex); if (groupStartIndex != -2 && previoudGroupId != DEFAULT_GROUP_ID && previoudGroupId != groupId) { - drawGroup(Math.max(DEFAULT_GROUP_ID, previoudGroupId), groupStartIndex, rowIndex - 1); + if (previoudGroupId != sortableGroupId) { + drawGroup(Math.max(DEFAULT_GROUP_ID, previoudGroupId), groupStartIndex, rowIndex - 1); + } groupStartIndex = -2; } @@ -523,9 +605,11 @@ public void draw(int mousex, int mousey) { } if (groupStartIndex != -2) { - final int rowIndex = this.nextPageGroupId != DEFAULT_GROUP_ID - && this.nextPageGroupId == groupMask.get(groupMask.size() - 1) ? this.rows : getLastRowIndex(); - drawGroup(Math.max(DEFAULT_GROUP_ID, previoudGroupId), groupStartIndex, rowIndex); + final int rowIndex = nextPageGroupId != DEFAULT_GROUP_ID + && nextPageGroupId == groupMask.get(groupMask.size() - 1) ? this.rows : getLastRowIndex(); + if (previoudGroupId != sortableGroupId) { + drawGroup(Math.max(DEFAULT_GROUP_ID, previoudGroupId), groupStartIndex, rowIndex); + } } if (NEIClientUtils.shiftKey() && !LayoutManager.bookmarkPanel.inEditingState()) { @@ -704,14 +788,9 @@ protected void onItemsChanged() { } protected void createGroup(GroupingItem groupingItem) { - final List mask = getMask(); - final int topRowIndex = groupingItem.getTopRowIndex(this); - final int bottomRowIndex = groupingItem.getBottomRowIndex(this); - final int groupIdA = getRowGroupId(groupingItem.rowIndexA); - final int startMaskIndex = topRowIndex * columns; - final int endMaskIntex = Math.min((bottomRowIndex + 1) * columns, mask.size()); - int startItemIndex = -1; - int endItemIndex = -1; + final int topItemIndex = Math.min(groupingItem.startItemIndexTop, groupingItem.endItemIndexTop); + final int bottomItemIndex = Math.max(groupingItem.startItemIndexBottom, groupingItem.endItemIndexBottom); + final int groupIdA = this.metadata.get(groupingItem.startItemIndexTop).groupId; int groupId = DEFAULT_GROUP_ID; if (!groupingItem.ungroup) { @@ -727,28 +806,33 @@ protected void createGroup(GroupingItem groupingItem) { } } - for (int index = startMaskIndex; index < endMaskIntex; index++) { - if (mask.get(index) != null) { - startItemIndex = startItemIndex == -1 ? mask.get(index) : startItemIndex; - this.metadata.get(mask.get(index)).groupId = groupId; - endItemIndex = mask.get(index); - } + for (int idx = topItemIndex; idx <= bottomItemIndex; idx++) { + this.metadata.get(idx).groupId = groupId; } - if (startItemIndex != -1 && endItemIndex != -1 - && groupIdA != DEFAULT_GROUP_ID - && !groupingItem.ungroup - && groupingItem.rowIndexA != groupingItem.rowIndexB) { - if (groupingItem.rowIndexB == topRowIndex) { - for (int idx = startItemIndex - 1; idx >= 0 && this.metadata.get(idx).groupId == groupIdA; idx--) { - this.metadata.get(idx).groupId = DEFAULT_GROUP_ID; - } - } else { - for (int idx = endItemIndex + 1; idx < this.metadata.size() - && this.metadata.get(idx).groupId == groupIdA; idx++) { - this.metadata.get(idx).groupId = DEFAULT_GROUP_ID; + if (groupIdA != DEFAULT_GROUP_ID) { + + if (!groupingItem.ungroup) { + if (groupingItem.endItemIndexTop < groupingItem.startItemIndexTop) { + for (int idx = topItemIndex - 1; idx >= 0 + && this.metadata.get(idx).groupId == groupIdA; idx--) { + this.metadata.get(idx).groupId = DEFAULT_GROUP_ID; + } + } else { + for (int idx = bottomItemIndex + 1; idx < this.metadata.size() + && this.metadata.get(idx).groupId == groupIdA; idx++) { + this.metadata.get(idx).groupId = DEFAULT_GROUP_ID; + } } - } + } else if (bottomItemIndex + 1 < this.metadata.size() + && this.metadata.get(bottomItemIndex + 1).groupId == groupIdA) { + this.groups.put(++groupId, new BookmarkGroup(getViewMode(groupIdA))); + + for (int idx = bottomItemIndex + 1; idx < this.metadata.size() + && this.metadata.get(idx).groupId == groupIdA; idx++) { + this.metadata.get(idx).groupId = groupId; + } + } } final HashSet usedSetIds = new HashSet<>(); @@ -777,6 +861,56 @@ protected void removeGroup(int groupId) { onItemsChanged(); } + protected void moveGroup(int groupId, int overRowIndex) { + final int overGroupId = getRowGroupId(overRowIndex); + final int overItemIndex = getRowItemIndex(overRowIndex, false); + final List items = new ArrayList<>(); + final List metadata = new ArrayList<>(); + boolean moveDown = true; + + for (int idx = overItemIndex + 1; idx < this.realItems.size() && moveDown; idx++) { + moveDown = this.metadata.get(idx).groupId != groupId; + } + + for (int idx = 0; idx < this.realItems.size(); idx++) { + if (this.metadata.get(idx).groupId == groupId) { + items.add(this.realItems.get(idx)); + metadata.add(this.metadata.get(idx)); + } + } + + if (moveDown) { + int bottomItemIndex = overItemIndex + 1; + + if (overGroupId == BookmarkGrid.DEFAULT_GROUP_ID || bottomItemIndex == this.realItems.size() + || this.metadata.get(bottomItemIndex).groupId != overGroupId) { + this.realItems.removeAll(items); + this.metadata.removeAll(metadata); + + bottomItemIndex -= items.size(); + + this.realItems.addAll(bottomItemIndex, items); + this.metadata.addAll(bottomItemIndex, metadata); + onItemsChanged(); + } + + } else { + int topItemIndex = getRowItemIndex(overRowIndex, true) - 1; + + if (topItemIndex >= -1 && (overGroupId == BookmarkGrid.DEFAULT_GROUP_ID || topItemIndex == -1 + || this.metadata.get(topItemIndex).groupId != overGroupId)) { + this.realItems.removeAll(items); + this.metadata.removeAll(metadata); + + this.realItems.addAll(topItemIndex + 1, items); + this.metadata.addAll(topItemIndex + 1, metadata); + + onItemsChanged(); + } + } + + } + public int indexOf(ItemStack stackA, BookmarkRecipeId recipeId) { return indexOf(stackA, recipeId, DEFAULT_GROUP_ID); } @@ -843,13 +977,16 @@ protected void removeRecipe(int idx, boolean removeFullRecipe) { } } - protected void removeRecipe(BookmarkRecipeId recipeIdA, int groupId) { + protected boolean removeRecipe(BookmarkRecipeId recipeIdA, int groupId) { + boolean removed = false; for (int slotIndex = metadata.size() - 1; slotIndex >= 0; slotIndex--) { if (metadata.get(slotIndex).equalsRecipe(recipeIdA, groupId)) { - removeItem(slotIndex); + removed = removeItem(slotIndex) || removed; } } + + return removed; } protected boolean removeItem(int idx) { @@ -898,7 +1035,6 @@ protected void moveItem(SortableItem sortableItem, int slotIndex, int groupId, b onItemsChanged(); } - } protected boolean shouldCacheItemRendering() { @@ -908,37 +1044,51 @@ protected boolean shouldCacheItemRendering() { @Override protected void beforeDrawSlot(@Nullable ItemPanelSlot focus, int idx, Rectangle4i rect) { - if (LayoutManager.bookmarkPanel.sortableItem != null || !NEIClientUtils.shiftKey()) { - super.beforeDrawSlot(focus, idx, rect); - } else if (NEIClientUtils.shiftKey() && !LayoutManager.bookmarkPanel.inEditingState()) { - ItemStack stack = this.realItems.get(idx); - ItemStackMetadata meta = this.getMetadata(idx); - BookmarkGroup groupMeta = this.groups.get(meta.groupId); + if (LayoutManager.bookmarkPanel.sortableGroup != null + && this.getMetadata(idx).groupId == LayoutManager.bookmarkPanel.sortableGroup.groupId) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0x66555555); + } else if (LayoutManager.bookmarkPanel.sortableItem != null + && LayoutManager.bookmarkPanel.sortableItem.items.contains(this.realItems.get(idx))) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0x66555555); + } else + if (!LayoutManager.bookmarkPanel.inEditingState()) { + + if (NEIClientUtils.shiftKey()) { + ItemStack stack = this.realItems.get(idx); + ItemStackMetadata meta = this.getMetadata(idx); + BookmarkGroup groupMeta = this.groups.get(meta.groupId); + + if (groupMeta.crafting != null && meta.groupId == this.focusedGroupId) { + + if (groupMeta.crafting.inputs.containsKey(stack)) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0x6645DA75); // inputs + } else if (groupMeta.crafting.outputs.containsKey(stack)) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0x9966CCFF); // exports + } else if (groupMeta.crafting.remainder.containsKey(stack)) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0x9966CCFF); // exports + } - if (groupMeta.crafting != null && meta.groupId == this.focusedGroupId) { + } else if (focus != null && meta.equalsRecipe(getMetadata(focus.slotIndex))) { + drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient ? 0x6645DA75 : 0x9966CCFF); // highlight + // recipe + } else { + super.beforeDrawSlot(focus, idx, rect); + } - if (groupMeta.crafting.inputs.containsKey(stack)) { - drawRect(rect.x, rect.y, rect.w, rect.h, 0x6645DA75); // inputs - } else if (groupMeta.crafting.outputs.containsKey(stack)) { - drawRect(rect.x, rect.y, rect.w, rect.h, 0x9966CCFF); // exports + } else { + super.beforeDrawSlot(focus, idx, rect); } - - } else if (focus != null && meta.equalsRecipe(getMetadata(focus.slotIndex))) { - drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient ? 0x6645DA75 : 0x9966CCFF); // highlight - // recipe - } else { - super.beforeDrawSlot(focus, idx, rect); } - } - } @Override protected void afterDrawSlot(@Nullable ItemPanelSlot focus, int idx, Rectangle4i rect) { final ItemStackMetadata meta = this.getMetadata(idx); - if (meta.ingredient == true || meta.recipeId == null || LayoutManager.bookmarkPanel.sortableItem != null) { + if (meta.ingredient == true || meta.recipeId == null + || LayoutManager.bookmarkPanel.sortableItem != null + || LayoutManager.bookmarkPanel.sortableGroup != null) { return; } @@ -974,8 +1124,10 @@ protected void afterDrawSlot(@Nullable ItemPanelSlot focus, int idx, Rectangle4i @Override protected void drawItem(Rectangle4i rect, int idx) { - if (LayoutManager.bookmarkPanel.sortableItem == null - || LayoutManager.bookmarkPanel.sortableItem.items.get(0) != this.realItems.get(idx)) { + if ((LayoutManager.bookmarkPanel.sortableGroup == null + || this.metadata.get(idx).groupId != LayoutManager.bookmarkPanel.sortableGroup.groupId) + && (LayoutManager.bookmarkPanel.sortableItem == null + || !LayoutManager.bookmarkPanel.sortableItem.items.contains(this.realItems.get(idx)))) { ItemStack realStack = this.realItems.get(idx); final ItemStackMetadata meta = this.getMetadata(idx); final BookmarkGroup groupMeta = this.groups.get(meta.groupId); @@ -987,6 +1139,8 @@ protected void drawItem(Rectangle4i rect, int idx) { drawStack = groupMeta.crafting.inputs.get(drawStack); } else if (groupMeta.crafting.outputs.containsKey(drawStack)) { drawStack = groupMeta.crafting.outputs.get(drawStack); + } else if (groupMeta.crafting.remainder.containsKey(drawStack)) { + drawStack = groupMeta.crafting.remainder.get(drawStack); } else if (groupMeta.crafting.intermediate.containsKey(drawStack)) { drawStack = groupMeta.crafting.intermediate.get(drawStack); } @@ -1044,124 +1198,208 @@ protected void drawRecipeMarker(int offsetX, int offsetY, FontRenderer fontRende GuiContainerManager.enable3DRender(); } - public void update() { + @Override + protected void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) { + super.afterDrawItems(mousex, mousey, focused); + + if (focused != null && NEIClientConfig.getRecipeTooltipsMode() != 0 && NEIClientConfig.isLoaded()) { + final ItemStackMetadata meta = this.metadata.get(focused.slotIndex); + final int tooltipMode = NEIClientConfig.getRecipeTooltipsMode(); + + if (meta.recipeId == null || meta.ingredient) { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler = null; + } else if (this.groups.get(meta.groupId).viewMode == BookmarkViewMode.DEFAULT && tooltipMode != 1 + && tooltipMode != 3) { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler = null; + } else + if (this.groups.get(meta.groupId).viewMode == BookmarkViewMode.TODO_LIST && tooltipMode != 2 + && tooltipMode != 3) { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler = null; + } else + if (LayoutManager.bookmarkPanel.recipeTooltipLineHandler == null + || LayoutManager.bookmarkPanel.recipeTooltipLineHandler.recipeId != meta.recipeId) { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler = new RecipeTooltipLineHandler( + focused.item, + meta.recipeId); + } - if (this.recipeTooltipRenderer != null) { + } else { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler = null; + } - if (this.recipeTooltipRenderer.createRecipeGui != null) { - this.recipeTooltipRenderer.createRecipeGui.run(); - this.recipeTooltipRenderer.createRecipeGui = null; - } + } - if (this.recipeTooltipRenderer.gui != null) { - this.recipeTooltipRenderer.gui.updateAsTooltip(); - } + public void update() { + if (LayoutManager.bookmarkPanel.recipeTooltipLineHandler != null) { + LayoutManager.bookmarkPanel.recipeTooltipLineHandler.update(); } } - public void postDrawTooltips(int mousex, int mousey, List tooltip) { - if (NEIClientConfig.getRecipeTooltipsMode() != 0) { - try { - drawRecipeTooltip(mousex, mousey, tooltip); - } catch (Exception e) { - NEIClientConfig.logger.warn("Cannot draw recipe tooltip", e); + } + + protected static class RecipeTooltipLineHandler implements ITooltipLineHandler { + + protected ItemStack stack = null; + protected GuiRecipe gui = null; + protected BookmarkRecipeId recipeId = null; + protected boolean createdGui = false; + + public RecipeTooltipLineHandler(ItemStack stack, BookmarkRecipeId recipeId) { + this.stack = stack; + this.recipeId = recipeId; + } + + public void update() { + + if (this.gui == null && !this.createdGui) { + this.gui = GuiCraftingRecipe.createRecipeGui("recipeId", false, this.stack, this.recipeId); + this.createdGui = true; + + if (this.gui != null) { + this.gui.initGui(); + this.gui.guiTop = 0; + this.gui.guiLeft = 0; } } } - private void drawRecipeTooltip(int mousex, int mousey, List itemTooltip) { - if (!NEIClientConfig.isLoaded()) { - return; + @Override + public Dimension getSize() { + + if (this.gui != null) { + return this.gui.getWidgetSize(); } - ItemPanelSlot focused = getSlotMouseOver(mousex, mousey); + return new Dimension(0, 0); + } - if (focused == null) { - this.recipeTooltipRenderer = null; - return; - } + @Override + public void draw(int x, int y) { + if (this.gui == null) return; - final ItemStackMetadata meta = this.metadata.get(focused.slotIndex); - final int tooltipMode = NEIClientConfig.getRecipeTooltipsMode(); + GL11.glPushMatrix(); + GL11.glScaled(1, 1, 3); + GL11.glTranslatef(x, y, 0); + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + RenderHelper.disableStandardItemLighting(); - if (meta.recipeId == null || meta.ingredient) { - this.recipeTooltipRenderer = null; - return; - } + this.gui.drawGuiContainerBackgroundLayer(0.0f, -100, -100); - if (this.groups.get(meta.groupId).viewMode == BookmarkViewMode.DEFAULT && tooltipMode != 1 - && tooltipMode != 3) { - this.recipeTooltipRenderer = null; - return; - } + GL11.glPopAttrib(); - if (this.groups.get(meta.groupId).viewMode == BookmarkViewMode.TODO_LIST && tooltipMode != 2 - && tooltipMode != 3) { - this.recipeTooltipRenderer = null; - return; + if (this.gui.slotcontainer != null) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + GL11.glDisable(GL11.GL_DEPTH_TEST); + @SuppressWarnings("unchecked") + List slots = (List) this.gui.slotcontainer.inventorySlots; + + for (Slot slot : slots) { + if (slot != null && slot.getStack() != null) { + GuiContainerManager.drawItem(slot.xDisplayPosition, slot.yDisplayPosition, slot.getStack()); + } + } + + GL11.glPopAttrib(); } - if (this.recipeTooltipRenderer == null || this.recipeTooltipRenderer.recipeId != meta.recipeId) { - this.recipeTooltipRenderer = new RecipeTooltipRenderer(); - this.recipeTooltipRenderer.stack = this.realItems.get(focused.slotIndex); - this.recipeTooltipRenderer.recipeId = meta.recipeId; + this.gui.drawGuiContainerForegroundLayer(-100, -100); - this.recipeTooltipRenderer.createRecipeGui = () -> { - GuiRecipe gui = GuiCraftingRecipe.createRecipeGui( - "recipeId", - false, - this.recipeTooltipRenderer.stack, - this.recipeTooltipRenderer.recipeId); + GL11.glPopMatrix(); + } + } - if (gui != null) { - gui.initGui(); - gui.guiTop = 0; - gui.guiLeft = 0; - } + protected static class CraftingChainTooltipLineHandler implements ITooltipLineHandler { + + protected int groupId; + protected BookmarkCraftingChain craftingChain; + + protected ItemsTooltipLineHandler inputs; + protected ItemsTooltipLineHandler outputs; + protected ItemsTooltipLineHandler remainder; - this.recipeTooltipRenderer.gui = gui; - }; + protected Dimension size = new Dimension(); + + public CraftingChainTooltipLineHandler(int groupId, BookmarkCraftingChain craftingChain) { + this.groupId = groupId; + this.craftingChain = craftingChain; + + this.inputs = new ItemsTooltipLineHandler( + translate("bookmark.crafting_chain.input"), + craftingChain.inputs.values().stream().collect(Collectors.toCollection(LinkedList::new)), + true, + Integer.MAX_VALUE); + + this.outputs = new ItemsTooltipLineHandler( + translate("bookmark.crafting_chain.output"), + craftingChain.outputs.values().stream().collect(Collectors.toCollection(LinkedList::new)), + true, + Integer.MAX_VALUE); + + this.remainder = new ItemsTooltipLineHandler( + translate("bookmark.crafting_chain.remainder"), + craftingChain.remainder.values().stream().collect(Collectors.toCollection(LinkedList::new)), + true, + Integer.MAX_VALUE); + + if (!this.inputs.isEmpty() || !this.outputs.isEmpty() || !this.remainder.isEmpty()) { + this.size.height += 2 + fontRenderer.FONT_HEIGHT; + this.size.width = Math.max( + this.inputs.getSize().width, + Math.max(this.outputs.getSize().width, this.remainder.getSize().width)); + + this.size.height += this.inputs.getSize().height + this.outputs.getSize().height + + this.remainder.getSize().height; } + } - if (this.recipeTooltipRenderer.gui != null) { - final Minecraft mc = Minecraft.getMinecraft(); - int recipeTooltipLines = Math.max(1, itemTooltip.size()); + @Override + public Dimension getSize() { + return this.size; + } - GL11.glPushMatrix(); - final float tooltipYOffset; - if (mousey - marginTop > height / 2) { - tooltipYOffset = mousey - this.recipeTooltipRenderer.gui.getHeightAsWidget() + 8; - } else { - tooltipYOffset = mousey + ((recipeTooltipLines < 2) ? 1 : 3 + ((recipeTooltipLines - 1) * 10)); + @Override + public void draw(int x, int y) { + if (this.size.height == 0) return; + + fontRenderer.drawStringWithShadow( + EnumChatFormatting.AQUA + translate("bookmark.crafting_chain") + EnumChatFormatting.RESET, + x, + y + 2, + 0xee555555); + + y += 2 + fontRenderer.FONT_HEIGHT; + + if (NEIClientConfig.craftingChainDir() == 0) { + + if (!this.inputs.isEmpty()) { + this.inputs.draw(x, y); + y += this.inputs.getSize().height; } - GL11.glTranslatef(mousex, tooltipYOffset, 500); - GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); - RenderHelper.disableStandardItemLighting(); - this.recipeTooltipRenderer.gui.drawGuiContainerBackgroundLayer(0.0f, -100, -100); - GL11.glPopAttrib(); - if (this.recipeTooltipRenderer.gui.slotcontainer != null) { - GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); - RenderHelper.enableGUIStandardItemLighting(); - GL11.glEnable(GL12.GL_RESCALE_NORMAL); - @SuppressWarnings("unchecked") - List slots = (List) this.recipeTooltipRenderer.gui.slotcontainer.inventorySlots; + if (!this.outputs.isEmpty()) { + this.outputs.draw(x, y); + y += this.outputs.getSize().height; + } - for (Slot slot : slots) { - if (slot != null && slot.getStack() != null) { - GuiContainerManager.drawItem(slot.xDisplayPosition, slot.yDisplayPosition, slot.getStack()); - } - } + } else { - GL11.glPopAttrib(); + if (!this.outputs.isEmpty()) { + this.outputs.draw(x, y); + y += this.outputs.getSize().height; } - this.recipeTooltipRenderer.gui.drawGuiContainerForegroundLayer(-100, -100); - for (GuiButton btn : this.recipeTooltipRenderer.gui.getOverlayButtons()) { - btn.drawButton(mc, -100, -100); + + if (!this.inputs.isEmpty()) { + this.inputs.draw(x, y); + y += this.inputs.getSize().height; } - GL11.glPopMatrix(); + } + + if (!this.remainder.isEmpty()) { + this.remainder.draw(x, y); } } @@ -1170,6 +1408,8 @@ private void drawRecipeTooltip(int mousex, int mousey, List itemTooltip) public BookmarkPanel() { grid = new BookmarkGrid(); + namespaces.add(new BookmarkGrid()); + setNamespace(0); } @Override @@ -1226,8 +1466,6 @@ public String getRenderLabel() { } }; - namespaces.add(new BookmarkGrid()); - setNamespace(activeNamespaceIndex); } @Override @@ -1241,8 +1479,9 @@ public String getLabelText() { } public boolean inEditingState() { - return this.sortableItem != null || this.draggedStack != null - || this.groupingItem != null && this.groupingItem.rowIndexB != -1; + return this.sortableItem != null || this.sortableGroup != null + || this.draggedStack != null + || this.groupingItem != null && this.groupingItem.hasEndRow(); } public void addItem(ItemStack itemStack) { @@ -1288,6 +1527,7 @@ public void addOrRemoveItem(ItemStack stackover, final String handlerName, final } else if (saveIngredients && handlerName != null && !handlerName.isEmpty() && ingredients != null) { BookmarkRecipe recipe = new BookmarkRecipe(stackover); recipe.handlerName = handlerName; + recipe.recipeId = recipeId; for (PositionedStack stack : ingredients) { recipe.ingredients.add(stack.item); @@ -1308,7 +1548,6 @@ public void addOrRemoveItem(ItemStack stackover, final String handlerName, final } fixCountOfNamespaces(); - saveBookmarks(); } public void addRecipe(BookmarkRecipe recipe, boolean saveSize) { @@ -1358,7 +1597,6 @@ public void addRecipe(BookmarkRecipe recipe, boolean saveSize, int groupId) { } fixCountOfNamespaces(); - saveBookmarks(); } public void addBookmarkGroup(List items, BookmarkViewMode viewMode) { @@ -1394,7 +1632,6 @@ public void addBookmarkGroup(List recipes, BookmarkViewMode view } fixCountOfNamespaces(); - saveBookmarks(); } public BookmarkRecipeId getBookmarkRecipeId(int slotIndex) { @@ -1417,9 +1654,26 @@ public BookmarkRecipeId getBookmarkRecipeId(ItemStack stackA) { return null; } + public boolean removeBookmarkRecipeId(BookmarkRecipeId recipeId) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final int groupId = BookmarkGrid.DEFAULT_GROUP_ID; + + return BGrid.removeRecipe(recipeId, groupId); + } + public int getHoveredGroupId(boolean groupPanel) { final BookmarkGrid BGrid = (BookmarkGrid) grid; final int overRowIndex = BGrid.getHoveredRowIndex(groupPanel); + + if (groupPanel && overRowIndex == -1) { + final Point mouse = getMousePosition(); + + if (new Rectangle4i(pagePrev.x + pagePrev.w, pagePrev.y, pageNext.x - (pagePrev.x + pagePrev.w), pagePrev.h) + .contains(mouse.x, mouse.y)) { + return BookmarkGrid.DEFAULT_GROUP_ID; + } + } + return overRowIndex >= 0 ? BGrid.getRowGroupId(overRowIndex) : -1; } @@ -1428,7 +1682,6 @@ public void removeGroup(int groupId) { if (groupId >= 0 || groupId < BGrid.groups.size()) { BGrid.removeGroup(groupId); - saveBookmarks(); } } @@ -1440,18 +1693,18 @@ protected String getNamespaceLabelText(boolean shortFormat) { protected int fixCountOfNamespaces() { - if (namespaces.get(getNameSpaceSize() - 1).size() > 0) { + if (namespaces.get(getNamespaceSize() - 1).size() > 0) { namespaces.add(new BookmarkGrid()); - } else if (activeNamespaceIndex == getNameSpaceSize() - 2 && grid.size() == 0) { - namespaces.remove(getNameSpaceSize() - 1); + } else if (activeNamespaceIndex == getNamespaceSize() - 2 && grid.size() == 0) { + namespaces.remove(getNamespaceSize() - 1); } - return getNameSpaceSize(); + return getNamespaceSize(); } protected boolean removeEmptyNamespaces() { - if (activeNamespaceIndex != getNameSpaceSize() - 1 && grid.size() == 0) { + if (activeNamespaceIndex != getNamespaceSize() - 1 && grid.size() == 0) { namespaces.remove(activeNamespaceIndex); setNamespace(activeNamespaceIndex); return true; @@ -1469,7 +1722,7 @@ protected boolean prevNamespace() { removeEmptyNamespaces(); if (activeNamespaceIndex == 0) { - setNamespace(getNameSpaceSize() - 1); + setNamespace(getNamespaceSize() - 1); } else { setNamespace(activeNamespaceIndex - 1); } @@ -1496,7 +1749,7 @@ protected boolean nextNamespace() { } protected void setNamespace(int namespaceIndex) { - activeNamespaceIndex = namespaceIndex; + activeNamespaceIndex = Math.min(namespaceIndex, namespaces.size() - 1); grid = namespaces.get(activeNamespaceIndex); if (grid.size() == 0 && activeNamespaceIndex > 0) { @@ -1507,7 +1760,7 @@ protected void setNamespace(int namespaceIndex) { } - public int getNameSpaceSize() { + public int getNamespaceSize() { return namespaces.size(); } @@ -1519,10 +1772,6 @@ public void setBookmarkFile(String worldPath) { dir.mkdirs(); } - if (bookmarksState == BookmarkLoadingState.LOADED) { - saveBookmarks(); - } - bookmarkFile = new File(dir, "bookmarks.ini"); if (!bookmarkFile.exists()) { @@ -1556,14 +1805,14 @@ public void saveBookmarks() { return; } - ArrayList strings = new ArrayList<>(); - - for (int grpIdx = 0; grpIdx < getNameSpaceSize() - 1; grpIdx++) { - final BookmarkGrid grid = namespaces.get(grpIdx); + List strings = new ArrayList<>(); + NBTTagCompound navigation = new NBTTagCompound(); + navigation.setInteger("namespaceIndex", activeNamespaceIndex); + for (int grpIdx = 0; grpIdx < getNamespaceSize() - 1; grpIdx++) { + BookmarkGrid grid = namespaces.get(grpIdx); JsonObject settings = new JsonObject(); JsonObject groups = new JsonObject(); - settings.add("active", new JsonPrimitive(activeNamespaceIndex == grpIdx)); for (int groupId : grid.groups.keySet()) { BookmarkGroup group = grid.groups.get(groupId); @@ -1576,6 +1825,8 @@ public void saveBookmarks() { settings.add("groups", groups); strings.add("; " + NBTJson.toJson(settings)); + navigation.setInteger("namespacePage." + grpIdx, grid.page); + for (int idx = 0; idx < grid.size(); idx++) { try { @@ -1608,12 +1859,13 @@ public void saveBookmarks() { try (FileOutputStream output = new FileOutputStream(bookmarkFile)) { IOUtils.writeLines(strings, "\n", output, StandardCharsets.UTF_8); + NEIClientConfig.world.nbt.setTag("bookmark", navigation); } catch (IOException e) { NEIClientConfig.logger.error("Filed to save bookmarks list to file {}", bookmarkFile, e); } } - public void loadBookmarksIfNeeded() { + protected void loadBookmarksIfNeeded() { if (bookmarksState != null || bookmarksState == BookmarkLoadingState.LOADING) { return; @@ -1637,10 +1889,14 @@ public void loadBookmarksIfNeeded() { final JsonParser parser = new JsonParser(); final List namespaces = new ArrayList<>(); + NBTTagCompound navigation = new NBTTagCompound(); namespaces.add(new BookmarkGrid()); BookmarkGrid grid = namespaces.get(0); int groupId = BookmarkGrid.DEFAULT_GROUP_ID; - int namespaceIndex = 0; + + if (NEIClientConfig.world.nbt.hasKey("bookmark")) { + navigation = NEIClientConfig.world.nbt.getCompoundTag("bookmark"); + } for (String itemStr : itemStrings) { @@ -1659,6 +1915,10 @@ public void loadBookmarksIfNeeded() { namespaces.add(grid); } + if (navigation.hasKey("namespacePage." + (namespaces.size() - 1))) { + grid.page = navigation.getInteger("namespacePage." + (namespaces.size() - 1)); + } + if (settings.get("viewmode") != null) { grid.groups.get(BookmarkGrid.DEFAULT_GROUP_ID).viewMode = BookmarkViewMode .valueOf(settings.get("viewmode").getAsString()); @@ -1680,10 +1940,6 @@ public void loadBookmarksIfNeeded() { } } - if (settings.get("active") != null && settings.get("active").getAsBoolean()) { - namespaceIndex = namespaces.size() - 1; - } - continue; } @@ -1732,7 +1988,13 @@ public void loadBookmarksIfNeeded() { this.namespaces = namespaces; bookmarksState = BookmarkLoadingState.LOADED; - setNamespace(namespaceIndex); + + if (navigation.hasKey("namespaceIndex")) { + setNamespace(navigation.getInteger("namespaceIndex")); + } else { + setNamespace(0); + } + } @Override @@ -1845,151 +2107,165 @@ protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) { @Override public void mouseDragged(int mousex, int mousey, int button, long heldTime) { - if (button == 0 && NEIClientUtils.shiftKey() && mouseDownSlot >= 0) { - ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); + if (this.groupingItem != null) { + final int overRowIndex = (mousey - grid.marginTop) / BookmarkGrid.SLOT_SIZE; - if (this.sortableItem == null) { + if (this.groupingItem.hasEndRow() || overRowIndex != this.groupingItem.startRowIndex || heldTime > 250) { + this.groupingItem.setEndRowIndex( + (BookmarkGrid) grid, + Math.max(0, Math.min(overRowIndex, grid.getLastRowIndex()))); + } - if (grid.getItem(mouseDownSlot) != null - && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 250)) { - final BookmarkGrid BGrid = (BookmarkGrid) grid; - final ItemStackMetadata meta = BGrid.getMetadata(mouseDownSlot); - final List items = new ArrayList<>(); - final List metadata = new ArrayList<>(); + return; + } else if (this.sortableGroup != null) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final int overRowIndex = (mousey - grid.marginTop) / BookmarkGrid.SLOT_SIZE; - if (meta.recipeId == null || meta.ingredient - || BGrid.getViewMode(meta.groupId) == BookmarkViewMode.DEFAULT) { - items.add(BGrid.realItems.get(this.mouseDownSlot)); - metadata.add(BGrid.metadata.get(this.mouseDownSlot)); - } else { + if (this.sortableGroup.groupId != BGrid.getRowGroupId(overRowIndex)) { + BGrid.moveGroup(this.sortableGroup.groupId, overRowIndex); + } - for (int i = 0; i < BGrid.metadata.size(); i++) { - if (meta.equalsRecipe(BGrid.getMetadata(i))) { - items.add(BGrid.realItems.get(i)); - metadata.add(BGrid.metadata.get(i)); - } - } + return; + } else if (this.sortableItem != null) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final ItemStackMetadata sortMeta = this.sortableItem.metadata.get(0); + final BookmarkViewMode sortViewMode = BGrid.getViewMode(sortMeta.groupId); + ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); - } + if (sortViewMode == BookmarkViewMode.TODO_LIST && !sortMeta.ingredient) { + mouseOverSlot = getSlotMouseOver(grid.marginLeft + grid.paddingLeft, mousey); - this.sortableItem = new SortableItem(items, metadata); - grid.onGridChanged(); - } + if (mouseOverSlot != null) { + float ySlot = (float) (mousey - BGrid.marginTop) / BookmarkGrid.SLOT_SIZE; + int lastRowIndex = BGrid.getLastRowIndex(); + int overRowIndex = (int) ySlot; + int beforeGroupId = overRowIndex > 0 ? BGrid.getRowGroupId(overRowIndex - 1) + : BookmarkGrid.DEFAULT_GROUP_ID; + int afterGroupId = overRowIndex < lastRowIndex ? BGrid.getRowGroupId(overRowIndex + 1) + : BookmarkGrid.DEFAULT_GROUP_ID; + int overGroupId = BGrid.metadata.get(mouseOverSlot.slotIndex).groupId; + ySlot -= overRowIndex; - } else { - final BookmarkGrid BGrid = (BookmarkGrid) grid; - final ItemStackMetadata sortMeta = this.sortableItem.metadata.get(0); - final BookmarkViewMode sortViewMode = BGrid.getViewMode(sortMeta.groupId); - - if (sortViewMode == BookmarkViewMode.TODO_LIST && !sortMeta.ingredient) { - mouseOverSlot = getSlotMouseOver(grid.marginLeft + grid.paddingLeft, mousey); - - if (mouseOverSlot != null) { - float ySlot = (float) (mousey - BGrid.marginTop) / BookmarkGrid.SLOT_SIZE; - int lastRowIndex = BGrid.getLastRowIndex(); - int overRowIndex = (int) ySlot; - int beforeGroupId = overRowIndex > 0 ? BGrid.getRowGroupId(overRowIndex - 1) - : BookmarkGrid.DEFAULT_GROUP_ID; - int afterGroupId = overRowIndex < lastRowIndex ? BGrid.getRowGroupId(overRowIndex + 1) - : BookmarkGrid.DEFAULT_GROUP_ID; - int overGroupId = BGrid.metadata.get(mouseOverSlot.slotIndex).groupId; - ySlot -= overRowIndex; - - if (this.sortableItem.items.indexOf(BGrid.realItems.get(mouseOverSlot.slotIndex)) == -1 - && overGroupId == sortMeta.groupId) { - - if (mouseOverSlot.slotIndex < BGrid.realItems.indexOf(sortableItem.items.get(0))) { - BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, overGroupId, true); - } else { - BGrid.moveItem( - this.sortableItem, - BGrid.getRowItemIndex(overRowIndex, false), - overGroupId, - false); - } + if (this.sortableItem.items.indexOf(BGrid.realItems.get(mouseOverSlot.slotIndex)) == -1 + && overGroupId == sortMeta.groupId) { - } else if (ySlot <= 0.25) { + if (mouseOverSlot.slotIndex < BGrid.realItems.indexOf(sortableItem.items.get(0))) { + BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, overGroupId, true); + } else { + BGrid.moveItem( + this.sortableItem, + BGrid.getRowItemIndex(overRowIndex, false), + overGroupId, + false); + } - if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) { - BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true); - } + } else if (ySlot <= 0.25) { - } else if (ySlot > 0.25 && ySlot <= 0.5) { + if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) { + BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true); + } - if (beforeGroupId != afterGroupId && beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID - && (afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID - || BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT) - && BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) { - beforeGroupId = BookmarkGrid.DEFAULT_GROUP_ID; - } + } else if (ySlot > 0.25 && ySlot <= 0.5) { - if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) { - BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true); - } + if (beforeGroupId != afterGroupId && beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID + && (afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID + || BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT) + && BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) { + beforeGroupId = BookmarkGrid.DEFAULT_GROUP_ID; + } - } else if (ySlot > 0.5 && ySlot < 0.75) { + if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) { + BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true); + } - if (beforeGroupId != afterGroupId - && (beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID - || BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT) - && afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID - && BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) { - afterGroupId = BookmarkGrid.DEFAULT_GROUP_ID; - } + } else if (ySlot > 0.5 && ySlot < 0.75) { - if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) { - BGrid.moveItem( - this.sortableItem, - BGrid.getRowItemIndex(overRowIndex, false), - afterGroupId, - false); - } + if (beforeGroupId != afterGroupId + && (beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID + || BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT) + && afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID + && BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) { + afterGroupId = BookmarkGrid.DEFAULT_GROUP_ID; + } - } else if (ySlot >= 0.75) { + if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) { + BGrid.moveItem( + this.sortableItem, + BGrid.getRowItemIndex(overRowIndex, false), + afterGroupId, + false); + } - if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST - && !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) { - BGrid.moveItem( - this.sortableItem, - BGrid.getRowItemIndex(overRowIndex, false), - afterGroupId, - false); - } + } else if (ySlot >= 0.75) { + if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST + && !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) { + BGrid.moveItem( + this.sortableItem, + BGrid.getRowItemIndex(overRowIndex, false), + afterGroupId, + false); } } - } else if (mouseOverSlot != null - && this.sortableItem.items.indexOf(BGrid.realItems.get(mouseOverSlot.slotIndex)) == -1) { - final ItemStackMetadata meta = BGrid.getMetadata(mouseOverSlot.slotIndex); + } - if (meta.groupId == sortMeta.groupId) { + } else if (mouseOverSlot != null + && this.sortableItem.items.indexOf(BGrid.realItems.get(mouseOverSlot.slotIndex)) == -1) { + final ItemStackMetadata meta = BGrid.getMetadata(mouseOverSlot.slotIndex); - if (sortViewMode == BookmarkViewMode.DEFAULT) { - BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex); - } else if (sortViewMode == BookmarkViewMode.TODO_LIST && meta.recipeId != null - && meta.recipeId.equals(sortMeta.recipeId)) { - BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex); - } + if (meta.groupId == sortMeta.groupId) { - } + if (sortViewMode == BookmarkViewMode.DEFAULT) { + BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex); + } else if (sortViewMode == BookmarkViewMode.TODO_LIST && meta.recipeId != null + && meta.recipeId.equals(sortMeta.recipeId)) { + BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex); + } } - } - + } return; - } else if (this.groupingItem != null) { - final int overRowIndex = (mousey - grid.marginTop) / BookmarkGrid.SLOT_SIZE; + } + + if (button == 0 && NEIClientUtils.shiftKey() && mouseDownSlot >= 0 && this.sortableItem == null) { + ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); + + if (grid.getItem(mouseDownSlot) != null + && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 250)) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final ItemStackMetadata meta = BGrid.getMetadata(mouseDownSlot); + final List items = new ArrayList<>(); + final List metadata = new ArrayList<>(); + + if (meta.recipeId == null || meta.ingredient + || BGrid.getViewMode(meta.groupId) == BookmarkViewMode.DEFAULT) { + items.add(BGrid.realItems.get(this.mouseDownSlot)); + metadata.add(BGrid.metadata.get(this.mouseDownSlot)); + } else { - if (this.groupingItem.rowIndexB != -1 || overRowIndex != this.groupingItem.rowIndexA || heldTime > 250) { - this.groupingItem.rowIndexB = Math.max(0, Math.min(overRowIndex, grid.getLastRowIndex())); + for (int i = 0; i < BGrid.metadata.size(); i++) { + if (BGrid.metadata.get(i).recipeId != null && meta.groupId == BGrid.metadata.get(i).groupId + && meta.recipeId.equals(BGrid.metadata.get(i).recipeId)) { + items.add(BGrid.realItems.get(i)); + metadata.add(BGrid.metadata.get(i)); + } + } + + } + + this.sortableItem = new SortableItem(items, metadata); + this.sortableItem.shiftX = -8; + this.sortableItem.shiftY = -8; + + grid.onGridChanged(); } return; @@ -2030,8 +2306,87 @@ private int getNextSlot() { public void postDraw(int mousex, int mousey) { if (this.sortableItem != null) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final List mask = BGrid.getMask(); + Point startRect = null; + GuiContainerManager.drawItems.zLevel += 100; - GuiContainerManager.drawItem(mousex - 8, mousey - 8, this.sortableItem.items.get(0).copy(), true); + + for (int i = 0; i < mask.size(); i++) { + if (mask.get(i) != null) { + int idx = mask.get(i); + + if (this.sortableItem.items.contains(BGrid.realItems.get(idx))) { + Rectangle4i rect = grid.getSlotRect(i); + + if (startRect == null) { + startRect = new Point(rect.x - this.sortableItem.shiftX, rect.y - this.sortableItem.shiftY); + } + + GuiContainerManager.drawItem( + mousex + rect.x - startRect.x + 1, + mousey + rect.y - startRect.y + 1, + BGrid.getItem(idx), + true, + ""); + } + } + } + + GuiContainerManager.drawItems.zLevel -= 100; + } + + if (this.sortableGroup != null) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final List mask = BGrid.getMask(); + Point startRect = null; + + GuiContainerManager.drawItems.zLevel += 100; + + for (int i = 0; i < mask.size(); i++) { + if (mask.get(i) != null) { + int idx = mask.get(i); + + if (BGrid.metadata.get(idx).groupId == this.sortableGroup.groupId) { + Rectangle4i rect = grid.getSlotRect(i); + + if (startRect == null) { + startRect = new Point( + rect.x - this.sortableGroup.shiftX, + rect.y - this.sortableGroup.shiftY); + } + + GuiContainerManager.drawItem( + mousex + rect.x - startRect.x + 1, + mousey + rect.y - startRect.y + 1, + BGrid.getItem(idx), + true, + ""); + } + } + } + + if (startRect != null) { + int startRowIndex = -1; + int endRowIndex = 0; + + for (int rowIndex = 0; rowIndex < BGrid.gridGroupMask.size(); rowIndex++) { + if (BGrid.gridGroupMask.get(rowIndex) == this.sortableGroup.groupId) { + + if (startRowIndex == -1) { + startRowIndex = rowIndex; + } + + endRowIndex = rowIndex; + } + } + + GL11.glPushMatrix(); + GL11.glTranslated(mousex - startRect.x, mousey - startRect.y, 1); + BGrid.drawGroup(this.sortableGroup.groupId, startRowIndex, endRowIndex); + GL11.glPopMatrix(); + } + GuiContainerManager.drawItems.zLevel -= 100; } @@ -2050,11 +2405,32 @@ public void postDraw(int mousex, int mousey) { @Override public boolean handleClickExt(int mousex, int mousey, int button) { - if (button == 0 || button == 1) { + if (button == 0 && NEIClientUtils.shiftKey()) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final int overRowIndex = BGrid.getHoveredRowIndex(true); + final int groupId = BGrid.getRowGroupId(overRowIndex); + + if (groupId != BookmarkGrid.DEFAULT_GROUP_ID) { + int rowIndex = overRowIndex; + + while (rowIndex >= 0 && groupId == BGrid.getRowGroupId(rowIndex)) { + rowIndex--; + } + + Rectangle4i rect = BGrid.getSlotRect(rowIndex + 1, 0); + this.sortableGroup = new SortableGroup(groupId); + this.sortableGroup.shiftX = rect.x - mousex; + this.sortableGroup.shiftY = rect.y - mousey; + + return true; + } + } + + if (!NEIClientUtils.shiftKey() && (button == 0 || button == 1)) { final int overRowIndex = ((BookmarkGrid) grid).getHoveredRowIndex(true); if (overRowIndex != -1) { - this.groupingItem = new GroupingItem(button == 1, overRowIndex); + this.groupingItem = new GroupingItem((BookmarkGrid) grid, button == 1, overRowIndex); return true; } } @@ -2076,18 +2452,141 @@ public boolean handleClickExt(int mousex, int mousey, int button) { } @Override - public List handleTooltip(int mx, int my, List tooltip) { + public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final int overRowIndex = BGrid.getHoveredRowIndex(true); if (new Rectangle4i(pagePrev.x + pagePrev.w, pagePrev.y, pageNext.x - (pagePrev.x + pagePrev.w), pagePrev.h) - .contains(mx, my)) { - tooltip.add(translate("bookmark.viewmode.toggle.tip")); + .contains(mousex, mousey)) { + currenttip.add(translate("bookmark.group")); + currenttip = craftingChainTooltip(BookmarkGrid.DEFAULT_GROUP_ID, currenttip); } + if (new Rectangle4i(pullBookmarkedItems.x, pullBookmarkedItems.y, pullBookmarkedItems.w, pullBookmarkedItems.h) - .contains(mx, my) && BookmarkContainerInfo.getBookmarkContainerHandler(getGuiContainer()) != null) { - tooltip.add(translate("bookmark.pullBookmarkedItems.tip")); + .contains(mousex, mousey) && BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) { + currenttip.add(translate("bookmark.pullBookmarkedItems.tip")); + } + + if (overRowIndex != -1) { + final int groupId = BGrid.getRowGroupId(overRowIndex); + + currenttip.add(translate("bookmark.group")); + + if (groupId != BookmarkGrid.DEFAULT_GROUP_ID) { + currenttip = craftingChainTooltip(groupId, currenttip); + } else { + this.craftingChainTooltipLineHandler = null; + } + } else { + this.craftingChainTooltipLineHandler = null; + } + + return super.handleTooltip(gui, mousex, mousey, currenttip); + } + + @Override + public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final int overRowIndex = BGrid.getHoveredRowIndex(true); + + if (new Rectangle4i(pagePrev.x + pagePrev.w, pagePrev.y, pageNext.x - (pagePrev.x + pagePrev.w), pagePrev.h) + .contains(mousex, mousey)) { + + hotkeys.put(translate("bookmark.group.toggle_mode.key"), translate("bookmark.group.toggle_mode")); + hotkeys.put( + translate("bookmark.group.toggle_crafting_chain.key"), + translate("bookmark.group.toggle_crafting_chain")); + + String keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.remove_recipe"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.remove_recipe")); + } + + if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) { + + keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_pull_items"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.pull_items")); + } + + keyName = NEIClientConfig + .getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_pull_items_ingredients"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.pull_items_ingredients")); + } + } + + } + + if (overRowIndex != -1) { + final int groupId = BGrid.getRowGroupId(overRowIndex); + + hotkeys.put(translate("bookmark.group.include_group.key"), translate("bookmark.group.include_group")); + + if (groupId != BookmarkGrid.DEFAULT_GROUP_ID) { + + hotkeys.put(translate("bookmark.group.exclude_group.key"), translate("bookmark.group.exclude_group")); + hotkeys.put(translate("bookmark.group.toggle_mode.key"), translate("bookmark.group.toggle_mode")); + hotkeys.put( + translate("bookmark.group.toggle_crafting_chain.key"), + translate("bookmark.group.toggle_crafting_chain")); + hotkeys.put(translate("bookmark.group.sorting.key"), translate("bookmark.group.sorting")); + } + + String keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.remove_recipe"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.remove_recipe")); + } + + if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) { + keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_pull_items"), true); + + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.pull_items")); + } + + keyName = NEIClientConfig + .getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_pull_items_ingredients"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("bookmark.group.pull_items_ingredients")); + } + } + } + + return hotkeys; + } + + private List craftingChainTooltip(int groupId, List currenttip) { + final BookmarkGrid BGrid = (BookmarkGrid) grid; + final BookmarkGroup group = BGrid.groups.get(groupId); + + if (this.craftingChainTooltipLineHandler == null || this.craftingChainTooltipLineHandler.groupId != groupId) { + + if (group.crafting != null) { + this.craftingChainTooltipLineHandler = new CraftingChainTooltipLineHandler(groupId, group.crafting); + } else { + this.craftingChainTooltipLineHandler = null; + } + } else if (group.crafting == null) { + this.craftingChainTooltipLineHandler = null; + } + + if (this.craftingChainTooltipLineHandler != null) { + currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.craftingChainTooltipLineHandler)); + } + + return currenttip; + } + + @Override + public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, + List currenttip) { + + if (contains(mousex, mousey) && itemstack != null && this.recipeTooltipLineHandler != null) { + currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.recipeTooltipLineHandler)); } - return super.handleTooltip(mx, my, tooltip); + return currenttip; } @Override @@ -2097,14 +2596,17 @@ public void mouseUp(int mousex, int mousey, int button) { this.sortableItem = null; this.mouseDownSlot = -1; grid.onItemsChanged(); /* make sure grid redraws the new item */ - saveBookmarks(); + } else if (this.sortableGroup != null) { + this.sortableGroup = null; + this.mouseDownSlot = -1; + grid.onItemsChanged(); /* make sure grid redraws the new item */ } else if (this.groupingItem != null) { final BookmarkGrid BGrid = (BookmarkGrid) grid; - if (this.groupingItem.rowIndexB != -1) { + if (this.groupingItem.hasEndRow()) { BGrid.createGroup(this.groupingItem); } else { - int groupId = BGrid.getRowGroupId(this.groupingItem.rowIndexA); + int groupId = BGrid.getRowGroupId(this.groupingItem.startRowIndex); if (groupId != BookmarkGrid.DEFAULT_GROUP_ID) { if (button == 0) { @@ -2119,7 +2621,6 @@ public void mouseUp(int mousex, int mousey, int button) { this.mouseDownSlot = -1; this.groupingItem = null; grid.onItemsChanged(); /* make sure grid redraws the new item */ - saveBookmarks(); } else { super.mouseUp(mousex, mousey, button); } @@ -2140,7 +2641,6 @@ public boolean onMouseWheel(int shift, int mousex, int mousey) { nextNamespace(); } - saveBookmarks(); return true; } @@ -2182,12 +2682,27 @@ public boolean onMouseWheel(int shift, int mousex, int mousey) { } BGrid.onItemsChanged(); - saveBookmarks(); return true; } } - return super.onMouseWheel(shift, mousex, mousey); + if (super.onMouseWheel(shift, mousex, mousey)) { + final int overRowIndex = (mousey - grid.marginTop) / BookmarkGrid.SLOT_SIZE; + final BookmarkGrid BGrid = (BookmarkGrid) grid; + + if (this.sortableGroup != null && this.sortableGroup.groupId != BGrid.getRowGroupId(overRowIndex)) { + BGrid.moveGroup(this.sortableGroup.groupId, overRowIndex); + } + + if (this.groupingItem != null + && (this.groupingItem.hasEndRow() || overRowIndex != this.groupingItem.startRowIndex)) { + this.groupingItem.setEndRowIndex(BGrid, Math.max(0, Math.min(overRowIndex, grid.getLastRowIndex()))); + } + + return true; + } + + return false; } private ItemStack shiftStackSize(BookmarkGrid BGrid, int slotIndex, int shift, int shiftMultiplier) { diff --git a/src/main/java/codechicken/nei/ClientHandler.java b/src/main/java/codechicken/nei/ClientHandler.java index f002dcd42..4f498e730 100644 --- a/src/main/java/codechicken/nei/ClientHandler.java +++ b/src/main/java/codechicken/nei/ClientHandler.java @@ -42,6 +42,7 @@ import codechicken.lib.packet.PacketCustom; import codechicken.nei.api.API; import codechicken.nei.api.ItemInfo; +import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiRecipeTab; import codechicken.nei.recipe.StackInfo; import cpw.mods.fml.client.CustomModLoadingErrorDisplayException; @@ -243,7 +244,7 @@ public static void loadEnableAutoFocus() { try (FileReader reader = new FileReader(file)) { NEIClientConfig.logger.info("Loading enable auto focus from file {}", file); - NEIClientConfig.enableAutoFocusPrefixes = IOUtils.readLines(reader).stream() + AutoFocusWidget.enableAutoFocusPrefixes = IOUtils.readLines(reader).stream() .filter((line) -> !line.startsWith("#")).collect(Collectors.toCollection(ArrayList::new)); } catch (IOException e) { NEIClientConfig.logger.error("Failed to load enable auto focus from file {}", file, e); @@ -265,6 +266,7 @@ public static void load() { public static void postInit() { loadHandlerOrdering(); + GuiContainerManager.registerReloadResourceListener(); } public static void loadHandlerOrdering() { diff --git a/src/main/java/codechicken/nei/CollapsibleItems.java b/src/main/java/codechicken/nei/CollapsibleItems.java index e5c90b929..935a7044b 100644 --- a/src/main/java/codechicken/nei/CollapsibleItems.java +++ b/src/main/java/codechicken/nei/CollapsibleItems.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -18,10 +19,17 @@ import java.util.stream.IntStream; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase.NBTPrimitive; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; import net.minecraftforge.oredict.OreDictionary; import org.apache.commons.io.IOUtils; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + import codechicken.nei.ItemList.AllMultiItemFilter; import codechicken.nei.ItemList.AnyMultiItemFilter; import codechicken.nei.ItemList.EverythingItemFilter; @@ -216,15 +224,21 @@ protected boolean matches(ItemStack stack, Predicate matcher) { protected static class GroupItem { - protected static int lastGroupIndex = 0; - - public final int groupIndex; - public final ItemFilter filter; + public String guid; + public ItemFilter filter; public boolean expanded = false; + public String displayName = ""; - public GroupItem(ItemFilter filter) { - this.groupIndex = lastGroupIndex++; + public GroupItem() {} + + public void setFilter(String filter) { + this.filter = CollapsibleItems.groupParser.getFilter(filter.trim()); + this.guid = UUID.nameUUIDFromBytes(filter.getBytes()).toString(); + } + + public void setFilter(ItemFilter filter, String guid) { this.filter = filter; + this.guid = guid; } public boolean matches(ItemStack stack) { @@ -232,8 +246,9 @@ public boolean matches(ItemStack stack) { } } + protected File statesFile; protected static final GroupTokenParser groupParser = new GroupTokenParser(); - protected final Map groups = new ConcurrentHashMap<>(); + protected final List groups = new ArrayList<>(); protected final Map cache = new ConcurrentHashMap<>(); static { @@ -242,18 +257,24 @@ public boolean matches(ItemStack stack) { } public void reload() { - GroupItem.lastGroupIndex = 0; this.groups.clear(); this.cache.clear(); for (int i = PresetsList.presets.size() - 1; i >= 0; i--) { Preset preset = PresetsList.presets.get(i); if (preset.enabled && preset.mode == PresetMode.GROUP) { - addGroup(preset); + GroupItem group = new GroupItem(); + group.setFilter(preset, UUID.nameUUIDFromBytes(preset.items.toString().getBytes()).toString()); + group.displayName = preset.name; + addGroup(group); } } - loadCollapsibleItems(); + if (NEIClientConfig.enableCollapsibleItems()) { + loadCollapsibleItems(); + } + + loadStates(); if (ItemList.loadFinished) { LayoutManager.markItemsDirty(); @@ -277,27 +298,75 @@ protected void loadCollapsibleItems() { try (FileReader reader = new FileReader(file)) { NEIClientConfig.logger.info("Loading collapsible items from file {}", file); - IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#") && !line.trim().isEmpty()) - .forEach(this::addGroup); + parseFile(IOUtils.readLines(reader)); } catch (IOException e) { NEIClientConfig.logger.error("Failed to load collapsible items from file {}", file, e); } } - protected void addGroup(String filterText) { - addGroup(CollapsibleItems.groupParser.getFilter(filterText.trim())); + public void parseFile(List itemStrings) { + final JsonParser parser = new JsonParser(); + GroupItem group = new GroupItem(); + + for (String itemStr : itemStrings) { + + if (itemStr.startsWith("#") || itemStr.trim().isEmpty()) { + continue; + } + + try { + + if (itemStr.startsWith("; ")) { + JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject(); + + if (settings.get("displayName") != null) { + group.displayName = settings.get("displayName").getAsString(); + } + + if (settings.get("unlocalizedName") != null) { + String displayName = StatCollector + .translateToLocal(settings.get("unlocalizedName").getAsString()); + + if (!displayName.equals(settings.get("unlocalizedName").getAsString())) { + group.displayName = displayName; + } + } + + if (settings.get("expanded") != null) { + group.expanded = settings.get("expanded").getAsBoolean(); + } + + } else { + group.setFilter(itemStr); + } + + if (group != null && group.filter != null) { + addGroup(group); + group = new GroupItem(); + } + + } catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) { + NEIClientConfig.logger.error("Failed to load collapsible items from json string:\n{}", itemStr); + } + } + } + + protected void addGroup(GroupItem group) { + if (group == null || group.filter == null + || group.filter instanceof EverythingItemFilter + || group.filter instanceof NothingItemFilter) + return; + this.groups.add(group); } - protected void addGroup(ItemFilter filter) { - if (filter == null || filter instanceof EverythingItemFilter || filter instanceof NothingItemFilter) return; - GroupItem group = new GroupItem(filter); - this.groups.put(group.groupIndex, group); + public boolean isEmpty() { + return this.groups.isEmpty(); } public ItemFilter getItemFilter() { AnyMultiItemFilter filter = new AnyMultiItemFilter(); - for (GroupItem group : this.groups.values()) { + for (GroupItem group : this.groups) { filter.filters.add(group.filter); } @@ -310,10 +379,10 @@ public void updateCache(final List items) { try { ItemList.forkJoinPool.submit(() -> items.parallelStream().forEach(stack -> { - GroupItem group = this.groups.values().stream().filter(g -> g.matches(stack)).findFirst().orElse(null); + GroupItem group = this.groups.stream().filter(g -> g.matches(stack)).findFirst().orElse(null); if (group != null) { - this.cache.put(stack, group.groupIndex); + this.cache.put(stack, this.groups.indexOf(group)); } })).get(); @@ -332,9 +401,18 @@ public int getGroupIndex(ItemStack stack) { return this.cache.getOrDefault(stack, -1); } + public String getDisplayName(int groupIndex) { + + if (groupIndex < this.groups.size()) { + return this.groups.get(groupIndex).displayName; + } + + return null; + } + public boolean isExpanded(int groupIndex) { - if (this.groups.containsKey(groupIndex)) { + if (groupIndex < this.groups.size()) { return this.groups.get(groupIndex).expanded; } @@ -343,22 +421,60 @@ public boolean isExpanded(int groupIndex) { public void setExpanded(int groupIndex, boolean expanded) { - if (this.groups.containsKey(groupIndex)) { + if (groupIndex < this.groups.size()) { this.groups.get(groupIndex).expanded = expanded; + saveStates(); } - } public void toggleGroups(Boolean expanded) { if (expanded == null) { - expanded = !this.groups.values().stream().filter(g -> g.expanded).findAny().isPresent(); + expanded = !this.groups.stream().filter(g -> g.expanded).findAny().isPresent(); } - for (GroupItem group : this.groups.values()) { + for (GroupItem group : this.groups) { group.expanded = expanded; } + saveStates(); + } + + private void loadStates() { + + try { + + if (NEIClientConfig.world.nbt.hasKey("collapsibleitems")) { + NBTTagCompound states = NEIClientConfig.world.nbt.getCompoundTag("collapsibleitems"); + @SuppressWarnings("unchecked") + final Map list = (Map) states.tagMap; + final Map mapping = new HashMap<>(); + + for (GroupItem group : this.groups) { + mapping.put(group.guid, group); + } + + for (Map.Entry nbtEntry : list.entrySet()) { + if (mapping.containsKey(nbtEntry.getKey())) { + mapping.get(nbtEntry.getKey()).expanded = nbtEntry.getValue().func_150290_f() == 1; + } + } + } + + } catch (Exception e) { + NEIClientConfig.logger.error("Error loading collapsible items states", e); + } + + } + + private void saveStates() { + NBTTagCompound list = new NBTTagCompound(); + + for (GroupItem group : this.groups) { + list.setBoolean(group.guid, group.expanded); + } + + NEIClientConfig.world.nbt.setTag("collapsibleitems", list); } } diff --git a/src/main/java/codechicken/nei/GuiExtendedCreativeInv.java b/src/main/java/codechicken/nei/GuiExtendedCreativeInv.java index 8d4c1d7e0..35711f491 100644 --- a/src/main/java/codechicken/nei/GuiExtendedCreativeInv.java +++ b/src/main/java/codechicken/nei/GuiExtendedCreativeInv.java @@ -12,7 +12,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.vec.Rectangle4i; -import codechicken.nei.api.INEIAutoFocusSearchEnable; +import codechicken.nei.AutoFocusWidget.INEIAutoFocusSearchEnable; import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.api.TaggedInventoryArea; diff --git a/src/main/java/codechicken/nei/HeldItemHandler.java b/src/main/java/codechicken/nei/HeldItemHandler.java new file mode 100644 index 000000000..edf3360a4 --- /dev/null +++ b/src/main/java/codechicken/nei/HeldItemHandler.java @@ -0,0 +1,119 @@ +package codechicken.nei; + +import static codechicken.nei.NEIClientUtils.translate; + +import java.util.List; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerInputHandler; +import codechicken.nei.guihook.IContainerTooltipHandler; + +public class HeldItemHandler implements IContainerInputHandler, IContainerTooltipHandler { + + protected HeldItemHandler() { + + } + + public static void load() { + HeldItemHandler instance = new HeldItemHandler(); + GuiContainerManager.addInputHandler(instance); + GuiContainerManager.addTooltipHandler(instance); + } + + protected boolean contains(int mousex, int mousey) { + return NEIClientUtils.getHeldItem() != null + && (ItemPanels.bookmarkPanel.contains(mousex, mousey) || ItemPanels.itemPanel.contains(mousex, mousey) + || ItemPanels.itemPanel.historyPanel.contains(mousex, mousey)); + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + + if (contains(mousex, mousey)) { + + if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) { + if (button == 1) { + NEIClientUtils.decreaseSlotStack(-999); + } else { + NEIClientUtils.deleteHeldItem(); + } + } else { + NEIClientUtils.dropHeldItem(); + } + + return true; + } + + return false; + } + + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { + + return false; + } + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { + + return false; + } + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) { + + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + + } + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) { + + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + + } + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) { + + } + + @Override + public List handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List currenttip) { + return currenttip; + } + + @Override + public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, + List currenttip) { + return currenttip; + } + + @Override + public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { + + if (contains(mousex, mousey)) { + currenttip.clear(); + currenttip.add(EnumChatFormatting.RED + translate("itempanel.deleteItem")); + } + + return currenttip; + } + +} diff --git a/src/main/java/codechicken/nei/ItemHistoryPanel.java b/src/main/java/codechicken/nei/ItemHistoryPanel.java index 993d653b4..b1580816b 100644 --- a/src/main/java/codechicken/nei/ItemHistoryPanel.java +++ b/src/main/java/codechicken/nei/ItemHistoryPanel.java @@ -120,28 +120,8 @@ public void mouseDragged(int mousex, int mousey, int button, long heldTime) { @Override public boolean handleClick(int mousex, int mousey, int button) { - if (handleClickExt(mousex, mousey, button)) return true; - if (NEIClientUtils.getHeldItem() != null) { - - if (!grid.contains(mousex, mousey)) { - return false; - } - - if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) { - if (button == 1) { - NEIClientUtils.decreaseSlotStack(-999); - } else { - NEIClientUtils.deleteHeldItem(); - } - } else { - NEIClientUtils.dropHeldItem(); - } - - return true; - } - ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); if (hoverSlot != null) { @@ -168,7 +148,8 @@ public void mouseUp(int mousex, int mousey, int button) { if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && ItemPanels.itemPanel.draggedStack == null) { ItemStack item = hoverSlot.item.copy(); - if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) { + if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey() + || !NEIClientConfig.canCheatItem(item)) { if (button == 0) { GuiCraftingRecipe.openRecipeGui("item", item); diff --git a/src/main/java/codechicken/nei/ItemList.java b/src/main/java/codechicken/nei/ItemList.java index 86d6ad8bd..485cfdf8f 100644 --- a/src/main/java/codechicken/nei/ItemList.java +++ b/src/main/java/codechicken/nei/ItemList.java @@ -15,6 +15,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; import com.google.common.collect.ArrayListMultimap; @@ -90,7 +91,8 @@ public PatternItemFilter(Pattern pattern) { @Override public boolean matches(ItemStack item) { - return pattern.matcher(item.getDisplayName()).find(); + String displayName = EnumChatFormatting.getTextWithoutFormattingCodes(item.getDisplayName()); + return !displayName.isEmpty() && pattern.matcher(displayName).find(); } } @@ -230,7 +232,7 @@ private void updateOrdering(List items) { ItemSorter.sort(items); - if (NEIClientConfig.enableCollapsibleItems()) { + if (!ItemList.collapsibleItems.isEmpty()) { HashMap groups = new HashMap<>(); int orderIndex = 0; diff --git a/src/main/java/codechicken/nei/ItemPanel.java b/src/main/java/codechicken/nei/ItemPanel.java index 006c2684c..31f110409 100644 --- a/src/main/java/codechicken/nei/ItemPanel.java +++ b/src/main/java/codechicken/nei/ItemPanel.java @@ -17,11 +17,11 @@ import org.lwjgl.opengl.GL11; +import codechicken.lib.gui.GuiDraw; import codechicken.lib.vec.Rectangle4i; import codechicken.nei.guihook.GuiContainerManager; -import codechicken.nei.guihook.IContainerTooltipHandler; -public class ItemPanel extends PanelWidget implements IContainerTooltipHandler { +public class ItemPanel extends PanelWidget { /** * Backwards compat :-/ @@ -66,6 +66,7 @@ public ItemPanelSlot(int idx) { protected static class MaskMetadata { public int groupIndex = -1; + public String displayName = ""; public boolean extended = false; public Color bgColor = null; @@ -97,7 +98,7 @@ public void refresh(GuiContainer gui) { this.groupItems.clear(); this.forceExpand = false; - if (NEIClientConfig.enableCollapsibleItems() && !this.newItems.isEmpty()) { + if (!ItemList.collapsibleItems.isEmpty() && !this.newItems.isEmpty()) { final Set groups = new HashSet<>(); boolean outsideGroup = false; @@ -196,6 +197,7 @@ protected void calculateGroupBorders(List mask) { MaskMetadata metadata = new MaskMetadata(); metadata.groupIndex = groupIndex; + metadata.displayName = ItemList.collapsibleItems.getDisplayName(groupIndex); metadata.extended = this.forceExpand || ItemList.collapsibleItems.isExpanded(groupIndex); metadata.bgColor = metadata.extended ? expandedColor : collapsedColor; metadata.color = darkerColor(metadata.bgColor); @@ -317,7 +319,6 @@ public String getMessageOnEmpty() { public ItemPanel() { grid = new ItemPanelGrid(); - GuiContainerManager.addTooltipHandler(this); } public static void updateItemList(ArrayList newItems) { @@ -481,7 +482,7 @@ public void setVisible() { LayoutManager.addWidget(quantity); } - if (NEIClientConfig.enableCollapsibleItems()) { + if (!ItemList.collapsibleItems.isEmpty()) { LayoutManager.addWidget(toggleGroups); } @@ -513,16 +514,6 @@ protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) { return null; } - @Override - public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { - return currenttip; - } - - @Override - public List handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List currenttip) { - return currenttip; - } - @Override public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip) { @@ -537,6 +528,12 @@ public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int if (metadata != null) { final List items = panelGrid.groupItems.get(metadata.groupIndex); + if (NEIClientConfig.getBooleanSetting("inventory.collapsibleItems.customName") && !metadata.extended + && !"".equals(metadata.displayName)) { + currenttip.clear(); + currenttip.add(metadata.displayName + GuiDraw.TOOLTIP_LINESPACE); + } + if (items != null && items.size() > 1) { String message = metadata.extended ? "itempanel.collapsed.hint.collapse" : "itempanel.collapsed.hint.expand"; @@ -549,7 +546,7 @@ public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int } } - return currenttip; + return super.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip); } @Override diff --git a/src/main/java/codechicken/nei/ItemZoom.java b/src/main/java/codechicken/nei/ItemZoom.java new file mode 100644 index 000000000..3aebc09bd --- /dev/null +++ b/src/main/java/codechicken/nei/ItemZoom.java @@ -0,0 +1,249 @@ +package codechicken.nei; + +import static codechicken.lib.gui.GuiDraw.drawStringC; +import static codechicken.lib.gui.GuiDraw.fontRenderer; +import static codechicken.lib.gui.GuiDraw.getMousePosition; + +import java.awt.Point; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; + +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerInputHandler; +import codechicken.nei.recipe.StackInfo; + +public class ItemZoom extends Widget implements IContainerInputHandler { + + public static final int MIN_ZOOM = 0; + public static final int MAX_ZOOM = 1000; + + private static final int MIN_SCALE = 2; + private static final int SLOT_SIZE = 16; + + private Boolean previousKeyboardRepeatEnabled = null; + + private ItemStack stack = null; + private String displayName = ""; + private int availableAreaWidth = 0; + private float xPosition = 0; + private float yPosition = 0; + private float scale = 1; + + public ItemZoom() { + GuiContainerManager.addInputHandler(this); + } + + @Override + public void draw(int mx, int my) { + + if (this.stack != null + && (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled") + || NEIClientConfig.isKeyHashDown("gui.itemzoom_hold")) + && GuiContainerManager.shouldShowTooltip(NEIClientUtils.getGuiContainer())) { + final float inverseScaleFactor = 1.0f / this.scale; + final float screenScale = getScreenScale(); + final float size = SLOT_SIZE * this.scale; + int shiftText = 10; + + GL11.glPushMatrix(); + GL11.glScaled(screenScale, screenScale, 1); + GL11.glScaled(this.scale, this.scale, 2); + GL11.glTranslated(this.xPosition * inverseScaleFactor, this.yPosition * inverseScaleFactor, 0); + + GuiContainerManager.drawItem(0, 0, this.stack, false, ""); + + GL11.glPopMatrix(); + + if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.showName")) { + String dispalyName = NEIClientUtils.cropText(fontRenderer, this.displayName, this.availableAreaWidth); + drawStringC( + dispalyName, + (int) ((this.xPosition + size / 2) * screenScale), + (int) ((this.yPosition + size) * screenScale) + shiftText, + NEIClientConfig.getSetting("inventory.itemzoom.nameColor").getHexValue()); + shiftText += fontRenderer.FONT_HEIGHT; + } + + if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled") + && NEIClientConfig.getBooleanSetting("inventory.itemzoom.helpText")) { + int key = NEIClientConfig.getKeyBinding("gui.itemzoom_toggle"); + + if (key > 0) { + String helpText = NEIClientUtils + .translate("itemzoom.toggle", NEIClientConfig.getKeyName(key, true)); + @SuppressWarnings("unchecked") + List lines = fontRenderer.listFormattedStringToWidth(helpText, this.availableAreaWidth); + + for (String line : lines) { + drawStringC( + line, + (int) ((this.xPosition + size / 2) * screenScale), + (int) ((this.yPosition + size) * screenScale) + 10 + shiftText, + 0x66555555); + shiftText += fontRenderer.FONT_HEIGHT; + } + } + } + + } + } + + public void resize(GuiContainer gui) { + final ItemStack stack = getStackMouseOver(gui); + + if (stack != null && (!NEIClientConfig.getBooleanSetting("inventory.itemzoom.onlySolid") + || Block.getBlockFromItem(stack.getItem()).getMaterial().isSolid())) { + final float screenScale = 1.0f / getScreenScale(); + final float availableAreaWidth = (gui.width - (gui.xSize + gui.width) / 2) * screenScale; + final float availableAreaHeight = gui.height * screenScale; + final Point mouse = getMousePosition(); + + this.scale = Math.round(getZoomAmount(gui) * getPointSize(gui) / SLOT_SIZE); + this.yPosition = (availableAreaHeight - this.scale * SLOT_SIZE) / 2; + this.xPosition = (availableAreaWidth - this.scale * SLOT_SIZE) / 2; + this.availableAreaWidth = (int) (availableAreaWidth / screenScale); + + if (ItemPanels.bookmarkPanel.contains(mouse.x, mouse.y)) { + this.xPosition += (gui.guiLeft + gui.xSize) * screenScale;; + } + + try { + this.displayName = stack.getDisplayName(); + } catch (Throwable ignored) { + this.displayName = "Unnamed"; + } + + this.stack = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack), 0); + } else { + this.stack = null; + this.displayName = ""; + } + } + + private float getPointSize(GuiContainer gui) { + final float screenScale = 1.0f / getScreenScale(); + final float availableAreaWidth = (gui.width - (gui.xSize + gui.width) / 2) * screenScale; + return availableAreaWidth / MAX_ZOOM; + } + + private float getScreenScale() { + return Minecraft.getMinecraft().currentScreen.width * 1f / Minecraft.getMinecraft().displayWidth; + } + + private int getZoomAmount(GuiContainer gui) { + return Math.max( + Math.round(SLOT_SIZE * MIN_SCALE / getPointSize(gui)), + NEIClientConfig.getIntSetting("inventory.itemzoom.zoom")); + } + + private void increaseZoom(GuiContainer gui) { + final float pointSize = getPointSize(gui); + final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE); + + NEIClientConfig.setIntSetting( + "inventory.itemzoom.zoom", + Math.min(MAX_ZOOM, Math.round((scale + 1) / (pointSize / SLOT_SIZE)))); + } + + private void decreaseZoom(GuiContainer gui) { + final float pointSize = getPointSize(gui); + final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE); + + NEIClientConfig.setIntSetting( + "inventory.itemzoom.zoom", + Math.max(MIN_ZOOM, Math.round(Math.max(MIN_SCALE, scale - 1) / (pointSize / SLOT_SIZE)))); + } + + private ItemStack getStackMouseOver(GuiContainer gui) { + + if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.neiOnly")) { + final Point mouse = getMousePosition(); + ItemStack stack = ItemPanels.itemPanel.getStackMouseOver(mouse.x, mouse.y); + + if (stack == null) { + stack = ItemPanels.bookmarkPanel.getStackMouseOver(mouse.x, mouse.y); + } + + if (stack == null) { + stack = ItemPanels.itemPanel.historyPanel.getStackMouseOver(mouse.x, mouse.y); + } + + return stack; + } + + return GuiContainerManager.getStackMouseOver(gui); + } + + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { + return false; + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {} + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { + + if (NEIClientConfig.isKeyHashDown("gui.itemzoom_toggle")) { + NEIClientConfig.getSetting("inventory.itemzoom.enabled") + .setBooleanValue(!NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")); + return true; + } + + if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_hold")) { + return true; + } + + if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_in")) { + increaseZoom(gui); + previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled(); + Keyboard.enableRepeatEvents(true); + return true; + } + + if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_out")) { + decreaseZoom(gui); + previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled(); + Keyboard.enableRepeatEvents(true); + return true; + } + + if (previousKeyboardRepeatEnabled != null) { + Keyboard.enableRepeatEvents(previousKeyboardRepeatEnabled); + previousKeyboardRepeatEnabled = null; + } + + return false; + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {} + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {} + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + return false; + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {} + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {} + +} diff --git a/src/main/java/codechicken/nei/ItemsGrid.java b/src/main/java/codechicken/nei/ItemsGrid.java index 2146f7701..e518ef39d 100644 --- a/src/main/java/codechicken/nei/ItemsGrid.java +++ b/src/main/java/codechicken/nei/ItemsGrid.java @@ -260,7 +260,7 @@ protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot f } } - private void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) { + protected void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) { final List mask = getMask(); for (int i = 0; i < mask.size(); i++) { @@ -367,8 +367,6 @@ public void draw(int mousex, int mousey) { afterDrawItems(mousex, mousey, focused); } - public void postDrawTooltips(int mousex, int mousey, List tooltip) {} - public void setVisible() { if (getItems().isEmpty() && getMessageOnEmpty() != null) { LayoutManager.addWidget(messageLabel); diff --git a/src/main/java/codechicken/nei/ItemsTooltipLineHandler.java b/src/main/java/codechicken/nei/ItemsTooltipLineHandler.java new file mode 100644 index 000000000..110090029 --- /dev/null +++ b/src/main/java/codechicken/nei/ItemsTooltipLineHandler.java @@ -0,0 +1,149 @@ +package codechicken.nei; + +import static codechicken.lib.gui.GuiDraw.fontRenderer; + +import java.awt.Dimension; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import codechicken.lib.gui.GuiDraw.ITooltipLineHandler; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.StackInfo; +import codechicken.nei.util.ReadableNumberConverter; + +public class ItemsTooltipLineHandler implements ITooltipLineHandler { + + protected static int MAX_COLUMNS = 11; + protected static int MARGIN_TOP = 2; + + protected String label; + protected EnumChatFormatting labelColor = EnumChatFormatting.GRAY; + protected List items; + protected Dimension size = new Dimension(); + protected boolean saveStackSize = false; + protected int columns = 0; + protected int count = 0; + protected int rows = 0; + protected int length = 0; + + public ItemsTooltipLineHandler(String label, List items, boolean saveStackSize) { + this(label, items, true, 5); + } + + public ItemsTooltipLineHandler(String label, List items, boolean saveStackSize, int maxRows) { + this.label = label; + this.items = groupingItemStacks(items); + this.saveStackSize = saveStackSize; + this.length = this.items.size(); + + if (this.length > 0) { + this.columns = Math.min(MAX_COLUMNS, this.length); + this.rows = Math.min(maxRows, (int) Math.ceil((float) this.length / this.columns)); + + this.size.width = Math + .max(this.columns * ItemsGrid.SLOT_SIZE, fontRenderer.getStringWidth(this.label) + 15); + this.size.height = this.rows * ItemsGrid.SLOT_SIZE + fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP; + + this.count = Math.min( + this.length, + Math.min( + this.columns * this.rows, + this.length > MAX_COLUMNS * maxRows ? (MAX_COLUMNS * maxRows - 1) : Integer.MAX_VALUE)); + } + + } + + public boolean isEmpty() { + return this.items.isEmpty(); + } + + @Override + public Dimension getSize() { + return this.size; + } + + public void setLabelColor(EnumChatFormatting color) { + this.labelColor = color; + } + + @Override + public void draw(int x, int y) { + if (this.length == 0) return; + + y += MARGIN_TOP; + + fontRenderer.drawStringWithShadow(this.labelColor + this.label + ":", x, y, 0); + + GL11.glPushMatrix(); + RenderHelper.enableGUIStandardItemLighting(); + + GL11.glScaled(1, 1, 3); + GL11.glTranslatef(x, y + fontRenderer.FONT_HEIGHT + 2, 0); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + + for (int i = 0; i < this.count; i++) { + ItemStack drawStack = this.items.get(i); + int col = i % this.columns; + int row = i / this.columns; + + String stackSize = !this.saveStackSize || drawStack.stackSize == 0 ? "" + : ReadableNumberConverter.INSTANCE.toWideReadableForm(drawStack.stackSize); + + GuiContainerManager + .drawItem(col * ItemsGrid.SLOT_SIZE, row * ItemsGrid.SLOT_SIZE, drawStack, true, stackSize); + } + + if (this.count < this.items.size()) { + fontRenderer.drawStringWithShadow( + "+" + (this.items.size() - this.count), + (this.columns - 1) * ItemsGrid.SLOT_SIZE, + (this.rows - 1) * ItemsGrid.SLOT_SIZE + (ItemsGrid.SLOT_SIZE - fontRenderer.FONT_HEIGHT) / 2 - 1, + 0xee555555); + } + + GL11.glDisable(GL12.GL_RESCALE_NORMAL); + GL11.glPopMatrix(); + } + + private List groupingItemStacks(List items) { + final Map count = new HashMap<>(); + final Map unique = new LinkedHashMap<>(); + final List result = new ArrayList<>(); + + for (ItemStack stack : items) { + final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack, true); + final String GUID = StackInfo.getItemStackGUID(stack); + + if (!unique.containsKey(GUID)) { + count.put(GUID, nbTag.getInteger("Count")); + unique.put(GUID, nbTag); + } else { + count.put(GUID, count.get(GUID) + nbTag.getInteger("Count")); + } + } + + for (String GUID : unique.keySet()) { + ItemStack stack = StackInfo.loadFromNBT(unique.get(GUID), count.get(GUID)); + + if (unique.get(GUID).hasKey("gtFluidName")) { + stack.stackSize = 0; + } + + result.add(stack); + } + + return result; + } + +} diff --git a/src/main/java/codechicken/nei/LayoutManager.java b/src/main/java/codechicken/nei/LayoutManager.java index 94421567a..2874c3350 100644 --- a/src/main/java/codechicken/nei/LayoutManager.java +++ b/src/main/java/codechicken/nei/LayoutManager.java @@ -32,7 +32,9 @@ import static codechicken.nei.NEIClientUtils.translate; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.TreeSet; import net.minecraft.client.Minecraft; @@ -40,7 +42,6 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.gui.inventory.GuiContainerCreative; import net.minecraft.client.renderer.InventoryEffectRenderer; -import net.minecraft.client.settings.GameSettings; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -53,7 +54,6 @@ import codechicken.nei.KeyManager.IKeyStateTracker; import codechicken.nei.api.API; import codechicken.nei.api.GuiInfo; -import codechicken.nei.api.INEIAutoFocusSearchEnable; import codechicken.nei.api.IRecipeOverlayRenderer; import codechicken.nei.api.ItemInfo; import codechicken.nei.api.LayoutStyle; @@ -84,13 +84,13 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH */ private static TreeSet controlWidgets = new TreeSet<>(new WidgetZOrder(true)); + private static List tooltipWidgets = new LinkedList<>(); + public static ItemPanel itemPanel; public static BookmarkPanel bookmarkPanel; public static SubsetWidget dropDown; public static SearchField searchField; - public static boolean searchInitFocusedCancellable = false; - protected static int mousePriorX; - protected static int mousePriorY; + public static ItemZoom itemZoom; public static ButtonCycled options; public static ButtonCycled bookmarksButton; @@ -167,38 +167,10 @@ public static int getLeftSize(GuiContainer gui) { return getSideWidth(gui); } - protected boolean isAllowedGuiAutoSearchFocus(GuiContainer gui) { - if (gui instanceof INEIAutoFocusSearchEnable) { - return true; - } - String guiClassName = gui.getClass().getName(); - for (String prefix : NEIClientConfig.enableAutoFocusPrefixes) { - if (guiClassName.startsWith(prefix)) { - return true; - } - } - // Maybe make this an option to make it easier to figure out what GPU class to add to the configuration? - // NEIClientConfig.logger.info("Checking for autofocus on " + guiClassName + " had no match"); - return false; - } - - protected void searchFocusInitCancelCheck() { - if (searchInitFocusedCancellable) { - if (searchField.isVisible() && NEIClientConfig.searchWidgetAutofocus() - && getInputFocused() == searchField) { - searchField.setFocus(false); - setInputFocused(null); - } - searchInitFocusedCancellable = false; - } - } - @Override public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { if (isHidden()) return; - searchFocusInitCancelCheck(); - for (Widget widget : controlWidgets) widget.onGuiClick(mousex, mousey); } @@ -208,8 +180,6 @@ public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button if (!isEnabled()) return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button); - searchFocusInitCancelCheck(); - for (Widget widget : controlWidgets) { widget.onGuiClick(mousex, mousey); if (widget.contains(mousex, mousey) ? widget.handleClick(mousex, mousey, button) @@ -230,14 +200,6 @@ public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) { public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) { if (isEnabled() && !isHidden()) { - if (searchInitFocusedCancellable) { - searchInitFocusedCancellable = false; - if (NEIClientConfig.isFirstInvCloseClosesInSearch() - && GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindInventory)) { - searchField.setFocus(false); - setInputFocused(null); - } - } if (inputFocused != null) return inputFocused.handleKeyPress(keyID, keyChar); for (Widget widget : controlWidgets) if (widget.handleKeyPress(keyID, keyChar)) return true; @@ -258,7 +220,7 @@ public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { } if (NEIClientConfig.isKeyHashDown("gui.hide_bookmarks")) { - toggleBooleanSetting("inventory.bookmarksEnabled"); + toggleBooleanSetting("inventory.bookmarks.enabled"); return true; } @@ -276,7 +238,6 @@ public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { public void onMouseUp(GuiContainer gui, int mx, int my, int button) { if (!isHidden() && isEnabled()) { - searchFocusInitCancelCheck(); for (Widget widget : controlWidgets) widget.mouseUp(mx, my, button); } } @@ -284,7 +245,6 @@ public void onMouseUp(GuiContainer gui, int mx, int my, int button) { @Override public void onMouseDragged(GuiContainer gui, int mx, int my, int button, long heldTime) { if (!isHidden() && isEnabled()) { - searchFocusInitCancelCheck(); for (Widget widget : controlWidgets) widget.mouseDragged(mx, my, button, heldTime); } } @@ -303,14 +263,6 @@ public ItemStack getStackUnderMouse(GuiContainer gui, int mousex, int mousey) { public void renderObjects(GuiContainer gui, int mousex, int mousey) { if (!isHidden()) { layout(gui); - if (mousePriorX == -1) { - mousePriorX = mousex; - mousePriorY = mousey; - } else if (mousePriorX != mousex || mousePriorY != mousey) { - searchFocusInitCancelCheck(); - mousePriorX = mousex; - mousePriorY = mousey; - } if (isEnabled()) { getLayoutStyle().drawBackground(GuiContainerManager.getManager(gui)); for (Widget widget : drawWidgets) widget.draw(mousex, mousey); @@ -342,6 +294,8 @@ public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { for (Widget widget : drawWidgets) currenttip = widget.handleTooltip(mousex, mousey, currenttip); + for (IContainerTooltipHandler tip : tooltipWidgets) + currenttip = tip.handleTooltip(gui, mousex, mousey, currenttip); } return currenttip; } @@ -359,15 +313,37 @@ public List handleItemDisplayName(GuiContainer gui, ItemStack stack, Lis currenttip.set(0, mainname); } + if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { + for (IContainerTooltipHandler tip : tooltipWidgets) + currenttip = tip.handleItemDisplayName(gui, stack, currenttip); + } + return currenttip; } @Override public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip) { + + if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { + for (IContainerTooltipHandler tip : tooltipWidgets) + currenttip = tip.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip); + } + return currenttip; } + @Override + public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + + if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { + for (IContainerTooltipHandler tip : tooltipWidgets) + hotkeys = tip.handleHotkeys(gui, mousex, mousey, hotkeys); + } + + return hotkeys; + } + public static void layout(GuiContainer gui) { VisiblityData visiblity = new VisiblityData(); @@ -403,6 +379,8 @@ private static void init() { bookmarkPanel = ItemPanels.bookmarkPanel; bookmarkPanel.init(); + itemZoom = new ItemZoom(); + dropDown = new SubsetWidget(); searchField = new SearchField("search"); API.addItemFilter(searchField); @@ -470,7 +448,7 @@ public void init() { @Override public boolean onButtonPress(boolean rightclick) { - NEIClientConfig.toggleBooleanSetting("inventory.bookmarksEnabled"); + NEIClientConfig.toggleBooleanSetting("inventory.bookmarks.enabled"); return true; } @@ -668,15 +646,7 @@ public void load(GuiContainer gui) { getLayoutStyle().init(); layout(gui); - mousePriorX = -1; - mousePriorY = -1; - - if (searchField.isVisible() && NEIClientConfig.searchWidgetAutofocus() - && isAllowedGuiAutoSearchFocus(gui)) { - searchField.setFocus(true); - setInputFocused(searchField); - searchInitFocusedCancellable = true; - } + AutoFocusWidget.instance.load(gui); } NEIController.load(gui); @@ -703,6 +673,7 @@ public boolean checkCreativeInv(GuiContainer gui) { public static void updateWidgetVisiblities(GuiContainer gui, VisiblityData visiblity) { drawWidgets = new TreeSet<>(new WidgetZOrder(false)); controlWidgets = new TreeSet<>(new WidgetZOrder(true)); + tooltipWidgets.clear(); if (!visiblity.showNEI) return; @@ -735,6 +706,8 @@ public static void updateWidgetVisiblities(GuiContainer gui, VisiblityData visib if (canPerformAction("delete")) addWidget(delete); } + addWidget(itemZoom); + if (visiblity.showSubsetDropdown) { // Bookmarks or Subset/dropdown addWidget(dropDown); @@ -754,6 +727,10 @@ public static LayoutStyle getLayoutStyle() { public static void addWidget(Widget widget) { drawWidgets.add(widget); controlWidgets.add(widget); + + if (widget instanceof IContainerTooltipHandler) { + tooltipWidgets.add((IContainerTooltipHandler) widget); + } } @Override @@ -768,7 +745,6 @@ public void guiTick(GuiContainer gui) { @Override public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { if (isHidden() || !isEnabled()) return false; - searchFocusInitCancelCheck(); for (Widget widget : drawWidgets) if (widget.onMouseWheel(scrolled, mousex, mousey)) return true; @@ -876,13 +852,11 @@ public static void drawButtonBackground(int x, int y, int w, int h, boolean edge public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent, boolean slotHighlight) { if (slotHighlight) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glTranslatef(0, 0, -150); drawRect(slotX, slotY, 16, 16, isPresent ? 0x8000AA00 : 0x80AA0000); - GL11.glTranslatef(0, 0, 150); - GL11.glEnable(GL11.GL_LIGHTING); - GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glPopAttrib(); } else { Image icon = itemPresenceOverlays[isPresent ? 1 : 0]; drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon); diff --git a/src/main/java/codechicken/nei/LayoutStyleMinecraft.java b/src/main/java/codechicken/nei/LayoutStyleMinecraft.java index 3d0458ac1..22e5c5741 100644 --- a/src/main/java/codechicken/nei/LayoutStyleMinecraft.java +++ b/src/main/java/codechicken/nei/LayoutStyleMinecraft.java @@ -9,6 +9,7 @@ import static codechicken.nei.LayoutManager.heal; import static codechicken.nei.LayoutManager.itemPanel; import static codechicken.nei.LayoutManager.itemPresenceOverlays; +import static codechicken.nei.LayoutManager.itemZoom; import static codechicken.nei.LayoutManager.magnet; import static codechicken.nei.LayoutManager.options; import static codechicken.nei.LayoutManager.rain; @@ -104,6 +105,7 @@ public void layout(GuiContainer gui, VisiblityData visiblity) { itemPanel.resize(gui); bookmarkPanel.resize(gui); + itemZoom.resize(gui); options.x = isEnabled() ? 0 : 6; options.y = isEnabled() ? gui.height - 22 : gui.height - 28; diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index c39f08565..eadeca141 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -1,7 +1,6 @@ package codechicken.nei; import java.io.File; -import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -101,9 +100,6 @@ public class NEIClientConfig { // Any handler not in the map will be assigned to 0, and negative numbers are fine. public static HashMap handlerOrdering = new HashMap<>(); - // List of prefixes of classes that should enable the autofocus search widget on open. - public static ArrayList enableAutoFocusPrefixes = new ArrayList<>(); - // Function that extracts the handler ID from a handler, with special logic for // TemplateRecipeHandler: prefer using the overlay ID if it exists. public static final Function HANDLER_ID_FUNCTION = handler -> Objects @@ -178,8 +174,8 @@ public boolean optionValid(int index) { tag.getTag("inventory.search.widgetAutofocus") .setComment( "Focus Search Widget on Open, blurs/unfocuses on mouse move unless typing has started first") - .getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.search.widgetAutofocus", true)); + .getIntValue(0); + API.addOption(new OptionCycled("inventory.search.widgetAutofocus", 3, true)); tag.getTag("inventory.search.patternMode").setComment("Search Mode").getIntValue(1); API.addOption(new OptionCycled("inventory.search.patternMode", 3, true)); @@ -242,6 +238,74 @@ public String getButtonText() { }); + tag.getTag("inventory.bookmarks.enabled").setComment("Enable/Disable Bookmark Panel").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.bookmarks.enabled", true)); + + tag.getTag("inventory.bookmarks.worldSpecific").setComment("Global or world specific bookmarks") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.bookmarks.worldSpecific", true) { + + @Override + public boolean onClick(int button) { + super.onClick(button); + initBookmarkFile(worldPath); + return true; + } + }); + + tag.getTag("inventory.bookmarks.animation").setComment("REI Style Animation in Bookmarks") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.bookmarks.animation", true)); + + tag.getTag("inventory.bookmarks.recipeTooltipsMode").setComment("Show recipe tooltips in Bookmarks") + .getIntValue(1); + API.addOption(new OptionCycled("inventory.bookmarks.recipeTooltipsMode", 4, true)); + + tag.getTag("inventory.bookmarks.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.bookmarks.showRecipeMarker", true)); + + tag.getTag("inventory.bookmarks.craftingChainDir").getIntValue(1); + API.addOption(new OptionCycled("inventory.bookmarks.craftingChainDir", 2, true)); + + tag.getTag("inventory.bookmarks.ignorePotionOverlap").setComment("Ignore overlap with potion effect HUD") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.bookmarks.ignorePotionOverlap", true)); + + tag.getTag("inventory.guirecipe.jeiStyleTabs").setComment("Enable/disable JEI Style Tabs") + .getBooleanValue(true); + API.addOption(new OptionToggleButtonBoubs("inventory.guirecipe.jeiStyleTabs", true)); + + tag.getTag("inventory.guirecipe.jeiStyleRecipeCatalyst").setComment("Enable/disable JEI Style Recipe Catalysts") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.guirecipe.jeiStyleRecipeCatalyst", true)); + + tag.getTag("inventory.guirecipe.jeiStyleCycledIngredients").setComment("JEI styled cycled ingredients") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.guirecipe.jeiStyleCycledIngredients", true)); + + tag.getTag("inventory.guirecipe.cycledIngredientsTooltip").setComment("Show cycled ingredients tooltip") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.guirecipe.cycledIngredientsTooltip", true)); + + tag.getTag("inventory.guirecipe.creativeTabStyle").setComment("Creative or JEI style tabs") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.guirecipe.creativeTabStyle", true)); + + tag.getTag("inventory.guirecipe.itemPresenceOverlay").setComment("Item presence overlay on ?-hover") + .getIntValue(1); + API.addOption(new OptionCycled("inventory.guirecipe.itemPresenceOverlay", 3, true)); + + tag.getTag("inventory.guirecipe.slotHighlightPresent").setComment("Highlight Present Item") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.guirecipe.slotHighlightPresent", true)); + + tag.getTag("inventory.guirecipe.shiftOverlayRecipe") + .setComment("Require holding shift to move items when overlaying recipe").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.guirecipe.shiftOverlayRecipe", true)); + + tag.getTag("inventory.guirecipe.profile").getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.guirecipe.profile", true)); + tag.getTag("inventory.history.enabled").setComment("Enable/disable History Panel").getBooleanValue(true); API.addOption(new OptionToggleButton("inventory.history.enabled", true)); @@ -265,6 +329,9 @@ public boolean onClick(int button) { } }); + tag.getTag("inventory.collapsibleItems.customName").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.collapsibleItems.customName", true)); + tag.getTag("inventory.collapsibleItems.expandedColor") .setComment("Color of the collapsible item expanded state").getHexValue(0x335555EE); API.addOption(new OptionIntegerField("inventory.collapsibleItems.expandedColor")); @@ -286,6 +353,31 @@ public boolean onClick(int button) { } }); + tag.getTag("inventory.itemzoom.enabled").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.itemzoom.enabled", true)); + + tag.getTag("inventory.itemzoom.neiOnly") + .setComment("Zoom items only from the JEI ingredient and bookmark list overlays.") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.itemzoom.neiOnly", true)); + + tag.getTag("inventory.itemzoom.onlySolid").getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.itemzoom.onlySolid", true)); + + tag.getTag("inventory.itemzoom.helpText") + .setComment("Display name \"Item Zoom\" and the hotkey to toggle this mod below the zoomed item.") + .getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.itemzoom.helpText", true)); + + tag.getTag("inventory.itemzoom.zoom").getIntValue(500); + API.addOption(new OptionIntegerField("inventory.itemzoom.zoom", ItemZoom.MIN_ZOOM, ItemZoom.MAX_ZOOM)); + + tag.getTag("inventory.itemzoom.showName").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.itemzoom.showName", true)); + + tag.getTag("inventory.itemzoom.nameColor").getHexValue(0xFFFFFFFF); + API.addOption(new OptionIntegerField("inventory.itemzoom.nameColor")); + tag.getTag("inventory.itemIDs").getIntValue(1); API.addOption(new OptionCycled("inventory.itemIDs", 3, true)); @@ -308,9 +400,6 @@ public boolean onClick(int button) { API.addOption(new OptionOpenGui("world.presets", GuiPresetList.class)); - tag.getTag("inventory.profileRecipes").getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.profileRecipes", true)); - tag.getTag("inventory.disableMouseScrollTransfer").getBooleanValue(false); API.addOption(new OptionToggleButton("inventory.disableMouseScrollTransfer", true)); @@ -339,18 +428,6 @@ public boolean isEnabled() { tag.getTag("command.heal").setDefaultValue(""); API.addOption(new OptionTextField("command.heal")); - tag.getTag("inventory.worldSpecificBookmarks").setComment("Global or world specific bookmarks") - .getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.worldSpecificBookmarks", true) { - - @Override - public boolean onClick(int button) { - super.onClick(button); - initBookmarkFile(worldPath); - return true; - } - }); - tag.getTag("inventory.worldSpecificPresets").setComment("Global or world specific presets") .getBooleanValue(false); API.addOption(new OptionToggleButton("inventory.worldSpecificPresets", true) { @@ -363,59 +440,13 @@ public boolean onClick(int button) { } }); - tag.getTag("inventory.bookmarksEnabled").setComment("Enable/disable bookmarks").getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.bookmarksEnabled", true)); - - tag.getTag("inventory.bookmarksAnimationEnabled").setComment("REI Style Animation in Bookmarks") - .getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.bookmarksAnimationEnabled", true)); - - tag.getTag("inventory.recipeTooltipsMode").setComment("Show recipe tooltips in Bookmarks").getIntValue(1); - API.addOption(new OptionCycled("inventory.recipeTooltipsMode", 4, true)); - - tag.getTag("inventory.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.showRecipeMarker", true)); - tag.getTag("inventory.showItemQuantityWidget").setComment("Show Item Quantity Widget").getBooleanValue(true); API.addOption(new OptionToggleButton("inventory.showItemQuantityWidget", true)); - tag.getTag("inventory.firstInvCloseClosesInSearch").setComment( - "Pressing the open inventory key when the inventory was just opened when the search is focused will close it instead of typing in the search") - .getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.firstInvCloseClosesInSearch", true)); - - tag.getTag("inventory.jei_style_tabs").setComment("Enable/disable JEI Style Tabs").getBooleanValue(true); - API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true)); - - tag.getTag("inventory.itemPresenceOverlay").setComment("Item presence overlay on ?-hover").getIntValue(1); - API.addOption(new OptionCycled("inventory.itemPresenceOverlay", 3, true)); - - tag.getTag("inventory.slotHighlightPresent").setComment("Highlight Present Item").getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.slotHighlightPresent", true)); - - tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts") - .getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true)); - - tag.getTag("inventory.creative_tab_style").setComment("Creative or JEI style tabs").getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.creative_tab_style", true)); - - tag.getTag("inventory.ignore_potion_overlap").setComment("Ignore overlap with potion effect HUD") - .getBooleanValue(false); - API.addOption(new OptionToggleButton("inventory.ignore_potion_overlap", true)); - tag.getTag("inventory.optimize_gui_overlap_computation").setComment("Optimize computation for GUI overlap") .getBooleanValue(false); API.addOption(new OptionToggleButton("inventory.optimize_gui_overlap_computation", true)); - tag.getTag("inventory.jei_style_cycled_ingredients").setComment("JEI styled cycled ingredients") - .getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.jei_style_cycled_ingredients", true)); - - tag.getTag("inventory.shift_overlay_recipe") - .setComment("Require holding shift to move items when overlaying recipe").getBooleanValue(true); - API.addOption(new OptionToggleButton("inventory.shift_overlay_recipe", true)); - tag.getTag("tools.handler_load_from_config").setComment("ADVANCED: Load handlers from config") .getBooleanValue(false); API.addOption(new OptionToggleButton("tools.handler_load_from_config", true) { @@ -484,6 +515,7 @@ private static void setDefaultKeyBindings() { API.addHashBind("gui.search", Keyboard.KEY_F); API.addHashBind("gui.bookmark", Keyboard.KEY_A); API.addHashBind("gui.bookmark_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH); + API.addHashBind("gui.remove_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH); API.addHashBind("gui.bookmark_count", Keyboard.KEY_A + NEIClientUtils.CTRL_HASH); API.addHashBind( "gui.bookmark_recipe_count", @@ -498,6 +530,11 @@ private static void setDefaultKeyBindings() { API.addKeyBind("gui.getnextsearch", Keyboard.KEY_DOWN); API.addHashBind("gui.next_tooltip", Keyboard.KEY_Z); + API.addHashBind("gui.itemzoom_toggle", Keyboard.KEY_Z + NEIClientUtils.SHIFT_HASH); + API.addHashBind("gui.itemzoom_hold", 0); + API.addHashBind("gui.itemzoom_zoom_in", 0); + API.addHashBind("gui.itemzoom_zoom_out", 0); + API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9); API.addKeyBind("world.moboverlay", Keyboard.KEY_F7); API.addKeyBind("world.highlight_tips", Keyboard.KEY_NUMPAD0); @@ -530,9 +567,9 @@ public static void loadWorld(String worldPath) { specificDir.mkdirs(); } + world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg"))); initBookmarkFile(worldPath); initPresetsFile(worldPath); - world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg"))); onWorldLoad(newWorld); } @@ -624,6 +661,7 @@ public static void bootNEI(World world) { ItemInfo.load(world); GuiInfo.load(); RecipeInfo.load(); + HeldItemHandler.load(); LayoutManager.load(); NEIController.load(); BookmarkContainerInfo.load(); @@ -668,7 +706,7 @@ public void run() { private static void initBookmarkFile(String worldPath) { - if (!global.config.getTag("inventory.worldSpecificBookmarks").getBooleanValue()) { + if (!global.config.getTag("inventory.bookmarks.worldSpecific").getBooleanValue()) { worldPath = "global"; } @@ -703,19 +741,19 @@ public static boolean isHidden() { } public static boolean isBookmarkPanelHidden() { - return !getBooleanSetting("inventory.bookmarksEnabled"); + return !getBooleanSetting("inventory.bookmarks.enabled"); } public static boolean areBookmarksAnimated() { - return getBooleanSetting("inventory.bookmarksAnimationEnabled"); + return getBooleanSetting("inventory.bookmarks.animation"); } public static int getRecipeTooltipsMode() { - return getIntSetting("inventory.recipeTooltipsMode"); + return getIntSetting("inventory.bookmarks.recipeTooltipsMode"); } public static boolean showRecipeMarker() { - return getBooleanSetting("inventory.showRecipeMarker"); + return getBooleanSetting("inventory.bookmarks.showRecipeMarker"); } public static boolean showItemQuantityWidget() { @@ -726,36 +764,36 @@ public static boolean isSearchWidgetCentered() { return getBooleanSetting("inventory.search.widgetPosition"); } - public static boolean searchWidgetAutofocus() { - return getBooleanSetting("inventory.search.widgetAutofocus"); - } - - public static boolean isFirstInvCloseClosesInSearch() { - return getBooleanSetting("inventory.firstInvCloseClosesInSearch"); + public static int searchWidgetAutofocus() { + return getIntSetting("inventory.search.widgetAutofocus"); } public static boolean areJEIStyleTabsVisible() { - return getBooleanSetting("inventory.jei_style_tabs"); + return getBooleanSetting("inventory.guirecipe.jeiStyleTabs"); } public static int itemPresenceOverlay() { - return getIntSetting("inventory.itemPresenceOverlay"); + return getIntSetting("inventory.guirecipe.itemPresenceOverlay"); } public static boolean isSlotHighlightPresent() { - return getBooleanSetting("inventory.slotHighlightPresent"); + return getBooleanSetting("inventory.guirecipe.slotHighlightPresent"); } public static boolean areJEIStyleRecipeCatalystsVisible() { - return getBooleanSetting("inventory.jei_style_recipe_catalyst"); + return getBooleanSetting("inventory.guirecipe.jeiStyleRecipeCatalyst"); } public static boolean useCreativeTabStyle() { - return getBooleanSetting("inventory.creative_tab_style"); + return getBooleanSetting("inventory.guirecipe.creativeTabStyle"); } public static boolean ignorePotionOverlap() { - return getBooleanSetting("inventory.ignore_potion_overlap"); + return getBooleanSetting("inventory.bookmarks.ignorePotionOverlap"); + } + + public static int craftingChainDir() { + return getIntSetting("inventory.bookmarks.craftingChainDir"); } public static boolean optimizeGuiOverlapComputation() { @@ -763,11 +801,15 @@ public static boolean optimizeGuiOverlapComputation() { } public static boolean useJEIStyledCycledIngredients() { - return getBooleanSetting("inventory.jei_style_cycled_ingredients"); + return getBooleanSetting("inventory.guirecipe.jeiStyleCycledIngredients"); + } + + public static boolean showCycledIngredientsTooltip() { + return getBooleanSetting("inventory.guirecipe.cycledIngredientsTooltip"); } public static boolean requireShiftForOverlayRecipe() { - return getBooleanSetting("inventory.shift_overlay_recipe"); + return getBooleanSetting("inventory.guirecipe.shiftOverlayRecipe"); } public static boolean isEnabled() { @@ -787,7 +829,7 @@ public static boolean loadCatalystsFromJar() { } public static boolean isProfileRecipeEnabled() { - return NEIClientConfig.getBooleanSetting("inventory.profileRecipes"); + return NEIClientConfig.getBooleanSetting("inventory.guirecipe.profile"); } public static void setEnabled(boolean flag) { diff --git a/src/main/java/codechicken/nei/NEIClientUtils.java b/src/main/java/codechicken/nei/NEIClientUtils.java index e111ccdd8..709af4638 100644 --- a/src/main/java/codechicken/nei/NEIClientUtils.java +++ b/src/main/java/codechicken/nei/NEIClientUtils.java @@ -367,18 +367,23 @@ public static ArrayList addIntegersToRanges(List ranges, List containerWidth) { - textWidth += fontRenderer.getStringWidth("..."); + int dots = fontRenderer.getStringWidth("..."); + + if (containerWidth > dots) { + textWidth += dots; + + while (textWidth > containerWidth) { + textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1)); + text = text.substring(0, text.length() - 1); + } - while (textWidth > containerWidth) { - textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1)); - text = text.substring(0, text.length() - 1); + return text + "..."; } - return text + "..."; + return "..."; } return text; diff --git a/src/main/java/codechicken/nei/PanelWidget.java b/src/main/java/codechicken/nei/PanelWidget.java index 291a338da..c48fe7e92 100644 --- a/src/main/java/codechicken/nei/PanelWidget.java +++ b/src/main/java/codechicken/nei/PanelWidget.java @@ -11,11 +11,12 @@ import codechicken.nei.api.GuiInfo; import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipe; import codechicken.nei.recipe.GuiUsageRecipe; -public abstract class PanelWidget extends Widget { +public abstract class PanelWidget extends Widget implements IContainerTooltipHandler { protected static final int PADDING = 2; @@ -197,11 +198,6 @@ public void postDraw(int mousex, int mousey) { } } - @Override - public void postDrawTooltips(int mx, int my, List tooltip) { - grid.postDrawTooltips(mx, my, tooltip); - } - @Override public void mouseDragged(int mousex, int mousey, int button, long heldTime) { if (mouseDownSlot >= 0 && draggedStack == null @@ -220,28 +216,8 @@ public void mouseDragged(int mousex, int mousey, int button, long heldTime) { @Override public boolean handleClick(int mousex, int mousey, int button) { - if (handleClickExt(mousex, mousey, button)) return true; - if (NEIClientUtils.getHeldItem() != null) { - - if (!grid.contains(mousex, mousey)) { - return false; - } - - if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) { - if (button == 1) { - NEIClientUtils.decreaseSlotStack(-999); - } else { - NEIClientUtils.deleteHeldItem(); - } - } else { - NEIClientUtils.dropHeldItem(); - } - - return true; - } - ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); if (hoverSlot != null) { @@ -336,7 +312,8 @@ public void mouseUp(int mousex, int mousey, int button) { if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) { ItemStack item = hoverSlot.item.copy(); - if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) { + if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey() + || !NEIClientConfig.canCheatItem(item)) { if (button == 0) { GuiCraftingRecipe.openRecipeGui("item", item); @@ -400,4 +377,21 @@ public int getNumPages() { public boolean contains(int px, int py) { return grid.contains(px, py); } + + @Override + public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { + return currenttip; + } + + @Override + public List handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List currenttip) { + return currenttip; + } + + @Override + public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, + List currenttip) { + return currenttip; + } + } diff --git a/src/main/java/codechicken/nei/api/DefaultOverlayRenderer.java b/src/main/java/codechicken/nei/api/DefaultOverlayRenderer.java index e0397221b..2975be1b2 100644 --- a/src/main/java/codechicken/nei/api/DefaultOverlayRenderer.java +++ b/src/main/java/codechicken/nei/api/DefaultOverlayRenderer.java @@ -1,5 +1,7 @@ package codechicken.nei.api; +import static codechicken.lib.gui.GuiDraw.drawRect; + import java.util.ArrayList; import java.util.List; @@ -21,20 +23,26 @@ public DefaultOverlayRenderer(List ai, IStackPositioner positio @Override public void renderOverlay(GuiContainerManager gui, Slot slot) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(770, 1); - GL11.glColor4d(0.6, 0.6, 0.6, 0.7); - GuiContainerManager.setColouredItemRender(true); for (PositionedStack stack : ingreds) { - if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition) + if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition && !slot.getHasStack()) { GuiContainerManager.drawItem(stack.relx, stack.rely, stack.item); + drawHover(stack.relx, stack.rely); + } } - GuiContainerManager.setColouredItemRender(false); - GL11.glColor4f(1, 1, 1, 1); - GL11.glDisable(GL11.GL_BLEND); - GL11.glEnable(GL11.GL_LIGHTING); + GL11.glPopAttrib(); + } + + private static void drawHover(int x, int y) { + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + drawRect(x, y, 16, 16, 0x66555555); + GL11.glPopAttrib(); } final IStackPositioner positioner; diff --git a/src/main/java/codechicken/nei/api/INEIAutoFocusSearchEnable.java b/src/main/java/codechicken/nei/api/INEIAutoFocusSearchEnable.java deleted file mode 100644 index 3f0d6b91d..000000000 --- a/src/main/java/codechicken/nei/api/INEIAutoFocusSearchEnable.java +++ /dev/null @@ -1,8 +0,0 @@ -package codechicken.nei.api; - -/** - * Implement this interface on a GuiContainer to enable the autofocus search in NEI (if the autofocus option is enabled) - * without needing to add the classname to the config file . - */ -public interface INEIAutoFocusSearchEnable { -} diff --git a/src/main/java/codechicken/nei/api/IOverlayHandler.java b/src/main/java/codechicken/nei/api/IOverlayHandler.java index 68e574e16..bf7aebe3a 100644 --- a/src/main/java/codechicken/nei/api/IOverlayHandler.java +++ b/src/main/java/codechicken/nei/api/IOverlayHandler.java @@ -1,10 +1,45 @@ package codechicken.nei.api; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import codechicken.nei.PositionedStack; import codechicken.nei.recipe.IRecipeHandler; public interface IOverlayHandler { void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift); + + default List presenceOverlay(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex) { + final List itemPresenceSlots = new ArrayList<>(); + final List ingredients = recipe.getIngredientStacks(recipeIndex); + @SuppressWarnings("unchecked") + final List invStacks = ((List) firstGui.inventorySlots.inventorySlots).stream() + .filter( + s -> s != null && s.getStack() != null + && s.getStack().stackSize > 0 + && s.isItemValid(s.getStack()) + && s.canTakeStack(firstGui.mc.thePlayer)) + .map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new)); + + for (PositionedStack stack : ingredients) { + Optional used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is)) + .findFirst(); + + itemPresenceSlots.add(used.isPresent()); + + if (used.isPresent()) { + ItemStack is = used.get(); + is.stackSize -= 1; + } + } + + return itemPresenceSlots; + } } diff --git a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java index 59aaee36a..49eda2e76 100644 --- a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java +++ b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java @@ -44,7 +44,7 @@ public static boolean handleKeyEvent(ItemStack stackover) { return ItemPanels.bookmarkPanel.pullBookmarkItems(ItemPanels.bookmarkPanel.getHoveredGroupId(true), true); } - if (stackover == null && NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) { + if (stackover == null && NEIClientConfig.isKeyHashDown("gui.remove_recipe")) { final int groupId = ItemPanels.bookmarkPanel.getHoveredGroupId(true); if (groupId != -1) { diff --git a/src/main/java/codechicken/nei/config/preset/GuiPresetList.java b/src/main/java/codechicken/nei/config/preset/GuiPresetList.java index 972fdea0d..bf7b2c64f 100644 --- a/src/main/java/codechicken/nei/config/preset/GuiPresetList.java +++ b/src/main/java/codechicken/nei/config/preset/GuiPresetList.java @@ -6,6 +6,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.EnumChatFormatting; import org.lwjgl.opengl.GL11; @@ -25,25 +26,33 @@ public class GuiPresetList extends GuiOptionPane { protected final static int SLOT_HEIGHT = 24; protected final static int BUTTON_HEIGHT = 20; protected GuiCCButton createButton; + protected GuiCCButton toggleButton; protected int sortingItemIndex = -1; public GuiPresetList(Option opt) { this.opt = opt; this.createButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.new")) .setActionCommand("create"); + this.toggleButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.toggle")) + .setActionCommand("toggle"); } @Override public void initGui() { super.initGui(); + this.createButton.width = getStringWidth(this.createButton.text) + 15; this.createButton.x = width - this.createButton.width - 15; + + this.toggleButton.width = getStringWidth(this.toggleButton.text) + 15; + this.toggleButton.x = width - this.toggleButton.width - 15 - this.createButton.width - 10; } @Override public void addWidgets() { super.addWidgets(); add(this.createButton); + add(this.toggleButton); } @Override @@ -53,11 +62,14 @@ public void actionPerformed(String ident, Object... params) { if (ident.equals("create")) { cretePreset(); } + + if (ident.equals("toggle")) { + togglePreset(); + } } protected void mouseClicked(int x, int y, int button) { super.mouseClicked(x, y, button); - } @Override @@ -138,6 +150,16 @@ protected void cretePreset() { Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, -1)); } + protected void togglePreset() { + boolean enabled = !PresetsList.presets.stream().filter(g -> g.enabled).findAny().isPresent(); + + for (Preset preset : PresetsList.presets) { + preset.enabled = enabled; + } + + PresetsList.savePresets(); + } + protected void openPreset(int slot) { Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, slot)); } @@ -186,13 +208,16 @@ protected void drawSlot(Rectangle w, int slot, int x, int y, int mx, int my) { switch (preset.mode) { case HIDE: - modeName = NEIClientUtils.translate("presets.mode.hide.char"); + modeName = EnumChatFormatting.GOLD + NEIClientUtils.translate("presets.mode.hide.char") + + EnumChatFormatting.RESET; break; case REMOVE: - modeName = NEIClientUtils.translate("presets.mode.remove.char"); + modeName = EnumChatFormatting.RED + NEIClientUtils.translate("presets.mode.remove.char") + + EnumChatFormatting.RESET; break; case GROUP: - modeName = NEIClientUtils.translate("presets.mode.group.char"); + modeName = EnumChatFormatting.AQUA + NEIClientUtils.translate("presets.mode.group.char") + + EnumChatFormatting.RESET; break; default: modeName = "?"; @@ -215,7 +240,7 @@ protected void drawSlot(Rectangle w, int slot, int x, int y, int mx, int my) { LayoutManager.drawButtonBackground(option.x, option.y, option.w, option.h, true, optionState); GuiDraw.drawString("⋮⋮", option.x + 4, option.y + 5, optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0); GuiDraw.drawString( - NEIClientUtils.cropText(this.fontRendererObj, modeName + ": " + displayName, option.w - 16), + NEIClientUtils.cropText(this.fontRendererObj, modeName + " " + displayName, option.w - 16), option.x + 6 + 4, option.y + 6, optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0); diff --git a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java index cf0497337..afbf1412a 100644 --- a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java +++ b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java @@ -4,13 +4,16 @@ import static codechicken.lib.gui.GuiDraw.fontRenderer; import static codechicken.lib.gui.GuiDraw.getMousePosition; import static codechicken.lib.gui.GuiDraw.renderEngine; +import static codechicken.nei.NEIClientUtils.translate; import java.awt.Point; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.StringJoiner; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Pattern; @@ -23,6 +26,9 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.entity.RenderItem; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.client.resources.SimpleReloadableResourceManager; import net.minecraft.init.Blocks; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; @@ -35,6 +41,7 @@ import org.lwjgl.opengl.GL12; import codechicken.lib.gui.GuiDraw; +import codechicken.nei.ItemStackSet; import codechicken.nei.NEIClientConfig; import codechicken.nei.NEIClientUtils; import codechicken.nei.recipe.StackInfo; @@ -42,6 +49,14 @@ public class GuiContainerManager { + private static class ResourcePackReloaded implements IResourceManagerReloadListener { + + @Override + public void onResourceManagerReload(IResourceManager p_110549_1_) { + renderingErrorItems.clear(); + } + } + public GuiContainer window; public static RenderItem drawItems = new RenderItem(); @@ -273,58 +288,64 @@ public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer font private static int modelviewDepth = -1; private static final HashSet stackTraces = new HashSet<>(); + private static final ItemStackSet renderingErrorItems = new ItemStackSet(); public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer, boolean smallAmount, String stackSize) { enable3DRender(); // for lighting correction boolean glRescale = GL11.glGetBoolean(GL12.GL_RESCALE_NORMAL); - float zLevel = drawItems.zLevel += 100F; - float scale = smallAmount ? 0.5f : 1f; - try { - drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, i, j); - - if (stackSize == null) { - if (itemstack.stackSize > 1) { - stackSize = ReadableNumberConverter.INSTANCE.toWideReadableForm(itemstack.stackSize); - - if (stackSize.length() == 3) { - scale = 0.8f; - } else if (stackSize.length() == 4) { - scale = 0.6f; - } else if (stackSize.length() > 4) { - scale = 0.5f; + if (!renderingErrorItems.contains(itemstack)) { + float scale = smallAmount ? 0.5f : 1f; + + try { + drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, i, j); + + if (stackSize == null) { + if (itemstack.stackSize > 1) { + stackSize = ReadableNumberConverter.INSTANCE.toWideReadableForm(itemstack.stackSize); + + if (stackSize.length() == 3) { + scale = 0.8f; + } else if (stackSize.length() == 4) { + scale = 0.6f; + } else if (stackSize.length() > 4) { + scale = 0.5f; + } + + } else { + stackSize = ""; } - } else { - stackSize = ""; } - } + if (scale != 1f) { - if (scale != 1f) { + if (!stackSize.isEmpty()) { + drawBigStackSize(i, j, stackSize, scale); + } - if (!stackSize.isEmpty()) { - drawBigStackSize(i, j, stackSize, scale); + // stackSize = "". it needed for correct draw item with alpha and blend + drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, ""); + } else { + drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, stackSize); } - // stackSize = "". it needed for correct draw item with alpha and blend - drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, ""); - } else { - drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, stackSize); - } - - if (!checkMatrixStack()) throw new IllegalStateException("Modelview matrix stack too deep"); - if (Tessellator.instance.isDrawing) throw new IllegalStateException("Still drawing"); - } catch (Exception e) { - NEIClientUtils.reportErrorBuffered(e, stackTraces, itemstack); + if (!checkMatrixStack()) throw new IllegalStateException("Modelview matrix stack too deep"); + if (Tessellator.instance.isDrawing) throw new IllegalStateException("Still drawing"); + } catch (Exception e) { + NEIClientUtils.reportErrorBuffered(e, stackTraces, itemstack); - restoreMatrixStack(); - if (Tessellator.instance.isDrawing) Tessellator.instance.draw(); + restoreMatrixStack(); + if (Tessellator.instance.isDrawing) Tessellator.instance.draw(); - drawItems.zLevel = zLevel; + drawItems.zLevel = zLevel; + drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), i, j); + renderingErrorItems.add(itemstack); + } + } else { drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), i, j); } @@ -354,6 +375,14 @@ protected static void drawBigStackSize(int offsetX, int offsetY, String stackSiz enable3DRender(); } + public static void registerReloadResourceListener() { + if (Minecraft.getMinecraft().getResourceManager() instanceof SimpleReloadableResourceManager) { + SimpleReloadableResourceManager manager = (SimpleReloadableResourceManager) Minecraft.getMinecraft() + .getResourceManager(); + manager.registerReloadListener(new ResourcePackReloaded()); + } + } + public static void enableMatrixStackLogging() { modelviewDepth = GL11.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH); } @@ -517,6 +546,7 @@ public void renderObjects(int mousex, int mousey) { public void renderToolTips(int mousex, int mousey) { List tooltip = new LinkedList<>(); + Map hotkeys = new HashMap<>(); FontRenderer font = GuiDraw.fontRenderer; synchronized (instanceTooltipHandlers) { @@ -540,6 +570,36 @@ public void renderToolTips(int mousex, int mousey) { if (tooltip.size() > 0) tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title' + synchronized (instanceTooltipHandlers) { + for (IContainerTooltipHandler handler : instanceTooltipHandlers) { + hotkeys = handler.handleHotkeys(window, mousex, mousey, hotkeys); + } + } + + if (!hotkeys.isEmpty()) { + + if (!NEIClientUtils.altKey()) { + tooltip.add( + 1, + EnumChatFormatting.GRAY + translate( + "showHotkeys", + "" + EnumChatFormatting.GOLD + "ALT" + EnumChatFormatting.GRAY)); + } else { + List hotkeystips = new LinkedList<>(); + + for (String key : hotkeys.keySet()) { + hotkeystips.add(getHotkeyTip(key, hotkeys.get(key))); + } + + hotkeystips.sort((a, b) -> Integer.compare(a.indexOf(" - "), b.indexOf(" - "))); + hotkeystips.set( + hotkeystips.size() - 1, + hotkeystips.get(hotkeystips.size() - 1) + GuiDraw.TOOLTIP_LINESPACE); + + tooltip.addAll(1, hotkeystips); + } + } + drawPagedTooltip(font, mousex + 12, mousey - 12, tooltip); for (IContainerDrawHandler drawHandler : drawHandlers) { @@ -547,6 +607,10 @@ public void renderToolTips(int mousex, int mousey) { } } + private String getHotkeyTip(String key, String message) { + return EnumChatFormatting.GOLD + key + EnumChatFormatting.GRAY + " - " + message + EnumChatFormatting.RESET; + } + private static int tooltipPage; public static void drawPagedTooltip(FontRenderer font, int x, int y, List list) { @@ -590,6 +654,7 @@ public static List> splitTooltipByPage(List list) { } public static boolean shouldShowTooltip(GuiContainer window) { + if (window == null) return false; for (IContainerObjectHandler handler : objectHandlers) if (!handler.shouldShowTooltip(window)) return false; return window.mc.thePlayer.inventory.getItemStack() == null; @@ -675,25 +740,30 @@ public void drawSlotItem(Slot slot, ItemStack stack, int x, int y, String quanti boolean glRescale = GL11.glGetBoolean(GL12.GL_RESCALE_NORMAL); float zLevel = drawItems.zLevel += 100F; - try { - if (window instanceof IGuiSlotDraw) { - ((IGuiSlotDraw) window).drawSlotItem(slot, stack, x, y, quantity); - } else { + if (!renderingErrorItems.contains(stack)) { + try { + if (window instanceof IGuiSlotDraw) { + ((IGuiSlotDraw) window).drawSlotItem(slot, stack, x, y, quantity); + } else { - if (quantity == null) { - quantity = stack != null && stack.stackSize > 1 ? String.valueOf(stack.stackSize) : ""; - } + if (quantity == null) { + quantity = stack != null && stack.stackSize > 1 ? String.valueOf(stack.stackSize) : ""; + } - drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, stack, x, y); - drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, stack, x, y, quantity); - } - } catch (Exception e) { - NEIClientUtils.reportErrorBuffered(e, stackTraces, stack); + drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, stack, x, y); + drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, stack, x, y, quantity); + } + } catch (Exception e) { + NEIClientUtils.reportErrorBuffered(e, stackTraces, stack); - restoreMatrixStack(); - if (Tessellator.instance.isDrawing) Tessellator.instance.draw(); + restoreMatrixStack(); + if (Tessellator.instance.isDrawing) Tessellator.instance.draw(); - drawItems.zLevel = zLevel; + drawItems.zLevel = zLevel; + drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), x, y); + renderingErrorItems.add(stack); + } + } else { drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), x, y); } diff --git a/src/main/java/codechicken/nei/guihook/IContainerTooltipHandler.java b/src/main/java/codechicken/nei/guihook/IContainerTooltipHandler.java index d58f34610..05fb11263 100644 --- a/src/main/java/codechicken/nei/guihook/IContainerTooltipHandler.java +++ b/src/main/java/codechicken/nei/guihook/IContainerTooltipHandler.java @@ -1,6 +1,7 @@ package codechicken.nei.guihook; import java.util.List; +import java.util.Map; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; @@ -15,7 +16,7 @@ public interface IContainerTooltipHandler { * Use this to add tooltips for other objects. If the current tip has lines in it after this call, the item tootip * will not be handled. GuiContainerManager.shouldShowTooltip is not enforced here. It is recommended that you make * this check yourself - * + * * @param gui An instance of the currentscreen * @param mousex The x position of the mouse in pixels from left * @param mousey The y position of the mouse in pixels from top @@ -27,7 +28,7 @@ public interface IContainerTooltipHandler { /** * Use this for modifying the multiline display name of an item which may not necessarily be under the mouse. * GuiContainerManager.shouldShowTooltip is enforced here. - * + * * @param gui An instance of the currentscreen. If only general information about the item is wanted (Eg. * potion effects) then this may be null. * @param itemstack The ItemStack under the mouse @@ -39,7 +40,7 @@ public interface IContainerTooltipHandler { /** * Use this for modifying the tooltips of items that are under the mouse. GuiContainerManager.shouldShowTooltip is * enforced here. - * + * * @param gui An instance of the currentscreen * @param itemstack The ItemStack under the mouse * @param currenttip A list of strings, representing each line of the current tooltip as modified by other handlers @@ -47,4 +48,16 @@ public interface IContainerTooltipHandler { */ public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip); + + /** + * Use this to specify a list of hotkeys that will work when hovering over an element that is under the mouse + * pointer. + * + * @param gui An instance of the currentscreen + * @param mousex The x position of the mouse in pixels from left + * @param mousey The y position of the mouse in pixels from top + */ + default Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + return hotkeys; + } } diff --git a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java index 026f7eedb..b7adc22d4 100644 --- a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java @@ -41,7 +41,7 @@ public static GuiRecipe createRecipeGui(String outputId, boolean open, Object } else if ("recipeId".equals(outputId)) { recipeId = (BookmarkRecipeId) results[1]; } else { - recipeId = getCurrentRecipe(mc.currentScreen); + recipeId = getCurrentRecipeId(mc.currentScreen); } final ArrayList handlers = getCraftingHandlers(outputId, results); diff --git a/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java b/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java new file mode 100644 index 000000000..40cd5a648 --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java @@ -0,0 +1,331 @@ +package codechicken.nei.recipe; + +import static codechicken.nei.NEIClientUtils.translate; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.client.event.GuiScreenEvent; + +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.BookmarkPanel.BookmarkRecipe; +import codechicken.nei.GuiNEIButton; +import codechicken.nei.ItemPanels; +import codechicken.nei.ItemsTooltipLineHandler; +import codechicken.nei.LayoutManager; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.PositionedStack; +import codechicken.nei.api.IOverlayHandler; +import cpw.mods.fml.common.eventhandler.Cancelable; + +public class GuiOverlayButton extends GuiNEIButton { + + public static class UpdateOverlayButtonsEvent extends GuiScreenEvent { + + public List buttonList; + + public UpdateOverlayButtonsEvent(GuiRecipe gui, List buttonList) { + super(gui); + this.buttonList = new ArrayList<>(buttonList); + } + + @Cancelable + public static class Pre extends UpdateOverlayButtonsEvent { + + public int xOffset; + public int yOffset; + public int height; + public HandlerInfo handlerInfo; + + public Pre(GuiRecipe gui, int xOffset, int yOffset, int height, HandlerInfo handlerInfo) { + super(gui, new ArrayList<>()); + this.xOffset = xOffset; + this.yOffset = yOffset; + this.height = height; + this.handlerInfo = handlerInfo; + } + } + + public static class Post extends UpdateOverlayButtonsEvent { + + public Post(GuiRecipe gui, List buttonList) { + super(gui, buttonList); + } + } + } + + private final static int OVERLAY_BUTTON_ID_START = 4; + + public final GuiContainer firstGui; + public final IRecipeHandler handler; + public final int recipeIndex; + + protected ItemsTooltipLineHandler missedMaterialsTooltipLineHandler; + + protected final IOverlayHandler overlayHandler; + protected final List itemPresenceCache = new ArrayList<>(); + protected boolean requireShiftForOverlayRecipe = true; + protected boolean useOverlayRenderer = false; + protected boolean hasOverlay = false; + + public GuiOverlayButton(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex, int x, int y, int width, + int height) { + super(OVERLAY_BUTTON_ID_START + recipeIndex, x, y, width, height, "+"); + this.firstGui = firstGui != null && firstGui.inventorySlots != null ? firstGui : null; + this.handler = handler; + this.recipeIndex = recipeIndex; + this.hasOverlay = this.firstGui != null + && handler.hasOverlay(this.firstGui, this.firstGui.inventorySlots, recipeIndex); + this.useOverlayRenderer = this.hasOverlay && handler.getOverlayRenderer(firstGui, recipeIndex) != null; + this.overlayHandler = this.hasOverlay ? handler.getOverlayHandler(firstGui, recipeIndex) : null; + + setRequireShiftForOverlayRecipe(NEIClientConfig.requireShiftForOverlayRecipe()); + ingredientsOverlay(); + } + + public List handleTooltip(GuiRecipe gui, List currenttip) { + currenttip.add(translate("recipe.overlay")); + + if (!this.enabled && this.requireShiftForOverlayRecipe && this.overlayHandler == null) { + currenttip.set(currenttip.size() - 1, currenttip.get(currenttip.size() - 1) + GuiDraw.TOOLTIP_LINESPACE); + currenttip.add(EnumChatFormatting.RED + translate("recipe.overlay.mismatch") + EnumChatFormatting.RESET); + } else if (this.missedMaterialsTooltipLineHandler != null) { + + if ((!this.requireShiftForOverlayRecipe || NEIClientUtils.shiftKey()) && this.overlayHandler != null) { + this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.RED); + } else { + this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.GRAY); + } + + currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.missedMaterialsTooltipLineHandler)); + } + + return currenttip; + } + + public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + + if (this.requireShiftForOverlayRecipe) { + hotkeys.put(translate("recipe.overlay.fillCraftingGrid.key"), translate("recipe.overlay.fillCraftingGrid")); + } + + String keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("recipe.overlay.bookmark")); + } + + keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_recipe"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipe")); + } + + keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_count"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("recipe.overlay.bookmarkAmount")); + } + + keyName = NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.bookmark_recipe_count"), true); + if (keyName != null) { + hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipeAndAmount")); + } + + return hotkeys; + } + + @Override + public void mouseReleased(int mouseX, int mouseY) { + if (this.firstGui != null) { + this.firstGui.mc.displayGuiScreen(this.firstGui); + overlayRecipe(NEIClientUtils.shiftKey()); + } + } + + public void drawItemPresenceOverlay() { + final int presenceOverlay = NEIClientConfig.itemPresenceOverlay(); + final boolean highlightPresentItem = NEIClientConfig.isSlotHighlightPresent(); + final List ingredients = this.handler.getIngredientStacks(recipeIndex); + final List itemPresenceCache = ingredientsOverlay(); + + for (int j = 0; j < ingredients.size(); j++) { + PositionedStack stack = ingredients.get(j); + Boolean isPresent = j < itemPresenceCache.size() ? itemPresenceCache.get(j) : null; + + if (isPresent != null && (highlightPresentItem || !isPresent)) { + LayoutManager.drawItemPresenceOverlay(stack.relx, stack.rely, isPresent, presenceOverlay == 2); + } + } + } + + protected List ingredientsOverlay() { + List ingredients = this.handler.getIngredientStacks(recipeIndex); + + if (this.itemPresenceCache.size() != ingredients.size()) { + this.itemPresenceCache.clear(); + + if (this.overlayHandler != null) { + this.itemPresenceCache + .addAll(this.overlayHandler.presenceOverlay(this.firstGui, this.handler, this.recipeIndex)); + } else if (this.firstGui != null) { + this.itemPresenceCache.addAll(presenceOverlay(ingredients)); + } + + List items = new ArrayList<>(); + + for (int j = 0; j < ingredients.size(); j++) { + if (j >= this.itemPresenceCache.size() || !this.itemPresenceCache.get(j)) { + items.add(ingredients.get(j).item); + } + } + + if (!items.isEmpty()) { + this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler( + translate("recipe.overlay.missing"), + items, + true, + Integer.MAX_VALUE); + } else { + this.missedMaterialsTooltipLineHandler = null; + } + } + + return this.itemPresenceCache; + } + + public void setRequireShiftForOverlayRecipe(boolean require) { + this.requireShiftForOverlayRecipe = require; + this.enabled = this.hasOverlay && (this.requireShiftForOverlayRecipe || this.overlayHandler != null); + } + + public void setUseOverlayRenderer(boolean use) { + this.useOverlayRenderer = use; + } + + public boolean useOverlayRenderer() { + return this.useOverlayRenderer; + } + + public boolean canFillCraftingGrid() { + return this.missedMaterialsTooltipLineHandler == null; + } + + public boolean hasOverlay() { + return this.hasOverlay; + } + + private List presenceOverlay(List ingredients) { + final List itemPresenceSlots = new ArrayList<>(); + @SuppressWarnings("unchecked") + final List invStacks = ((List) this.firstGui.inventorySlots.inventorySlots).stream() + .filter( + s -> s != null && s.getStack() != null + && s.getStack().stackSize > 0 + && s.isItemValid(s.getStack()) + && s.canTakeStack(this.firstGui.mc.thePlayer)) + .map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new)); + + for (PositionedStack stack : ingredients) { + Optional used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is)) + .findFirst(); + + itemPresenceSlots.add(used.isPresent()); + + if (used.isPresent()) { + ItemStack is = used.get(); + is.stackSize -= 1; + } + } + + return itemPresenceSlots; + } + + public void overlayRecipe(boolean shift) { + if (!this.hasOverlay) return; + + if (!this.useOverlayRenderer || !this.requireShiftForOverlayRecipe || shift) { + if (this.overlayHandler != null) { + this.overlayHandler.overlayRecipe( + this.firstGui, + this.handler, + this.recipeIndex, + !this.requireShiftForOverlayRecipe || shift); + } + } else { + LayoutManager.overlayRenderer = this.handler.getOverlayRenderer(this.firstGui, this.recipeIndex); + } + + } + + public void lastKeyTyped(GuiRecipe gui, char keyChar, int keyID) { + + if (NEIClientConfig.isKeyHashDown("gui.bookmark")) { + saveRecipeInBookmark(false, false); + } else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) { + saveRecipeInBookmark(true, false); + } else if (NEIClientConfig.isKeyHashDown("gui.bookmark_count")) { + saveRecipeInBookmark(false, true); + } else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe_count")) { + saveRecipeInBookmark(true, true); + } + + } + + public void saveRecipeInBookmark(boolean saveIngredients, boolean saveStackSize) { + final HandlerInfo handlerInfo = GuiRecipeTab.getHandlerInfo(this.handler); + final List ingredients = this.handler.getIngredientStacks(this.recipeIndex); + final BookmarkRecipeId recipeId = new BookmarkRecipeId(handlerInfo.getHandlerName(), ingredients); + + if (!ItemPanels.bookmarkPanel.removeBookmarkRecipeId(recipeId)) { + BookmarkRecipe recipe = new BookmarkRecipe(); + recipe.handlerName = recipeId.handlerName; + recipe.recipeId = recipeId; + + if (saveIngredients) { + for (PositionedStack stack : ingredients) { + recipe.ingredients.add(stack.item); + } + } + + PositionedStack result = this.handler.getResultStack(this.recipeIndex); + + if (result != null) { + recipe.result.add(result.item); + } else { + for (PositionedStack stack : this.handler.getOtherStacks(this.recipeIndex)) { + recipe.result.add(stack.item); + } + } + + ItemPanels.bookmarkPanel.addRecipe(recipe, saveStackSize); + } + } + + public int getResultStackSize(ItemStack stackover) { + final List stacks = this.handler.getOtherStacks(this.recipeIndex); + int stackSize = stackover.stackSize; + + for (PositionedStack pStack : stacks) { + if (StackInfo.equalItemAndNBT(pStack.item, stackover, true)) { + stackSize += pStack.item.stackSize; + } + } + + return stackSize; + } + + public Rectangle4i bounds() { + return new Rectangle4i(this.xPosition, this.yPosition, this.width, this.height); + } + + public boolean contains(int mx, int my) { + return bounds().contains(mx, my); + } +} diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipe.java b/src/main/java/codechicken/nei/recipe/GuiRecipe.java index 50aac3d61..573bdc99a 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipe.java @@ -1,7 +1,6 @@ package codechicken.nei.recipe; -import static codechicken.lib.gui.GuiDraw.fontRenderer; - +import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; @@ -9,7 +8,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.Optional; +import java.util.Map; import java.util.regex.Matcher; import java.util.stream.Collectors; @@ -21,6 +20,8 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.common.MinecraftForge; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; @@ -28,6 +29,7 @@ import codechicken.lib.gui.GuiDraw; import codechicken.nei.Button; import codechicken.nei.GuiNEIButton; +import codechicken.nei.ItemsTooltipLineHandler; import codechicken.nei.LayoutManager; import codechicken.nei.NEICPH; import codechicken.nei.NEIClientConfig; @@ -51,6 +53,7 @@ import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.guihook.IGuiClientSide; import codechicken.nei.guihook.IGuiHandleMouseWheel; +import codechicken.nei.recipe.GuiOverlayButton.UpdateOverlayButtonsEvent; public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOverlay, IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler, INEIGuiHandler { @@ -72,6 +75,7 @@ public abstract class GuiRecipe extends GuiContainer i public static final List recipeFilterers = new LinkedList<>(); protected boolean limitToOneRecipe = false; + protected PermutationTooltipLineHandler permutationTooltipLineHandler; // Background image final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT) @@ -103,8 +107,7 @@ public abstract class GuiRecipe extends GuiContainer i private GuiButton nexttype; private GuiButton prevtype; - private final int OVERLAY_BUTTON_ID_START = 4; - private GuiButton[] overlayButtons; + private GuiOverlayButton[] overlayButtons = new GuiOverlayButton[0]; private final Rectangle area = new Rectangle(); private final GuiRecipeTabs recipeTabs; @@ -114,6 +117,29 @@ public abstract class GuiRecipe extends GuiContainer i private int yShift = 0; + protected static class PermutationTooltipLineHandler extends ItemsTooltipLineHandler { + + protected PositionedStack pStack = null; + + public PermutationTooltipLineHandler(PositionedStack pStack, List items) { + super(NEIClientUtils.translate("recipe.accepts"), items, false, 5); + this.pStack = pStack; + } + + public static PermutationTooltipLineHandler getInstance(PositionedStack pStack) { + final ItemFilter filter = TemplateRecipeHandler.getItemFilter(); + List items = Arrays.asList(pStack.items).stream().filter(filter::matches) + .collect(Collectors.toCollection(ArrayList::new)); + + if (items.isEmpty()) { + items = Arrays.asList(pStack.items); + } + + return new PermutationTooltipLineHandler(pStack, items); + } + + } + public static class ItemRecipeFilter implements IRecipeFilter { public ItemFilter filter; @@ -384,7 +410,7 @@ public void initGui() { super.initGui(); } else { this.guiLeft = (this.width - this.xSize) / 2; - this.ySize = this.getHeightAsWidget(); + this.ySize = this.getWidgetSize().height; this.mc = NEIClientUtils.mc(); this.fontRendererObj = mc.fontRenderer; ScaledResolution scaledresolution = new ScaledResolution( @@ -400,7 +426,7 @@ public void initGui() { if (handler == null) { setRecipePage(recipetype); } else { - initOverlayButtons(); + updateOverlayButtons(); } checkYShift(); @@ -408,15 +434,40 @@ public void initGui() { final int rightButtonX = guiLeft + xSize - borderPadding - buttonWidth; final int leftButtonX = guiLeft + borderPadding; - nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<"); - prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">"); + nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<") { + + @Override + public void mouseReleased(int mouseX, int mouseY) { + prevType(); + } + }; + prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">") { - nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<"); - prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">"); + @Override + public void mouseReleased(int mouseX, int mouseY) { + nextType(); + } + }; + + nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<") { + + @Override + public void mouseReleased(int mouseX, int mouseY) { + prevPage(); + } + }; + prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">") { + + @Override + public void mouseReleased(int mouseX, int mouseY) { + nextPage(); + } + }; toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 76, 10, 10).build(); - buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage)); + this.buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage)); + this.overlayButtons = new GuiOverlayButton[0]; if (currenthandlers.size() == 1) { nexttype.visible = false; @@ -428,34 +479,71 @@ public void initGui() { } @SuppressWarnings("unchecked") - private void initOverlayButtons() { - if (overlayButtons != null) { - buttonList.removeIf(Arrays.asList(overlayButtons)::contains); + private void updateOverlayButtons() { + final List indices = getRecipeIndices(); + + if (isDirtyOverlayButtons(indices)) { + this.buttonList.removeIf(Arrays.asList(this.overlayButtons)::contains); + + final int xOffset = (limitToOneRecipe ? 0 : guiLeft) + xSize - borderPadding; + final int yOffset = (limitToOneRecipe ? -buttonHeight : guiTop - 18) + getRecipePosition(0).y; + final int height = handlerInfo.getHeight() - yShift; + final UpdateOverlayButtonsEvent.Pre preEvent = new UpdateOverlayButtonsEvent.Pre( + this, + xOffset, + yOffset, + height, + handlerInfo); + List buttons = new ArrayList<>(); + + if (MinecraftForge.EVENT_BUS.post(preEvent)) { + buttons = preEvent.buttonList; + } else { + + for (int refIndex = 0; refIndex < indices.size(); refIndex++) { + final int recipeIndex = indices.get(refIndex); + + if (handler.original.getResultStack(recipeIndex) == null + && handler.original.getOtherStacks(recipeIndex).isEmpty()) { + continue; + } + + buttons.add( + new GuiOverlayButton( + firstGui, + handler.original, + recipeIndex, + xOffset - buttonWidth, + yOffset + height * (refIndex + 1), + buttonWidth, + buttonHeight)); + } + + if (this.equals(this.mc.currentScreen)) { + UpdateOverlayButtonsEvent.Post postEvent = new UpdateOverlayButtonsEvent.Post(this, buttons); + MinecraftForge.EVENT_BUS.post(postEvent); + buttons = postEvent.buttonList; + } + } + + this.overlayButtons = buttons.toArray(new GuiOverlayButton[buttons.size()]); + this.buttonList.addAll(buttons); } + } - final int recipesPerPage = getRecipesPerPage(); - overlayButtons = new GuiButton[recipesPerPage]; - final int xOffset = limitToOneRecipe ? ((xSize / 2) - 2) : (width / 2); - final int yOffset = limitToOneRecipe ? 0 : guiTop - 18; - final String overlayKeyName = NEIClientConfig - .getKeyName(NEIClientConfig.getKeyBinding("gui.overlay_use"), true); - for (int i = 0; i < recipesPerPage; i++) { - overlayButtons[i] = new GuiNEIButton( - OVERLAY_BUTTON_ID_START + i, - xOffset + 65, - yOffset + getRecipePosition(i).y + handlerInfo.getHeight(), - buttonWidth, - buttonHeight, - "?"); - if (overlayKeyName != null && limitToOneRecipe) { - overlayButtons[i].visible = true; - overlayButtons[i].displayString = overlayKeyName; - overlayButtons[i].width = fontRenderer.getStringWidth(overlayKeyName) + 6; - overlayButtons[i].xPosition = xOffset + 85 - overlayButtons[i].width; + private boolean isDirtyOverlayButtons(List indices) { + + if (this.overlayButtons.length == 0) { + return true; + } + + for (GuiOverlayButton button : this.overlayButtons) { + if (button.handler != handler.original || !indices.contains(button.recipeIndex)) { + return true; } } - Collections.addAll(buttonList, overlayButtons); - itemPresenceCacheRecipe = -1; + + return false; } public static IRecipeFilter getRecipeListFilter() { @@ -501,11 +589,10 @@ public void setRecipePage(int idx, int refIndex) { changePage(0); recipeTabs.calcPageNumber(); checkYShift(); - initOverlayButtons(); } public List getOverlayButtons() { - return Collections.unmodifiableList(Arrays.asList(overlayButtons)); + return Collections.unmodifiableList(Arrays.asList(this.overlayButtons)); } public int openTargetRecipe(BookmarkRecipeId recipeId) { @@ -649,6 +736,14 @@ public void keyTyped(char c, int i) { return; } } + + Point mouse = GuiDraw.getMousePosition(); + + for (GuiOverlayButton button : this.overlayButtons) { + if (button.contains(mouse.x, mouse.y)) { + button.lastKeyTyped(this, c, i); + } + } } if (i == mc.gameSettings.keyBindInventory.getKeyCode()) { @@ -734,44 +829,9 @@ public void mouseScrolled(int scroll) { } } - @Override - protected void actionPerformed(GuiButton guibutton) { - super.actionPerformed(guibutton); - switch (guibutton.id) { - case 0: - prevType(); - return; - case 1: - nextType(); - return; - case 2: - prevPage(); - return; - case 3: - nextPage(); - return; - } - - if (overlayButtons != null && guibutton.id >= OVERLAY_BUTTON_ID_START - && guibutton.id < OVERLAY_BUTTON_ID_START + overlayButtons.length) { - final List indices = getRecipeIndices(); - final int refIndex = guibutton.id - OVERLAY_BUTTON_ID_START; - - if (refIndex >= 0 && refIndex < indices.size()) { - mc.displayGuiScreen(firstGui); - overlayRecipe(indices.get(refIndex), NEIClientUtils.shiftKey()); - } - } - } - @Override public void updateScreen() { super.updateScreen(); - updateAsTooltip(); - } - - /** updateScreen() that's safe to call when this isn't the currently open GUI */ - public void updateAsTooltip() { handler.original.onUpdate(); refreshPage(); } @@ -783,6 +843,12 @@ public List handleTooltip(GuiContainer gui, int mousex, int mousey, List for (int recipeIndex : getRecipeIndices()) { currenttip = handler.original.handleTooltip(this, currenttip, recipeIndex); } + + for (GuiOverlayButton button : this.overlayButtons) { + if (button.contains(mousex, mousey)) { + currenttip = button.handleTooltip(this, currenttip); + } + } } recipeTabs.handleTooltip(mousex, mousey, currenttip); @@ -802,18 +868,67 @@ && new Rectangle(searchField.x + searchField.w, 15, 44, 16) } @Override - public List handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey, + public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip) { try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (int recipeIndex : getRecipeIndices()) { - currenttip = handler.original.handleItemTooltip(this, stack, currenttip, recipeIndex); + List indices = getRecipeIndices(); + + for (int recipeIndex : indices) { + currenttip = handler.original.handleItemTooltip(this, itemstack, currenttip, recipeIndex); } + + if (NEIClientConfig.showCycledIngredientsTooltip()) { + PositionedStack focused = null; + + for (int refIndex = 0; refIndex < indices.size(); refIndex++) { + final int recipeIndex = indices.get(refIndex); + + if (itemstack != null && focused == null) { + final List stacks = handler.original.getIngredientStacks(recipeIndex); + + for (PositionedStack pStack : stacks) { + if (isMouseOver(pStack, refIndex)) { + focused = pStack; + break; + } + } + } + } + + if (focused == null || focused.items.length <= 1) { + this.permutationTooltipLineHandler = null; + } else if (this.permutationTooltipLineHandler == null + || this.permutationTooltipLineHandler.pStack != focused) { + this.permutationTooltipLineHandler = PermutationTooltipLineHandler.getInstance(focused); + } + } else if (this.permutationTooltipLineHandler != null) { + this.permutationTooltipLineHandler = null; + } + + } + + if (this.permutationTooltipLineHandler != null) { + currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.permutationTooltipLineHandler)); } return currenttip; } + @Override + public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + + try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { + for (GuiOverlayButton button : this.overlayButtons) { + if (button.contains(mousex, mousey)) { + hotkeys = button.handleHotkeys(gui, mousex, mousey, hotkeys); + } + } + } + + return hotkeys; + } + @Override public List handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List currenttip) { return currenttip; @@ -835,19 +950,20 @@ protected void prevType() { setRecipePage(--recipetype); } - protected void overlayRecipe(int recipeIndex, final boolean shift) { + protected void overlayRecipe(int recipeIndex, boolean shift) { if (handler == null || !handler.original.hasOverlay(firstGui, firstGui.inventorySlots, recipeIndex)) { return; } - final boolean moveItems = shift || !NEIClientConfig.requireShiftForOverlayRecipe(); - final IRecipeOverlayRenderer renderer = handler.original.getOverlayRenderer(firstGui, recipeIndex); + final boolean requireShiftForOverlayRecipe = NEIClientConfig.requireShiftForOverlayRecipe(); final IOverlayHandler overlayHandler = handler.original.getOverlayHandler(firstGui, recipeIndex); + final IRecipeOverlayRenderer renderer = handler.original.getOverlayRenderer(firstGui, recipeIndex); - if (renderer == null || moveItems) { + if (renderer == null || !requireShiftForOverlayRecipe || shift) { if (overlayHandler != null) { - overlayHandler.overlayRecipe(firstGui, handler.original, recipeIndex, moveItems); + overlayHandler + .overlayRecipe(firstGui, handler.original, recipeIndex, !requireShiftForOverlayRecipe || shift); } } else { LayoutManager.overlayRenderer = renderer; @@ -865,7 +981,6 @@ protected void changePage(int shift) { } else { this.page = 0; } - } public void refreshPage() { @@ -895,22 +1010,7 @@ public void refreshPage() { nextpage.enabled = prevpage.enabled = multiplepages; - if (firstGui == null) { - for (GuiButton overlay : overlayButtons) { - overlay.visible = false; - } - } else { - final List indices = getRecipeIndices(); - for (int i = 0; i < overlayButtons.length; i++) { - if (i >= indices.size()) { - overlayButtons[i].visible = false; - } else { - overlayButtons[i].visible = handler.original - .hasOverlay(firstGui, firstGui.inventorySlots, indices.get(i)); - } - } - } - + updateOverlayButtons(); recipeTabs.refreshPage(); } @@ -952,39 +1052,11 @@ private void refreshSlots() { } } - private int itemPresenceCacheRecipe = -1; - private ArrayList itemPresenceCacheSlots; - - private void updateItemPresenceCache(int recipeIndex) { - if (itemPresenceCacheSlots == null) { - itemPresenceCacheSlots = new ArrayList<>(); - } - itemPresenceCacheRecipe = recipeIndex; - itemPresenceCacheSlots.clear(); - List ingredients = handler.original.getIngredientStacks(recipeIndex); - ArrayList invStacks = ((List) firstGui.inventorySlots.inventorySlots).stream() - .filter( - s -> s != null && s.getStack() != null - && s.getStack().stackSize > 0 - && s.isItemValid(s.getStack()) - && s.canTakeStack(mc.thePlayer)) - .map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new)); - for (PositionedStack stack : ingredients) { - Optional used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is)) - .findFirst(); - itemPresenceCacheSlots.add(used.isPresent()); - if (used.isPresent()) { - ItemStack is = used.get(); - is.stackSize -= 1; - } - } - } - @Override public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { GuiContainerManager.enable2DRender(); final int recipesPerPage = getRecipesPerPage(); - final int ySkip = limitToOneRecipe ? 25 : 0; + final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32; if (!limitToOneRecipe) { String s = handler.original.getRecipeName().trim(); @@ -1012,37 +1084,31 @@ public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { } - final int presenceOverlay = NEIClientConfig.itemPresenceOverlay(); - final boolean highlightPresentItem = NEIClientConfig.isSlotHighlightPresent(); - - GL11.glPushMatrix(); - GL11.glTranslatef(5, 32 - ySkip + yShift, 0); try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { List indices = getRecipeIndices(); + GL11.glPushMatrix(); + GL11.glTranslatef(5, ySkip + yShift, 0); + for (int refIndex = 0; refIndex < indices.size(); refIndex++) { int recipeIndex = indices.get(refIndex); handler.original.drawForeground(recipeIndex); - if (presenceOverlay > 0 && firstGui != null - && firstGui.inventorySlots != null - && (isMouseOverOverlayButton(refIndex) || limitToOneRecipe)) { - - List ingredients = handler.original.getIngredientStacks(recipeIndex); - - if (itemPresenceCacheRecipe != recipeIndex || itemPresenceCacheSlots == null - || itemPresenceCacheSlots.size() != ingredients.size()) { - updateItemPresenceCache(recipeIndex); - } + if (limitToOneRecipe) { + GuiOverlayButton overlayButton = Arrays.asList(this.overlayButtons).stream() + .filter(b -> b.recipeIndex == recipeIndex).findAny().orElse(null); - for (int j = 0; j < ingredients.size(); j++) { - PositionedStack stack = ingredients.get(j); - boolean isPresent = itemPresenceCacheSlots.get(j); + if (overlayButton != null && overlayButton.enabled) { + final String overlayKeyName = NEIClientConfig + .getKeyName(NEIClientConfig.getKeyBinding("gui.overlay_use"), true); - if (highlightPresentItem || !isPresent) { - LayoutManager - .drawItemPresenceOverlay(stack.relx, stack.rely, isPresent, presenceOverlay == 2); + if (overlayKeyName != null) { + fontRendererObj.drawStringWithShadow( + EnumChatFormatting.ITALIC + overlayKeyName, + xSize - borderPadding - fontRendererObj.getStringWidth(overlayKeyName) - 10, + handlerInfo.getHeight() - fontRendererObj.FONT_HEIGHT, + 0xffffff); } } } @@ -1050,14 +1116,29 @@ public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { GL11.glTranslatef(0, handlerInfo.getHeight(), 0); } + GL11.glPopMatrix(); + + GL11.glPushMatrix(); + GL11.glTranslatef(5, ySkip + yShift, 0); + + if (!limitToOneRecipe && NEIClientConfig.itemPresenceOverlay() > 0) { + for (GuiOverlayButton button : this.overlayButtons) { + if (button.contains(mouseX, mouseY)) { + GL11.glTranslatef(0, handlerInfo.getHeight() * indices.indexOf(button.recipeIndex), 0); + button.drawItemPresenceOverlay(); + break; + } + } + } + + GL11.glPopMatrix(); } - GL11.glPopMatrix(); } @Override public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { - final int ySkip = limitToOneRecipe ? 25 : 0; + final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32; GL11.glColor4f(1, 1, 1, 1); drawBackgroundTiled(guiLeft, guiTop); @@ -1086,7 +1167,7 @@ public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { } GL11.glPushMatrix(); - GL11.glTranslatef(guiLeft + 5, guiTop - ySkip + 32 + yShift, 0); + GL11.glTranslatef(guiLeft + 5, guiTop + ySkip + yShift, 0); try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { for (int recipeIndex : getRecipeIndices()) { @@ -1099,13 +1180,13 @@ public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { } private void drawBackgroundTiled(int j, int k) { + final int handlerHeight = getWidgetSize().height; + // Draw the top - final int ySkip = limitToOneRecipe ? 25 : 0; - final int handlerHeight = limitToOneRecipe ? getHeightAsWidget() : ySize; bgTop.draw(j, k + BG_TOP_Y); // Maybe Tile the middle - final int tiledHeight = handlerHeight - ySkip - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT; + final int tiledHeight = handlerHeight - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT; if (tiledHeight > 0) { final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT; @@ -1122,11 +1203,18 @@ private void drawBackgroundTiled(int j, int k) { } // Draw the bottom - bgBottom.draw(j, k + handlerHeight - ySkip - BG_BOTTOM_HEIGHT); + bgBottom.draw(j, k + handlerHeight - BG_BOTTOM_HEIGHT); } - public int getHeightAsWidget() { - return (handlerInfo == null) ? ySize : (handlerInfo.getHeight() + 56); + public Dimension getWidgetSize() { + + if (handlerInfo == null) { + return new Dimension(xSize, ySize); + } + + final int handlerHeight = limitToOneRecipe ? handlerInfo.getHeight() + yShift + BG_TOP_HEIGHT + BG_BOTTOM_HEIGHT + : ySize; + return new Dimension(xSize, handlerHeight); } @Override @@ -1148,19 +1236,6 @@ public boolean isMouseOver(PositionedStack stack, int refIndex) { return stackSlot == mouseoverSlot; } - private boolean isMouseOverOverlayButton(int buttonId) { - if (buttonId >= 0 && buttonId < overlayButtons.length) { - GuiButton button = overlayButtons[buttonId]; - Point mousePos = GuiDraw.getMousePosition(); - return button.visible && mousePos.x >= button.xPosition - && mousePos.y >= button.yPosition - && mousePos.x < button.xPosition + button.width - && mousePos.y < button.yPosition + button.height; - } else { - return false; - } - } - private int getRecipesPerPage() { return limitToOneRecipe ? 1 : getRecipesPerPage(handlerInfo); } @@ -1223,7 +1298,7 @@ public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) { return area.intersects(x, y, w, h); } - protected static BookmarkRecipeId getCurrentRecipe(GuiScreen gui) { + protected static BookmarkRecipeId getCurrentRecipeId(GuiScreen gui) { if (gui instanceof GuiRecipe && ((GuiRecipe) gui).handler.numRecipes() > 0) { final GuiRecipe gRecipe = (GuiRecipe) gui; diff --git a/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java b/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java index 46225a602..6294e7fe2 100644 --- a/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java @@ -27,7 +27,7 @@ public static boolean openRecipeGui(String inputId, Object... ingredients) { if (!handlers.isEmpty()) { final Minecraft mc = NEIClientUtils.mc(); - final BookmarkRecipeId recipeId = getCurrentRecipe(mc.currentScreen); + final BookmarkRecipeId recipeId = getCurrentRecipeId(mc.currentScreen); final GuiUsageRecipe gui = new GuiUsageRecipe(handlers); mc.displayGuiScreen(gui); diff --git a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java index 80f7aba9e..e702ec1ad 100644 --- a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java +++ b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java @@ -430,7 +430,7 @@ public TemplateRecipeHandler() { RecipeTransferRectHandler.registerRectsToGuis(getRecipeTransferRectGuis(), transferRects); } - protected static ItemFilter getItemFilter() { + public static ItemFilter getItemFilter() { return new AllMultiItemFilter( item -> !ItemInfo.hiddenItems.contains(item), PresetsList.getItemFilter(), @@ -767,20 +767,31 @@ public boolean mouseScrolled(GuiRecipe gui, int scroll, int recipe) { } private void shiftPermutationToRender(PositionedStack pStack, ItemStack stack, int scroll, ItemFilter filter) { + if (!pStack.containsWithNBT(stack)) return; - for (int index = 0; index < pStack.items.length; index++) { - if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[index], stack)) { - ArrayList filtered = getFilteredIngredientAlternatives(pStack, filter); + final List filtered = getFilteredIngredientAlternatives(pStack, filter); + int index = 0; - if (filtered.isEmpty()) { - pStack.setPermutationToRender((int) ((pStack.items.length + scroll + index) % pStack.items.length)); - } else { - pStack.setPermutationToRender( - filtered.get((int) ((filtered.size() + scroll + index) % filtered.size()))); + if (filtered.isEmpty()) { + + for (int i = 0; i < pStack.items.length; i++) { + if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[i], stack)) { + index = i; + break; } + } - break; + pStack.setPermutationToRender((int) ((pStack.items.length - scroll + index) % pStack.items.length)); + } else { + + for (int i = 0; i < filtered.size(); i++) { + if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[filtered.get(i)], stack)) { + index = i; + break; + } } + + pStack.setPermutationToRender(filtered.get((int) ((filtered.size() - scroll + index) % filtered.size()))); } } diff --git a/src/main/resources/assets/nei/lang/cs_CZ.lang b/src/main/resources/assets/nei/lang/cs_CZ.lang index 7af91a0e7..b57a3125c 100644 --- a/src/main/resources/assets/nei/lang/cs_CZ.lang +++ b/src/main/resources/assets/nei/lang/cs_CZ.lang @@ -88,9 +88,9 @@ nei.options.inventory.widgetsenabled.false=NEI zakázáno nei.options.inventory.cheatmode.0=Mód receptů nei.options.inventory.cheatmode.1=Užitný mód nei.options.inventory.cheatmode.2=Cheatovací mód -nei.options.inventory.profileRecipes=Profilové recepty -nei.options.inventory.profileRecipes.true=Povoleny -nei.options.inventory.profileRecipes.false=Nepovoleny +nei.options.inventory.guirecipe.profile=Profilové recepty +nei.options.inventory.guirecipe.profile.true=Povoleny +nei.options.inventory.guirecipe.profile.false=Nepovoleny nei.options.inventory.itemsort=Řazení panelu předmětů nei.options.inventory.itemIDs=IDčka předmětů nei.options.inventory.itemIDs.0=Skryté diff --git a/src/main/resources/assets/nei/lang/de_DE.lang b/src/main/resources/assets/nei/lang/de_DE.lang index 1fde46f1b..5df1b8fbc 100644 --- a/src/main/resources/assets/nei/lang/de_DE.lang +++ b/src/main/resources/assets/nei/lang/de_DE.lang @@ -92,9 +92,9 @@ nei.options.inventory.widgetsenabled.false=NEI Deaktiviert nei.options.inventory.cheatmode.0=Rezeptmodus nei.options.inventory.cheatmode.1=Mehrzweckmodus nei.options.inventory.cheatmode.2=Cheat-Modus -nei.options.inventory.profileRecipes=Profil-Rezepte -nei.options.inventory.profileRecipes.true=Wahr -nei.options.inventory.profileRecipes.false=Falsch +nei.options.inventory.guirecipe.profile=Profil-Rezepte +nei.options.inventory.guirecipe.profile.true=Wahr +nei.options.inventory.guirecipe.profile.false=Falsch nei.options.inventory.itemsort=Item-Panel-Sortierung nei.options.inventory.itemIDs=Item-IDs nei.options.inventory.itemIDs.0=Versteckt diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index 0c561f116..cdd722f61 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -5,15 +5,35 @@ nei.save=Save nei.key.ctrl=CTRL # Mac Command Key nei.key.ctrl.mac=CMD +nei.showHotkeys=Hold %s for hotkeys nei.bookmark.toggle=Bookmarks nei.bookmark.toggle.tip=Toggle visibility of the Bookmark Panel -nei.bookmark.viewmode.toggle.tip=Toggle Bookmark View Mode nei.bookmark.pullBookmarkedItems.tip=Pull all bookmarked items from storage to inventory +nei.bookmark.group=Bookmarks Group +nei.bookmark.group.include_group=Create/Include Group +nei.bookmark.group.include_group.key=LMB + Drag +nei.bookmark.group.exclude_group=Remove/Exclude Group +nei.bookmark.group.exclude_group.key=RMB + Drag +nei.bookmark.group.toggle_mode=Toggle Group Mode +nei.bookmark.group.toggle_mode.key=Left Click +nei.bookmark.group.toggle_crafting_chain=Toggle Crafting Chain +nei.bookmark.group.toggle_crafting_chain.key=Right Click +nei.bookmark.group.sorting=Sorting +nei.bookmark.group.sorting.key=SHIFT + LMB + Drag +nei.bookmark.group.remove_recipe=Remove Group +nei.bookmark.group.pull_items=Pull all Items +nei.bookmark.group.pull_items_ingredients=Pull all Ingredients +nei.bookmark.crafting_chain=Crafting Chain +nei.bookmark.crafting_chain.input=Ingredients +nei.bookmark.crafting_chain.output=Results +nei.bookmark.crafting_chain.remainder=Remainders + nei.itempanel.quantity.default=One stack nei.itempanel.loading=Loading Item List... -nei.itempanel.collapsed.button.tip=Toggle Groups +nei.itempanel.deleteItem=Delete Item +nei.itempanel.collapsed.button.tip=Collapse/Expand All Collapsible Items nei.itempanel.collapsed.hint.expand=Alt-Click to expand (%d items) nei.itempanel.collapsed.hint.collapse=Alt-Click to collapse (%d items) @@ -113,6 +133,7 @@ nei.options.keys.gui.next_machine=Next Machine nei.options.keys.gui.prev_machine=Prev Machine nei.options.keys.gui.search=Focus Search Bar nei.options.keys.gui.bookmark=Add Bookmark +nei.options.keys.gui.remove_recipe=Remove Group from Bookmarks nei.options.keys.gui.bookmark_recipe=Add Bookmark with Recipe nei.options.keys.gui.bookmark_count=Add Bookmark with Count nei.options.keys.gui.bookmark_pull_items=Pull all Bookmarked Items @@ -127,6 +148,10 @@ nei.options.keys.gui.getnextsearch=Next Search nei.options.keys.gui.next_tooltip=Next Tooltip nei.options.keys.gui.copy_name=Copy Item Name nei.options.keys.gui.copy_oredict=Copy Item OreDictionary +nei.options.keys.gui.itemzoom_toggle=Toggle Item Zoom +nei.options.keys.gui.itemzoom_hold=Hold to Display Item Zoom +nei.options.keys.gui.itemzoom_zoom_in=Item Zoom In +nei.options.keys.gui.itemzoom_zoom_out=Item Zoom Out nei.options.keys.world=World nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay nei.options.keys.world.moboverlay=Mob Spawn Overlay @@ -141,42 +166,50 @@ nei.options.keys.world.creative=Gamemode nei.options.keys.world.creative.tip=Cycle Gamemode nei.options.inventory=Inventory -nei.options.inventory.worldSpecificBookmarks=World Specific Bookmarks -nei.options.inventory.worldSpecificBookmarks.true=Yes -nei.options.inventory.worldSpecificBookmarks.false=No +nei.options.inventory.bookmarks=Bookmarks Panel +nei.options.inventory.bookmarks.enabled=Bookmarks Panel Visibility +nei.options.inventory.bookmarks.enabled.true=Visible +nei.options.inventory.bookmarks.enabled.false=Hidden +nei.options.inventory.bookmarks.animation=REI Style Animation in Bookmarks +nei.options.inventory.bookmarks.animation.true=Yes +nei.options.inventory.bookmarks.animation.false=No +nei.options.inventory.bookmarks.craftingChainDir=Crafting Chain Info Direction +nei.options.inventory.bookmarks.craftingChainDir.0=Input First +nei.options.inventory.bookmarks.craftingChainDir.1=Output First +nei.options.inventory.bookmarks.recipeTooltipsMode=Show recipe tooltips in Bookmarks +nei.options.inventory.bookmarks.recipeTooltipsMode.0=None +nei.options.inventory.bookmarks.recipeTooltipsMode.1=In Horizontal View +nei.options.inventory.bookmarks.recipeTooltipsMode.2=In Vertical View +nei.options.inventory.bookmarks.recipeTooltipsMode.3=Always +nei.options.inventory.bookmarks.showRecipeMarker=Show Recipe Marker +nei.options.inventory.bookmarks.showRecipeMarker.true=Yes +nei.options.inventory.bookmarks.showRecipeMarker.false=No +nei.options.inventory.bookmarks.ignorePotionOverlap=Ignore overlap with potion effect HUD +nei.options.inventory.bookmarks.ignorePotionOverlap.true=Yes +nei.options.inventory.bookmarks.ignorePotionOverlap.false=No +nei.options.inventory.bookmarks.worldSpecific=World Specific Bookmarks +nei.options.inventory.bookmarks.worldSpecific.true=Yes +nei.options.inventory.bookmarks.worldSpecific.false=No nei.options.inventory.worldSpecificPresets=World Specific Presets nei.options.inventory.worldSpecificPresets.true=Yes nei.options.inventory.worldSpecificPresets.false=No -nei.options.inventory.bookmarksEnabled=Bookmarks Panel Visibility -nei.options.inventory.bookmarksEnabled.true=Visible -nei.options.inventory.bookmarksEnabled.false=Hidden -nei.options.inventory.jei_style_tabs=JEI Style Tabs -nei.options.inventory.jei_style_tabs.true=Yes -nei.options.inventory.jei_style_tabs.false=No [Weirdo] -nei.options.inventory.itemPresenceOverlay=Item Overlay on ?-Hover -nei.options.inventory.itemPresenceOverlay.0=None -nei.options.inventory.itemPresenceOverlay.1=Icon -nei.options.inventory.itemPresenceOverlay.2=Background -nei.options.inventory.slotHighlightPresent=Highlight Present Item -nei.options.inventory.slotHighlightPresent.true=Yes -nei.options.inventory.slotHighlightPresent.false=No -nei.options.inventory.jei_style_recipe_catalyst=JEI Style Recipe Catalysts -nei.options.inventory.jei_style_recipe_catalyst.true=Yes -nei.options.inventory.jei_style_recipe_catalyst.false=No -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=Save Current Recipe in Bookmarks -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=Enabled -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=Disabled -nei.options.inventory.recipeTooltipsMode=Show recipe tooltips in Bookmarks -nei.options.inventory.recipeTooltipsMode.0=None -nei.options.inventory.recipeTooltipsMode.1=In Horizontal View -nei.options.inventory.recipeTooltipsMode.2=In Vertical View -nei.options.inventory.recipeTooltipsMode.3=Always -nei.options.inventory.bookmarksAnimationEnabled=REI Style Animation in Bookmarks -nei.options.inventory.bookmarksAnimationEnabled.true=Yes -nei.options.inventory.bookmarksAnimationEnabled.false=No -nei.options.inventory.showRecipeMarker=Show Recipe Marker -nei.options.inventory.showRecipeMarker.true=Yes -nei.options.inventory.showRecipeMarker.false=No +nei.options.inventory.guirecipe=Recipes GUI +nei.options.inventory.guirecipe.jeiStyleTabs=JEI Style Tabs +nei.options.inventory.guirecipe.jeiStyleTabs.true=Yes +nei.options.inventory.guirecipe.jeiStyleTabs.false=No [Weirdo] +nei.options.inventory.guirecipe.itemPresenceOverlay=Item Overlay on ?-Hover +nei.options.inventory.guirecipe.itemPresenceOverlay.0=None +nei.options.inventory.guirecipe.itemPresenceOverlay.1=Icon +nei.options.inventory.guirecipe.itemPresenceOverlay.2=Background +nei.options.inventory.guirecipe.slotHighlightPresent=Highlight Present Item +nei.options.inventory.guirecipe.slotHighlightPresent.true=Yes +nei.options.inventory.guirecipe.slotHighlightPresent.false=No +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst=JEI Style Recipe Catalysts +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst.true=Yes +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst.false=No +nei.options.inventory.guirecipe.cycledIngredientsTooltip=Cycled Ingredients Tooltip +nei.options.inventory.guirecipe.cycledIngredientsTooltip.true=Show +nei.options.inventory.guirecipe.cycledIngredientsTooltip.false=Nide nei.options.inventory.showItemQuantityWidget=Show Item Quantity Widget nei.options.inventory.showItemQuantityWidget.true=Yes nei.options.inventory.showItemQuantityWidget.false=No @@ -185,8 +218,9 @@ nei.options.inventory.search.widgetPosition=Widget Position nei.options.inventory.search.widgetPosition.true=Center nei.options.inventory.search.widgetPosition.false=Right nei.options.inventory.search.widgetAutofocus=Autofocus -nei.options.inventory.search.widgetAutofocus.true=Yes -nei.options.inventory.search.widgetAutofocus.false=No +nei.options.inventory.search.widgetAutofocus.0=No +nei.options.inventory.search.widgetAutofocus.1=Yes +nei.options.inventory.search.widgetAutofocus.2=Extended nei.options.inventory.search.patternMode=Search Mode nei.options.inventory.search.patternMode.0=Plain nei.options.inventory.search.patternMode.1=Extended @@ -214,32 +248,26 @@ nei.options.inventory.search.subsetsSearchMode=Item Subsets Search nei.options.inventory.search.subsetsSearchMode.0=Always nei.options.inventory.search.subsetsSearchMode.1=Prefix: %s nei.options.inventory.search.subsetsSearchMode.2=Never -nei.options.inventory.firstInvCloseClosesInSearch=First Inventory Close Closes in Search -nei.options.inventory.firstInvCloseClosesInSearch.true=Yes -nei.options.inventory.firstInvCloseClosesInSearch.false=No -nei.options.inventory.creative_tab_style=Creative or JEI tab style -nei.options.inventory.creative_tab_style.true=Creative -nei.options.inventory.creative_tab_style.false=JEI -nei.options.inventory.ignore_potion_overlap=Ignore overlap with potion effect HUD -nei.options.inventory.ignore_potion_overlap.true=Yes -nei.options.inventory.ignore_potion_overlap.false=No +nei.options.inventory.guirecipe.creativeTabStyle=Creative or JEI tab style +nei.options.inventory.guirecipe.creativeTabStyle.true=Creative +nei.options.inventory.guirecipe.creativeTabStyle.false=JEI nei.options.inventory.optimize_gui_overlap_computation=Optimize computation for GUI overlap nei.options.inventory.optimize_gui_overlap_computation.true=Yes nei.options.inventory.optimize_gui_overlap_computation.false=No -nei.options.inventory.jei_style_cycled_ingredients=JEI styled cycled ingredients -nei.options.inventory.jei_style_cycled_ingredients.true=Yes -nei.options.inventory.jei_style_cycled_ingredients.false=No -nei.options.inventory.shift_overlay_recipe=Require holding shift to move items when overlaying recipe -nei.options.inventory.shift_overlay_recipe.true=Yes -nei.options.inventory.shift_overlay_recipe.false=No +nei.options.inventory.guirecipe.jeiStyleCycledIngredients=JEI styled cycled ingredients +nei.options.inventory.guirecipe.jeiStyleCycledIngredients.true=Yes +nei.options.inventory.guirecipe.jeiStyleCycledIngredients.false=No +nei.options.inventory.guirecipe.shiftOverlayRecipe=Require holding shift to move items when overlaying recipe +nei.options.inventory.guirecipe.shiftOverlayRecipe.true=Yes +nei.options.inventory.guirecipe.shiftOverlayRecipe.false=No nei.options.inventory.widgetsenabled.true=NEI Enabled nei.options.inventory.widgetsenabled.false=NEI Disabled nei.options.inventory.cheatmode.0=Recipe Mode nei.options.inventory.cheatmode.1=Utility Mode nei.options.inventory.cheatmode.2=Cheat Mode -nei.options.inventory.profileRecipes=Profile Recipes -nei.options.inventory.profileRecipes.true=True -nei.options.inventory.profileRecipes.false=False +nei.options.inventory.guirecipe.profile=Profile Recipes +nei.options.inventory.guirecipe.profile.true=True +nei.options.inventory.guirecipe.profile.false=False nei.options.inventory.itemsort=Item Panel Sorting nei.options.inventory.itemIDs=Item IDs nei.options.inventory.itemIDs.0=Hidden @@ -274,6 +302,9 @@ nei.options.inventory.collapsibleItems=Collapsible Items nei.options.inventory.collapsibleItems.enabled=Collapsible Items nei.options.inventory.collapsibleItems.enabled.true=Enabled nei.options.inventory.collapsibleItems.enabled.false=Disabled +nei.options.inventory.collapsibleItems.customName=Show Custom Group Name +nei.options.inventory.collapsibleItems.customName.true=Yes +nei.options.inventory.collapsibleItems.customName.false=No nei.options.inventory.collapsibleItems.expandedColor=Expanded Color nei.options.inventory.collapsibleItems.collapsedColor=Collapsed Color nei.options.inventory.collapsibleItems.reloadLabel=Reload @@ -287,6 +318,27 @@ nei.options.inventory.history.useRows=Rows nei.options.inventory.history.splittingMode=Splitting Mode nei.options.inventory.history.splittingMode.0=Background nei.options.inventory.history.splittingMode.1=Dotted Line +nei.options.inventory.itemzoom=Item Zoom Panel +nei.options.inventory.itemzoom.enabled=Item Zoom Panel Visibility +nei.options.inventory.itemzoom.enabled.true=Enabled +nei.options.inventory.itemzoom.enabled.false=Disabled +nei.options.inventory.itemzoom.neiOnly=NEI Overlays Only +nei.options.inventory.itemzoom.neiOnly.true=Enabled +nei.options.inventory.itemzoom.neiOnly.false=Disabled +nei.options.inventory.itemzoom.neiOnly.tip=Zoom items only from the JEI ingredient and bookmark list overlays. +nei.options.inventory.itemzoom.onlySolid=Show Only Solid Items +nei.options.inventory.itemzoom.onlySolid.true=Enabled +nei.options.inventory.itemzoom.onlySolid.false=Disabled +nei.options.inventory.itemzoom.helpText=Display Help Text +nei.options.inventory.itemzoom.helpText.true=Enabled +nei.options.inventory.itemzoom.helpText.false=Disabled +nei.options.inventory.itemzoom.helpText.tip=Display name "Item Zoom" and the hotkey to toggle this mod below the zoomed item. +nei.options.inventory.itemzoom.zoom=Zoom Amount +nei.options.inventory.itemzoom.zoom.tip=Set lower amount to make the item zoom less. +nei.options.inventory.itemzoom.showName=Display Name +nei.options.inventory.itemzoom.showName.true=Show +nei.options.inventory.itemzoom.showName.false=Hide +nei.options.inventory.itemzoom.nameColor=Display Name Color nei.options.command=Commands nei.options.command.creative=Gamemode @@ -366,6 +418,17 @@ nei.recipe.profiler.crafting=Crafting Profiling nei.recipe.profiler.usage=Usage Profiling nei.recipe.concurrent.usage=Concurrent Usage - Total nei.recipe.concurrent.crafting=Concurrent Crafting - Total +nei.recipe.accepts=Accepts following + +nei.recipe.overlay=Recipe Overlay +nei.recipe.overlay.missing=Missing following +nei.recipe.overlay.mismatch=Mismatch Crafting Grid +nei.recipe.overlay.fillCraftingGrid=Fill Crafting Grid +nei.recipe.overlay.fillCraftingGrid.key=SHIFT + Click +nei.recipe.overlay.bookmark=Save to Bookmark +nei.recipe.overlay.bookmarkRecipe=Save with Recipe +nei.recipe.overlay.bookmarkAmount=Save with Amount +nei.recipe.overlay.bookmarkRecipeAndAmount=Save with Recipe & Amount nei.itemsort.minecraft=Minecraft nei.itemsort.minecraft.tip=Sorts items from vanilla minecraft first @@ -405,6 +468,7 @@ nei.subsets.Items.Weapons.Swords=Swords nei.subsets.Mod=Mod nei.presets.new=New Preset +nei.presets.toggle=Toggle Presets nei.presets.create=Create Preset nei.presets.update=Update Preset nei.presets.enabled=Enabled @@ -421,3 +485,5 @@ nei.presets.mode.remove.char=R nei.presets.mode.group=Group nei.presets.mode.group.tip=Create custom collapsible items group nei.presets.mode.group.char=G + +nei.itemzoom.toggle=Use %s to toggle Item Zoom diff --git a/src/main/resources/assets/nei/lang/et_EE.lang b/src/main/resources/assets/nei/lang/et_EE.lang index 230724469..7e087913a 100644 --- a/src/main/resources/assets/nei/lang/et_EE.lang +++ b/src/main/resources/assets/nei/lang/et_EE.lang @@ -91,9 +91,9 @@ nei.options.inventory.widgetsenabled.false=NEI keelatud nei.options.inventory.cheatmode.0=Retsepti mood nei.options.inventory.cheatmode.1=Utiliidi mood nei.options.inventory.cheatmode.2=Petmis mood -nei.options.inventory.profileRecipes=Profileeri retsepte -nei.options.inventory.profileRecipes.true=Tõene -nei.options.inventory.profileRecipes.false=Väär +nei.options.inventory.guirecipe.profile=Profileeri retsepte +nei.options.inventory.guirecipe.profile.true=Tõene +nei.options.inventory.guirecipe.profile.false=Väär nei.options.inventory.itemsort=Item Panel Sorting nei.options.inventory.itemIDs=Asja ID-d nei.options.inventory.itemIDs.0=Peidetud diff --git a/src/main/resources/assets/nei/lang/fr_FR.lang b/src/main/resources/assets/nei/lang/fr_FR.lang index cd9750664..a7f77a726 100644 --- a/src/main/resources/assets/nei/lang/fr_FR.lang +++ b/src/main/resources/assets/nei/lang/fr_FR.lang @@ -89,9 +89,9 @@ nei.options.inventory.widgetsenabled.false=NEI désactivé nei.options.inventory.cheatmode.0=Mode recette nei.options.inventory.cheatmode.1=Mode utilitaire nei.options.inventory.cheatmode.2=Mode triche -nei.options.inventory.profileRecipes=Profil Recettes -nei.options.inventory.profileRecipes.true=Vrai -nei.options.inventory.profileRecipes.false=Faux +nei.options.inventory.guirecipe.profile=Profil Recettes +nei.options.inventory.guirecipe.profile.true=Vrai +nei.options.inventory.guirecipe.profile.false=Faux nei.options.inventory.itemsort=Tri du panneau d'élément nei.options.inventory.itemIDs=Objet IDs nei.options.inventory.itemIDs.0=Cachés diff --git a/src/main/resources/assets/nei/lang/it_IT.lang b/src/main/resources/assets/nei/lang/it_IT.lang index 856d1e1b3..717236929 100644 --- a/src/main/resources/assets/nei/lang/it_IT.lang +++ b/src/main/resources/assets/nei/lang/it_IT.lang @@ -92,9 +92,9 @@ nei.options.inventory.widgetsenabled.false=NEI Disattivato nei.options.inventory.cheatmode.0=Modalità ricette nei.options.inventory.cheatmode.1=Modalità utilità nei.options.inventory.cheatmode.2=Modalità cheat -nei.options.inventory.profileRecipes=Ricerca profilo -nei.options.inventory.profileRecipes.true=Vero -nei.options.inventory.profileRecipes.false=Falso +nei.options.inventory.guirecipe.profile=Ricerca profilo +nei.options.inventory.guirecipe.profile.true=Vero +nei.options.inventory.guirecipe.profile.false=Falso nei.options.inventory.itemsort=Pannello ordine degli oggetti nei.options.inventory.itemIDs=ID degli oggetti nei.options.inventory.itemIDs.0=Nascosti diff --git a/src/main/resources/assets/nei/lang/ko_KR.lang b/src/main/resources/assets/nei/lang/ko_KR.lang index 7fa8eb0d1..ace32e571 100644 --- a/src/main/resources/assets/nei/lang/ko_KR.lang +++ b/src/main/resources/assets/nei/lang/ko_KR.lang @@ -87,9 +87,9 @@ nei.options.inventory.widgetsenabled.false=NEI 비활성화 nei.options.inventory.cheatmode.0=레시피모드 nei.options.inventory.cheatmode.1=유틸리티모드 nei.options.inventory.cheatmode.2=치트모드 -nei.options.inventory.profileRecipes=프로파일 레시피 -nei.options.inventory.profileRecipes.true=설정 -nei.options.inventory.profileRecipes.false=비설정 +nei.options.inventory.guirecipe.profile=프로파일 레시피 +nei.options.inventory.guirecipe.profile.true=설정 +nei.options.inventory.guirecipe.profile.false=비설정 nei.options.inventory.itemsort=아이템 정렬 nei.options.inventory.itemIDs=아이템 ID nei.options.inventory.itemIDs.0= 숨기기 diff --git a/src/main/resources/assets/nei/lang/pl_PL.lang b/src/main/resources/assets/nei/lang/pl_PL.lang index b0d0c1a42..4c1bfbaf2 100644 --- a/src/main/resources/assets/nei/lang/pl_PL.lang +++ b/src/main/resources/assets/nei/lang/pl_PL.lang @@ -89,9 +89,9 @@ nei.options.inventory.cheatmode.0=Tryb recept nei.options.inventory.cheatmode.1=Tryb użytku nei.options.inventory.cheatmode.2=Tryb oszukiwania -nei.options.inventory.profileRecipes=Profiluj recepty -nei.options.inventory.profileRecipes.true=Tak -nei.options.inventory.profileRecipes.false=Nie +nei.options.inventory.guirecipe.profile=Profiluj recepty +nei.options.inventory.guirecipe.profile.true=Tak +nei.options.inventory.guirecipe.profile.false=Nie nei.options.inventory.itemsort=Sortowanie paelu przedmiotów nei.options.inventory.itemIDs=ID przedmiotów nei.options.inventory.itemIDs.0=Ukryte diff --git a/src/main/resources/assets/nei/lang/pt_BR.lang b/src/main/resources/assets/nei/lang/pt_BR.lang index 90d88bccf..e03baf6d4 100644 --- a/src/main/resources/assets/nei/lang/pt_BR.lang +++ b/src/main/resources/assets/nei/lang/pt_BR.lang @@ -90,8 +90,8 @@ nei.options.inventory.cheatmode.1=Modo Utilidade nei.options.inventory.cheatmode.2=Modo Cheat nei.options.inventory.profileRecAtivaripes=Perfilar Receitas -nei.options.inventory.profileRecipes.true=Verdadeiro -nei.options.inventory.profileRecipes.false=Falso +nei.options.inventory.guirecipe.profile.true=Verdadeiro +nei.options.inventory.guirecipe.profile.false=Falso nei.options.inventory.itemsort=Ordenamento do Painel de Itens nei.options.inventory.itemIDs=IDs de Itens nei.options.inventory.itemIDs.0=Escondido diff --git a/src/main/resources/assets/nei/lang/sk_SK.lang b/src/main/resources/assets/nei/lang/sk_SK.lang index f94c73398..1ac07628f 100644 --- a/src/main/resources/assets/nei/lang/sk_SK.lang +++ b/src/main/resources/assets/nei/lang/sk_SK.lang @@ -89,9 +89,9 @@ nei.options.inventory.cheatmode.0=Mód Receptov nei.options.inventory.cheatmode.1=Úžitkový mód nei.options.inventory.cheatmode.2=Čítovací mód -nei.options.inventory.profileRecipes=Profilovanie receptov -nei.options.inventory.profileRecipes.true=Áno -nei.options.inventory.profileRecipes.false=Nie +nei.options.inventory.guirecipe.profile=Profilovanie receptov +nei.options.inventory.guirecipe.profile.true=Áno +nei.options.inventory.guirecipe.profile.false=Nie nei.options.inventory.itemsort=Zoradenie itemov nei.options.inventory.itemIDs=ID itemov nei.options.inventory.itemIDs.0=Skryté diff --git a/src/main/resources/assets/nei/lang/tr_TR.lang b/src/main/resources/assets/nei/lang/tr_TR.lang index 8651693b4..cc344086d 100644 --- a/src/main/resources/assets/nei/lang/tr_TR.lang +++ b/src/main/resources/assets/nei/lang/tr_TR.lang @@ -89,9 +89,9 @@ nei.options.inventory.cheatmode.0=Tarif modu nei.options.inventory.cheatmode.1=Yardımcı mod nei.options.inventory.cheatmode.2=Hileli mod -nei.options.inventory.profileRecipes=Profil tarifleri -nei.options.inventory.profileRecipes.true=Yazı -nei.options.inventory.profileRecipes.false=Şekil +nei.options.inventory.guirecipe.profile=Profil tarifleri +nei.options.inventory.guirecipe.profile.true=Yazı +nei.options.inventory.guirecipe.profile.false=Şekil nei.options.inventory.itemsort=Item Panel Sıralaması nei.options.inventory.itemIDs=Item IDleri nei.options.inventory.itemIDs.0=Gizli diff --git a/src/main/resources/assets/nei/lang/zh_CN.lang b/src/main/resources/assets/nei/lang/zh_CN.lang index 8b5d54380..4e6d21d8f 100644 --- a/src/main/resources/assets/nei/lang/zh_CN.lang +++ b/src/main/resources/assets/nei/lang/zh_CN.lang @@ -128,47 +128,44 @@ nei.options.keys.world.creative=游戏模式 nei.options.keys.world.creative.tip=循环游戏模式 nei.options.inventory=物品栏 -nei.options.inventory.worldSpecificBookmarks=书签存储位置 -nei.options.inventory.worldSpecificBookmarks.true=存档内 -nei.options.inventory.worldSpecificBookmarks.false=全局 +nei.options.inventory.bookmarks.worldSpecific=书签存储位置 +nei.options.inventory.bookmarks.worldSpecific.true=存档内 +nei.options.inventory.bookmarks.worldSpecific.false=全局 nei.options.inventory.worldSpecificPresets=预设存储位置 nei.options.inventory.worldSpecificPresets.true=存档内 nei.options.inventory.worldSpecificPresets.false=全局 -nei.options.inventory.bookmarksEnabled=显示/隐藏书签页 -nei.options.inventory.bookmarksEnabled.true=显示 -nei.options.inventory.bookmarksEnabled.false=隐藏 -nei.options.inventory.jei_style_tabs=JEI标签页 -nei.options.inventory.jei_style_tabs.true=是 -nei.options.inventory.jei_style_tabs.false=否 [不会吧] -nei.options.inventory.jei_style_recipe_catalyst=JEI风格可执行合成表机器显示[测试中] -nei.options.inventory.jei_style_recipe_catalyst.true=是 -nei.options.inventory.jei_style_recipe_catalyst.false=否 -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=保存书签中的当前合成表 -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=启用 -nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=禁用 -nei.options.inventory.bookmarksAnimationEnabled=REI风格书签动画 -nei.options.inventory.bookmarksAnimationEnabled.true=是 -nei.options.inventory.bookmarksAnimationEnabled.false=否 -nei.options.inventory.showRecipeMarker=在书签栏显示合成产物标记 -nei.options.inventory.showRecipeMarker.true=是 -nei.options.inventory.showRecipeMarker.false=否 +nei.options.inventory.bookmarks.enabled=显示/隐藏书签页 +nei.options.inventory.bookmarks.enabled.true=显示 +nei.options.inventory.bookmarks.enabled.false=隐藏 +nei.options.inventory.guirecipe.jeiStyleTabs=JEI标签页 +nei.options.inventory.guirecipe.jeiStyleTabs.true=是 +nei.options.inventory.guirecipe.jeiStyleTabs.false=否 [不会吧] +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst=JEI风格可执行合成表机器显示[测试中] +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst.true=是 +nei.options.inventory.guirecipe.jeiStyleRecipeCatalyst.false=否 +nei.options.inventory.bookmarks.animation=REI风格书签动画 +nei.options.inventory.bookmarks.animation.true=是 +nei.options.inventory.bookmarks.animation.false=否 +nei.options.inventory.bookmarks.showRecipeMarker=在书签栏显示合成产物标记 +nei.options.inventory.bookmarks.showRecipeMarker.true=是 +nei.options.inventory.bookmarks.showRecipeMarker.false=否 nei.options.inventory.showItemQuantityWidget=显示物品数量栏(右下角) nei.options.inventory.showItemQuantityWidget.true=是 nei.options.inventory.showItemQuantityWidget.false=否 -nei.options.inventory.creative_tab_style=创造模式/JEI标签页 -nei.options.inventory.creative_tab_style.true=创造模式 -nei.options.inventory.creative_tab_style.false=JEI -nei.options.inventory.ignore_potion_overlap=忽略书签与药水效果重叠 -nei.options.inventory.ignore_potion_overlap.true=忽略 -nei.options.inventory.ignore_potion_overlap.false=规避 +nei.options.inventory.guirecipe.creativeTabStyle=创造模式/JEI标签页 +nei.options.inventory.guirecipe.creativeTabStyle.true=创造模式 +nei.options.inventory.guirecipe.creativeTabStyle.false=JEI +nei.options.inventory.bookmarks.ignorePotionOverlap=忽略书签与药水效果重叠 +nei.options.inventory.bookmarks.ignorePotionOverlap.true=忽略 +nei.options.inventory.bookmarks.ignorePotionOverlap.false=规避 nei.options.inventory.widgetsenabled.true=激活NEI nei.options.inventory.widgetsenabled.false=禁用NEI nei.options.inventory.cheatmode.0=合成模式 nei.options.inventory.cheatmode.1=实用模式 nei.options.inventory.cheatmode.2=作弊模式 -nei.options.inventory.profileRecipes=合成查阅性能分析 -nei.options.inventory.profileRecipes.true=开启 -nei.options.inventory.profileRecipes.false=关闭 +nei.options.inventory.guirecipe.profile=合成查阅性能分析 +nei.options.inventory.guirecipe.profile.true=开启 +nei.options.inventory.guirecipe.profile.false=关闭 nei.options.inventory.itemsort=物品面板排序方式 nei.options.inventory.itemIDs=物品ID nei.options.inventory.itemIDs.0=隐藏 diff --git a/src/main/resources/assets/nei/lang/zh_TW.lang b/src/main/resources/assets/nei/lang/zh_TW.lang index 725cfc083..9a89921ba 100644 --- a/src/main/resources/assets/nei/lang/zh_TW.lang +++ b/src/main/resources/assets/nei/lang/zh_TW.lang @@ -88,9 +88,9 @@ nei.options.inventory.cheatmode.0=合成模式 nei.options.inventory.cheatmode.1=實用模式 nei.options.inventory.cheatmode.2=作弊模式 -nei.options.inventory.profileRecipes=合成查詢 -nei.options.inventory.profileRecipes.true=開啟 -nei.options.inventory.profileRecipes.false=關閉 +nei.options.inventory.guirecipe.profile=合成查詢 +nei.options.inventory.guirecipe.profile.true=開啟 +nei.options.inventory.guirecipe.profile.false=關閉 nei.options.inventory.itemsort=物品面板排序方式 nei.options.inventory.itemIDs=物品ID nei.options.inventory.itemIDs.0=隱藏