aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConutik <60240193+Conutik@users.noreply.github.com>2024-08-04 17:11:44 +0300
committerGitHub <noreply@github.com>2024-08-04 16:11:44 +0200
commit17bce62559a449f770602512603a3af88b663b18 (patch)
tree0dcd39bba5915aae8f1e0b960f43dab56a08d8e2
parent30fea5f435098d2089444952d8bc02db5dcf41e7 (diff)
downloadnotenoughupdates-17bce62559a449f770602512603a3af88b663b18.tar.gz
notenoughupdates-17bce62559a449f770602512603a3af88b663b18.tar.bz2
notenoughupdates-17bce62559a449f770602512603a3af88b663b18.zip
Add Recipe Search Overlay (#1045)
Co-authored-by: nopo <nopotheemail@gmail.com>
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java26
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java10
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java9
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java46
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java10
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/RecipeTweaks.java88
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/RecipeSearchOverlay.java520
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/commands/misc/SearchCommand.kt9
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();