diff --git a/src/main/java/codechicken/nei/AbstractSubpanel.java b/src/main/java/codechicken/nei/AbstractSubpanel.java index 61c6f09f..20452286 100644 --- a/src/main/java/codechicken/nei/AbstractSubpanel.java +++ b/src/main/java/codechicken/nei/AbstractSubpanel.java @@ -6,12 +6,11 @@ import net.minecraft.item.ItemStack; import org.lwjgl.opengl.GL11; import codechicken.nei.ItemsGrid.ItemsGridSlot; +import codechicken.nei.api.ShortcutInputHandler; import codechicken.nei.drawable.DrawableBuilder; import codechicken.nei.drawable.DrawableResource; import codechicken.nei.guihook.IContainerTooltipHandler; -import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipe; -import codechicken.nei.recipe.GuiUsageRecipe; public abstract class AbstractSubpanel> extends Widget implements IContainerTooltipHandler { @@ -122,13 +121,7 @@ public abstract class AbstractSubpanel { } @Override - public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { + public List handleTooltip(int mousex, int mousey, List currenttip) { if (this.grid.getPerPage() == 0 || this.grid.isEmpty()) { return new ArrayList<>(); @@ -724,7 +724,7 @@ public class BookmarkPanel extends PanelWidget { this.recipeChainTooltipLineHandler = null; } - return super.handleTooltip(gui, mousex, mousey, currenttip); + return super.handleTooltip(mousex, mousey, currenttip); } @Override @@ -750,7 +750,7 @@ public class BookmarkPanel extends PanelWidget { } @Override - public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { final int overRowIndex = this.grid.getHoveredRowIndex(true); final BookmarksGridSlot slot = getSlotMouseOver(mousex, mousey); @@ -783,7 +783,7 @@ public class BookmarkPanel extends PanelWidget { NEIClientConfig.getKeyName("gui.remove_recipe"), NEIClientUtils.translate("bookmark.group.remove_recipe")); - if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) { + if (BookmarkContainerInfo.getBookmarkContainerHandler(NEIClientUtils.getGuiContainer()) != null) { hotkeys.put( NEIClientConfig.getKeyName("gui.bookmark_pull_items"), NEIClientUtils.translate("bookmark.group.pull_items")); @@ -880,7 +880,7 @@ public class BookmarkPanel extends PanelWidget { } } - return hotkeys; + return super.handleHotkeys(mousex, mousey, hotkeys); } private List recipeChainTooltip(int groupId, List currenttip) { @@ -917,8 +917,7 @@ public class BookmarkPanel extends PanelWidget { } @Override - public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, - List currenttip) { + public List handleItemTooltip(ItemStack itemstack, int mousex, int mousey, List currenttip) { final BookmarksGridSlot slot = this.grid.getSlotMouseOver(mousex, mousey); if (slot != null) { diff --git a/src/main/java/codechicken/nei/HeldItemHandler.java b/src/main/java/codechicken/nei/HeldItemHandler.java index c11f2a51..11d91720 100644 --- a/src/main/java/codechicken/nei/HeldItemHandler.java +++ b/src/main/java/codechicken/nei/HeldItemHandler.java @@ -27,8 +27,8 @@ public class HeldItemHandler implements IContainerInputHandler, IContainerToolti protected boolean contains(int mousex, int mousey) { return NEIClientUtils.getHeldItem() != null && !ItemPanels.bookmarkPanel.inEditingState() && !AutoCraftingManager.processing() - && (ItemPanels.bookmarkPanel.contains(mousex, mousey) || ItemPanels.itemPanel.contains(mousex, mousey) - || ItemPanels.itemPanel.historyPanel.contains(mousex, mousey)); + && (ItemPanels.bookmarkPanel.contains(mousex, mousey) + || ItemPanels.itemPanel.containsWithSubpanels(mousex, mousey)); } @Override diff --git a/src/main/java/codechicken/nei/ItemPanel.java b/src/main/java/codechicken/nei/ItemPanel.java index f7f5cb48..951217db 100644 --- a/src/main/java/codechicken/nei/ItemPanel.java +++ b/src/main/java/codechicken/nei/ItemPanel.java @@ -222,8 +222,7 @@ public class ItemPanel extends PanelWidget { } @Override - public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, - List currenttip) { + public List handleItemTooltip(ItemStack itemstack, int mousex, int mousey, List currenttip) { if (!this.grid.forceExpand && !currenttip.isEmpty()) { final ItemsPanelGridSlot hoverSlot = this.grid.getSlotMouseOver(mousex, mousey); @@ -237,7 +236,7 @@ public class ItemPanel extends PanelWidget { } } - return super.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip); + return super.handleItemTooltip(itemstack, mousex, mousey, currenttip); } @Override @@ -258,7 +257,7 @@ public class ItemPanel extends PanelWidget { } @Override - public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { final ItemsPanelGridSlot hoverSlot = this.grid.getSlotMouseOver(mousex, mousey); if (!this.grid.forceExpand && hoverSlot != null && hoverSlot.groupIndex >= 0 && hoverSlot.groupSize > 1) { @@ -269,7 +268,12 @@ public class ItemPanel extends PanelWidget { NEIClientUtils.translate(message, hoverSlot.groupSize)); } - return hotkeys; + return super.handleHotkeys(mousex, mousey, hotkeys); + } + + public boolean containsWithSubpanels(int px, int py) { + return contains(px, py) || NEIClientConfig.showHistoryPanelWidget() && this.historyPanel.contains(px, py) + || NEIClientConfig.showCraftablesPanelWidget() && this.craftablesPanel.contains(px, py); } } diff --git a/src/main/java/codechicken/nei/LayoutManager.java b/src/main/java/codechicken/nei/LayoutManager.java index 9aae9380..bae76d38 100644 --- a/src/main/java/codechicken/nei/LayoutManager.java +++ b/src/main/java/codechicken/nei/LayoutManager.java @@ -66,6 +66,7 @@ import codechicken.nei.guihook.IContainerInputHandler; import codechicken.nei.guihook.IContainerObjectHandler; import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.recipe.AutoCraftingManager; +import codechicken.nei.recipe.DebugHandlerWidget; import codechicken.nei.recipe.GuiRecipeTab; import codechicken.nei.recipe.RecipeCatalysts; @@ -91,6 +92,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH public static SubsetWidget dropDown; public static SearchField searchField; public static ItemZoom itemZoom; + public static DebugHandlerWidget recipeHandlerWidget; public static ButtonCycled options; public static ButtonCycled bookmarksButton; @@ -291,19 +293,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH } } - @Override - public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List tooltip) { - - if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { - final Widget focused = getWidgetUnderMouse(mousex, mousey); - - if (focused != null) { - focused.postDrawTooltips(mousex, mousey, tooltip); - } - } - - } - @Override public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { @@ -354,6 +343,10 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { final Widget focused = getWidgetUnderMouse(mousex, mousey); + if (focused != null) { + currenttip = focused.handleItemTooltip(itemstack, mousex, mousey, currenttip); + } + if (focused instanceof IContainerTooltipHandler tip) { currenttip = tip.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip); } @@ -368,9 +361,14 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { final Widget focused = getWidgetUnderMouse(mousex, mousey); - if (focused instanceof IContainerTooltipHandler tip) { - hotkeys = tip.handleHotkeys(gui, mousex, mousey, hotkeys); + if (focused != null) { + hotkeys = focused.handleHotkeys(mousex, mousey, hotkeys); + + if (focused instanceof IContainerTooltipHandler tip) { + hotkeys = tip.handleHotkeys(gui, mousex, mousey, hotkeys); + } } + } return hotkeys; @@ -408,6 +406,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH itemZoom = new ItemZoom(); + recipeHandlerWidget = new DebugHandlerWidget(); + dropDown = new SubsetWidget(); searchField = new SearchField("search"); API.addItemFilter(searchField); @@ -783,9 +783,11 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH addWidget(itemZoom); if (visiblity.showSubsetDropdown) { - // Bookmarks or Subset/dropdown addWidget(dropDown); } + + addWidget(recipeHandlerWidget); + recipeHandlerWidget.setVisible(); } public static LayoutStyle getLayoutStyle(int id) { diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index cd6c3dc0..29cbd032 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -56,6 +56,7 @@ import codechicken.nei.config.OptionToggleButtonBoubs; import codechicken.nei.config.OptionUtilities; import codechicken.nei.config.preset.GuiPresetList; import codechicken.nei.event.NEIConfigsLoadedEvent; +import codechicken.nei.recipe.DebugHandlerWidget; import codechicken.nei.recipe.GuiRecipeTab; import codechicken.nei.recipe.IRecipeHandler; import codechicken.nei.recipe.InformationHandler; @@ -252,6 +253,13 @@ public class NEIClientConfig { .getBooleanValue(true); API.addOption(new OptionToggleButton("inventory.guirecipe.slotHighlightPresent", true)); + tag.getTag("inventory.guirecipe.infiniteScroll").setComment("Use Infinite Scroll for Handlers") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.guirecipe.infiniteScroll", true)); + + tag.getTag("inventory.guirecipe.maxHeight").setComment("Recipe GUI Max Height").getIntValue(370); + API.addOption(new OptionIntegerField("inventory.guirecipe.maxHeight", 166, 4000)); + 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)); @@ -259,6 +267,10 @@ public class NEIClientConfig { tag.getTag("inventory.guirecipe.profile").getBooleanValue(false); API.addOption(new OptionToggleButton("inventory.guirecipe.profile", true)); + tag.getTag("inventory.guirecipe.handlerInfo").setComment("ADVANCED: Handler Info Widget") + .getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.guirecipe.handlerInfo", true)); + tag.getTag("inventory.subsets.enabled").setComment("Enable/disable Subsets Dropdown").getBooleanValue(true); API.addOption(new OptionToggleButton("inventory.subsets.enabled", true)); @@ -999,6 +1011,7 @@ public class NEIClientConfig { pluginNEIConfigLoaded = true; MinecraftForge.EVENT_BUS.post(new NEIConfigsLoadedEvent()); + DebugHandlerWidget.loadHandlerInfoPatch(); ItemList.loadItems.restart(); } }.start(); diff --git a/src/main/java/codechicken/nei/NEIClientUtils.java b/src/main/java/codechicken/nei/NEIClientUtils.java index 8e85cfac..b11a5c14 100644 --- a/src/main/java/codechicken/nei/NEIClientUtils.java +++ b/src/main/java/codechicken/nei/NEIClientUtils.java @@ -528,7 +528,9 @@ public class NEIClientUtils extends NEIServerUtils { } public static void drawRect(double left, double top, double width, double height, Color color) { - Tessellator tessellator = Tessellator.instance; + final boolean is2DTexture = GL11.glGetBoolean(GL11.GL_TEXTURE_2D); + final boolean isBlend = GL11.glGetBoolean(GL11.GL_BLEND); + final Tessellator tessellator = Tessellator.instance; GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_TEXTURE_2D); @@ -540,8 +542,9 @@ public class NEIClientUtils extends NEIServerUtils { tessellator.addVertex(left + width, top, 0.0D); tessellator.addVertex(left, top, 0.0D); tessellator.draw(); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_BLEND); + GL11.glColor4f(1, 1, 1, 1); + if (is2DTexture) GL11.glEnable(GL11.GL_TEXTURE_2D); + if (!isBlend) GL11.glDisable(GL11.GL_BLEND); } public static void drawNEIOverlayText(String text, Rectangle4i rect, float scale, int color, boolean shadow, diff --git a/src/main/java/codechicken/nei/PanelWidget.java b/src/main/java/codechicken/nei/PanelWidget.java index fba45c74..60093fc4 100644 --- a/src/main/java/codechicken/nei/PanelWidget.java +++ b/src/main/java/codechicken/nei/PanelWidget.java @@ -11,14 +11,12 @@ import codechicken.lib.vec.Rectangle4i; import codechicken.nei.ItemsGrid.ItemsGridSlot; import codechicken.nei.api.GuiInfo; import codechicken.nei.api.INEIGuiHandler; +import codechicken.nei.api.ShortcutInputHandler; 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 implements IContainerTooltipHandler { + extends Widget { protected static final int PADDING = 2; @@ -284,13 +282,7 @@ public abstract class PanelWidget= 0) { + setPermutationToRender(stackIndex); + } + + return stackIndex >= 0; } public void setPermutationToRender(int index) { @@ -136,6 +145,10 @@ public class PositionedStack { } } + public boolean contains(int mx, int my) { + return this.relx <= mx && this.rely <= my && this.relx + 16 >= mx && this.rely + 16 >= my; + } + public boolean contains(ItemStack ingredient) { for (ItemStack item : items) if (NEIServerUtils.areStacksSameTypeCrafting(item, ingredient)) return true; diff --git a/src/main/java/codechicken/nei/SubsetWidget.java b/src/main/java/codechicken/nei/SubsetWidget.java index 74d6798d..1852674a 100644 --- a/src/main/java/codechicken/nei/SubsetWidget.java +++ b/src/main/java/codechicken/nei/SubsetWidget.java @@ -18,7 +18,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; @@ -40,7 +39,6 @@ import codechicken.nei.api.API; import codechicken.nei.api.ItemFilter; import codechicken.nei.api.ItemFilter.ItemFilterProvider; import codechicken.nei.guihook.GuiContainerManager; -import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipeTab; import codechicken.nei.recipe.ICraftingHandler; @@ -49,7 +47,7 @@ import codechicken.nei.recipe.StackInfo; import codechicken.nei.util.NBTJson; import codechicken.nei.util.NEIMouseUtils; -public class SubsetWidget extends Button implements ItemFilterProvider, IContainerTooltipHandler { +public class SubsetWidget extends Button implements ItemFilterProvider { protected static final int SLOT_HEIGHT = 18; protected static final int MARGIN = 2; @@ -939,7 +937,7 @@ public class SubsetWidget extends Button implements ItemFilterProvider, IContain } @Override - public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { if (SubsetWidget.hoverStack != null) { diff --git a/src/main/java/codechicken/nei/Widget.java b/src/main/java/codechicken/nei/Widget.java index 08967c3b..19328ea1 100644 --- a/src/main/java/codechicken/nei/Widget.java +++ b/src/main/java/codechicken/nei/Widget.java @@ -1,6 +1,7 @@ package codechicken.nei; import java.util.List; +import java.util.Map; import net.minecraft.item.ItemStack; @@ -14,8 +15,6 @@ public abstract class Widget { public void postDraw(int mx, int my) {} - public void postDrawTooltips(int mx, int my, List tooltip) {} - public boolean handleClick(int mx, int my, int button) { return true; } @@ -38,6 +37,10 @@ public abstract class Widget { return false; } + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { + return hotkeys; + } + public void update() {} public Rectangle4i bounds() { @@ -58,6 +61,14 @@ public abstract class Widget { return tooltip; } + public List handleItemTooltip(ItemStack itemstack, int mousex, int mousey, List tooltip) { + return tooltip; + } + + public boolean isFocused() { + return false; + } + public void loseFocus() {} public void gainFocus() {} @@ -67,4 +78,5 @@ public abstract class Widget { public int z; public int w; public int h; + } diff --git a/src/main/java/codechicken/nei/WidgetContainer.java b/src/main/java/codechicken/nei/WidgetContainer.java new file mode 100644 index 00000000..028a1d03 --- /dev/null +++ b/src/main/java/codechicken/nei/WidgetContainer.java @@ -0,0 +1,254 @@ +package codechicken.nei; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +import net.minecraft.item.ItemStack; + +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; + +public class WidgetContainer extends Widget { + + protected final List widgets = new ArrayList<>(); + protected boolean isFocused = false; + + public void addWidget(Widget widget) { + this.widgets.add(widget); + } + + public void setWidgets(List widgets) { + final boolean isFocused = this.isFocused; + clear(); + loseFocus(); + + for (Widget widget : widgets) { + addWidget(widget); + } + + this.isFocused = isFocused; + } + + public void clear() { + this.widgets.clear(); + this.isFocused = false; + } + + public List getWidgets() { + return Collections.unmodifiableList(this.widgets); + } + + public boolean removeIf(Predicate filter) { + return this.widgets.removeIf(filter); + } + + @Override + public void draw(int mousex, int mousey) { + drawWidgets(mousex, mousey); + } + + protected void drawWidgets(int mousex, int mousey) { + final Rectangle4i bounds = bounds(); + + for (Widget widget : this.widgets) { + if (widget.bounds().intersects(bounds)) { + widget.draw(mousex, mousey); + } + } + } + + @Override + public void update() { + + for (Widget widget : this.widgets) { + widget.update(); + } + + Collections.sort(this.widgets, Comparator.comparingInt((Widget widget) -> widget.z)); + } + + public Widget getWidgetUnderMouse(int mousex, int mousey) { + + if (!bounds().contains(mousex, mousey)) { + return null; + } + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + if (widget.contains(mousex, mousey)) { + return widget; + } + } + + return null; + } + + @Override + public boolean onMouseWheel(int scroll, int mousex, int mousey) { + final Widget widget = getWidgetUnderMouse(mousex, mousey); + + return widget != null && widget.onMouseWheel(scroll, mousex, mousey); + } + + @Override + public boolean handleClick(int mousex, int mousey, int button) { + + if (contains(mousex, mousey)) { + gainFocus(); + } + + final Widget widget = getWidgetUnderMouse(mousex, mousey); + + return widget != null && widget.handleClick(mousex, mousey, button); + } + + @Override + public boolean handleClickExt(int mousex, int mousey, int button) { + loseFocus(); + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + if (!widget.contains(mousex, mousey) && widget.handleClickExt(mousex, mousey, button)) { + return true; + } + } + + return false; + } + + @Override + public void mouseDragged(int mousex, int mousey, int button, long heldTime) { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + widget.mouseDragged(mousex, mousey, button, heldTime); + } + } + + @Override + public void mouseUp(int mousex, int mousey, int button) { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + widget.mouseUp(mousex, mousey, button); + } + } + + @Override + public boolean handleKeyPress(int keyCode, char keyChar) { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + if (widget.handleKeyPress(keyCode, keyChar)) { + return true; + } + } + + return false; + } + + @Override + public void lastKeyTyped(int keyID, char keyChar) { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + widget.lastKeyTyped(keyID, keyChar); + } + + } + + @Override + public boolean isFocused() { + return this.isFocused; + } + + @Override + public void loseFocus() { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + if (widget.isFocused()) { + widget.loseFocus(); + } + } + + this.isFocused = false; + } + + @Override + public void gainFocus() { + final Point mouse = GuiDraw.getMousePosition(); + final Widget widget = getWidgetUnderMouse(mouse.x, mouse.y); + + if (widget != null) { + + if (!widget.isFocused()) { + loseFocus(); + widget.gainFocus(); + } + + } else { + loseFocus(); + } + + this.isFocused = true; + } + + @Override + public ItemStack getStackMouseOver(int mousex, int mousey) { + final Widget widget = getWidgetUnderMouse(mousex, mousey); + + if (widget != null) { + return widget.getStackMouseOver(mousex, mousey); + } + + return null; + } + + @Override + public void postDraw(int mousex, int mousey) { + + for (Widget widget : this.widgets) { + widget.postDraw(mousex, mousey); + } + + } + + @Override + public void onGuiClick(int mousex, int mousey) { + + for (int index = this.widgets.size() - 1; index >= 0; index--) { + final Widget widget = this.widgets.get(index); + widget.onGuiClick(mousex, mousey); + } + + } + + @Override + public List handleTooltip(int mousex, int mousey, List tooltip) { + final Widget widget = getWidgetUnderMouse(mousex, mousey); + + if (widget != null) { + return widget.handleTooltip(mousex, mousey, tooltip); + } + + return tooltip; + } + + @Override + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { + final Widget widget = getWidgetUnderMouse(mousex, mousey); + + if (widget != null) { + return widget.handleHotkeys(mousex, mousey, hotkeys); + } + + return hotkeys; + } + +} diff --git a/src/main/java/codechicken/nei/api/GuiInfo.java b/src/main/java/codechicken/nei/api/GuiInfo.java index f09d2806..35415a02 100644 --- a/src/main/java/codechicken/nei/api/GuiInfo.java +++ b/src/main/java/codechicken/nei/api/GuiInfo.java @@ -16,7 +16,6 @@ import codechicken.nei.NEIDummySlotHandler; import codechicken.nei.NEIPotionGuiHandler; import codechicken.nei.recipe.CheatItemHandler; import codechicken.nei.recipe.FillFluidContainerHandler; -import codechicken.nei.recipe.GuiRecipeCatalyst; import codechicken.nei.recipe.SearchInputDropHandler; public class GuiInfo { @@ -31,7 +30,6 @@ public class GuiInfo { API.registerNEIGuiHandler(new NEICreativeGuiHandler()); API.registerNEIGuiHandler(new NEIChestGuiHandler()); API.registerNEIGuiHandler(new NEIDummySlotHandler()); - API.registerNEIGuiHandler(new GuiRecipeCatalyst(null)); API.registerNEIGuiHandler(new SearchInputDropHandler()); API.registerNEIGuiHandler(new FillFluidContainerHandler()); API.registerNEIGuiHandler(new CheatItemHandler()); diff --git a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java index 78678eeb..e6ad1910 100644 --- a/src/main/java/codechicken/nei/api/ShortcutInputHandler.java +++ b/src/main/java/codechicken/nei/api/ShortcutInputHandler.java @@ -145,9 +145,9 @@ public abstract class ShortcutInputHandler { final int button = Mouse.getEventButton(); if (button == 0) { - return GuiCraftingRecipe.openRecipeGui("item", stackover); + return GuiCraftingRecipe.openRecipeGui("item", stackover.copy()); } else if (button == 1) { - return GuiUsageRecipe.openRecipeGui("item", stackover); + return GuiUsageRecipe.openRecipeGui("item", stackover.copy()); } } @@ -305,10 +305,9 @@ public abstract class ShortcutInputHandler { if (!saveStackSize) { stackover = StackInfo.withAmount(stackover, 0); - } else if (ItemPanels.itemPanel.contains(mousePos.x, mousePos.y) - || ItemPanels.itemPanel.historyPanel.contains(mousePos.x, mousePos.y)) { - stackover = ItemQuantityField.prepareStackWithQuantity(stackover, 0); - } + } else if (ItemPanels.itemPanel.containsWithSubpanels(mousePos.x, mousePos.y)) { + stackover = ItemQuantityField.prepareStackWithQuantity(stackover, 0); + } ItemPanels.bookmarkPanel .addItem(stackover, existsRecipe ? recipeId : null, BookmarkGrid.DEFAULT_GROUP_ID); @@ -380,7 +379,8 @@ public abstract class ShortcutInputHandler { return ItemPanels.bookmarkPanel.pullBookmarkItems(math, shift); } - public static Map handleHotkeys(GuiContainer gui, int mousex, int mousey, ItemStack stack) { + public static Map handleHotkeys(int mousex, int mousey, ItemStack stack) { + final GuiContainer gui = NEIClientUtils.getGuiContainer(); final int groupId = ItemPanels.bookmarkPanel.getHoveredGroupId(true); final Map hotkeys = new HashMap<>(); diff --git a/src/main/java/codechicken/nei/config/IMCHandler.java b/src/main/java/codechicken/nei/config/IMCHandler.java index 62837a3c..3b85688a 100644 --- a/src/main/java/codechicken/nei/config/IMCHandler.java +++ b/src/main/java/codechicken/nei/config/IMCHandler.java @@ -98,6 +98,7 @@ public class IMCHandler { } // true if not set to false + info.setUseCustomScroll(tag.hasKey("useCustomScroll") && tag.getBoolean("useCustomScroll")); info.setShowFavoritesButton(!tag.hasKey("showFavoritesButton") || tag.getBoolean("showFavoritesButton")); info.setShowOverlayButton(!tag.hasKey("showOverlayButton") || tag.getBoolean("showOverlayButton")); diff --git a/src/main/java/codechicken/nei/drawable/DrawableResource.java b/src/main/java/codechicken/nei/drawable/DrawableResource.java index 7686fa74..f73b9fd1 100644 --- a/src/main/java/codechicken/nei/drawable/DrawableResource.java +++ b/src/main/java/codechicken/nei/drawable/DrawableResource.java @@ -4,6 +4,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + import codechicken.nei.Image; public class DrawableResource extends Image { @@ -43,15 +45,160 @@ public class DrawableResource extends Image { } public void draw(int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight) { - Minecraft.getMinecraft().getTextureManager().bindTexture(this.resourceLocation); - - final int x = xOffset + this.paddingLeft + maskLeft; - final int y = yOffset + this.paddingTop + maskTop; - final int textureX = this.x + maskLeft; - final int textureY = this.y + maskTop; + final boolean is2DTexture = GL11.glGetBoolean(GL11.GL_TEXTURE_2D); final int width = this.width - maskRight - maskLeft; final int height = this.height - maskBottom - maskTop; - // drawModalRectWithCustomSizedTexture - Gui.func_146110_a(x, y, textureX, textureY, width, height, textureWidth, textureHeight); + + GL11.glEnable(GL11.GL_TEXTURE_2D); + Minecraft.getMinecraft().getTextureManager().bindTexture(this.resourceLocation); + drawModalRectWithCustomSizedTexture(xOffset + maskLeft, yOffset + maskTop, maskLeft, maskTop, width, height); + if (!is2DTexture) GL11.glDisable(GL11.GL_TEXTURE_2D); } + + public void draw(int xOffset, int yOffset, int width, int height, int sliceLeft, int sliceRight, int sliceTop, + int sliceBottom) { + final int textureWidth = getWidth(); + final int textureHeight = getHeight(); + final int middleWidth = textureWidth - sliceLeft - sliceRight; + final int middleHeight = textureHeight - sliceTop - sliceBottom; + final int tileWidth = width - sliceLeft - sliceRight; + final int tileHeight = height - sliceTop - sliceBottom; + + if (middleWidth > 0 && middleHeight > 0 && tileWidth > 0 && tileHeight > 0) { + final boolean is2DTexture = GL11.glGetBoolean(GL11.GL_TEXTURE_2D); + final int tileWidthCount = tileWidth / middleWidth; + final int remainderWidth = tileWidth - (tileWidthCount * middleWidth); + final int tileHeightCount = tileHeight / middleHeight; + final int remainderHeight = tileHeight - (tileHeightCount * middleHeight); + + GL11.glEnable(GL11.GL_TEXTURE_2D); + Minecraft.getMinecraft().getTextureManager().bindTexture(this.resourceLocation); + + // middle parts + for (int tileW = 0; tileW <= tileWidthCount; tileW++) { + final int tileWidthSize = (tileW == tileWidthCount) ? remainderWidth : middleWidth; + final int x = xOffset + sliceLeft + tileW * middleWidth; + + for (int tileH = 0; tileH <= tileHeightCount; tileH++) { + final int tileHeightSize = (tileH == tileHeightCount) ? remainderHeight : middleHeight; + drawModalRectWithCustomSizedTexture( + x, + yOffset + sliceTop + tileH * middleHeight, + sliceLeft, + sliceTop, + tileWidthSize, + tileHeightSize); + } + } + + // border top + if (sliceTop > 0) { + for (int tileW = 0; tileW <= tileWidthCount; tileW++) { + final int tileWidthSize = (tileW == tileWidthCount) ? remainderWidth : middleWidth; + drawModalRectWithCustomSizedTexture( + xOffset + sliceLeft + tileW * middleWidth, + yOffset, + sliceLeft, + 0, + tileWidthSize, + sliceTop); + } + } + + // border bottom + if (sliceBottom > 0) { + for (int tileW = 0; tileW <= tileWidthCount; tileW++) { + final int tileWidthSize = (tileW == tileWidthCount) ? remainderWidth : middleWidth; + drawModalRectWithCustomSizedTexture( + xOffset + sliceLeft + tileW * middleWidth, + yOffset + sliceTop + tileHeight, + sliceLeft, + sliceTop + middleHeight, + tileWidthSize, + sliceBottom); + } + } + + // border left + if (sliceLeft > 0) { + for (int tileH = 0; tileH <= tileHeightCount; tileH++) { + final int tileHeightSize = (tileH == tileHeightCount) ? remainderHeight : middleHeight; + drawModalRectWithCustomSizedTexture( + xOffset, + yOffset + sliceTop + tileH * middleHeight, + 0, + sliceTop, + sliceLeft, + tileHeightSize); + } + } + + // border right + if (sliceRight > 0) { + for (int tileH = 0; tileH <= tileHeightCount; tileH++) { + final int tileHeightSize = (tileH == tileHeightCount) ? remainderHeight : middleHeight; + drawModalRectWithCustomSizedTexture( + xOffset + sliceLeft + tileWidth, + yOffset + sliceTop + tileH * middleHeight, + sliceLeft + middleWidth, + sliceTop, + sliceRight, + tileHeightSize); + } + } + + // angle left-top + if (sliceLeft > 0 && sliceTop > 0) { + drawModalRectWithCustomSizedTexture(xOffset, yOffset, 0, 0, sliceLeft, sliceTop); + } + + // angle right-top + if (sliceRight > 0 && sliceTop > 0) { + drawModalRectWithCustomSizedTexture( + xOffset + sliceLeft + tileWidth, + yOffset, + sliceLeft + middleWidth, + 0, + sliceRight, + sliceTop); + } + + // angle left-bottom + if (sliceLeft > 0 && sliceBottom > 0) { + drawModalRectWithCustomSizedTexture( + xOffset, + yOffset + sliceTop + tileHeight, + 0, + sliceTop + middleHeight, + sliceLeft, + sliceBottom); + } + + // angle right-bottom + if (sliceRight > 0 && sliceBottom > 0) { + drawModalRectWithCustomSizedTexture( + xOffset + sliceLeft + tileWidth, + yOffset + sliceTop + tileHeight, + sliceLeft + middleWidth, + sliceTop + middleHeight, + sliceRight, + sliceBottom); + } + + if (!is2DTexture) GL11.glDisable(GL11.GL_TEXTURE_2D); + } + } + + private void drawModalRectWithCustomSizedTexture(int xOffset, int yOffset, int u, int v, int width, int height) { + Gui.func_146110_a( + xOffset + this.paddingLeft, + yOffset + this.paddingTop, + this.x + u, + this.y + v, + width, + height, + this.textureWidth, + this.textureHeight); + } + } diff --git a/src/main/java/codechicken/nei/drawable/GuiElementDuex.java b/src/main/java/codechicken/nei/drawable/GuiElementDuex.java deleted file mode 100644 index 00a7627e..00000000 --- a/src/main/java/codechicken/nei/drawable/GuiElementDuex.java +++ /dev/null @@ -1,93 +0,0 @@ -package codechicken.nei.drawable; - -import net.minecraft.client.gui.GuiScreen; - -import org.lwjgl.opengl.GL11; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -/* - * Taken from Mantle 1.12-1.3.3.49 under the MIT License The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights - * (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -@SideOnly(Side.CLIENT) -public class GuiElementDuex { - - // this is totally completely ugly but it's a simple solution that doesn't clutter everything too much >_> - public static int defaultTexW = 256; - public static int defaultTexH = 256; - - public final int x; - public final int y; - public final int w; - public final int h; - - public int texW; - public int texH; - - public GuiElementDuex(int x, int y, int w, int h, int texW, int texH) { - this(x, y, w, h); - setTextureSize(texW, texH); - - defaultTexW = texW; - defaultTexH = texH; - } - - public GuiElementDuex(int x, int y, int w, int h) { - this.x = x; - this.y = y; - this.w = w; - this.h = h; - setTextureSize(defaultTexW, defaultTexH); - } - - public GuiElementDuex setTextureSize(int w, int h) { - texW = w; - texH = h; - - return this; - } - - public GuiElementDuex shift(int xd, int yd) { - return new GuiElementDuex(this.x + xd, this.y + yd, this.w, this.h, this.texW, this.texH); - } - - /** - * Draws the element at the given x/y coordinates - * - * @param xPos X-Coordinate on the screen - * @param yPos Y-Coordinate on the screen - */ - public int draw(int xPos, int yPos) { - // drawModalRectWithCustomSizedTexture - GL11.glColor4f(1, 1, 1, 1); - GuiScreen.func_146110_a(xPos, yPos, x, y, w, h, texW, texH); - return w; - } - - public static class Builder { - - public int w; - public int h; - - public Builder(int w, int h) { - this.w = w; - this.h = h; - } - - public GuiElementDuex get(int x, int y, int w, int h) { - return new GuiElementDuex(x, y, w, h, this.w, this.h); - } - } -} diff --git a/src/main/java/codechicken/nei/drawable/GuiElementScalable.java b/src/main/java/codechicken/nei/drawable/GuiElementScalable.java deleted file mode 100644 index bb02bf50..00000000 --- a/src/main/java/codechicken/nei/drawable/GuiElementScalable.java +++ /dev/null @@ -1,91 +0,0 @@ -package codechicken.nei.drawable; - -import net.minecraft.client.gui.GuiScreen; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; - -/* - * Taken from Mantle 1.12-1.3.3.49 under the MIT License The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights - * (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -@SideOnly(Side.CLIENT) -public class GuiElementScalable extends GuiElementDuex { - - public GuiElementScalable(int x, int y, int w, int h, int texW, int texH) { - super(x, y, w, h, texW, texH); - } - - public GuiElementScalable(int x, int y, int w, int h) { - super(x, y, w, h); - } - - public int drawScaledX(int xPos, int yPos, int width) { - for (int i = 0; i < width / w; i++) { - draw(xPos + i * w, yPos); - } - // remainder that doesn't fit total width - int remainder = width % w; - if (remainder > 0) { - GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, h, texW, texH); - } - - return width; - } - - public int drawScaledY(int xPos, int yPos, int height) { - for (int i = 0; i < height / h; i++) { - draw(xPos, yPos + i * h); - } - // remainder that doesn't fit total width - int remainder = height % h; - if (remainder > 0) { - // drawModalRectWithCustomSizedTexture - GuiScreen.func_146110_a(xPos, yPos + height - remainder, x, y, w, remainder, texW, texH); - } - - return w; - } - - public int drawScaled(int xPos, int yPos, int width, int height) { - // we draw full height row-wise - int full = height / this.h; - for (int i = 0; i < full; i++) { - drawScaledX(xPos, yPos + i * this.h, width); - } - - yPos += full * this.h; - - // and the remainder is drawn manually - int yRest = height % this.h; - // the same as drawScaledX but with the remaining height - for (int i = 0; i < width / w; i++) { - drawScaledY(xPos + i * w, yPos, yRest); - } - // remainder that doesn't fit total width - int remainder = width % w; - if (remainder > 0) { - // drawModalRectWithCustomSizedTexture - GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, yRest, texW, texH); - } - - return width; - } - - @Override - public GuiElementScalable shift(int xd, int yd) { - GuiElementScalable element = new GuiElementScalable(this.x + xd, this.y + yd, this.w, this.h); - element.setTextureSize(texW, texH); - return element; - } -} diff --git a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java index 63b5ee81..f26a820c 100644 --- a/src/main/java/codechicken/nei/guihook/GuiContainerManager.java +++ b/src/main/java/codechicken/nei/guihook/GuiContainerManager.java @@ -648,9 +648,6 @@ public class GuiContainerManager { drawPagedTooltip(font, mousex + 12, mousey - 12, tooltip); } - for (IContainerDrawHandler drawHandler : drawHandlers) { - drawHandler.postRenderTooltips(window, mousex, mousey, tooltip); - } } private List collectHotkeyTips(int mousex, int mousey) { diff --git a/src/main/java/codechicken/nei/guihook/IContainerDrawHandler.java b/src/main/java/codechicken/nei/guihook/IContainerDrawHandler.java index e12d1b36..35c76c40 100644 --- a/src/main/java/codechicken/nei/guihook/IContainerDrawHandler.java +++ b/src/main/java/codechicken/nei/guihook/IContainerDrawHandler.java @@ -1,7 +1,5 @@ package codechicken.nei.guihook; -import java.util.List; - import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.inventory.Slot; @@ -9,14 +7,14 @@ public interface IContainerDrawHandler { /** * Initialize your objects and the gui for drawing. - * + * * @param gui An instance of the currentscreen */ public void onPreDraw(GuiContainer gui); /** * Draw your objects. Called after all normal gui rendering has been performed. - * + * * @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 @@ -25,27 +23,16 @@ public interface IContainerDrawHandler { /** * Use this to draw things that should always be on top, for example objects being held by the mouse. - * + * * @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 */ public void postRenderObjects(GuiContainer gui, int mousex, int mousey); - /** - * Use this to draw things that should be drawn just after vanilla slot tooltips, on top of buttons and other - * usually always-on-top widgets. - * - * @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 - * @param tooltip The contents of the tooltip that has previously been drawn - */ - default void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List tooltip) {} - /** * Render something over a slot before the item in the slot. - * + * * @param gui An instance of the currentscreen * @param slot The slot being rendered. */ @@ -53,7 +40,7 @@ public interface IContainerDrawHandler { /** * Render something over a slot after the item in the slot. - * + * * @param gui An instance of the currentscreen * @param slot The slot being rendered. */ diff --git a/src/main/java/codechicken/nei/recipe/ContainerRecipe.java b/src/main/java/codechicken/nei/recipe/ContainerRecipe.java index 9859f064..6a9f8b55 100644 --- a/src/main/java/codechicken/nei/recipe/ContainerRecipe.java +++ b/src/main/java/codechicken/nei/recipe/ContainerRecipe.java @@ -2,122 +2,29 @@ package codechicken.nei.recipe; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; -import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import codechicken.nei.PositionedStack; +import codechicken.nei.api.ShortcutInputHandler; public class ContainerRecipe extends Container { - private class RecipeInventory implements IInventory { + private ItemStack activeStack = null; - @Override - public boolean isUseableByPlayer(EntityPlayer entityplayer) { - return true; - } - - @Override - public int getSizeInventory() { - return inventorySlots.size(); - } - - @Override - public ItemStack getStackInSlot(int i) { - if (i < 0 || i > inventoryItemStacks.size()) return null; - return (ItemStack) inventoryItemStacks.get(i); - } - - @Override - public ItemStack decrStackSize(int i, int j) { - return null; - } - - @Override - public void setInventorySlotContents(int slot, ItemStack itemstack) { - if (slot < 0 || slot >= inventoryItemStacks.size()) return; - - inventoryItemStacks.set(slot, itemstack); - } - - @Override - public String getInventoryName() { - return null; - } - - @Override - public int getInventoryStackLimit() { - return 1; - } - - @Override - public void markDirty() {} - - @Override - public void openInventory() {} - - @Override - public void closeInventory() {} - - @Override - public ItemStack getStackInSlotOnClosing(int var1) { - return null; - } - - @Override - public boolean isItemValidForSlot(int i, ItemStack itemstack) { - return false; - } - - @Override - public boolean hasCustomInventoryName() { - return false; - } - } - - private final RecipeInventory recipeInventory = new RecipeInventory(); - - public void clearInventory() { - inventoryItemStacks.clear(); - inventorySlots.clear(); - } - - public ItemStack slotClick(int slot, int button, boolean flag, EntityPlayer entityplayer) { - if (slot < 0) return null; - - ItemStack stack = recipeInventory.getStackInSlot(slot); - if (stack != null) { - - if (button == 0) { - GuiCraftingRecipe.openRecipeGui("item", stack); - } else if (button == 1) { - GuiUsageRecipe.openRecipeGui("item", stack); - } - } + @Override + public ItemStack slotClick(int slotId, int clickedButton, int mode, EntityPlayer player) { + ShortcutInputHandler.handleMouseClick(this.activeStack); return null; } - public void addSlot(PositionedStack stack, int recipex, int recipey) { - int slot = inventorySlots.size(); - addSlotToContainer(new Slot(recipeInventory, slot, recipex + stack.relx, recipey + stack.rely) { - - @Override - public boolean isItemValid(ItemStack par1ItemStack) { - return false; - } - }); - recipeInventory.setInventorySlotContents(slot, stack.item); - } - - public Slot getSlotWithStack(PositionedStack stack, int recipex, int recipey) { - for (Object inventorySlot : inventorySlots) { - Slot slot = (Slot) inventorySlot; - if (slot.xDisplayPosition == (stack.relx + recipex) && slot.yDisplayPosition == (stack.rely + recipey)) - return slot; - } - return null; + public void setActiveStack(ItemStack activeStack) { + this.inventorySlots.clear(); + this.inventoryItemStacks.clear(); + this.activeStack = activeStack; } + @Override public boolean canInteractWith(EntityPlayer entityplayer) { return true; } @@ -131,4 +38,9 @@ public class ContainerRecipe extends Container { public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2) { return null; // no shift clicking (scrolling...) } + + @Deprecated + public Slot getSlotWithStack(PositionedStack stack, int recipex, int recipey) { + return null; + } } diff --git a/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java b/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java new file mode 100644 index 00000000..1879d73a --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java @@ -0,0 +1,640 @@ +package codechicken.nei.recipe; + +import java.awt.Point; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.inventory.GuiContainer; + +import org.apache.commons.io.IOUtils; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.Button; +import codechicken.nei.ClientHandler; +import codechicken.nei.FormattedTextField; +import codechicken.nei.LayoutManager; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.TextField; +import codechicken.nei.Widget; +import codechicken.nei.drawable.DrawableBuilder; +import codechicken.nei.drawable.DrawableResource; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerInputHandler; +import codechicken.nei.recipe.TemplateRecipeHandler.RecipeTransferRect; + +public class DebugHandlerWidget extends Widget implements IContainerInputHandler { + + private static abstract class IntegerField extends TextField { + + protected int defaultValue = 0; + + public IntegerField(String ident, int defaultValue) { + super(ident); + this.defaultValue = defaultValue; + this.h = LINE_HEIGHT; + this.z = 2; + ((FormattedTextField) field).setPlaceholder(Integer.toString(this.defaultValue)); + } + + @Override + protected void initInternalTextField() { + field = new FormattedTextField(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0) { + + @Override + public String getText() { + String text = super.getText(); + return !isFocused() && this.placeholder.equals(text) ? "" : text; + } + + @Override + protected boolean beforeWrite(String text) { + if (text == null || text.isEmpty()) return true; + try { + return Integer.parseInt(text) >= 0; + } catch (NumberFormatException e) { + return false; + } + } + + @Override + public boolean textboxKeyTyped(char keyChar, int keyID) { + if (!isFocused()) return false; + + if (super.textboxKeyTyped(keyChar, keyID)) { + return true; + } else if (keyID == Keyboard.KEY_DOWN) { + setText(Integer.toString(getInteger() - 1)); + return true; + } else if (keyID == Keyboard.KEY_UP) { + setText(Integer.toString(getInteger() + 1)); + return true; + } + + return false; + } + + }; + field.setMaxStringLength(maxSearchLength); + field.setCursorPositionZero(); + } + + protected int getInteger() { + try { + return Integer.parseInt(text()); + } catch (NumberFormatException nfe) { + return this.defaultValue; + } + } + + @Override + public boolean onMouseWheel(int i, int mx, int my) { + if (!contains(mx, my)) return false; + setText(Integer.toString(getInteger() + i)); + return true; + } + + } + + private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 }; + + private IRecipeHandler handler; + private HandlerInfo handlerInfo; + + private static final int WINDOW_WIDTH = 176; + private static final int LINE_HEIGHT = 16; + private static final int INLINE_PADDING = 6; + private static final int LABEL_WIDTH = 50; + + private IntegerField order; + private IntegerField yShift; + private IntegerField handlerHeight; + private IntegerField handlerWidth; + private IntegerField maxRecipesPerPage; + private Button useCustomScroll; + + private Point dragPoint = null; + public boolean showWidget = false; + + private static final int BORDER_PADDING = 6; + private final DrawableResource BG_TEXTURE = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, 0, 176, 166) + .build(); + + public DebugHandlerWidget() { + GuiContainerManager.addInputHandler(this); + + this.order = new IntegerField("order", 0) { + + @Override + public void onTextChange(String oldText) { + + if (NEIClientConfig.handlerOrdering.get(handler.getOverlayIdentifier()) != null) { + if (getInteger() != NEIClientConfig.handlerOrdering.get(handler.getOverlayIdentifier())) { + updatePatch(5, getInteger(), this.defaultValue); + } + } else if (NEIClientConfig.handlerOrdering.get(handler.getHandlerId()) != null) { + if (getInteger() != NEIClientConfig.handlerOrdering.get(handler.getHandlerId())) { + updatePatch(5, getInteger(), this.defaultValue); + } + } + } + }; + + this.yShift = new IntegerField("yShift", 0) { + + @Override + public void onTextChange(String oldText) { + if (getInteger() != handlerInfo.getYShift()) { + handlerInfo.setYShift(getInteger()); + updatePatch(1, getInteger(), this.defaultValue); + } + } + }; + + this.maxRecipesPerPage = new IntegerField("maxRecipesPerPage", HandlerInfo.DEFAULT_MAX_PER_PAGE) { + + @Override + public void onTextChange(String oldText) { + if (getInteger() != handlerInfo.getMaxRecipesPerPage()) { + handlerInfo.setHandlerDimensions(handlerInfo.getHeight(), handlerInfo.getWidth(), getInteger()); + updatePatch(4, getInteger(), this.defaultValue); + } + } + }; + + this.handlerHeight = new IntegerField("handlerHeight", HandlerInfo.DEFAULT_HEIGHT) { + + @Override + public void onTextChange(String oldText) { + if (getInteger() != handlerInfo.getHeight()) { + handlerInfo.setHandlerDimensions( + getInteger(), + handlerInfo.getWidth(), + handlerInfo.getMaxRecipesPerPage()); + updatePatch(2, getInteger(), this.defaultValue); + } + } + }; + + this.handlerWidth = new IntegerField("handlerWidth", HandlerInfo.DEFAULT_WIDTH) { + + @Override + public void onTextChange(String oldText) { + if (getInteger() != handlerInfo.getWidth()) { + handlerInfo.setHandlerDimensions( + handlerInfo.getHeight(), + getInteger(), + handlerInfo.getMaxRecipesPerPage()); + updatePatch(3, getInteger(), this.defaultValue); + } + } + }; + + this.useCustomScroll = new Button() { + + { + this.h = LINE_HEIGHT; + this.z = 2; + } + + public String getRenderLabel() { + return handlerInfo.getUseCustomScroll() ? "On" : "Off"; + } + + @Override + public boolean onButtonPress(boolean rightclick) { + handlerInfo.setUseCustomScroll(!handlerInfo.getUseCustomScroll()); + updatePatch(6, handlerInfo.getUseCustomScroll() ? 1 : 0, 0); + return true; + } + + }; + + this.w = WINDOW_WIDTH; + this.h = 10 + 13 * LINE_HEIGHT; + this.x = 10; + this.y = 50; + this.z = 1; + } + + private void updatePatch(int key, int value, int defaultValue) { + final String handlerKey = getHandlerID(handler); + + if (!patches.containsKey(handlerKey)) { + patches.put(handlerKey, new String[] { handlerKey, null, null, null, null, null, null }); + } + + if (value == defaultValue) { + patches.get(handlerKey)[key] = null; + } else { + patches.get(handlerKey)[key] = String.valueOf(value); + } + + saveHandlerInfoPatch(); + + if (NEIClientUtils.getGuiContainer() instanceof GuiReciperecipe) { + recipe.forceRefreshPage(); + } + + } + + private void drawKeyLabel(String keyLabel, int topShift) { + GuiDraw.drawString( + NEIClientUtils.cropText(GuiDraw.fontRenderer, keyLabel, LABEL_WIDTH), + this.x + INLINE_PADDING, + topShift, + 0x66555555, + false); + GuiDraw.drawString(":", this.x + INLINE_PADDING + LABEL_WIDTH, topShift, 0x66555555, false); + } + + private void drawDetail(String keyLabel, String valueLabel, int topShift, int spaceWidth) { + drawKeyLabel(keyLabel, topShift); + GuiDraw.drawString( + NEIClientUtils.cropText( + GuiDraw.fontRenderer, + valueLabel, + this.w - INLINE_PADDING * 2 - LABEL_WIDTH - spaceWidth), + this.x + INLINE_PADDING + LABEL_WIDTH + spaceWidth, + topShift, + 0xffffff); + } + + private void drawControl(String keyLabel, Widget field, int topShift, int spaceWidth) { + drawKeyLabel(keyLabel, topShift); + + field.x = this.x + INLINE_PADDING + LABEL_WIDTH + spaceWidth; + field.y = topShift - 4; + field.w = this.w - INLINE_PADDING * 2 - LABEL_WIDTH - spaceWidth; + } + + @Override + public void draw(int mx, int my) { + + if (this.handler != null) { + final int spaceWidth = GuiDraw.fontRenderer.getStringWidth(": "); + int topShift = this.y + BORDER_PADDING + 12 + 6; + + GL11.glColor4f(1F, 1F, 1F, 1F); + GL11.glScaled(1, 1, 2f); + GL11.glDisable(GL11.GL_DEPTH_TEST); + BG_TEXTURE.draw( + this.x, + this.y, + this.w, + this.h, + BORDER_PADDING, + BORDER_PADDING, + BORDER_PADDING, + BORDER_PADDING); + GuiDraw.drawRect( + this.x + INLINE_PADDING, + this.y + BORDER_PADDING, + this.w - INLINE_PADDING * 2, + 12, + 0x30000000); + GuiDraw.drawStringC("Debug Recipe Handler", this.x + this.w / 2, this.y + BORDER_PADDING + 2, 0xffffff); + + for (Map.Entry entry : getDetailsInfo().entrySet()) { + drawDetail(entry.getKey(), entry.getValue(), topShift, spaceWidth); + topShift += LINE_HEIGHT; + } + + drawControl("Order", this.order, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + drawControl("yShift", this.yShift, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + drawControl("Per Page", this.maxRecipesPerPage, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + drawControl("Height", this.handlerHeight, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + drawControl("Width", this.handlerWidth, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + drawControl("Use Custom Scroll", this.useCustomScroll, topShift, spaceWidth); + topShift += LINE_HEIGHT; + + GL11.glScaled(1, 1, 1 / 2f); + } + } + + private Map getDetailsInfo() { + final Map lines = new LinkedHashMap<>(); + final boolean isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream() + .map(pattern -> pattern.matcher(this.handler.getHandlerId())).anyMatch(Matcher::matches); + + lines.put("Name", this.handler.getRecipeName()); + lines.put("ID", this.handler.getOverlayIdentifier()); + lines.put("Key", this.handler.getHandlerId()); + lines.put("H.Hack", String.valueOf(isHeightHackApplied)); + lines.put("Mod Name", this.handlerInfo.getModName()); + lines.put("Mod ID", this.handlerInfo.getModId()); + + return lines; + } + + public void setVisible() { + if (showWidget && this.handler != null) { + LayoutManager.addWidget(this.order); + LayoutManager.addWidget(this.yShift); + LayoutManager.addWidget(this.handlerHeight); + LayoutManager.addWidget(this.handlerWidth); + LayoutManager.addWidget(this.maxRecipesPerPage); + LayoutManager.addWidget(this.useCustomScroll); + } + } + + @Override + public void update() { + final GuiContainer gui = NEIClientUtils.getGuiContainer(); + + if (showWidget && gui instanceof GuiRecipe recipe) { + + if (this.handler != recipe.getHandler()) { + this.handler = recipe.getHandler(); + this.handlerInfo = GuiRecipeTab.getHandlerInfo(handler); + + this.order.setText(String.valueOf(NEIClientConfig.getHandlerOrder(this.handler))); + this.yShift.setText(String.valueOf(this.handlerInfo.getYShift())); + this.handlerHeight.setText(String.valueOf(this.handlerInfo.getHeight())); + this.handlerWidth.setText(String.valueOf(this.handlerInfo.getWidth())); + this.maxRecipesPerPage.setText(String.valueOf(this.handlerInfo.getMaxRecipesPerPage())); + } + + } else { + this.handler = null; + this.handlerInfo = null; + showWidget = false; + } + + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) { + + if (this.handler != null) { + final int spaceWidth = GuiDraw.fontRenderer.getStringWidth(": "); + final int leftShift = this.x + INLINE_PADDING; + + if (mx >= leftShift && mx < this.x + WINDOW_WIDTH - INLINE_PADDING) { + int topShift = this.y + BORDER_PADDING + 12 + 6; + + for (Map.Entry entry : getDetailsInfo().entrySet()) { + if (my >= topShift && my < topShift + LINE_HEIGHT) { + + if (mx < leftShift + LABEL_WIDTH + spaceWidth) { + tooltip.add(String.valueOf(entry.getKey())); + } else { + tooltip.add(String.valueOf(entry.getValue())); + } + + break; + } + topShift += LINE_HEIGHT; + } + } + } + + return tooltip; + } + + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { + + if (NEIClientConfig.getBooleanSetting("inventory.guirecipe.handlerInfo") && showWidget + && keyCode == Keyboard.KEY_C + && NEIClientUtils.controlKey()) { + final int spaceWidth = GuiDraw.fontRenderer.getStringWidth(": "); + final Point mouse = GuiDraw.getMousePosition(); + + if (mouse.x >= this.x + INLINE_PADDING + LABEL_WIDTH + spaceWidth + && mouse.x < this.x + WINDOW_WIDTH - INLINE_PADDING) { + int topShift = this.y + BORDER_PADDING + 12 + 6; + + for (Map.Entry entry : getDetailsInfo().entrySet()) { + if (mouse.y >= topShift && mouse.y < topShift + LINE_HEIGHT) { + GuiScreen.setClipboardString(entry.getValue()); + return true; + } + topShift += LINE_HEIGHT; + } + } + } + + 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.getBooleanSetting("inventory.guirecipe.handlerInfo") && keyID == Keyboard.KEY_D + && NEIClientUtils.shiftKey()) { + showWidget = !showWidget; + return true; + } else if (this.handler != null) { + return this.order.focused() || this.yShift.focused() + || this.handlerHeight.focused() + || this.handlerWidth.focused() + || this.maxRecipesPerPage.focused(); + } + + return false; + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + if (this.handler != null + && new Rectangle4i(this.x + INLINE_PADDING, this.y + BORDER_PADDING, this.w - INLINE_PADDING * 2, 12) + .contains(mousex, mousey)) { + this.dragPoint = new Point(mousex, mousey); + } + } + + @Override + public boolean contains(int px, int py) { + return this.handler != null && super.contains(px, py); + } + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) { + this.dragPoint = null; + } + + @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 boolean handleClickExt(int mx, int my, int button) { + return false; + } + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) { + if (this.dragPoint != null) { + this.x -= this.dragPoint.x - mousex; + this.y -= this.dragPoint.y - mousey; + this.dragPoint.move(mousex, mousey); + } + } + + public void drawGuiPlaceholder(NEIRecipeWidget widget) { + if (!showWidget) return; + + NEIClientUtils.gl2DRenderContext(() -> { + + // background + GuiDraw.drawRect( + widget.x, + widget.y, + widget.w, + widget.h, + COLORS[widget.handlerRef.recipeIndex % COLORS.length]); + + // blue-line-top (grid-top) + GuiDraw.drawRect(widget.x + 14, widget.y + 5, widget.w - 38, 1, 0xff0000aa); + + // blue-line-bottom {grid-bottom} + GuiDraw.drawRect(widget.x + 14, widget.y + widget.h - 7, widget.w - 38, 1, 0xff0000aa); + + // blue-left (grid start) + GuiDraw.drawRect(widget.x + 24, widget.y + (widget.h - 16) / 2, 1, 16, 0xffaa00aa); + + // purple (before favorite) + GuiDraw.drawRect( + widget.x + Math.min(168, widget.w) - 27, + widget.y + widget.h - 6 - GuiRecipeButton.BUTTON_HEIGHT * 2 - 4, + GuiRecipeButton.BUTTON_WIDTH, + 1, + 0xffaa00aa); + + // green () + GuiDraw.drawRect( + widget.x + Math.min(168, widget.w) - 35, + widget.y + widget.h - 6 - GuiRecipeButton.BUTTON_HEIGHT - 3, + 20, + 1, + 0xff00aa00); + + // purple space before bottom grid + GuiDraw.drawRect( + widget.x + 14, + widget.y + widget.h - 7 - GuiRecipeButton.BUTTON_WIDTH / 2, + 38, + 1, + 0xffaa00aa); + + if (widget.handlerRef.handler instanceof TemplateRecipeHandler handler) { + int yShift = widget.getHandlerInfo().getYShift(); + + for (RecipeTransferRect rect : handler.transferRects) { + GuiDraw.drawRect( + widget.x + rect.rect.x, + widget.y + yShift + rect.rect.y, + rect.rect.width, + rect.rect.height, + 0x40ff0000); + } + } + + }); + } + + private static Map patches = new HashMap<>(); + + public static void loadHandlerInfoPatch() { + + ClientHandler.loadSettingsFile("handlers.patch", lines -> { + + for (String line : lines.collect(Collectors.toCollection(HashSet::new))) { + final String[] parts = line.split(","); + final String handler = parts[0]; + + if (GuiRecipeTab.handlerMap.containsKey(handler)) { + final HandlerInfo info = GuiRecipeTab.handlerMap.get(handler); + final int yShift = intOrDefault(parts[1], info.getYShift()); + final int height = intOrDefault(parts[2], info.getHeight()); + final int width = intOrDefault(parts[3], info.getWidth()); + final int maxRecipesPerPage = intOrDefault(parts[4], info.getMaxRecipesPerPage()); + final int order = intOrDefault(parts[5], NEIClientConfig.handlerOrdering.getOrDefault(handler, 0)); + final boolean useCustomScroll = intOrDefault(parts[6], info.getUseCustomScroll() ? 1 : 0) == 1; + + info.setYShift(yShift); + info.setHandlerDimensions(height, width, maxRecipesPerPage); + info.setUseCustomScroll(useCustomScroll); + NEIClientConfig.handlerOrdering.put(handler, order); + } + + patches.put(handler, parts); + } + + }); + + } + + private static void saveHandlerInfoPatch() { + final List lines = new ArrayList<>(); + + for (String[] line : patches.values()) { + lines.add(String.join(",", line)); + } + + final File path = new File(NEIClientConfig.configDir, "handlers.patch"); + + try (FileOutputStream output = new FileOutputStream(path)) { + IOUtils.writeLines(lines, "\n", output, StandardCharsets.UTF_8); + } catch (IOException e) {} + } + + private static int intOrDefault(String str, int defaultValue) { + if (str == null || str.equals("")) return defaultValue; + try { + return Integer.parseInt(str); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + private static String getHandlerID(IRecipeHandler handler) { + + if (GuiRecipeTab.handlerMap.containsKey(handler.getHandlerId())) { + return handler.getHandlerId(); + } else if (handler instanceof TemplateRecipeHandler) { + return handler.getOverlayIdentifier(); + } + + return null; + } + +} diff --git a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java index 577d930c..261bb38a 100644 --- a/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java @@ -50,7 +50,7 @@ public class GuiCraftingRecipe extends GuiRecipe { final ArrayList handlers = getCraftingHandlers(outputId, results); if (!handlers.isEmpty()) { - final GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers, "recipeId".equals(outputId)); + final GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers); if (open) { @@ -147,9 +147,8 @@ public class GuiCraftingRecipe extends GuiRecipe { return null; } - private GuiCraftingRecipe(ArrayList handlers, boolean limitToOneRecipe) { + private GuiCraftingRecipe(ArrayList handlers) { super(NEIClientUtils.mc().currentScreen); - this.limitToOneRecipe = limitToOneRecipe; this.currenthandlers = handlers; } diff --git a/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java b/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java index 3c8ac936..557243d2 100644 --- a/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java +++ b/src/main/java/codechicken/nei/recipe/GuiFavoriteButton.java @@ -9,7 +9,6 @@ import java.util.Map; import java.util.Set; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; import org.lwjgl.opengl.GL11; @@ -116,7 +115,7 @@ public class GuiFavoriteButton extends GuiRecipeButton { return Recipe.of(this.handlerRef); } - public void lastKeyTyped(GuiRecipe gui, char keyChar, int keyID) { + public void lastKeyTyped(char keyChar, int keyID) { if (NEIClientConfig.isKeyHashDown("gui.bookmark") && NEIClientUtils.shiftKey()) { saveRecipeInBookmark(); @@ -125,7 +124,7 @@ public class GuiFavoriteButton extends GuiRecipeButton { } @Override - public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { hotkeys.put( NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH), translate("recipe.favorite.bookmark_recipe")); @@ -140,7 +139,7 @@ public class GuiFavoriteButton extends GuiRecipeButton { } @Override - public List handleTooltip(GuiRecipe gui, List currenttip) { + public List handleTooltip(List currenttip) { currenttip.add(translate("recipe.favorite")); return currenttip; @@ -161,7 +160,7 @@ public class GuiFavoriteButton extends GuiRecipeButton { } @Override - public boolean mouseScrolled(GuiRecipe gui, int scroll) { + public boolean mouseScrolled(int scroll) { if (this.selectedResult == null) return true; final List results = new ArrayList<>(this.recipe.getResults()); diff --git a/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java b/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java index 31fdbc9b..27e18b62 100644 --- a/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java +++ b/src/main/java/codechicken/nei/recipe/GuiOverlayButton.java @@ -106,17 +106,17 @@ public class GuiOverlayButton extends GuiRecipeButton { } @Override - public List handleTooltip(GuiRecipe gui, List currenttip) { + public List handleTooltip(List currenttip) { currenttip.add(NEIClientUtils.translate("recipe.overlay")); - if (!this.enabled && this.requireShiftForOverlayRecipe && this.canFillCraftingGrid) { + if (!this.enabled && requireShiftForOverlayRecipe() && canFillCraftingGrid()) { currenttip.set(currenttip.size() - 1, currenttip.get(currenttip.size() - 1) + GuiDraw.TOOLTIP_LINESPACE); currenttip.add( EnumChatFormatting.RED + NEIClientUtils.translate("recipe.overlay.mismatch") + EnumChatFormatting.RESET); } else if (this.missedMaterialsTooltipLineHandler != null) { - if ((!this.requireShiftForOverlayRecipe || NEIClientUtils.shiftKey()) && this.canFillCraftingGrid) { + if ((!requireShiftForOverlayRecipe() || NEIClientUtils.shiftKey()) && canFillCraftingGrid()) { this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.RED); } else { this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.GRAY); @@ -129,7 +129,7 @@ public class GuiOverlayButton extends GuiRecipeButton { } @Override - public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { if (requireShiftForOverlayRecipe()) { @@ -174,7 +174,7 @@ public class GuiOverlayButton extends GuiRecipeButton { protected void drawContent(Minecraft minecraft, int y, int x, boolean mouseOver) { DrawableResource icon = ICON_OVERLAY; - if (this.hasOverlay && (!this.requireShiftForOverlayRecipe || NEIClientUtils.shiftKey())) { + if (hasOverlay() && (!requireShiftForOverlayRecipe() || NEIClientUtils.shiftKey())) { icon = this.missedMaterialsTooltipLineHandler == null ? ICON_FILL : ICON_FILL_ERROR; } @@ -206,18 +206,19 @@ public class GuiOverlayButton extends GuiRecipeButton { } protected List ingredientsOverlay() { - List ingredients = this.handlerRef.handler.getIngredientStacks(this.handlerRef.recipeIndex); + final List ingredients = this.handlerRef.handler + .getIngredientStacks(this.handlerRef.recipeIndex); if (this.itemPresenceCache.size() != ingredients.size()) { this.itemPresenceCache.clear(); - if (this.canFillCraftingGrid) { + if (canFillCraftingGrid()) { this.itemPresenceCache.addAll(this.handlerRef.getPresenceOverlay(this.firstGui)); } else if (this.firstGui != null) { this.itemPresenceCache.addAll(presenceOverlay(ingredients)); } - List items = this.itemPresenceCache.stream().filter(state -> !state.isPresent()) + final List items = this.itemPresenceCache.stream().filter(state -> !state.isPresent()) .map(state -> state.getSlot().item).collect(Collectors.toList()); if (!items.isEmpty()) { @@ -236,7 +237,7 @@ public class GuiOverlayButton extends GuiRecipeButton { public void setRequireShiftForOverlayRecipe(boolean require) { this.requireShiftForOverlayRecipe = require; - this.enabled = this.hasOverlay && (this.requireShiftForOverlayRecipe || this.canFillCraftingGrid); + this.enabled = hasOverlay() && (this.requireShiftForOverlayRecipe || canFillCraftingGrid()); } public void setCanUseOverlayRenderer(boolean use) { @@ -263,7 +264,7 @@ public class GuiOverlayButton extends GuiRecipeButton { return Recipe.of(this.handlerRef); } - private List presenceOverlay(List ingredients) { + protected List presenceOverlay(List ingredients) { final List itemPresenceSlots = new ArrayList<>(); final List invStacks = this.firstGui.inventorySlots.inventorySlots.stream() .filter( @@ -289,9 +290,9 @@ public class GuiOverlayButton extends GuiRecipeButton { } public void overlayRecipe(boolean shift) { - if (!this.hasOverlay) return; + if (!hasOverlay()) return; - if (!this.requireShiftForOverlayRecipe || shift) { + if (!requireShiftForOverlayRecipe() || shift) { if (canFillCraftingGrid()) { this.handlerRef.fillCraftingGrid(this.firstGui, 0); } @@ -302,8 +303,7 @@ public class GuiOverlayButton extends GuiRecipeButton { } @Override - public void lastKeyTyped(GuiRecipe gui, char keyChar, int keyID) { - + public void lastKeyTyped(char keyChar, int keyID) { if (NEIClientConfig.isKeyHashDown("gui.bookmark") && NEIClientUtils.shiftKey()) { saveRecipeInBookmark(); } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipe.java b/src/main/java/codechicken/nei/recipe/GuiRecipe.java index 5d441675..4fe17e30 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipe.java @@ -1,6 +1,5 @@ package codechicken.nei.recipe; -import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; @@ -13,18 +12,17 @@ import java.util.regex.Matcher; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; import codechicken.nei.Button; import codechicken.nei.GuiNEIButton; import codechicken.nei.NEICPH; @@ -35,6 +33,7 @@ import codechicken.nei.RecipeSearchField; import codechicken.nei.RestartableTask; import codechicken.nei.SearchField; import codechicken.nei.VisiblityData; +import codechicken.nei.Widget; import codechicken.nei.api.IGuiContainerOverlay; import codechicken.nei.api.INEIGuiHandler; import codechicken.nei.api.IRecipeFilter; @@ -48,85 +47,62 @@ import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.guihook.IContainerTooltipHandler; import codechicken.nei.guihook.IGuiClientSide; import codechicken.nei.guihook.IGuiHandleMouseWheel; -import codechicken.nei.recipe.GuiRecipeButton.UpdateRecipeButtonsEvent; import codechicken.nei.recipe.Recipe.RecipeId; +import codechicken.nei.scroll.ScrollBar; +import codechicken.nei.scroll.ScrollBar.OverflowType; +import codechicken.nei.scroll.ScrollBar.ScrollPlace; +import codechicken.nei.scroll.ScrollContainer; import codechicken.nei.util.NEIMouseUtils; +import codechicken.nei.util.SlotInaccessible; public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOverlay, IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler, INEIGuiHandler { - // Background image calculations - private static final int BG_TOP_HEIGHT = 6; - private static final int BG_MIDDLE_HEIGHT = 154; - private static final int BG_BOTTOM_HEIGHT = 6; + private static final int BORDER_PADDING = 5; + private final DrawableResource BG_TEXTURE = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, 0, 176, 166) + .build(); - private static final int BG_TOP_Y = 0; - private static final int BG_MIDDLE_Y = BG_TOP_Y + BG_TOP_HEIGHT; - private static final int BG_BOTTOM_Y = BG_MIDDLE_Y + BG_MIDDLE_HEIGHT; - - // Button sizes - private static final int BORDER_PADDING = 6; private static final int BUTTON_WIDTH = 13; private static final int BUTTON_HEIGHT = 12; + protected static final ScrollBar VERTICAL_SCROLLBAR = new ScrollBar().setScrollbarSize(14) + .setOverflowType(OverflowType.AUTO).setScrollPlace(ScrollPlace.OUTSIDE) + .setTrackTexture(new DrawableBuilder("nei:textures/nei_sprites.png", 42, 90, 13, 21).build(), 9, 9) + .setThumbTexture(new DrawableBuilder("nei:textures/nei_sprites.png", 21, 96, 8, 9).build(), 3, 2) + .setThumbPadding(6); + public static final List recipeFilterers = new LinkedList<>(); - protected boolean limitToOneRecipe = false; protected AcceptsFollowingTooltipLineHandler acceptsFollowingTooltipLineHandler; - // Background image - final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT) - .build(); - final DrawableResource bgMiddle = new DrawableBuilder( - "nei:textures/gui/recipebg.png", - 0, - BG_MIDDLE_Y, - 176, - BG_MIDDLE_HEIGHT).build(); - final DrawableResource bgBottom = new DrawableBuilder( - "nei:textures/gui/recipebg.png", - 0, - BG_BOTTOM_Y, - 176, - BG_BOTTOM_HEIGHT).build(); - + // some mods reflect this properties public ArrayList currenthandlers = new ArrayList<>(); public int page; public int recipetype; private RecipeId recipeId; - public ContainerRecipe slotcontainer; public GuiContainer firstGui; public GuiScreen firstGuiGeneral; public GuiScreen prevGui; - public GuiButton nextpage; - public GuiButton prevpage; - private GuiButton nexttype; + private GuiButton nextpage; + private GuiButton prevpage; private GuiButton prevtype; + private GuiButton nexttype; - // some mods reflect this property - @Deprecated - private GuiOverlayButton[] overlayButtons = new GuiOverlayButton[0]; + protected String recipePageCacheKey = ""; - private final List recipeButtons = new ArrayList<>(); - private String recipePageCacheKey = ""; - - private final Rectangle area = new Rectangle(); private final GuiRecipeTabs recipeTabs; - private final GuiRecipeCatalyst guiRecipeCatalyst; + private final GuiRecipeCatalyst recipeCatalyst; private SearchRecipeHandler handler; private HandlerInfo handlerInfo; - private int yShift = 0; - protected static final RestartableTask updateFilter = new RestartableTask("NEI Recipe Filtering") { @Override public void execute() { final GuiScreen currentScreen = NEIClientUtils.mc().currentScreen; - if (currentScreen instanceof GuiRecipe) { - final GuiRecipe guiRecipe = (GuiRecipe) currentScreen; + if (currentScreen instanceof GuiRecipeguiRecipe) { final SearchRecipeHandler searchHandler = guiRecipe.handler; if (searchHandler != null && searchHandler.searchingAvailable()) { @@ -147,6 +123,7 @@ public abstract class GuiRecipe extends GuiContainer i guiRecipe.changePage(0); } + guiRecipe.recipePageCacheKey = ""; } } @@ -159,7 +136,7 @@ public abstract class GuiRecipe extends GuiContainer i @Override protected boolean noResults() { - GuiScreen currentScreen = NEIClientUtils.mc().currentScreen; + final GuiScreen currentScreen = NEIClientUtils.mc().currentScreen; return !(currentScreen instanceof GuiRecipe) || ((GuiRecipe) currentScreen).numRecipes() > 0; } @@ -176,14 +153,14 @@ public abstract class GuiRecipe extends GuiContainer i public boolean onButtonPress(boolean rightclick) { if (rightclick) return false; - if (searchField.isVisible()) { - searchField.setText(""); - searchField.setFocus(false); - searchField.setVisible(false); + if (GuiRecipe.searchField.isVisible()) { + GuiRecipe.searchField.setText(""); + GuiRecipe.searchField.setFocus(false); + GuiRecipe.searchField.setVisible(false); state = 0; } else { - searchField.setVisible(true); - searchField.setFocus(true); + GuiRecipe.searchField.setVisible(true); + GuiRecipe.searchField.setFocus(true); state = 2; } @@ -200,15 +177,22 @@ public abstract class GuiRecipe extends GuiContainer i protected GuiRecipe(GuiScreen prevgui) { super(new ContainerRecipe()); - recipeTabs = new GuiRecipeTabs(this); - guiRecipeCatalyst = new GuiRecipeCatalyst(this); - slotcontainer = (ContainerRecipe) inventorySlots; + this.recipeTabs = new GuiRecipeTabs() { + + @Override + protected void setRecipePage(int recipetype) { + GuiRecipe.this.setRecipePage(recipetype); + } + + }; + this.recipeCatalyst = new GuiRecipeCatalyst(); + this.slotcontainer = (ContainerRecipe) this.inventorySlots; this.prevGui = prevgui; this.firstGuiGeneral = prevgui; - if (prevgui instanceof GuiContainer) { - this.firstGui = (GuiContainer) prevgui; + if (prevgui instanceof GuiContainer firstGui) { + this.firstGui = firstGui; } if (prevgui instanceof IGuiContainerOverlay gui) { @@ -217,16 +201,6 @@ public abstract class GuiRecipe extends GuiContainer i } } - /** Changes the GUI mode to only display one recipe at a time, e.g. for tooltip usage */ - public void limitToOneRecipe() { - limitToOneRecipe = true; - } - - /** Checks if the gui only displays one recipe at a time, e.g. for tooltip usage */ - public boolean isLimitedToOneRecipe() { - return limitToOneRecipe; - } - /** * Many old mods assumed a fixed NEI window height of {@code 166} pixels. Now that this is no longer the case, their * tooltip and click zone handling is broken. This helper class fixes these old mods by hacking the {@link #height} @@ -247,7 +221,6 @@ public abstract class GuiRecipe extends GuiContainer i private final int trueHeight; private final int trueGuiTop; - private final GuiScreen trueGui; private CompatibilityHacks() { trueHeight = height; @@ -256,34 +229,38 @@ public abstract class GuiRecipe extends GuiContainer i isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream() .map(pattern -> pattern.matcher(handler.original.getHandlerId())).anyMatch(Matcher::matches); if (isHeightHackApplied) { - // guiTop is the top edge of the recipe screen on the y-axis. Old recipe handlers expect a single paging - // widget at the top and at the bottom of the recipe screen with a height of 16px each, but GTNH NEI - // moved the bottom paging widget to the top following JEI's design, increasing the "forbidden" zone at - // the top to 32px. To fix these old recipe handlers we move guiTop down 16px so that they can keep + // guiTop is the top edge of the recipe screen on the y-axis. Old recipe + // handlers expect a single paging + // widget at the top and at the bottom of the recipe screen with a height of + // 16px each, but GTNH NEI + // moved the bottom paging widget to the top following JEI's design, increasing + // the "forbidden" zone at + // the top to 32px. To fix these old recipe handlers we move guiTop down 16px so + // that they can keep // working with the old 16px gap. guiTop += 16; - // The old NEI recipe screen had a fixed width and height and was always centered on the screen. Legacy - // recipe handlers use the calculation ((height - 166) / 2) to compute the y-value of the top edge of - // the NEI window. GTNH NEI changes the layout so that the recipe screen length now has a flexible - // length and is no longer centered vertically. In order for the top-of-screen calculation to return the - // correct result, we have to hack the height field with an inverse of the calculation using the actual + // The old NEI recipe screen had a fixed width and height and was always + // centered on the screen. Legacy + // recipe handlers use the calculation ((height - 166) / 2) to compute the + // y-value of the top edge of + // the NEI window. GTNH NEI changes the layout so that the recipe screen length + // now has a flexible + // length and is no longer centered vertically. In order for the top-of-screen + // calculation to return the + // correct result, we have to hack the height field with an inverse of the + // calculation using the actual // top of the recipe screen stored in guiTop. height = (2 * guiTop) + 166; // For reference, in case we ever need to modify width as well: - // the legacy calculation used for width is ((width - 176) / 2), which should evaluate to be equal to - // guiWidth (the x-value of the left edge of the NEI recipe screen). So if we wanted to override width + // the legacy calculation used for width is ((width - 176) / 2), which should + // evaluate to be equal to + // guiWidth (the x-value of the left edge of the NEI recipe screen). So if we + // wanted to override width // as well, we'd do this: // width = (2 * guiWidth) + 176; } - - // Recipe handlers may assume the current screen is the GuiRecipe object, which is not the case in - // recipe tooltips drawn on the bookmarks panel with the main inventory open. - trueGui = NEIClientUtils.mc().currentScreen; - if (limitToOneRecipe) { - NEIClientUtils.mc().currentScreen = GuiRecipe.this; - } } @Override @@ -291,53 +268,38 @@ public abstract class GuiRecipe extends GuiContainer i guiTop = trueGuiTop; height = trueHeight; - // Only restore currentScreen if it hasn't been altered by a recipe handler (for example through - // Minecraft#displayGuiScreen). - if (limitToOneRecipe && NEIClientUtils.mc().currentScreen == GuiRecipe.this) { - NEIClientUtils.mc().currentScreen = trueGui; - } - isHeightHackApplied = false; } } + private ScrollContainer container = new ScrollContainer(); + + @Override public void initGui() { - xSize = 176; - ySize = Math.min(Math.max(height - 68, 166), 370); - if (!this.limitToOneRecipe) { - super.initGui(); - } else { - this.guiLeft = (this.width - this.xSize) / 2; - this.ySize = this.getWidgetSize().height; - this.mc = NEIClientUtils.mc(); - this.fontRendererObj = mc.fontRenderer; - ScaledResolution scaledresolution = new ScaledResolution( - this.mc, - this.mc.displayWidth, - this.mc.displayHeight); - this.width = scaledresolution.getScaledWidth(); - this.height = scaledresolution.getScaledHeight(); + final int tabHeight = GuiRecipeTabs.getTabHeight(); + this.xSize = 176; + this.ySize = Math + .min(this.height - 22 - 22 - tabHeight, NEIClientConfig.getIntSetting("inventory.guirecipe.maxHeight")); + + super.initGui(); + + this.guiTop = Math.max(22 - 3 + tabHeight, (this.height - this.ySize) / 2); + + if (this.handler == null) { + setRecipePage(this.recipetype); } - guiTop = (height - ySize) / 2 + 10; + final int rightButtonX = this.guiLeft + this.xSize - BORDER_PADDING - BUTTON_WIDTH + 1; + final int leftButtonX = this.guiLeft + BORDER_PADDING; - if (handler == null) { - setRecipePage(recipetype); - } - - checkYShift(); - - final int rightButtonX = guiLeft + xSize - BORDER_PADDING - BUTTON_WIDTH; - final int leftButtonX = guiLeft + BORDER_PADDING; - - nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, BUTTON_WIDTH, BUTTON_HEIGHT, "<") { + this.prevtype = new GuiNEIButton(0, leftButtonX, guiTop + 3, BUTTON_WIDTH, BUTTON_HEIGHT, "<") { @Override public void mouseReleased(int mouseX, int mouseY) { prevType(); } }; - prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, BUTTON_WIDTH, BUTTON_HEIGHT, ">") { + this.nexttype = new GuiNEIButton(1, rightButtonX, guiTop + 3, BUTTON_WIDTH, BUTTON_HEIGHT, ">") { @Override public void mouseReleased(int mouseX, int mouseY) { @@ -345,14 +307,14 @@ public abstract class GuiRecipe extends GuiContainer i } }; - nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, BUTTON_WIDTH, BUTTON_HEIGHT, "<") { + this.prevpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, BUTTON_WIDTH, BUTTON_HEIGHT, "<") { @Override public void mouseReleased(int mouseX, int mouseY) { prevPage(); } }; - prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, BUTTON_WIDTH, BUTTON_HEIGHT, ">") { + this.nextpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, BUTTON_WIDTH, BUTTON_HEIGHT, ">") { @Override public void mouseReleased(int mouseX, int mouseY) { @@ -360,100 +322,66 @@ public abstract class GuiRecipe extends GuiContainer i } }; - toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 76, 10, 10).build(); + GuiRecipe.toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 76, 10, 10).build(); + GuiRecipe.toggleSearch.w = GuiRecipe.toggleSearch.h = 12; + GuiRecipe.toggleSearch.x = this.guiLeft + BORDER_PADDING + BUTTON_WIDTH; + GuiRecipe.toggleSearch.y = this.guiTop + 17; - this.buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage)); - this.recipeButtons.clear(); + GuiRecipe.searchField.y = this.guiTop + 16; + GuiRecipe.searchField.x = this.guiLeft + BORDER_PADDING + BUTTON_WIDTH + GuiRecipe.toggleSearch.w; + GuiRecipe.searchField.w = this.xSize - (BORDER_PADDING + BUTTON_WIDTH) * 2 + 1 - GuiRecipe.toggleSearch.w - 45; + GuiRecipe.searchField.h = 14; + + this.buttonList.addAll(Arrays.asList(this.prevtype, this.nexttype, this.prevpage, this.nextpage)); this.recipePageCacheKey = ""; if (currenthandlers.size() == 1) { - nexttype.visible = false; - prevtype.visible = false; + this.prevtype.visible = false; + this.nexttype.visible = false; } - recipeTabs.initLayout(); - refreshPage(); + this.recipeTabs.update(this); } private void updateRecipePage() { final List indices = getRecipeIndices(); - final String cacheKey = indices.isEmpty() ? "" + final String cacheKey = indices.isEmpty() ? "empty" : handlerInfo.getHandlerName() + ":" + indices.get(0) + ":" + indices.get(indices.size() - 1); if (!cacheKey.equals(this.recipePageCacheKey)) { this.recipePageCacheKey = cacheKey; - for (final int recipeIndex : indices) { - for (PositionedStack pStack : handler.original.getIngredientStacks(recipeIndex)) { - pStack.setPermutationToRender(pStack.getFilteredPermutations().get(0)); + final boolean recipeGrow = this.handlerInfo.getUseCustomScroll() + && this.handlerInfo.getMaxRecipesPerPage() <= 1; + final List widgets = new ArrayList<>(); + int shiftY = 0; + + for (int recipeIndex : indices) { + final NEIRecipeWidget widget = RecipeHandlerRef.of(this.handler.original, recipeIndex) + .getRecipeWidget(); + widget.setLocation(Math.max(0, (this.container.w - widget.w) / 2), shiftY); + + if (recipeGrow) { + widget.h = Math.min( + this.handlerInfo.getHeight() + this.handlerInfo.getYShift(), + this.container.getVisibleHeight()); } + + widgets.add(widget); + shiftY += widget.h; } - final int xOffset = (limitToOneRecipe ? 0 : guiLeft) + xSize - BORDER_PADDING; - final int yOffset = (limitToOneRecipe ? -BUTTON_HEIGHT : guiTop - 18) + getRefIndexPosition(0).y; - final int height = handlerInfo.getHeight() - yShift; - final boolean showFavorites = NEIClientConfig.favoritesEnabled() && handlerInfo.getShowFavoritesButton(); - final boolean showOverlay = handlerInfo.getShowOverlayButton(); - final UpdateRecipeButtonsEvent.Pre preEvent = new UpdateRecipeButtonsEvent.Pre( - this, - xOffset, - yOffset, - height, - handlerInfo); - List buttons = new ArrayList<>(); + this.container.setWidgets(widgets); - if (MinecraftForge.EVENT_BUS.post(preEvent)) { - buttons = preEvent.buttonList; + if (this.handlerInfo.getUseCustomScroll()) { + this.container.setVerticalScroll(null); + } else if (this.container.w == this.xSize - 6) { + this.container.setVerticalScroll(VERTICAL_SCROLLBAR); } 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; - } - - int x = xOffset - GuiRecipeButton.BUTTON_WIDTH; - int y = yOffset + height * (refIndex + 1); - if (showOverlay) { - buttons.add( - new GuiOverlayButton( - firstGui, - RecipeHandlerRef.of(handler.original, recipeIndex), - x, - y)); - y -= GuiRecipeButton.BUTTON_HEIGHT + 1; - } - if (showFavorites) { - buttons.add(new GuiFavoriteButton(RecipeHandlerRef.of(handler.original, recipeIndex), x, y)); - } - - } - - if (this.equals(this.mc.currentScreen)) { - UpdateRecipeButtonsEvent.Post postEvent = new UpdateRecipeButtonsEvent.Post(this, buttons); - MinecraftForge.EVENT_BUS.post(postEvent); - buttons = postEvent.buttonList; - } + this.container.setVerticalScroll( + ScrollBar.defaultVerticalBar().setOverflowType(OverflowType.OVERLAY) + .setScrollPlace(ScrollPlace.OUTSIDE)); } - - if (!showFavorites) { - buttons.removeIf(GuiFavoriteButton.class::isInstance); - } - - if (!showOverlay) { - buttons.removeIf(GuiOverlayButton.class::isInstance); - } - - /** compatibility with old format */ - this.overlayButtons = buttons.stream().filter(GuiOverlayButton.class::isInstance) - .toArray(GuiOverlayButton[]::new); - - this.buttonList.removeIf(this.recipeButtons::contains); - this.recipeButtons.clear(); - - this.recipeButtons.addAll(buttons); - this.buttonList.addAll(buttons); } } @@ -478,11 +406,7 @@ public abstract class GuiRecipe extends GuiContainer i } public static ItemFilter getSearchItemFilter() { - return searchField.getFilter(); - } - - private void checkYShift() { - yShift = handlerInfo == null ? 0 : handlerInfo.getYShift(); + return GuiRecipe.searchField.getFilter(); } public void setRecipePage(int idx) { @@ -490,32 +414,20 @@ public abstract class GuiRecipe extends GuiContainer i } public void setRecipePage(int idx, int refIndex) { - recipetype = (currenthandlers.size() + idx) % currenthandlers.size(); + this.recipetype = (this.currenthandlers.size() + idx) % this.currenthandlers.size(); + this.handler = new SearchRecipeHandler<>(this.currenthandlers.get(this.recipetype)); + this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.handler.original); - handler = new SearchRecipeHandler<>(currenthandlers.get(recipetype)); - handlerInfo = GuiRecipeTab.getHandlerInfo(handler.original); + GuiRecipe.searchField.setText(""); + GuiRecipe.searchField.setVisible(false); + GuiRecipe.toggleSearch.state = 0; - if (!limitToOneRecipe) { - searchField.setText(""); - searchField.setVisible(false); - toggleSearch.state = 0; - } - - page = Math.min(Math.max(0, refIndex), this.numRecipes() - 1) / getRecipesPerPage(); + this.container.setVerticalScrollOffset(0); + this.container.setHorizontalScrollOffset(0); + this.page = Math.min(Math.max(0, refIndex), this.numRecipes() - 1) / getRecipesPerPage(); changePage(0); - recipeTabs.calcPageNumber(); - checkYShift(); - } - public List getRecipeButtons() { - return Collections.unmodifiableList(this.recipeButtons); - } - - public List getOverlayButtons() { - return Collections.unmodifiableList( - Arrays.asList( - this.recipeButtons.stream().filter(GuiOverlayButton.class::isInstance) - .toArray(GuiButton[]::new))); + this.recipeTabs.update(this); } public int openTargetRecipe(RecipeId recipeId) { @@ -525,9 +437,9 @@ public abstract class GuiRecipe extends GuiContainer i this.recipeId = recipeId; if (this.recipeId != null) { - for (int j = 0; j < currenthandlers.size(); j++) { - H localHandler = currenthandlers.get(j); - HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler); + for (int j = 0; j < this.currenthandlers.size(); j++) { + final H localHandler = this.currenthandlers.get(j); + final HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler); if (localHandlerInfo.getHandlerName().equals(this.recipeId.getHandleName())) { recipetype = j; @@ -550,111 +462,123 @@ public abstract class GuiRecipe extends GuiContainer i } public Recipe getFocusedRecipe() { - final List indices = getRecipeIndices(); + final Point mouse = GuiDraw.getMousePosition(); + final Widget activeWidget = this.container.getWidgetUnderMouse(mouse.x, mouse.y); - for (int refIndex = 0; refIndex < indices.size(); refIndex++) { - final int recipeIndex = indices.get(refIndex); - if (recipeInFocus(refIndex, recipeIndex)) { - return Recipe.of(handler.original, recipeIndex); - } + if (activeWidget instanceof NEIRecipeWidget recipeWidget && recipeWidget.isFocusedRecipe(mouse.x, mouse.y)) { + return recipeWidget.getRecipe(); } return null; } - protected boolean recipeInFocus(int refIndex, int recipeIndex) { - final PositionedStack result = handler.original.getResultStack(recipeIndex); - if (result != null && isMouseOver(result, refIndex)) { - return true; - } + public boolean isMouseOver(PositionedStack stack, int refIndex) { + final Point mouse = GuiDraw.getMousePosition(); + final Widget activeWidget = this.container.getWidgetUnderMouse(mouse.x, mouse.y); - final List stacks = handler.original.getOtherStacks(recipeIndex); - for (PositionedStack stack : stacks) { - if (isMouseOver(stack, refIndex)) { - return true; + if (activeWidget instanceof NEIRecipeWidget recipeWidget) { + final PositionedStack hovered = recipeWidget.getPositionedStackMouseOver(mouse.x, mouse.y); + + if (hovered != null) { + return stack.relx == hovered.relx && stack.rely == hovered.rely; } } return false; } - public boolean isMouseOver(PositionedStack stack, int refIndex) { - Point p = getRefIndexPosition(refIndex); - Point mousepos = GuiDraw.getMousePosition(); - Slot stackSlot = slotcontainer.getSlotWithStack(stack, p.x, p.y); - Slot mouseoverSlot = getSlotAtPosition(mousepos.x, mousepos.y); + @Override + public Slot getSlotAtPosition(int mousex, int mousey) { + final Widget activeWidget = this.container.getWidgetUnderMouse(mousex, mousey); + final ContainerRecipe slotcontainer = (ContainerRecipe) inventorySlots; + slotcontainer.setActiveStack(null); - return stackSlot == mouseoverSlot; + if (activeWidget instanceof NEIRecipeWidget recipeWidget) { + final PositionedStack hovered = recipeWidget.getPositionedStackMouseOver(mousex, mousey); + + if (hovered != null) { + slotcontainer.setActiveStack(hovered.item); + return new SlotInaccessible(hovered.item, hovered.relx, hovered.rely); + } + } + + final PositionedStack activeStack = this.recipeCatalyst.getPositionedStackMouseOver(mousex, mousey); + + if (activeStack != null) { + slotcontainer.setActiveStack(activeStack.item); + return new SlotInaccessible(activeStack.item, activeStack.relx, activeStack.rely); + } + + return null; } public String getHandlerName() { - return handlerInfo.getHandlerName(); + return this.handlerInfo.getHandlerName(); } public H getHandler() { - return handler.original; + return this.handler.original; } public List getRecipeIndices() { final int recipesPerPage = getRecipesPerPage(); - final int minIndex = page * recipesPerPage; - final int maxIndex = Math.min(this.numRecipes(), (page + 1) * recipesPerPage); + final int minIndex = this.page * recipesPerPage; + final int maxIndex = Math.min(this.numRecipes(), (this.page + 1) * recipesPerPage); final List range = new ArrayList<>(); for (int index = minIndex; index < maxIndex; index++) { - range.add(handler.ref(index)); + range.add(this.handler.ref(index)); } return range; } private int numRecipes() { - return handler == null ? 0 : handler.numRecipes(); + return this.handler == null ? 0 : this.handler.numRecipes(); } @Override public void keyTyped(char c, int i) { - if (searchField.isVisible() && searchField.focused() && searchField.handleKeyPress(i, c)) { + if (GuiRecipe.searchField.isVisible() && GuiRecipe.searchField.focused() + && GuiRecipe.searchField.handleKeyPress(i, c)) { return; } if (i == Keyboard.KEY_ESCAPE) { // esc - mc.displayGuiScreen(firstGuiGeneral); + this.mc.displayGuiScreen(getFirstScreenGeneral()); NEICPH.sendRequestContainer(); return; } - if (searchField.isVisible() && searchField.focused()) { - searchField.lastKeyTyped(i, c); + if (GuiRecipe.searchField.isVisible() && GuiRecipe.searchField.focused()) { + GuiRecipe.searchField.lastKeyTyped(i, c); return; } + if (this.recipeCatalyst.isShowWidget()) { + if (this.recipeCatalyst.handleKeyPress(i, c)) { + return; + } + + this.recipeCatalyst.lastKeyTyped(i, c); + } + + if (this.container.handleKeyPress(i, c)) { + return; + } + + this.container.lastKeyTyped(i, c); + if (GuiContainerManager.getManager(this).lastKeyTyped(i, c)) { return; } - try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (int recipeIndex : getRecipeIndices()) { - if (handler.original.keyTyped(this, c, i, recipeIndex)) { - return; - } - } - - Point mouse = GuiDraw.getMousePosition(); - - for (GuiRecipeButton button : this.recipeButtons) { - if (button.contains(mouse.x, mouse.y)) { - button.lastKeyTyped(this, c, i); - } - } - } - if (i == mc.gameSettings.keyBindInventory.getKeyCode()) { - mc.displayGuiScreen(firstGuiGeneral); + this.mc.displayGuiScreen(getFirstScreenGeneral()); NEICPH.sendRequestContainer(); } else if (NEIClientConfig.isKeyHashDown("gui.back")) { - mc.displayGuiScreen(prevGui); + this.mc.displayGuiScreen(this.prevGui); } else if (NEIClientConfig.isKeyHashDown("gui.prev_machine")) { prevType(); } else if (NEIClientConfig.isKeyHashDown("gui.next_machine")) { @@ -669,25 +593,27 @@ public abstract class GuiRecipe extends GuiContainer i @Override protected void mouseClicked(int mousex, int mousey, int button) { - if (!limitToOneRecipe && handler != null && handler.searchingAvailable()) { - if (toggleSearch.contains(mousex - guiLeft, mousey - guiTop)) { - toggleSearch.handleClick(mousex - guiLeft, mousey - guiTop, button); - } else if (searchField.contains(mousex - guiLeft, mousey - guiTop)) { - searchField.handleClick(mousex - guiLeft, mousey - guiTop, button); + if (this.handler != null && this.handler.searchingAvailable()) { + if (GuiRecipe.toggleSearch.contains(mousex, mousey)) { + GuiRecipe.toggleSearch.handleClick(mousex, mousey, button); + } else if (GuiRecipe.searchField.contains(mousex, mousey)) { + GuiRecipe.searchField.handleClick(mousex, mousey, button); } else { - searchField.onGuiClick(mousex - guiLeft, mousey - guiTop); + GuiRecipe.searchField.onGuiClick(mousex, mousey); } } + if (this.recipeCatalyst.isShowWidget() && this.recipeCatalyst.handleClick(mousex, mousey, button)) { + return; + } + try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (int recipeIndex : getRecipeIndices()) { - if (handler.original.mouseClicked(this, button, recipeIndex)) { - return; - } + if (this.container.handleClick(mousex, mousey, button)) { + return; } } - if (recipeTabs.mouseClicked(mousex, mousey, button)) { + if (this.recipeTabs.mouseClicked(mousex, mousey, button)) { return; } @@ -695,33 +621,59 @@ public abstract class GuiRecipe extends GuiContainer i } @Override - public void mouseScrolled(int scroll) { - // Height hacking is not necessary here since mouse scrolling is a new feature, added in - // GTNH NEI. So no old mods will use this. Though not hacking the height here does mean that - // the value of the height field will be different from in other mouseover methods, which - // could be confusing... + protected void mouseClickMove(int mousex, int mousey, int button, long heldTime) { + if (this.recipeCatalyst.isShowWidget()) { + this.recipeCatalyst.mouseDragged(mousex, mousey, button, heldTime); + } - // First, invoke scroll handling over recipe handler tabbar. Makes sure it is not overwritten by recipe - // handler-specific scroll behavior. - if (recipeTabs.mouseScrolled(scroll)) return; + this.container.mouseDragged(mousex, mousey, button, heldTime); + super.mouseClickMove(mousex, mousey, button, heldTime); + } - try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - Point mouse = GuiDraw.getMousePosition(); + @Override + protected void mouseMovedOrUp(int mousex, int mousey, int state) { - for (GuiRecipeButton button : this.recipeButtons) { - if (button.contains(mouse.x, mouse.y) && button.mouseScrolled(this, scroll)) { - return; - } + if (state != -1) { + + if (this.recipeCatalyst.isShowWidget()) { + this.recipeCatalyst.mouseUp(mousex, mousey, state); } - for (int recipeIndex : getRecipeIndices()) { - if (handler.original.mouseScrolled(this, scroll, recipeIndex)) { - return; - } + this.container.mouseUp(mousex, mousey, state); + } + + super.mouseMovedOrUp(mousex, mousey, state); + } + + @Override + public void mouseScrolled(int scroll) { + // Height hacking is not necessary here since mouse scrolling is a new feature, + // added in + // GTNH NEI. So no old mods will use this. Though not hacking the height here + // does mean that + // the value of the height field will be different from in other mouseover + // methods, which + // could be confusing... + + // First, invoke scroll handling over recipe handler tabbar. Makes sure it is + // not overwritten by recipe + // handler-specific scroll behavior. + if (this.recipeTabs.mouseScrolled(scroll)) return; + + final Point mouse = GuiDraw.getMousePosition(); + + if (this.recipeCatalyst.isShowWidget() && this.recipeCatalyst.onMouseWheel(scroll, mouse.x, mouse.y)) { + return; + } + + try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { + if (this.container.onMouseWheel(scroll, mouse.x, mouse.y)) { + return; } } - // If shift is held, try switching to the next recipe handler. Replicates the GuiRecipeTabs.mouseScrolled() + // If shift is held, try switching to the next recipe handler. Replicates the + // GuiRecipeTabs.mouseScrolled() // without the checking for the cursor being inside the tabbar. if (NEIClientUtils.shiftKey()) { if (scroll < 0) { @@ -733,8 +685,9 @@ public abstract class GuiRecipe extends GuiContainer i return; } - // Finally, if nothing else has handled scrolling, try changing to the next recipe page. - if (new Rectangle(guiLeft, guiTop, xSize, ySize).contains(GuiDraw.getMousePosition())) { + // Finally, if nothing else has handled scrolling, try changing to the next + // recipe page. + if (new Rectangle(this.guiLeft, this.guiTop, this.xSize, this.ySize).contains(mouse)) { if (scroll > 0) { prevPage(); } else { @@ -746,44 +699,45 @@ public abstract class GuiRecipe extends GuiContainer i @Override public void updateScreen() { super.updateScreen(); - onUpdate(); - } - public void onUpdate() { - handler.original.onUpdate(); + this.container.x = this.guiLeft + 3; + this.container.y = this.guiTop + 32; - if (limitToOneRecipe) { - refreshSlots(); - } else { - refreshPage(); - } + this.container.w = Math.max(this.xSize - 6, this.handlerInfo.getWidth()); + this.container.h = this.ySize - 32 - 5; + + this.handler.original.onUpdate(); + refreshPage(); + this.container.update(); + + this.recipeCatalyst.setAvailableHeight(this.container.h); + this.recipeCatalyst.update(); + this.recipeCatalyst.y = this.guiTop; + this.recipeCatalyst.x = this.guiLeft - this.recipeCatalyst.w + 6; } @Override public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { - try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (int recipeIndex : getRecipeIndices()) { - currenttip = handler.original.handleTooltip(this, currenttip, recipeIndex); - } - - for (GuiRecipeButton button : this.recipeButtons) { - if (button.contains(mousex, mousey)) { - currenttip = button.handleTooltip(this, currenttip); - } - } + if (this.recipeCatalyst.isShowWidget()) { + currenttip = this.recipeCatalyst.handleTooltip(mousex, mousey, currenttip); } - recipeTabs.handleTooltip(mousex, mousey, currenttip); + try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { + currenttip = this.container.handleTooltip(mousex, mousey, currenttip); + } - if (currenttip.isEmpty() && searchField.isVisible() - && new Rectangle(searchField.x + searchField.w, 15, 44, 16) - .contains(mousex - guiLeft, mousey - guiTop)) { + this.recipeTabs.handleTooltip(mousex, mousey, currenttip); - final String s = String.format("%d/%d", page + 1, (this.numRecipes() - 1) / getRecipesPerPage() + 1); + if (currenttip.isEmpty() && GuiRecipe.searchField.isVisible() + && new Rectangle(GuiRecipe.searchField.x + GuiRecipe.searchField.w, 15, 44, 16) + .contains(mousex - this.guiLeft, mousey - this.guiTop)) { - if (fontRendererObj.getStringWidth(s) >= 45) { - currenttip.add(s); + final String pageInfo = String + .format("%d/%d", page + 1, Math.max(1, this.numRecipes() - 1) / getRecipesPerPage() + 1); + + if (this.fontRendererObj.getStringWidth(pageInfo) >= 45) { + currenttip.add(pageInfo); } } @@ -793,33 +747,17 @@ public abstract class GuiRecipe extends GuiContainer i @Override public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip) { + final Widget activeWidget = this.container.getWidgetUnderMouse(mousex, mousey); - List indices = getRecipeIndices(); - - try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (int recipeIndex : indices) { - currenttip = handler.original.handleItemTooltip(this, itemstack, currenttip, recipeIndex); - } + if (activeWidget instanceof NEIRecipeWidget recipeWidget) { + currenttip = recipeWidget.handleItemTooltip(itemstack, mousex, mousey, currenttip); } if (NEIClientConfig.showCycledIngredientsTooltip() && itemstack != null) { PositionedStack hovered = null; - outer: for (int refIndex = 0; refIndex < indices.size(); refIndex++) { - final int recipeIndex = indices.get(refIndex); - - List> stackGroups = Arrays.asList( - handler.original.getIngredientStacks(recipeIndex), - handler.original.getOtherStacks(recipeIndex)); - - for (List group : stackGroups) { - for (PositionedStack pStack : group) { - if (isMouseOver(pStack, refIndex)) { - hovered = pStack; - break outer; - } - } - } + if (activeWidget instanceof NEIRecipeWidget recipeWidget) { + hovered = recipeWidget.getPositionedStackMouseOver(mousex, mousey); } if (hovered == null || hovered.items.length <= 1) { @@ -845,12 +783,12 @@ public abstract class GuiRecipe extends GuiContainer i @Override public Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys) { + if (this.recipeCatalyst.isShowWidget()) { + hotkeys = this.recipeCatalyst.handleHotkeys(mousex, mousey, hotkeys); + } + try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - for (GuiRecipeButton button : this.recipeButtons) { - if (button.contains(mousex, mousey)) { - hotkeys = button.handleHotkeys(gui, mousex, mousey, hotkeys); - } - } + hotkeys = this.container.handleHotkeys(mousex, mousey, hotkeys); } if (this.acceptsFollowingTooltipLineHandler != null) { @@ -864,11 +802,6 @@ public abstract class GuiRecipe extends GuiContainer i return hotkeys; } - @Override - public List handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List currenttip) { - return currenttip; - } - private void nextPage() { changePage(1); } @@ -888,6 +821,7 @@ public abstract class GuiRecipe extends GuiContainer i protected void changePage(int shift) { final int recipesPerPage = getRecipesPerPage(); final int numRecipes = this.numRecipes(); + final int oldPage = this.page; if (numRecipes > 0) { final int numPages = (int) Math.ceil(numRecipes / (float) recipesPerPage); @@ -896,265 +830,147 @@ public abstract class GuiRecipe extends GuiContainer i } else { this.page = 0; } + + if (this.page != oldPage) { + this.container.setVerticalScrollOffset(0); + this.container.setHorizontalScrollOffset(0); + } + + } + + public GuiRecipeCatalyst getRecipeCatalystWidget() { + return this.recipeCatalyst; + } + + public void forceRefreshPage() { + this.buttonList.removeIf(Arrays.asList(this.overlayButtons)::contains); + this.overlayButtons = new GuiOverlayButton[0]; + this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR); + this.recipePageCacheKey = ""; + refreshPage(); } public void refreshPage() { changePage(0); final int recipesPerPage = getRecipesPerPage(); final boolean multiplepages = this.numRecipes() > recipesPerPage; - final int numRecipes = Math.min(this.numRecipes() - (page * recipesPerPage), recipesPerPage); - area.width = handlerInfo.getWidth(); - area.height = handlerInfo.getHeight() * numRecipes; - area.x = guiLeft - 2; - area.y = guiTop - 4 + yShift; - checkYShift(); - - if (!limitToOneRecipe) { - RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2)); - toggleSearch.w = toggleSearch.h = 12; - toggleSearch.x = BORDER_PADDING + BUTTON_WIDTH; - toggleSearch.y = 17; - - searchField.y = 16; - searchField.x = BORDER_PADDING + BUTTON_WIDTH + toggleSearch.w - 1; - searchField.w = xSize - (BORDER_PADDING + BUTTON_WIDTH) * 2 + 1 - toggleSearch.w - 45; - searchField.h = 14; - } - - nextpage.enabled = prevpage.enabled = multiplepages; + this.prevpage.enabled = this.nextpage.enabled = multiplepages; + this.recipeCatalyst.setCatalysts(RecipeCatalysts.getRecipeCatalysts(this.handler.original)); updateRecipePage(); - refreshSlots(); - recipeTabs.refreshPage(); - } - - private void refreshSlots() { - slotcontainer.inventorySlots.clear(); - final List indices = getRecipeIndices(); - - for (int refIndex = 0; refIndex < indices.size(); refIndex++) { - int recipeIndex = indices.get(refIndex); - Point p = getRefIndexPosition(refIndex); - // Legacy recipe handlers only expect a single paging widget at the top of the recipe screen, in contrast, - // GTNH NEI moves the recipe paging widget from the bottom to the top, which means said legacy handlers will - // position item slots 16px too high in the screen. - if (isHeightHackApplied) { - p.translate(0, 16); - } - - TemplateRecipeHandler.disableCycledIngredients = false; - - for (PositionedStack stack : handler.original.getIngredientStacks(recipeIndex)) { - slotcontainer.addSlot(stack, p.x, p.y); - } - - for (PositionedStack stack : handler.original.getOtherStacks(recipeIndex)) { - slotcontainer.addSlot(stack, p.x, p.y); - } - - PositionedStack result = handler.original.getResultStack(recipeIndex); - if (result != null) { - slotcontainer.addSlot(result, p.x, p.y); - } - - if (!limitToOneRecipe) { - for (PositionedStack catalyst : RecipeCatalysts.getRecipeCatalysts(handler.original)) { - int xOffset = -GuiRecipeCatalyst.ingredientSize + 1; - int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder; - slotcontainer.addSlot(catalyst, xOffset, yOffset); - } - } - - TemplateRecipeHandler.disableCycledIngredients = true; - } } @Override public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { - GuiContainerManager.enable2DRender(); - final int recipesPerPage = getRecipesPerPage(); - final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32; - - if (!limitToOneRecipe) { - String s = handler.original.getRecipeName().trim(); - fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff); - - if (handler.searchingAvailable()) { - toggleSearch.draw(mouseX - guiLeft, mouseY - guiTop); - } - - if (searchField.isVisible()) { - searchField.draw(mouseX - guiLeft, mouseY - guiTop); - s = NEIClientUtils.cropText( - fontRendererObj, - String.format("%d/%d", page + 1, (this.numRecipes() - 1) / recipesPerPage + 1), - 45); - fontRendererObj.drawStringWithShadow( - s, - searchField.x + searchField.w + (44 - fontRendererObj.getStringWidth(s)) / 2, - 19, - 0xffffff); - } else { - s = NEIClientUtils.translate("recipe.page", page + 1, (this.numRecipes() - 1) / recipesPerPage + 1); - fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff); - } - - } - - 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 (limitToOneRecipe) { - GuiOverlayButton overlayButton = (GuiOverlayButton) this.recipeButtons.stream() - .filter(b -> b instanceof GuiOverlayButton && b.handlerRef.recipeIndex == recipeIndex) - .findAny().orElse(null); - - if (overlayButton != null && overlayButton.enabled) { - overlayButton.drawItemOverlay(); - } - } - - GL11.glTranslatef(0, handlerInfo.getHeight(), 0); - } - - GL11.glPopMatrix(); - - GL11.glPushMatrix(); - GL11.glTranslatef(5, ySkip + yShift, 0); - - if (!limitToOneRecipe) { - for (GuiRecipeButton button : this.recipeButtons) { - if (button.contains(mouseX, mouseY)) { - GL11.glTranslatef( - 0, - handlerInfo.getHeight() * indices.indexOf(button.handlerRef.recipeIndex), - 0); - button.drawItemOverlay(); - break; - } - } - } - - GL11.glPopMatrix(); - } - + GL11.glTranslatef(-guiLeft, -guiTop, 0); + this.container.draw(mouseX, mouseY); + GL11.glTranslatef(guiLeft, guiTop, 0); } @Override public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { - final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32; - GL11.glColor4f(1, 1, 1, 1); + BG_TEXTURE.draw( + this.guiLeft, + this.guiTop, + this.xSize, + this.ySize, + BORDER_PADDING, + BORDER_PADDING, + BORDER_PADDING, + BORDER_PADDING); - drawBackgroundTiled(guiLeft, guiTop); + drawJEITabs(mouseX, mouseY); + } - if (NEIClientConfig.areJEIStyleTabsVisible() && !limitToOneRecipe) { - drawRect( - guiLeft + BORDER_PADDING + BUTTON_WIDTH - 1, - nexttype.yPosition, - guiLeft + xSize - BORDER_PADDING - BUTTON_WIDTH, - nexttype.yPosition + BUTTON_HEIGHT, - 0x30000000); - drawRect( - guiLeft + BORDER_PADDING + BUTTON_WIDTH - 1, - nextpage.yPosition, - guiLeft + xSize - BORDER_PADDING - BUTTON_WIDTH, - nextpage.yPosition + BUTTON_HEIGHT, - 0x30000000); + private void drawJEITabs(int mouseX, int mouseY) { + final int recipesPerPage = getRecipesPerPage(); + final int textMiddle = (BUTTON_WIDTH - this.fontRendererObj.FONT_HEIGHT) / 2; + drawRect( + this.prevtype.xPosition + BUTTON_WIDTH - 1, + this.prevtype.yPosition, + this.nexttype.xPosition, + this.prevtype.yPosition + BUTTON_HEIGHT, + 0x30000000); + drawRect( + this.prevpage.xPosition + BUTTON_WIDTH - 1, + this.prevpage.yPosition, + this.nextpage.xPosition, + this.prevpage.yPosition + BUTTON_HEIGHT, + 0x30000000); + + drawCenteredString( + this.fontRendererObj, + this.handler.original.getRecipeName().trim(), + this.guiLeft + this.xSize / 2, + this.prevtype.yPosition + textMiddle, + 0xffffff); + + if (this.handler.searchingAvailable()) { + GuiRecipe.toggleSearch.draw(mouseX, mouseY); + } + + if (GuiRecipe.searchField.isVisible()) { + GuiRecipe.searchField.draw(mouseX, mouseY); + } + + if (GuiRecipe.searchField.isVisible()) { + final String recipePage = NEIClientUtils.cropText( + this.fontRendererObj, + String.format("%d/%d", this.page + 1, Math.max(0, numRecipes() - 1) / recipesPerPage + 1), + 45); + drawCenteredString( + this.fontRendererObj, + recipePage, + GuiRecipe.searchField.x + GuiRecipe.searchField.w + 22, + this.prevpage.yPosition + textMiddle, + 0xffffff); + } else { + final String recipePage = NEIClientUtils + .translate("recipe.page", this.page + 1, Math.max(0, numRecipes() - 1) / recipesPerPage + 1); + drawCenteredString( + this.fontRendererObj, + recipePage, + this.guiLeft + this.xSize / 2, + this.prevpage.yPosition + textMiddle, + 0xffffff); + } + + if (NEIClientConfig.areJEIStyleTabsVisible()) { RenderHelper.enableGUIStandardItemLighting(); OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f); - recipeTabs.draw(mouseX, mouseY); + this.recipeTabs.draw(mouseX, mouseY); + if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) { - guiRecipeCatalyst.draw(); + this.recipeCatalyst.draw(mouseX, mouseY); } + RenderHelper.disableStandardItemLighting(); } - - GL11.glPushMatrix(); - GL11.glTranslatef(guiLeft + 5, guiTop + ySkip + yShift, 0); - try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) { - - for (int recipeIndex : getRecipeIndices()) { - handler.original.drawBackground(recipeIndex); - GL11.glTranslatef(0, handlerInfo.getHeight(), 0); - } - - } - GL11.glPopMatrix(); - } - - private void drawBackgroundTiled(int j, int k) { - final int handlerHeight = getWidgetSize().height; - - // Draw the top - bgTop.draw(j, k + BG_TOP_Y); - - // Maybe Tile the middle - final int tiledHeight = handlerHeight - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT; - - if (tiledHeight > 0) { - final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT; - final int yRemainder = tiledHeight - (yTileCount * BG_MIDDLE_HEIGHT); - final int yStart = k + BG_TOP_HEIGHT + tiledHeight; - - for (int yTile = 0; yTile <= yTileCount; yTile++) { - final int tileHeight = (yTile == yTileCount) ? yRemainder : BG_MIDDLE_HEIGHT; - final int y = yStart - ((yTile + 1) * BG_MIDDLE_HEIGHT); - if (tileHeight > 0) { - bgMiddle.draw(j, y, BG_MIDDLE_HEIGHT - tileHeight, 0, 0, 0); - } - } - } - - // Draw the bottom - bgBottom.draw(j, k + handlerHeight - BG_BOTTOM_HEIGHT); - } - - 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 public GuiContainer getFirstScreen() { - return firstGui; + return this.firstGui; } @Override public GuiScreen getFirstScreenGeneral() { - return firstGuiGeneral; + return this.firstGuiGeneral; } private int getRecipesPerPage() { - return limitToOneRecipe ? 1 : getRecipesPerPage(handlerInfo); - } - private int getRecipesPerPage(HandlerInfo handlerInfo) { - if (handlerInfo != null) { - return Math.max( - Math.min( - ((ySize - (BUTTON_HEIGHT * 3)) / handlerInfo.getHeight()), - handlerInfo.getMaxRecipesPerPage()), - 1); - } else if (handler != null) { - return handler.original.recipiesPerPage(); + if (this.handlerInfo.getMaxRecipesPerPage() <= 1) { + return 1; } - return 1; + + if (NEIClientConfig.getBooleanSetting("inventory.guirecipe.infiniteScroll")) { + return Math.max(1, this.handler.numRecipes()); + } + + return Math.max(this.container.h / (this.handlerInfo.getHeight() + this.handlerInfo.getYShift()), 1); } public Point getRecipePosition(int recipe) { @@ -1162,14 +978,21 @@ public abstract class GuiRecipe extends GuiContainer i } protected Point getRefIndexPosition(int refIndex) { - // Legacy recipe handlers using the height hack might use getRefIndexPosition in combination with guiTop/height - // to position certain elements like tooltips. Since guiTop is moved down by 16px during height hacking, we need + // Legacy recipe handlers using the height hack might use getRefIndexPosition in + // combination with guiTop/height + // to position certain elements like tooltips. Since guiTop is moved down by + // 16px during height hacking, we need // to reduce the vertical shift here to 16px instead of 32px. - return new Point( - 5, - (isHeightHackApplied ? 16 : 32) - (limitToOneRecipe ? 25 : 0) - + yShift - + ((refIndex % getRecipesPerPage()) * handlerInfo.getHeight())); + final List children = this.container.getWidgets(); + + if (refIndex >= 0 && refIndex < children.size() + && children.get(refIndex) instanceof NEIRecipeWidget recipeWidget) { + return new Point( + recipeWidget.x - this.guiLeft, + recipeWidget.y - this.guiTop + recipeWidget.getHandlerInfo().getYShift()); + } + + return new Point(0, 0); } public abstract ArrayList getCurrentRecipeHandlers(); @@ -1192,8 +1015,8 @@ public abstract class GuiRecipe extends GuiContainer i @Override public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) { - if (searchField.isVisible() && searchField.contains(mousex - guiLeft, mousey - guiTop)) { - searchField.setText(SearchField.getEscapedSearchText(draggedStack)); + if (GuiRecipe.searchField.isVisible() && GuiRecipe.searchField.contains(mousex, mousey)) { + GuiRecipe.searchField.setText(SearchField.getEscapedSearchText(draggedStack)); return true; } @@ -1202,13 +1025,23 @@ public abstract class GuiRecipe extends GuiContainer i @Override public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) { + final Rectangle4i rect = new Rectangle4i(x, y, w, h); // Because some of the handlers *cough avaritia* are oversized - return area.intersects(x, y, w, h); + + if (this.recipeCatalyst.isShowWidget() && this.recipeCatalyst.bounds().intersects(rect)) { + return true; + } + + if (getRecipesPerPage() == 1 && !this.container.getWidgets().isEmpty()) { + return this.container.getWidgets().get(0).bounds().intersects(rect); + } + + return this.container.boundsOutside().intersects(rect); } protected static RecipeId getCurrentRecipeId(GuiScreen gui) { - if ((gui instanceof GuiRecipegRecipe) && gRecipe.handler.numRecipes() > 0) { + if (gui instanceof GuiRecipegRecipe && gRecipe.handler.numRecipes() > 0) { final List indices = gRecipe.getRecipeIndices(); final int curRecipe = indices.isEmpty() ? 0 : indices.get(0); final Recipe recipe = Recipe.of(gRecipe.handler.original, curRecipe); @@ -1218,4 +1051,21 @@ public abstract class GuiRecipe extends GuiContainer i return null; } + + // some mods reflect this property + @Deprecated + private GuiOverlayButton[] overlayButtons = new GuiOverlayButton[0]; + + @Deprecated + public ContainerRecipe slotcontainer; + + @Deprecated + public List getOverlayButtons() { + return Arrays.asList(this.overlayButtons); + } + + @Deprecated + public boolean isLimitedToOneRecipe() { + return false; + } } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeButton.java b/src/main/java/codechicken/nei/recipe/GuiRecipeButton.java index 2570e149..fc13147e 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeButton.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeButton.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraftforge.client.event.GuiScreenEvent; import codechicken.lib.vec.Rectangle4i; @@ -16,33 +15,30 @@ public abstract class GuiRecipeButton extends GuiNEIButton { public static class UpdateRecipeButtonsEvent extends GuiScreenEvent { public List buttonList; + public NEIRecipeWidget recipeWidget; - public UpdateRecipeButtonsEvent(GuiRecipe gui, List buttonList) { + public UpdateRecipeButtonsEvent(GuiRecipe gui, NEIRecipeWidget recipeWidget, + List buttonList) { super(gui); + this.recipeWidget = recipeWidget; this.buttonList = new ArrayList<>(buttonList); } @Cancelable public static class Pre extends UpdateRecipeButtonsEvent { - 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; + public Pre(GuiRecipe gui, NEIRecipeWidget recipeWidget, HandlerInfo handlerInfo) { + super(gui, recipeWidget, new ArrayList<>()); this.handlerInfo = handlerInfo; } } public static class Post extends UpdateRecipeButtonsEvent { - public Post(GuiRecipe gui, List buttonList) { - super(gui, buttonList); + public Post(GuiRecipe gui, NEIRecipeWidget recipeWidget, List buttonList) { + super(gui, recipeWidget, buttonList); } } } @@ -57,15 +53,15 @@ public abstract class GuiRecipeButton extends GuiNEIButton { this.handlerRef = point; } - abstract List handleTooltip(GuiRecipe gui, List currenttip); + public abstract List handleTooltip(List currenttip); - abstract Map handleHotkeys(GuiContainer gui, int mousex, int mousey, Map hotkeys); + public abstract Map handleHotkeys(int mousex, int mousey, Map hotkeys); - abstract void lastKeyTyped(GuiRecipe gui, char keyChar, int keyID); + public abstract void lastKeyTyped(char keyChar, int keyID); - abstract void drawItemOverlay(); + public abstract void drawItemOverlay(); - public boolean mouseScrolled(GuiRecipe gui, int scroll) { + public boolean mouseScrolled(int scroll) { return false; } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeCatalyst.java b/src/main/java/codechicken/nei/recipe/GuiRecipeCatalyst.java index 84a6a43a..8dce3e4a 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeCatalyst.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeCatalyst.java @@ -1,159 +1,167 @@ package codechicken.nei.recipe; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.util.ResourceLocation; +import java.util.ArrayList; +import java.util.List; -import org.lwjgl.util.Rectangle; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; -import codechicken.nei.api.INEIGuiAdapter; -import codechicken.nei.drawable.GuiElementDuex; -import codechicken.nei.drawable.GuiElementScalable; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; -public class GuiRecipeCatalyst extends INEIGuiAdapter { +import codechicken.lib.gui.GuiDraw; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.NEIServerUtils; +import codechicken.nei.PositionedStack; +import codechicken.nei.Widget; +import codechicken.nei.api.ShortcutInputHandler; +import codechicken.nei.drawable.DrawableBuilder; +import codechicken.nei.drawable.DrawableResource; +import codechicken.nei.guihook.GuiContainerManager; - private GuiRecipe guiRecipe; - public static final int ingredientSize = 16; - public static final int ingredientBorder = 1; - public static final int tabBorder = 5; - public static final int fullBorder = ingredientBorder + tabBorder; +public class GuiRecipeCatalyst extends Widget { - private static final Rectangle catalystRect = new Rectangle(); - private static final Rectangle targetRect = new Rectangle(); + private static final int SLOT_SIZE = 16; + private static final int BORDER_PADDING = 6; + private static final DrawableResource BG_TEXTURE = new DrawableBuilder( + "nei:textures/catalyst_tab.png", + 0, + 0, + 28, + 28).setTextureSize(28, 28).build(); - public GuiRecipeCatalyst(GuiRecipe guiRecipe) { - this.guiRecipe = guiRecipe; + private static final DrawableResource FG_TEXTURE = new DrawableBuilder("nei:textures/slot.png", 0, 0, 18, 18) + .setTextureSize(18, 18).build(); + + private final List items = new ArrayList<>(); + private int availableHeight = 0; + private boolean showWidget = false; + + public void setCatalysts(List items) { + this.items.clear(); + this.items.addAll(items); } - public void draw() { - if (guiRecipe == null) return; - int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler()).size(); - if (catalystsSize == 0) return; + public void setAvailableHeight(int height) { + this.availableHeight = height; + } - int availableHeight = RecipeCatalysts.getHeight(); - int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize); - int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize); - int width, height, xPos, yPos; + public int getAvailableHeight() { + return this.availableHeight; + } - width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize); - height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize); - xPos = guiRecipe.guiLeft - width + tabBorder + 1; - yPos = guiRecipe.guiTop; - drawBordered("nei:textures/catalyst_tab.png", xPos, yPos, width, height, 28, 28, 6, 6, 6, 6); + public boolean isShowWidget() { + return this.showWidget; + } - width = (ingredientBorder * 2) + (columnCount * ingredientSize); - height = (ingredientBorder * 2) + (rowCount * ingredientSize); - xPos = guiRecipe.guiLeft - width + ingredientBorder + 1; - yPos = guiRecipe.guiTop + fullBorder - ingredientBorder; - drawBordered("nei:textures/slot.png", xPos, yPos, width, height, 18, 18, 1, 1, 1, 1); + public int getColumnCount() { + final int maxItemsPerColumn = Math.max(0, this.availableHeight - 2 - BORDER_PADDING * 2) / SLOT_SIZE; + return maxItemsPerColumn > 0 ? NEIServerUtils.divideCeil(this.items.size(), maxItemsPerColumn) : 0; + } + + public int getRowCount() { + final int columnCount = getColumnCount(); + return columnCount > 0 ? NEIServerUtils.divideCeil(this.items.size(), columnCount) : 0; } @Override - public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) { - if (!(gui instanceof GuiRecipe)) return false; - guiRecipe = (GuiRecipe) gui; - int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler()).size(); - if (catalystsSize == 0) return false; + public void update() { + final int columns = getColumnCount(); + final int rows = getRowCount(); - int availableHeight = RecipeCatalysts.getHeight(); - int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize); - int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize); - int margin = 4; + this.showWidget = rows * columns > 0; + this.w = columns * SLOT_SIZE + 2 + BORDER_PADDING * 2; + this.h = rows * SLOT_SIZE + 2 + BORDER_PADDING * 2; + + if (rows == 0 || columns == 0) { + return; + } + + int index = 0; + for (PositionedStack pStack : this.items) { + + if (pStack.items.length > 1) { + final int stackIndex = (pStack.items.length + pStack.getPermutationIndex(pStack.item) + 1) + % pStack.items.length; + pStack.setPermutationToRender(stackIndex); + } + + pStack.relx = this.w - BORDER_PADDING - 1 - SLOT_SIZE - (index / rows) * SLOT_SIZE; + pStack.rely = BORDER_PADDING + 1 + (index % rows) * SLOT_SIZE; + index++; + } - int width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize) + margin; - int height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize) + margin; - int xOffset = guiRecipe.guiLeft - width + tabBorder; - int yOffset = guiRecipe.guiTop; - catalystRect.setBounds(xOffset, yOffset, width, height); - targetRect.setBounds(x, y, w, h); - return targetRect.intersects(catalystRect); } - private void drawBordered(String location, int xPos, int yPos, int width, int height, int texWidth, int texHeight, - int sliceLeft, int sliceRight, int sliceTop, int sliceBottom) { - Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(location)); + @Override + public void draw(int mx, int my) { + if (!this.showWidget) return; - GuiElementDuex cornerTopLeft = new GuiElementDuex(0, 0, sliceLeft, sliceTop, texWidth, texHeight); - GuiElementDuex cornerTopRight = new GuiElementDuex( - texWidth - sliceRight, - 0, - sliceRight, - sliceTop, - texWidth, - texHeight); - GuiElementDuex cornerBottomLeft = new GuiElementDuex( - 0, - texHeight - sliceBottom, - sliceLeft, - sliceBottom, - texWidth, - texHeight); - GuiElementDuex cornerBottomRight = new GuiElementDuex( - texWidth - sliceRight, - texHeight - sliceBottom, - sliceRight, - sliceBottom, - texWidth, - texHeight); + GL11.glTranslatef(this.x, this.y, 0); + GL11.glColor4f(1, 1, 1, 1); - GuiElementScalable borderTop = new GuiElementScalable( - sliceLeft, - 0, - texWidth - sliceLeft - sliceRight, - sliceTop, - texWidth, - texHeight); - GuiElementScalable borderBottom = new GuiElementScalable( - sliceLeft, - texHeight - sliceBottom, - texWidth - sliceLeft - sliceRight, - sliceBottom, - texWidth, - texHeight); - GuiElementScalable borderLeft = new GuiElementScalable( - 0, - sliceTop, - sliceLeft, - texHeight - sliceTop - sliceBottom, - texWidth, - texHeight); - GuiElementScalable borderRight = new GuiElementScalable( - texWidth - sliceRight, - sliceTop, - sliceRight, - texHeight - sliceTop - sliceBottom, - texWidth, - texHeight); - GuiElementScalable center = new GuiElementScalable( - sliceLeft, - sliceTop, - texWidth - sliceLeft - sliceRight, - texHeight - sliceTop - sliceBottom, - texWidth, - texHeight); + BG_TEXTURE.draw(0, 0, this.w, this.h, BORDER_PADDING, BORDER_PADDING, BORDER_PADDING, BORDER_PADDING); + FG_TEXTURE.draw( + BORDER_PADDING, + BORDER_PADDING, + this.w - BORDER_PADDING * 2, + this.h - BORDER_PADDING * 2, + 1, + 1, + 1, + 1); - int midW = width - borderLeft.w - borderRight.w; - int midH = height - borderTop.h - borderBottom.h; + GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); - // top row - int x = xPos; - int y = yPos; - x += cornerTopLeft.draw(x, y); - x += borderTop.drawScaledX(x, y, midW); - cornerTopRight.draw(x, y); + for (PositionedStack pStack : this.items) { + GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item); - // center row - x = xPos; - y += borderTop.h; - x += borderLeft.drawScaledY(x, y, midH); - x += center.drawScaled(x, y, midW, midH); - borderRight.drawScaledY(x, y, midH); + if (pStack.contains(mx - this.x, my - this.y)) { + NEIClientUtils.gl2DRenderContext( + () -> GuiDraw.drawRect(pStack.relx, pStack.rely, SLOT_SIZE, SLOT_SIZE, -2130706433)); + } + } - // bottom row - x = xPos; - y += midH; - x += cornerBottomLeft.draw(x, y); - x += borderBottom.drawScaledX(x, y, midW); - cornerBottomRight.draw(x, y); + GL11.glPopAttrib(); + GL11.glTranslatef(-this.x, -this.y, 0); } + + public PositionedStack getPositionedStackMouseOver(int mx, int my) { + + for (PositionedStack pStack : this.items) { + if (pStack.contains(mx - this.x, my - this.y)) { + return pStack; + } + } + + return null; + } + + @Override + public ItemStack getStackMouseOver(int mx, int my) { + final PositionedStack pStack = getPositionedStackMouseOver(mx, my); + + if (pStack != null) { + return pStack.item; + } + + return null; + } + + @Override + public boolean handleClick(int mx, int my, int button) { + return ShortcutInputHandler.handleMouseClick(getStackMouseOver(mx, my)); + } + + @Deprecated + public static final int ingredientSize = 16; + @Deprecated + public static final int ingredientBorder = 1; + @Deprecated + public static final int tabBorder = 5; + @Deprecated + public static final int fullBorder = ingredientBorder + tabBorder; + } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java index bdd3fb01..22990c51 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java @@ -42,10 +42,9 @@ public abstract class GuiRecipeTab extends Widget { public static HashMap handlerAdderFromIMC = new HashMap<>(); public static Set handlerRemoverFromIMC = new HashSet<>(); - private final GuiRecipe guiRecipe; - private final IRecipeHandler handler; - private final String handlerName; - private final String handlerID; + protected final IRecipeHandler handler; + protected final String handlerName; + protected final String handlerID; private boolean selected; @@ -61,7 +60,7 @@ public abstract class GuiRecipeTab extends Widget { protected abstract int getForegroundIconY(); - public GuiRecipeTab(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) { + public GuiRecipeTab(IRecipeHandler handler, int x, int y) { super(); this.x = x; this.y = y; @@ -69,7 +68,6 @@ public abstract class GuiRecipeTab extends Widget { this.h = getHeight(); this.handler = handler; this.handlerName = handler.getHandlerId(); - this.guiRecipe = guiRecipe; this.selected = false; if (handler instanceof TemplateRecipeHandler) { @@ -154,16 +152,10 @@ public abstract class GuiRecipeTab extends Widget { } } - public boolean onButtonPress(boolean rightclick) { - int newIdx = guiRecipe.currenthandlers.indexOf(handler); - if (newIdx == -1) return false; + public abstract boolean onButtonPress(boolean rightclick); - guiRecipe.setRecipePage(newIdx); - return true; - } - - public void setSelected(IRecipeHandler current) { - selected = handler == current; + public void setSelected(boolean selected) { + this.selected = selected; } public static HandlerInfo getHandlerInfo(IRecipeHandler handler) { @@ -273,6 +265,8 @@ public abstract class GuiRecipeTab extends Widget { NEIClientConfig.logger.info("Error setting handler dimensions for " + handler); } + info.setUseCustomScroll( + record.isSet("useCustomScroll") ? Boolean.parseBoolean(record.get("useCustomScroll")) : false); handlerMap.put(handler, info); NEIClientConfig.logger.info("Loaded " + handler); } diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTabCreative.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTabCreative.java index 3fc1c0e1..30ebd32d 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTabCreative.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTabCreative.java @@ -3,7 +3,7 @@ package codechicken.nei.recipe; import codechicken.nei.drawable.DrawableBuilder; import codechicken.nei.drawable.DrawableResource; -public class GuiRecipeTabCreative extends GuiRecipeTab { +public abstract class GuiRecipeTabCreative extends GuiRecipeTab { public static final int TAB_WIDTH = 28; public static final int TAB_HEIGHT = 31; @@ -20,8 +20,8 @@ public class GuiRecipeTabCreative extends GuiRecipeTab { 28, 30).build(); - public GuiRecipeTabCreative(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) { - super(guiRecipe, handler, x, y); + public GuiRecipeTabCreative(IRecipeHandler handler, int x, int y) { + super(handler, x, y); } @Override diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTabJEI.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTabJEI.java index 73bda07b..344b9cf6 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTabJEI.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTabJEI.java @@ -3,7 +3,7 @@ package codechicken.nei.recipe; import codechicken.nei.drawable.DrawableBuilder; import codechicken.nei.drawable.DrawableResource; -public class GuiRecipeTabJEI extends GuiRecipeTab { +public abstract class GuiRecipeTabJEI extends GuiRecipeTab { public static final int TAB_WIDTH = 24; public static final int TAB_HEIGHT = 24; @@ -20,8 +20,8 @@ public class GuiRecipeTabJEI extends GuiRecipeTab { 24, 24).build(); - public GuiRecipeTabJEI(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) { - super(guiRecipe, handler, x, y); + public GuiRecipeTabJEI(IRecipeHandler handler, int x, int y) { + super(handler, x, y); } @Override diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTabs.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTabs.java index 75e0797f..e37eb634 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTabs.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTabs.java @@ -1,168 +1,154 @@ package codechicken.nei.recipe; -import static codechicken.lib.gui.GuiDraw.getMousePosition; - -import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.List; +import codechicken.lib.gui.GuiDraw; import codechicken.nei.Button; import codechicken.nei.NEIClientConfig; import codechicken.nei.NEIClientUtils; public class GuiRecipeTabs { - private final GuiRecipe guiRecipe; private final List tabs = new ArrayList<>(); private final List