diff --git a/src/main/java/codechicken/nei/LayoutManager.java b/src/main/java/codechicken/nei/LayoutManager.java index dfe92f91..18813b35 100644 --- a/src/main/java/codechicken/nei/LayoutManager.java +++ b/src/main/java/codechicken/nei/LayoutManager.java @@ -66,9 +66,9 @@ 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; +import codechicken.nei.recipe.debug.DebugHandlerWidget; public class LayoutManager implements IContainerInputHandler, IContainerTooltipHandler, IContainerDrawHandler, IContainerObjectHandler, IKeyStateTracker { @@ -92,7 +92,6 @@ 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; @@ -406,8 +405,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH itemZoom = new ItemZoom(); - recipeHandlerWidget = new DebugHandlerWidget(); - dropDown = new SubsetWidget(); searchField = new SearchField("search"); API.addItemFilter(searchField); @@ -786,8 +783,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH addWidget(dropDown); } - addWidget(recipeHandlerWidget); - recipeHandlerWidget.setVisible(); + addWidget(DebugHandlerWidget.instance); } 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 0f3e26c3..5c952ba2 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -56,7 +56,6 @@ 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; @@ -1017,8 +1016,6 @@ public class NEIClientConfig { // API. I don't expect any handler to do this, but who knows what modders have come up with... pluginNEIConfigLoaded = true; MinecraftForge.EVENT_BUS.post(new NEIConfigsLoadedEvent()); - - DebugHandlerWidget.loadHandlerInfoPatch(); ItemList.loadItems.restart(); } }.start(); diff --git a/src/main/java/codechicken/nei/config/IMCHandler.java b/src/main/java/codechicken/nei/config/IMCHandler.java index 63b8b37c..9430cce9 100644 --- a/src/main/java/codechicken/nei/config/IMCHandler.java +++ b/src/main/java/codechicken/nei/config/IMCHandler.java @@ -93,7 +93,8 @@ public class IMCHandler { final boolean multipleWidgetsAllowed = tag.hasKey("multipleWidgetsAllowed") ? tag.getBoolean("multipleWidgetsAllowed") : tag.hasKey("maxRecipesPerPage") && tag.getInteger("maxRecipesPerPage") > 1; - info.setHandlerDimensions(handlerWidth, handlerHeight, multipleWidgetsAllowed); + info.setHandlerDimensions(handlerWidth, handlerHeight); + info.setMultipleWidgetsAllowed(multipleWidgetsAllowed); } catch (NumberFormatException ignored) { NEIClientConfig.logger.info("Error setting handler dimensions for {}", handler); } diff --git a/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java b/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java deleted file mode 100644 index 5ea84073..00000000 --- a/src/main/java/codechicken/nei/recipe/DebugHandlerWidget.java +++ /dev/null @@ -1,718 +0,0 @@ -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 net.minecraft.util.EnumChatFormatting; - -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 Button multipleWidgetsAllowed; - private Button useCustomScroll; - - private Point dragPoint = null; - public boolean showWidget = false; - - private static final int BORDER_PADDING = 6; - private static final int TRANSPARENCY_BORDER = 4; - private static final String TOOLTIP_PREFIX = "debug.RecipeHandler."; - private static final Map TOOLTIP_KEYS = new HashMap<>(); - - static { - TOOLTIP_KEYS.put("Name", TOOLTIP_PREFIX + "Name"); - TOOLTIP_KEYS.put("ID", TOOLTIP_PREFIX + "Id"); - TOOLTIP_KEYS.put("Key", TOOLTIP_PREFIX + "Key"); - TOOLTIP_KEYS.put("H.Hack", TOOLTIP_PREFIX + "HHack"); - TOOLTIP_KEYS.put("Mod Name", TOOLTIP_PREFIX + "ModName"); - TOOLTIP_KEYS.put("Mod ID", TOOLTIP_PREFIX + "ModId"); - TOOLTIP_KEYS.put("Order", TOOLTIP_PREFIX + "Order"); - TOOLTIP_KEYS.put("yShift", TOOLTIP_PREFIX + "yShift"); - TOOLTIP_KEYS.put("Multi Widgets", TOOLTIP_PREFIX + "MultiWidgets"); - TOOLTIP_KEYS.put("Height", TOOLTIP_PREFIX + "Height"); - TOOLTIP_KEYS.put("Width", TOOLTIP_PREFIX + "Width"); - TOOLTIP_KEYS.put("Use Custom Scroll", TOOLTIP_PREFIX + "UseCustomScroll"); - } - private final DrawableResource BG_TEXTURE = new DrawableBuilder( - "nei:textures/gui/recipebg.png", - 0, - 0, - 176 + TRANSPARENCY_BORDER * 2, - 166 + TRANSPARENCY_BORDER * 2).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.multipleWidgetsAllowed = new Button() { - - { - this.h = LINE_HEIGHT; - this.z = 2; - } - - public String getRenderLabel() { - return handlerInfo.isMultipleWidgetsAllowed() ? "On" : "Off"; - } - - @Override - public boolean onButtonPress(boolean rightclick) { - handlerInfo.setHandlerDimensions( - handlerInfo.getWidth(), - handlerInfo.getHeight(), - !handlerInfo.isMultipleWidgetsAllowed()); - updatePatch(4, handlerInfo.isMultipleWidgetsAllowed() ? 1 : 0, 1); - return true; - } - - }; - - this.handlerHeight = new IntegerField("handlerHeight", HandlerInfo.DEFAULT_HEIGHT) { - - @Override - public void draw(int mx, int my) { - this.field.setEnabled(handler.getRecipeHeight(0) <= 0); - super.draw(mx, my); - } - - @Override - public void onTextChange(String oldText) { - if (getInteger() != handlerInfo.getHeight()) { - handlerInfo.setHandlerDimensions( - handlerInfo.getWidth(), - getInteger(), - handlerInfo.isMultipleWidgetsAllowed()); - 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( - getInteger(), - handlerInfo.getHeight(), - handlerInfo.isMultipleWidgetsAllowed()); - 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) { - final String displayLabel = translateDisplayLabel(keyLabel); - GuiDraw.drawString( - NEIClientUtils.cropText(GuiDraw.fontRenderer, displayLabel, 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; - } - - private static String translateTooltipLabel(String label) { - String key = TOOLTIP_KEYS.get(label); - String text = label; - if (key == null) { - return EnumChatFormatting.WHITE + EnumChatFormatting.getTextWithoutFormattingCodes(text); - } - text = NEIClientUtils.translate(key); - return EnumChatFormatting.WHITE + EnumChatFormatting.getTextWithoutFormattingCodes(text); - } - - private static String translateDisplayLabel(String label) { - String key = TOOLTIP_KEYS.get(label); - if (key == null) { - return label; - } - return NEIClientUtils.translate(key); - } - - @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 - TRANSPARENCY_BORDER, - this.y - TRANSPARENCY_BORDER, - this.w + TRANSPARENCY_BORDER * 2, - this.h + TRANSPARENCY_BORDER * 2, - BORDER_PADDING + TRANSPARENCY_BORDER, - BORDER_PADDING + TRANSPARENCY_BORDER, - BORDER_PADDING + TRANSPARENCY_BORDER, - BORDER_PADDING + TRANSPARENCY_BORDER); - GuiDraw.drawRect( - this.x + INLINE_PADDING, - this.y + BORDER_PADDING, - this.w - INLINE_PADDING * 2, - 12, - 0x30000000); - GuiDraw.drawStringC( - NEIClientUtils.translate("debug.RecipeHandler.title"), - 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("Multi Widgets", this.multipleWidgetsAllowed, 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.multipleWidgetsAllowed); - 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())); - } - - } 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(translateTooltipLabel(entry.getKey())); - } else { - tooltip.add(String.valueOf(entry.getValue())); - } - - return tooltip; - } - topShift += LINE_HEIGHT; - } - - String[] controlLabels = new String[] { "Order", "yShift", "Multi Widgets", "Height", "Width", - "Use Custom Scroll" }; - for (String label : controlLabels) { - if (my >= topShift && my < topShift + LINE_HEIGHT) { - tooltip.add(translateTooltipLabel(label)); - return tooltip; - } - 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(); - } - - 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]); - - // center cross - GuiDraw.drawRect(widget.x + widget.w / 2 - 1, widget.y, 1, widget.h, 0x88ffffff); - GuiDraw.drawRect(widget.x, widget.y + widget.h / 2 - 1, widget.w, 1, 0x88ffffff); - - // 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 boolean isMultipleWidgetsAllowed = intOrDefault( - parts[4], - info.isMultipleWidgetsAllowed() ? 1 : 0) == 1; - 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(width, height, isMultipleWidgetsAllowed); - 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/GuiRecipe.java b/src/main/java/codechicken/nei/recipe/GuiRecipe.java index 4cf5e9c9..badd18f8 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipe.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipe.java @@ -783,7 +783,7 @@ public abstract class GuiRecipe extends GuiContainer i return this.recipeCatalyst; } - protected void forceRefreshPage() { + public void forceRefreshPage() { this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR); final int currentPage = this.handlerPages.getCurrentPageIndex(); diff --git a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java index af4c013d..ab7ac590 100644 --- a/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java +++ b/src/main/java/codechicken/nei/recipe/GuiRecipeTab.java @@ -33,6 +33,7 @@ import codechicken.nei.Widget; import codechicken.nei.drawable.DrawableResource; import codechicken.nei.event.NEIRegisterHandlerInfosEvent; import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.debug.DebugHandlerWidget; import cpw.mods.fml.common.Loader; public abstract class GuiRecipeTab extends Widget { @@ -258,7 +259,8 @@ public abstract class GuiRecipeTab extends Widget { final int handlerHeight = intOrDefault(record.get("handlerHeight"), HandlerInfo.DEFAULT_HEIGHT); final int handlerWidth = intOrDefault(record.get("handlerWidth"), HandlerInfo.DEFAULT_WIDTH); final boolean multipleWidgetsAllowed = intOrDefault(record.get("maxRecipesPerPage"), 1) > 1; - info.setHandlerDimensions(handlerWidth, handlerHeight, multipleWidgetsAllowed); + info.setHandlerDimensions(handlerWidth, handlerHeight); + info.setMultipleWidgetsAllowed(multipleWidgetsAllowed); } catch (NumberFormatException ignored) { NEIClientConfig.logger.info("Error setting handler dimensions for " + handler); } @@ -292,11 +294,12 @@ public abstract class GuiRecipeTab extends Widget { } NEIClientConfig.logger.info("Sending {}", NEIRegisterHandlerInfosEvent.class.getSimpleName()); MinecraftForge.EVENT_BUS.post(new NEIRegisterHandlerInfosEvent()); + DebugHandlerWidget.instance.loadHandlerInfoPatch(); } private static HandlerInfo getDefaultHandlerInfo() { final HandlerInfo info = new HandlerInfo("Unknown", "Unknown", "Unknown", false, ""); - info.setHandlerDimensions(HandlerInfo.DEFAULT_WIDTH, HandlerInfo.DEFAULT_HEIGHT, false); + info.setHandlerDimensions(HandlerInfo.DEFAULT_WIDTH, HandlerInfo.DEFAULT_HEIGHT); return info; } diff --git a/src/main/java/codechicken/nei/recipe/HandlerInfo.java b/src/main/java/codechicken/nei/recipe/HandlerInfo.java index 571a4f4f..d443e8d7 100644 --- a/src/main/java/codechicken/nei/recipe/HandlerInfo.java +++ b/src/main/java/codechicken/nei/recipe/HandlerInfo.java @@ -45,13 +45,13 @@ public class HandlerInfo { @Deprecated public void setHandlerDimensions(int height, int width, int maxRecipesPerPage) { - setHandlerDimensions(width, height, maxRecipesPerPage > 1); + setHandlerDimensions(width, height); + setMultipleWidgetsAllowed(maxRecipesPerPage > 1); } - public void setHandlerDimensions(int width, int height, boolean multipleWidgetsAllowed) { + public void setHandlerDimensions(int width, int height) { this.height = height; this.width = width; - this.multipleWidgetsAllowed = multipleWidgetsAllowed; } public boolean setItem(String itemId, String nbtString) { @@ -102,6 +102,10 @@ public class HandlerInfo { return this.multipleWidgetsAllowed ? Integer.MAX_VALUE : 1; } + public void setMultipleWidgetsAllowed(boolean multipleWidgetsAllowed) { + this.multipleWidgetsAllowed = multipleWidgetsAllowed; + } + public boolean isMultipleWidgetsAllowed() { return this.multipleWidgetsAllowed; } diff --git a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java index f8d40f8b..972d2fdc 100644 --- a/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java +++ b/src/main/java/codechicken/nei/recipe/NEIRecipeWidget.java @@ -22,7 +22,6 @@ import org.lwjgl.opengl.GL12; import codechicken.lib.gui.GuiDraw; import codechicken.nei.FavoriteRecipes; -import codechicken.nei.LayoutManager; import codechicken.nei.NEIClientConfig; import codechicken.nei.NEIClientUtils; import codechicken.nei.NEIServerUtils; @@ -33,6 +32,7 @@ import codechicken.nei.api.ShortcutInputHandler; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiRecipeButton.UpdateRecipeButtonsEvent; import codechicken.nei.recipe.Recipe.RecipeId; +import codechicken.nei.recipe.debug.DebugHandlerWidget; import codechicken.nei.util.NEIMouseUtils; public class NEIRecipeWidget extends Widget { @@ -252,7 +252,7 @@ public class NEIRecipeWidget extends Widget { } } - LayoutManager.recipeHandlerWidget.drawGuiPlaceholder(this); + DebugHandlerWidget.instance.drawGuiPlaceholder(this); } @Override diff --git a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java index d10f3d08..1b88b9d7 100644 --- a/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java +++ b/src/main/java/codechicken/nei/recipe/TemplateRecipeHandler.java @@ -256,6 +256,10 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH return rect.hashCode(); } + public Rectangle getRect() { + return rect; + } + Rectangle rect; String outputId; Object[] results; diff --git a/src/main/java/codechicken/nei/recipe/debug/CheckboxWidget.java b/src/main/java/codechicken/nei/recipe/debug/CheckboxWidget.java new file mode 100644 index 00000000..8d9148d5 --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/debug/CheckboxWidget.java @@ -0,0 +1,37 @@ +package codechicken.nei.recipe.debug; + +import java.util.function.Consumer; + +import codechicken.nei.Button; +import codechicken.nei.NEIClientUtils; + +public class CheckboxWidget extends Button implements IUpdatableWidget { + + protected Consumer onChange; + protected boolean value; + + public CheckboxWidget(Consumer onChange) { + super(); + this.onChange = onChange; + this.h = 16; + this.z = 2; + } + + @Override + public String getRenderLabel() { + return this.value ? NEIClientUtils.translate("debug.RecipeHandler.checkbox.on") + : NEIClientUtils.translate("debug.RecipeHandler.checkbox.off"); + } + + @Override + public boolean onButtonPress(boolean rightclick) { + this.value = !this.value; + onChange.accept(this); + return true; + } + + public void updateValue(String newValue) { + this.value = Boolean.parseBoolean(newValue); + } + +} diff --git a/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java b/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java new file mode 100644 index 00000000..ee385b6e --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/debug/DebugHandlerWidget.java @@ -0,0 +1,618 @@ +package codechicken.nei.recipe.debug; + +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.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.stream.Collectors; + +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.ClientHandler; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.Widget; +import codechicken.nei.drawable.DrawableBuilder; +import codechicken.nei.drawable.DrawableResource; +import codechicken.nei.recipe.GuiRecipe; +import codechicken.nei.recipe.GuiRecipeButton; +import codechicken.nei.recipe.GuiRecipeTab; +import codechicken.nei.recipe.HandlerInfo; +import codechicken.nei.recipe.IRecipeHandler; +import codechicken.nei.recipe.NEIRecipeWidget; +import codechicken.nei.recipe.TemplateRecipeHandler; +import codechicken.nei.recipe.TemplateRecipeHandler.RecipeTransferRect; +import codechicken.nei.scroll.ScrollContainer; + +public class DebugHandlerWidget extends Widget { + + private static class HandlerInfoRecord { + + public String handlerKey; + public int yShift; + public int width; + public int height; + public boolean multiWidgets; + public int order; + public boolean useCustomScroll; + public boolean showFavorites; + public boolean showOverlay; + + private String csvLine; + + public HandlerInfoRecord(String handlerKey, HandlerInfo info) { + this.handlerKey = handlerKey; + this.yShift = info.getYShift(); + this.width = info.getWidth(); + this.height = info.getHeight(); + this.multiWidgets = info.isMultipleWidgetsAllowed(); + this.order = NEIClientConfig.handlerOrdering.getOrDefault(handlerKey, 0); + this.useCustomScroll = info.getUseCustomScroll(); + this.showFavorites = info.getShowFavoritesButton(); + this.showOverlay = info.getShowOverlayButton(); + this.csvLine = toCsvLine(); + } + + public void applyTo(HandlerInfo info) { + info.setYShift(this.yShift); + info.setHandlerDimensions(this.width, this.height); + info.setMultipleWidgetsAllowed(this.multiWidgets); + info.setUseCustomScroll(this.useCustomScroll); + info.setShowFavoritesButton(this.showFavorites); + info.setShowOverlayButton(this.showOverlay); + NEIClientConfig.handlerOrdering.put(this.handlerKey, this.order); + } + + public String toCsvLine() { + return String.join( + ",", + handlerKey, + String.valueOf(yShift), + String.valueOf(height), + String.valueOf(width), + String.valueOf(multiWidgets ? 1 : 0), + String.valueOf(order), + String.valueOf(useCustomScroll ? 1 : 0), + String.valueOf(showFavorites ? 1 : 0), + String.valueOf(showOverlay ? 1 : 0)); + } + + public boolean isUnmodified() { + return this.csvLine.equals(this.toCsvLine()); + } + } + + 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 static final String TOOLTIP_PREFIX = "debug.RecipeHandler."; + private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,UseCustomScroll,ShowFavorites,ShowOverlay"; + private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 }; + + public static DebugHandlerWidget instance = new DebugHandlerWidget(); + + private ScrollContainer container = new ScrollContainer(); + private final Map values = new LinkedHashMap<>(); + private Map patches = new HashMap<>(); + + private IRecipeHandler handler; + private HandlerInfo handlerInfo; + private HandlerInfoRecord record; + + private Point dragPoint = null; + private boolean showWidget = false; + + private final DrawableResource BG_TEXTURE = new DrawableBuilder( + "nei:textures/gui/recipebg.png", + 0, + 0, + 176 + TRANSPARENCY_BORDER * 2, + 166 + TRANSPARENCY_BORDER * 2).build(); + private static final int BORDER_PADDING = 6; + private static final int TRANSPARENCY_BORDER = 4; + + public DebugHandlerWidget() { + this.w = WINDOW_WIDTH; + this.x = 10; + this.y = 50; + this.z = 4; + + this.container.x = this.x + INLINE_PADDING; + this.container.y = this.y + 5 + LINE_HEIGHT; + this.container.w = this.w - INLINE_PADDING * 2; + + int y = 0; + y = addInfoWidget("Name", y); + y = addInfoWidget("Id", y); + y = addInfoWidget("Key", y); + y = addInfoWidget("HHack", y); + y = addInfoWidget("ModName", y); + y = addInfoWidget("ModId", y); + y = addInfoWidget("Override", y); + + y = addTextFieldWidget("Order", 0, (field, oldText) -> { + + if (field.getInteger() != record.order) { + record.order = field.getInteger(); + saveHandlerInfoPatch(); + } + + }, y); + + y = addTextFieldWidget("yShift", 0, (field, oldText) -> { + + if (field.getInteger() != handlerInfo.getYShift()) { + handlerInfo.setYShift(field.getInteger()); + record.yShift = field.getInteger(); + saveHandlerInfoPatch(); + } + + }, y); + + y = addCheckboxWidget("MultiWidgets", button -> { + handlerInfo.setMultipleWidgetsAllowed(button.value); + record.multiWidgets = button.value; + saveHandlerInfoPatch(); + }, y); + + final LabelWidget readonly = new LabelWidget(0xffffff, true); + + readonly.y = y; + readonly.w = 57; + readonly.x = this.w - INLINE_PADDING * 2 - readonly.w; + this.values.put("height_readonly", readonly); + + y = addTextFieldWidget("Height", HandlerInfo.DEFAULT_HEIGHT, (field, oldText) -> { + + if (field.getInteger() != handlerInfo.getHeight()) { + handlerInfo.setHandlerDimensions(handlerInfo.getWidth(), field.getInteger()); + record.height = field.getInteger(); + saveHandlerInfoPatch(); + } + + }, y); + + y = addTextFieldWidget("Width", HandlerInfo.DEFAULT_WIDTH, (field, oldText) -> { + + if (field.getInteger() != handlerInfo.getWidth()) { + handlerInfo.setHandlerDimensions(field.getInteger(), handlerInfo.getHeight()); + record.width = field.getInteger(); + saveHandlerInfoPatch(); + } + + }, y); + + y = addCheckboxWidget("UseCustomScroll", button -> { + handlerInfo.setUseCustomScroll(button.value); + record.useCustomScroll = button.value; + saveHandlerInfoPatch(); + }, y); + + y = addCheckboxWidget("ShowFavorites", button -> { + handlerInfo.setShowFavoritesButton(button.value); + record.showFavorites = button.value; + saveHandlerInfoPatch(); + }, y); + + y = addCheckboxWidget("ShowOverlay", button -> { + handlerInfo.setShowOverlayButton(button.value); + record.showOverlay = button.value; + saveHandlerInfoPatch(); + }, y); + + this.h = 10 + LINE_HEIGHT + y; + this.container.h = this.h - INLINE_PADDING * 2 - LINE_HEIGHT; + } + + private int addInfoWidget(String key, int y) { + final LabelWidget label = new LabelWidget(0x888888, false); + final LabelWidget value = new LabelWidget(0xffffff, true); + + label.y = value.y = y; + label.w = LABEL_WIDTH; + value.x = LABEL_WIDTH + 5; + value.w = this.w - INLINE_PADDING * 2 - value.x; + + label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key)); + + this.container.addWidget(label); + this.container.addWidget(value); + this.values.put(key.toLowerCase(), value); + + return y + value.h + 1; + } + + private int addTextFieldWidget(String key, int defaultValue, BiConsumer onChange, int y) { + final LabelWidget label = new LabelWidget(0x888888, false); + final IntegerField value = new IntegerField(key, onChange, defaultValue); + + label.y = value.y = y; + value.w = 60; + value.x = this.w - INLINE_PADDING * 2 - value.w; + label.w = value.x; + + label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key)); + + this.container.addWidget(label); + this.container.addWidget(value); + + this.values.put(key.toLowerCase(), value); + + return y + value.h + 1; + } + + private int addCheckboxWidget(String key, Consumer onChange, int y) { + final LabelWidget label = new LabelWidget(0x888888, false); + final CheckboxWidget value = new CheckboxWidget(onChange); + + label.y = value.y = y; + value.w = 58; + value.x = this.w - INLINE_PADDING * 2 - value.w - 1; + label.w = value.x; + + label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key)); + + this.container.addWidget(label); + this.container.addWidget(value); + this.values.put(key.toLowerCase(), value); + + return y + value.h + 1; + } + + @Override + public void draw(int mx, int my) { + + if (this.handler != null) { + GL11.glColor4f(1F, 1F, 1F, 1F); + GL11.glScaled(1, 1, 2f); + GL11.glDisable(GL11.GL_DEPTH_TEST); + BG_TEXTURE.draw( + this.x - TRANSPARENCY_BORDER, + this.y - TRANSPARENCY_BORDER, + this.w + TRANSPARENCY_BORDER * 2, + this.h + TRANSPARENCY_BORDER * 2, + BORDER_PADDING + TRANSPARENCY_BORDER, + BORDER_PADDING + TRANSPARENCY_BORDER, + BORDER_PADDING + TRANSPARENCY_BORDER, + BORDER_PADDING + TRANSPARENCY_BORDER); + GuiDraw.drawRect( + this.x + INLINE_PADDING, + this.y + BORDER_PADDING, + this.w - INLINE_PADDING * 2, + 12, + 0x30000000); + GuiDraw.drawStringC( + NEIClientUtils.translate("debug.RecipeHandler.title"), + this.x + this.w / 2, + this.y + BORDER_PADDING + 2, + 0xffffff); + + this.container.draw(mx, my); + + GL11.glScaled(1, 1, 1 / 2f); + } + } + + @Override + public void update() { + final GuiContainer gui = NEIClientUtils.getGuiContainer(); + + if (this.showWidget && gui instanceof GuiRecipe recipe) { + + if (this.handler != recipe.getHandler()) { + this.handler = recipe.getHandler(); + this.handlerInfo = GuiRecipeTab.getHandlerInfo(handler); + this.record = this.patches.computeIfAbsent( + getHandlerID(handler), + handlerKey -> new HandlerInfoRecord(handlerKey, handlerInfo)); + + final boolean isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream() + .map(pattern -> pattern.matcher(this.handler.getHandlerId())).anyMatch(Matcher::matches); + + this.values.get("name").updateValue(this.handler.getRecipeName()); + this.values.get("id").updateValue(this.handler.getOverlayIdentifier()); + this.values.get("key").updateValue(this.handler.getHandlerId()); + this.values.get("hhack").updateValue( + isHeightHackApplied ? NEIClientUtils.translate("debug.RecipeHandler.yes") + : NEIClientUtils.translate("debug.RecipeHandler.no")); + this.values.get("modname").updateValue(this.handlerInfo.getModName()); + this.values.get("modid").updateValue(this.handlerInfo.getModId()); + + this.values.get("order").updateValue(String.valueOf(this.record.order)); + this.values.get("yshift").updateValue(String.valueOf(this.record.yShift)); + this.values.get("height").updateValue(String.valueOf(this.record.height)); + this.values.get("height_readonly").updateValue(String.valueOf(this.record.height)); + this.values.get("width").updateValue(String.valueOf(this.record.width)); + + this.values.get("multiwidgets").updateValue(String.valueOf(this.record.multiWidgets)); + this.values.get("usecustomscroll").updateValue(String.valueOf(this.record.useCustomScroll)); + + this.values.get("showfavorites").updateValue(String.valueOf(this.record.showFavorites)); + this.values.get("showoverlay").updateValue(String.valueOf(this.record.showOverlay)); + + this.values.get("override").updateValue( + this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no") + : NEIClientUtils.translate("debug.RecipeHandler.yes")); + + this.container.removeIf( + widget -> this.values.get("height") == widget || this.values.get("height_readonly") == widget); + if (handler.getRecipeHeight(0) > 0) { + this.container.addWidget((Widget) this.values.get("height_readonly")); + } else { + this.container.addWidget((Widget) this.values.get("height")); + } + + } + + } else { + this.handler = null; + this.record = null; + this.handlerInfo = null; + this.showWidget = false; + } + + this.container.update(); + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) { + return this.handler != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip; + } + + @Override + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { + return this.handler != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys; + } + + @Override + public boolean handleKeyPress(int keyID, char keyChar) { + + if (NEIClientConfig.getBooleanSetting("inventory.guirecipe.handlerInfo") && keyID == Keyboard.KEY_D + && NEIClientUtils.shiftKey()) { + this.showWidget = !this.showWidget; + return true; + } else if (this.handler != null) { + + if (this.container.handleKeyPress(keyID, keyChar)) { + return true; + } + + this.container.lastKeyTyped(keyID, keyChar); + + return this.container.isFocused(); + } + + return false; + } + + @Override + public void onGuiClick(int mx, int my) { + if (this.handler != null) { + this.container.onGuiClick(mx, my); + } + } + + @Override + public boolean handleClick(int mx, int my, int button) { + + if (this.handler != null) { + + if (new Rectangle4i(this.x + INLINE_PADDING, this.y + BORDER_PADDING, this.w - INLINE_PADDING * 2, 12) + .contains(mx, my)) { + this.dragPoint = new Point(mx, my); + } + + this.container.handleClick(mx, my, button); + } + + return this.handler != null; + } + + @Override + public boolean contains(int px, int py) { + return this.handler != null && super.contains(px, py); + } + + @Override + public void mouseUp(int mx, int my, int button) { + this.dragPoint = null; + + if (this.handler != null) { + this.container.mouseUp(mx, my, button); + } + } + + @Override + public boolean onMouseWheel(int scrolled, int mousex, int mousey) { + + if (this.handler != null && contains(mousex, mousey)) { + this.container.onMouseWheel(scrolled, mousex, mousey); + return true; + } + + return false; + } + + @Override + public boolean handleClickExt(int mx, int my, int button) { + return this.handler != null && this.container.handleClickExt(mx, my, button); + } + + @Override + public void mouseDragged(int mx, int my, int button, long heldTime) { + if (this.dragPoint != null) { + this.x -= this.dragPoint.x - mx; + this.y -= this.dragPoint.y - my; + + this.container.y = this.y + INLINE_PADDING + LINE_HEIGHT; + this.container.x = this.x + INLINE_PADDING; + + this.dragPoint.move(mx, my); + } + } + + public void drawGuiPlaceholder(NEIRecipeWidget widget) { + if (!this.showWidget) return; + + NEIClientUtils.gl2DRenderContext(() -> { + + // background + GuiDraw.drawRect( + widget.x, + widget.y, + widget.w, + widget.h, + COLORS[widget.getRecipeHandlerRef().recipeIndex % COLORS.length]); + + // center cross + GuiDraw.drawRect(widget.x + widget.w / 2 - 1, widget.y, 1, widget.h, 0x88ffffff); + GuiDraw.drawRect(widget.x, widget.y + widget.h / 2 - 1, widget.w, 1, 0x88ffffff); + + // 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.getRecipeHandlerRef().handler instanceof TemplateRecipeHandler handler) { + int yShift = widget.getHandlerInfo().getYShift(); + + for (RecipeTransferRect rect : handler.transferRects) { + GuiDraw.drawRect( + widget.x + rect.getRect().x, + widget.y + yShift + rect.getRect().y, + rect.getRect().width, + rect.getRect().height, + 0x40ff0000); + } + } + + }); + } + + public void loadHandlerInfoPatch() { + + ClientHandler.loadSettingsFile("handlers.patch", lines -> { + + for (String line : lines.collect(Collectors.toCollection(HashSet::new))) { + if (HEADER.equals(line)) continue; + final String[] parts = Arrays.copyOf((line + ",null,null,null,null,null,null,null,null").split(","), 9); + final String handler = parts[0]; + + if (GuiRecipeTab.handlerMap.containsKey(handler)) { + final HandlerInfo info = GuiRecipeTab.handlerMap.get(handler); + final HandlerInfoRecord record = patches + .computeIfAbsent(handler, handlerKey -> new HandlerInfoRecord(handler, info)); + + record.yShift = intOrDefault(parts[1], info.getYShift()); + record.height = intOrDefault(parts[2], info.getHeight()); + record.width = intOrDefault(parts[3], info.getWidth()); + record.multiWidgets = intOrDefault(parts[4], info.isMultipleWidgetsAllowed() ? 1 : 0) == 1; + record.order = intOrDefault(parts[5], NEIClientConfig.handlerOrdering.getOrDefault(handler, 0)); + record.useCustomScroll = intOrDefault(parts[6], info.getUseCustomScroll() ? 1 : 0) == 1; + record.showFavorites = intOrDefault(parts[7], info.getShowFavoritesButton() ? 1 : 0) == 1; + record.showOverlay = intOrDefault(parts[8], info.getShowOverlayButton() ? 1 : 0) == 1; + + record.applyTo(info); + } + + } + + }); + + } + + private void saveHandlerInfoPatch() { + final List lines = new ArrayList<>(); + lines.add(HEADER); + + for (HandlerInfoRecord record : patches.values()) { + if (!record.csvLine.equals(record.toCsvLine())) { + lines.add(record.toCsvLine()); + } + } + + 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) {} + + if (this.record != null) { + this.values.get("override").updateValue( + this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no") + : NEIClientUtils.translate("debug.RecipeHandler.yes")); + } + + if (NEIClientUtils.getGuiContainer() instanceof GuiReciperecipe) { + recipe.forceRefreshPage(); + } + } + + private int intOrDefault(String str, int defaultValue) { + if (str == null || str.isEmpty()) return defaultValue; + try { + return Integer.parseInt(str); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + private String getHandlerID(IRecipeHandler handler) { + + if (GuiRecipeTab.handlerMap.containsKey(handler.getHandlerId())) { + return handler.getHandlerId(); + } else if (handler instanceof TemplateRecipeHandler) { + return handler.getOverlayIdentifier(); + } + + return handler.getHandlerId(); + } + +} diff --git a/src/main/java/codechicken/nei/recipe/debug/IUpdatableWidget.java b/src/main/java/codechicken/nei/recipe/debug/IUpdatableWidget.java new file mode 100644 index 00000000..0caa5a6b --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/debug/IUpdatableWidget.java @@ -0,0 +1,7 @@ +package codechicken.nei.recipe.debug; + +public interface IUpdatableWidget { + + public void updateValue(String newValue); + +} diff --git a/src/main/java/codechicken/nei/recipe/debug/IntegerField.java b/src/main/java/codechicken/nei/recipe/debug/IntegerField.java new file mode 100644 index 00000000..9dd33dc6 --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/debug/IntegerField.java @@ -0,0 +1,94 @@ +package codechicken.nei.recipe.debug; + +import java.util.function.BiConsumer; + +import net.minecraft.client.Minecraft; + +import org.lwjgl.input.Keyboard; + +import codechicken.nei.FormattedTextField; +import codechicken.nei.TextField; + +public class IntegerField extends TextField implements IUpdatableWidget { + + protected int defaultValue = 0; + protected BiConsumer onChange; + + public IntegerField(String ident, BiConsumer onChange, int defaultValue) { + super(ident); + this.onChange = onChange; + this.defaultValue = defaultValue; + this.h = 16; + 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() { + final 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 { + Integer.parseInt(text); + return true; + } 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; + } + + public void updateValue(String newValue) { + setText(newValue); + } + + @Override + public void onTextChange(String oldText) { + onChange.accept(this, oldText); + } + +} diff --git a/src/main/java/codechicken/nei/recipe/debug/LabelWidget.java b/src/main/java/codechicken/nei/recipe/debug/LabelWidget.java new file mode 100644 index 00000000..3918de13 --- /dev/null +++ b/src/main/java/codechicken/nei/recipe/debug/LabelWidget.java @@ -0,0 +1,74 @@ +package codechicken.nei.recipe.debug; + +import java.awt.Point; +import java.util.List; +import java.util.Map; + +import net.minecraft.client.gui.GuiScreen; + +import org.lwjgl.input.Keyboard; + +import codechicken.lib.gui.GuiDraw; +import codechicken.nei.NEIClientUtils; +import codechicken.nei.Widget; +import codechicken.nei.util.NEIMouseUtils; + +public class LabelWidget extends Widget implements IUpdatableWidget { + + protected int color; + protected boolean shadow; + protected String value = ""; + protected String croppedValue; + + public LabelWidget(int color, boolean shadow) { + this.color = color; + this.shadow = shadow; + this.h = 16; + this.z = 2; + } + + @Override + public void draw(int mx, int my) { + GuiDraw.drawString(this.croppedValue, this.x, this.y + (this.h - 8) / 2, this.color, this.shadow); + } + + public void updateValue(String newValue) { + this.value = newValue; + this.croppedValue = NEIClientUtils.cropText(GuiDraw.fontRenderer, this.value, this.w); + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) { + + if (contains(mx, my)) { + tooltip.add(this.value); + } + + return tooltip; + } + + @Override + public boolean handleKeyPress(int keyID, char keyChar) { + final Point mouse = GuiDraw.getMousePosition(); + + if (contains(mouse.x, mouse.y) && Keyboard.KEY_C == keyID && NEIClientUtils.controlKey()) { + GuiScreen.setClipboardString(this.value); + return true; + } + + return false; + } + + @Override + public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { + + if (contains(mousex, mousey)) { + hotkeys.put( + NEIClientUtils.getKeyName(NEIClientUtils.CTRL_HASH + Keyboard.KEY_C, NEIMouseUtils.MOUSE_BTN_NONE), + NEIClientUtils.translate("debug.RecipeHandler.copy")); + } + + return hotkeys; + } + +} diff --git a/src/main/java/codechicken/nei/scroll/ScrollContainer.java b/src/main/java/codechicken/nei/scroll/ScrollContainer.java index 28143d21..faf11cb9 100644 --- a/src/main/java/codechicken/nei/scroll/ScrollContainer.java +++ b/src/main/java/codechicken/nei/scroll/ScrollContainer.java @@ -2,6 +2,7 @@ package codechicken.nei.scroll; import java.awt.Point; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.function.Predicate; @@ -38,7 +39,7 @@ public class ScrollContainer extends WidgetContainer { protected int paddingBlockStart = 0; protected int paddingBlockEnd = 0; - protected final Map relativePostion = new HashMap<>(); + protected final Map relativePosition = new HashMap<>(); protected ScrollBar horizontalScrollBar; protected ScrollBar verticalScrollBar; protected int fade = 0; @@ -80,23 +81,40 @@ public class ScrollContainer extends WidgetContainer { @Override public void clear() { + + for (Map.Entry entry : this.relativePosition.entrySet()) { + entry.getKey().x = entry.getValue().x; + entry.getKey().y = entry.getValue().y; + } + super.clear(); - this.relativePostion.clear(); + this.relativePosition.clear(); } @Override public boolean removeIf(Predicate filter) { - this.relativePostion.keySet().removeIf(filter); + final Iterator> it = this.relativePosition.entrySet().iterator(); + + while (it.hasNext()) { + final Map.Entry entry = it.next(); + + if (filter.test(entry.getKey())) { + entry.getKey().x = entry.getValue().x; + entry.getKey().y = entry.getValue().y; + it.remove(); + } + } + return super.removeIf(filter); } public void addWidget(Widget widget) { super.addWidget(widget); - this.relativePostion.put(widget, new Point(widget.x, widget.y)); + this.relativePosition.put(widget, new Point(widget.x, widget.y)); } public Point getWidgetPosition(Widget widget) { - return this.relativePostion.get(widget); + return this.relativePosition.get(widget); } public void setPaddingInline(int start, int end) { @@ -275,7 +293,7 @@ public class ScrollContainer extends WidgetContainer { this.actualHeight = 0; this.actualWidth = 0; - for (Map.Entry entry : this.relativePostion.entrySet()) { + for (Map.Entry entry : this.relativePosition.entrySet()) { entry.getKey().x = entry.getValue().x; entry.getKey().y = entry.getValue().y; } @@ -385,6 +403,10 @@ public class ScrollContainer extends WidgetContainer { @Override public boolean handleKeyPress(int keyCode, char keyChar) { + if (super.handleKeyPress(keyCode, keyChar)) { + return true; + } + if (this.isFocused()) { switch (keyCode) { case Keyboard.KEY_UP: @@ -402,7 +424,7 @@ public class ScrollContainer extends WidgetContainer { } } - return super.handleKeyPress(keyCode, keyChar); + return false; } } diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index e991c6c3..477305e5 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -525,6 +525,7 @@ nei.options.tools.dump.handlers.mode.0=CSV nei.options.tools.dump.handlers.mode.1=Json nei.debug.RecipeHandler.title=Debug Recipe Handler +nei.debug.RecipeHandler.copy=Copy nei.debug.RecipeHandler.Name=Name nei.debug.RecipeHandler.Id=ID nei.debug.RecipeHandler.Key=Key @@ -536,7 +537,14 @@ nei.debug.RecipeHandler.yShift=yShift nei.debug.RecipeHandler.MultiWidgets=Multi Widgets nei.debug.RecipeHandler.Height=Height nei.debug.RecipeHandler.Width=Width +nei.debug.RecipeHandler.ShowFavorites=Show Favorites +nei.debug.RecipeHandler.ShowOverlay=Show Overlays nei.debug.RecipeHandler.UseCustomScroll=Use Custom Scroll +nei.debug.RecipeHandler.Override=Override +nei.debug.RecipeHandler.checkbox.on=On +nei.debug.RecipeHandler.checkbox.off=Off +nei.debug.RecipeHandler.yes=Yes +nei.debug.RecipeHandler.no=No nei.recipe.page=Page %s/%s nei.recipe.tooltip=Recipes