From 5dde7cad8b051cab2009981d720ac0d832be52f4 Mon Sep 17 00:00:00 2001 From: slprime <31038811+slprime@users.noreply.github.com> Date: Sun, 2 Jan 2022 23:30:54 +0200 Subject: [PATCH] NEI Bookmarks improvements (#188) * Add bookmarks sets; save items count in bookmarks; change counts in bookmarks; save ingredients in bookmarks; fill fluidcontainers in bookmarks; * change fill container controls * fix fill container * rollback public variables Co-authored-by: Serghei Borovetchi --- .../java/codechicken/nei/BookmarkPanel.java | 700 +++++++++++++++--- src/main/java/codechicken/nei/ItemPanel.java | 539 +++++++------- src/main/java/codechicken/nei/ItemsGrid.java | 315 ++++++++ .../codechicken/nei/LayoutStyleMinecraft.java | 2 +- .../java/codechicken/nei/NEIClientUtils.java | 6 +- .../java/codechicken/nei/SearchField.java | 5 +- .../nei/api/IStackStringifyHandler.java | 5 +- .../nei/config/GuiItemIconDumper.java | 18 +- .../codechicken/nei/config/HandlerDumper.java | 4 - .../nei/config/ItemPanelDumper.java | 6 +- .../nei/guihook/GuiContainerManager.java | 38 +- .../nei/recipe/BookmarkRecipeId.java | 87 ++- .../codechicken/nei/recipe/GuiRecipe.java | 42 +- .../codechicken/nei/recipe/GuiRecipeTab.java | 18 + .../codechicken/nei/recipe/RecipeInfo.java | 2 - .../nei/recipe/RecipeItemInputHandler.java | 16 +- .../codechicken/nei/recipe/StackInfo.java | 43 +- .../nei/recipe/StackStringifyHandler.java | 69 -- .../DefaultStackStringifyHandler.java | 56 ++ .../GTFluidStackStringifyHandler.java | 84 +++ 20 files changed, 1523 insertions(+), 532 deletions(-) create mode 100644 src/main/java/codechicken/nei/ItemsGrid.java delete mode 100644 src/main/java/codechicken/nei/recipe/StackStringifyHandler.java create mode 100644 src/main/java/codechicken/nei/recipe/stackinfo/DefaultStackStringifyHandler.java create mode 100644 src/main/java/codechicken/nei/recipe/stackinfo/GTFluidStackStringifyHandler.java diff --git a/src/main/java/codechicken/nei/BookmarkPanel.java b/src/main/java/codechicken/nei/BookmarkPanel.java index 5b4f8148e..f8805f13a 100644 --- a/src/main/java/codechicken/nei/BookmarkPanel.java +++ b/src/main/java/codechicken/nei/BookmarkPanel.java @@ -1,123 +1,454 @@ package codechicken.nei; +import codechicken.lib.vec.Rectangle4i; import codechicken.nei.util.NBTJson; import codechicken.nei.recipe.StackInfo; import codechicken.nei.recipe.BookmarkRecipeId; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.ItemPanel.ItemPanelSlot; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.JsonObject; -import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; -import cpw.mods.fml.common.registry.GameData; import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import org.apache.commons.io.IOUtils; +import static codechicken.lib.gui.GuiDraw.getMousePosition; +import static codechicken.lib.gui.GuiDraw.drawRect; + +import java.awt.Point; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.HashMap; -/* - * TODO: - * 1) Bookmark button to toggle visibility - */ -public class BookmarkPanel extends ItemPanel { +public class BookmarkPanel extends ItemPanel +{ - protected ArrayList _recipes = new ArrayList<>(); protected boolean bookmarksIsLoaded = false; public int sortedStackIndex = -1; + public int sortedNamespaceIndex = -1; + + + public Button namespacePrev; + public Button namespaceNext; + public Label namespaceLabel; + + + protected ArrayList namespaces = new ArrayList<>(); + public int activeNamespaceIndex = 0; + + + protected static class BookmarkStackMeta + { + public int factor; + public BookmarkRecipeId recipeId; + public boolean ingredient = false; + + + public BookmarkStackMeta(BookmarkRecipeId recipeId, int count, boolean ingredient) + { + this.recipeId = recipeId; + this.factor = count; + this.ingredient = ingredient; + } - public void init() { - super.init(); } - @Override - protected void setItems() { - realItems = _items; + protected static class BookmarkGrid extends ItemsGrid + { + protected List metadata = new ArrayList<>(); + + public int indexOf(ItemStack stackA, BookmarkRecipeId recipeId) + { + final boolean useNBT = NEIClientConfig.useNBTInBookmarks(); + + for (int idx = 0; idx < realItems.size(); idx++) { + final BookmarkStackMeta meta = getMetadata(idx); + if ((recipeId == null && meta.recipeId == null || recipeId != null && meta.recipeId != null && recipeId.equals(meta.recipeId)) && StackInfo.equalItemAndNBT(stackA, realItems.get(idx), useNBT)) { + return idx; + } + } + + return -1; + } + + public BookmarkStackMeta getMetadata(int idx) + { + return metadata.get(idx); + } + + public void addItem(ItemStack stackA, BookmarkStackMeta meta) + { + realItems.add(stackA); + metadata.add(meta); + needRefresh = true; + } + + public void replaceItem(int idx, ItemStack stack) + { + realItems.set(idx, stack); + } + + public void removeRecipe(int idx, boolean removeFullRecipe) + { + final BookmarkStackMeta meta = getMetadata(idx); + + if (removeFullRecipe && meta.recipeId != null) { + removeRecipe(meta.recipeId); + } else { + removeItem(idx); + } + + } + + public void removeRecipe(BookmarkRecipeId recipeIdA) + { + BookmarkRecipeId recipeIdB; + + for (int slotIndex = metadata.size() - 1; slotIndex >= 0; slotIndex--) { + recipeIdB = getRecipeId(slotIndex); + + if (recipeIdB != null && recipeIdA.equals(recipeIdB)) { + removeItem(slotIndex); + } + + } + + } + + protected boolean removeItem(int idx) + { + realItems.remove(idx); + metadata.remove(idx); + needRefresh = true; + return true; + } + + public BookmarkRecipeId getRecipeId(int idx) + { + return getMetadata(idx).recipeId; + } + + public BookmarkRecipeId findRecipeId(ItemStack stackA) + { + final boolean useNBT = NEIClientConfig.useNBTInBookmarks(); + + for (int idx = 0; idx < realItems.size(); idx++) { + if (StackInfo.equalItemAndNBT(stackA, getItem(idx), useNBT)) { + return getRecipeId(idx); + } + } + + return null; + } + + public void moveItem(int src, int dst) + { + realItems.add(dst, realItems.remove(src)); + metadata.add(dst, metadata.remove(src)); + needRefresh = true; + } + + @Override + protected void drawItem(Rectangle4i rect, int idx, ItemPanelSlot focus) + { + + if (LayoutManager.bookmarkPanel.sortedNamespaceIndex == LayoutManager.bookmarkPanel.activeNamespaceIndex && LayoutManager.bookmarkPanel.sortedStackIndex == idx) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + } else { + + if (focus != null) { + + if (focus.slotIndex == idx) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + } else if ( + LayoutManager.bookmarkPanel.sortedStackIndex == -1 && //disabled when sorting + NEIClientUtils.shiftKey() && //show only with shift key + getRecipeId(focus.slotIndex) != null && getRecipeId(idx) != null && getRecipeId(focus.slotIndex).equals(getRecipeId(idx))//is some recipeId + ) { + drawRect(rect.x, rect.y, rect.w, rect.h, getMetadata(idx).ingredient? 0x88b3b300: 0x88009933);//highlight recipe + } + + } + + GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, getItem(idx), true); + } + + } + } - public String getLabelText() { - return super.getLabelText() + " [" + realItems.size() + "]"; + + public BookmarkPanel() + { + grid = new BookmarkGrid(); } - public void addOrRemoveItem(ItemStack item) + public void init() { - addOrRemoveItem(item, null); + super.init(); + + namespaceLabel = new Label("1", true); + + namespacePrev = new Button("Prev") + { + public boolean onButtonPress(boolean rightclick) + { + + if (rightclick) { + return false; + } + + return prevNamespace(); + } + + @Override + public String getRenderLabel() + { + return "<"; + } + }; + + namespaceNext = new Button("Next") + { + public boolean onButtonPress(boolean rightclick) + { + if (rightclick) { + return false; + } + + return nextNamespace(); + } + + @Override + public String getRenderLabel() + { + return ">"; + } + }; + + namespaces.add(new BookmarkGrid()); + grid = namespaces.get(activeNamespaceIndex); } - public void addOrRemoveItem(ItemStack item, BookmarkRecipeId recipeId) + @Override + public String getLabelText() + { + return super.getLabelText() + " [" + grid.size() + "]"; + } + + public void addOrRemoveItem(ItemStack stackA) + { + addOrRemoveItem(stackA, "", null); + } + + public void addOrRemoveItem(ItemStack stackover, String handlerName, List ingredients) { loadBookmarksIfNeeded(); - ItemStack normalized = StackInfo.normalize(item); + final Point mousePos = getMousePosition(); + final ItemPanelSlot slot = getSlotMouseOver(mousePos.x, mousePos.y); + final boolean addFullRecipe = NEIClientUtils.shiftKey(); + final BookmarkGrid BGrid = (BookmarkGrid) grid; + + if (slot != null && StackInfo.equalItemAndNBT(slot.item, stackover, true)) { + BGrid.removeRecipe(slot.slotIndex, addFullRecipe); + } else { + final boolean saveStackSize = NEIClientUtils.controlKey(); + final NBTTagCompound nbTagA = StackInfo.itemStackToNBT(stackover, saveStackSize); + final ItemStack normalizedA = StackInfo.loadFromNBT(nbTagA); + BookmarkRecipeId recipeId = null; + + if (NEIClientConfig.saveCurrentRecipeInBookmarksEnabled() && handlerName != "" && ingredients != null && ingredients.size() > 0) { + recipeId = new BookmarkRecipeId(handlerName, ingredients); + } + + final int idx = BGrid.indexOf(normalizedA, recipeId); + + if (idx != -1) { + BGrid.removeRecipe(idx, addFullRecipe); + } else { + + if (addFullRecipe && handlerName != "" && ingredients != null) { + final Map unique = new HashMap<>(); + final ArrayList sorted = new ArrayList<>(); + + BGrid.removeRecipe(recipeId); + + for (PositionedStack stack : ingredients) { + final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack.item, saveStackSize); + + if (nbTag.getInteger("Count") > 0) { + + if (unique.get(nbTag) == null) { + unique.put(nbTag, 1); + sorted.add(nbTag); + } else if (saveStackSize) { + unique.put(nbTag, unique.get(nbTag) + 1); + } + + } + + } + + for (NBTTagCompound nbTag : sorted) { + nbTag.setInteger("Count", nbTag.getInteger("Count") * unique.get(nbTag)); + BGrid.addItem(StackInfo.loadFromNBT(nbTag), new BookmarkStackMeta(recipeId, nbTag.getInteger("Count"), true)); + } + + } + + BGrid.addItem(normalizedA, new BookmarkStackMeta(recipeId, nbTagA.getInteger("Count"), false)); + } + - if (normalized != null && !remove(normalized)) { - _items.add(normalized); - _recipes.add(recipeId); } saveBookmarks(); } - public BookmarkRecipeId getBookmarkRecipeId(ItemStack item) + public BookmarkRecipeId getBookmarkRecipeId(ItemStack stackA) { - int index = findStackIndex(item); - if (index >= 0) { - return _recipes.get(index); + final Point mousePos = getMousePosition(); + final ItemPanelSlot slot = getSlotMouseOver(mousePos.x, mousePos.y); + + if (slot != null && StackInfo.equalItemAndNBT(slot.item, stackA, true)) { + return ((BookmarkGrid) grid).getRecipeId(slot.slotIndex); } - return null; + BookmarkRecipeId recipeId = ((BookmarkGrid) grid).findRecipeId(stackA); + + if (recipeId == null) { + + for (int idx = 0; idx < namespaces.size() && recipeId == null; idx++) { + if (idx == activeNamespaceIndex) continue; + recipeId = namespaces.get(idx).findRecipeId(stackA); + } + + } + + return recipeId; + } + + protected String getNamespaceLabelText(boolean shortFormat) + { + String activePage = String.valueOf(activeNamespaceIndex + 1); + + return shortFormat? activePage: (activePage + "/" + fixCountOfNamespaces()); } - public int findStackIndex(ItemStack stackA) + protected int fixCountOfNamespaces() { - boolean useNBT = NEIClientConfig.useNBTInBookmarks(); - int i = 0; - for (ItemStack stackB : _items) { + if (namespaces.get(namespaces.size() - 1).size() > 0) { + namespaces.add(new BookmarkGrid()); + } else if (activeNamespaceIndex == namespaces.size() - 2 && grid.size() == 0) { + namespaces.remove(namespaces.size() - 1); + } - if (StackInfo.equalItemAndNBT(stackA, stackB, useNBT)) { - return i; - } + return namespaces.size(); + } + + protected boolean removeEmptyNamespaces() + { + + if (activeNamespaceIndex != namespaces.size() - 1 && grid.size() == 0) { + namespaces.remove(activeNamespaceIndex); + grid = namespaces.get(activeNamespaceIndex); + return true; + } + + return false; + } - i++; + protected boolean prevNamespace() + { + if (!bookmarksIsLoaded) { + return false; } + + fixCountOfNamespaces(); + removeEmptyNamespaces(); - return -1; + if (activeNamespaceIndex == 0) { + activeNamespaceIndex = namespaces.size() - 1; + } else { + activeNamespaceIndex --; + } + + grid = namespaces.get(activeNamespaceIndex); + + return true; } + protected boolean nextNamespace() + { + if (!bookmarksIsLoaded) { + return false; + } + + if (removeEmptyNamespaces()) { + return true; + } + + if (activeNamespaceIndex == fixCountOfNamespaces() - 1) { + activeNamespaceIndex = 0; + } else { + activeNamespaceIndex ++; + } + + grid = namespaces.get(activeNamespaceIndex); + + return true; + } + + public void saveBookmarks() { - List strings = new ArrayList<>(); - int index = 0; - for (ItemStack item: _items) { - try { - final NBTTagCompound nbTag = StackInfo.itemStackToNBT(item); + ArrayList strings = new ArrayList<>(); - if (nbTag != null) { - JsonObject row = new JsonObject(); - BookmarkRecipeId recipeId = _recipes.get(index); + for (int grpIdx = 0; grpIdx < namespaces.size() - 1; grpIdx++) { + final BookmarkGrid grid = namespaces.get(grpIdx); - row.add("item", NBTJson.toJsonObject(nbTag)); + if (grpIdx > 0) { + strings.add("");//namespace separator; ignore first namespace + } - if (recipeId != null) { - row.add("recipeId", recipeId.toJsonObject()); + for (int idx = 0; idx < grid.size(); idx++) { + + try { + final NBTTagCompound nbTag = StackInfo.itemStackToNBT(grid.getItem(idx)); + + if (nbTag != null) { + JsonObject row = new JsonObject(); + BookmarkStackMeta meta = grid.getMetadata(idx); + + row.add("item", NBTJson.toJsonObject(nbTag)); + row.add("factor", new JsonPrimitive(meta.factor)); + row.add("ingredient", new JsonPrimitive(meta.ingredient)); + + if (meta.recipeId != null) { + row.add("recipeId", meta.recipeId.toJsonObject()); + } + + strings.add(NBTJson.toJson(row)); } - - strings.add(NBTJson.toJson(row)); + + } catch (JsonSyntaxException e) { + NEIClientConfig.logger.error("Failed to stringify bookmarked ItemStack to json string"); } - - } catch (JsonSyntaxException e) { - NEIClientConfig.logger.error("Failed to stringify bookmarked ItemStack to json string"); + } - index++; } File file = NEIClientConfig.bookmarkFile; @@ -134,7 +465,7 @@ public void saveBookmarks() public void loadBookmarksIfNeeded() { - if (bookmarksIsLoaded == true) { + if (bookmarksIsLoaded) { return; } @@ -144,6 +475,7 @@ public void loadBookmarksIfNeeded() if (file == null || !file.exists()) { return; } + List itemStrings; try (FileReader reader = new FileReader(file)) { NEIClientConfig.logger.info("Loading bookmarks from file {}", file); @@ -153,17 +485,33 @@ public void loadBookmarksIfNeeded() return; } - _items.clear(); - JsonParser parser = new JsonParser(); + namespaces.clear(); + namespaces.add(new BookmarkGrid()); + activeNamespaceIndex = 0; + + final JsonParser parser = new JsonParser(); + for (String itemStr: itemStrings) { try { + + if (itemStr.isEmpty()) { + + if (namespaces.get(activeNamespaceIndex).size() > 0) { + //do not create empty namespaces + namespaces.add(new BookmarkGrid()); + activeNamespaceIndex++; + } + + continue; + } + JsonObject jsonObject = parser.parse(itemStr).getAsJsonObject(); - NBTTagCompound itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject); BookmarkRecipeId recipeId = null; + NBTTagCompound itemStackNBT; if (jsonObject.get("item") != null) { itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject.get("item")); - } else {//old format + } else {// old format itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject); } @@ -173,9 +521,13 @@ public void loadBookmarksIfNeeded() ItemStack itemStack = StackInfo.loadFromNBT(itemStackNBT); + if (itemStack != null) { - _items.add(itemStack); - _recipes.add(recipeId); + namespaces.get(activeNamespaceIndex).addItem(itemStack, new BookmarkStackMeta( + recipeId, + jsonObject.has("factor")? jsonObject.get("factor").getAsInt(): 1, + jsonObject.has("ingredient")? jsonObject.get("ingredient").getAsBoolean(): false + )); } else { NEIClientConfig.logger.warn("Failed to load bookmarked ItemStack from json string, the item no longer exists:\n{}", itemStr); } @@ -184,67 +536,87 @@ public void loadBookmarksIfNeeded() NEIClientConfig.logger.error("Failed to load bookmarked ItemStack from json string:\n{}", itemStr); } } + + if (namespaces.get(activeNamespaceIndex).size() == 0) { + activeNamespaceIndex = Math.max(activeNamespaceIndex - 1, 0); + } + + grid = namespaces.get(activeNamespaceIndex); } + @Override - public void draw(int mousex, int mousey) + public void resize(GuiContainer gui) { loadBookmarksIfNeeded(); - super.draw(mousex, mousey); - } + super.resize(gui); - private boolean remove(ItemStack item) - { - int index = findStackIndex(item); + final int buttonHeight = 16; + final int buttonWidth = 16; + + final int buttonTop = gui.height - buttonHeight - 2; + final int leftBorder = LayoutManager.bookmarksButton.x + LayoutManager.bookmarksButton.w + 2; + final int rightBorder = x + w; + final int center = leftBorder + (rightBorder - leftBorder) / 2; + int labelWidth = 2; + + namespacePrev.h = namespaceNext.h = buttonHeight; + namespacePrev.w = namespaceNext.w = buttonWidth; + namespacePrev.y = namespaceNext.y = buttonTop; - if (index >= 0) { - _items.remove(index); - _recipes.remove(index); - return true; + + if (rightBorder - leftBorder >= 70) { + labelWidth = 36; + namespaceLabel.text = getNamespaceLabelText(false); + } else { + labelWidth = 18; + namespaceLabel.text = getNamespaceLabelText(true); } - return false; + namespaceLabel.y = buttonTop + 5; + namespaceLabel.x = center; + + namespacePrev.x = center - labelWidth / 2 - 2 - namespacePrev.w; + namespaceNext.x = center + labelWidth / 2 + 2; + } @Override - public int getX(GuiContainer gui) { - return 5; + public void setVisible() + { + super.setVisible(); + + LayoutManager.addWidget(namespacePrev); + LayoutManager.addWidget(namespaceNext); + LayoutManager.addWidget(namespaceLabel); } @Override - public int getMarginLeft() { + public int getMarginLeft(GuiContainer gui) + { return 5; } - @Override - public int getButtonTop() { + public int getMarginTop(GuiContainer gui) + { LayoutStyleMinecraft layout = (LayoutStyleMinecraft)LayoutManager.getLayoutStyle(); return 2 + (((int)Math.ceil((double)layout.buttonCount / layout.numButtons)) * 18); } @Override - public int getNextX(GuiContainer gui) { - return gui.width - prev.w - 2 - ((gui.xSize + gui.width) /2 + 2) - 16; - } - - @Override - public int getPrevX(GuiContainer gui) { - return 2; + public int getWidth(GuiContainer gui) + { + return LayoutManager.getLeftSize(gui) - ((gui.xSize + gui.width) / 2 + 3) - 16; } @Override - public int getPageX(GuiContainer gui) { - return gui.guiLeft * 3 / 2 + gui.xSize + 1 - ((gui.xSize + gui.width) / 2 + 2) - 16; - } - - public int getHightAdjustment() { - return 0; + public int getHeight(GuiContainer gui) + { + // - 19 = 22 + 1 -> input in bottom + return gui.height - getMarginTop(gui) - 23; } - public int getWidth(GuiContainer gui) { - return LayoutManager.getLeftSize(gui) - ( (gui.xSize + gui.width) / 2 + 3 ) - 16; - } @Override public void mouseDragged(int mousex, int mousey, int button, long heldTime) @@ -253,26 +625,41 @@ public void mouseDragged(int mousex, int mousey, int button, long heldTime) if (button == 0 && NEIClientUtils.shiftKey() && mouseDownSlot >= 0) { ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); - if (mouseOverSlot == null) { - return; - } - if (sortedStackIndex == -1) { - ItemStack stack = _items.get(mouseDownSlot); + final ItemStack stack = grid.getItem(mouseDownSlot); - if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) { + if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 250)) { + sortedNamespaceIndex = activeNamespaceIndex; sortedStackIndex = mouseDownSlot; } - } else if (mouseOverSlot != null && mouseOverSlot.slotIndex != sortedStackIndex) { + } else { - int maxStackIndex = Math.max(mouseOverSlot.slotIndex, sortedStackIndex); - int slotIndex = mouseOverSlot.slotIndex; + if (mouseOverSlot == null && sortedNamespaceIndex != activeNamespaceIndex) { + mouseOverSlot = getNextSlot(mousex, mousey); + } - _items.add(slotIndex, _items.remove(sortedStackIndex)); - _recipes.add(slotIndex, _recipes.remove(sortedStackIndex)); + if (mouseOverSlot != null) { + + if (sortedNamespaceIndex != activeNamespaceIndex) { + BookmarkGrid BGrid = namespaces.get(sortedNamespaceIndex); + BookmarkStackMeta meta = BGrid.getMetadata(sortedStackIndex); + ItemStack stack = BGrid.getItem(sortedStackIndex); + BGrid.removeItem(sortedStackIndex); + + ((BookmarkGrid) grid).addItem(stack, meta); + + sortedNamespaceIndex = activeNamespaceIndex; + sortedStackIndex = grid.size() - 1; + } + + if (mouseOverSlot.slotIndex != sortedStackIndex) { + ((BookmarkGrid) grid).moveItem(sortedStackIndex, mouseOverSlot.slotIndex); + sortedStackIndex = mouseOverSlot.slotIndex; + } + + } - sortedStackIndex = mouseOverSlot.slotIndex; } return; @@ -281,10 +668,53 @@ public void mouseDragged(int mousex, int mousey, int button, long heldTime) super.mouseDragged(mousex, mousey, button, heldTime); } + private ItemPanelSlot getNextSlot(int mousex, int mousey) + { + int idx = grid.getPage() * grid.getPerPage() - grid.getPerPage(); + int gSize = grid.size(); + + for (int i = 0; i < grid.getRows() * grid.getColumns() && idx <= gSize; i++) { + + if (!grid.isInvalidSlot(i)) { + + if (idx == gSize && grid.getSlotRect(i).contains(mousex, mousey)) { + return new ItemPanelSlot(idx, null); + } + + idx++; + } + + } + + return null; + } + + @Override + public void postDraw(int mousex, int mousey) + { + + if (sortedStackIndex != -1) { + GuiContainerManager.drawItems.zLevel += 100; + GuiContainerManager.drawItem(mousex - 8, mousey - 8, namespaces.get(sortedNamespaceIndex).getItem(sortedStackIndex).copy(), true); + GuiContainerManager.drawItems.zLevel -= 100; + } + + super.postDraw(mousex, mousey); + } + + @Override + protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) + { + ItemStack stack = grid.getItem(mouseDownSlot); + + return stack != null? stack.copy(): null; + } + @Override public void mouseUp(int mousex, int mousey, int button) { - if (sortedStackIndex >= 0) { + if (sortedStackIndex != -1) { + sortedNamespaceIndex = -1; sortedStackIndex = -1; mouseDownSlot = -1; saveBookmarks(); @@ -293,4 +723,62 @@ public void mouseUp(int mousex, int mousey, int button) } } + @Override + public boolean onMouseWheel(int shift, int mousex, int mousey) + { + + if (new Rectangle4i(namespacePrev.x, namespacePrev.y, namespaceNext.x + namespaceNext.w - namespacePrev.x, namespacePrev.h).contains(mousex, mousey)) { + + if (shift > 0) { + prevNamespace(); + } else { + nextNamespace(); + } + + return true; + } + + if (!contains(mousex, mousey)) { + return false; + } + + if (NEIClientUtils.controlKey()) { + final ItemPanelSlot slot = getSlotMouseOver(mousex, mousey); + + if (slot != null) { + final BookmarkGrid BGrid = (BookmarkGrid)grid; + final BookmarkRecipeId recipeId = BGrid.getRecipeId(slot.slotIndex); + final BookmarkStackMeta meta = BGrid.getMetadata(slot.slotIndex); + final boolean addFullRecipe = NEIClientUtils.shiftKey(); + + if (addFullRecipe) { + BookmarkStackMeta iMeta; + + for (int slotIndex = grid.size() - 1; slotIndex >= 0; slotIndex--) { + iMeta = BGrid.getMetadata(slotIndex); + + if (iMeta.recipeId != null && iMeta.recipeId.equals(recipeId)) { + NBTTagCompound nbTag = StackInfo.itemStackToNBT(BGrid.getItem(slotIndex), true); + nbTag.setInteger("Count", Math.max(nbTag.getInteger("Count") + iMeta.factor * shift, iMeta.factor)); + BGrid.replaceItem(slotIndex, StackInfo.loadFromNBT(nbTag)); + } + + } + + } + + NBTTagCompound nbTag = StackInfo.itemStackToNBT(slot.item, true); + nbTag.setInteger("Count", Math.max(nbTag.getInteger("Count") + meta.factor * shift, meta.factor)); + BGrid.replaceItem(slot.slotIndex, StackInfo.loadFromNBT(nbTag)); + + saveBookmarks(); + + return true; + } + + } + + return super.onMouseWheel(shift, mousex, mousey); + } + } diff --git a/src/main/java/codechicken/nei/ItemPanel.java b/src/main/java/codechicken/nei/ItemPanel.java index 0332caac5..219223275 100644 --- a/src/main/java/codechicken/nei/ItemPanel.java +++ b/src/main/java/codechicken/nei/ItemPanel.java @@ -1,85 +1,117 @@ package codechicken.nei; -import codechicken.lib.vec.Rectangle4i; import codechicken.nei.api.GuiInfo; import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipe; import codechicken.nei.recipe.GuiUsageRecipe; +import codechicken.nei.recipe.StackInfo; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiContainerCreative; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidContainerItem; import java.util.ArrayList; -import static codechicken.lib.gui.GuiDraw.drawRect; -import static codechicken.nei.NEIClientConfig.canPerformAction; +public class ItemPanel extends Widget +{ + + public ItemStack draggedStack; + public int mouseDownSlot = -1; + + public Button pagePrev; + public Button pageNext; + public Label pageLabel; -public class ItemPanel extends Widget { /** * Backwards compat :-/ */ + @Deprecated + private int itemsPerPage = 0; + + @Deprecated public static ArrayList items = new ArrayList<>(); - /** - * Should not be externally modified, use updateItemList - */ + @Deprecated public ArrayList realItems = new ArrayList<>(); - /** - * Swapped into visible items on update - */ - protected ArrayList _items = realItems; - public ArrayList getItems() { - return realItems; - } - - public static void updateItemList(ArrayList newItems) { - ItemPanels.itemPanel._items = newItems; - } - - public class ItemPanelSlot + public static class ItemPanelSlot { public ItemStack item; public int slotIndex; - public ItemPanelSlot(int index) { - item = realItems.get(index); - slotIndex = index; + public ItemPanelSlot(int idx, ItemStack stack) + { + slotIndex = idx; + item = stack; + } + + @Deprecated + public ItemPanelSlot(int idx) + { + this(idx, ItemPanels.itemPanel.getGrid().getItem(idx)); } + } - public ItemStack draggedStack; - public int mouseDownSlot = -1; + protected static class ItemPanelGrid extends ItemsGrid + { + public ArrayList newItems; - public Button prev; - public Button next; - public Label pageLabel; + public void setItems(ArrayList items) + { + newItems = items; + needRefresh = true; + } + public void refresh(GuiContainer gui) + { - private int marginLeft; - private int marginTop; - private int rows; - private int columns; + if (newItems != null) { + realItems = newItems; + newItems = null; + } - private boolean[] validSlotMap; - private int firstIndex; - private int itemsPerPage; + super.refresh(gui); + } - private int page; - private int numPages; + } + protected ItemsGrid grid = new ItemPanelGrid(); + public ArrayList getItems() + { + return grid.getItems(); + } + + public static void updateItemList(ArrayList newItems) + { + ((ItemPanelGrid) ItemPanels.itemPanel.getGrid()).setItems(newItems); + ItemPanels.itemPanel.realItems = newItems; + } + + @Deprecated + public void scroll(int i) + { + grid.shiftPage(i); + } + + public ItemsGrid getGrid() + { + return grid; + } public void init() { pageLabel = new Label("(0/0)", true); - prev = new Button("Prev") + pagePrev = new Button("Prev") { public boolean onButtonPress(boolean rightclick) { if (!rightclick) { - scroll(-1); + grid.shiftPage(-1); return true; } return false; @@ -90,11 +122,11 @@ public String getRenderLabel() { return "<"; } }; - next = new Button("Next") + pageNext = new Button("Next") { public boolean onButtonPress(boolean rightclick) { if (!rightclick) { - scroll(1); + grid.shiftPage(1); return true; } return false; @@ -105,169 +137,89 @@ public String getRenderLabel() { return ">"; } }; - } - public int getX(GuiContainer gui) { - return (gui.xSize + gui.width) / 2 + 3; } - public int getMarginLeft() { - return x + (w % 18) / 2; - } + public int getMarginLeft(GuiContainer gui) + { + if (gui instanceof GuiContainerCreative && NEIClientUtils.getGamemode() == 2) { + //then activate creative+ first render creative gui and oly then creative+ + return (gui.width + 176) / 2 + 2; + } - public int getMarginTop() { - return y + (h % 18) / 2; + return (gui.width + gui.xSize) / 2 + 2; } - public int getButtonTop() { + public int getMarginTop(GuiContainer gui) + { return 2; } - public int getNextX(GuiContainer gui) { - return gui.width - prev.w - 2; - } - - public int getPrevX(GuiContainer gui) { - return (gui.xSize + gui.width) / 2 + 2; - } - - public int getPageX(GuiContainer gui) { - return gui.guiLeft * 3 / 2 + gui.xSize + 1; - } - - public int getHeight(GuiContainer gui) { - return gui.height - 15 - y; - } - - public int getWidth(GuiContainer gui) { - return LayoutManager.getSideWidth(gui) - x; + public int getWidth(GuiContainer gui) + { + return LayoutManager.getSideWidth(gui) - getMarginLeft(gui); } - public String getLabelText() { - return pageLabel.text = "(" + getPage() + "/" + getNumPages() + ")"; + public int getHeight(GuiContainer gui) + { + // - 19 = 2 + 16 + 1 -> input in bottom + return gui.height - getMarginTop(gui) - 19; } - protected void setItems() { - realItems = _items; - - // Backwards compat - ItemPanels.itemPanel._items = _items; + public String getLabelText() + { + return "(" + getPage() + "/" + Math.max(1, getNumPages()) + ")"; } - public void resize(GuiContainer gui) { - setItems(); + public void resize(GuiContainer gui) + { + final int marginLeft = getMarginLeft(gui); + final int marginTop = getMarginTop(gui); + final int width = getWidth(gui); + final int height = getHeight(gui); final int buttonHeight = 16; final int buttonWidth = 16; - prev.x = getPrevX(gui); - prev.y = getButtonTop(); - prev.h = buttonHeight; - prev.w = buttonWidth; + pagePrev.w = pageNext.w = buttonWidth; + pagePrev.h = pageNext.h = buttonHeight; + pagePrev.y = pageNext.y = marginTop; - next.x = getNextX(gui); - next.y = getButtonTop(); - next.h = buttonHeight; - next.w = buttonWidth; + pagePrev.x = marginLeft; + pageNext.x = marginLeft + width - buttonWidth; - pageLabel.x = getPageX(gui); - pageLabel.y = prev.y + 5; + pageLabel.x = marginLeft + width / 2; + pageLabel.y = marginTop + 5; pageLabel.text = getLabelText(); - y = prev.h + prev.y; - x = getX(gui); - w = getWidth(gui); - h = getHeight(gui); - - marginLeft = getMarginLeft(); - marginTop = getMarginTop(); - columns = w / 18; - rows = h / 18; - //sometimes width and height can be negative with certain resizing - if(rows < 0) rows = 0; - if(columns < 0) columns = 0; - - calculatePage(); - updateValidSlots(); - } - private void calculatePage() { - if (itemsPerPage == 0) - numPages = 0; - else - numPages = (int) Math.ceil((float) realItems.size() / (float) itemsPerPage); + y = marginTop + buttonHeight + 2; + x = marginLeft; + w = width; + h = height - buttonHeight - 2; - if (firstIndex >= realItems.size()) - firstIndex = 0; + grid.setGridSize(x, y, w, h); + grid.refresh(gui); - if (numPages == 0) - page = 0; - else - page = firstIndex / itemsPerPage + 1; } - public void setVisible() { - LayoutManager.addWidget(prev); - LayoutManager.addWidget(next); + public void setVisible() + { + LayoutManager.addWidget(pagePrev); + LayoutManager.addWidget(pageNext); LayoutManager.addWidget(pageLabel); - - } - private void updateValidSlots() { - GuiContainer gui = NEIClientUtils.getGuiContainer(); - validSlotMap = new boolean[rows * columns]; - itemsPerPage = 0; - for (int i = 0; i < validSlotMap.length; i++) - if (slotValid(gui, i)) { - validSlotMap[i] = true; - itemsPerPage++; - } - } - - private boolean slotValid(GuiContainer gui, int i) { - Rectangle4i rect = getSlotRect(i); - try { - GuiInfo.readLock.lock(); - if(GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h))) - return false; - } finally { - GuiInfo.readLock.unlock(); - } - return true; - } - - public Rectangle4i getSlotRect(int i) { - return getSlotRect(i / columns, i % columns); - } - - public Rectangle4i getSlotRect(int row, int column) { - return new Rectangle4i(marginLeft + column * 18, marginTop + row * 18, 18, 18); } @Override - public void draw(int mousex, int mousey) { - if (itemsPerPage == 0) - return; - - GuiContainerManager.enableMatrixStackLogging(); - int index = firstIndex; - for (int i = 0; i < rows * columns && index < realItems.size(); i++) { - if (validSlotMap[i]) { - Rectangle4i rect = getSlotRect(i); - if (rect.contains(mousex, mousey)) - drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight - - GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, realItems.get(index)); - - index++; - } - } - GuiContainerManager.disableMatrixStackLogging(); + public void draw(int mousex, int mousey) + { + grid.draw(mousex, mousey); } @Override public void postDraw(int mousex, int mousey) { if (draggedStack != null) { GuiContainerManager.drawItems.zLevel += 100; - GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack); + GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack, true); GuiContainerManager.drawItems.zLevel -= 100; } } @@ -277,29 +229,42 @@ public void mouseDragged(int mousex, int mousey, int button, long heldTime) { if (mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null && NEIClientConfig.hasSMPCounterPart() && !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) { ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); - ItemStack stack = new ItemPanelSlot(mouseDownSlot).item; - if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) { - int amount = NEIClientConfig.getItemQuantity(); - if (amount == 0) - amount = stack.getMaxStackSize(); - draggedStack = NEIServerUtils.copyStack(stack, amount); + if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) { + draggedStack = getDraggedStackWithQuantity(mouseDownSlot); } + } } + protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) + { + ItemStack stack = grid.getItem(mouseDownSlot); + + if (stack != null) { + int amount = NEIClientConfig.getItemQuantity(); + + if (amount == 0) { + amount = stack.getMaxStackSize(); + } + + return NEIServerUtils.copyStack(stack, amount); + } + + return null; + } + @Override - public boolean handleClick(int mousex, int mousey, int button) { - if (handleDraggedClick(mousex, mousey, button)) + public boolean handleClick(int mousex, int mousey, int button) + { + + if (handleClickExt(mousex, mousey, button)) return true; if (NEIClientUtils.getHeldItem() != null) { - try { - GuiInfo.readLock.lock(); - if (GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(NEIClientUtils.getGuiContainer(), mousex, mousey, 1, 1))) - return false; - } finally { - GuiInfo.readLock.unlock(); + + if (!grid.contains(mousex, mousey)) { + return false; } if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) @@ -315,84 +280,177 @@ public boolean handleClick(int mousex, int mousey, int button) { ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); if (hoverSlot != null) { + if (button == 2) { - ItemStack stack = hoverSlot.item; - if (stack != null) { - int amount = NEIClientConfig.getItemQuantity(); - if (amount == 0) - amount = stack.getMaxStackSize(); - draggedStack = NEIServerUtils.copyStack(stack, amount); + if (hoverSlot.item != null) { + draggedStack = getDraggedStackWithQuantity(hoverSlot.slotIndex); } + } else { mouseDownSlot = hoverSlot.slotIndex; } + return true; } return false; } - private boolean handleDraggedClick(int mousex, int mousey, int button) { - if (draggedStack == null) + @Override + public boolean handleClickExt(int mouseX, int mouseY, int button) + { + if (ItemPanels.itemPanel.draggedStack != null) { + return ItemPanels.itemPanel.handleDraggedClick(mouseX, mouseY, button); + } + + if (ItemPanels.bookmarkPanel.draggedStack != null) { + return ItemPanels.bookmarkPanel.handleDraggedClick(mouseX, mouseY, button); + } + + return false; + } + + protected boolean handleDraggedClick(int mouseX, int mouseY, int button) + { + if (draggedStack == null) { + return false; + } + + if (handleFillFluidContainerClick(mouseX, mouseY, button)) { + return true; + } + + if (handleGUIContainerClick(mouseX, mouseY, button)) { + return true; + } + + if (handleCheatItemClick(mouseX, mouseY, button)) { + return true; + } + + final GuiContainer gui = NEIClientUtils.getGuiContainer(); + if (mouseX < gui.guiLeft || mouseY < gui.guiTop || mouseX >= gui.guiLeft + gui.xSize || mouseY >= gui.guiTop + gui.ySize) { + draggedStack = null; + } + + return true; + } + + protected boolean handleFillFluidContainerClick(int mouseX, int mouseY, int button) + { + + if (button == 2) { return false; + } + + ItemPanelSlot mouseOverSlot = ItemPanels.itemPanel.getSlotMouseOver(mouseX, mouseY); + + if (mouseOverSlot == null) { + mouseOverSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseX, mouseY); + } + + if (mouseOverSlot != null && draggedStack.getItem() instanceof IFluidContainerItem) { + FluidStack fluidStack = StackInfo.getFluid(mouseOverSlot.item); + + if (fluidStack != null) { + final int stackSize = draggedStack.stackSize; + + fluidStack = fluidStack.copy(); + + if (fluidStack.amount == 0) { + fluidStack.amount = 1000; + } + + if (mouseOverSlot.item.stackSize > 1) { + fluidStack.amount *= mouseOverSlot.item.stackSize; + } + + draggedStack.stackSize = 1; + ((IFluidContainerItem) draggedStack.getItem()).fill(draggedStack, fluidStack, true); + draggedStack.stackSize = stackSize; + + if (button == 1 && ((IFluidContainerItem) draggedStack.getItem()).getFluid(draggedStack) != null) { + ItemPanels.bookmarkPanel.addOrRemoveItem(draggedStack.copy()); + } + + } + + return true; + } - GuiContainer gui = NEIClientUtils.getGuiContainer(); + return false; + } + + protected boolean handleGUIContainerClick(int mouseX, int mouseY, int button) + { + final GuiContainer gui = NEIClientUtils.getGuiContainer(); boolean handled = false; + try { GuiInfo.readLock.lock(); for (INEIGuiHandler handler : GuiInfo.guiHandlers) { - if (handler.handleDragNDrop(gui, mousex, mousey, draggedStack, button)) { + if (handler.handleDragNDrop(gui, mouseX, mouseY, draggedStack, button)) { handled = true; - if (draggedStack.stackSize == 0) { - draggedStack = null; - return true; - } + break; } } } finally { GuiInfo.readLock.unlock(); } - - if (handled) - return true; - Slot overSlot = gui.getSlotAtPosition(mousex, mousey); + if (draggedStack.stackSize == 0) { + draggedStack = null; + } + + return handled; + } + + protected boolean handleCheatItemClick(int mouseX, int mouseY, int button) + { + final GuiContainer gui = NEIClientUtils.getGuiContainer(); + final Slot overSlot = gui.getSlotAtPosition(mouseX, mouseY); + if (overSlot != null && overSlot.isItemValid(draggedStack)) { + if (NEIClientConfig.canCheatItem(draggedStack)) { int contents = overSlot.getHasStack() ? overSlot.getStack().stackSize : 0; - int add = button == 0 ? draggedStack.stackSize : 1; - if (overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) + final int add = button == 0 ? draggedStack.stackSize : 1; + + if (overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) { contents = 0; - int total = Math.min(contents + add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize())); + } + + final int total = Math.min(contents + add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize())); if (total > contents) { NEIClientUtils.setSlotContents(overSlot.slotNumber, NEIServerUtils.copyStack(draggedStack, total), true); NEICPH.sendGiveItem(NEIServerUtils.copyStack(draggedStack, total), false, false); draggedStack.stackSize -= total - contents; } - if (draggedStack.stackSize == 0) + + if (draggedStack.stackSize == 0) { draggedStack = null; + } + } else { draggedStack = null; } - } else if (mousex < gui.guiLeft || mousey < gui.guiTop || mousex >= gui.guiLeft + gui.xSize || mousey >= gui.guiTop + gui.ySize) { - draggedStack = null; - } - return true; - } + return true; + } - @Override - public boolean handleClickExt(int mousex, int mousey, int button) { - return handleDraggedClick(mousex, mousey, button); + return false; } @Override public void mouseUp(int mousex, int mousey, int button) { ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); + if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) { ItemStack item = hoverSlot.item; + if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) { + if (button == 0) GuiCraftingRecipe.openRecipeGui("item", item); else if (button == 1) @@ -403,7 +461,7 @@ else if (button == 1) return; } - NEIClientUtils.cheatItem(item, button, -1); + NEIClientUtils.cheatItem(getDraggedStackWithQuantity(hoverSlot.slotIndex), button, -1); } mouseDownSlot = -1; @@ -414,20 +472,23 @@ public boolean onMouseWheel(int i, int mousex, int mousey) { if (!contains(mousex, mousey)) return false; - scroll(-i); + grid.shiftPage(-i); return true; } @Override public boolean handleKeyPress(int keyID, char keyChar) { + if (keyID == NEIClientConfig.getKeyBinding("gui.next")) { - scroll(1); + grid.shiftPage(1); return true; } + if (keyID == NEIClientConfig.getKeyBinding("gui.prev")) { - scroll(-1); + grid.shiftPage(-1); return true; } + return false; } @@ -437,53 +498,23 @@ public ItemStack getStackMouseOver(int mousex, int mousey) { return slot == null ? null : slot.item; } - public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) { - int index = firstIndex; - for (int i = 0; i < rows * columns && index < realItems.size(); i++) - if (validSlotMap[i]) { - if (getSlotRect(i).contains(mousex, mousey)) - return new ItemPanelSlot(index); - index++; - } - - return null; - } - - public void scroll(int i) { - if (itemsPerPage != 0) { - int oldIndex = firstIndex; - firstIndex += i * itemsPerPage; - if (firstIndex >= realItems.size()) - firstIndex = 0; - if (firstIndex < 0) - if (oldIndex > 0) - firstIndex = 0; - else - firstIndex = (realItems.size() - 1) / itemsPerPage * itemsPerPage; - - calculatePage(); - } + public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) + { + return grid.getSlotMouseOver(mousex, mousey); } public int getPage() { - return page; + return grid.page + 1; } public int getNumPages() { - return numPages; + return grid.numPages; } @Override - public boolean contains(int px, int py) { - GuiContainer gui = NEIClientUtils.getGuiContainer(); - Rectangle4i rect = new Rectangle4i(px, py, 1, 1); - try { - GuiInfo.readLock.lock(); - if(GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h))) - return false; - } finally { - GuiInfo.readLock.unlock(); - } - return super.contains(px, py); + public boolean contains(int px, int py) + { + return grid.contains(px, py); } + } diff --git a/src/main/java/codechicken/nei/ItemsGrid.java b/src/main/java/codechicken/nei/ItemsGrid.java new file mode 100644 index 000000000..700b4b3f4 --- /dev/null +++ b/src/main/java/codechicken/nei/ItemsGrid.java @@ -0,0 +1,315 @@ +package codechicken.nei; + +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.api.GuiInfo; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.StackInfo; +import codechicken.nei.ItemPanel.ItemPanelSlot; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; + +import static codechicken.lib.gui.GuiDraw.drawRect; + +public class ItemsGrid +{ + protected static final int SLOT_SIZE = 18; + + protected int width; + protected int height; + + protected int marginLeft; + protected int marginTop; + + protected ArrayList realItems = new ArrayList<>(); + + protected int page; + protected int perPage; + + protected int firstIndex; + protected int numPages; + + protected int rows; + protected int columns; + + protected boolean[] validSlotMap; + protected boolean[] invalidSlotMap; + + private int[] guiSize; + + protected boolean needRefresh = false; + + + public ArrayList getItems() + { + return realItems; + } + + public ItemStack getItem(int idx) + { + return realItems.get(idx); + } + + public int size() + { + return realItems.size(); + } + + public int indexOf(ItemStack stackA, boolean useNBT) + { + + for (int idx = 0; idx < realItems.size(); idx++) { + if (StackInfo.equalItemAndNBT(stackA, realItems.get(idx), useNBT)) { + return idx; + } + } + + return -1; + } + + public int getPage() + { + return page + 1; + } + + public int getPerPage() + { + return perPage; + } + + public int getNumPages() + { + return numPages; + } + + public int getRows() + { + return rows; + } + + public int getColumns() + { + return columns; + } + + public void setGridSize(int mleft, int mtop, int w, int h) + { + + //I don't like this big condition + if (marginLeft != mleft || marginTop != mtop || width != w || height != h) { + + marginLeft = mleft; + marginTop = mtop; + + width = Math.max(0, w); + height = Math.max(0, h); + + columns = width / SLOT_SIZE; + rows = height / SLOT_SIZE; + + needRefresh = true; + } + + } + + public void shiftPage(int shift) + { + if (perPage == 0) { + numPages = 0; + page = 0; + return; + } + + numPages = (int) Math.ceil((float) realItems.size() / (float) perPage); + + page += shift; + + if (page >= numPages) { + page = page - numPages; + } + + if (page < 0) { + page = numPages + page; + } + + page = Math.max(0, Math.min(page, numPages - 1)); + + needRefresh = true; + } + + public void refresh(GuiContainer gui) + { + if (!needRefresh(gui)) { + return; + } + + updateGuiOverlapSlots(gui); + shiftPage(0); + + needRefresh = false; + } + + private boolean needRefresh(GuiContainer gui) + { + + if (needRefresh == true) { + return true; + } + + if (gui == null && guiSize == null) { + return false; + } + + if (gui == null) { + guiSize = null; + return true; + } + + if (guiSize == null) { + guiSize = new int[]{ gui.guiLeft, gui.guiTop, gui.width, gui.height }; + return true; + } + + if (gui.guiLeft != guiSize[0] || gui.guiTop != guiSize[1] || gui.width != guiSize[2] || gui.height != guiSize[3]) { + guiSize = new int[]{ gui.guiLeft, gui.guiTop, gui.width, gui.height }; + return true; + } + + return false; + } + + private void updateGuiOverlapSlots(GuiContainer gui) + { + invalidSlotMap = new boolean[rows * columns]; + perPage = columns * rows; + + checkGuiOverlap(gui, 0, columns - 2, 1); + checkGuiOverlap(gui, columns - 1, 1, -1); + + } + + private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir) + { + boolean validColumn = false; + + for (int c = start; c != end && !validColumn; c += dir) { + validColumn = true; + + for (int r = 0; r < rows; r++) { + + if (!slotValid(gui, r, c) && !invalidSlotMap[columns * r + c]) { + invalidSlotMap[columns * r + c] = true; + validColumn = false; + perPage--; + } + + } + + } + + } + + private boolean slotValid(GuiContainer gui, int row, int column) + { + Rectangle4i rect = getSlotRect(row, column); + + try { + GuiInfo.readLock.lock(); + if (GuiInfo.guiHandlers.stream().anyMatch(handler -> handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h))) { + return false; + } + } finally { + GuiInfo.readLock.unlock(); + } + + return true; + } + + public Rectangle4i getSlotRect(int i) + { + return getSlotRect(i / columns, i % columns); + } + + public Rectangle4i getSlotRect(int row, int column) + { + return new Rectangle4i(marginLeft + (width % SLOT_SIZE) / 2 + column * SLOT_SIZE, marginTop + row * SLOT_SIZE, SLOT_SIZE, SLOT_SIZE); + } + + public boolean isInvalidSlot(int idx) + { + return invalidSlotMap[idx] == true; + } + + public void draw(int mousex, int mousey) + { + if (getPerPage() == 0) { + return; + } + + ItemPanelSlot slot = getSlotMouseOver(mousex, mousey); + + GuiContainerManager.enableMatrixStackLogging(); + + int idx = page * perPage; + for (int i = 0; i < rows * columns && idx < size(); i++) { + + if (!invalidSlotMap[i]) { + drawItem(getSlotRect(i), idx, slot); + idx ++; + } + + } + + GuiContainerManager.disableMatrixStackLogging(); + } + + protected void drawItem(Rectangle4i rect, int idx, ItemPanelSlot focus) + { + + if (focus != null && focus.slotIndex == idx) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + } + + GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, getItem(idx)); + } + + public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) + { + if (!contains(mousex, mousey)) { + return null; + } + + final int overRow = (int) ((mousey - marginTop) / SLOT_SIZE); + final int overColumn = (int) ((mousex - marginLeft - (width % SLOT_SIZE) / 2) / SLOT_SIZE); + final int slt = columns * overRow + overColumn; + int idx = page * perPage + slt; + + if (overRow >= rows || overColumn >= columns) { + return null; + } + + for (int i = 0; i < slt; i++) { + if (invalidSlotMap[i]) { + idx--; + } + } + + return idx < size()? new ItemPanelSlot(idx, realItems.get(idx)): null; + } + + public boolean contains(int px, int py) + { + + if (!(new Rectangle4i(marginLeft, marginTop, width, height)).contains(px, py)) { + return false; + } + + final int r = (int) ((py - marginTop) / SLOT_SIZE); + final int c = (int) ((px - marginLeft - (width % SLOT_SIZE) / 2) / SLOT_SIZE); + final int slt = columns * r + c; + + return r >= rows || c >= columns || !invalidSlotMap[slt]; + } + +} \ No newline at end of file diff --git a/src/main/java/codechicken/nei/LayoutStyleMinecraft.java b/src/main/java/codechicken/nei/LayoutStyleMinecraft.java index decef6a10..e71188256 100644 --- a/src/main/java/codechicken/nei/LayoutStyleMinecraft.java +++ b/src/main/java/codechicken/nei/LayoutStyleMinecraft.java @@ -119,7 +119,7 @@ else if (NEIClientUtils.isValidGamemode("adventure")) bookmarkPanel.resize(gui); more.w = more.h = less.w = less.h = 16; - less.x = itemPanel.prev.x; + less.x = itemPanel.pagePrev.x; more.x = gui.width - less.w - 2; more.y = less.y = gui.height - more.h - 2; diff --git a/src/main/java/codechicken/nei/NEIClientUtils.java b/src/main/java/codechicken/nei/NEIClientUtils.java index b87bfc8cb..927e024f2 100644 --- a/src/main/java/codechicken/nei/NEIClientUtils.java +++ b/src/main/java/codechicken/nei/NEIClientUtils.java @@ -5,7 +5,6 @@ import codechicken.lib.util.LangProxy; import codechicken.nei.api.GuiInfo; import codechicken.nei.api.IInfiniteItemHandler; -import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.api.ItemInfo; import com.google.common.collect.Iterables; import net.minecraft.client.Minecraft; @@ -136,10 +135,7 @@ public static void cheatItem(ItemStack stack, int button, int mode) { if (mode == 1 && stack.stackSize < stack.getMaxStackSize()) { giveStack(stack, stack.getMaxStackSize() - stack.stackSize); } else { - int amount = getItemQuantity(); - if (amount == 0) - amount = stack.getMaxStackSize(); - giveStack(stack, amount); + giveStack(stack); } } } diff --git a/src/main/java/codechicken/nei/SearchField.java b/src/main/java/codechicken/nei/SearchField.java index 9c04d7ecb..5d083c61a 100644 --- a/src/main/java/codechicken/nei/SearchField.java +++ b/src/main/java/codechicken/nei/SearchField.java @@ -63,8 +63,9 @@ public static boolean searchInventories() { } @Override - public int getTextColour() { - if(ItemPanels.itemPanel.realItems.size() == 0) { + public int getTextColour() + { + if (ItemPanels.itemPanel.getItems().isEmpty()) { return focused() ? 0xFFcc3300 : 0xFF993300; } else { return focused() ? 0xFFE0E0E0 : 0xFF909090; diff --git a/src/main/java/codechicken/nei/api/IStackStringifyHandler.java b/src/main/java/codechicken/nei/api/IStackStringifyHandler.java index 037743493..45cbf8138 100644 --- a/src/main/java/codechicken/nei/api/IStackStringifyHandler.java +++ b/src/main/java/codechicken/nei/api/IStackStringifyHandler.java @@ -1,15 +1,16 @@ package codechicken.nei.api; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; import net.minecraft.item.ItemStack; public interface IStackStringifyHandler { - public NBTTagCompound convertItemStackToNBT(ItemStack[] stacks); + public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize); public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag); - public ItemStack normalize(ItemStack item); + public FluidStack getFluid(ItemStack stack); } \ No newline at end of file diff --git a/src/main/java/codechicken/nei/config/GuiItemIconDumper.java b/src/main/java/codechicken/nei/config/GuiItemIconDumper.java index fe180a52a..3c09fb53f 100644 --- a/src/main/java/codechicken/nei/config/GuiItemIconDumper.java +++ b/src/main/java/codechicken/nei/config/GuiItemIconDumper.java @@ -22,6 +22,7 @@ import org.lwjgl.opengl.GL12; import javax.imageio.ImageIO; +import java.util.ArrayList; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; @@ -100,10 +101,12 @@ private void drawItems() { GL11.glEnable(GL12.GL_RESCALE_NORMAL); GL11.glColor4f(1, 1, 1, 1); - for(int i = 0; drawIndex < ItemPanels.itemPanel.realItems.size() && i < fit; drawIndex++, i++) { + final ArrayList items = ItemPanels.itemPanel.getItems(); + + for (int i = 0; drawIndex < items.size() && i < fit; drawIndex++, i++) { int x = i%cols * 18; int y = i/cols * 18; - GuiContainerManager.drawItem(x+1, y+1, ItemPanels.itemPanel.realItems.get(drawIndex)); + GuiContainerManager.drawItem(x+1, y+1, items.get(drawIndex)); } GL11.glFlush(); @@ -114,14 +117,19 @@ private void exportItems() throws IOException { int rows = img.getHeight() / boxSize; int cols = img.getWidth() / boxSize; int fit = rows*cols; - for(int i = 0; parseIndex < ItemPanels.itemPanel.realItems.size() && i < fit; parseIndex++, i++) { + + final ArrayList items = ItemPanels.itemPanel.getItems(); + + for(int i = 0; parseIndex < items.size() && i < fit; parseIndex++, i++) { int x = i%cols * boxSize; int y = i/cols * boxSize; - exportImage(dir, img.getSubimage(x+borderSize, y+borderSize, iconSize, iconSize), ItemPanels.itemPanel.realItems.get(parseIndex)); + exportImage(dir, img.getSubimage(x+borderSize, y+borderSize, iconSize, iconSize), items.get(parseIndex)); } - if(parseIndex >= ItemPanels.itemPanel.realItems.size()) + if (parseIndex >= items.size()) { returnScreen(new ChatComponentTranslation(opt.fullName()+".icon.dumped", "dumps/itempanel_icons")); + } + } public static String cleanFileName(String name) { diff --git a/src/main/java/codechicken/nei/config/HandlerDumper.java b/src/main/java/codechicken/nei/config/HandlerDumper.java index 551e21e3c..a752123fe 100644 --- a/src/main/java/codechicken/nei/config/HandlerDumper.java +++ b/src/main/java/codechicken/nei/config/HandlerDumper.java @@ -8,17 +8,13 @@ import codechicken.nei.recipe.TemplateRecipeHandler; import codechicken.nei.util.NBTJson; import com.google.common.base.Objects; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ChatComponentTranslation; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.tuple.Pair; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.io.PrintWriter; import java.util.LinkedList; public class HandlerDumper extends DataDumper diff --git a/src/main/java/codechicken/nei/config/ItemPanelDumper.java b/src/main/java/codechicken/nei/config/ItemPanelDumper.java index b51ac5477..bee0786f2 100644 --- a/src/main/java/codechicken/nei/config/ItemPanelDumper.java +++ b/src/main/java/codechicken/nei/config/ItemPanelDumper.java @@ -36,7 +36,7 @@ public String[] header() { @Override public Iterable dump(int mode) { LinkedList list = new LinkedList<>(); - for (ItemStack stack : ItemPanels.itemPanel.realItems) + for (ItemStack stack : ItemPanels.itemPanel.getItems()) list.add(new String[]{ Item.itemRegistry.getNameForObject(stack.getItem()), Integer.toString(Item.getIdFromItem(stack.getItem())), @@ -123,7 +123,7 @@ else if (getMode() == 1) public void dumpNBT(File file) throws IOException { NBTTagList list = new NBTTagList(); - for (ItemStack stack : ItemPanels.itemPanel.realItems) + for (ItemStack stack : ItemPanels.itemPanel.getItems()) list.appendTag(stack.writeToNBT(new NBTTagCompound())); NBTTagCompound tag = new NBTTagCompound(); @@ -134,7 +134,7 @@ public void dumpNBT(File file) throws IOException { public void dumpJson(File file) throws IOException { PrintWriter p = new PrintWriter(file); - for (ItemStack stack : ItemPanels.itemPanel.realItems) { + for (ItemStack stack : ItemPanels.itemPanel.getItems()) { NBTTagCompound tag = stack.writeToNBT(new NBTTagCompound()); tag.removeTag("Count"); p.println(tag); diff --git a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java index ff9f760b4..b6b32eb5e 100644 --- a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java +++ b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java @@ -181,15 +181,28 @@ public static void drawItem(int i, int j, ItemStack itemstack) { drawItem(i, j, itemstack, getFontRenderer(itemstack)); } + public static void drawItem(int i, int j, ItemStack itemstack, boolean smallAmount) { + drawItem(i, j, itemstack, getFontRenderer(itemstack), smallAmount); + } + + public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer) { + drawItem(i, j, itemstack, fontRenderer, false); + } + private static int modelviewDepth = -1; private static final HashSet stackTraces = new HashSet<>(); - public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer) { + public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer, boolean smallAmount) { enable3DRender(); float zLevel = drawItems.zLevel += 100F; try { drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, i, j); - drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j); + + if (!smallAmount) { + drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j); + } else if (itemstack.stackSize > 1) { + drawBigStackSize(i, j, itemstack.stackSize); + } if (!checkMatrixStack()) throw new IllegalStateException("Modelview matrix stack too deep"); @@ -217,6 +230,27 @@ public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer font drawItems.zLevel = zLevel - 100; } + //copy from appeng.client.render.AppEngRenderItem + protected static void drawBigStackSize(int offsetX, int offsetY, int amount) + { + final float scaleFactor = fontRenderer.getUnicodeFlag() ? 0.85f : 0.5f; + final float inverseScaleFactor = 1.0f / scaleFactor; + final String stackSize = String.valueOf( amount ); + + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + GL11.glPushMatrix(); + GL11.glScaled(scaleFactor, scaleFactor, scaleFactor); + + final int X = (int) ( ( (float) offsetX + 16.0f - fontRenderer.getStringWidth( stackSize ) * scaleFactor ) * inverseScaleFactor ); + final int Y = (int) ( ( (float) offsetY + 16.0f - 7.0f * scaleFactor ) * inverseScaleFactor ); + fontRenderer.drawStringWithShadow(stackSize, X, Y, 16777215); + + GL11.glPopMatrix(); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } + public static void enableMatrixStackLogging() { modelviewDepth = GL11.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH); } diff --git a/src/main/java/codechicken/nei/recipe/BookmarkRecipeId.java b/src/main/java/codechicken/nei/recipe/BookmarkRecipeId.java index c5fdaf7cf..e8882f770 100644 --- a/src/main/java/codechicken/nei/recipe/BookmarkRecipeId.java +++ b/src/main/java/codechicken/nei/recipe/BookmarkRecipeId.java @@ -5,6 +5,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonPrimitive; import codechicken.nei.util.NBTJson; +import codechicken.nei.NEIClientConfig; import codechicken.nei.PositionedStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.item.ItemStack; @@ -12,30 +13,29 @@ import java.util.ArrayList; import java.util.List; - public class BookmarkRecipeId { + public int position = -1; + public int recipetype = -1; + public String handlerName = null; - public List ingredients = new ArrayList<>(); - public BookmarkRecipeId(String handlerName, List stacks, int recipetype, int position) + public List ingredients = new ArrayList<>(); + + + public BookmarkRecipeId(String handlerName, List stacks) { this.handlerName = handlerName; - for (PositionedStack pStack : stacks) { - ingredients.add(getItemStackWithMinimumDamage(pStack.items)); + for (PositionedStack pos : stacks) { + final NBTTagCompound nbt = StackInfo.itemStackToNBT(getItemStackWithMinimumDamage(pos.items)); + if (nbt != null) { + ingredients.add(nbt); + } } - this.ingredients = ingredients; - this.recipetype = recipetype; - this.position = position; - } - - public BookmarkRecipeId(String handlerName, List stacks) - { - this(handlerName, stacks, -1, -1); } public BookmarkRecipeId(JsonObject json) @@ -47,10 +47,10 @@ public BookmarkRecipeId(JsonObject json) if (json.get("ingredients") != null) { JsonArray arr = (JsonArray) json.get("ingredients"); - List itemStacks = convertJsonArrayToIngredients(arr); + List ingredients = convertJsonArrayToIngredients(arr); - if (itemStacks != null) { - ingredients = itemStacks; + if (ingredients != null) { + this.ingredients = ingredients; } } @@ -67,10 +67,10 @@ public boolean equalsIngredients(List stacks) Short idx = 0; for (PositionedStack pStack : stacks) { - final ItemStack stackA = getItemStackWithMinimumDamage(pStack.items); - final ItemStack stackB = ingredients.get(idx); + final NBTTagCompound tagCompoundA = StackInfo.itemStackToNBT(getItemStackWithMinimumDamage(pStack.items)); + final NBTTagCompound tagCompoundB = ingredients.get(idx); - if (stackB == null || !StackInfo.equalItemAndNBT(stackA, stackB, true)) { + if (tagCompoundB == null || !tagCompoundA.equals(tagCompoundB)) { return false; } @@ -80,7 +80,7 @@ public boolean equalsIngredients(List stacks) return true; } - protected ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks) + public ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks) { int damage = Short.MAX_VALUE; ItemStack result = stacks[0]; @@ -109,38 +109,61 @@ public JsonObject toJsonObject() return json; } - protected List convertJsonArrayToIngredients(JsonArray arr) + protected List convertJsonArrayToIngredients(JsonArray arr) { - List ingredients = new ArrayList<>(); + List ingredients = new ArrayList<>(); for (JsonElement elem : arr) { - final ItemStack stack = StackInfo.loadFromNBT((NBTTagCompound) NBTJson.toNbt(elem)); + final NBTTagCompound nbt = (NBTTagCompound) NBTJson.toNbt(elem); - if (stack == null) { + if (nbt == null) { return null; } - ingredients.add(stack); + ingredients.add(nbt); } return ingredients; } - protected JsonArray convertIngredientsToJsonArray(List ingredients) + protected JsonArray convertIngredientsToJsonArray(List ingredients) { JsonArray arr = new JsonArray(); - for (ItemStack stack : ingredients) { - final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack); + for (NBTTagCompound nbTag : ingredients) { + arr.add(NBTJson.toJsonObject(nbTag)); + } - if (nbTag == null) { - return null; + return arr; + } + + public boolean equals(Object anObject) + { + if (this == anObject) { + return true; + } + + if (anObject instanceof BookmarkRecipeId) { + final BookmarkRecipeId anRecipeId = (BookmarkRecipeId) anObject; + + if (!handlerName.equals(anRecipeId.handlerName)) { + return false; } - arr.add(NBTJson.toJsonObject(nbTag)); + if (ingredients.size() != anRecipeId.ingredients.size()) { + return false; + } + + for (int idx = 0; idx < ingredients.size(); idx++) { + if (!ingredients.get(idx).equals(anRecipeId.ingredients.get(idx))) { + return false; + } + } + + return true; } - return arr; + return false; } } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipe.java b/src/main/java/codechicken/nei/recipe/GuiRecipe.java index 34d345ef9..6cf75c429 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipe.java @@ -208,7 +208,7 @@ public void setRecipePage(int idx, int position) { else if (recipetype >= currenthandlers.size()) recipetype = 0; handler = currenthandlers.get(recipetype); - handlerInfo = getHandlerInfo(handler); + handlerInfo = GuiRecipeTab.getHandlerInfo(handler); page = Math.min(Math.max(0, position), handler.numRecipes() - 1) / getRecipesPerPage(); recipeTabs.calcPageNumber(); checkYShift(); @@ -230,7 +230,7 @@ public void openTargetRecipe(BookmarkRecipeId recipeId) for (int j = 0; j < currenthandlers.size(); j++) { IRecipeHandler localHandler = currenthandlers.get(j); - HandlerInfo localHandlerInfo = getHandlerInfo(localHandler); + HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler); if (localHandlerInfo.getHandlerName().equals(recipeId.handlerName)) { recipeId.recipetype = j; @@ -258,29 +258,27 @@ public void openTargetRecipe(BookmarkRecipeId recipeId) setRecipePage(recipeId.recipetype, recipeId.position); } - public BookmarkRecipeId getFocusedRecipeId() + public List getFocusedRecipeIngredients() { - String handlerName = handlerInfo.getHandlerName(); - Point mousePos = GuiDraw.getMousePosition(); - int recipesPerPage = getRecipesPerPage(); + final int recipesPerPage = getRecipesPerPage(); - for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) { - if (recipeInFocus(i)) { - return new BookmarkRecipeId(handlerName, handler.getIngredientStacks(i), recipetype, i); + for (int idx = page * recipesPerPage; idx < handler.numRecipes() && idx < (page + 1) * recipesPerPage; idx++) { + if (recipeInFocus(idx)) { + return handler.getIngredientStacks(idx); } } return null; } - protected Boolean recipeInFocus(int idx) + protected boolean recipeInFocus(int idx) { - PositionedStack result = handler.getResultStack(idx); + final PositionedStack result = handler.getResultStack(idx); if (result != null && isMouseOver(result, idx)) { return true; } - List stacks = handler.getOtherStacks(idx); + final List stacks = handler.getOtherStacks(idx); for (PositionedStack stack : stacks) { if (isMouseOver(stack, idx)) { return true; @@ -290,6 +288,11 @@ protected Boolean recipeInFocus(int idx) return false; } + public String getHandlerName() + { + return handlerInfo.getHandlerName(); + } + public IRecipeHandler getHandler() { return handler; } @@ -436,21 +439,6 @@ private void prevType() { setRecipePage(--recipetype); } - public HandlerInfo getHandlerInfo(IRecipeHandler handler) { - final String handlerID; - if(handler instanceof TemplateRecipeHandler) { - handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier()); - } else { - handlerID = null; - } - HandlerInfo info = GuiRecipeTab.getHandlerInfo(handler.getHandlerId(), handlerID); - - if (info == null) - return GuiRecipeTab.DEFAULT_HANDLER_INFO; - - return info; - } - private void overlayRecipe(int recipe) { final IRecipeOverlayRenderer renderer = handler.getOverlayRenderer(firstGui, recipe); final IOverlayHandler overlayHandler = handler.getOverlayHandler(firstGui, recipe); diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java index ecb37a28e..4dcf0d272 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java @@ -157,6 +157,24 @@ public void setSelected(IRecipeHandler current) { selected = handler == current; } + public static HandlerInfo getHandlerInfo(IRecipeHandler handler) + { + final String handlerID; + + if (handler instanceof TemplateRecipeHandler) { + handlerID = ((TemplateRecipeHandler) handler).getOverlayIdentifier(); + } else { + handlerID = null; + } + + HandlerInfo info = getHandlerInfo(handler.getHandlerId(), handlerID); + + if (info == null) + return GuiRecipeTab.DEFAULT_HANDLER_INFO; + + return info; + } + public static HandlerInfo getHandlerInfo(String name, String name2) { HandlerInfo res = handlerMap.get(name); if (res == null) res = handlerMap.get(name2); diff --git a/src/main/java/codechicken/nei/recipe/RecipeInfo.java b/src/main/java/codechicken/nei/recipe/RecipeInfo.java index 08ea29795..3be24411f 100644 --- a/src/main/java/codechicken/nei/recipe/RecipeInfo.java +++ b/src/main/java/codechicken/nei/recipe/RecipeInfo.java @@ -119,8 +119,6 @@ public static void load() API.registerRecipeHandler(new ProfilerRecipeHandler(true)); API.registerUsageHandler(new ProfilerRecipeHandler(false)); - - API.registerStackStringifyHandler(new StackStringifyHandler()); } } diff --git a/src/main/java/codechicken/nei/recipe/RecipeItemInputHandler.java b/src/main/java/codechicken/nei/recipe/RecipeItemInputHandler.java index 77f359f85..55a5a77f7 100644 --- a/src/main/java/codechicken/nei/recipe/RecipeItemInputHandler.java +++ b/src/main/java/codechicken/nei/recipe/RecipeItemInputHandler.java @@ -5,9 +5,12 @@ import codechicken.nei.NEIClientUtils; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.guihook.IContainerInputHandler; +import codechicken.nei.PositionedStack; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; +import java.util.List; + public class RecipeItemInputHandler implements IContainerInputHandler { @Override @@ -23,14 +26,17 @@ public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) if(keyCode == NEIClientConfig.getKeyBinding("gui.usage")) return GuiUsageRecipe.openRecipeGui("item", stackover.copy()); - if(keyCode == NEIClientConfig.getKeyBinding("gui.bookmark")) { + if (keyCode == NEIClientConfig.getKeyBinding("gui.bookmark")) { NEIClientConfig.logger.debug("Adding or removing {} from bookmarks", stackover.getDisplayName()); - BookmarkRecipeId recipeId = null; + List ingredients = null; + String handlerName = ""; - if (gui instanceof GuiRecipe && NEIClientConfig.saveCurrentRecipeInBookmarksEnabled()) - recipeId = ((GuiRecipe)gui).getFocusedRecipeId(); + if (gui instanceof GuiRecipe && NEIClientConfig.saveCurrentRecipeInBookmarksEnabled()) { + ingredients = ((GuiRecipe) gui).getFocusedRecipeIngredients(); + handlerName = ((GuiRecipe) gui).getHandlerName(); + } - ItemPanels.bookmarkPanel.addOrRemoveItem(stackover.copy(), recipeId); + ItemPanels.bookmarkPanel.addOrRemoveItem(stackover.copy(), handlerName, ingredients); } return false; diff --git a/src/main/java/codechicken/nei/recipe/StackInfo.java b/src/main/java/codechicken/nei/recipe/StackInfo.java index c4edbe612..55db1bd56 100644 --- a/src/main/java/codechicken/nei/recipe/StackInfo.java +++ b/src/main/java/codechicken/nei/recipe/StackInfo.java @@ -1,8 +1,11 @@ package codechicken.nei.recipe; import codechicken.nei.api.IStackStringifyHandler; +import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler; +import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; import java.util.ArrayList; @@ -11,13 +14,22 @@ public class StackInfo public static final ArrayList stackStringifyHandlers = new ArrayList<>(); + static { + stackStringifyHandlers.add(new DefaultStackStringifyHandler()); + stackStringifyHandlers.add(new GTFluidStackStringifyHandler()); + } + public static NBTTagCompound itemStackToNBT(ItemStack stack) + { + return itemStackToNBT(stack, true); + } + + public static NBTTagCompound itemStackToNBT(ItemStack stack, boolean saveStackSize) { NBTTagCompound nbTag = null; - ItemStack[] stacks = new ItemStack[]{stack}; for (int i = stackStringifyHandlers.size() - 1; i >= 0 && nbTag == null; i--) { - nbTag = stackStringifyHandlers.get(i).convertItemStackToNBT(stacks); + nbTag = stackStringifyHandlers.get(i).convertItemStackToNBT(stack, saveStackSize); } return nbTag; @@ -34,26 +46,31 @@ public static ItemStack loadFromNBT(NBTTagCompound nbtTag) return stack; } - public static ItemStack normalize(ItemStack item) { - ItemStack copy = null; + public static boolean equalItemAndNBT(ItemStack stackA, ItemStack stackB, boolean useNBT) + { + if (!stackA.isItemEqual(stackB)) { + return false; + } - for (int i = stackStringifyHandlers.size() - 1; i >= 0 && copy == null; i--) { - copy = stackStringifyHandlers.get(i).normalize(item); + if (useNBT) { + NBTTagCompound tagCompoundA = itemStackToNBT(stackA, false); + NBTTagCompound tagCompoundB = itemStackToNBT(stackB, false); + + return tagCompoundA == null && tagCompoundB == null || tagCompoundA != null && tagCompoundB != null && tagCompoundA.equals(tagCompoundB); } - return copy; + return true; } - public static boolean equalItemAndNBT(ItemStack stackA, ItemStack stackB, boolean useNBT) + public static FluidStack getFluid(ItemStack stack) { - if (stackA.isItemEqual(stackB)) { - NBTTagCompound tagCompoundA = stackA.getTagCompound(); - NBTTagCompound tagCompoundB = stackB.getTagCompound(); + FluidStack fluid = null; - return !useNBT || (tagCompoundA == null && tagCompoundB == null) || (tagCompoundA != null && tagCompoundB != null && tagCompoundA.equals(tagCompoundB)); + for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) { + fluid = stackStringifyHandlers.get(i).getFluid(stack); } - return false; + return fluid; } } diff --git a/src/main/java/codechicken/nei/recipe/StackStringifyHandler.java b/src/main/java/codechicken/nei/recipe/StackStringifyHandler.java deleted file mode 100644 index 8fca7a334..000000000 --- a/src/main/java/codechicken/nei/recipe/StackStringifyHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -package codechicken.nei.recipe; - -import codechicken.nei.api.IStackStringifyHandler; -import cpw.mods.fml.common.registry.GameData; -import net.minecraft.nbt.NBTTagCompound; -import codechicken.nei.NEIClientConfig; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Item; - -public class StackStringifyHandler implements IStackStringifyHandler -{ - - public NBTTagCompound convertItemStackToNBT(ItemStack[] stacks) - { - ItemStack stack = getItemStackWithMinimumDamage(stacks); - NBTTagCompound nbTag = new NBTTagCompound(); - String strId = Item.itemRegistry.getNameForObject(stack.getItem()); - - nbTag.setString("strId", strId); - nbTag.setShort("Damage", (short)stack.getItemDamage()); - - if (stack.hasTagCompound()) { - nbTag.setTag("tag", stack.getTagCompound()); - } - - return nbTag; - } - - public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag) - { - - if (!nbtTag.hasKey("strId")) { - return null; - } - - String strId = nbtTag.getString("strId"); - - nbtTag = (NBTTagCompound)nbtTag.copy(); - nbtTag.setByte("Count", (byte)1); - nbtTag.setShort("id", (short)GameData.getItemRegistry().getId(strId)); - - return ItemStack.loadItemStackFromNBT(nbtTag); - } - - public ItemStack normalize(ItemStack item) - { - ItemStack copy = item.copy(); - copy.stackSize = 1; - return copy; - } - - protected static ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks) - { - int damage = Short.MAX_VALUE; - ItemStack result = stacks[0]; - - if (stacks.length > 1) { - for (ItemStack stack : stacks) { - if (stack.getItemDamage() < damage) { - damage = stack.getItemDamage(); - result = stack; - } - } - } - - return result; - } - -} \ No newline at end of file diff --git a/src/main/java/codechicken/nei/recipe/stackinfo/DefaultStackStringifyHandler.java b/src/main/java/codechicken/nei/recipe/stackinfo/DefaultStackStringifyHandler.java new file mode 100644 index 000000000..7ce230640 --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/stackinfo/DefaultStackStringifyHandler.java @@ -0,0 +1,56 @@ +package codechicken.nei.recipe.stackinfo; + +import codechicken.nei.api.IStackStringifyHandler; +import cpw.mods.fml.common.registry.GameData; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidContainerItem; + +public class DefaultStackStringifyHandler implements IStackStringifyHandler +{ + + public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize) + { + final NBTTagCompound nbTag = new NBTTagCompound(); + nbTag.setString("strId", Item.itemRegistry.getNameForObject(stack.getItem())); + nbTag.setInteger("Count", saveStackSize? stack.stackSize: 1); + nbTag.setShort("Damage", (short)stack.getItemDamage()); + + if (stack.hasTagCompound()) { + nbTag.setTag("tag", stack.getTagCompound()); + } + + return nbTag; + } + + public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag) + { + final String strId = nbtTag.getString("strId"); + + nbtTag = (NBTTagCompound)nbtTag.copy(); + nbtTag.setInteger("id", GameData.getItemRegistry().getId(strId)); //getObject + + final ItemStack stack = ItemStack.loadItemStackFromNBT(nbtTag); + + if (stack != null) { + stack.stackSize = nbtTag.getInteger("Count"); + } + + return stack; + } + + public FluidStack getFluid(ItemStack stack) + { + FluidStack fluidStack = FluidContainerRegistry.getFluidForFilledItem(stack); + + if (fluidStack == null && stack.getItem() instanceof IFluidContainerItem) { + fluidStack = ((IFluidContainerItem) stack.getItem()).getFluid(stack); + } + + return fluidStack; + } + +} diff --git a/src/main/java/codechicken/nei/recipe/stackinfo/GTFluidStackStringifyHandler.java b/src/main/java/codechicken/nei/recipe/stackinfo/GTFluidStackStringifyHandler.java new file mode 100644 index 000000000..e3cceb47c --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/stackinfo/GTFluidStackStringifyHandler.java @@ -0,0 +1,84 @@ +package codechicken.nei.recipe.stackinfo; + +import codechicken.nei.api.IStackStringifyHandler; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; + +import java.lang.reflect.Method; + +public class GTFluidStackStringifyHandler implements IStackStringifyHandler +{ + + public static Class GTDisplayFluid = null; + public static Method getFluidDisplayStack = null; + public static Method getFluidFromDisplayStack = null; + + static { + try { + final Class gtUtility = Class.forName("gregtech.api.util.GT_Utility"); + + GTDisplayFluid = Class.forName("gregtech.common.items.GT_FluidDisplayItem"); + getFluidFromDisplayStack = gtUtility.getMethod("getFluidFromDisplayStack", ItemStack.class); + getFluidDisplayStack = gtUtility.getMethod("getFluidDisplayStack", FluidStack.class, boolean.class); + + } catch (Exception ignored) { /*Do nothing*/ } + } + + public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize) + { + + if (GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) { + final NBTTagCompound nbTag = new NBTTagCompound(); + final FluidStack fluidStack = getFluid(stack); + + nbTag.setString("gtFluidName", fluidStack.getFluid().getName()); + nbTag.setInteger("Count", saveStackSize? fluidStack.amount: 1); + return nbTag; + } + + return null; + } + + public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag) + { + + if (getFluidDisplayStack != null && nbtTag.hasKey("gtFluidName")) { + final String fluidName = nbtTag.getString("gtFluidName"); + final Fluid fluid = FluidRegistry.getFluid(fluidName); + final int amount = nbtTag.getInteger("Count"); + + try { + final Object obj = getFluidDisplayStack.invoke(null, new FluidStack(fluid, amount), true); + + if (obj != null) { + return (ItemStack) obj; + } + + } catch (Exception e) {} + + } + + return null; + } + + public FluidStack getFluid(ItemStack stack) + { + + if (getFluidFromDisplayStack != null && GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) { + try { + final Object obj = getFluidFromDisplayStack.invoke(null, stack); + + if (obj != null) { + return (FluidStack) obj; + } + + } catch (Exception e) {} + } + + return null; + } + +}