diff options
| author | Conutik <60240193+Conutik@users.noreply.github.com> | 2024-08-04 17:11:44 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-04 16:11:44 +0200 |
| commit | 17bce62559a449f770602512603a3af88b663b18 (patch) | |
| tree | 0dcd39bba5915aae8f1e0b960f43dab56a08d8e2 | |
| parent | 30fea5f435098d2089444952d8bc02db5dcf41e7 (diff) | |
| download | notenoughupdates-17bce62559a449f770602512603a3af88b663b18.tar.gz notenoughupdates-17bce62559a449f770602512603a3af88b663b18.tar.bz2 notenoughupdates-17bce62559a449f770602512603a3af88b663b18.zip | |
Add Recipe Search Overlay (#1045)
Co-authored-by: nopo <nopotheemail@gmail.com>
10 files changed, 708 insertions, 14 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 43035ca8..f9e55203 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -408,6 +408,11 @@ public class NEUManager { return getRecipesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList()); } + public HashMap<String, Set<NeuRecipe>> getAllRecipes() { + return recipesMap; + + } + public Set<NeuRecipe> getUsagesFor(String internalName) { return usagesMap.getOrDefault(internalName, Collections.emptySet()); } @@ -421,12 +426,11 @@ public class NEUManager { String match; DebugMatch(int index, String match) { - this.index = index; - this.match = match; + this.index = index; + this.match = match; } } - private String searchDebug(String[] searchArray, ArrayList<DebugMatch> debugMatches) { //splitToSearch, debugMatches and query final String ANSI_RED = "\u001B[31m"; @@ -502,10 +506,10 @@ public class NEUManager { for (int k = 0; k < splitToSearch.length; k++) { if (queryIndex - 1 != -1 && (queryArray.length - queryIndex) > (splitToSearch.length - k)) continue; if (splitToSearch[k].startsWith(currentSearch)) { - if (((lastStringMatch != -1 ? lastStringMatch : k-1) == k-1)) { + if (((lastStringMatch != -1 ? lastStringMatch : k - 1) == k - 1)) { debugMatches.add(new DebugMatch(k, currentSearch)); lastStringMatch = k; - if (queryIndex+1 != queryArray.length) { + if (queryIndex + 1 != queryArray.length) { queryIndex++; currentSearch = queryArray[queryIndex]; } else { @@ -521,11 +525,13 @@ public class NEUManager { if (matchedLastQueryItem) { if (NEUDebugFlag.SEARCH.isSet()) { - NotEnoughUpdates.LOGGER.info("Found match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + searchDebug(splitToSearch, debugMatches)); + NotEnoughUpdates.LOGGER.info("Found match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + + searchDebug(splitToSearch, debugMatches)); } } else { if (NEUDebugFlag.SEARCH.isSet() && lastStringMatch != -1) { - NotEnoughUpdates.LOGGER.info("Found partial match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + searchDebug(splitToSearch, debugMatches)); + NotEnoughUpdates.LOGGER.info("Found partial match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + + searchDebug(splitToSearch, debugMatches)); } } @@ -569,12 +575,12 @@ public class NEUManager { result = result || multiSearchString(stack.getDisplayName(), sb.toString()); } - result = result || multiSearchString(stack.getDisplayName(), query); String lore = ""; - if (stack.getItem() instanceof ItemArmor && ((ItemArmor)stack.getItem()).getArmorMaterial() == ItemArmor.ArmorMaterial.LEATHER) { - lore = String.format("#%06x ",((ItemArmor)stack.getItem()).getColor(stack)); + if (stack.getItem() instanceof ItemArmor && + ((ItemArmor) stack.getItem()).getArmorMaterial() == ItemArmor.ArmorMaterial.LEATHER) { + lore = String.format("#%06x ", ((ItemArmor) stack.getItem()).getColor(stack)); } NBTTagCompound tag = stack.getTagCompound(); if (tag != null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java index f4ca5fe6..a0c8473a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -46,6 +46,7 @@ import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; +import io.github.moulberry.notenoughupdates.overlays.RecipeSearchOverlay; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewerUtils; @@ -954,6 +955,15 @@ public class RenderListener { }); } } + } else if (containerName.equals("Craft Item") && BetterContainers.recipeSearchStackIndex != -1 && + ((AccessorGuiContainer) eventGui).doIsMouseOverSlot( + cc.inventorySlots.get(BetterContainers.recipeSearchStackIndex), + mouseX, + mouseY + ) && + Mouse.getEventButton() >= 0) { + event.setCanceled(true); + NotEnoughUpdates.INSTANCE.openGui = new RecipeSearchOverlay(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java index c32b2b60..431a029a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java @@ -75,6 +75,7 @@ public class BetterContainers { private static final int lastHashcodeCheck = 0; public static int profileViewerStackIndex = -1; + public static int recipeSearchStackIndex = -1; public static void clickSlot(int slot) { clickedSlotMillis = System.currentTimeMillis(); @@ -141,6 +142,10 @@ public class BetterContainers { return false; } + if (index != -1 && index == recipeSearchStackIndex) { + return false; + } + return stack != null && stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) && stack.getItemDamage() == 15 && stack.getDisplayName() != null && stack.getDisplayName().trim().isEmpty(); @@ -155,6 +160,10 @@ public class BetterContainers { return true; } + if (index == recipeSearchStackIndex) { + return true; + } + return stack != null && stack.getItem() != Item.getItemFromBlock(Blocks.stained_glass_pane) && NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack) == null && !isToggleOn(stack) && !isToggleOff( stack); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index 75b78d9b..6d8992fc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -47,6 +47,7 @@ import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; @@ -69,11 +70,17 @@ import java.util.Set; @Mixin(value = GuiContainer.class, priority = 500) public abstract class MixinGuiContainer extends GuiScreen { private static boolean hasProfileViewerStack = false; + private static boolean hasRecipeSearchStack = false; private static final ItemStack profileViewerStack = Utils.createItemStack( Item.getItemFromBlock(Blocks.command_block), EnumChatFormatting.GREEN + "Profile Viewer", EnumChatFormatting.YELLOW + "Click to open NEU profile viewer!" ); + private static final ItemStack recipeSearchStack = Utils.createItemStack( + Items.golden_pickaxe, + EnumChatFormatting.GREEN + "Recipe Search", + EnumChatFormatting.YELLOW + "Click to open Recipe Search!" + ); @Inject(method = "drawSlot", at = @At("RETURN")) public void drawSlotRet(Slot slotIn, CallbackInfo ci) { @@ -128,10 +135,43 @@ public abstract class MixinGuiContainer extends GuiScreen { } } } - } else if (slot.getSlotIndex() == 0) + } else if (!hasRecipeSearchStack && $this instanceof GuiChest && slot.getSlotIndex() == 32 && + BetterContainers.isBlankStack(-1, slot.getStack())) { + BetterContainers.recipeSearchStackIndex = -1; + hasRecipeSearchStack = true; + + GuiChest eventGui = (GuiChest) $this; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.equals("Craft Item") && cc.inventorySlots.size() >= 54) { + ci.cancel(); + + this.zLevel = 100.0F; + this.itemRender.zLevel = 100.0F; + + GlStateManager.enableDepth(); + this.itemRender.renderItemAndEffectIntoGUI( + recipeSearchStack, + slot.xDisplayPosition, + slot.yDisplayPosition + ); + this.itemRender.renderItemOverlayIntoGUI(this.fontRendererObj, recipeSearchStack, + slot.xDisplayPosition, slot.yDisplayPosition, "" + ); + + this.itemRender.zLevel = 0.0F; + this.zLevel = 0.0F; + BetterContainers.recipeSearchStackIndex = slot.getSlotIndex(); + } else { + BetterContainers.recipeSearchStackIndex = -1; + } + } else if (slot.getSlotIndex() == 0) { hasProfileViewerStack = false; - else if (!($this instanceof GuiChest)) + hasRecipeSearchStack = false; + } else if (!($this instanceof GuiChest)) { + BetterContainers.recipeSearchStackIndex = -1; BetterContainers.profileViewerStackIndex = -1; + } if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock()) { @@ -175,6 +215,8 @@ public abstract class MixinGuiContainer extends GuiScreen { public ItemStack adjustItemStack(ItemStack itemStack) { if (theSlot.slotNumber == BetterContainers.profileViewerStackIndex) { return profileViewerStack; + } else if (theSlot.slotNumber == BetterContainers.recipeSearchStackIndex) { + return recipeSearchStack; } else { return itemStack; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java index 297a8afb..1a31e30e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -64,6 +64,7 @@ import io.github.moulberry.notenoughupdates.options.separatesections.Museum; import io.github.moulberry.notenoughupdates.options.separatesections.Notifications; import io.github.moulberry.notenoughupdates.options.separatesections.PetOverlay; import io.github.moulberry.notenoughupdates.options.separatesections.ProfileViewer; +import io.github.moulberry.notenoughupdates.options.separatesections.RecipeTweaks; import io.github.moulberry.notenoughupdates.options.separatesections.SkillOverlays; import io.github.moulberry.notenoughupdates.options.separatesections.SlayerOverlay; import io.github.moulberry.notenoughupdates.options.separatesections.SlotLocking; @@ -464,6 +465,13 @@ public class NEUConfig extends Config { @Expose @Category( + name = "Recipe Tweaks", + desc = "Tweaks for the Recipe Search" + ) + public RecipeTweaks recipeTweaks = new RecipeTweaks(); + + @Expose + @Category( name = "Price Graph", desc = "Graph of auction and bazaar prices" ) @@ -567,6 +575,8 @@ public class NEUConfig extends Config { @Expose public ArrayList<String> previousProfileSearches = new ArrayList<>(); @Expose + public ArrayList<String> previousRecipeSearches = new ArrayList<>(); + @Expose public ArrayList<String> eventFavourites = new ArrayList<>(); @Expose public ArrayList<String> quickCommands = createDefaultQuickCommands(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/RecipeTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/RecipeTweaks.java new file mode 100644 index 00000000..8124cb0e --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/RecipeTweaks.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2024 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.options.separatesections; + +import com.google.gson.annotations.Expose; +import io.github.moulberry.moulconfig.annotations.ConfigAccordionId; +import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion; +import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean; +import io.github.moulberry.moulconfig.annotations.ConfigEditorSlider; +import io.github.moulberry.moulconfig.annotations.ConfigOption; + +public class RecipeTweaks { + + @ConfigOption( + name = "Search GUI", + desc = "" + ) + @ConfigEditorAccordion(id = 0) + public boolean searchAccordion = false; + + @Expose + @ConfigOption( + name = "Enable Search GUI", + desc = "Use the advanced search GUI with autocomplete and history instead of the normal sign GUI" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean enableSearchOverlay = true; + + @Expose + @ConfigOption( + name = "Keep Previous Search", + desc = "Don't clear the search bar after closing the GUI" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean keepPreviousSearch = false; + + @Expose + @ConfigOption( + name = "Past Searches", + desc = "Show past searches below the autocomplete box" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean showPastSearches = true; + + @Expose + @ConfigOption( + name = "ESC to Full Close", + desc = "Make pressing ESCAPE close the search GUI without opening up the Craft menu again\n" + + "ENTER can still be used to search" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean escFullClose = true; + + @Expose + @ConfigOption( + name = "Search History Size", + desc = "Changes how many search items get stored" + ) + @ConfigEditorSlider( + minValue = 1, + maxValue = 15, + minStep = 1 + ) + @ConfigAccordionId(id = 0) + public int recipeSearchHistorySize = 5; + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java index c9d229b7..2a000540 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java @@ -184,7 +184,7 @@ public class AuctionSearchOverlay extends GuiScreen { String str = autoCompletedItemsArray[i]; JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str); if (obj != null) { - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj); + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj, false, true); //Gui.drawRect(width/2-96, height/4+30+num*22, width/2+96, height/4+30+num*22+20, 0xff505050); if (i == tabCompletionIndex) { Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java index 65da8972..7ab97026 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java @@ -136,7 +136,7 @@ public class BazaarSearchOverlay extends GuiScreen { String str = autoCompletedItemsArray[i]; JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str); if (obj != null) { - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj); + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj, false, true); if (i == tabCompletionIndex) { Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED); GlStateManager.color(1, 1, 1, 1); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/RecipeSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/RecipeSearchOverlay.java new file mode 100644 index 00000000..7e2de87c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/RecipeSearchOverlay.java @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.overlays; + +import com.google.common.base.Splitter; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; +import io.github.moulberry.notenoughupdates.commands.help.SettingsCommand; +import io.github.moulberry.notenoughupdates.core.GuiElementTextField; +import io.github.moulberry.notenoughupdates.events.SlotClickEvent; +import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; +import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe; +import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@NEUAutoSubscribe +public class RecipeSearchOverlay extends GuiScreen { + private static final ResourceLocation SEARCH_OVERLAY_TEXTURE = new ResourceLocation( + "notenoughupdates:auc_search/ah_search_overlay.png"); + private static final ResourceLocation SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED = new ResourceLocation( + "notenoughupdates:auc_search/ah_search_overlay_tab_completed.png"); + + private static final GuiElementTextField textField = new GuiElementTextField("", 200, 20, 0); + private static boolean searchFieldClicked = false; + private static String searchString = ""; + private static String searchStringExtra = ""; + private static final Splitter SPACE_SPLITTER = Splitter.on(" ").omitEmptyStrings().trimResults(); + private static boolean tabCompleted = false; + private static int tabCompletionIndex = -1; + private static final Pattern ENCHANTED_BOOK_PATTERN = Pattern.compile("(.*)( [IVX]+)"); + + private static final int AUTOCOMPLETE_HEIGHT = 118; + + private static final Set<String> autocompletedItems = new LinkedHashSet<>(); + + public RecipeSearchOverlay() { + super(); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + super.drawDefaultBackground(); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + int h = NotEnoughUpdates.INSTANCE.config.recipeTweaks.showPastSearches ? 219 : 145; + + int topY = height / 4; + if (scaledResolution.getScaleFactor() >= 4) { + topY = height / 2 - h / 2 + 5; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(width / 2 - 100, topY - 1, 203, 145, 0, 203 / 512f, 0, 145 / 256f, GL11.GL_NEAREST); + + Minecraft.getMinecraft().fontRendererObj.drawString("Enter Query:", width / 2 - 100, topY - 10, 0xdddddd, true); + + textField.setFocus(true); + textField.setText(searchString); + textField.setSize(149, 20); + textField.setCustomBorderColour(0xffffff); + textField.render(width / 2 - 100 + 1, topY + 1); + + if (textField.getText().trim().isEmpty()) autocompletedItems.clear(); + + List<String> tooltipToDisplay = null; + + int num = 0; + synchronized (autocompletedItems) { + String[] autoCompletedItemsArray = autocompletedItems.toArray(new String[0]); + for (int i = 0; i < autoCompletedItemsArray.length; i++) { + String str = autoCompletedItemsArray[i]; + JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str); + if (obj != null) { + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj, false, true); + if (i == tabCompletionIndex) { + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect( + width / 2 - 96 + 1, + topY + 30 + num * 22 + 1, + 193, + 21, + 0 / 512f, + 193 / 512f, + 0, + 21 / 256f, + GL11.GL_NEAREST + ); + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect( + width / 2 - 96 + 1, + topY + 30 + num * 22 + 1, + 193, + 21, + 214 / 512f, + 407 / 512f, + 0, + 21 / 256f, + GL11.GL_NEAREST + ); + + } + String itemName = Utils.trimIgnoreColour(stack.getDisplayName().replaceAll("\\[.+]", "")); + if (itemName.contains("Enchanted Book") && str.contains(";")) { + String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); + itemName = lore[0].trim(); + } + + Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().fontRendererObj.trimStringToWidth( + itemName, + 165 + ), width / 2 - 74, topY + 35 + num * 22 + 1, 0xdddddd, true); + + GlStateManager.enableDepth(); + Utils.drawItemStack(stack, width / 2 - 94 + 2, topY + 32 + num * 22 + 1); + + if (mouseX > width / 2 - 96 && mouseX < width / 2 + 96 && mouseY > topY + 30 + num * 22 && + mouseY < topY + 30 + num * 22 + 20) { + tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + + if (++num >= 5) break; + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.recipeTweaks.showPastSearches) { + Minecraft.getMinecraft().fontRendererObj.drawString( + "Past Searches:", + width / 2 - 100, + topY + 25 + AUTOCOMPLETE_HEIGHT + 5, + 0xdddddd, + true + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + Utils.drawTexturedRect(width / 2 - 100, topY - 1 + 160, 203, 4, 0, 203 / 512f, 160 / 256f, 163 / 256f, GL11.GL_NEAREST); + + for (int i = 0; i < NotEnoughUpdates.INSTANCE.config.recipeTweaks.recipeSearchHistorySize; i++) { + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + Utils.drawTexturedRect(width / 2 - 100, topY - 1 + 160 + 4 + i * 10, 203, 10, 0, 203 / 512f, 164 / 256f, 174 / 256f, GL11.GL_NEAREST); + if (i >= NotEnoughUpdates.INSTANCE.config.hidden.previousRecipeSearches.size()) continue; + + String s = NotEnoughUpdates.INSTANCE.config.hidden.previousRecipeSearches.get(i); + Minecraft.getMinecraft().fontRendererObj.drawString( + s, + width / 2 - 95 + 1, + topY + 45 + AUTOCOMPLETE_HEIGHT + i * 10 + 2, + 0xdddddd, + true + ); + } + + int size = NotEnoughUpdates.INSTANCE.config.recipeTweaks.recipeSearchHistorySize; + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + Utils.drawTexturedRect(width / 2 - 100, topY - 1 + 160 + 4 + size * 10, 203, 4, 0, 203 / 512f, 215 / 256f, 219 / 256f, GL11.GL_NEAREST); + + if (tooltipToDisplay != null) { + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1); + } + } + + } + + private static final ExecutorService searchES = Executors.newSingleThreadExecutor(); + private static final AtomicInteger searchId = new AtomicInteger(0); + + private static String getItemIdAtIndex(int i) { + if (!autocompletedItems.isEmpty()) { + if ((i > autocompletedItems.size() - 1) || i < 0 || i > 4) { + return ""; + } + String searchString = autocompletedItems.toArray()[i].toString(); + JsonObject repoObject = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(searchString); + if (repoObject != null) { + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(repoObject); + return Utils.cleanColour(stack.getDisplayName().replaceAll("\\[.+]", "")); + } + + } + return null; + } + + public static void close() { + if (tabCompleted) { + tabCompletionIndex = -1; + tabCompleted = false; + } + if (NotEnoughUpdates.INSTANCE.config.recipeTweaks.keepPreviousSearch) { + search(); + } else { + synchronized (autocompletedItems) { + autocompletedItems.clear(); + } + } + + StringBuilder stringBuilder = new StringBuilder(searchString.trim()); + if (!searchStringExtra.isEmpty()) { + stringBuilder.append(searchStringExtra); + } + + String search = stringBuilder.toString(); + + if (search.isEmpty()) return; + + Minecraft.getMinecraft().thePlayer.sendChatMessage("/recipe " + search); + + if (!searchString.trim().isEmpty()) { + List<String> previousRecipeSearches = NotEnoughUpdates.INSTANCE.config.hidden.previousRecipeSearches; + previousRecipeSearches.remove(searchString); + previousRecipeSearches.remove(searchString); + previousRecipeSearches.add(0, searchString); + while (previousRecipeSearches.size() > NotEnoughUpdates.INSTANCE.config.recipeTweaks.recipeSearchHistorySize) { + previousRecipeSearches.remove(previousRecipeSearches.size() - 1); + } + } + + BetterContainers.recipeSearchStackIndex = -1; + if (!NotEnoughUpdates.INSTANCE.config.recipeTweaks.keepPreviousSearch) searchString = ""; + } + + private static boolean updateTabCompletedSearch(int key) { + String id; + if (key == Keyboard.KEY_DOWN || key == Keyboard.KEY_TAB) { + id = getItemIdAtIndex(tabCompletionIndex + 1); + if (id == null) { + textField.setFocus(true); + textField.setText(searchString); + tabCompleted = false; + tabCompletionIndex = -1; + return true; + } else if (id.equals("")) { + tabCompletionIndex = 0; + return true; + } else { + searchString = id; + tabCompletionIndex += 1; + return true; + } + } else if (key == Keyboard.KEY_UP) { + id = getItemIdAtIndex(tabCompletionIndex - 1); + if (id == null) { + textField.setFocus(true); + textField.setText(searchString); + tabCompleted = false; + tabCompletionIndex = -1; + return true; + } else if (id.equals("")) { + if (autocompletedItems.size() > 4) tabCompletionIndex = 4; + else tabCompletionIndex = autocompletedItems.size() - 1; + tabCompletionIndex = autocompletedItems.size() - 1; + return true; + } else { + searchString = id; + tabCompletionIndex -= 1; + return true; + } + } + return false; + } + + public static void search() { + final int thisSearchId = searchId.incrementAndGet(); + + searchES.submit(() -> { + if (thisSearchId != searchId.get()) return; + + List<String> title = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("title:" + searchString.trim())); + + if (thisSearchId != searchId.get()) return; + + if (!searchString.trim().contains(" ")) { + StringBuilder sb = new StringBuilder(); + for (char c : searchString.toCharArray()) { + sb.append(c).append(" "); + } + title.addAll(NotEnoughUpdates.INSTANCE.manager.search("title:" + sb.toString().trim())); + } + + if (thisSearchId != searchId.get()) return; + + List<String> desc = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("desc:" + searchString.trim())); + desc.removeAll(title); + + if (thisSearchId != searchId.get()) return; + + HashMap<String, Set<NeuRecipe>> items = NotEnoughUpdates.INSTANCE.manager.getAllRecipes(); + + List<String> keys = new ArrayList<>(); + + for (Map.Entry<String, Set<NeuRecipe>> entry : items.entrySet()) { + for (NeuRecipe recipe : entry.getValue()) { + if (recipe instanceof CraftingRecipe && recipe.isAvailable()) keys.add(entry.getKey()); + } + } + title.retainAll(keys); + desc.retainAll(keys); + + if (thisSearchId != searchId.get()) return; + + synchronized (autocompletedItems) { + autocompletedItems.clear(); + autocompletedItems.addAll(title); + autocompletedItems.addAll(desc); + } + }); + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + super.keyTyped(typedChar, keyCode); + boolean ignoreKey = false; + + if (keyCode == Keyboard.KEY_ESCAPE) { + searchStringExtra = ""; + if (NotEnoughUpdates.INSTANCE.config.recipeTweaks.escFullClose) { + Minecraft.getMinecraft().displayGuiScreen(null); + } else { + close(); + } + return; + } else if (keyCode == Keyboard.KEY_RETURN) { + searchStringExtra = ""; + close(); + return; + } else if (keyCode == Keyboard.KEY_TAB) { + //autocomplete to first item in the list + if (!tabCompleted) { + tabCompleted = true; + ignoreKey = true; + String id = getItemIdAtIndex(0); + if (id == null) { + tabCompleted = false; + textField.setFocus(true); + textField.setText(searchString); + } else { + tabCompletionIndex = 0; + searchString = id; + } + } + } + + if (Keyboard.getEventKeyState()) { + if (tabCompleted) { + if (!ignoreKey) { + boolean success = updateTabCompletedSearch(keyCode); + if (success) return; + textField.setFocus(true); + textField.setText(searchString); + tabCompleted = false; + tabCompletionIndex = -1; + } else return; + + } + textField.setFocus(true); + textField.setText(searchString); + textField.keyTyped(Keyboard.getEventCharacter(), keyCode); + searchString = textField.getText(); + + search(); + } + } + + @Override + public void handleMouseInput() throws IOException { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + int h = NotEnoughUpdates.INSTANCE.config.recipeTweaks.showPastSearches ? 219 : 145; + + int topY = height / 4; + if (scaledResolution.getScaleFactor() >= 4) { + topY = height / 2 - h / 2 + 5; + } + + if (!Mouse.getEventButtonState() && Mouse.getEventButton() == -1 && searchFieldClicked) { + textField.mouseClickMove(mouseX - 2, topY + 10, 0, 0); + } + + if (Mouse.getEventButton() != -1) { + searchFieldClicked = false; + } + + if (Mouse.getEventButtonState()) { + if (mouseY > topY && mouseY < topY + 20) { + if (mouseX > width / 2 - 100) { + if (mouseX < width / 2 + 49) { + searchFieldClicked = true; + textField.mouseClicked(mouseX - 2, mouseY, Mouse.getEventButton()); + + if (Mouse.getEventButton() == 1) { + searchString = ""; + synchronized (autocompletedItems) { + autocompletedItems.clear(); + } + } + } else if (mouseX < width / 2 + 75) { + searchStringExtra = ""; + close(); |
