mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-15 09:44:44 +00:00
Compare commits
83
Commits
2.5.18-GTNH
...
2.7.27
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48934d621f | ||
|
|
0bbb889f39 | ||
|
|
af55a6b191 | ||
|
|
b3e1f23683 | ||
|
|
39578a4419 | ||
|
|
e3574800c0 | ||
|
|
5cd7556e6a | ||
|
|
80c2cba778 | ||
|
|
31173a1fbd | ||
|
|
fd08a93554 | ||
|
|
4dace1f6e5 | ||
|
|
0c0cf37eb0 | ||
|
|
3ec4f8dd68 | ||
|
|
e0dd6847cb | ||
|
|
6374c162ba | ||
|
|
8dd36f1c4a | ||
|
|
4613ade468 | ||
|
|
ca7030df72 | ||
|
|
b32f25c2ce | ||
|
|
4be7a30578 | ||
|
|
7ac3e32635 | ||
|
|
088d37a11a | ||
|
|
6a787dd5b7 | ||
|
|
c305649b95 | ||
|
|
b5d2815eab | ||
|
|
6049d0e9c3 | ||
|
|
9288fc4575 | ||
|
|
ec749ecc8e | ||
|
|
7471a82bca | ||
|
|
3f3c1791cb | ||
|
|
a0e16835c2 | ||
|
|
e9ce5cf72b | ||
|
|
fac011b67e | ||
|
|
f9c8ac504e | ||
|
|
f97711a33a | ||
|
|
b2934c4910 | ||
|
|
759ea69c9f | ||
|
|
36a2cafdac | ||
|
|
6100012f5b | ||
|
|
2e5781beb5 | ||
|
|
43918f3bb1 | ||
|
|
a41299dfca | ||
|
|
ee060b9253 | ||
|
|
82a2273995 | ||
|
|
06fadcc362 | ||
|
|
b328fd3db1 | ||
|
|
9563ebfe5a | ||
|
|
d9143c584e | ||
|
|
65652e5896 | ||
|
|
bd5e991a84 | ||
|
|
165afa2910 | ||
|
|
2507634196 | ||
|
|
e0171adc65 | ||
|
|
72ad8aa2e7 | ||
|
|
f0a554bcc1 | ||
|
|
65781a1649 | ||
|
|
6ad8f05323 | ||
|
|
d61a545d9d | ||
|
|
1774685af6 | ||
|
|
a63a227c3c | ||
|
|
0f115d5439 | ||
|
|
0fad93fb3b | ||
|
|
b1a34c761b | ||
|
|
cc9715d9f2 | ||
|
|
be253a00d2 | ||
|
|
5dde3b2e2f | ||
|
|
8da541460f | ||
|
|
dc4426d9c9 | ||
|
|
d05a9eafb3 | ||
|
|
5056fe5437 | ||
|
|
9fd9aad357 | ||
|
|
acaead41ee | ||
|
|
951f1b0d0d | ||
|
|
daab313288 | ||
|
|
25eaa492f7 | ||
|
|
1b34b24495 | ||
|
|
b9cd48f8f9 | ||
|
|
b2afc8c9e0 | ||
|
|
dc400ea560 | ||
|
|
ea03cfa17d | ||
|
|
94676e0934 | ||
|
|
f7ba34c0af | ||
|
|
db1fd255bb |
No files matched your search
@@ -0,0 +1,62 @@
|
||||
name: Report Bug
|
||||
description: "Report a bug."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "A bug/crash report with sufficient information and logs to reproduce and track down."
|
||||
- type: input
|
||||
id: discord
|
||||
attributes:
|
||||
label: Your GTNH Discord Username
|
||||
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
|
||||
placeholder: "Example: Fake#1234"
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Mod Version
|
||||
description: "What version of the Mod are you using?"
|
||||
placeholder: "Example: 1.0.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: report
|
||||
attributes:
|
||||
label: Bug Report
|
||||
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: java
|
||||
attributes:
|
||||
label: Java Version
|
||||
description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version.
|
||||
options:
|
||||
- Java 8
|
||||
- Java 9
|
||||
- Java 11
|
||||
- Java 17
|
||||
- Java 19
|
||||
- Java 20
|
||||
- Java 21
|
||||
- Other (Please Specify)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: modlist
|
||||
attributes:
|
||||
label: Mod List or GTNH Pack Version
|
||||
description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist."
|
||||
placeholder: "List of mods or GTNH Pack version goes here"
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: final
|
||||
attributes:
|
||||
label: Final Checklist
|
||||
description: Certify that you read things
|
||||
options:
|
||||
- label: "I have searched the issues and haven't found a similar issue."
|
||||
required: true
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Feature Request
|
||||
description: "Request a feature."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please use this form to request features. We ask you check if it was already requested though"
|
||||
- type: input
|
||||
id: discord
|
||||
attributes:
|
||||
label: Your GTNH Discord Username
|
||||
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
|
||||
placeholder: "Example: Wumpus#1234"
|
||||
- type: textarea
|
||||
id: request
|
||||
attributes:
|
||||
label: Feature Request
|
||||
description: "Relevant information, as well as relevant images"
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: final
|
||||
attributes:
|
||||
label: Final Checklist
|
||||
description: Certify that you read things
|
||||
options:
|
||||
- label: "I have searched the issues and haven't found a similar issue."
|
||||
required: true
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
api('com.github.GTNewHorizons:CodeChickenLib:1.2.1:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.2.1:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.4.1:dev')
|
||||
implementation('com.github.GTNewHorizons:GTNHLib:0.6.5:dev')
|
||||
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
|
||||
}
|
||||
+16
-5
@@ -41,11 +41,11 @@ developmentEnvironmentUserName = Developer
|
||||
|
||||
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
|
||||
# See https://github.com/bsideup/jabel for details on how this works.
|
||||
enableModernJavaSyntax = false
|
||||
enableModernJavaSyntax = true
|
||||
|
||||
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||
enableGenericInjection = false
|
||||
enableGenericInjection = true
|
||||
|
||||
# Generate a class with a String field for the mod version named as defined below.
|
||||
# If generateGradleTokenClass is empty or not missing, no such class will be generated.
|
||||
@@ -85,6 +85,11 @@ accessTransformersFile = nei_at.cfg
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
|
||||
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||
# Mixin classes will have access to "main" classes, but not the other way around.
|
||||
separateMixinSourceSet =
|
||||
|
||||
# Adds some debug arguments like verbose output and class export.
|
||||
usesMixinDebug = false
|
||||
|
||||
@@ -117,9 +122,15 @@ minimizeShadowedDependencies = true
|
||||
# If disabled, won't rename the shadowed classes.
|
||||
relocateShadowedDependencies = true
|
||||
|
||||
# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories.
|
||||
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||
includeWellKnownRepositories = true
|
||||
|
||||
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
|
||||
# list of strings, with the acceptable keys being(case does not matter):
|
||||
# cursemaven
|
||||
# modrinth
|
||||
excludeWellKnownRepositories =
|
||||
|
||||
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
|
||||
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
|
||||
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
|
||||
@@ -141,7 +152,7 @@ modrinthProjectId = notenoughitems-unofficial
|
||||
# and the name is the Modrinth project or version slug/id of the other mod.
|
||||
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
|
||||
# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
|
||||
modrinthRelations = required-project\:codechickenlib-unofficial;required-project\:codechickencore-unofficial
|
||||
modrinthRelations = required-project\:codechickencore-unofficial
|
||||
|
||||
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
|
||||
#
|
||||
@@ -155,7 +166,7 @@ curseForgeProjectId = 358228
|
||||
# and the name is the CurseForge project slug of the other mod.
|
||||
# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
|
||||
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
|
||||
curseForgeRelations = requiredDependency\:codechickencore-unofficial;requiredDependency\:codechickenlib-unofficial
|
||||
curseForgeRelations = requiredDependency\:codechickencore-unofficial
|
||||
|
||||
# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older
|
||||
# projects. New projects should not use this parameter.
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -55,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -84,7 +86,8 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
Vendored
+2
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.14'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.31'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
|
||||
public class AutoFocusWidget implements IContainerInputHandler {
|
||||
|
||||
/**
|
||||
* Implement this interface on a GuiContainer to enable the autofocus search in NEI (if the autofocus option is
|
||||
* enabled) without needing to add the classname to the config file .
|
||||
*/
|
||||
public interface INEIAutoFocusSearchEnable {
|
||||
}
|
||||
|
||||
public static AutoFocusWidget instance = new AutoFocusWidget();
|
||||
|
||||
public static List<String> enableAutoFocusPrefixes = new ArrayList<>();
|
||||
|
||||
protected boolean autofocus = false;
|
||||
protected Point mouse;
|
||||
|
||||
public AutoFocusWidget() {
|
||||
GuiContainerManager.addInputHandler(this);
|
||||
}
|
||||
|
||||
public void load(GuiContainer gui) {
|
||||
this.autofocus = LayoutManager.searchField.isVisible() && NEIClientConfig.searchWidgetAutofocus() != 0
|
||||
&& isAllowedGuiAutoSearchFocus(gui);
|
||||
this.mouse = getMousePosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
|
||||
if (this.autofocus) {
|
||||
this.autofocus = false;
|
||||
|
||||
if (!this.mouse.equals(getMousePosition())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.searchWidgetAutofocus() == 2
|
||||
&& GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindInventory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyCode == Keyboard.KEY_RETURN || keyCode == Keyboard.KEY_NUMPADENTER
|
||||
|| keyCode == Keyboard.KEY_ESCAPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LayoutManager.searchField.setFocus(true);
|
||||
LayoutManager.searchField.handleKeyPress(keyCode, keyChar);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
this.autofocus = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
protected boolean isAllowedGuiAutoSearchFocus(GuiContainer gui) {
|
||||
if (gui instanceof INEIAutoFocusSearchEnable) {
|
||||
return true;
|
||||
}
|
||||
String guiClassName = gui.getClass().getName();
|
||||
for (String prefix : enableAutoFocusPrefixes) {
|
||||
if (guiClassName.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public class BookmarkCraftingChain {
|
||||
|
||||
public HashMap<ItemStack, ItemStack> inputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> outputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> remainder = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> intermediate = new HashMap<>();
|
||||
|
||||
protected static class CraftingChainItem {
|
||||
@@ -206,6 +207,7 @@ public class BookmarkCraftingChain {
|
||||
|
||||
this.inputs.clear();
|
||||
this.outputs.clear();
|
||||
this.remainder.clear();
|
||||
this.intermediate.clear();
|
||||
this.calculatedItems.clear();
|
||||
this.multiplier.clear();
|
||||
@@ -245,18 +247,20 @@ public class BookmarkCraftingChain {
|
||||
}
|
||||
|
||||
} else { // output
|
||||
long iCount = calculateCount(request, request.inputs.get(item.stackIndex))
|
||||
- iShift.getOrDefault(item.stackIndex, 0L);
|
||||
long iCalcCount = calculateCount(request, request.inputs.get(item.stackIndex));
|
||||
long iCount = iCalcCount - iShift.getOrDefault(item.stackIndex, 0L);
|
||||
this.multiplier.put(item.stack, item.factor > 0 ? (int) (count / item.factor) : 0);
|
||||
|
||||
if (iCount < count) {
|
||||
this.outputs.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
} else if (iCount >= count) {
|
||||
if (iCount >= count) {
|
||||
this.intermediate.put(item.stack, item.getItemStack(0));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
} else if (iCalcCount > 0) {
|
||||
this.remainder.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
} else {
|
||||
this.outputs.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,19 +1,19 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -30,18 +30,18 @@ import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import codechicken.core.ClassDiscoverer;
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.core.GuiModListScroll;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.IConfigureNEI;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
|
||||
@@ -54,15 +54,8 @@ import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ClientHandler {
|
||||
|
||||
private static String[] defaultHandlerOrdering = {
|
||||
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
|
||||
"# Ordering lines are <handler ID>,<ordering number>.",
|
||||
"# Handlers will be sorted in order of number ascending, so smaller numbers first.",
|
||||
"# Any handlers that are missing from this file will be assigned to 0.", "# Negative numbers are fine.",
|
||||
"# If you delete this file, it will be regenerated with all registered handler IDs.", };
|
||||
private static ClientHandler instance;
|
||||
|
||||
private ArrayList<EntityItem> SMPmagneticItems = new ArrayList<>();
|
||||
private final ArrayList<EntityItem> SMPmagneticItems = new ArrayList<>();
|
||||
private World lastworld;
|
||||
private GuiScreen lastGui;
|
||||
|
||||
@@ -147,82 +140,77 @@ public class ClientHandler {
|
||||
|
||||
public static void preInit() {
|
||||
loadSerialHandlers();
|
||||
loadHiddenItems();
|
||||
loadHeightHackHandlers();
|
||||
loadHiddenHandlers();
|
||||
loadEnableAutoFocus();
|
||||
ItemInfo.preInit();
|
||||
StackInfo.loadGuidFilters();
|
||||
}
|
||||
|
||||
public static void loadSerialHandlers() {
|
||||
File file = NEIClientConfig.serialHandlersFile;
|
||||
public static void loadSettingsFile(String resource, Consumer<Stream<String>> callback) {
|
||||
loadSettingsFile(resource, (file, writer) -> {
|
||||
String folder = resource.substring(resource.lastIndexOf(".") + 1);
|
||||
URL defaultResource = ClientHandler.class.getResource("/assets/nei/" + folder + "/" + resource);
|
||||
|
||||
if (defaultResource != null) {
|
||||
try {
|
||||
IOUtils.copy(defaultResource.openStream(), writer);
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
||||
public static void loadSettingsFile(String resource, BiConsumer<File, FileWriter> createDefault,
|
||||
Consumer<Stream<String>> callback) {
|
||||
File file = new File(NEIClientConfig.configDir, resource);
|
||||
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default serial handlers list {}", file);
|
||||
URL defaultSerialHandlersResource = ClientHandler.class
|
||||
.getResource("/assets/nei/cfg/serialhandlers.cfg");
|
||||
if (defaultSerialHandlersResource != null) {
|
||||
IOUtils.copy(defaultSerialHandlersResource.openStream(), writer);
|
||||
}
|
||||
NEIClientConfig.logger.info("Creating default '{}' {}", resource, file);
|
||||
createDefault.accept(file, writer);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default serial handlers list to file {}", file, e);
|
||||
NEIClientConfig.logger.error("Failed to save default '{}' to file {}", resource, file, e);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading serial handlers from file {}", file);
|
||||
NEIClientConfig.serialHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#"))
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
NEIClientConfig.logger.info("Loading '{}' file {}", resource, file);
|
||||
callback.accept(
|
||||
IOUtils.readLines(reader).stream().filter(line -> !line.startsWith("#") && !line.trim().isEmpty()));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e);
|
||||
NEIClientConfig.logger.error("Failed to load '{}' file {}", resource, file, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadSerialHandlers() {
|
||||
loadSettingsFile(
|
||||
"serialhandlers.cfg",
|
||||
lines -> NEIClientConfig.serialHandlers = lines.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
public static void loadHeightHackHandlers() {
|
||||
File file = NEIClientConfig.heightHackHandlersFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default height hack handlers list {}", file);
|
||||
URL defaultHeightHackHandlersResource = ClientHandler.class
|
||||
.getResource("/assets/nei/cfg/heighthackhandlers.cfg");
|
||||
if (defaultHeightHackHandlersResource != null) {
|
||||
IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading height hack handlers from file {}", file);
|
||||
NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream()
|
||||
.filter((line) -> !line.startsWith("#")).map(Pattern::compile)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e);
|
||||
}
|
||||
loadSettingsFile(
|
||||
"heighthackhandlers.cfg",
|
||||
lines -> NEIClientConfig.heightHackHandlerRegex = lines.map(Pattern::compile)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
public static void loadHiddenHandlers() {
|
||||
File file = NEIClientConfig.hiddenHandlersFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default hidden handlers list {}", file);
|
||||
URL defaultHeightHackHandlersResource = ClientHandler.class
|
||||
.getResource("/assets/nei/cfg/hiddenhandlers.cfg");
|
||||
if (defaultHeightHackHandlersResource != null) {
|
||||
IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default hidden handlers list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
loadSettingsFile(
|
||||
"hiddenhandlers.cfg",
|
||||
lines -> NEIClientConfig.hiddenHandlers = lines.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading hidden handlers from file {}", file);
|
||||
NEIClientConfig.hiddenHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#"))
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load hidden handlers from file {}", file, e);
|
||||
}
|
||||
public static void loadEnableAutoFocus() {
|
||||
loadSettingsFile(
|
||||
"enableautofocus.cfg",
|
||||
lines -> AutoFocusWidget.enableAutoFocusPrefixes = lines
|
||||
.collect(Collectors.toCollection(ArrayList::new)));
|
||||
}
|
||||
|
||||
public static void loadHiddenItems() {
|
||||
loadSettingsFile("hiddenitems.cfg", lines -> lines.forEach(API::hideItem));
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
@@ -239,54 +227,38 @@ public class ClientHandler {
|
||||
}
|
||||
|
||||
public static void postInit() {
|
||||
loadHandlerOrdering();
|
||||
GuiContainerManager.registerReloadResourceListener();
|
||||
}
|
||||
|
||||
public static void loadHandlerOrdering() {
|
||||
File file = NEIClientConfig.handlerOrderingFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default handler ordering CSV {}", file);
|
||||
|
||||
List<String> toWrite = Lists.newArrayList(defaultHandlerOrdering);
|
||||
GuiRecipeTab.handlerMap.keySet().stream().sorted()
|
||||
.forEach(handlerId -> toWrite.add(String.format("%s,0", handlerId)));
|
||||
final String COMMA_DELIMITER = ",";
|
||||
final String[] defaultHandlerOrdering = {
|
||||
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
|
||||
"# Ordering lines are <handler ID>,<ordering number>.",
|
||||
"# Handlers will be sorted in order of number ascending, so smaller numbers first.",
|
||||
"# Any handlers that are missing from this file will be assigned to 0.", "# Negative numbers are fine.",
|
||||
"# If you delete this file, it will be regenerated with all registered handler IDs.", };
|
||||
|
||||
loadSettingsFile("handlerordering.csv", (file, writer) -> {
|
||||
List<String> toWrite = Lists.newArrayList(defaultHandlerOrdering);
|
||||
GuiRecipeTab.handlerMap.keySet().stream().sorted()
|
||||
.forEach(handlerId -> toWrite.add(String.format("%s" + COMMA_DELIMITER + "0", handlerId)));
|
||||
try {
|
||||
IOUtils.writeLines(toWrite, "\n", writer);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default handler ordering to file {}", file, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {}
|
||||
}, lines -> lines.map(line -> line.split(COMMA_DELIMITER)).filter(parts -> parts.length == 2).forEach(parts -> {
|
||||
String handlerId = parts[0];
|
||||
int ordering = Integer.parseInt(parts[1]);
|
||||
NEIClientConfig.handlerOrdering.put(handlerId, ordering);
|
||||
}));
|
||||
}
|
||||
|
||||
URL url;
|
||||
try {
|
||||
url = file.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
NEIClientConfig.logger.info("Invalid URL for handler ordering CSV.");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
public static void loadPluginsList() {
|
||||
final ClassDiscoverer classDiscoverer = new ClassDiscoverer(
|
||||
test -> test.startsWith("NEI") && test.endsWith("Config.class"),
|
||||
IConfigureNEI.class);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||
NEIClientConfig.logger.info("Loading handler ordering from file {}", file);
|
||||
CSVParser csvParser = CSVFormat.EXCEL.withCommentMarker('#').parse(reader);
|
||||
for (CSVRecord record : csvParser) {
|
||||
final String handlerId = record.get(0);
|
||||
|
||||
int ordering;
|
||||
try {
|
||||
ordering = Integer.parseInt(record.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
NEIClientConfig.logger.error("Error parsing CSV record {}: {}", record, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
NEIClientConfig.handlerOrdering.put(handlerId, ordering);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.info("Error parsing CSV");
|
||||
e.printStackTrace();
|
||||
}
|
||||
NEIClientConfig.pluginsList.addAll(classDiscoverer.findClasses());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -353,9 +325,8 @@ public class ClientHandler {
|
||||
|
||||
if (!Minecraft.getMinecraft().isSingleplayer()) // wait for server to initiate in singleplayer
|
||||
NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~'));
|
||||
|
||||
ItemMobSpawner.clearEntityReferences(world);
|
||||
}
|
||||
ItemMobSpawner.clearEntityReferences(world);
|
||||
|
||||
lastworld = world;
|
||||
}
|
||||
@@ -383,9 +354,10 @@ public class ClientHandler {
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
CustomModLoadingErrorDisplayException e = new CustomModLoadingErrorDisplayException() {
|
||||
|
||||
private static final long serialVersionUID = -5593387489666663375L;
|
||||
|
||||
@Override
|
||||
public void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(errorGui);
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase.NBTPrimitive;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.PresetsList.PresetMode;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.ItemStackFilterParser;
|
||||
|
||||
public class CollapsibleItems {
|
||||
|
||||
protected static class GroupItem {
|
||||
|
||||
public String guid;
|
||||
public ItemFilter filter;
|
||||
public boolean expanded = false;
|
||||
public String displayName = "";
|
||||
|
||||
public void setFilter(String filter) {
|
||||
this.filter = ItemStackFilterParser.parse(filter.trim());
|
||||
this.guid = this.filter != null ? UUID.nameUUIDFromBytes(filter.getBytes()).toString() : "";
|
||||
}
|
||||
|
||||
public void setFilter(ItemFilter filter, String guid) {
|
||||
this.filter = filter;
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public boolean matches(ItemStack stack) {
|
||||
return this.filter.matches(stack);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String STATE_KEY = "collapsibleitems";
|
||||
|
||||
protected static File statesFile;
|
||||
protected static final List<GroupItem> groups = new ArrayList<>();
|
||||
protected static final Map<ItemStack, Integer> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private CollapsibleItems() {}
|
||||
|
||||
public static void load() {
|
||||
CollapsibleItems.groups.clear();
|
||||
CollapsibleItems.cache.clear();
|
||||
|
||||
for (int i = PresetsList.presets.size() - 1; i >= 0; i--) {
|
||||
Preset preset = PresetsList.presets.get(i);
|
||||
if (preset.enabled && preset.mode == PresetMode.GROUP) {
|
||||
GroupItem group = new GroupItem();
|
||||
group.setFilter(preset, UUID.nameUUIDFromBytes(preset.items.toString().getBytes()).toString());
|
||||
group.displayName = preset.name;
|
||||
addGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.enableCollapsibleItems()) {
|
||||
ClientHandler.loadSettingsFile(
|
||||
"collapsibleitems.cfg",
|
||||
lines -> parseFile(lines.collect(Collectors.toCollection(ArrayList::new))));
|
||||
}
|
||||
|
||||
loadStates();
|
||||
}
|
||||
|
||||
private static void parseFile(List<String> itemStrings) {
|
||||
final JsonParser parser = new JsonParser();
|
||||
GroupItem group = new GroupItem();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
try {
|
||||
|
||||
if (itemStr.startsWith("; ")) {
|
||||
JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject();
|
||||
|
||||
if (settings.get("displayName") != null) {
|
||||
group.displayName = settings.get("displayName").getAsString();
|
||||
}
|
||||
|
||||
if (settings.get("unlocalizedName") != null) {
|
||||
String unlocalizedName = settings.get("unlocalizedName").getAsString();
|
||||
String displayName = StatCollector.translateToLocal(unlocalizedName);
|
||||
|
||||
if (!displayName.equals(unlocalizedName)) {
|
||||
group.displayName = displayName;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get("expanded") != null) {
|
||||
group.expanded = settings.get("expanded").getAsBoolean();
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setFilter(itemStr);
|
||||
}
|
||||
|
||||
if (group != null && group.filter != null) {
|
||||
addGroup(group);
|
||||
group = new GroupItem();
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) {
|
||||
NEIClientConfig.logger.error("Failed to load collapsible items from json string:\n{}", itemStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addGroup(GroupItem group) {
|
||||
if (group == null || group.filter == null
|
||||
|| group.filter instanceof EverythingItemFilter
|
||||
|| group.filter instanceof NothingItemFilter)
|
||||
return;
|
||||
CollapsibleItems.groups.add(group);
|
||||
}
|
||||
|
||||
public static boolean isEmpty() {
|
||||
return CollapsibleItems.groups.isEmpty();
|
||||
}
|
||||
|
||||
public static ItemFilter getItemFilter() {
|
||||
AnyMultiItemFilter filter = new AnyMultiItemFilter();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
filter.filters.add(group.filter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
CollapsibleItems.cache.clear();
|
||||
}
|
||||
|
||||
public static void putItem(ItemStack stack) {
|
||||
final GroupItem group = CollapsibleItems.groups.stream().filter(g -> g.matches(stack)).findFirst().orElse(null);
|
||||
|
||||
if (group != null) {
|
||||
CollapsibleItems.cache.put(stack, CollapsibleItems.groups.indexOf(group));
|
||||
}
|
||||
}
|
||||
|
||||
public static int getGroupIndex(ItemStack stack) {
|
||||
|
||||
if (stack == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return CollapsibleItems.cache.getOrDefault(stack, -1);
|
||||
}
|
||||
|
||||
public static String getDisplayName(int groupIndex) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
return CollapsibleItems.groups.get(groupIndex).displayName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isExpanded(int groupIndex) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
return CollapsibleItems.groups.get(groupIndex).expanded;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setExpanded(int groupIndex, boolean expanded) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
CollapsibleItems.groups.get(groupIndex).expanded = expanded;
|
||||
}
|
||||
}
|
||||
|
||||
public static void toggleGroups(Boolean expanded) {
|
||||
|
||||
if (expanded == null) {
|
||||
expanded = CollapsibleItems.groups.stream().noneMatch(g -> g.expanded);
|
||||
}
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
group.expanded = expanded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void saveStates() {
|
||||
NBTTagCompound list = new NBTTagCompound();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
list.setBoolean(group.guid, group.expanded);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.world != null) {
|
||||
NEIClientConfig.world.nbt.setTag(STATE_KEY, list);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadStates() {
|
||||
|
||||
try {
|
||||
|
||||
if (NEIClientConfig.world.nbt.hasKey(STATE_KEY)) {
|
||||
NBTTagCompound states = NEIClientConfig.world.nbt.getCompoundTag(STATE_KEY);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Map<String, NBTPrimitive> list = (Map<String, NBTPrimitive>) states.tagMap;
|
||||
final Map<String, GroupItem> mapping = new HashMap<>();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
mapping.put(group.guid, group);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, NBTPrimitive> nbtEntry : list.entrySet()) {
|
||||
if (mapping.containsKey(nbtEntry.getKey())) {
|
||||
mapping.get(nbtEntry.getKey()).expanded = nbtEntry.getValue().func_150290_f() == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Error loading collapsible items states", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -116,7 +116,6 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
if (!player.worldObj.isRemote) InventoryUtils.dropOnClose(player, potionInv);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleServerPacket(PacketCustom packet) {
|
||||
ItemStack potion = potionInv.getStackInSlot(0);
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class FormattedTextField extends GuiTextField {
|
||||
|
||||
public static interface TextFormatter {
|
||||
|
||||
TextFormatter DEFAULT = (text) -> text;
|
||||
|
||||
public String format(String text);
|
||||
}
|
||||
|
||||
protected FontRenderer fontRenderer;
|
||||
protected String rawText = "";
|
||||
protected String formattedText = "";
|
||||
protected boolean editable = true;
|
||||
protected int editableColor = 14737632;
|
||||
protected int notEditableColor = 7368816;
|
||||
protected TextFormatter formatter = TextFormatter.DEFAULT;
|
||||
protected int lineScrollOffset = 0;
|
||||
protected int frame = 0;
|
||||
|
||||
public FormattedTextField(FontRenderer fontRenderer, int xPosition, int yPosition, int width, int height) {
|
||||
super(fontRenderer, xPosition, yPosition, width, height);
|
||||
this.fontRenderer = fontRenderer;
|
||||
}
|
||||
|
||||
public void setFormatter(TextFormatter formatter) {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCursorCounter() {
|
||||
super.updateCursorCounter();
|
||||
++this.frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(boolean focus) {
|
||||
if (focus && !this.isFocused()) {
|
||||
this.frame = 0;
|
||||
}
|
||||
|
||||
super.setFocused(focus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionPos(int p_146199_1_) {
|
||||
String text = this.getText();
|
||||
int j = text.length();
|
||||
|
||||
super.setSelectionPos(p_146199_1_);
|
||||
|
||||
p_146199_1_ = Math.max(0, Math.min(p_146199_1_, j));
|
||||
|
||||
if (this.fontRenderer != null) {
|
||||
|
||||
if (this.lineScrollOffset > j) {
|
||||
this.lineScrollOffset = j;
|
||||
}
|
||||
|
||||
int k = this.getWidth();
|
||||
String s = this.fontRenderer.trimStringToWidth(text.substring(this.lineScrollOffset), k);
|
||||
int l = s.length() + this.lineScrollOffset;
|
||||
|
||||
if (p_146199_1_ == this.lineScrollOffset) {
|
||||
this.lineScrollOffset -= this.fontRenderer.trimStringToWidth(text, k, true).length();
|
||||
}
|
||||
|
||||
if (p_146199_1_ > l) {
|
||||
this.lineScrollOffset += p_146199_1_ - l;
|
||||
} else if (p_146199_1_ <= this.lineScrollOffset) {
|
||||
this.lineScrollOffset -= this.lineScrollOffset - p_146199_1_;
|
||||
}
|
||||
|
||||
this.lineScrollOffset = Math.max(0, Math.min(this.lineScrollOffset, j));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(int p_146193_1_) {
|
||||
super.setTextColor(p_146193_1_);
|
||||
this.editableColor = p_146193_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisabledTextColour(int p_146204_1_) {
|
||||
super.setDisabledTextColour(p_146204_1_);
|
||||
this.notEditableColor = p_146204_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean p_146184_1_) {
|
||||
super.setEnabled(p_146184_1_);
|
||||
this.editable = p_146184_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextBox() {
|
||||
if (this.getVisible()) {
|
||||
if (this.getEnableBackgroundDrawing()) {
|
||||
drawRect(
|
||||
this.xPosition - 1,
|
||||
this.yPosition - 1,
|
||||
this.xPosition + this.width + 1,
|
||||
this.yPosition + this.height + 1,
|
||||
-6250336);
|
||||
drawRect(
|
||||
this.xPosition,
|
||||
this.yPosition,
|
||||
this.xPosition + this.width,
|
||||
this.yPosition + this.height,
|
||||
-16777216);
|
||||
}
|
||||
|
||||
if (!this.rawText.equals(getText())) {
|
||||
this.rawText = getText();
|
||||
this.formattedText = this.formatter.format(this.rawText);
|
||||
if (!EnumChatFormatting.getTextWithoutFormattingCodes(this.formattedText).toLowerCase()
|
||||
.equals(this.rawText.toLowerCase())) {
|
||||
this.formattedText = this.rawText;
|
||||
}
|
||||
}
|
||||
|
||||
int firstCharacterIndex = getFormattedTextShift(this.lineScrollOffset);
|
||||
String rawTextClipped = this.fontRenderer
|
||||
.trimStringToWidth(this.rawText.substring(this.lineScrollOffset), this.getWidth());
|
||||
String textClipped = this.formattedText.substring(
|
||||
firstCharacterIndex,
|
||||
getFormattedTextShift(this.lineScrollOffset + rawTextClipped.length()));
|
||||
int cursorPosition = getFormattedTextShift(this.getCursorPosition());
|
||||
int selectionEnd = getFormattedTextShift(this.getSelectionEnd());
|
||||
|
||||
int color = this.editable ? this.editableColor : this.notEditableColor;
|
||||
int cursorA = cursorPosition - firstCharacterIndex;
|
||||
int cursorB = selectionEnd - firstCharacterIndex;
|
||||
boolean flag = cursorA >= 0 && cursorA <= textClipped.length();
|
||||
boolean flag1 = this.isFocused() && this.frame / 6 % 2 == 0 && flag;
|
||||
boolean flag2 = this.getCursorPosition() < this.rawText.length()
|
||||
|| this.rawText.length() >= this.getMaxStringLength();
|
||||
int x = this.getEnableBackgroundDrawing() ? this.xPosition + 4 : this.xPosition;
|
||||
int y = this.getEnableBackgroundDrawing() ? this.yPosition + (this.height - 8) / 2 : this.yPosition;
|
||||
int x2 = x;
|
||||
|
||||
if (cursorB > textClipped.length()) {
|
||||
cursorB = textClipped.length();
|
||||
}
|
||||
|
||||
if (textClipped.length() > 0) {
|
||||
String s1 = flag ? textClipped.substring(0, cursorA) : textClipped;
|
||||
String colorA = getPreviousColor(firstCharacterIndex);
|
||||
x2 = this.fontRenderer.drawStringWithShadow(colorA + s1, x, y, color);
|
||||
}
|
||||
|
||||
int k1 = x2;
|
||||
|
||||
if (!flag) {
|
||||
k1 = cursorA > 0 ? x + this.width : x;
|
||||
} else if (flag2) {
|
||||
k1 = x2 - 1;
|
||||
--x2;
|
||||
}
|
||||
|
||||
if (textClipped.length() > 0 && flag && cursorA < textClipped.length()) {
|
||||
String colorB = getPreviousColor(firstCharacterIndex + cursorA);
|
||||
this.fontRenderer.drawStringWithShadow(colorB + textClipped.substring(cursorA), x2, y, color);
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
if (flag2) {
|
||||
Gui.drawRect(k1, y - 1, k1 + 1, y + 1 + this.fontRenderer.FONT_HEIGHT, -3092272);
|
||||
} else {
|
||||
this.fontRenderer.drawStringWithShadow("_", k1, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorB != cursorA) {
|
||||
int l1 = x + this.fontRenderer.getStringWidth(textClipped.substring(0, cursorB));
|
||||
drawCursorVertical(k1, y - 1, l1 - 1, y + 1 + this.fontRenderer.FONT_HEIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCursorVertical(int x1, int y1, int x2, int y2) {
|
||||
int i1;
|
||||
|
||||
if (x1 < x2) {
|
||||
i1 = x1;
|
||||
x1 = x2;
|
||||
x2 = i1;
|
||||
}
|
||||
|
||||
if (y1 < y2) {
|
||||
i1 = y1;
|
||||
y1 = y2;
|
||||
y2 = i1;
|
||||
}
|
||||
|
||||
if (x2 > this.xPosition + this.width) {
|
||||
x2 = this.xPosition + this.width;
|
||||
}
|
||||
|
||||
if (x1 > this.xPosition + this.width) {
|
||||
x1 = this.xPosition + this.width;
|
||||
}
|
||||
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
GL11.glColor4f(0.0F, 0.0F, 255.0F, 255.0F);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_COLOR_LOGIC_OP);
|
||||
GL11.glLogicOp(GL11.GL_OR_REVERSE);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertex((double) x1, (double) y2, 0.0D);
|
||||
tessellator.addVertex((double) x2, (double) y2, 0.0D);
|
||||
tessellator.addVertex((double) x2, (double) y1, 0.0D);
|
||||
tessellator.addVertex((double) x1, (double) y1, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glDisable(GL11.GL_COLOR_LOGIC_OP);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
private int getFormattedTextShift(int position) {
|
||||
int shift = 0;
|
||||
|
||||
for (int i = 0; i < position; i++) {
|
||||
while (this.formattedText.length() > i + shift && this.formattedText.charAt(i + shift) == '\u00a7') {
|
||||
shift += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return position + shift;
|
||||
}
|
||||
|
||||
private String getPreviousColor(int position) {
|
||||
while (position >= 0) {
|
||||
if (this.formattedText.charAt(position) == '\u00a7') {
|
||||
return this.formattedText.substring(position, position + 2);
|
||||
}
|
||||
position--;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,10 +12,11 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.AutoFocusWidget.INEIAutoFocusSearchEnable;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
|
||||
public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandler {
|
||||
public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandler, INEIAutoFocusSearchEnable {
|
||||
|
||||
public GuiExtendedCreativeInv(Container par1Container) {
|
||||
super(par1Container);
|
||||
@@ -59,13 +60,13 @@ public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandl
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMouseClick(Slot p_146984_1_, int p_146984_2_, int p_146984_3_, int p_146984_4_) {
|
||||
protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) {
|
||||
|
||||
// Hack for armor slots, because they are outside the container
|
||||
if (p_146984_1_ != null && p_146984_4_ == 4 && p_146984_1_.xDisplayPosition < 0) {
|
||||
p_146984_4_ = 0;
|
||||
if (slotIn != null && clickType == 4 && slotIn.xDisplayPosition < 0) {
|
||||
clickType = 0;
|
||||
}
|
||||
|
||||
super.handleMouseClick(p_146984_1_, p_146984_2_, p_146984_3_, p_146984_4_);
|
||||
super.handleMouseClick(slotIn, slotId, clickedButton, clickType);
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,13 @@ public class GuiNEIButton extends GuiButton {
|
||||
super(i, j, k, l, i1, s);
|
||||
}
|
||||
|
||||
public void drawButton(Minecraft minecraft, int i, int j) {
|
||||
public void drawButton(Minecraft minecraft, int x, int y) {
|
||||
if (!visible) return;
|
||||
|
||||
FontRenderer fontrenderer = minecraft.fontRenderer;
|
||||
minecraft.renderEngine.bindTexture(guiTex);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
boolean flag = i >= xPosition && j >= yPosition && i < xPosition + width && j < yPosition + height;
|
||||
int k = getHoverState(flag);
|
||||
boolean mouseOver = x >= xPosition && y >= yPosition && x < xPosition + width && y < yPosition + height;
|
||||
int k = getHoverState(mouseOver);
|
||||
drawTexturedModalRect(xPosition, yPosition, 0, 46 + k * 20, width / 2, height / 2); // top left
|
||||
drawTexturedModalRect(xPosition + width / 2, yPosition, 200 - width / 2, 46 + k * 20, width / 2, height / 2); // top
|
||||
// right
|
||||
@@ -40,25 +39,27 @@ public class GuiNEIButton extends GuiButton {
|
||||
46 + k * 20 + 20 - height / 2,
|
||||
width / 2,
|
||||
height / 2); // bottom right
|
||||
mouseDragged(minecraft, i, j);
|
||||
mouseDragged(minecraft, x, y);
|
||||
|
||||
if (!enabled) drawCenteredString(
|
||||
fontrenderer,
|
||||
displayString,
|
||||
xPosition + width / 2,
|
||||
yPosition + (height - 8) / 2,
|
||||
0xffa0a0a0);
|
||||
else if (flag) drawCenteredString(
|
||||
fontrenderer,
|
||||
displayString,
|
||||
xPosition + width / 2,
|
||||
yPosition + (height - 8) / 2,
|
||||
0xffffa0);
|
||||
else drawCenteredString(
|
||||
fontrenderer,
|
||||
displayString,
|
||||
xPosition + width / 2,
|
||||
yPosition + (height - 8) / 2,
|
||||
0xe0e0e0);
|
||||
drawContent(minecraft, x, y, mouseOver);
|
||||
}
|
||||
|
||||
protected int getTextColour(boolean mouseOver) {
|
||||
int color = 0xe0e0e0;
|
||||
|
||||
if (!enabled) {
|
||||
color = 0xffa0a0a0;
|
||||
} else if (mouseOver) {
|
||||
color = 0xffffa0;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
protected void drawContent(Minecraft minecraft, int y, int x, boolean mouseOver) {
|
||||
FontRenderer fontrenderer = minecraft.fontRenderer;
|
||||
int color = getTextColour(mouseOver);
|
||||
|
||||
drawCenteredString(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class HeldItemHandler implements IContainerInputHandler, IContainerTooltipHandler {
|
||||
|
||||
protected HeldItemHandler() {
|
||||
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
HeldItemHandler instance = new HeldItemHandler();
|
||||
GuiContainerManager.addInputHandler(instance);
|
||||
GuiContainerManager.addTooltipHandler(instance);
|
||||
}
|
||||
|
||||
protected boolean contains(int mousex, int mousey) {
|
||||
return NEIClientUtils.getHeldItem() != null
|
||||
&& (ItemPanels.bookmarkPanel.contains(mousex, mousey) || ItemPanels.itemPanel.contains(mousex, mousey)
|
||||
|| ItemPanels.itemPanel.historyPanel.contains(mousex, mousey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
if (contains(mousex, mousey)) {
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
if (button == 1) {
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
} else {
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
}
|
||||
} else {
|
||||
NEIClientUtils.dropHeldItem();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
|
||||
if (contains(mousex, mousey)) {
|
||||
currenttip.clear();
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
currenttip.add(EnumChatFormatting.RED + translate("itempanel.deleteItem"));
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemHistoryPanel extends Widget {
|
||||
|
||||
protected int mouseDownSlot = -1;
|
||||
protected ItemsGrid grid;
|
||||
|
||||
public ItemHistoryPanel() {
|
||||
grid = new ItemsGrid();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return grid.isEmpty();
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey) {
|
||||
|
||||
if (NEIClientConfig.getIntSetting("inventory.history.splittingMode") == 0) {
|
||||
GuiDraw.drawRect(x, y, w, h, NEIClientConfig.getSetting("inventory.history.historyColor").getHexValue());
|
||||
} else {
|
||||
drawSplittingArea(x, y, w, h, NEIClientConfig.getSetting("inventory.history.historyColor").getHexValue());
|
||||
}
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
grid.update();
|
||||
}
|
||||
|
||||
public void addItem(ItemStack stack) {
|
||||
if (stack != null) {
|
||||
ItemStack is = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack), 0);
|
||||
|
||||
grid.realItems.removeIf(historyStack -> StackInfo.equalItemAndNBT(historyStack, stack, true));
|
||||
grid.realItems.add(0, is);
|
||||
|
||||
if (grid.realItems.size() > Math.max(50, grid.rows * grid.columns)) {
|
||||
grid.realItems.remove(grid.realItems.size() - 1);
|
||||
}
|
||||
|
||||
grid.onItemsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
grid.setGridSize(x, y, w, h);
|
||||
grid.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackMouseOver(int mousex, int mousey) {
|
||||
ItemPanelSlot slot = getSlotMouseOver(mousex, mousey);
|
||||
return slot == null ? null : slot.item;
|
||||
}
|
||||
|
||||
public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) {
|
||||
return grid.getSlotMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
private void drawSplittingArea(int x, int y, int width, int height, int color) {
|
||||
|
||||
float alpha = (color >> 24 & 255) / 255.0F;
|
||||
float red = (color >> 16 & 255) / 255.0F;
|
||||
float green = (color >> 8 & 255) / 255.0F;
|
||||
float blue = (color & 255) / 255.0F;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_LINE_STIPPLE);
|
||||
GL11.glColor4f(red, green, blue, alpha);
|
||||
GL11.glLineWidth(2F);
|
||||
GL11.glLineStipple(2, (short) 0x00FF);
|
||||
|
||||
GL11.glBegin(GL11.GL_LINE_LOOP);
|
||||
|
||||
GL11.glVertex2i(x, y);
|
||||
GL11.glVertex2i(x + width, y);
|
||||
GL11.glVertex2i(x + width, y + height);
|
||||
GL11.glVertex2i(x, y + height);
|
||||
|
||||
GL11.glEnd();
|
||||
|
||||
GL11.glLineStipple(1, (short) 0xFFFF);
|
||||
GL11.glLineWidth(1F);
|
||||
GL11.glDisable(GL11.GL_LINE_STIPPLE);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glColor4f(1F, 1F, 1F, 1F);
|
||||
|
||||
GL11.glPopMatrix();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
||||
|
||||
if (mouseDownSlot >= 0 && ItemPanels.itemPanel.draggedStack == null
|
||||
&& NEIClientUtils.getHeldItem() == null
|
||||
&& NEIClientConfig.hasSMPCounterPart()) {
|
||||
|
||||
ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) {
|
||||
ItemPanels.itemPanel.draggedStack = getDraggedStackWithQuantity(mouseDownSlot);
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
if (handleClickExt(mousex, mousey, button)) return true;
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
|
||||
if (button == 2) {
|
||||
|
||||
if (hoverSlot.item != null) {
|
||||
ItemPanels.itemPanel.draggedStack = getDraggedStackWithQuantity(hoverSlot.slotIndex);
|
||||
}
|
||||
|
||||
} else {
|
||||
mouseDownSlot = hoverSlot.slotIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mousex, int mousey, int button) {
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && ItemPanels.itemPanel.draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item.copy();
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey()
|
||||
|| !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
if (button == 0) {
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
} else if (button == 1) {
|
||||
GuiUsageRecipe.openRecipeGui("item", item);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
NEIClientUtils.cheatItem(getDraggedStackWithQuantity(hoverSlot.slotIndex), button, -1);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) {
|
||||
ItemStack stack = grid.getItem(mouseDownSlot);
|
||||
|
||||
if (stack != null) {
|
||||
int amount = NEIClientConfig.showItemQuantityWidget() ? NEIClientConfig.getItemQuantity() : 0;
|
||||
|
||||
if (amount == 0) {
|
||||
amount = stack.getMaxStackSize();
|
||||
}
|
||||
|
||||
return NEIServerUtils.copyStack(stack, amount);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,16 +2,22 @@ package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IIcon;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
@@ -21,7 +27,7 @@ import codechicken.nei.ThreadOperationTimer.TimeoutException;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.search.TooltipFilter;
|
||||
|
||||
public class ItemList {
|
||||
|
||||
@@ -37,11 +43,11 @@ public class ItemList {
|
||||
* Updates to this should be synchronised on this
|
||||
*/
|
||||
public static final List<ItemFilterProvider> itemFilterers = new LinkedList<>();
|
||||
|
||||
public static final List<ItemsLoadedCallback> loadCallbacks = new LinkedList<>();
|
||||
|
||||
private static final HashSet<Item> erroredItems = new HashSet<>();
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static HashMap<ItemStack, Integer> ordering = new HashMap<>();
|
||||
/**
|
||||
* Unlike {@link LayoutManager#itemsLoaded}, this indicates whether item loading is actually finished or not.
|
||||
*/
|
||||
@@ -63,6 +69,20 @@ public class ItemList {
|
||||
}
|
||||
}
|
||||
|
||||
public static class NegatedItemFilter implements ItemFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public NegatedItemFilter(ItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return this.filter == null || !this.filter.matches(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PatternItemFilter implements ItemFilter {
|
||||
|
||||
public Pattern pattern;
|
||||
@@ -73,7 +93,20 @@ public class ItemList {
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return pattern.matcher(ItemInfo.getSearchName(item)).find();
|
||||
String displayName = EnumChatFormatting.getTextWithoutFormattingCodes(item.getDisplayName());
|
||||
|
||||
if (displayName != null && !displayName.isEmpty() && pattern.matcher(displayName).find()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.hasDisplayName()) {
|
||||
displayName = EnumChatFormatting
|
||||
.getTextWithoutFormattingCodes(item.getItem().getItemStackDisplayName(item));
|
||||
|
||||
return displayName != null && !displayName.isEmpty() && pattern.matcher(displayName).find();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +119,7 @@ public class ItemList {
|
||||
}
|
||||
|
||||
public AllMultiItemFilter(ItemFilter... filters) {
|
||||
this(Arrays.asList(filters));
|
||||
this(new LinkedList<>(Arrays.asList(filters)));
|
||||
}
|
||||
|
||||
public AllMultiItemFilter() {
|
||||
@@ -98,7 +131,8 @@ public class ItemList {
|
||||
for (ItemFilter filter : filters) try {
|
||||
if (filter != null && !filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -120,9 +154,10 @@ public class ItemList {
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
for (ItemFilter filter : filters) try {
|
||||
if (filter.matches(item)) return true;
|
||||
if (filter != null && filter.matches(item)) return true;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -137,9 +172,10 @@ public class ItemList {
|
||||
public static boolean itemMatchesAll(ItemStack item, List<ItemFilter> filters) {
|
||||
for (ItemFilter filter : filters) {
|
||||
try {
|
||||
if (!filter.matches(item)) return false;
|
||||
if (filter != null && !filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +197,9 @@ public class ItemList {
|
||||
public static List<ItemFilter> getItemFilters() {
|
||||
LinkedList<ItemFilter> filters = new LinkedList<>();
|
||||
synchronized (itemFilterers) {
|
||||
for (ItemFilterProvider p : itemFilterers) filters.add(p.getFilter());
|
||||
for (ItemFilterProvider p : itemFilterers) {
|
||||
filters.add(p.getFilter());
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
@@ -173,7 +211,7 @@ public class ItemList {
|
||||
for (int damage = 0; damage < 16; damage++) try {
|
||||
ItemStack itemstack = new ItemStack(item, 1, damage);
|
||||
IIcon icon = item.getIconIndex(itemstack);
|
||||
String name = GuiContainerManager.concatenatedDisplayName(itemstack, false);
|
||||
String name = getTooltip(itemstack);
|
||||
String s = name + "@" + (icon == null ? 0 : icon.hashCode());
|
||||
if (!damageIconSet.contains(s)) {
|
||||
damageIconSet.add(s);
|
||||
@@ -190,43 +228,126 @@ public class ItemList {
|
||||
}
|
||||
}
|
||||
|
||||
private String getTooltip(ItemStack stack) {
|
||||
try {
|
||||
return String.join("\n", stack.getTooltip(Minecraft.getMinecraft().thePlayer, false));
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateOrdering(List<ItemStack> items) {
|
||||
ItemSorter.sort(items);
|
||||
|
||||
HashMap<ItemStack, Integer> newOrdering = new HashMap<>();
|
||||
|
||||
if (!CollapsibleItems.isEmpty()) {
|
||||
HashMap<Integer, Integer> groups = new HashMap<>();
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
} else {
|
||||
|
||||
if (!groups.containsKey(groupIndex)) {
|
||||
groups.put(groupIndex, orderIndex++);
|
||||
}
|
||||
|
||||
newOrdering.put(stack, groups.get(groupIndex));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
ItemList.ordering = newOrdering;
|
||||
}
|
||||
|
||||
private List<ItemStack> getPermutations(Item item) {
|
||||
final List<ItemStack> permutations = new LinkedList<>(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
item.getSubItems(item, null, permutations);
|
||||
}
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
damageSearch(item, permutations);
|
||||
}
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
return permutations.stream()
|
||||
.filter(
|
||||
stack -> stack.getItem() != null && stack.getItem().delegate.name() != null
|
||||
&& !ItemInfo.isHidden(stack))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// For optimization it generate itemslist, permutations, orders & collapsibleitems
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Loading");
|
||||
if (!NEIClientConfig.isEnabled()) return;
|
||||
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
LayoutManager.itemsLoaded = true;
|
||||
loadFinished = false;
|
||||
|
||||
LinkedList<ItemStack> items = new LinkedList<>();
|
||||
LinkedList<ItemStack> permutations = new LinkedList<>();
|
||||
SearchField.searchParser.clearCache();
|
||||
ItemSorter.instance.ordering.clear();
|
||||
CollapsibleItems.clearCache();
|
||||
TooltipFilter.clearCache();
|
||||
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
ItemStackSet unique = new ItemStackSet();
|
||||
|
||||
timer.setLimit(NEIClientConfig.getItemLoadingTimeout());
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
if (interrupted()) return;
|
||||
|
||||
if (item == null || erroredItems.contains(item)) continue;
|
||||
StreamSupport.stream(((Iterable<Item>) Item.itemRegistry).spliterator(), true).forEach(item -> {
|
||||
if (item == null || item.delegate.name() == null || erroredItems.contains(item)) return;
|
||||
|
||||
try {
|
||||
timer.reset(item);
|
||||
|
||||
permutations.clear();
|
||||
permutations.addAll(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) item.getSubItems(item, null, permutations);
|
||||
|
||||
if (permutations.isEmpty()) damageSearch(item, permutations);
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
List<ItemStack> permutations = getPermutations(item);
|
||||
timer.reset();
|
||||
|
||||
items.addAll(permutations);
|
||||
itemMap.putAll(item, permutations);
|
||||
for (ItemStack stack : permutations) {
|
||||
if (!unique.contains(stack)) {
|
||||
|
||||
synchronized (unique) {
|
||||
unique.add(stack);
|
||||
}
|
||||
|
||||
synchronized (items) {
|
||||
items.add(stack);
|
||||
}
|
||||
|
||||
CollapsibleItems.putItem(stack);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (itemMap) {
|
||||
itemMap.putAll(item, permutations);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
NEIServerConfig.logger.error("Removing item: " + item + " from list.", t);
|
||||
NEIServerConfig.logger.error("Removing item: {} from list.", item, t);
|
||||
erroredItems.add(item);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
int index = 0;
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
for (ItemStack stack : itemMap.get(item)) {
|
||||
ItemSorter.instance.ordering.put(stack, index++);
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
@@ -234,28 +355,47 @@ public class ItemList {
|
||||
ItemList.itemMap = itemMap;
|
||||
for (ItemsLoadedCallback callback : loadCallbacks) callback.itemsLoaded();
|
||||
|
||||
updateFilter.restart();
|
||||
if (interrupted()) return;
|
||||
updateOrdering(ItemList.items);
|
||||
|
||||
new Thread(
|
||||
() -> ItemList.items.parallelStream().forEach(TooltipFilter::getSearchTooltip),
|
||||
"NEI Tooltip Filter Loader").start();
|
||||
|
||||
loadFinished = true;
|
||||
|
||||
SubsetWidget.updateHiddenItems();
|
||||
updateFilter.restart();
|
||||
}
|
||||
};
|
||||
|
||||
public static ForkJoinPool getPool(int poolSize) {
|
||||
public static ForkJoinPool forkJoinPool;
|
||||
|
||||
static {
|
||||
final ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
|
||||
|
||||
private int workerId;
|
||||
|
||||
@Override
|
||||
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
|
||||
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
|
||||
worker.setName("NEI-worker-thread-" + workerId++);
|
||||
return worker;
|
||||
}
|
||||
};
|
||||
int poolSize = Runtime.getRuntime().availableProcessors() * 2 / 3;
|
||||
if (poolSize < 1) poolSize = 1;
|
||||
|
||||
return new ForkJoinPool(poolSize);
|
||||
forkJoinPool = new ForkJoinPool(poolSize, factory, null, false);
|
||||
}
|
||||
|
||||
public static final int numProcessors = Runtime.getRuntime().availableProcessors();
|
||||
public static ForkJoinPool forkJoinPool = getPool(numProcessors * 2 / 3);
|
||||
|
||||
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Filtering");
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
if (!loadFinished) return;
|
||||
ItemFilter filter = getItemListFilter();
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
@@ -269,8 +409,12 @@ public class ItemList {
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(filtered);
|
||||
|
||||
Comparator<ItemStack> comparator = Comparator.comparingInt(ItemList.ordering::get);
|
||||
filtered.sort(comparator::compare);
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
ItemPanel.updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -66,7 +66,7 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack itemstack, EntityPlayer par2EntityPlayer, List list, boolean par4) {
|
||||
public void addInformation(ItemStack itemstack, EntityPlayer par2EntityPlayer, List<String> list, boolean par4) {
|
||||
setDefaultTag(itemstack);
|
||||
int meta = itemstack.getItemDamage();
|
||||
if (meta == 0) {
|
||||
@@ -106,9 +106,10 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
public static void loadSpawners(World world) {
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
HashMap<Class<Entity>, String> classToStringMapping = (HashMap<Class<Entity>, String>) EntityList.classToStringMapping;
|
||||
HashMap<Class<Entity>, Integer> classToIDMapping = (HashMap<Class<Entity>, Integer>) EntityList.classToIDMapping;
|
||||
for (Class<Entity> eclass : classToStringMapping.keySet()) {
|
||||
Map<Class<? extends Entity>, String> classToStringMapping = EntityList.classToStringMapping;
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class<? extends Entity>, Integer> classToIDMapping = (Map<Class<? extends Entity>, Integer>) EntityList.classToIDMapping;
|
||||
for (Class<? extends Entity> eclass : classToStringMapping.keySet()) {
|
||||
if (!EntityLiving.class.isAssignableFrom(eclass)) continue;
|
||||
try {
|
||||
EntityLiving entityliving = (EntityLiving) eclass.getConstructor(new Class[] { World.class })
|
||||
@@ -131,7 +132,7 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSubItems(Item item, CreativeTabs tab, List list) {
|
||||
public void getSubItems(Item item, CreativeTabs tab, List<ItemStack> list) {
|
||||
if (!NEIClientConfig.hasSMPCounterPart()) list.add(new ItemStack(item));
|
||||
else for (int i : IDtoNameMap.keySet()) list.add(new ItemStack(item, 1, i));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class ItemPanel extends PanelWidget {
|
||||
|
||||
@@ -31,9 +41,8 @@ public class ItemPanel extends PanelWidget {
|
||||
return super.getStackMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
public Button more;
|
||||
public Button less;
|
||||
public ItemQuantityField quantity;
|
||||
public ItemHistoryPanel historyPanel;
|
||||
public Button toggleGroups;
|
||||
|
||||
public static class ItemPanelSlot {
|
||||
|
||||
@@ -51,9 +60,30 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MaskMetadata {
|
||||
|
||||
public int groupIndex = -1;
|
||||
public String displayName = "";
|
||||
public boolean extended = false;
|
||||
|
||||
public Color bgColor = null;
|
||||
public Color color = null;
|
||||
|
||||
public boolean left = false;
|
||||
public boolean top = false;
|
||||
public boolean right = false;
|
||||
public boolean bottom = false;
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelGrid extends ItemsGrid {
|
||||
|
||||
public ArrayList<ItemStack> newItems;
|
||||
public ArrayList<ItemStack> rawItems;
|
||||
|
||||
protected final HashMap<Integer, List<ItemStack>> groupItems = new HashMap<>();
|
||||
protected final HashMap<Integer, MaskMetadata> maskMetadata = new HashMap<>();
|
||||
protected boolean forceExpand = false;
|
||||
|
||||
public void setItems(ArrayList<ItemStack> items) {
|
||||
newItems = items;
|
||||
@@ -61,9 +91,48 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
|
||||
if (newItems != null) {
|
||||
realItems = newItems;
|
||||
newItems = null;
|
||||
if (this.newItems != null) {
|
||||
this.groupItems.clear();
|
||||
this.forceExpand = false;
|
||||
|
||||
if (!CollapsibleItems.isEmpty() && !this.newItems.isEmpty()) {
|
||||
final Set<Integer> groups = new HashSet<>();
|
||||
boolean outsideGroup = false;
|
||||
|
||||
this.realItems = new ArrayList<>();
|
||||
this.rawItems = new ArrayList<>(this.newItems);
|
||||
|
||||
for (ItemStack stack : this.newItems) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
this.realItems.add(stack);
|
||||
outsideGroup = true;
|
||||
} else {
|
||||
|
||||
if (!groups.contains(groupIndex) || CollapsibleItems.isExpanded(groupIndex)) {
|
||||
this.realItems.add(stack);
|
||||
groups.add(groupIndex);
|
||||
}
|
||||
|
||||
if (!this.groupItems.containsKey(groupIndex)) {
|
||||
this.groupItems.put(groupIndex, new ArrayList<>());
|
||||
}
|
||||
|
||||
this.groupItems.get(groupIndex).add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
// automatically opens if there are elements from only one group
|
||||
if (!outsideGroup && groups.size() == 1) {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
this.forceExpand = true;
|
||||
}
|
||||
} else {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
}
|
||||
|
||||
this.newItems = null;
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
@@ -71,11 +140,171 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
if (!PresetsWidget.isHidden(getItem(slotIdx))) drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
protected List<Integer> getMask() {
|
||||
final boolean updateBorders = this.gridMask == null;
|
||||
final List<Integer> mask = super.getMask();
|
||||
|
||||
if (updateBorders) {
|
||||
calculateGroupBorders(mask);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
protected void calculateGroupBorders(List<Integer> mask) {
|
||||
this.maskMetadata.clear();
|
||||
|
||||
if (mask.isEmpty() || this.groupItems.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final HashMap<Integer, Integer> maskGroup = new HashMap<>();
|
||||
final Color collapsedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.collapsedColor").getHexValue(),
|
||||
true);
|
||||
final Color expandedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.expandedColor").getHexValue(),
|
||||
true);
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
maskGroup.put(idx, CollapsibleItems.getGroupIndex(getItem(idx)));
|
||||
}
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
int groupIndex = maskGroup.get(idx);
|
||||
|
||||
if (groupIndex == -1 || this.groupItems.get(groupIndex).size() == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int column = slotIndex % this.columns;
|
||||
int row = slotIndex / this.columns;
|
||||
int prevSlotIndex = (row - 1) * this.columns + column;
|
||||
int nextSlotIndex = (row + 1) * this.columns + column;
|
||||
MaskMetadata metadata = new MaskMetadata();
|
||||
|
||||
metadata.groupIndex = groupIndex;
|
||||
metadata.displayName = CollapsibleItems.getDisplayName(groupIndex);
|
||||
metadata.extended = this.forceExpand || CollapsibleItems.isExpanded(groupIndex);
|
||||
metadata.bgColor = metadata.extended ? expandedColor : collapsedColor;
|
||||
metadata.color = darkerColor(metadata.bgColor);
|
||||
metadata.left = column == 0 || idx == 0
|
||||
|| mask.get(slotIndex - 1) == null
|
||||
|| maskGroup.getOrDefault(idx - 1, -1) != groupIndex;
|
||||
metadata.right = column == this.columns - 1 || maskGroup.getOrDefault(idx + 1, -1) != groupIndex;
|
||||
|
||||
if (prevSlotIndex >= 0) {
|
||||
Integer previdx = mask.get(prevSlotIndex);
|
||||
metadata.top = previdx == null || maskGroup.getOrDefault(previdx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.top = true;
|
||||
}
|
||||
|
||||
if (nextSlotIndex < mask.size()) {
|
||||
Integer nextidx = mask.get(nextSlotIndex);
|
||||
metadata.bottom = nextidx == null || maskGroup.getOrDefault(nextidx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.bottom = true;
|
||||
}
|
||||
|
||||
this.maskMetadata.put(idx, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
super.beforeDrawItems(mousex, mousey, focused);
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
drawBorder(mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBorder(int slotIdx, Rectangle4i rect) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null) {
|
||||
final float LINE_WIDTH = 0.75f;
|
||||
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, metadata.bgColor);
|
||||
|
||||
if (metadata.left) {
|
||||
float leftBottom = metadata.bottom ? -LINE_WIDTH : 0;
|
||||
drawRect(rect.x, rect.y, LINE_WIDTH, rect.h + leftBottom, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.right) {
|
||||
float rightTop = metadata.top ? LINE_WIDTH : 0;
|
||||
drawRect(rect.x + rect.w, rect.y - rightTop, LINE_WIDTH, rect.h + rightTop, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.top) {
|
||||
drawRect(rect.x, rect.y - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.bottom) {
|
||||
drawRect(rect.x, rect.y + rect.h - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Color darkerColor(Color color) {
|
||||
return new Color(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
Math.min((int) (color.getAlpha() + (255f / 5) * 2), 255));
|
||||
}
|
||||
|
||||
private static void drawRect(double left, double top, double width, double height, Color color) {
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glColor4f(
|
||||
color.getRed() / 255f,
|
||||
color.getGreen() / 255f,
|
||||
color.getBlue() / 255f,
|
||||
color.getAlpha() / 255f);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertex(left, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top, 0.0D);
|
||||
tessellator.addVertex(left, top, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItem(Rectangle4i rect, int slotIdx) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null && !metadata.extended) {
|
||||
final List<ItemStack> groupItems = this.groupItems.get(metadata.groupIndex);
|
||||
|
||||
GuiContainerManager.drawItems.zLevel -= 10F;
|
||||
GuiContainerManager.drawItem(rect.x + 1, rect.y - 1, groupItems.get(groupItems.size() - 1), true, "");
|
||||
GuiContainerManager.drawItems.zLevel += 10F;
|
||||
|
||||
GuiContainerManager.drawItem(rect.x - 1, rect.y + 1, getItem(slotIdx), true, "");
|
||||
} else {
|
||||
super.beforeDrawSlot(focused, slotIdx, rect);
|
||||
super.drawItem(rect, slotIdx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,42 +327,22 @@ public class ItemPanel extends PanelWidget {
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
more = new Button("+") {
|
||||
toggleGroups = new Button("G") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? 64 : NEIClientUtils.shiftKey() ? 10 : 1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
public String getButtonTip() {
|
||||
return NEIClientUtils.translate("itempanel.collapsed.button.tip");
|
||||
}
|
||||
};
|
||||
less = new Button("-") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? -64 : NEIClientUtils.shiftKey() ? -10 : -1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
CollapsibleItems.toggleGroups(rightclick ? false : null);
|
||||
ItemList.updateFilter.restart();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
historyPanel = new ItemHistoryPanel();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -165,46 +374,62 @@ public class ItemPanel extends PanelWidget {
|
||||
return gui.height - getMarginTop(gui) - PADDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int resizeHeader(GuiContainer gui) {
|
||||
int marginTop = super.resizeHeader(gui);
|
||||
|
||||
toggleGroups.w = pageNext.w;
|
||||
toggleGroups.h = pageNext.h;
|
||||
toggleGroups.y = pageNext.y;
|
||||
toggleGroups.x = pageNext.x - toggleGroups.w - 2;
|
||||
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
protected int resizeFooter(GuiContainer gui) {
|
||||
if (!NEIClientConfig.showItemQuantityWidget() && NEIClientConfig.isSearchWidgetCentered()) return 0;
|
||||
|
||||
final int BUTTON_SIZE = 20;
|
||||
more.w = less.w = BUTTON_SIZE;
|
||||
quantity.h = BUTTON_SIZE;
|
||||
|
||||
if (NEIClientConfig.isSearchWidgetCentered()) {
|
||||
more.h = less.h = BUTTON_SIZE;
|
||||
more.x = x + w - BUTTON_SIZE;
|
||||
more.y = less.y = quantity.y = y + h - BUTTON_SIZE;
|
||||
less.x = x;
|
||||
quantity.x = x + BUTTON_SIZE + 2;
|
||||
quantity.w = more.x - quantity.x - 2;
|
||||
} else {
|
||||
quantity.x = (int) (x + (w * 0.7)) + 3;
|
||||
quantity.y = y + h - BUTTON_SIZE;
|
||||
quantity.w = (int) ((w * 0.3) - BUTTON_SIZE - 1);
|
||||
|
||||
more.h = less.h = BUTTON_SIZE / 2;
|
||||
more.y = y + h - (more.h * 2);
|
||||
|
||||
less.x = more.x = quantity.x + quantity.w;
|
||||
less.y = more.y + more.h;
|
||||
if (!NEIClientConfig.showItemQuantityWidget() && NEIClientConfig.isSearchWidgetCentered()
|
||||
&& !NEIClientConfig.showHistoryPanelWidget()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BUTTON_SIZE + 2;
|
||||
if (NEIClientConfig.showHistoryPanelWidget()) {
|
||||
historyPanel.x = x;
|
||||
historyPanel.w = w;
|
||||
historyPanel.h = ItemsGrid.SLOT_SIZE * NEIClientConfig.getIntSetting("inventory.history.useRows");
|
||||
|
||||
if (NEIClientConfig.showItemQuantityWidget() || !NEIClientConfig.isSearchWidgetCentered()) {
|
||||
historyPanel.y = LayoutManager.quantity.y - historyPanel.h - PanelWidget.PADDING;
|
||||
return LayoutManager.quantity.h + historyPanel.h + PanelWidget.PADDING * 2;
|
||||
} else {
|
||||
historyPanel.y = y + h - historyPanel.h;
|
||||
return historyPanel.h + PanelWidget.PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
return LayoutManager.quantity.h + PanelWidget.PADDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible() {
|
||||
super.setVisible();
|
||||
|
||||
if (grid.getPerPage() > 0 && NEIClientConfig.showItemQuantityWidget()) {
|
||||
LayoutManager.addWidget(more);
|
||||
LayoutManager.addWidget(less);
|
||||
LayoutManager.addWidget(quantity);
|
||||
if (grid.getPerPage() > 0) {
|
||||
if (!CollapsibleItems.isEmpty() && !grid.isEmpty()) {
|
||||
LayoutManager.addWidget(toggleGroups);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.showHistoryPanelWidget() && (!grid.isEmpty() || !historyPanel.isEmpty())) {
|
||||
LayoutManager.addWidget(historyPanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(GuiContainer gui) {
|
||||
super.resize(gui);
|
||||
historyPanel.resize(gui);
|
||||
}
|
||||
|
||||
protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) {
|
||||
ItemStack stack = grid.getItem(mouseDownSlot);
|
||||
|
||||
@@ -220,4 +445,61 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (!panelGrid.forceExpand && !NEIClientConfig.isHidden() && !currenttip.isEmpty()) {
|
||||
final ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
final List<ItemStack> items = panelGrid.groupItems.get(metadata.groupIndex);
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.collapsibleItems.customName") && !metadata.extended
|
||||
&& !"".equals(metadata.displayName)) {
|
||||
currenttip.clear();
|
||||
currenttip.add(metadata.displayName + GuiDraw.TOOLTIP_LINESPACE);
|
||||
}
|
||||
|
||||
if (items != null && items.size() > 1) {
|
||||
String message = metadata.extended ? "itempanel.collapsed.hint.collapse"
|
||||
: "itempanel.collapsed.hint.expand";
|
||||
currenttip.add(
|
||||
1,
|
||||
EnumChatFormatting.GRAY + NEIClientUtils.translate(message, items.size())
|
||||
+ EnumChatFormatting.RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (NEIClientUtils.altKey() && button == 0 && !panelGrid.forceExpand) {
|
||||
final ItemPanelSlot hoverSlot = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
CollapsibleItems.setExpanded(metadata.groupIndex, !metadata.extended);
|
||||
panelGrid.setItems(panelGrid.rawItems);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.handleClick(mousex, mousey, button);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,6 +44,7 @@ public class ItemQuantityField extends TextField {
|
||||
|
||||
if (!focused() && intValue() == 0) {
|
||||
field.setText(translate("itempanel.quantity.default"));
|
||||
field.setCursorPositionZero();
|
||||
field.setEnabled(false);
|
||||
super.draw(mousex, mousey);
|
||||
field.setEnabled(true);
|
||||
|
||||
@@ -4,19 +4,19 @@ import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
import codechicken.lib.config.ConfigTagParent;
|
||||
import codechicken.nei.ItemList.ItemsLoadedCallback;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.config.GuiItemSorter;
|
||||
import codechicken.nei.config.OptionOpenGui;
|
||||
|
||||
public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
public class ItemSorter implements Comparator<ItemStack> {
|
||||
|
||||
public static class SortEntry {
|
||||
|
||||
@@ -44,12 +44,10 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
public static final ItemSorter instance = new ItemSorter();
|
||||
|
||||
// optimisations
|
||||
public HashMap<ItemStack, Integer> ordering = null;
|
||||
public Map<ItemStack, Integer> ordering = new HashMap<>();
|
||||
|
||||
public static void sort(ArrayList<ItemStack> items) {
|
||||
public static void sort(List<ItemStack> items) {
|
||||
try {
|
||||
// items = (ArrayList<ItemStack>)
|
||||
// items.parallelStream().sorted(instance).collect(Collectors.toList());
|
||||
items.sort(instance);
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception sorting item list", e);
|
||||
@@ -65,14 +63,6 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemsLoaded() {
|
||||
HashMap<ItemStack, Integer> newMap = new HashMap<>();
|
||||
int i = 0;
|
||||
for (ItemStack stack : ItemList.items) newMap.put(stack, i++);
|
||||
ordering = newMap;
|
||||
}
|
||||
|
||||
public static SortEntry find(String name) {
|
||||
for (SortEntry e : entries) if (e.name.equals(name)) return e;
|
||||
|
||||
@@ -123,8 +113,8 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
return compareInt(id1, id2);
|
||||
});
|
||||
API.addSortOption("nei.itemsort.name", (o1, o2) -> {
|
||||
String name1 = ItemInfo.getSearchName(o1);
|
||||
String name2 = ItemInfo.getSearchName(o2);
|
||||
String name1 = o1.getDisplayName();
|
||||
String name2 = o2.getDisplayName();
|
||||
return name1.compareTo(name2);
|
||||
});
|
||||
tag.getTag("inventory.itemsort").setDefaultValue(getSaveString(list));
|
||||
@@ -136,7 +126,6 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
list = fromSaveString(activeTag().getValue());
|
||||
}
|
||||
});
|
||||
ItemList.loadCallbacks.add(instance);
|
||||
}
|
||||
|
||||
public static String getSaveString(List<SortEntry> list) {
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemStackAmount {
|
||||
|
||||
private final Map<NBTTagCompound, Long> itemMap = new LinkedHashMap<>();
|
||||
|
||||
public void putAll(ItemStackAmount amounts) {
|
||||
for (Map.Entry<NBTTagCompound, Long> entry : amounts.itemMap.entrySet()) {
|
||||
this.itemMap.put(entry.getKey(), entry.getValue() + this.itemMap.getOrDefault(entry.getKey(), 0L));
|
||||
}
|
||||
}
|
||||
|
||||
public void add(ItemStack item) {
|
||||
add(item, (long) StackInfo.getAmount(item));
|
||||
}
|
||||
|
||||
public void add(ItemStack stack, Long value) {
|
||||
if (stack == null || stack.getItem() == null) return;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
this.itemMap.put(key, value + this.itemMap.getOrDefault(key, 0L));
|
||||
}
|
||||
|
||||
public Long get(ItemStack stack) {
|
||||
if (stack == null || stack.getItem() == null) return null;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
return this.itemMap.get(key);
|
||||
}
|
||||
|
||||
public void put(ItemStack stack, long value) {
|
||||
if (stack == null || stack.getItem() == null) return;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
this.itemMap.put(key, value);
|
||||
}
|
||||
|
||||
public long getOrDefault(ItemStack stack, long defaultAmount) {
|
||||
final Long e = get(stack);
|
||||
|
||||
return e == null ? defaultAmount : e;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.itemMap.clear();
|
||||
}
|
||||
|
||||
public Long remove(ItemStack stack) {
|
||||
if (stack == null || stack.getItem() == null) return null;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
return this.itemMap.remove(key);
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<Map.Entry<NBTTagCompound, Long>> predicate) {
|
||||
return this.itemMap.entrySet().removeIf(predicate);
|
||||
}
|
||||
|
||||
public Set<Map.Entry<NBTTagCompound, Long>> entrySet() {
|
||||
return this.itemMap.entrySet();
|
||||
}
|
||||
|
||||
public List<ItemStack> values() {
|
||||
List<ItemStack> list = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<NBTTagCompound, Long> entry : this.itemMap.entrySet()) {
|
||||
list.add(StackInfo.loadFromNBT(entry.getKey(), Math.max(0, entry.getValue())));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.itemMap.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.itemMap.isEmpty();
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(ItemStackAmount map) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
result.itemMap.putAll(map.itemMap);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(ItemStackMap<Long> map) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
|
||||
for (ItemStackMap.Entry<Long> entry : map.entries()) {
|
||||
result.put(entry.key, entry.value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(Iterable<ItemStack> items) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
result.add(stack);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,9 +5,11 @@ import static codechicken.lib.inventory.InventoryUtils.newItemStack;
|
||||
import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -24,8 +26,13 @@ public class ItemStackMap<T> {
|
||||
|
||||
public final int damage;
|
||||
public final NBTTagCompound tag;
|
||||
private final int hashCode;
|
||||
|
||||
public StackMetaKey(int damage, NBTTagCompound tag) {
|
||||
if (tag != null && tag.hasNoTags()) {
|
||||
tag = null;
|
||||
}
|
||||
this.hashCode = Objects.hashCode(damage, tag);
|
||||
this.damage = damage;
|
||||
this.tag = tag;
|
||||
}
|
||||
@@ -35,7 +42,7 @@ public class ItemStackMap<T> {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(damage, tag);
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
@@ -191,7 +198,7 @@ public class ItemStackMap<T> {
|
||||
WILDCARD_TAG.setBoolean("*", true);
|
||||
}
|
||||
|
||||
private final HashMap<Item, DetailMap> itemMap = new HashMap<>();
|
||||
private final Map<Item, DetailMap> itemMap = new LinkedHashMap<>();
|
||||
private int size;
|
||||
|
||||
public T get(ItemStack key) {
|
||||
@@ -216,8 +223,22 @@ public class ItemStackMap<T> {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
public T computeIfAbsent(ItemStack key, Function<ItemStack, ? extends T> mappingFunction) {
|
||||
T value;
|
||||
if ((value = get(key)) == null) {
|
||||
T newValue;
|
||||
if ((newValue = mappingFunction.apply(key)) != null) {
|
||||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
itemMap.clear();
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public T remove(ItemStack key) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -29,11 +27,16 @@ public class ItemStackSet extends ItemStackMap<ItemStack> implements ItemFilter
|
||||
put(item, item);
|
||||
}
|
||||
|
||||
public ItemStackSet addAll(List<ItemStack> items) {
|
||||
public ItemStackSet addAll(Iterable<ItemStack> items) {
|
||||
for (ItemStack item : items) add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackSet removeAll(Iterable<ItemStack> items) {
|
||||
for (ItemStack item : items) remove(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack item) {
|
||||
return get(item) != null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
|
||||
public static final int MIN_ZOOM = 0;
|
||||
public static final int MAX_ZOOM = 1000;
|
||||
|
||||
private static final int MIN_SCALE = 2;
|
||||
private static final int SLOT_SIZE = 16;
|
||||
|
||||
private Boolean previousKeyboardRepeatEnabled = null;
|
||||
|
||||
private ItemStack stack = null;
|
||||
private String displayName = "";
|
||||
private int availableAreaWidth = 0;
|
||||
private float xPosition = 0;
|
||||
private float yPosition = 0;
|
||||
private float scale = 1;
|
||||
|
||||
public ItemZoom() {
|
||||
GuiContainerManager.addInputHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mx, int my) {
|
||||
|
||||
if (this.stack != null
|
||||
&& (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
|| NEIClientConfig.isKeyHashDown("gui.itemzoom_hold"))
|
||||
&& GuiContainerManager.shouldShowTooltip(NEIClientUtils.getGuiContainer())) {
|
||||
final float inverseScaleFactor = 1.0f / this.scale;
|
||||
final float screenScale = getScreenScale();
|
||||
final float size = SLOT_SIZE * this.scale;
|
||||
int shiftText = 10;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScaled(screenScale, screenScale, 1);
|
||||
GL11.glScaled(this.scale, this.scale, 2);
|
||||
GL11.glTranslated(this.xPosition * inverseScaleFactor, this.yPosition * inverseScaleFactor, 0);
|
||||
|
||||
GuiContainerManager.drawItem(0, 0, this.stack, false, "");
|
||||
|
||||
GL11.glPopMatrix();
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GuiContainerManager.enable2DRender();
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.showName")) {
|
||||
String dispalyName = NEIClientUtils
|
||||
.cropText(GuiDraw.fontRenderer, this.displayName, this.availableAreaWidth);
|
||||
GuiDraw.drawStringC(
|
||||
dispalyName,
|
||||
(int) ((this.xPosition + size / 2) * screenScale),
|
||||
(int) ((this.yPosition + size) * screenScale) + shiftText,
|
||||
NEIClientConfig.getSetting("inventory.itemzoom.nameColor").getHexValue());
|
||||
shiftText += GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
&& NEIClientConfig.getBooleanSetting("inventory.itemzoom.helpText")) {
|
||||
String keyName = NEIClientConfig.getKeyName("gui.itemzoom_toggle");
|
||||
|
||||
if (keyName != null) {
|
||||
String helpText = NEIClientUtils.translate("itemzoom.toggle", keyName);
|
||||
List<String> lines = GuiDraw.fontRenderer
|
||||
.listFormattedStringToWidth(helpText, this.availableAreaWidth);
|
||||
|
||||
for (String line : lines) {
|
||||
GuiDraw.drawStringC(
|
||||
line,
|
||||
(int) ((this.xPosition + size / 2) * screenScale),
|
||||
(int) ((this.yPosition + size) * screenScale) + 10 + shiftText,
|
||||
0x66555555);
|
||||
shiftText += GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
final ItemStack stack = getStackMouseOver(gui);
|
||||
|
||||
if (stack != null && (!NEIClientConfig.getBooleanSetting("inventory.itemzoom.onlySolid")
|
||||
|| Block.getBlockFromItem(stack.getItem()).getMaterial().isSolid())) {
|
||||
final float screenScale = 1.0f / getScreenScale();
|
||||
final float availableAreaWidth = (gui.width - gui.xSize) / 2 * screenScale;
|
||||
final float availableAreaHeight = gui.height * screenScale;
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
|
||||
this.scale = Math.round(getZoomAmount(gui) * getPointSize(gui) / SLOT_SIZE);
|
||||
this.yPosition = (availableAreaHeight - this.scale * SLOT_SIZE) / 2;
|
||||
this.xPosition = (availableAreaWidth - this.scale * SLOT_SIZE) / 2;
|
||||
this.availableAreaWidth = (int) (availableAreaWidth / screenScale);
|
||||
|
||||
if (availableAreaWidth / screenScale >= mouse.x) {
|
||||
this.xPosition += gui.width * screenScale - availableAreaWidth;
|
||||
}
|
||||
|
||||
try {
|
||||
this.displayName = stack.getDisplayName();
|
||||
} catch (Throwable ignored) {
|
||||
this.displayName = "Unnamed";
|
||||
}
|
||||
|
||||
this.stack = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack), 0);
|
||||
} else {
|
||||
this.stack = null;
|
||||
this.displayName = "";
|
||||
}
|
||||
}
|
||||
|
||||
private float getPointSize(GuiContainer gui) {
|
||||
final float screenScale = 1.0f / getScreenScale();
|
||||
final float availableAreaWidth = (gui.width - (gui.xSize + gui.width) / 2) * screenScale;
|
||||
return availableAreaWidth / MAX_ZOOM;
|
||||
}
|
||||
|
||||
private float getScreenScale() {
|
||||
return Minecraft.getMinecraft().currentScreen.width * 1f / Minecraft.getMinecraft().displayWidth;
|
||||
}
|
||||
|
||||
private int getZoomAmount(GuiContainer gui) {
|
||||
return Math.max(
|
||||
Math.round(SLOT_SIZE * MIN_SCALE / getPointSize(gui)),
|
||||
NEIClientConfig.getIntSetting("inventory.itemzoom.zoom"));
|
||||
}
|
||||
|
||||
private void increaseZoom(GuiContainer gui) {
|
||||
final float pointSize = getPointSize(gui);
|
||||
final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE);
|
||||
|
||||
NEIClientConfig.setIntSetting(
|
||||
"inventory.itemzoom.zoom",
|
||||
Math.min(MAX_ZOOM, Math.round((scale + 1) / (pointSize / SLOT_SIZE))));
|
||||
}
|
||||
|
||||
private void decreaseZoom(GuiContainer gui) {
|
||||
final float pointSize = getPointSize(gui);
|
||||
final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE);
|
||||
|
||||
NEIClientConfig.setIntSetting(
|
||||
"inventory.itemzoom.zoom",
|
||||
Math.max(MIN_ZOOM, Math.round(Math.max(MIN_SCALE, scale - 1) / (pointSize / SLOT_SIZE))));
|
||||
}
|
||||
|
||||
private ItemStack getStackMouseOver(GuiContainer gui) {
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.neiOnly")) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
ItemStack stack = ItemPanels.itemPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
|
||||
if (stack == null) {
|
||||
stack = ItemPanels.bookmarkPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
}
|
||||
|
||||
if (stack == null) {
|
||||
stack = ItemPanels.itemPanel.historyPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
return GuiContainerManager.getStackMouseOver(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
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.isKeyHashDown("gui.itemzoom_toggle")) {
|
||||
NEIClientConfig.getSetting("inventory.itemzoom.enabled")
|
||||
.setBooleanValue(!NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_hold")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_in")) {
|
||||
increaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_out")) {
|
||||
decreaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (previousKeyboardRepeatEnabled != null) {
|
||||
Keyboard.enableRepeatEvents(previousKeyboardRepeatEnabled);
|
||||
previousKeyboardRepeatEnabled = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {}
|
||||
|
||||
@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 void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
@@ -26,6 +27,119 @@ import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemsGrid {
|
||||
|
||||
private static class ScreenCapture {
|
||||
|
||||
private long nextCacheRefresh = 0;
|
||||
private Framebuffer framebuffer;
|
||||
|
||||
public ScreenCapture() {
|
||||
this.framebuffer = new Framebuffer(1, 1, true);
|
||||
this.framebuffer.setFramebufferColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
}
|
||||
|
||||
protected int getGridRenderingCacheFPS(int mode) {
|
||||
return mode == 1 ? NEIClientConfig.getIntSetting("inventory.gridRenderingCacheFPS") : 0;
|
||||
}
|
||||
|
||||
public boolean needRefresh(int mode) {
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
return this.nextCacheRefresh == 0 || this.framebuffer.framebufferWidth != minecraft.displayWidth
|
||||
|| framebuffer.framebufferHeight != minecraft.displayHeight
|
||||
|| getGridRenderingCacheFPS(mode) > 0 && this.nextCacheRefresh < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void refreshBuffer() {
|
||||
this.nextCacheRefresh = 0;
|
||||
}
|
||||
|
||||
public void captureScreen(Runnable callback, int mode) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
|
||||
resetFramebuffer();
|
||||
this.framebuffer.bindFramebuffer(false);
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glDepthMask(true);
|
||||
OpenGlHelper.glBlendFunc(
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
callback.run();
|
||||
|
||||
GL11.glPopAttrib();
|
||||
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
this.nextCacheRefresh = System.currentTimeMillis() + (1000 / Math.max(1, getGridRenderingCacheFPS(mode)));
|
||||
}
|
||||
|
||||
private void resetFramebuffer() {
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
|
||||
if (this.framebuffer.framebufferWidth != minecraft.displayWidth
|
||||
|| framebuffer.framebufferHeight != minecraft.displayHeight) {
|
||||
this.framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
||||
this.framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
|
||||
} else {
|
||||
this.framebuffer.framebufferClear();
|
||||
}
|
||||
|
||||
// copy depth buffer from MC (fix Angelica)
|
||||
OpenGlHelper.func_153171_g(GL30.GL_READ_FRAMEBUFFER, minecraft.getFramebuffer().framebufferObject);
|
||||
OpenGlHelper.func_153171_g(GL30.GL_DRAW_FRAMEBUFFER, this.framebuffer.framebufferObject);
|
||||
GL30.glBlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT,
|
||||
GL11.GL_NEAREST);
|
||||
}
|
||||
|
||||
public void renderCapturedScreen() {
|
||||
this.framebuffer.bindFramebufferTexture();
|
||||
|
||||
final Tessellator tessellator = Tessellator.instance;
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
final ScaledResolution scaledresolution = new ScaledResolution(
|
||||
minecraft,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight);
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper
|
||||
.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
|
||||
tessellator.startDrawingQuads();
|
||||
|
||||
tessellator.addVertexWithUV(0, scaledresolution.getScaledHeight_double(), 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(
|
||||
scaledresolution.getScaledWidth_double(),
|
||||
scaledresolution.getScaledHeight_double(),
|
||||
0.0,
|
||||
1,
|
||||
0);
|
||||
tessellator.addVertexWithUV(scaledresolution.getScaledWidth_double(), 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
this.framebuffer.unbindFramebufferTexture();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final int SLOT_SIZE = 18;
|
||||
|
||||
protected int width;
|
||||
@@ -49,10 +163,7 @@ public class ItemsGrid {
|
||||
|
||||
protected Label messageLabel = new Label(getMessageOnEmpty(), true);
|
||||
|
||||
@Nullable
|
||||
private Framebuffer framebuffer = null;
|
||||
|
||||
protected boolean refreshBuffer = true;
|
||||
protected ScreenCapture screenCapture = null;
|
||||
|
||||
public ArrayList<ItemStack> getItems() {
|
||||
return realItems;
|
||||
@@ -66,6 +177,10 @@ public class ItemsGrid {
|
||||
return realItems.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return realItems.isEmpty();
|
||||
}
|
||||
|
||||
public int indexOf(ItemStack stackA, boolean useNBT) {
|
||||
|
||||
for (int idx = 0; idx < realItems.size(); idx++) {
|
||||
@@ -152,7 +267,9 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
protected void onGridChanged() {
|
||||
refreshBuffer = true;
|
||||
if (this.screenCapture != null) {
|
||||
this.screenCapture.refreshBuffer();
|
||||
}
|
||||
this.gridMask = null;
|
||||
}
|
||||
|
||||
@@ -173,11 +290,13 @@ public class ItemsGrid {
|
||||
invalidSlotMap = new boolean[rows * columns];
|
||||
perPage = columns * rows;
|
||||
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
if (gui != null) {
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRows != rows || oldColumns != columns || !Arrays.equals(oldSlotMap, invalidSlotMap)) {
|
||||
@@ -247,7 +366,7 @@ public class ItemsGrid {
|
||||
return this.gridMask;
|
||||
}
|
||||
|
||||
private void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
@@ -258,7 +377,7 @@ public class ItemsGrid {
|
||||
}
|
||||
}
|
||||
|
||||
private void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
protected void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
@@ -278,34 +397,6 @@ public class ItemsGrid {
|
||||
|
||||
protected void afterDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {}
|
||||
|
||||
private void blitExistingBuffer() {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
getFrameBuffer().bindFramebufferTexture();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
ScaledResolution res = new ScaledResolution(minecraft, minecraft.displayWidth, minecraft.displayHeight);
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertexWithUV(0, res.getScaledHeight_double(), 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), res.getScaledHeight_double(), 0.0, 1, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
||||
tessellator.draw();
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
private Framebuffer getFrameBuffer() {
|
||||
|
||||
if (framebuffer == null) {
|
||||
framebuffer = new Framebuffer(1, 1, true);
|
||||
framebuffer.setFramebufferColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
private void drawItems() {
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
|
||||
@@ -319,8 +410,8 @@ public class ItemsGrid {
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
}
|
||||
|
||||
protected boolean shouldCacheItemRendering() {
|
||||
return NEIClientConfig.shouldCacheItemRendering();
|
||||
protected int getGridRenderingCacheMode() {
|
||||
return NEIClientConfig.getGridRenderingCacheMode();
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey) {
|
||||
@@ -329,44 +420,28 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
final ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
final int gridRenderingCacheMode = getGridRenderingCacheMode();
|
||||
|
||||
if (shouldCacheItemRendering()) {
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
|
||||
if (refreshBuffer) {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
Framebuffer framebuffer = getFrameBuffer();
|
||||
framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
||||
framebuffer.framebufferClear();
|
||||
framebuffer.bindFramebuffer(false);
|
||||
if (gridRenderingCacheMode > 0) {
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glDepthMask(true);
|
||||
OpenGlHelper.glBlendFunc(
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
drawItems();
|
||||
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
refreshBuffer = false;
|
||||
if (this.screenCapture == null) {
|
||||
this.screenCapture = new ScreenCapture();
|
||||
}
|
||||
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
blitExistingBuffer();
|
||||
if (this.screenCapture.needRefresh(gridRenderingCacheMode)) {
|
||||
this.screenCapture.captureScreen(this::drawItems, gridRenderingCacheMode);
|
||||
}
|
||||
|
||||
this.screenCapture.renderCapturedScreen();
|
||||
} else {
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
drawItems();
|
||||
}
|
||||
|
||||
afterDrawItems(mousex, mousey, focused);
|
||||
}
|
||||
|
||||
public void postDrawTooltips(int mousex, int mousey, List<String> tooltip) {}
|
||||
|
||||
public void setVisible() {
|
||||
if (getItems().isEmpty() && getMessageOnEmpty() != null) {
|
||||
LayoutManager.addWidget(messageLabel);
|
||||
@@ -382,8 +457,8 @@ public class ItemsGrid {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int overRow = (int) ((mousey - marginTop) / SLOT_SIZE);
|
||||
final int overColumn = (int) ((mousex - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int overRow = (mousey - marginTop) / SLOT_SIZE;
|
||||
final int overColumn = (mousex - marginLeft - paddingLeft) / SLOT_SIZE;
|
||||
final int slt = columns * overRow + overColumn;
|
||||
|
||||
if (overRow >= rows || overColumn >= columns) {
|
||||
@@ -412,8 +487,8 @@ public class ItemsGrid {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int r = (int) ((py - marginTop) / SLOT_SIZE);
|
||||
final int c = (int) ((px - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int r = (py - marginTop) / SLOT_SIZE;
|
||||
final int c = (px - marginLeft - paddingLeft) / SLOT_SIZE;
|
||||
|
||||
return !isInvalidSlot(columns * r + c);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.fontRenderer;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw.ITooltipLineHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.ReadableNumberConverter;
|
||||
|
||||
public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
protected static final int MAX_COLUMNS = 11;
|
||||
protected static final int MARGIN_TOP = 2;
|
||||
|
||||
protected String label;
|
||||
protected EnumChatFormatting labelColor = EnumChatFormatting.GRAY;
|
||||
protected List<ItemStack> items;
|
||||
protected Dimension size = new Dimension();
|
||||
protected boolean saveStackSize = false;
|
||||
protected int columns = 0;
|
||||
protected int count = 0;
|
||||
protected int rows = 0;
|
||||
protected int length = 0;
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items) {
|
||||
this(label, items, true, 5);
|
||||
}
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items, boolean saveStackSize, int maxRows) {
|
||||
this.label = label;
|
||||
this.items = groupingItemStacks(items);
|
||||
this.saveStackSize = saveStackSize;
|
||||
this.length = this.items.size();
|
||||
|
||||
if (this.length > 0) {
|
||||
this.columns = Math.min(MAX_COLUMNS, this.length);
|
||||
this.rows = Math.min(maxRows, (int) Math.ceil((float) this.length / this.columns));
|
||||
|
||||
this.size.width = Math
|
||||
.max(this.columns * ItemsGrid.SLOT_SIZE, fontRenderer.getStringWidth(this.label) + 15);
|
||||
this.size.height = this.rows * ItemsGrid.SLOT_SIZE + fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP;
|
||||
|
||||
this.count = Math.min(
|
||||
this.length,
|
||||
Math.min(
|
||||
this.columns * this.rows,
|
||||
this.length > MAX_COLUMNS * maxRows ? (MAX_COLUMNS * maxRows) : Integer.MAX_VALUE));
|
||||
|
||||
if (this.items.size() > this.count) {
|
||||
String text = "+" + (this.items.size() - this.count);
|
||||
this.count -= (int) Math.ceil((float) (fontRenderer.getStringWidth(text) - 2) / ItemsGrid.SLOT_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.items.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public void setLabelColor(EnumChatFormatting color) {
|
||||
this.labelColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.length == 0) return;
|
||||
|
||||
y += MARGIN_TOP;
|
||||
|
||||
fontRenderer.drawStringWithShadow(this.labelColor + this.label + ":", x, y, 0);
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glPushMatrix();
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
|
||||
GL11.glScaled(1, 1, 3);
|
||||
GL11.glTranslatef(x, y + fontRenderer.FONT_HEIGHT + 2, 0);
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
for (int i = 0; i < this.count; i++) {
|
||||
ItemStack drawStack = this.items.get(i);
|
||||
int col = i % this.columns;
|
||||
int row = i / this.columns;
|
||||
|
||||
String stackSize = !this.saveStackSize || drawStack.stackSize == 0 ? ""
|
||||
: ReadableNumberConverter.INSTANCE.toWideReadableForm(drawStack.stackSize);
|
||||
|
||||
drawItem(col * ItemsGrid.SLOT_SIZE, row * ItemsGrid.SLOT_SIZE, drawStack, stackSize);
|
||||
}
|
||||
|
||||
if (this.count < this.items.size()) {
|
||||
String text = "+" + (this.items.size() - this.count);
|
||||
|
||||
fontRenderer.drawStringWithShadow(
|
||||
text,
|
||||
MAX_COLUMNS * ItemsGrid.SLOT_SIZE - fontRenderer.getStringWidth(text) - 2,
|
||||
(this.rows - 1) * ItemsGrid.SLOT_SIZE + (ItemsGrid.SLOT_SIZE - fontRenderer.FONT_HEIGHT) / 2,
|
||||
0xee555555);
|
||||
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
protected void drawItem(int x, int y, ItemStack drawStack, String stackSize) {
|
||||
GuiContainerManager.drawItem(x, y, drawStack, true, stackSize);
|
||||
}
|
||||
|
||||
private List<ItemStack> groupingItemStacks(List<ItemStack> items) {
|
||||
final List<ItemStack> result = ItemStackAmount.of(items).values();
|
||||
|
||||
for (ItemStack stack : result) {
|
||||
if (StackInfo.itemStackToNBT(stack).hasKey("gtFluidName")) {
|
||||
stack.stackSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// Simple LRUCache
|
||||
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
private final int capacity;
|
||||
|
||||
public LRUCache(int capacity) {
|
||||
super(capacity, 0.75f, true);
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > capacity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,8 +31,11 @@ import static codechicken.nei.NEIClientUtils.toggleMagnetMode;
|
||||
import static codechicken.nei.NEIClientUtils.toggleRaining;
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -76,28 +79,23 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
/**
|
||||
* Sorted bottom first
|
||||
*/
|
||||
private static TreeSet<Widget> drawWidgets = new TreeSet<>(new WidgetZOrder(false));
|
||||
private static Set<Widget> drawWidgets = new TreeSet<>(new WidgetZOrder(false));
|
||||
/**
|
||||
* Sorted top first
|
||||
*/
|
||||
private static TreeSet<Widget> controlWidgets = new TreeSet<>(new WidgetZOrder(true));
|
||||
private static Set<Widget> controlWidgets = new TreeSet<>(new WidgetZOrder(true));
|
||||
|
||||
public static ItemPanel itemPanel;
|
||||
public static BookmarkPanel bookmarkPanel;
|
||||
public static SubsetWidget dropDown;
|
||||
public static PresetsWidget presetsPanel;
|
||||
public static SearchField searchField;
|
||||
public static ItemZoom itemZoom;
|
||||
|
||||
public static ButtonCycled options;
|
||||
public static ButtonCycled bookmarksButton;
|
||||
|
||||
@Deprecated
|
||||
public static Button more;
|
||||
|
||||
@Deprecated
|
||||
public static Button less;
|
||||
|
||||
@Deprecated
|
||||
public static ItemQuantityField quantity;
|
||||
|
||||
public static Button delete;
|
||||
@@ -145,8 +143,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
gui.guiTop = (gui.height - gui.ySize) / 2;
|
||||
|
||||
if (gui instanceof GuiContainerCreative && gui.buttonList.size() >= 2) {
|
||||
GuiButton button1 = (GuiButton) gui.buttonList.get(0);
|
||||
GuiButton button2 = (GuiButton) gui.buttonList.get(1);
|
||||
GuiButton button1 = gui.buttonList.get(0);
|
||||
GuiButton button2 = gui.buttonList.get(1);
|
||||
button1.xPosition = gui.guiLeft;
|
||||
button2.xPosition = gui.guiLeft + gui.xSize - 20;
|
||||
}
|
||||
@@ -167,14 +165,18 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
if (isHidden()) return;
|
||||
|
||||
for (Widget widget : controlWidgets) widget.onGuiClick(mousex, mousey);
|
||||
for (Widget widget : controlWidgets) {
|
||||
widget.onGuiClick(mousex, mousey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
if (isHidden()) return false;
|
||||
|
||||
if (!isEnabled()) return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button);
|
||||
if (!isEnabled()) {
|
||||
return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button);
|
||||
}
|
||||
|
||||
for (Widget widget : controlWidgets) {
|
||||
widget.onGuiClick(mousex, mousey);
|
||||
@@ -188,10 +190,22 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled())
|
||||
for (Widget widget : drawWidgets) if (widget.contains(mousex, mousey)) return true;
|
||||
return getWidgetUnderMouse(mousex, mousey) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
public Widget getWidgetUnderMouse(int mousex, int mousey) {
|
||||
|
||||
if (isHidden() || !isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Widget widget : controlWidgets) {
|
||||
if (widget.contains(mousex, mousey)) {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
@@ -216,7 +230,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.hide_bookmarks")) {
|
||||
toggleBooleanSetting("inventory.bookmarksEnabled");
|
||||
toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -247,12 +261,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public ItemStack getStackUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled()) {
|
||||
for (Widget widget : drawWidgets) {
|
||||
ItemStack stack = widget.getStackMouseOver(mousex, mousey);
|
||||
if (stack != null) return stack;
|
||||
}
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
return focused.getStackMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -281,16 +295,32 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
for (Widget widget : drawWidgets) widget.postDrawTooltips(mousex, mousey, tooltip);
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
focused.postDrawTooltips(mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
for (Widget widget : drawWidgets) currenttip = widget.handleTooltip(mousex, mousey, currenttip);
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
currenttip = focused.handleTooltip(mousex, mousey, currenttip);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleTooltip(gui, mousex, mousey, currenttip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@@ -307,32 +337,55 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
currenttip.set(0, mainname);
|
||||
}
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
final Widget focused = getWidgetUnderMouse(mouse.x, mouse.y);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleItemDisplayName(gui, stack, currenttip);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
hotkeys = tip.handleHotkeys(gui, mousex, mousey, hotkeys);
|
||||
}
|
||||
}
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
public static void layout(GuiContainer gui) {
|
||||
VisiblityData visiblity = new VisiblityData();
|
||||
|
||||
if (isHidden()) visiblity.showNEI = false;
|
||||
|
||||
if (isBookmarkPanelHidden()) visiblity.showBookmarkPanel = false;
|
||||
|
||||
if (gui.height - gui.ySize <= 40 && NEIClientConfig.isSearchWidgetCentered())
|
||||
visiblity.showSearchSection = false;
|
||||
|
||||
if (visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showSubsetDropdown = false;
|
||||
|
||||
if (!visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showPresetsDropdown = false;
|
||||
|
||||
if (gui.guiLeft - 4 < 76) visiblity.showWidgets = false;
|
||||
|
||||
if (!itemsLoaded) visiblity.showPresetsDropdown = false;
|
||||
visiblity.showNEI = !isHidden();
|
||||
visiblity.showBookmarkPanel = !isBookmarkPanelHidden();
|
||||
visiblity.showSearchSection = !(gui.height - gui.ySize <= 40 && NEIClientConfig.isSearchWidgetCentered());
|
||||
visiblity.showSubsetDropdown = NEIClientConfig.showSubsetWidget()
|
||||
&& (gui.guiTop > 20 || visiblity.showSearchSection && !NEIClientConfig.subsetWidgetOnTop());
|
||||
visiblity.showWidgets = gui.guiLeft - 4 > 76;
|
||||
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
@@ -355,9 +408,11 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
bookmarkPanel = ItemPanels.bookmarkPanel;
|
||||
bookmarkPanel.init();
|
||||
|
||||
itemZoom = new ItemZoom();
|
||||
|
||||
dropDown = new SubsetWidget();
|
||||
presetsPanel = new PresetsWidget();
|
||||
searchField = new SearchField("search");
|
||||
API.addItemFilter(searchField);
|
||||
|
||||
options = new ButtonCycled(3) {
|
||||
|
||||
@@ -379,7 +434,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
if (Keyboard.getEventKeyState() && getIsAccessibleControlEventKey()) {
|
||||
if (Keyboard.getEventKeyState() && getIsAccessibleControlEventKey()
|
||||
&& NEIClientConfig.canChangeCheatMode()) {
|
||||
NEIClientConfig.cycleSetting("inventory.cheatmode", 3);
|
||||
} else {
|
||||
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT
|
||||
@@ -403,7 +459,10 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
else if (cheatMode == 2) modeColor = EnumChatFormatting.RED.toString();
|
||||
String controlKeyLocalization = translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl");
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode." + cheatMode));
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
|
||||
if (NEIClientConfig.canChangeCheatMode()) {
|
||||
tooltip.add(
|
||||
modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,7 +481,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
NEIClientConfig.toggleBooleanSetting("inventory.bookmarksEnabled");
|
||||
NEIClientConfig.toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -436,9 +495,43 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
}
|
||||
};
|
||||
|
||||
more = ItemPanels.itemPanel.more;
|
||||
less = ItemPanels.itemPanel.less;
|
||||
quantity = ItemPanels.itemPanel.quantity;
|
||||
more = new Button("+") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? 64 : NEIClientUtils.shiftKey() ? 10 : 1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
less = new Button("-") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? -64 : NEIClientUtils.shiftKey() ? -10 : -1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
|
||||
delete = new Button() {
|
||||
|
||||
@Override
|
||||
@@ -614,12 +707,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
if (!itemsLoaded) {
|
||||
ItemList.loadItems.restart();
|
||||
itemsLoaded = true;
|
||||
}
|
||||
overlayRenderer = null;
|
||||
|
||||
overlayRenderer = null;
|
||||
getLayoutStyle().init();
|
||||
layout(gui);
|
||||
AutoFocusWidget.instance.load(gui);
|
||||
}
|
||||
|
||||
NEIController.load(gui);
|
||||
@@ -651,14 +744,15 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
addWidget(options);
|
||||
addWidget(bookmarksButton);
|
||||
|
||||
if (visiblity.showItemPanel && NEIClientConfig.showItemQuantityWidget()) {
|
||||
addWidget(quantity);
|
||||
addWidget(more);
|
||||
addWidget(less);
|
||||
}
|
||||
|
||||
if (visiblity.showItemPanel) {
|
||||
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
drawWidgets.add(itemPanel);
|
||||
} else {
|
||||
addWidget(itemPanel);
|
||||
}
|
||||
|
||||
addWidget(itemPanel);
|
||||
itemPanel.setVisible();
|
||||
}
|
||||
|
||||
@@ -667,13 +761,13 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
bookmarkPanel.setVisible();
|
||||
}
|
||||
|
||||
if (visiblity.showPresetsDropdown) {
|
||||
addWidget(presetsPanel);
|
||||
}
|
||||
|
||||
searchField.setVisible(visiblity.showSearchSection);
|
||||
if (visiblity.showSearchSection) {
|
||||
if (visiblity.showSearchSection && NEIClientConfig.isSearchWidgetCentered()
|
||||
|| visiblity.showItemPanel && !NEIClientConfig.isSearchWidgetCentered()) {
|
||||
searchField.setVisible(true);
|
||||
addWidget(searchField);
|
||||
} else {
|
||||
searchField.setVisible(false);
|
||||
searchField.setFocus(false);
|
||||
}
|
||||
|
||||
if (visiblity.showUtilityButtons) {
|
||||
@@ -688,6 +782,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
if (canPerformAction("delete")) addWidget(delete);
|
||||
}
|
||||
|
||||
addWidget(itemZoom);
|
||||
|
||||
if (visiblity.showSubsetDropdown) {
|
||||
// Bookmarks or Subset/dropdown
|
||||
addWidget(dropDown);
|
||||
@@ -722,7 +818,9 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
if (isHidden() || !isEnabled()) return false;
|
||||
|
||||
for (Widget widget : drawWidgets) if (widget.onMouseWheel(scrolled, mousex, mousey)) return true;
|
||||
for (Widget widget : controlWidgets) {
|
||||
if (widget.onMouseWheel(scrolled, mousex, mousey)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -825,9 +923,19 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
drawTexturedModalRect(x2, y2, tx2, ty2, w2, h2); // bottom right
|
||||
}
|
||||
|
||||
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent) {
|
||||
Image icon = itemPresenceOverlays[isPresent ? 1 : 0];
|
||||
drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon);
|
||||
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent, boolean slotHighlight) {
|
||||
|
||||
if (slotHighlight) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
drawRect(slotX, slotY, 16, 16, isPresent ? 0x8000AA00 : 0x80AA0000);
|
||||
GL11.glPopAttrib();
|
||||
} else {
|
||||
Image icon = itemPresenceOverlays[isPresent ? 1 : 0];
|
||||
drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static LayoutManager instance() {
|
||||
|
||||
@@ -1,34 +1,20 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
import static codechicken.nei.LayoutManager.bookmarkPanel;
|
||||
import static codechicken.nei.LayoutManager.bookmarksButton;
|
||||
import static codechicken.nei.LayoutManager.delete;
|
||||
import static codechicken.nei.LayoutManager.dropDown;
|
||||
import static codechicken.nei.LayoutManager.gamemode;
|
||||
import static codechicken.nei.LayoutManager.heal;
|
||||
import static codechicken.nei.LayoutManager.itemPanel;
|
||||
import static codechicken.nei.LayoutManager.itemPresenceOverlays;
|
||||
import static codechicken.nei.LayoutManager.magnet;
|
||||
import static codechicken.nei.LayoutManager.options;
|
||||
import static codechicken.nei.LayoutManager.presetsPanel;
|
||||
import static codechicken.nei.LayoutManager.rain;
|
||||
import static codechicken.nei.LayoutManager.searchField;
|
||||
import static codechicken.nei.LayoutManager.timeButtons;
|
||||
import static codechicken.nei.NEIClientConfig.canPerformAction;
|
||||
import static codechicken.nei.NEIClientConfig.disabledActions;
|
||||
import static codechicken.nei.NEIClientConfig.getMagnetMode;
|
||||
import static codechicken.nei.NEIClientConfig.isEnabled;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.LayoutStyle;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
|
||||
public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
protected static final int BUTTON_SIZE = 20;
|
||||
protected static final int MARGIN = 2;
|
||||
|
||||
public int buttonCount;
|
||||
public int leftSize;
|
||||
public int numButtons;
|
||||
@@ -40,19 +26,21 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
delete.icon = new Image(144, 12, 12, 12);
|
||||
rain.icon = new Image(120, 12, 12, 12);
|
||||
gamemode.icons[0] = new Image(132, 12, 12, 12);
|
||||
gamemode.icons[1] = new Image(156, 12, 12, 12);
|
||||
gamemode.icons[2] = new Image(168, 12, 12, 12);
|
||||
magnet.icon = new Image(180, 24, 12, 12);
|
||||
timeButtons[0].icon = new Image(132, 24, 12, 12);
|
||||
timeButtons[1].icon = new Image(120, 24, 12, 12);
|
||||
timeButtons[2].icon = new Image(144, 24, 12, 12);
|
||||
timeButtons[3].icon = new Image(156, 24, 12, 12);
|
||||
heal.icon = new Image(168, 24, 12, 12);
|
||||
itemPresenceOverlays[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 40, 8, 8).build();
|
||||
itemPresenceOverlays[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8).build();
|
||||
LayoutManager.delete.icon = new Image(144, 12, 12, 12);
|
||||
LayoutManager.rain.icon = new Image(120, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[0] = new Image(132, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[1] = new Image(156, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[2] = new Image(168, 12, 12, 12);
|
||||
LayoutManager.magnet.icon = new Image(180, 24, 12, 12);
|
||||
LayoutManager.timeButtons[0].icon = new Image(132, 24, 12, 12);
|
||||
LayoutManager.timeButtons[1].icon = new Image(120, 24, 12, 12);
|
||||
LayoutManager.timeButtons[2].icon = new Image(144, 24, 12, 12);
|
||||
LayoutManager.timeButtons[3].icon = new Image(156, 24, 12, 12);
|
||||
LayoutManager.heal.icon = new Image(168, 24, 12, 12);
|
||||
LayoutManager.itemPresenceOverlays[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 40, 8, 8)
|
||||
.build();
|
||||
LayoutManager.itemPresenceOverlays[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,89 +53,177 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
reset();
|
||||
|
||||
leftSize = ItemPanels.bookmarkPanel.getWidth(gui);
|
||||
numButtons = Math.max(leftSize / 18, 1);
|
||||
numButtons = Math.max(leftSize / 20, 1);
|
||||
|
||||
delete.state = 0x4;
|
||||
if (NEIController.getDeleteMode()) delete.state |= 1;
|
||||
else if (!visiblity.enableDeleteMode) delete.state |= 2;
|
||||
|
||||
rain.state = 0x4;
|
||||
if (disabledActions.contains("rain")) rain.state |= 2;
|
||||
else if (NEIClientUtils.isRaining()) rain.state |= 1;
|
||||
|
||||
gamemode.state = 0x4;
|
||||
if (NEIClientUtils.getGamemode() != 0) {
|
||||
gamemode.state |= 0x1;
|
||||
gamemode.index = NEIClientUtils.getGamemode() - 1;
|
||||
} else {
|
||||
if (NEIClientUtils.isValidGamemode("creative")) gamemode.index = 0;
|
||||
else if (NEIClientUtils.isValidGamemode("creative+")) gamemode.index = 1;
|
||||
else if (NEIClientUtils.isValidGamemode("adventure")) gamemode.index = 2;
|
||||
LayoutManager.delete.state = 0x4;
|
||||
if (NEIController.getDeleteMode()) {
|
||||
LayoutManager.delete.state |= 1;
|
||||
} else if (!visiblity.enableDeleteMode) {
|
||||
LayoutManager.delete.state |= 2;
|
||||
}
|
||||
bookmarksButton.index = NEIClientConfig.isBookmarkPanelHidden() ? 0 : 1;
|
||||
options.index = NEIClientConfig.getCheatMode();
|
||||
|
||||
magnet.state = 0x4 | (getMagnetMode() ? 1 : 0);
|
||||
LayoutManager.rain.state = 0x4;
|
||||
if (NEIClientConfig.disabledActions.contains("rain")) {
|
||||
LayoutManager.rain.state |= 2;
|
||||
} else if (NEIClientUtils.isRaining()) {
|
||||
LayoutManager.rain.state |= 1;
|
||||
}
|
||||
|
||||
if (canPerformAction("delete")) layoutButton(delete);
|
||||
if (canPerformAction("rain")) layoutButton(rain);
|
||||
if (NEIClientUtils.isValidGamemode("creative") || NEIClientUtils.isValidGamemode("creative+")
|
||||
|| NEIClientUtils.isValidGamemode("adventure"))
|
||||
layoutButton(gamemode);
|
||||
if (canPerformAction("magnet")) layoutButton(magnet);
|
||||
if (canPerformAction("time")) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
timeButtons[i].state = disabledActions.contains(NEIActions.timeZones[i]) ? 2 : 0;
|
||||
layoutButton(timeButtons[i]);
|
||||
LayoutManager.gamemode.state = 0x4;
|
||||
if (NEIClientUtils.getGamemode() != 0) {
|
||||
LayoutManager.gamemode.state |= 0x1;
|
||||
LayoutManager.gamemode.index = NEIClientUtils.getGamemode() - 1;
|
||||
} else {
|
||||
if (NEIClientUtils.isValidGamemode("creative")) {
|
||||
LayoutManager.gamemode.index = 0;
|
||||
} else if (NEIClientUtils.isValidGamemode("creative+")) {
|
||||
LayoutManager.gamemode.index = 1;
|
||||
} else if (NEIClientUtils.isValidGamemode("adventure")) {
|
||||
LayoutManager.gamemode.index = 2;
|
||||
}
|
||||
}
|
||||
if (canPerformAction("heal")) layoutButton(heal);
|
||||
LayoutManager.bookmarksButton.index = NEIClientConfig.isBookmarkPanelHidden() ? 0 : 1;
|
||||
LayoutManager.options.index = NEIClientConfig.getCheatMode();
|
||||
|
||||
itemPanel.resize(gui);
|
||||
bookmarkPanel.resize(gui);
|
||||
LayoutManager.magnet.state = 0x4 | (NEIClientConfig.getMagnetMode() ? 1 : 0);
|
||||
|
||||
options.x = isEnabled() ? 0 : 6;
|
||||
options.y = isEnabled() ? gui.height - 22 : gui.height - 28;
|
||||
options.w = 22;
|
||||
options.h = 22;
|
||||
if (NEIClientConfig.canPerformAction("delete")) {
|
||||
layoutButton(LayoutManager.delete);
|
||||
}
|
||||
|
||||
bookmarksButton.x = 24 + (isEnabled() ? 0 : 6);
|
||||
bookmarksButton.y = isEnabled() ? gui.height - 22 : gui.height - 28;
|
||||
bookmarksButton.w = 22;
|
||||
bookmarksButton.h = 22;
|
||||
if (NEIClientConfig.canPerformAction("rain")) {
|
||||
layoutButton(LayoutManager.rain);
|
||||
}
|
||||
|
||||
dropDown.h = 18;
|
||||
dropDown.w = 150;
|
||||
dropDown.y = 0;
|
||||
dropDown.x = (gui.width - gui.xSize) / 2 + gui.xSize - dropDown.w;
|
||||
if (NEIClientUtils.isValidGamemode("creative") || NEIClientUtils.isValidGamemode("creative+")
|
||||
|| NEIClientUtils.isValidGamemode("adventure")) {
|
||||
layoutButton(LayoutManager.gamemode);
|
||||
}
|
||||
|
||||
presetsPanel.h = 16;
|
||||
presetsPanel.w = 150;
|
||||
presetsPanel.y = 2;
|
||||
presetsPanel.x = (gui.width - gui.xSize) / 2 + gui.xSize - presetsPanel.w;
|
||||
if (NEIClientConfig.canPerformAction("magnet")) {
|
||||
layoutButton(LayoutManager.magnet);
|
||||
}
|
||||
|
||||
searchField.h = 20;
|
||||
if (NEIClientConfig.isSearchWidgetCentered()) {
|
||||
searchField.w = 150;
|
||||
searchField.x = (gui.width - searchField.w) / 2;
|
||||
if (NEIClientConfig.canPerformAction("time")) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LayoutManager.timeButtons[i].state = NEIClientConfig.disabledActions.contains(NEIActions.timeZones[i])
|
||||
? 2
|
||||
: 0;
|
||||
layoutButton(LayoutManager.timeButtons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("heal")) {
|
||||
layoutButton(LayoutManager.heal);
|
||||
}
|
||||
|
||||
layoutFooter(gui, visiblity);
|
||||
|
||||
LayoutManager.itemPanel.resize(gui);
|
||||
LayoutManager.bookmarkPanel.resize(gui);
|
||||
LayoutManager.itemZoom.resize(gui);
|
||||
}
|
||||
|
||||
protected void layoutFooter(GuiContainer gui, VisiblityData visiblity) {
|
||||
|
||||
LayoutManager.options.x = MARGIN;
|
||||
LayoutManager.options.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
LayoutManager.options.w = LayoutManager.options.h = BUTTON_SIZE;
|
||||
|
||||
LayoutManager.bookmarksButton.x = LayoutManager.options.x + LayoutManager.options.w + MARGIN;
|
||||
LayoutManager.bookmarksButton.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
LayoutManager.bookmarksButton.w = LayoutManager.bookmarksButton.h = BUTTON_SIZE;
|
||||
|
||||
final Rectangle4i searchArea = getSearchFieldArea(gui);
|
||||
final Rectangle4i quantityArea = getQuantityFieldArea(visiblity);
|
||||
|
||||
LayoutManager.searchField.x = searchArea.x;
|
||||
LayoutManager.searchField.y = searchArea.y;
|
||||
LayoutManager.searchField.w = searchArea.w;
|
||||
LayoutManager.searchField.h = searchArea.h;
|
||||
|
||||
if (!NEIClientConfig.subsetWidgetOnTop() && visiblity.showSubsetDropdown) {
|
||||
LayoutManager.dropDown.x = searchArea.x;
|
||||
LayoutManager.dropDown.y = searchArea.y;
|
||||
LayoutManager.dropDown.h = LayoutManager.dropDown.w = BUTTON_SIZE;
|
||||
|
||||
LayoutManager.searchField.x += BUTTON_SIZE;
|
||||
LayoutManager.searchField.w -= BUTTON_SIZE;
|
||||
} else {
|
||||
searchField.w = (int) (itemPanel.w * (NEIClientConfig.showItemQuantityWidget() ? 0.7 : 1));
|
||||
searchField.x = itemPanel.x;
|
||||
LayoutManager.dropDown.h = 16;
|
||||
LayoutManager.dropDown.w = 150;
|
||||
LayoutManager.dropDown.y = MARGIN;
|
||||
LayoutManager.dropDown.x = (gui.width - LayoutManager.dropDown.w) / 2;
|
||||
}
|
||||
searchField.y = gui.height - searchField.h - 2;
|
||||
|
||||
if (!visiblity.showItemSection) {
|
||||
searchField.setFocus(false);
|
||||
if (quantityArea.w == ItemPanels.itemPanel.w) {
|
||||
LayoutManager.more.w = LayoutManager.less.w = BUTTON_SIZE;
|
||||
LayoutManager.more.h = LayoutManager.less.h = LayoutManager.quantity.h = quantityArea.h;
|
||||
LayoutManager.more.y = LayoutManager.less.y = LayoutManager.quantity.y = quantityArea.y;
|
||||
|
||||
LayoutManager.less.x = quantityArea.x;
|
||||
LayoutManager.more.x = quantityArea.x2() - BUTTON_SIZE;
|
||||
|
||||
LayoutManager.quantity.x = LayoutManager.less.x + LayoutManager.less.w + 1;
|
||||
LayoutManager.quantity.w = LayoutManager.more.x - LayoutManager.quantity.x - 1;
|
||||
} else {
|
||||
LayoutManager.quantity.x = quantityArea.x;
|
||||
LayoutManager.quantity.w = quantityArea.w - 18;
|
||||
LayoutManager.quantity.y = LayoutManager.more.y = quantityArea.y;
|
||||
LayoutManager.quantity.h = quantityArea.h;
|
||||
|
||||
LayoutManager.more.w = LayoutManager.less.w = 18;
|
||||
LayoutManager.more.x = LayoutManager.less.x = LayoutManager.quantity.x + LayoutManager.quantity.w;
|
||||
LayoutManager.more.h = LayoutManager.less.h = LayoutManager.quantity.h / 2;
|
||||
LayoutManager.less.y = LayoutManager.more.y + LayoutManager.more.h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Rectangle4i getSearchFieldArea(GuiContainer gui) {
|
||||
final Rectangle4i area = new Rectangle4i(0, 0, 0, BUTTON_SIZE);
|
||||
|
||||
if (NEIClientConfig.isSearchWidgetCentered()) {
|
||||
area.w = gui.xSize - MARGIN * 2;
|
||||
area.x = (gui.width - area.w) / 2;
|
||||
area.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
} else if (NEIClientConfig.showItemQuantityWidget()) {
|
||||
area.w = ItemPanels.itemPanel.w - (int) Math.max(BUTTON_SIZE * 2.5f, ItemPanels.itemPanel.w * 0.3f) - 1;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
} else {
|
||||
area.w = ItemPanels.itemPanel.w;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
private Rectangle4i getQuantityFieldArea(VisiblityData visiblity) {
|
||||
final Rectangle4i area = new Rectangle4i(0, 0, 0, BUTTON_SIZE);
|
||||
|
||||
if (!visiblity.showSearchSection || NEIClientConfig.isSearchWidgetCentered()) {
|
||||
area.w = ItemPanels.itemPanel.w;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
} else {
|
||||
area.w = (int) Math.max(BUTTON_SIZE * 2.5f, ItemPanels.itemPanel.w * 0.3f);
|
||||
area.x = ItemPanels.itemPanel.x + ItemPanels.itemPanel.w - area.w;
|
||||
}
|
||||
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
public void layoutButton(Button button) {
|
||||
button.x = 2 + (buttonCount % numButtons) * 19;
|
||||
button.y = 2 + (buttonCount / numButtons) * 18;
|
||||
|
||||
button.h = 17;
|
||||
button.w = button.contentWidth() + 6;
|
||||
|
||||
button.x = MARGIN + (buttonCount % numButtons) * (button.w + MARGIN);
|
||||
button.y = MARGIN + (buttonCount / numButtons) * (button.h + MARGIN);
|
||||
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
@@ -181,9 +257,16 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
@Override
|
||||
public void drawSubsetTag(String text, int x, int y, int w, int h, int state, boolean mouseover) {
|
||||
if (state == 1) GL11.glColor4f(0.65F, 0.65F, 0.65F, 1.0F);
|
||||
else GL11.glColor4f(1, 1, 1, 1);
|
||||
if (state == 1) {
|
||||
GL11.glColor4f(0.65F, 0.65F, 0.65F, 1.0F);
|
||||
} else {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
LayoutManager.drawButtonBackground(x, y, w, h, false, state == 0 ? 0 : 1);
|
||||
if (text != null) drawStringC(text, x, y, w, h, state == 2 ? 0xFFE0E0E0 : 0xFFA0A0A0);
|
||||
|
||||
if (text != null) {
|
||||
drawStringC(text, x, y, w, h, mouseover ? 0xFFFFFFA0 : (state == 2 ? 0xFFE0E0E0 : 0xFFA0A0A0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -14,6 +15,7 @@ import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.storage.SaveFormatComparator;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -23,9 +25,11 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import codechicken.core.CCUpdateChecker;
|
||||
import codechicken.core.ClassDiscoverer;
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
@@ -41,14 +45,17 @@ import codechicken.nei.config.GuiHighlightTips;
|
||||
import codechicken.nei.config.GuiNEIOptionList;
|
||||
import codechicken.nei.config.GuiOptionList;
|
||||
import codechicken.nei.config.GuiPanelSettings;
|
||||
import codechicken.nei.config.OptionButton;
|
||||
import codechicken.nei.config.OptionCycled;
|
||||
import codechicken.nei.config.OptionGamemodes;
|
||||
import codechicken.nei.config.OptionIntegerField;
|
||||
import codechicken.nei.config.OptionList;
|
||||
import codechicken.nei.config.OptionOpenGui;
|
||||
import codechicken.nei.config.OptionTextField;
|
||||
import codechicken.nei.config.OptionToggleButton;
|
||||
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.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
@@ -71,10 +78,6 @@ public class NEIClientConfig {
|
||||
public static ConfigSet world;
|
||||
public static final File handlerFile = new File(configDir, "handlers.csv");
|
||||
public static final File catalystFile = new File(configDir, "catalysts.csv");
|
||||
public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg");
|
||||
public static final File heightHackHandlersFile = new File(configDir, "heighthackhandlers.cfg");
|
||||
public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv");
|
||||
public static final File hiddenHandlersFile = new File(configDir, "hiddenhandlers.csv");
|
||||
|
||||
@Deprecated
|
||||
public static File bookmarkFile;
|
||||
@@ -94,6 +97,8 @@ public class NEIClientConfig {
|
||||
// Any handler not in the map will be assigned to 0, and negative numbers are fine.
|
||||
public static HashMap<String, Integer> handlerOrdering = new HashMap<>();
|
||||
|
||||
public static final Set<Class<?>> pluginsList = new HashSet<>();
|
||||
|
||||
// Function that extracts the handler ID from a handler, with special logic for
|
||||
// TemplateRecipeHandler: prefer using the overlay ID if it exists.
|
||||
public static final Function<IRecipeHandler, String> HANDLER_ID_FUNCTION = handler -> Objects
|
||||
@@ -152,7 +157,7 @@ public class NEIClientConfig {
|
||||
return getLockedMode() == -1 || getLockedMode() == index && NEIInfo.isValidMode(index);
|
||||
}
|
||||
});
|
||||
checkCheatMode();
|
||||
canChangeCheatMode();
|
||||
|
||||
tag.getTag("inventory.utilities").setDefaultValue("delete, magnet");
|
||||
API.addOption(new OptionUtilities("inventory.utilities"));
|
||||
@@ -161,13 +166,168 @@ public class NEIClientConfig {
|
||||
API.addOption(new OptionGamemodes("inventory.gamemodes"));
|
||||
|
||||
ItemSorter.initConfig(tag);
|
||||
setInventorySearchDefaults(tag);
|
||||
|
||||
tag.getTag("inventory.bookmarks.enabled").setComment("Enable/Disable Bookmark Panel").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.enabled", true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.worldSpecific").setComment("Global or world specific bookmarks")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.worldSpecific", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
ItemPanels.bookmarkPanel.load();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.bookmarks.animation").setComment("REI Style Animation in Bookmarks")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.animation", true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.recipeTooltipsMode").setComment("Show recipe tooltips in Bookmarks")
|
||||
.getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.bookmarks.recipeTooltipsMode", 4, true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.showRecipeMarker", true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.craftingChainDir").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.bookmarks.craftingChainDir", 2, true));
|
||||
|
||||
tag.getTag("inventory.bookmarks.ignorePotionOverlap").setComment("Ignore overlap with potion effect HUD")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarks.ignorePotionOverlap", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.jeiStyleTabs").setComment("Enable/disable JEI Style Tabs")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButtonBoubs("inventory.guirecipe.jeiStyleTabs", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.jeiStyleRecipeCatalyst").setComment("Enable/disable JEI Style Recipe Catalysts")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.jeiStyleRecipeCatalyst", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.jeiStyleCycledIngredients").setComment("JEI styled cycled ingredients")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.jeiStyleCycledIngredients", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.cycledIngredientsTooltip").setComment("Show cycled ingredients tooltip")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.cycledIngredientsTooltip", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.creativeTabStyle").setComment("Creative or JEI style tabs")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.creativeTabStyle", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.itemPresenceOverlay").setComment("Item presence overlay on ?-hover")
|
||||
.getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.guirecipe.itemPresenceOverlay", 3, true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.slotHighlightPresent").setComment("Highlight Present Item")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.slotHighlightPresent", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.shiftOverlayRecipe")
|
||||
.setComment("Require holding shift to move items when overlaying recipe").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.shiftOverlayRecipe", true));
|
||||
|
||||
tag.getTag("inventory.subsets.enabled").setComment("Enable/disable Subsets Dropdown").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.subsets.enabled", true));
|
||||
|
||||
tag.getTag("inventory.subsets.widgetPosition").setComment("Subsets Widget Position").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.subsets.widgetPosition", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.profile").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.profile", true));
|
||||
|
||||
tag.getTag("inventory.history.enabled").setComment("Enable/disable History Panel").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.history.enabled", true));
|
||||
|
||||
tag.getTag("inventory.history.historyColor").setComment("Color of the history area display")
|
||||
.getHexValue(0xee555555);
|
||||
API.addOption(new OptionIntegerField("inventory.history.historyColor", 0, OptionIntegerField.UNSIGNED_INT_MAX));
|
||||
|
||||
tag.getTag("inventory.history.useRows").setComment("Rows used in historical areas").getIntValue(2);
|
||||
API.addOption(new OptionIntegerField("inventory.history.useRows", 1, 5));
|
||||
|
||||
tag.getTag("inventory.history.splittingMode").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.history.splittingMode", 2, true));
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.enabled").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.collapsibleItems.enabled", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
CollapsibleItems.saveStates();
|
||||
CollapsibleItems.load();
|
||||
LayoutManager.markItemsDirty();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.customName").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.collapsibleItems.customName", true));
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.expandedColor")
|
||||
.setComment("Color of the collapsible item expanded state").getHexValue(0x335555EE);
|
||||
API.addOption(
|
||||
new OptionIntegerField(
|
||||
"inventory.collapsibleItems.expandedColor",
|
||||
0,
|
||||
OptionIntegerField.UNSIGNED_INT_MAX));
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.collapsedColor")
|
||||
.setComment("Color of the collapsible item collapsed state").getHexValue(0x335555EE);
|
||||
API.addOption(
|
||||
new OptionIntegerField(
|
||||
"inventory.collapsibleItems.collapsedColor",
|
||||
0,
|
||||
OptionIntegerField.UNSIGNED_INT_MAX));
|
||||
|
||||
API.addOption(
|
||||
new OptionButton(
|
||||
"inventory.collapsibleItems.reloadLabel",
|
||||
"inventory.collapsibleItems.reloadButton",
|
||||
"inventory.collapsibleItems.reloadTip") {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
LayoutManager.markItemsDirty();
|
||||
return super.onClick(button);
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.itemzoom.enabled").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.itemzoom.enabled", true));
|
||||
|
||||
tag.getTag("inventory.itemzoom.neiOnly")
|
||||
.setComment("Zoom items only from the JEI ingredient and bookmark list overlays.")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.itemzoom.neiOnly", true));
|
||||
|
||||
tag.getTag("inventory.itemzoom.onlySolid").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.itemzoom.onlySolid", true));
|
||||
|
||||
tag.getTag("inventory.itemzoom.helpText")
|
||||
.setComment("Display name \"Item Zoom\" and the hotkey to toggle this mod below the zoomed item.")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.itemzoom.helpText", true));
|
||||
|
||||
tag.getTag("inventory.itemzoom.zoom").getIntValue(500);
|
||||
API.addOption(new OptionIntegerField("inventory.itemzoom.zoom", ItemZoom.MIN_ZOOM, ItemZoom.MAX_ZOOM));
|
||||
|
||||
tag.getTag("inventory.itemzoom.showName").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.itemzoom.showName", true));
|
||||
|
||||
tag.getTag("inventory.itemzoom.nameColor").getHexValue(0xFFFFFFFF);
|
||||
API.addOption(new OptionIntegerField("inventory.itemzoom.nameColor", 0, OptionIntegerField.UNSIGNED_INT_MAX));
|
||||
|
||||
tag.getTag("inventory.itemIDs").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.itemIDs", 3, true));
|
||||
|
||||
tag.getTag("inventory.searchmode").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.searchmode", 3, true));
|
||||
|
||||
tag.getTag("world.highlight_tips").getBooleanValue(false);
|
||||
tag.getTag("world.highlight_tips.x").getIntValue(5000);
|
||||
tag.getTag("world.highlight_tips.y").getIntValue(100);
|
||||
@@ -185,8 +345,7 @@ public class NEIClientConfig {
|
||||
|
||||
API.addOption(new OptionOpenGui("world.panels", GuiPanelSettings.class));
|
||||
|
||||
tag.getTag("inventory.profileRecipes").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.profileRecipes", true));
|
||||
API.addOption(new OptionOpenGui("world.presets", GuiPresetList.class));
|
||||
|
||||
tag.getTag("inventory.disableMouseScrollTransfer").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.disableMouseScrollTransfer", true));
|
||||
@@ -200,8 +359,10 @@ public class NEIClientConfig {
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.cacheItemRendering").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.cacheItemRendering", true));
|
||||
tag.getTag("inventory.gridRenderingCacheFPS").getIntValue(8);
|
||||
|
||||
tag.getTag("inventory.gridRenderingCacheMode").getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.gridRenderingCacheMode", 3, true));
|
||||
|
||||
tag.getTag("itemLoadingTimeout").getIntValue(500);
|
||||
|
||||
@@ -216,79 +377,13 @@ public class NEIClientConfig {
|
||||
tag.getTag("command.heal").setDefaultValue("");
|
||||
API.addOption(new OptionTextField("command.heal"));
|
||||
|
||||
tag.getTag("inventory.worldSpecificBookmarks").setComment("Global or world specific bookmarks")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.worldSpecificBookmarks", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
initBookmarkFile(worldPath);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.worldSpecificPresets").setComment("Global or world specific presets")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.worldSpecificPresets", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
initPresetsFile(worldPath);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.bookmarksEnabled").setComment("Enable/disable bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarksEnabled", true));
|
||||
|
||||
tag.getTag("inventory.bookmarksAnimationEnabled").setComment("REI Style Animation in Bookmarks")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarksAnimationEnabled", true));
|
||||
|
||||
tag.getTag("inventory.recipeTooltipsMode").setComment("Show recipe tooltips in Bookmarks").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.recipeTooltipsMode", 4, true));
|
||||
|
||||
tag.getTag("inventory.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.showRecipeMarker", true));
|
||||
|
||||
tag.getTag("inventory.showItemQuantityWidget").setComment("Show Item Quantity Widget").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.showItemQuantityWidget", true));
|
||||
|
||||
tag.getTag("inventory.centerSearchWidget").setComment("Center Search Widget").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.centerSearchWidget", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_tabs").setComment("Enable/disable JEI Style Tabs").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_item_presence_overlay")
|
||||
.setComment("Enable/disable JEI Style item presence overlay on ?-hover").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_item_presence_overlay", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true));
|
||||
|
||||
tag.getTag("inventory.creative_tab_style").setComment("Creative or JEI style tabs").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.creative_tab_style", true));
|
||||
|
||||
tag.getTag("inventory.ignore_potion_overlap").setComment("Ignore overlap with potion effect HUD")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.ignore_potion_overlap", true));
|
||||
|
||||
tag.getTag("inventory.optimize_gui_overlap_computation").setComment("Optimize computation for GUI overlap")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.optimize_gui_overlap_computation", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_cycled_ingredients").setComment("JEI styled cycled ingredients")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_cycled_ingredients", true));
|
||||
|
||||
tag.getTag("inventory.shift_overlay_recipe")
|
||||
.setComment("Require holding shift to move items when overlaying recipe").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.shift_overlay_recipe", true));
|
||||
|
||||
tag.getTag("tools.handler_load_from_config").setComment("ADVANCED: Load handlers from config")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("tools.handler_load_from_config", true) {
|
||||
@@ -341,6 +436,237 @@ public class NEIClientConfig {
|
||||
});
|
||||
}
|
||||
|
||||
private static void setInventorySearchDefaults(ConfigTagParent tag) {
|
||||
|
||||
tag.getTag("inventory.search.widgetPosition").setComment("Widget Position").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.search.widgetPosition", true));
|
||||
|
||||
tag.getTag("inventory.search.hideUntilSearching").setComment("Hide Items Until Searching")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.search.hideUntilSearching", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
super.onClick(button);
|
||||
ItemList.updateFilter.restart();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.widgetAutofocus")
|
||||
.setComment(
|
||||
"Focus Search Widget on Open, blurs/unfocuses on mouse move unless typing has started first")
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.widgetAutofocus", 3, true));
|
||||
|
||||
tag.getTag("inventory.search.patternMode").setComment("Search Mode").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.search.patternMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.quoteDropItemName").setComment("Quote Drop Item Name").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.search.quoteDropItemName", true));
|
||||
|
||||
tag.getTag("inventory.search.format").setComment("Search Format (true: old format, false: custom format)")
|
||||
.getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.search.format", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
|
||||
if (!super.onClick(button)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state()) {
|
||||
NEIClientConfig.setIntSetting("inventory.search.spaceMode", 1);
|
||||
NEIClientConfig.setIntSetting("inventory.search.modNameSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.tooltipSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.identifierSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.oreDictSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.subsetsSearchMode", 1);
|
||||
tag.getTag("inventory.search.prefixRedefinitions").setValue("{\"%\": \"@\", \"@\": \"%\"}");
|
||||
SearchField.searchParser.prefixRedefinitions.clear();
|
||||
SearchField.searchParser.prefixRedefinitions.put('%', '@');
|
||||
SearchField.searchParser.prefixRedefinitions.put('@', '%');
|
||||
SearchField.searchParser.clearCache();
|
||||
} else {
|
||||
NEIClientConfig.setIntSetting("inventory.search.spaceMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.modNameSearchMode", 1);
|
||||
NEIClientConfig.setIntSetting("inventory.search.tooltipSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.identifierSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.oreDictSearchMode", 0);
|
||||
NEIClientConfig.setIntSetting("inventory.search.subsetsSearchMode", 1);
|
||||
tag.getTag("inventory.search.prefixRedefinitions").setValue("{}");
|
||||
SearchField.searchParser.prefixRedefinitions.clear();
|
||||
SearchField.searchParser.clearCache();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.spaceMode").setComment("Search Space Rules").getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.spaceMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
// SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.modNameSearchMode").setComment("Search mode for Mod Names (prefix: @)")
|
||||
.getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.search.modNameSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(
|
||||
name + "." + value(),
|
||||
EnumChatFormatting.LIGHT_PURPLE
|
||||
+ String.valueOf(SearchField.searchParser.getRedefinedPrefix('@')));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.tooltipSearchMode").setComment("Search mode for Tooltips (prefix: #)")
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.tooltipSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(
|
||||
name + "." + value(),
|
||||
EnumChatFormatting.YELLOW + String.valueOf(SearchField.searchParser.getRedefinedPrefix('#')));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.identifierSearchMode").setComment("Search mode for identifier (prefix: &)")
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.identifierSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(
|
||||
name + "." + value(),
|
||||
EnumChatFormatting.GOLD + String.valueOf(SearchField.searchParser.getRedefinedPrefix('&')));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.oreDictSearchMode").setComment("Search mode for Tag Names (prefix: $)")
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.oreDictSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(
|
||||
name + "." + value(),
|
||||
EnumChatFormatting.AQUA + String.valueOf(SearchField.searchParser.getRedefinedPrefix('$')));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.subsetsSearchMode").setComment("Search mode for Item Subsets (prefix: %)")
|
||||
.getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.search.subsetsSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
SearchField.searchParser.clearCache();
|
||||
return super.onClick(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(
|
||||
name + "." + value(),
|
||||
EnumChatFormatting.DARK_PURPLE
|
||||
+ String.valueOf(SearchField.searchParser.getRedefinedPrefix('%')));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return !tag.getTag("inventory.search.format").getBooleanValue();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
String prefixRedefinitions = tag.getTag("inventory.search.prefixRedefinitions").setComment(
|
||||
"Redefine search prefixes by providing a char-to-char map (JSON). The keys are the original prefixes, the values the new ones. Example: { \"$\": \"€\", \"#\": \"+\", \"@\": \"°\", \"%\": \"!\" }")
|
||||
.getValue("{}");
|
||||
try {
|
||||
TypeToken<Map<Character, Character>> typeToken = new TypeToken<Map<Character, Character>>() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
};
|
||||
Map<Character, Character> charMap = new Gson().fromJson(prefixRedefinitions, typeToken.getType());
|
||||
SearchField.searchParser.prefixRedefinitions.putAll(charMap);
|
||||
} catch (JsonParseException e) {
|
||||
logger.warn("Failed to convert prefix redefinitions from JSON to CharToCharMap:", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void setDefaultKeyBindings() {
|
||||
API.addHashBind("gui.recipe", Keyboard.KEY_R);
|
||||
API.addHashBind("gui.usage", Keyboard.KEY_U);
|
||||
@@ -357,6 +683,7 @@ public class NEIClientConfig {
|
||||
API.addHashBind("gui.search", Keyboard.KEY_F);
|
||||
API.addHashBind("gui.bookmark", Keyboard.KEY_A);
|
||||
API.addHashBind("gui.bookmark_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.remove_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.bookmark_count", Keyboard.KEY_A + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind(
|
||||
"gui.bookmark_recipe_count",
|
||||
@@ -371,6 +698,11 @@ public class NEIClientConfig {
|
||||
API.addKeyBind("gui.getnextsearch", Keyboard.KEY_DOWN);
|
||||
API.addHashBind("gui.next_tooltip", Keyboard.KEY_Z);
|
||||
|
||||
API.addHashBind("gui.itemzoom_toggle", Keyboard.KEY_Z + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.itemzoom_hold", 0);
|
||||
API.addHashBind("gui.itemzoom_zoom_in", 0);
|
||||
API.addHashBind("gui.itemzoom_zoom_out", 0);
|
||||
|
||||
API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9);
|
||||
API.addKeyBind("world.moboverlay", Keyboard.KEY_F7);
|
||||
API.addKeyBind("world.highlight_tips", Keyboard.KEY_NUMPAD0);
|
||||
@@ -381,6 +713,8 @@ public class NEIClientConfig {
|
||||
API.addKeyBind("world.rain", 0);
|
||||
API.addKeyBind("world.heal", 0);
|
||||
API.addKeyBind("world.creative", 0);
|
||||
API.addHashBind("gui.copy_name", Keyboard.KEY_C + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind("gui.copy_oredict", Keyboard.KEY_D + NEIClientUtils.CTRL_HASH);
|
||||
}
|
||||
|
||||
public static OptionList getOptionList() {
|
||||
@@ -388,23 +722,29 @@ public class NEIClientConfig {
|
||||
}
|
||||
|
||||
public static void loadWorld(String worldPath) {
|
||||
NEIClientConfig.worldPath = worldPath;
|
||||
|
||||
unloadWorld();
|
||||
setInternalEnabled(true);
|
||||
logger.debug("Loading " + (Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote") + " World");
|
||||
bootNEI(ClientUtils.getWorld());
|
||||
|
||||
final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
final boolean newWorld = !specificDir.exists();
|
||||
if (!worldPath.equals(NEIClientConfig.worldPath)) {
|
||||
NEIClientConfig.worldPath = worldPath;
|
||||
|
||||
if (newWorld) {
|
||||
specificDir.mkdirs();
|
||||
logger.debug("Loading " + (Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote") + " World");
|
||||
|
||||
final File specificDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
final boolean newWorld = !specificDir.exists();
|
||||
|
||||
if (newWorld) {
|
||||
specificDir.mkdirs();
|
||||
}
|
||||
|
||||
world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg")));
|
||||
bootNEI(ClientUtils.getWorld());
|
||||
onWorldLoad(newWorld);
|
||||
}
|
||||
}
|
||||
|
||||
initBookmarkFile(worldPath);
|
||||
initPresetsFile(worldPath);
|
||||
world = new ConfigSet(new File(specificDir, "NEI.dat"), new ConfigFile(new File(specificDir, "NEI.cfg")));
|
||||
onWorldLoad(newWorld);
|
||||
public static String getWorldPath() {
|
||||
return NEIClientConfig.worldPath;
|
||||
}
|
||||
|
||||
private static void onWorldLoad(boolean newWorld) {
|
||||
@@ -414,11 +754,12 @@ public class NEIClientConfig {
|
||||
setWorldDefaults();
|
||||
creativeInv = new ItemStack[54];
|
||||
LayoutManager.searchField.setText(getSearchExpression());
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(getItemQuantity()));
|
||||
SubsetWidget.loadHidden();
|
||||
LayoutManager.quantity.setText(Integer.toString(getItemQuantity()));
|
||||
|
||||
if (newWorld && Minecraft.getMinecraft().isSingleplayer()) world.config.getTag("inventory.cheatmode")
|
||||
.setIntValue(NEIClientUtils.mc().playerController.isInCreativeMode() ? 2 : 0);
|
||||
if (newWorld && Minecraft.getMinecraft().isSingleplayer()) {
|
||||
world.config.getTag("inventory.cheatmode")
|
||||
.setIntValue(NEIClientUtils.mc().playerController.isInCreativeMode() ? 2 : 0);
|
||||
}
|
||||
|
||||
NEIInfo.load(ClientUtils.getWorld());
|
||||
}
|
||||
@@ -437,6 +778,9 @@ public class NEIClientConfig {
|
||||
ItemPanels.bookmarkPanel.saveBookmarks();
|
||||
}
|
||||
|
||||
SubsetWidget.saveHidden();
|
||||
CollapsibleItems.saveStates();
|
||||
|
||||
if (world != null) {
|
||||
world.saveNBT();
|
||||
}
|
||||
@@ -458,101 +802,66 @@ public class NEIClientConfig {
|
||||
return hash != Keyboard.CHAR_NONE && hash == NEIClientUtils.getKeyHash();
|
||||
}
|
||||
|
||||
public static String getKeyName(int keyBind, boolean useHash) {
|
||||
return getKeyName(keyBind, useHash, false);
|
||||
}
|
||||
public static String getKeyName(String keyBind) {
|
||||
final int hash = getKeyBinding(keyBind);
|
||||
|
||||
public static String getKeyName(int keyBind, boolean useHash, boolean showOnlyHash) {
|
||||
String keyText = "";
|
||||
|
||||
if (useHash) {
|
||||
final String DELIMITER = " + ";
|
||||
if ((keyBind & NEIClientUtils.CTRL_HASH) != 0) {
|
||||
keyText += NEIClientUtils.translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl") + DELIMITER;
|
||||
}
|
||||
if ((keyBind & NEIClientUtils.SHIFT_HASH) != 0) {
|
||||
keyText += "SHIFT" + DELIMITER;
|
||||
}
|
||||
if ((keyBind & NEIClientUtils.ALT_HASH) != 0) {
|
||||
keyText += "ALT" + DELIMITER;
|
||||
}
|
||||
if (hash == Keyboard.CHAR_NONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!showOnlyHash) {
|
||||
keyText += Keyboard.getKeyName(unHashKey(keyBind));
|
||||
}
|
||||
return keyText;
|
||||
}
|
||||
|
||||
public static int unHashKey(int keyBind) {
|
||||
return keyBind & ~(NEIClientUtils.CTRL_HASH | NEIClientUtils.SHIFT_HASH | NEIClientUtils.ALT_HASH);
|
||||
return NEIClientUtils.getKeyName(hash);
|
||||
}
|
||||
|
||||
public static void bootNEI(World world) {
|
||||
if (mainNEIConfigLoaded) return;
|
||||
if (!mainNEIConfigLoaded) {
|
||||
// main NEI config loading
|
||||
ItemInfo.load(world);
|
||||
GuiInfo.load();
|
||||
RecipeInfo.load();
|
||||
HeldItemHandler.load();
|
||||
LayoutManager.load();
|
||||
NEIController.load();
|
||||
BookmarkContainerInfo.load();
|
||||
mainNEIConfigLoaded = true;
|
||||
|
||||
// main NEI config loading
|
||||
ItemInfo.load(world);
|
||||
GuiInfo.load();
|
||||
RecipeInfo.load();
|
||||
LayoutManager.load();
|
||||
NEIController.load();
|
||||
BookmarkContainerInfo.load();
|
||||
mainNEIConfigLoaded = true;
|
||||
new Thread("NEI Plugin Loader") {
|
||||
|
||||
new Thread("NEI Plugin Loader") {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.debug("Started NEI plugin loading");
|
||||
ClassDiscoverer classDiscoverer = new ClassDiscoverer(
|
||||
test -> test.startsWith("NEI") && test.endsWith("Config.class"),
|
||||
IConfigureNEI.class);
|
||||
NEIClientConfig.pluginsList.parallelStream().forEach(clazz -> {
|
||||
try {
|
||||
IConfigureNEI config = (IConfigureNEI) clazz.getConstructor().newInstance();
|
||||
config.loadConfig();
|
||||
NEIModContainer.plugins.add(config);
|
||||
logger.debug("Loaded {}", clazz.getName());
|
||||
} catch (Throwable e) {
|
||||
logger.error("Failed to Load {}", clazz.getName(), e);
|
||||
}
|
||||
});
|
||||
|
||||
classDiscoverer.findClasses();
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
ItemPanels.bookmarkPanel.load();
|
||||
SubsetWidget.loadHidden();
|
||||
CollapsibleItems.load();
|
||||
ItemSorter.loadConfig();
|
||||
|
||||
for (Class<?> clazz : classDiscoverer.classes) {
|
||||
try {
|
||||
IConfigureNEI config = (IConfigureNEI) clazz.newInstance();
|
||||
config.loadConfig();
|
||||
NEIModContainer.plugins.add(config);
|
||||
logger.debug("Loaded " + clazz.getName());
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to Load " + clazz.getName(), e);
|
||||
}
|
||||
// Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the
|
||||
// other way around, but apparently if your modpack includes 800 mods the event poster might not
|
||||
// return in time and cause issues when loading a world for a second time as configLoaded is still
|
||||
// false. This may cause issues in case one of the event handler calls the (non-thread-safe) NEI
|
||||
// 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());
|
||||
|
||||
ItemList.loadItems.restart();
|
||||
}
|
||||
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
|
||||
// Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the other
|
||||
// way around, but apparently if your modpack includes 800 mods the event poster might not return in
|
||||
// time and cause issues when loading a world for a second time as configLoaded is still false. This may
|
||||
// cause issues in case one of the event handler calls the (non-thread-safe) NEI API. I don't expect any
|
||||
// handler to do this, but who knows what modders have come up with...
|
||||
pluginNEIConfigLoaded = true;
|
||||
logger.debug("NEI plugin loading finished");
|
||||
MinecraftForge.EVENT_BUS.post(new NEIConfigsLoadedEvent());
|
||||
}
|
||||
}.start();
|
||||
ItemSorter.loadConfig();
|
||||
}
|
||||
|
||||
private static void initBookmarkFile(String worldPath) {
|
||||
|
||||
if (!global.config.getTag("inventory.worldSpecificBookmarks").getBooleanValue()) {
|
||||
worldPath = "global";
|
||||
}.start();
|
||||
} else {
|
||||
ItemPanels.bookmarkPanel.load();
|
||||
SubsetWidget.loadHidden();
|
||||
ItemList.loadItems.restart();
|
||||
}
|
||||
|
||||
ItemPanels.bookmarkPanel.setBookmarkFile(worldPath);
|
||||
}
|
||||
|
||||
private static void initPresetsFile(String worldPath) {
|
||||
|
||||
if (!global.config.getTag("inventory.worldSpecificPresets").getBooleanValue()) {
|
||||
worldPath = "global";
|
||||
}
|
||||
|
||||
PresetsWidget.loadPresets(worldPath);
|
||||
}
|
||||
|
||||
public static boolean isWorldSpecific(String setting) {
|
||||
@@ -574,47 +883,71 @@ public class NEIClientConfig {
|
||||
}
|
||||
|
||||
public static boolean isBookmarkPanelHidden() {
|
||||
return !getBooleanSetting("inventory.bookmarksEnabled");
|
||||
return !getBooleanSetting("inventory.bookmarks.enabled");
|
||||
}
|
||||
|
||||
public static boolean areBookmarksAnimated() {
|
||||
return getBooleanSetting("inventory.bookmarksAnimationEnabled");
|
||||
return getBooleanSetting("inventory.bookmarks.animation");
|
||||
}
|
||||
|
||||
public static int getRecipeTooltipsMode() {
|
||||
return getIntSetting("inventory.recipeTooltipsMode");
|
||||
return getIntSetting("inventory.bookmarks.recipeTooltipsMode");
|
||||
}
|
||||
|
||||
public static boolean showRecipeMarker() {
|
||||
return getBooleanSetting("inventory.showRecipeMarker");
|
||||
return getBooleanSetting("inventory.bookmarks.showRecipeMarker");
|
||||
}
|
||||
|
||||
public static boolean showItemQuantityWidget() {
|
||||
return getBooleanSetting("inventory.showItemQuantityWidget");
|
||||
}
|
||||
|
||||
public static boolean hideItemsUntilSearching() {
|
||||
return getBooleanSetting("inventory.search.hideUntilSearching");
|
||||
}
|
||||
|
||||
public static boolean isSearchWidgetCentered() {
|
||||
return getBooleanSetting("inventory.centerSearchWidget");
|
||||
return getBooleanSetting("inventory.search.widgetPosition");
|
||||
}
|
||||
|
||||
public static boolean showSubsetWidget() {
|
||||
return getBooleanSetting("inventory.subsets.enabled");
|
||||
}
|
||||
|
||||
public static boolean subsetWidgetOnTop() {
|
||||
return getBooleanSetting("inventory.subsets.widgetPosition");
|
||||
}
|
||||
|
||||
public static int searchWidgetAutofocus() {
|
||||
return getIntSetting("inventory.search.widgetAutofocus");
|
||||
}
|
||||
|
||||
public static boolean areJEIStyleTabsVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_tabs");
|
||||
return getBooleanSetting("inventory.guirecipe.jeiStyleTabs");
|
||||
}
|
||||
|
||||
public static boolean isJEIStyleItemPresenceOverlayVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_item_presence_overlay");
|
||||
public static int itemPresenceOverlay() {
|
||||
return getIntSetting("inventory.guirecipe.itemPresenceOverlay");
|
||||
}
|
||||
|
||||
public static boolean isSlotHighlightPresent() {
|
||||
return getBooleanSetting("inventory.guirecipe.slotHighlightPresent");
|
||||
}
|
||||
|
||||
public static boolean areJEIStyleRecipeCatalystsVisible() {
|
||||
return getBooleanSetting("inventory.jei_style_recipe_catalyst");
|
||||
return getBooleanSetting("inventory.guirecipe.jeiStyleRecipeCatalyst");
|
||||
}
|
||||
|
||||
public static boolean useCreativeTabStyle() {
|
||||
return getBooleanSetting("inventory.creative_tab_style");
|
||||
return getBooleanSetting("inventory.guirecipe.creativeTabStyle");
|
||||
}
|
||||
|
||||
public static boolean ignorePotionOverlap() {
|
||||
return getBooleanSetting("inventory.ignore_potion_overlap");
|
||||
return getBooleanSetting("inventory.bookmarks.ignorePotionOverlap");
|
||||
}
|
||||
|
||||
public static int craftingChainDir() {
|
||||
return getIntSetting("inventory.bookmarks.craftingChainDir");
|
||||
}
|
||||
|
||||
public static boolean optimizeGuiOverlapComputation() {
|
||||
@@ -622,11 +955,15 @@ public class NEIClientConfig {
|
||||
}
|
||||
|
||||
public static boolean useJEIStyledCycledIngredients() {
|
||||
return getBooleanSetting("inventory.jei_style_cycled_ingredients");
|
||||
return getBooleanSetting("inventory.guirecipe.jeiStyleCycledIngredients");
|
||||
}
|
||||
|
||||
public static boolean showCycledIngredientsTooltip() {
|
||||
return getBooleanSetting("inventory.guirecipe.cycledIngredientsTooltip");
|
||||
}
|
||||
|
||||
public static boolean requireShiftForOverlayRecipe() {
|
||||
return getBooleanSetting("inventory.shift_overlay_recipe");
|
||||
return getBooleanSetting("inventory.guirecipe.shiftOverlayRecipe");
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
@@ -645,6 +982,10 @@ public class NEIClientConfig {
|
||||
return !getBooleanSetting("tools.catalyst_load_from_config");
|
||||
}
|
||||
|
||||
public static boolean isProfileRecipeEnabled() {
|
||||
return NEIClientConfig.getBooleanSetting("inventory.guirecipe.profile");
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean flag) {
|
||||
getSetting("inventory.widgetsenabled").setBooleanValue(flag);
|
||||
}
|
||||
@@ -657,8 +998,13 @@ public class NEIClientConfig {
|
||||
return getIntSetting("inventory.cheatmode");
|
||||
}
|
||||
|
||||
private static void checkCheatMode() {
|
||||
if (getLockedMode() != -1) setIntSetting("inventory.cheatmode", getLockedMode());
|
||||
public static boolean canChangeCheatMode() {
|
||||
if (getLockedMode() != -1) {
|
||||
setIntSetting("inventory.cheatmode", getLockedMode());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int getLockedMode() {
|
||||
@@ -716,8 +1062,16 @@ public class NEIClientConfig {
|
||||
return !getBooleanSetting("inventory.invertMouseScrollTransfer");
|
||||
}
|
||||
|
||||
public static boolean shouldCacheItemRendering() {
|
||||
return getBooleanSetting("inventory.cacheItemRendering") && OpenGlHelper.framebufferSupported;
|
||||
public static boolean showHistoryPanelWidget() {
|
||||
return getBooleanSetting("inventory.history.enabled");
|
||||
}
|
||||
|
||||
public static int getGridRenderingCacheMode() {
|
||||
return OpenGlHelper.framebufferSupported ? getIntSetting("inventory.gridRenderingCacheMode") : 0;
|
||||
}
|
||||
|
||||
public static boolean enableCollapsibleItems() {
|
||||
return getBooleanSetting("inventory.collapsibleItems.enabled");
|
||||
}
|
||||
|
||||
public static boolean getMagnetMode() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -36,8 +37,6 @@ import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@@ -58,11 +57,26 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
/** Formats a number with group separator and at most 2 fraction digits. */
|
||||
private static final Map<Locale, DecimalFormat> decimalFormatters = new HashMap<>();
|
||||
private static final Map<Integer, Integer> keyHashMap = new HashMap<>();
|
||||
|
||||
public static final int ALT_HASH = 1 << 27;
|
||||
public static final int SHIFT_HASH = 1 << 26;
|
||||
public static final int CTRL_HASH = 1 << 25;
|
||||
|
||||
static {
|
||||
keyHashMap.put(Keyboard.KEY_LSHIFT, SHIFT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RSHIFT, SHIFT_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMETA, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RMETA, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
}
|
||||
|
||||
public static Minecraft mc() {
|
||||
return Minecraft.getMinecraft();
|
||||
}
|
||||
@@ -308,7 +322,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static void sendCommand(String command, Object... args) {
|
||||
if (command.length() == 0) return;
|
||||
if (command.isEmpty()) return;
|
||||
|
||||
NumberFormat numberformat = NumberFormat.getIntegerInstance();
|
||||
numberformat.setGroupingUsed(false);
|
||||
@@ -367,18 +381,23 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static String cropText(FontRenderer fontRenderer, String text, int containerWidth) {
|
||||
|
||||
int textWidth = fontRenderer.getStringWidth(text);
|
||||
|
||||
if (textWidth > containerWidth) {
|
||||
textWidth += fontRenderer.getStringWidth("...");
|
||||
int dots = fontRenderer.getStringWidth("...");
|
||||
|
||||
while (textWidth > containerWidth) {
|
||||
textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1));
|
||||
text = text.substring(0, text.length() - 1);
|
||||
if (containerWidth > dots) {
|
||||
textWidth += dots;
|
||||
|
||||
while (textWidth > containerWidth) {
|
||||
textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1));
|
||||
text = text.substring(0, text.length() - 1);
|
||||
}
|
||||
|
||||
return text + "...";
|
||||
}
|
||||
|
||||
return text + "...";
|
||||
return "...";
|
||||
}
|
||||
|
||||
return text;
|
||||
@@ -433,11 +452,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
if (Keyboard.getEventKeyState()) {
|
||||
final int keycode = Keyboard.getEventKey();
|
||||
|
||||
if (keycode != Keyboard.KEY_LSHIFT && keycode != Keyboard.KEY_RSHIFT
|
||||
&& keycode != Keyboard.KEY_LCONTROL
|
||||
&& keycode != Keyboard.KEY_RCONTROL
|
||||
&& keycode != Keyboard.KEY_LMENU
|
||||
&& keycode != Keyboard.KEY_RMENU) {
|
||||
if (!keyHashMap.containsKey(keycode)) {
|
||||
return getMetaHash() + keycode;
|
||||
}
|
||||
}
|
||||
@@ -445,6 +460,45 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
return Keyboard.CHAR_NONE;
|
||||
}
|
||||
|
||||
public static String getKeyHashName(int keyBind) {
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
|
||||
if ((keyBind & CTRL_HASH) != 0) {
|
||||
keyText.add(translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl"));
|
||||
}
|
||||
|
||||
if ((keyBind & SHIFT_HASH) != 0) {
|
||||
keyText.add(translate("key.shift"));
|
||||
}
|
||||
|
||||
if ((keyBind & ALT_HASH) != 0) {
|
||||
keyText.add(translate("key.alt"));
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
}
|
||||
|
||||
public static String getKeyName(int keyBind) {
|
||||
keyBind = keyHashMap.getOrDefault(keyBind, keyBind);
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
String hashText = getKeyHashName(keyBind);
|
||||
int keyID = unHashKey(keyBind);
|
||||
|
||||
if (!hashText.isEmpty()) {
|
||||
keyText.add(hashText);
|
||||
}
|
||||
|
||||
if (keyID != Keyboard.CHAR_NONE || hashText.isEmpty()) {
|
||||
keyText.add(Keyboard.getKeyName(keyID));
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
}
|
||||
|
||||
public static int unHashKey(int keyBind) {
|
||||
return keyBind & ~(CTRL_HASH | SHIFT_HASH | ALT_HASH);
|
||||
}
|
||||
|
||||
public static void playClickSound() {
|
||||
mc().getSoundHandler()
|
||||
.playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
@@ -456,16 +510,9 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
String stackTrace = cause + sw;
|
||||
if (buffer.contains(stackTrace)) return;
|
||||
|
||||
System.err.println("Error while rendering: " + cause);
|
||||
System.err.println("Error while rendering: " + cause + " (" + e.getMessage() + ")");
|
||||
e.printStackTrace();
|
||||
buffer.add(stackTrace);
|
||||
|
||||
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
if (player != null) {
|
||||
IChatComponent chat = new ChatComponentTranslation("nei.chat.render.error");
|
||||
chat.getChatStyle().setColor(EnumChatFormatting.RED);
|
||||
player.addChatComponentMessage(chat);
|
||||
}
|
||||
}
|
||||
|
||||
public static void reportErrorBuffered(Throwable e, Set<String> buffer, ItemStack cause) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -38,6 +39,7 @@ public class NEIModContainer extends DummyModContainer {
|
||||
public static LinkedList<IConfigureNEI> plugins = new LinkedList<>();
|
||||
|
||||
private static boolean gregTech5Loaded;
|
||||
private static boolean gtnhLibLoaded;
|
||||
|
||||
public NEIModContainer() {
|
||||
super(getModMetadata());
|
||||
@@ -59,16 +61,23 @@ public class NEIModContainer extends DummyModContainer {
|
||||
return gregTech5Loaded;
|
||||
}
|
||||
|
||||
public static boolean isGTNHLibLoaded() {
|
||||
return gtnhLibLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements() {
|
||||
Set<ArtifactVersion> deps = new HashSet<>();
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + CodeChickenCorePlugin.version + ",)"));
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + codechicken.core.asm.Tags.VERSION + ",)"));
|
||||
return deps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependencies() {
|
||||
return new LinkedList<>(getRequirements());
|
||||
List<ArtifactVersion> deps = new ArrayList<>();
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + codechicken.core.asm.Tags.VERSION + ",)"));
|
||||
deps.add(VersionParser.parseVersionReference("gtnhlib@[0.6.0,)"));
|
||||
return deps;
|
||||
}
|
||||
|
||||
private String description;
|
||||
@@ -106,6 +115,7 @@ public class NEIModContainer extends DummyModContainer {
|
||||
@Subscribe
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
gregTech5Loaded = Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi_post");
|
||||
gtnhLibLoaded = Loader.isModLoaded("gtnhlib");
|
||||
if (CommonUtils.isClient()) ClientHandler.preInit();
|
||||
}
|
||||
|
||||
@@ -127,6 +137,8 @@ public class NEIModContainer extends DummyModContainer {
|
||||
public void loadComplete(FMLLoadCompleteEvent event) {
|
||||
if (CommonUtils.isClient()) {
|
||||
GuiRecipeTab.loadHandlerInfo();
|
||||
ClientHandler.loadPluginsList();
|
||||
ClientHandler.loadHandlerOrdering();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ public class NEIServerConfig {
|
||||
FileReader r = new FileReader(file);
|
||||
int line = 0;
|
||||
for (String s : IOUtils.readLines(r)) {
|
||||
if (s.charAt(0) == '#' || s.trim().length() == 0) continue;
|
||||
if (s.charAt(0) == '#' || s.trim().isEmpty()) continue;
|
||||
int delim = s.lastIndexOf('=');
|
||||
if (delim < 0) {
|
||||
logger.error("line " + line + ": Missing =");
|
||||
|
||||
@@ -89,9 +89,8 @@ public class NEIServerUtils {
|
||||
else return player.inventory.getStackInSlot(slot);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void deleteAllItems(EntityPlayerMP player) {
|
||||
for (Slot slot : (List<Slot>) player.openContainer.inventorySlots) slot.putStack(null);
|
||||
for (Slot slot : player.openContainer.inventorySlots) slot.putStack(null);
|
||||
|
||||
player.sendContainerAndContentsToPlayer(player.openContainer, player.openContainer.getInventory());
|
||||
}
|
||||
|
||||
@@ -11,11 +11,12 @@ import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
|
||||
public abstract class PanelWidget extends Widget {
|
||||
public abstract class PanelWidget extends Widget implements IContainerTooltipHandler {
|
||||
|
||||
protected static final int PADDING = 2;
|
||||
|
||||
@@ -42,11 +43,14 @@ public abstract class PanelWidget extends Widget {
|
||||
pagePrev = new Button("Prev") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(0);
|
||||
} else {
|
||||
grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,11 +61,14 @@ public abstract class PanelWidget extends Widget {
|
||||
pageNext = new Button("Next") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(grid.getNumPages() - 1);
|
||||
} else {
|
||||
grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,7 +171,7 @@ public abstract class PanelWidget extends Widget {
|
||||
protected abstract int resizeFooter(GuiContainer gui);
|
||||
|
||||
public void setVisible() {
|
||||
if (grid.getPerPage() > 0) {
|
||||
if (grid.getPerPage() > 0 && !grid.isEmpty()) {
|
||||
LayoutManager.addWidget(pagePrev);
|
||||
LayoutManager.addWidget(pageNext);
|
||||
LayoutManager.addWidget(pageLabel);
|
||||
@@ -191,13 +198,12 @@ public abstract class PanelWidget extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDrawTooltips(int mx, int my, List<String> tooltip) {
|
||||
grid.postDrawTooltips(mx, my, tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
||||
if (mouseDownSlot >= grid.realItems.size()) {
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
if (mouseDownSlot >= 0 && draggedStack == null
|
||||
&& NEIClientUtils.getHeldItem() == null
|
||||
&& NEIClientConfig.hasSMPCounterPart()) {
|
||||
@@ -214,28 +220,8 @@ public abstract class PanelWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
|
||||
if (handleClickExt(mousex, mousey, button)) return true;
|
||||
|
||||
if (NEIClientUtils.getHeldItem() != null) {
|
||||
|
||||
if (!grid.contains(mousex, mousey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
if (button == 1) {
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
} else {
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
}
|
||||
} else {
|
||||
NEIClientUtils.dropHeldItem();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
|
||||
@@ -330,7 +316,8 @@ public abstract class PanelWidget extends Widget {
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item.copy();
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) {
|
||||
if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey()
|
||||
|| !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
if (button == 0) {
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
@@ -394,4 +381,21 @@ public abstract class PanelWidget extends Widget {
|
||||
public boolean contains(int px, int py) {
|
||||
return grid.contains(px, py);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
|
||||
/**
|
||||
* Simply an {@link ItemStack} with position. Mainly used in the recipe handlers.
|
||||
*/
|
||||
@@ -40,7 +47,7 @@ public class PositionedStack {
|
||||
public void generatePermutations() {
|
||||
if (permutated) return;
|
||||
|
||||
ArrayList<ItemStack> stacks = new ArrayList<>();
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
for (ItemStack item : items) {
|
||||
if (item == null || item.getItem() == null) continue;
|
||||
|
||||
@@ -75,18 +82,60 @@ public class PositionedStack {
|
||||
}
|
||||
|
||||
public PositionedStack copy() {
|
||||
return new PositionedStack(items, relx, rely);
|
||||
PositionedStack pStack = new PositionedStack(Arrays.asList(items), relx, rely, false);
|
||||
pStack.permutated = this.permutated;
|
||||
return pStack;
|
||||
}
|
||||
|
||||
public List<ItemStack> getFilteredPermutations() {
|
||||
return getFilteredPermutations(null);
|
||||
}
|
||||
|
||||
public List<ItemStack> getFilteredPermutations(ItemFilter additionalFilter) {
|
||||
List<ItemStack> items = Arrays.asList(this.items).stream().filter(getItemFilter(additionalFilter)::matches)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (items.isEmpty()) {
|
||||
items.addAll(
|
||||
Arrays.asList(this.items).stream().filter(item -> !ItemInfo.isHidden(item))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (items.isEmpty()) {
|
||||
items.addAll(Arrays.asList(this.items));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private ItemFilter getItemFilter(ItemFilter additionalFilter) {
|
||||
return new AllMultiItemFilter(
|
||||
additionalFilter,
|
||||
item -> !ItemInfo.isHidden(item),
|
||||
PresetsList.getItemFilter(),
|
||||
GuiRecipe.getSearchItemFilter());
|
||||
}
|
||||
|
||||
public boolean setPermutationToRender(ItemStack ingredient) {
|
||||
|
||||
for (int index = 0; index < this.items.length; index++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(this.items[index], ingredient)) {
|
||||
setPermutationToRender(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPermutationToRender(int index) {
|
||||
item = items[index].copy();
|
||||
this.item = this.items[index].copy();
|
||||
|
||||
if (item.getItem() == null) {
|
||||
item = new ItemStack(Blocks.fire);
|
||||
} else if (item.getItemDamage() == OreDictionary.WILDCARD_VALUE && item.getItem() != null
|
||||
&& item.getItem().isRepairable()) {
|
||||
item.setItemDamage(0);
|
||||
}
|
||||
if (this.item.getItem() == null) {
|
||||
this.item = new ItemStack(Blocks.fire);
|
||||
} else if (this.item.getItemDamage() == OreDictionary.WILDCARD_VALUE && this.item.getItem().isRepairable()) {
|
||||
this.item.setItemDamage(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack ingredient) {
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.IRecipeFilter;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class PresetsList {
|
||||
|
||||
public enum PresetMode {
|
||||
HIDE,
|
||||
REMOVE,
|
||||
GROUP;
|
||||
}
|
||||
|
||||
public static class Preset implements ItemFilter {
|
||||
|
||||
public String name = "";
|
||||
public boolean enabled = true;
|
||||
public PresetMode mode = PresetMode.HIDE;
|
||||
public Set<String> items = new HashSet<>();
|
||||
|
||||
public static String getIdentifier(ItemStack stack) {
|
||||
return StackInfo.getItemStackGUID(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return items.contains(Preset.getIdentifier(item));
|
||||
}
|
||||
|
||||
public Preset copy() {
|
||||
Preset preset = new Preset();
|
||||
|
||||
preset.name = name;
|
||||
preset.enabled = enabled;
|
||||
preset.mode = mode;
|
||||
preset.items = new HashSet<>(items);
|
||||
|
||||
return preset;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class RecipesFilter implements IRecipeFilterProvider, IRecipeFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public IRecipeFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream().filter(p -> p.enabled && p.mode == PresetMode.REMOVE)
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others) {
|
||||
|
||||
if (matchPositionedStack(ingredients, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result != null && matchPositionedStack(result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!others.isEmpty() && matchPositionedStack(others, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return result == null && others.isEmpty();
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(List<PositionedStack> items, boolean dir) {
|
||||
for (PositionedStack pStack : items) {
|
||||
if (matchPositionedStack(pStack) == dir) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(PositionedStack pStack) {
|
||||
for (ItemStack stack : pStack.items) {
|
||||
if (!cache.contains(Preset.getIdentifier(stack))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelFilter implements ItemFilterProvider, ItemFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream()
|
||||
.filter(p -> p.enabled && (p.mode == PresetMode.HIDE || p.mode == PresetMode.REMOVE))
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack stack) {
|
||||
return !cache.contains(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
public static final List<Preset> presets = new ArrayList<>();
|
||||
protected static RecipesFilter recipeFilter = new RecipesFilter();
|
||||
protected static ItemPanelFilter itemFilter = new ItemPanelFilter();
|
||||
|
||||
static {
|
||||
API.addItemFilter(itemFilter);
|
||||
API.addRecipeFilter(recipeFilter);
|
||||
}
|
||||
|
||||
public static ItemFilter getItemFilter() {
|
||||
return itemFilter.getFilter();
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
|
||||
|
||||
if (presetsFile == null || !presetsFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> itemStrings;
|
||||
try (FileInputStream reader = new FileInputStream(presetsFile)) {
|
||||
NEIClientConfig.logger.info("Loading presets from file {}", presetsFile);
|
||||
itemStrings = IOUtils.readLines(reader, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets from file {}", presetsFile, e);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
Preset preset = new Preset();
|
||||
presets.clear();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
|
||||
try {
|
||||
|
||||
if (itemStr.isEmpty()) {
|
||||
itemStr = "; {}";
|
||||
}
|
||||
|
||||
if (itemStr.startsWith("; ")) {
|
||||
JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject();
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
// do not create empty namespaces
|
||||
presets.add(preset);
|
||||
preset = new Preset();
|
||||
}
|
||||
|
||||
if (settings.has("name")) {
|
||||
preset.name = settings.get("name").getAsString();
|
||||
}
|
||||
|
||||
if (settings.has("enabled")) {
|
||||
preset.enabled = settings.get("enabled").getAsBoolean();
|
||||
}
|
||||
|
||||
if (settings.has("mode")) {
|
||||
preset.mode = PresetMode.valueOf(settings.get("mode").getAsString());
|
||||
}
|
||||
|
||||
} else {
|
||||
preset.items.add(itemStr);
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets ItemStack from json string:\n{}", itemStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
presets.add(preset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void savePresets() {
|
||||
final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
|
||||
final List<String> strings = new ArrayList<>();
|
||||
|
||||
for (Preset preset : presets) {
|
||||
JsonObject settings = new JsonObject();
|
||||
|
||||
settings.add("name", new JsonPrimitive(preset.name));
|
||||
settings.add("enabled", new JsonPrimitive(preset.enabled));
|
||||
settings.add("mode", new JsonPrimitive(preset.mode.toString()));
|
||||
|
||||
strings.add("; " + NBTJson.toJson(settings));
|
||||
strings.addAll(preset.items);
|
||||
}
|
||||
|
||||
try (FileOutputStream output = new FileOutputStream(presetsFile)) {
|
||||
IOUtils.writeLines(strings, "\n", output, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Filed to save presets list to file {}", presetsFile, e);
|
||||
}
|
||||
|
||||
recipeFilter.cache = null;
|
||||
itemFilter.cache = null;
|
||||
CollapsibleItems.saveStates();
|
||||
CollapsibleItems.load();
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,6 +2,7 @@ package codechicken.nei;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.SearchField.GuiSearchField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
@@ -14,6 +15,13 @@ public abstract class RecipeSearchField extends TextField {
|
||||
this.field.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.field.getVisible();
|
||||
}
|
||||
@@ -51,7 +59,7 @@ public abstract class RecipeSearchField extends TextField {
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return SearchField.getFilter(text());
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.PatternItemFilter;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
||||
import codechicken.nei.SearchTokenParser.SearchMode;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
public class SearchField extends TextField implements ItemFilterProvider {
|
||||
@@ -23,6 +26,7 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
/**
|
||||
* Interface for returning a custom filter based on search field text
|
||||
*/
|
||||
@Deprecated
|
||||
public static interface ISearchProvider {
|
||||
|
||||
/**
|
||||
@@ -36,34 +40,98 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
public ItemFilter getFilter(String searchText);
|
||||
}
|
||||
|
||||
private static class DefaultSearchProvider implements ISearchProvider {
|
||||
public static class SearchParserProvider implements ISearchParserProvider {
|
||||
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
return false;
|
||||
protected final Function<Pattern, ItemFilter> createFilter;
|
||||
protected final String name;
|
||||
protected final char prefix;
|
||||
protected final EnumChatFormatting highlightedColor;
|
||||
|
||||
public SearchParserProvider(char prefix, String name, EnumChatFormatting highlightedColor,
|
||||
Function<Pattern, ItemFilter> createFilter) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
this.highlightedColor = highlightedColor;
|
||||
this.createFilter = createFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter(String searchText) {
|
||||
Pattern pattern = getPattern(searchText);
|
||||
return pattern == null ? null : new PatternItemFilter(pattern);
|
||||
Pattern pattern = SearchField.getPattern(searchText);
|
||||
|
||||
if (pattern != null) {
|
||||
return this.createFilter(pattern);
|
||||
}
|
||||
|
||||
return new NothingItemFilter();
|
||||
}
|
||||
|
||||
protected ItemFilter createFilter(Pattern pattern) {
|
||||
final ItemFilter filter = this.createFilter.apply(pattern);
|
||||
|
||||
return filter == null ? new NothingItemFilter() : filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumChatFormatting getHighlightedColor() {
|
||||
return this.highlightedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchMode getSearchMode() {
|
||||
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search." + this.name + "SearchMode"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class GuiSearchField extends FormattedTextField {
|
||||
|
||||
protected final SearchTokenParser searchParser;
|
||||
|
||||
public GuiSearchField() {
|
||||
this(SearchField.searchParser);
|
||||
}
|
||||
|
||||
public GuiSearchField(SearchTokenParser searchParser) {
|
||||
super(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
||||
this.searchParser = searchParser;
|
||||
setFormatter(new SearchTextFormatter(searchParser));
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return getFilter(getText());
|
||||
}
|
||||
|
||||
public ItemFilter getFilter(String filterText) {
|
||||
return this.searchParser.getFilter(filterText);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<ISearchProvider> searchProviders = new LinkedList<>();
|
||||
public static final SearchTokenParser searchParser = new SearchTokenParser();
|
||||
private static final TextHistory history = new TextHistory();
|
||||
private boolean isVisible = true;
|
||||
|
||||
long lastclicktime;
|
||||
private long lastclicktime;
|
||||
|
||||
public SearchField(String ident) {
|
||||
super(ident);
|
||||
API.addItemFilter(this);
|
||||
API.addSearchProvider(new DefaultSearchProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
public static boolean searchInventories() {
|
||||
return world.nbt.getBoolean("searchinventories");
|
||||
return NEIClientConfig.world.nbt.getBoolean("searchinventories");
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
@@ -76,7 +144,8 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (ItemPanels.itemPanel.getItems().isEmpty()) {
|
||||
if (ItemPanels.itemPanel.getItems().isEmpty()
|
||||
&& (!this.field.getText().isEmpty() || !NEIClientConfig.hideItemsUntilSearching())) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
@@ -85,14 +154,37 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
|
||||
super.draw(mousex, mousey);
|
||||
|
||||
if (searchInventories()) {
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(x + w, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y + h, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Bottom
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition + field.width,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition + field.height,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Bottom
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,10 +202,11 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
final String newText = text();
|
||||
if (newText.length() > 0) NEIClientConfig.logger.debug("Searching for " + text());
|
||||
|
||||
NEIClientConfig.setSearchExpression(newText);
|
||||
ItemList.updateFilter.restart();
|
||||
if (!newText.equals(oldText)) {
|
||||
if (newText.length() > 0) NEIClientConfig.logger.debug("Searching for " + newText);
|
||||
NEIClientConfig.setSearchExpression(newText);
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,47 +230,102 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static Pattern getPattern(String search) {
|
||||
switch (NEIClientConfig.getIntSetting("inventory.searchmode")) {
|
||||
return getPattern(search, NEIClientConfig.getIntSetting("inventory.search.patternMode"));
|
||||
}
|
||||
|
||||
public static Pattern getPattern(String search, int patternMode) {
|
||||
switch (patternMode) {
|
||||
case 0: // plain
|
||||
search = "\\Q" + search + "\\E";
|
||||
search = Pattern.quote(search);
|
||||
break;
|
||||
case 1:
|
||||
search = search.replace(".", "").replace("?", ".").replace("*", ".+?");
|
||||
case 1: // extended
|
||||
|
||||
if (search.length() >= 3 && search.startsWith("r/") && search.endsWith("/")) {
|
||||
search = search.substring(2, search.length() - 1);
|
||||
} else {
|
||||
final Matcher matcher = Pattern.compile("(\\?|\\*)").matcher(search);
|
||||
final StringBuilder cleanedString = new StringBuilder();
|
||||
int lastEndIndex = 0;
|
||||
|
||||
while (matcher.find()) {
|
||||
cleanedString.append(Pattern.quote(search.substring(lastEndIndex, matcher.start())));
|
||||
|
||||
switch (matcher.group(0).charAt(0)) {
|
||||
case '?':
|
||||
cleanedString.append(".");
|
||||
break;
|
||||
case '*':
|
||||
cleanedString.append(".+?");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lastEndIndex = matcher.end();
|
||||
}
|
||||
|
||||
search = cleanedString + Pattern.quote(search.substring(lastEndIndex, search.length()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Pattern pattern = null;
|
||||
try {
|
||||
pattern = Pattern.compile(search);
|
||||
} catch (PatternSyntaxException ignored) {}
|
||||
if (!search.isEmpty()) {
|
||||
try {
|
||||
return Pattern.compile(search, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
} catch (PatternSyntaxException ignored) {}
|
||||
}
|
||||
|
||||
return pattern == null || pattern.toString().length() == 0 ? null : pattern;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getEscapedSearchText(ItemStack stack) {
|
||||
final FluidStack fluidStack = StackInfo.isFluidContainer(stack) ? null : StackInfo.getFluid(stack);
|
||||
String displayName;
|
||||
|
||||
if (fluidStack != null) {
|
||||
displayName = fluidStack.getLocalizedName();
|
||||
} else {
|
||||
displayName = stack.getDisplayName();
|
||||
}
|
||||
|
||||
return getEscapedSearchText(displayName);
|
||||
}
|
||||
|
||||
public static String getEscapedSearchText(String text) {
|
||||
text = EnumChatFormatting.getTextWithoutFormattingCodes(text);
|
||||
|
||||
switch (NEIClientConfig.getIntSetting("inventory.search.patternMode")) {
|
||||
case 1:
|
||||
text = text.replaceAll("[\\?|\\*]", "\\\\$0");
|
||||
break;
|
||||
case 2:
|
||||
text = text.replaceAll("[{}()\\[\\].+*?^$\\\\|]", "\\\\$0");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (text.contains(" ") && NEIClientConfig.getBooleanSetting("inventory.search.quoteDropItemName")) {
|
||||
text = "\"" + text + "\"";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
return getFilter(text());
|
||||
|
||||
if (field.getText().isEmpty() && NEIClientConfig.hideItemsUntilSearching()) {
|
||||
return new NothingItemFilter();
|
||||
}
|
||||
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
public static ItemFilter getFilter(String s_filter) {
|
||||
List<ItemFilter> primary = new LinkedList<>();
|
||||
List<ItemFilter> secondary = new LinkedList<>();
|
||||
s_filter = s_filter.toLowerCase();
|
||||
|
||||
for (ISearchProvider p : searchProviders) {
|
||||
ItemFilter filter = p.getFilter(s_filter);
|
||||
if (filter != null) (p.isPrimary() ? primary : secondary).add(filter);
|
||||
}
|
||||
|
||||
if (!primary.isEmpty()) {
|
||||
return new AnyMultiItemFilter(primary);
|
||||
}
|
||||
|
||||
if (!secondary.isEmpty()) {
|
||||
return new AnyMultiItemFilter(secondary);
|
||||
}
|
||||
|
||||
return new EverythingItemFilter();
|
||||
public static ItemFilter getFilter(String filterText) {
|
||||
return SearchField.searchParser.getFilter(filterText);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.FormattedTextField.TextFormatter;
|
||||
import codechicken.nei.SearchTokenParser.SearchToken;
|
||||
|
||||
public class SearchTextFormatter implements TextFormatter {
|
||||
|
||||
protected final SearchTokenParser searchParser;
|
||||
|
||||
public SearchTextFormatter(SearchTokenParser searchParser) {
|
||||
this.searchParser = searchParser;
|
||||
}
|
||||
|
||||
public String format(String text) {
|
||||
final String[] parts = (text + "| ").split("\\|");
|
||||
StringJoiner formattedText = new StringJoiner(EnumChatFormatting.GRAY + "|");
|
||||
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
final String filterText = parts[i];
|
||||
final List<SearchToken> tokens = searchParser.splitSearchText(filterText);
|
||||
StringBuilder formattedPart = new StringBuilder();
|
||||
int startIndex = 0;
|
||||
|
||||
for (SearchToken token : tokens) {
|
||||
formattedPart.append(filterText.substring(startIndex, token.start));
|
||||
EnumChatFormatting tokenColor = EnumChatFormatting.RESET;
|
||||
|
||||
if (token.firstChar != null) {
|
||||
tokenColor = searchParser.getProvider(token.firstChar).getHighlightedColor();
|
||||
}
|
||||
|
||||
if (token.ignore) {
|
||||
formattedPart.append(EnumChatFormatting.BLUE + "-");
|
||||
}
|
||||
|
||||
if (token.firstChar != null) {
|
||||
formattedPart.append(tokenColor + String.valueOf(token.firstChar));
|
||||
}
|
||||
|
||||
if (token.quotes) {
|
||||
formattedPart.append(EnumChatFormatting.GOLD + "\"");
|
||||
}
|
||||
|
||||
if (!token.rawText.isEmpty()) {
|
||||
formattedPart.append(tokenColor + token.rawText);
|
||||
}
|
||||
|
||||
if (token.quotes) {
|
||||
formattedPart.append(EnumChatFormatting.GOLD + "\"");
|
||||
}
|
||||
|
||||
startIndex = token.end;
|
||||
}
|
||||
|
||||
formattedPart.append(filterText.substring(startIndex, filterText.length()));
|
||||
formattedText.add(formattedPart);
|
||||
}
|
||||
|
||||
return formattedText.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.Language;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public class SearchTokenParser {
|
||||
|
||||
public enum SearchMode {
|
||||
|
||||
ALWAYS,
|
||||
PREFIX,
|
||||
NEVER;
|
||||
|
||||
public static SearchMode fromInt(int value) {
|
||||
return switch (value) {
|
||||
case 0 -> ALWAYS;
|
||||
case 1 -> PREFIX;
|
||||
default -> NEVER;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchToken {
|
||||
|
||||
public boolean ignore = false;
|
||||
public boolean quotes = false;
|
||||
public Character firstChar = null;
|
||||
|
||||
public String[] words;
|
||||
|
||||
public String rawText = "";
|
||||
public int start = 0;
|
||||
public int end = 0;
|
||||
|
||||
}
|
||||
|
||||
public static interface ISearchParserProvider {
|
||||
|
||||
public ItemFilter getFilter(String searchText);
|
||||
|
||||
public static List<Language> getAllLanguages() {
|
||||
return new ArrayList<>(Minecraft.getMinecraft().getLanguageManager().getLanguages());
|
||||
}
|
||||
|
||||
default List<Language> getMatchingLanguages() {
|
||||
return getAllLanguages();
|
||||
}
|
||||
|
||||
public char getPrefix();
|
||||
|
||||
public EnumChatFormatting getHighlightedColor();
|
||||
|
||||
public SearchMode getSearchMode();
|
||||
}
|
||||
|
||||
private static class ProvidersCache {
|
||||
|
||||
public String languageCode = null;
|
||||
public List<ISearchParserProvider> providers = new ArrayList<>();
|
||||
|
||||
public void clear() {
|
||||
this.languageCode = null;
|
||||
this.providers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static class IsRegisteredItemFilter implements ItemFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public IsRegisteredItemFilter(ItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return item != null && item.getItem() != null
|
||||
&& item.getItem().delegate.name() != null
|
||||
&& this.filter.matches(item);
|
||||
}
|
||||
}
|
||||
|
||||
protected final LRUCache<String, ItemFilter> filtersCache = new LRUCache<>(20);
|
||||
protected final List<ISearchParserProvider> searchProviders;
|
||||
protected final ProvidersCache providersCache = new ProvidersCache();
|
||||
protected final Map<Character, Character> prefixRedefinitions = new HashMap<>();
|
||||
|
||||
public SearchTokenParser(List<ISearchParserProvider> searchProviders) {
|
||||
this.searchProviders = searchProviders;
|
||||
}
|
||||
|
||||
public SearchTokenParser() {
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addProvider(ISearchParserProvider provider) {
|
||||
this.searchProviders.add(provider);
|
||||
this.providersCache.clear();
|
||||
this.filtersCache.clear();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
this.filtersCache.clear();
|
||||
}
|
||||
|
||||
protected List<ISearchParserProvider> getProviders() {
|
||||
Language currentLanguage = Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage();
|
||||
|
||||
if (!currentLanguage.getLanguageCode().equals(providersCache.languageCode)) {
|
||||
Map<Character, ISearchParserProvider> providers = new HashMap<>();
|
||||
|
||||
for (int index = this.searchProviders.size() - 1; index >= 0; index--) {
|
||||
ISearchParserProvider provider = this.searchProviders.get(index);
|
||||
|
||||
if (!providers.containsKey(provider.getPrefix())
|
||||
&& provider.getMatchingLanguages().contains(currentLanguage)) {
|
||||
providers.put(provider.getPrefix(), provider);
|
||||
}
|
||||
}
|
||||
|
||||
providersCache.providers = new ArrayList<>(providers.values());
|
||||
providersCache.languageCode = currentLanguage.getLanguageCode();
|
||||
}
|
||||
|
||||
return providersCache.providers;
|
||||
}
|
||||
|
||||
public ISearchParserProvider getProvider(char ch) {
|
||||
return getProviders().stream()
|
||||
.filter(
|
||||
provider -> provider.getSearchMode() == SearchMode.PREFIX
|
||||
&& getRedefinedPrefix(provider.getPrefix()) == ch)
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public synchronized ItemFilter getFilter(String filterText) {
|
||||
filterText = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase();
|
||||
|
||||
return this.filtersCache.computeIfAbsent(filterText, text -> {
|
||||
final String[] parts = text.split("\\|");
|
||||
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(this::parseSearchText).filter(s -> s != null)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
if (searchTokens.isEmpty()) {
|
||||
return new EverythingItemFilter();
|
||||
} else if (searchTokens.size() == 1) {
|
||||
return new IsRegisteredItemFilter(searchTokens.get(0));
|
||||
} else {
|
||||
return new IsRegisteredItemFilter(new AnyMultiItemFilter(searchTokens));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public List<SearchToken> splitSearchText(String filterText) {
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<SearchToken> tokens = new ArrayList<>();
|
||||
final String prefixes = getPrefixes();
|
||||
final int spaceMode = NEIClientConfig.getIntSetting("inventory.search.spaceMode");
|
||||
// The regular expression first tries to match a string that starts with a space or the beginning of the string,
|
||||
// followed by a sequence of characters that do not contain special characters -"@#$%&, and ends with a space
|
||||
// and the characters -"@#$%& or the end of the string.
|
||||
final String patternPart1 = "(?<tokenA>(^|\\s+)(?:[^" + Pattern.quote(" -\"" + prefixes)
|
||||
+ "]).+?(?=\\s+["
|
||||
+ Pattern.quote("-\"" + prefixes)
|
||||
+ "]|$))";
|
||||
// If the first condition is not met, it tries to match a sequence of - characters, followed by @#$%&
|
||||
// characters, then either a quoted string or non-space characters.
|
||||
final String patternPart2 = "((?<ignore>-*)(?<firstChar>[" + Pattern.quote(prefixes)
|
||||
+ "]*)(?<tokenB>\\\".*?(?:\\\"|$)|\\S+\\s*))";
|
||||
final Pattern pattern = Pattern.compile(spaceMode == 0 ? patternPart2 : (patternPart1 + "|" + patternPart2));
|
||||
final Matcher filterMatcher = pattern.matcher(filterText);
|
||||
|
||||
while (filterMatcher.find()) {
|
||||
String firstChar = filterMatcher.group("firstChar");
|
||||
SearchToken token = new SearchToken();
|
||||
token.start = filterMatcher.start();
|
||||
token.end = filterMatcher.end();
|
||||
token.ignore = "-".equals(filterMatcher.group("ignore"));
|
||||
token.rawText = spaceMode == 0 ? null : filterMatcher.group("tokenA");
|
||||
|
||||
if (firstChar != null && !firstChar.isEmpty()) {
|
||||
token.firstChar = firstChar.charAt(0);
|
||||
}
|
||||
|
||||
if (token.rawText == null) { // spaceMode == 0
|
||||
token.rawText = filterMatcher.group("tokenB");
|
||||
token.quotes = token.rawText.length() > 1 && token.rawText.startsWith("\"")
|
||||
&& token.rawText.endsWith("\"");
|
||||
|
||||
if (token.quotes) {
|
||||
token.rawText = token.rawText.substring(1, token.rawText.length() - 1);
|
||||
}
|
||||
|
||||
token.words = new String[] { token.rawText.trim() };
|
||||
} else if (spaceMode == 2) {
|
||||
token.words = token.rawText.trim().split("\\s+");
|
||||
} else {
|
||||
token.words = new String[] { token.rawText.trim() };
|
||||
}
|
||||
|
||||
tokens.add(token);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private String getPrefixes() {
|
||||
StringBuilder prefixes = new StringBuilder().append('\0');
|
||||
|
||||
for (ISearchParserProvider provider : getProviders()) {
|
||||
if (provider.getSearchMode() == SearchMode.PREFIX) {
|
||||
prefixes.append(getRedefinedPrefix(provider.getPrefix()));
|
||||
}
|
||||
}
|
||||
|
||||
return prefixes.toString();
|
||||
}
|
||||
|
||||
public char getRedefinedPrefix(char prefix) {
|
||||
return this.prefixRedefinitions.getOrDefault(prefix, prefix);
|
||||
}
|
||||
|
||||
private ItemFilter parseSearchText(String filterText) {
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AllMultiItemFilter searchTokens = new AllMultiItemFilter();
|
||||
final List<SearchToken> tokens = splitSearchText(filterText);
|
||||
|
||||
for (SearchToken token : tokens) {
|
||||
if (!token.rawText.isEmpty()) {
|
||||
ItemFilter result = parseToken(token);
|
||||
|
||||
if (token.ignore) {
|
||||
searchTokens.filters.add(new NegatedItemFilter(result));
|
||||
} else {
|
||||
searchTokens.filters.add(result);
|
||||
}
|
||||
} else if (!token.ignore) {
|
||||
searchTokens.filters.add(new NothingItemFilter());
|
||||
}
|
||||
}
|
||||
|
||||
return searchTokens;
|
||||
}
|
||||
|
||||
private ItemFilter parseToken(SearchToken token) {
|
||||
final ISearchParserProvider provider = token.firstChar == null ? null : this.getProvider(token.firstChar);
|
||||
|
||||
if (provider == null || provider.getSearchMode() == SearchMode.NEVER) {
|
||||
final List<ItemFilter> filters = new ArrayList<>();
|
||||
|
||||
for (ISearchParserProvider _provider : getProviders()) {
|
||||
if (_provider.getSearchMode() == SearchMode.ALWAYS) {
|
||||
AllMultiItemFilter filter = generateFilters(_provider, token.words);
|
||||
|
||||
if (!filter.filters.isEmpty()) {
|
||||
filters.add(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filters.isEmpty() ? new NothingItemFilter() : new AnyMultiItemFilter(filters);
|
||||
} else {
|
||||
return generateFilters(provider, token.words);
|
||||
}
|
||||
}
|
||||
|
||||
private AllMultiItemFilter generateFilters(ISearchParserProvider provider, String[] words) {
|
||||
final AllMultiItemFilter filters = new AllMultiItemFilter();
|
||||
|
||||
for (String work : words) {
|
||||
final ItemFilter filter = provider.getFilter(work);
|
||||
|
||||
if (filter != null) {
|
||||
filters.filters.add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,6 @@ public class SpawnerRenderer implements IItemRenderer {
|
||||
BossStatus.hasColorModifier = bossHasColorModifier;
|
||||
}
|
||||
|
||||
@SuppressWarnings("incomplete-switch")
|
||||
@Override
|
||||
public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
|
||||
switch (type) {
|
||||
@@ -75,6 +74,8 @@ public class SpawnerRenderer implements IItemRenderer {
|
||||
case ENTITY:
|
||||
renderInventoryItem((RenderBlocks) data[0], item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -9,7 +9,7 @@ public abstract class TextField extends Widget {
|
||||
|
||||
protected GuiTextField field;
|
||||
|
||||
private static final int maxSearchLength = 256;
|
||||
protected static final int maxSearchLength = 256;
|
||||
|
||||
public boolean centered;
|
||||
public String identifier;
|
||||
|
||||
@@ -6,9 +6,9 @@ import cpw.mods.fml.common.FMLCommonHandler;
|
||||
|
||||
public class ThreadOperationTimer extends Thread {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class TimeoutException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -8621458005263888185L;
|
||||
public final Object operation;
|
||||
|
||||
public TimeoutException(String msg, Object op) {
|
||||
|
||||
@@ -15,10 +15,6 @@ public class VisiblityData {
|
||||
* Subset dropdown
|
||||
*/
|
||||
public boolean showSubsetDropdown = true;
|
||||
/**
|
||||
* Presets dropdown
|
||||
*/
|
||||
public boolean showPresetsDropdown = true;
|
||||
/**
|
||||
* Item and search section
|
||||
*/
|
||||
@@ -44,7 +40,6 @@ public class VisiblityData {
|
||||
public void translateDependancies() {
|
||||
if (!showNEI) showWidgets = false;
|
||||
if (!showWidgets) showItemSection = showUtilityButtons = false;
|
||||
if (!showItemSection)
|
||||
showBookmarkPanel = showSubsetDropdown = showPresetsDropdown = showSearchSection = showItemPanel = false;
|
||||
if (!showItemSection) showBookmarkPanel = showSubsetDropdown = showSearchSection = showItemPanel = false;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,6 @@ public class WidgetZOrder implements Comparator<Widget> {
|
||||
}
|
||||
|
||||
public int compare(Widget w1, Widget w2) {
|
||||
return w1.z != w2.z ? ((topfirst ? w1.z > w2.z : w1.z < w2.z) ? 1 : -1) : 1;
|
||||
return w1.z != w2.z ? ((topfirst ? w1.z < w2.z : w1.z > w2.z) ? 1 : -1) : 1;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.math.MathHelper;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
@@ -26,12 +27,11 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
private static byte[] mobSpawnCache;
|
||||
private static long mobOverlayUpdateTime;
|
||||
private static String oregenPatternName;
|
||||
private static boolean hasOregenPatternBeenSet = false;
|
||||
|
||||
public static void reset() {
|
||||
mobOverlay = 0;
|
||||
chunkOverlay = 0;
|
||||
hasOregenPatternBeenSet = false;
|
||||
oregenPatternName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,7 +204,9 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glLineWidth(1.5F);
|
||||
GL11.glBegin(GL11.GL_LINES);
|
||||
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
tess.startDrawing(GL11.GL_LINES);
|
||||
|
||||
for (int cx = -4; cx <= 4; cx++) for (int cz = -4; cz <= 4; cz++) {
|
||||
double x1 = ((entity.chunkCoordX + cx) << 4) - intOffsetX;
|
||||
@@ -230,22 +232,22 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
double dist = Math.pow(1.5, -(cx * cx + cz * cz));
|
||||
|
||||
GL11.glColor4d(0.9, 0, 0, dist);
|
||||
tess.setColorRGBA_F(0.9F, 0, 0, (float) dist);
|
||||
if (cx >= 0 && cz >= 0) {
|
||||
GL11.glVertex3d(x2, y1, z2);
|
||||
GL11.glVertex3d(x2, y2, z2);
|
||||
tess.addVertex(x2, y1, z2);
|
||||
tess.addVertex(x2, y2, z2);
|
||||
}
|
||||
if (cx >= 0 && cz <= 0) {
|
||||
GL11.glVertex3d(x2, y1, z1);
|
||||
GL11.glVertex3d(x2, y2, z1);
|
||||
tess.addVertex(x2, y1, z1);
|
||||
tess.addVertex(x2, y2, z1);
|
||||
}
|
||||
if (cx <= 0 && cz >= 0) {
|
||||
GL11.glVertex3d(x1, y1, z2);
|
||||
GL11.glVertex3d(x1, y2, z2);
|
||||
tess.addVertex(x1, y1, z2);
|
||||
tess.addVertex(x1, y2, z2);
|
||||
}
|
||||
if (cx <= 0 && cz <= 0) {
|
||||
GL11.glVertex3d(x1, y1, z1);
|
||||
GL11.glVertex3d(x1, y2, z1);
|
||||
tess.addVertex(x1, y1, z1);
|
||||
tess.addVertex(x1, y2, z1);
|
||||
}
|
||||
|
||||
if (cx == 0 && cz == 0) {
|
||||
@@ -266,40 +268,31 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
y1 -= intOffsetY;
|
||||
y2 -= intOffsetY;
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
tess.setColorRGBA_F(0, 0.9F, 0, 0.4F);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
tess.addVertex(x2, y, z1);
|
||||
tess.addVertex(x2, y, z2);
|
||||
tess.addVertex(x1, y, z1);
|
||||
tess.addVertex(x1, y, z2);
|
||||
tess.addVertex(x1, y, z2);
|
||||
tess.addVertex(x2, y, z2);
|
||||
tess.addVertex(x1, y, z1);
|
||||
tess.addVertex(x2, y, z1);
|
||||
}
|
||||
for (double h = 1; h <= 15; h++) {
|
||||
GL11.glVertex3d(x1 + h, y1, z1);
|
||||
GL11.glVertex3d(x1 + h, y2, z1);
|
||||
GL11.glVertex3d(x1 + h, y1, z2);
|
||||
GL11.glVertex3d(x1 + h, y2, z2);
|
||||
GL11.glVertex3d(x1, y1, z1 + h);
|
||||
GL11.glVertex3d(x1, y2, z1 + h);
|
||||
GL11.glVertex3d(x2, y1, z1 + h);
|
||||
GL11.glVertex3d(x2, y2, z1 + h);
|
||||
tess.addVertex(x1 + h, y1, z1);
|
||||
tess.addVertex(x1 + h, y2, z1);
|
||||
tess.addVertex(x1 + h, y1, z2);
|
||||
tess.addVertex(x1 + h, y2, z2);
|
||||
tess.addVertex(x1, y1, z1 + h);
|
||||
tess.addVertex(x1, y2, z1 + h);
|
||||
tess.addVertex(x2, y1, z1 + h);
|
||||
tess.addVertex(x2, y2, z1 + h);
|
||||
}
|
||||
} else if (chunkOverlay == 3) {
|
||||
if (!hasOregenPatternBeenSet) {
|
||||
try {
|
||||
oregenPatternName = ((Enum<?>) Class.forName("gregtech.common.GT_Worldgenerator")
|
||||
.getDeclaredField("oregenPattern").get(null)).name();
|
||||
} catch (Exception ignored) {
|
||||
oregenPatternName = "AXISSYMMETRICAL";
|
||||
}
|
||||
hasOregenPatternBeenSet = true;
|
||||
}
|
||||
int gx1;
|
||||
int gz1;
|
||||
if (oregenPatternName.equals("EQUAL_SPACING")) {
|
||||
if (getOregenPatternName().equals("EQUAL_SPACING")) {
|
||||
// gt oregen uses new regular pattern
|
||||
gx1 = ((Math.floorDiv(entity.chunkCoordX, 3) * 3) << 4) - intOffsetX;
|
||||
gz1 = ((Math.floorDiv(entity.chunkCoordZ, 3) * 3) << 4) - intOffsetZ;
|
||||
@@ -319,55 +312,71 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
int gx2 = gx1 + 48;
|
||||
int gz2 = gz1 + 48;
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
tess.setColorRGBA_F(0, 0.9F, 0, 0.4F);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
tess.addVertex(gx2, y, gz1);
|
||||
tess.addVertex(gx2, y, gz2);
|
||||
tess.addVertex(gx1, y, gz1);
|
||||
tess.addVertex(gx1, y, gz2);
|
||||
tess.addVertex(gx1, y, gz2);
|
||||
tess.addVertex(gx2, y, gz2);
|
||||
tess.addVertex(gx1, y, gz1);
|
||||
tess.addVertex(gx2, y, gz1);
|
||||
}
|
||||
for (double h = 4; h <= 44; h += 4) {
|
||||
if (h % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
GL11.glVertex3d(gx1 + h, y1, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y1, gz2);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz2);
|
||||
GL11.glVertex3d(gx1, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx1, y2, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y2, gz1 + h);
|
||||
tess.addVertex(gx1 + h, y1, gz1);
|
||||
tess.addVertex(gx1 + h, y2, gz1);
|
||||
tess.addVertex(gx1 + h, y1, gz2);
|
||||
tess.addVertex(gx1 + h, y2, gz2);
|
||||
tess.addVertex(gx1, y1, gz1 + h);
|
||||
tess.addVertex(gx1, y2, gz1 + h);
|
||||
tess.addVertex(gx2, y1, gz1 + h);
|
||||
tess.addVertex(gx2, y2, gz1 + h);
|
||||
}
|
||||
|
||||
GL11.glColor4d(0, 0, 0.9, 0.4);
|
||||
tess.setColorRGBA_F(0, 0, 0.9F, 0.4F);
|
||||
gx1 += 23;
|
||||
gz1 += 23;
|
||||
gx2 = gx1 + 1;
|
||||
gz2 = gz1 + 1;
|
||||
|
||||
GL11.glVertex3d(gx1, y1, gz1);
|
||||
GL11.glVertex3d(gx1, y2, gz1);
|
||||
GL11.glVertex3d(gx2, y1, gz1);
|
||||
GL11.glVertex3d(gx2, y2, gz1);
|
||||
GL11.glVertex3d(gx1, y1, gz2);
|
||||
GL11.glVertex3d(gx1, y2, gz2);
|
||||
GL11.glVertex3d(gx2, y1, gz2);
|
||||
GL11.glVertex3d(gx2, y2, gz2);
|
||||
tess.addVertex(gx1, y1, gz1);
|
||||
tess.addVertex(gx1, y2, gz1);
|
||||
tess.addVertex(gx2, y1, gz1);
|
||||
tess.addVertex(gx2, y2, gz1);
|
||||
tess.addVertex(gx1, y1, gz2);
|
||||
tess.addVertex(gx1, y2, gz2);
|
||||
tess.addVertex(gx2, y1, gz2);
|
||||
tess.addVertex(gx2, y2, gz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnd();
|
||||
tess.draw();
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
private static String getOregenPatternName() {
|
||||
|
||||
if (oregenPatternName == null) {
|
||||
try {
|
||||
final ClassLoader loader = WorldOverlayRenderer.class.getClassLoader();
|
||||
final Class<?> gtWorldGenerator = ReflectionHelper
|
||||
.getClass(loader, "gregtech.common.GTWorldgenerator", "gregtech.common.GT_Worldgenerator");
|
||||
oregenPatternName = ((Enum<?>) gtWorldGenerator.getDeclaredField("oregenPattern").get(null)).name();
|
||||
} catch (Exception ignored) {
|
||||
oregenPatternName = "AXISSYMMETRICAL";
|
||||
}
|
||||
}
|
||||
|
||||
return oregenPatternName;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
KeyManager.trackers.add(new WorldOverlayRenderer());
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.OffsetPositioner;
|
||||
import codechicken.nei.SearchField;
|
||||
import codechicken.nei.SearchField.ISearchProvider;
|
||||
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
||||
import codechicken.nei.SubsetWidget;
|
||||
import codechicken.nei.SubsetWidget.SubsetTag;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
@@ -41,6 +42,7 @@ import codechicken.nei.recipe.IUsageHandler;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import codechicken.nei.recipe.RecipeInfo;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.ItemStackFilterParser;
|
||||
|
||||
/**
|
||||
* This is the main class that handles item property configuration. WARNING: DO NOT access this class until the world
|
||||
@@ -150,6 +152,14 @@ public class API {
|
||||
}
|
||||
}
|
||||
|
||||
public static void hideItem(String rule) {
|
||||
ItemFilter filter = ItemStackFilterParser.parse(rule);
|
||||
if (filter != null) {
|
||||
ItemInfo.hiddenItemsRules.filters.add(filter);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or replace the name normally shown on the item tooltip
|
||||
*/
|
||||
@@ -314,11 +324,14 @@ public class API {
|
||||
SubsetWidget.addTag(tag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addSearchProvider(ISearchProvider provider) {}
|
||||
|
||||
/**
|
||||
* Adds a new search provider to the search field
|
||||
*/
|
||||
public static void addSearchProvider(ISearchProvider provider) {
|
||||
SearchField.searchProviders.add(provider);
|
||||
public static void addSearchProvider(ISearchParserProvider provider) {
|
||||
SearchField.searchParser.addProvider(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -13,7 +15,7 @@ import codechicken.nei.guihook.GuiContainerManager;
|
||||
public class DefaultOverlayRenderer implements IRecipeOverlayRenderer {
|
||||
|
||||
public DefaultOverlayRenderer(List<PositionedStack> ai, IStackPositioner positioner) {
|
||||
positioner = this.positioner = positioner;
|
||||
this.positioner = positioner;
|
||||
ingreds = new ArrayList<>();
|
||||
for (PositionedStack stack : ai) ingreds.add(stack.copy());
|
||||
ingreds = positioner.positionStacks(ingreds);
|
||||
@@ -21,20 +23,26 @@ public class DefaultOverlayRenderer implements IRecipeOverlayRenderer {
|
||||
|
||||
@Override
|
||||
public void renderOverlay(GuiContainerManager gui, Slot slot) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(770, 1);
|
||||
GL11.glColor4d(0.6, 0.6, 0.6, 0.7);
|
||||
|
||||
GuiContainerManager.setColouredItemRender(true);
|
||||
for (PositionedStack stack : ingreds) {
|
||||
if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition)
|
||||
if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition && !slot.getHasStack()) {
|
||||
GuiContainerManager.drawItem(stack.relx, stack.rely, stack.item);
|
||||
drawHover(stack.relx, stack.rely);
|
||||
}
|
||||
}
|
||||
GuiContainerManager.setColouredItemRender(false);
|
||||
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
private static void drawHover(int x, int y) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
drawRect(x, y, 16, 16, 0x66555555);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
final IStackPositioner positioner;
|
||||
|
||||
@@ -1,10 +1,44 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.recipe.GuiOverlayButton.ItemOverlayState;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
|
||||
public interface IOverlayHandler {
|
||||
|
||||
void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift);
|
||||
|
||||
default List<ItemOverlayState> presenceOverlay(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex) {
|
||||
final List<ItemOverlayState> itemPresenceSlots = new ArrayList<>();
|
||||
final List<PositionedStack> ingredients = recipe.getIngredientStacks(recipeIndex);
|
||||
final List<ItemStack> invStacks = firstGui.inventorySlots.inventorySlots.stream()
|
||||
.filter(
|
||||
s -> s != null && s.getStack() != null
|
||||
&& s.getStack().stackSize > 0
|
||||
&& s.isItemValid(s.getStack())
|
||||
&& s.canTakeStack(firstGui.mc.thePlayer))
|
||||
.map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
for (PositionedStack stack : ingredients) {
|
||||
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
|
||||
.findAny();
|
||||
|
||||
itemPresenceSlots.add(new ItemOverlayState(stack, used.isPresent()));
|
||||
|
||||
if (used.isPresent()) {
|
||||
ItemStack is = used.get();
|
||||
is.stackSize -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return itemPresenceSlots;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
@@ -44,12 +43,16 @@ import com.google.common.collect.ArrayListMultimap;
|
||||
import codechicken.core.featurehack.GameDataManipulator;
|
||||
import codechicken.nei.InfiniteStackSizeHandler;
|
||||
import codechicken.nei.InfiniteToolHandler;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.PatternItemFilter;
|
||||
import codechicken.nei.ItemMobSpawner;
|
||||
import codechicken.nei.ItemStackMap;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.PopupInputHandler;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.SearchField.SearchParserProvider;
|
||||
import codechicken.nei.SearchTokenParser.SearchMode;
|
||||
import codechicken.nei.config.ArrayDumper;
|
||||
import codechicken.nei.config.HandlerDumper;
|
||||
import codechicken.nei.config.ItemPanelDumper;
|
||||
@@ -57,6 +60,10 @@ import codechicken.nei.config.RegistryDumper;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.BrewingRecipeHandler;
|
||||
import codechicken.nei.recipe.RecipeItemInputHandler;
|
||||
import codechicken.nei.search.IdentifierFilter;
|
||||
import codechicken.nei.search.ModNameFilter;
|
||||
import codechicken.nei.search.OreDictionaryFilter;
|
||||
import codechicken.nei.search.TooltipFilter;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
@@ -76,6 +83,7 @@ public class ItemInfo {
|
||||
public static final ArrayListMultimap<Layout, IHighlightHandler> highlightHandlers = ArrayListMultimap.create();
|
||||
public static final ItemStackMap<String> nameOverrides = new ItemStackMap<>();
|
||||
public static final ItemStackSet hiddenItems = new ItemStackSet();
|
||||
public static final AnyMultiItemFilter hiddenItemsRules = new AnyMultiItemFilter();
|
||||
public static final ItemStackSet finiteItems = new ItemStackSet();
|
||||
public static final ArrayListMultimap<Item, ItemStack> itemOverrides = ArrayListMultimap.create();
|
||||
public static final ArrayListMultimap<Item, ItemStack> itemVariants = ArrayListMultimap.create();
|
||||
@@ -86,40 +94,11 @@ public class ItemInfo {
|
||||
|
||||
public static final HashMap<Item, String> itemOwners = new HashMap<>();
|
||||
|
||||
private static class ItemStackKey {
|
||||
|
||||
public final ItemStack stack;
|
||||
|
||||
public ItemStackKey(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (this.stack == null) return 1;
|
||||
int hashCode = 1;
|
||||
hashCode = 31 * hashCode + stack.stackSize;
|
||||
hashCode = 31 * hashCode + Item.getIdFromItem(stack.getItem());
|
||||
hashCode = 31 * hashCode + stack.getItemDamage();
|
||||
hashCode = 31 * hashCode + (!stack.hasTagCompound() ? 0 : stack.getTagCompound().hashCode());
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof ItemStackKey)) return false;
|
||||
return ItemStack.areItemStacksEqual(this.stack, ((ItemStackKey) o).stack);
|
||||
}
|
||||
}
|
||||
|
||||
// lookup optimisation
|
||||
public static final ConcurrentHashMap<ItemStackKey, String> itemSearchNames = new ConcurrentHashMap<>();
|
||||
|
||||
public static boolean isHidden(ItemStack stack) {
|
||||
return hiddenItems.contains(stack);
|
||||
return hiddenItems.contains(stack) || hiddenItemsRules.matches(stack);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean isHidden(Item item) {
|
||||
return hiddenItems.containsAll(item);
|
||||
}
|
||||
@@ -154,27 +133,28 @@ public class ItemInfo {
|
||||
addInfiniteHandlers();
|
||||
addInputHandlers();
|
||||
addIDDumps();
|
||||
addHiddenItemFilter();
|
||||
addSearchOptimisation();
|
||||
addSearchProviders();
|
||||
RecipeItemInputHandler.load();
|
||||
PresetsList.load();
|
||||
}
|
||||
|
||||
private static void addSearchOptimisation() {
|
||||
ItemList.loadCallbacks.add(ItemInfo::populateSearchMap);
|
||||
}
|
||||
private static void addSearchProviders() {
|
||||
API.addSearchProvider(
|
||||
new SearchParserProvider('\0', "default", EnumChatFormatting.RESET, PatternItemFilter::new) {
|
||||
|
||||
private static void populateSearchMap() {
|
||||
/* Create a snapshot of the current keys in the cache */
|
||||
HashSet<ItemStackKey> oldItems = new HashSet<>(itemSearchNames.keySet());
|
||||
for (ItemStack stack : ItemList.items) {
|
||||
/* Populate each entry and remove it from the snapshot */
|
||||
getSearchName(stack);
|
||||
oldItems.remove(new ItemStackKey(stack));
|
||||
}
|
||||
itemSearchNames.keySet().removeAll(oldItems);
|
||||
}
|
||||
@Override
|
||||
public SearchMode getSearchMode() {
|
||||
return SearchMode.ALWAYS;
|
||||
}
|
||||
|
||||
private static void addHiddenItemFilter() {
|
||||
API.addItemFilter(() -> item -> !hiddenItems.contains(item));
|
||||
});
|
||||
API.addSearchProvider(
|
||||
new SearchParserProvider('@', "modName", EnumChatFormatting.LIGHT_PURPLE, ModNameFilter::new));
|
||||
API.addSearchProvider(
|
||||
new SearchParserProvider('$', "oreDict", EnumChatFormatting.AQUA, OreDictionaryFilter::new));
|
||||
API.addSearchProvider(new SearchParserProvider('#', "tooltip", EnumChatFormatting.YELLOW, TooltipFilter::new));
|
||||
API.addSearchProvider(
|
||||
new SearchParserProvider('&', "identifier", EnumChatFormatting.GOLD, IdentifierFilter::new));
|
||||
}
|
||||
|
||||
private static void addIDDumps() {
|
||||
@@ -209,7 +189,7 @@ public class ItemInfo {
|
||||
public String[] dump(Block block, int id, String name) {
|
||||
final Item item = Item.getItemFromBlock(block);
|
||||
return new String[] { name, Integer.toString(id), Boolean.toString(item != null),
|
||||
ItemInfo.itemOwners.get(block), block.getClass().getCanonicalName(),
|
||||
ItemInfo.itemOwners.get(item), block.getClass().getCanonicalName(),
|
||||
item != null ? EnumChatFormatting.getTextWithoutFormattingCodes(
|
||||
GuiContainerManager.itemDisplayNameShort(new ItemStack(item))) : "null" };
|
||||
}
|
||||
@@ -316,7 +296,6 @@ public class ItemInfo {
|
||||
}
|
||||
|
||||
private static void addInputHandlers() {
|
||||
GuiContainerManager.addInputHandler(new RecipeItemInputHandler());
|
||||
GuiContainerManager.addInputHandler(new PopupInputHandler());
|
||||
}
|
||||
|
||||
@@ -460,7 +439,6 @@ public class ItemInfo {
|
||||
addEntityEgg(EntityIronGolem.class, 0xC5C2C1, 0xffe1cc);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void addEntityEgg(Class<?> entity, int i, int j) {
|
||||
int id = (Integer) EntityList.classToIDMapping.get(entity);
|
||||
EntityList.entityEggs.put(id, new EntityEggInfo(id, i, j));
|
||||
@@ -516,10 +494,8 @@ public class ItemInfo {
|
||||
return retString;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String getSearchName(ItemStack stack) {
|
||||
return itemSearchNames.computeIfAbsent(
|
||||
new ItemStackKey(stack),
|
||||
key -> EnumChatFormatting.getTextWithoutFormattingCodes(
|
||||
GuiContainerManager.concatenatedDisplayName(key.stack, true).toLowerCase()));
|
||||
return GuiContainerManager.concatenatedDisplayName(stack, true).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,15 @@ package codechicken.nei.api;
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
@@ -41,7 +46,7 @@ public abstract class ShortcutInputHandler {
|
||||
return ItemPanels.bookmarkPanel.pullBookmarkItems(ItemPanels.bookmarkPanel.getHoveredGroupId(true), true);
|
||||
}
|
||||
|
||||
if (stackover == null && NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) {
|
||||
if (stackover == null && NEIClientConfig.isKeyHashDown("gui.remove_recipe")) {
|
||||
final int groupId = ItemPanels.bookmarkPanel.getHoveredGroupId(true);
|
||||
|
||||
if (groupId != -1) {
|
||||
@@ -60,6 +65,14 @@ public abstract class ShortcutInputHandler {
|
||||
return openOverlayRecipe(stackover, false);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.copy_name")) {
|
||||
return copyItemStackName(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.copy_oredict")) {
|
||||
return copyItemStackOreDictionary(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.overlay_use")) {
|
||||
return openOverlayRecipe(stackover, true);
|
||||
}
|
||||
@@ -120,6 +133,30 @@ public abstract class ShortcutInputHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean copyItemStackName(ItemStack stackover) {
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard()
|
||||
.setContents(new StringSelection(stackover.getDisplayName()), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean copyItemStackOreDictionary(ItemStack stackover) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (int id : OreDictionary.getOreIDs(stackover)) {
|
||||
String oreDictionaryName = OreDictionary.getOreName(id);
|
||||
if (!"Unknown".equals(oreDictionaryName)) {
|
||||
builder.append(oreDictionaryName).append(",");
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.length() > 0) {
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
}
|
||||
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(builder.toString()), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean openOverlayRecipe(ItemStack stackover, boolean shift) {
|
||||
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
|
||||
@@ -164,4 +201,8 @@ public abstract class ShortcutInputHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, ItemStack stack) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -66,16 +66,6 @@ public class NEITransformer implements IClassTransformer {
|
||||
"func_149689_a",
|
||||
"(Lnet/minecraft/world/World;IIILnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;)V"),
|
||||
asmblocks.get("spawnerPlaced")));
|
||||
|
||||
// Make MobSpawnerBaseLogic use getSpawnerWorld when creating new entities
|
||||
transformer.add(
|
||||
new MethodReplacer(
|
||||
new ObfMapping(
|
||||
"net/minecraft/tileentity/MobSpawnerBaseLogic",
|
||||
"func_98281_h",
|
||||
"()Lnet/minecraft/entity/Entity;"),
|
||||
asmblocks.get("d_spawnerWorld"),
|
||||
asmblocks.get("spawnerWorld")));
|
||||
}
|
||||
|
||||
// Removes trailing seperators from NBTTagList/Compound.toString because OCD
|
||||
|
||||
@@ -113,8 +113,13 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
if (nslot != list.indexOf(dragged.e)) {
|
||||
list.remove(dragged.e);
|
||||
list.add(nslot, dragged.e);
|
||||
|
||||
opt.getTag().setValue(ItemSorter.getSaveString(list));
|
||||
if (opt.activeTag() == opt.getTag()) ItemSorter.list = new ArrayList<>(list);
|
||||
LayoutManager.markItemsDirty();
|
||||
|
||||
if (opt.activeTag() == opt.getTag()) {
|
||||
ItemSorter.list = new ArrayList<>(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,26 +75,25 @@ public abstract class OptionButton extends Option {
|
||||
}
|
||||
|
||||
public String getTooltip() {
|
||||
String tip = null;
|
||||
|
||||
if (tooltip != null) {
|
||||
String s = translateN(tooltip);
|
||||
|
||||
if (!s.equals(namespaced(tooltip))) {
|
||||
tip = s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
if (tip == null && getPrefix() != null) {
|
||||
if (getPrefix() != null) {
|
||||
final int width = getStringWidth(getPrefix());
|
||||
final Rectangle b = buttonSize();
|
||||
|
||||
if (width >= b.x) {
|
||||
tip = translateN(name);
|
||||
return translateN(name);
|
||||
}
|
||||
}
|
||||
|
||||
return tip;
|
||||
return null;
|
||||
}
|
||||
|
||||
public void drawPrefix() {
|
||||
|
||||
@@ -29,6 +29,18 @@ public class OptionCycled extends OptionButton {
|
||||
return prefixed ? translateN(name) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip() {
|
||||
String tooltip = name + "." + value() + ".tip";
|
||||
String s = translateN(tooltip);
|
||||
|
||||
if (!s.equals(namespaced(tooltip))) {
|
||||
return s;
|
||||
}
|
||||
|
||||
return super.getTooltip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
return cycle();
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package codechicken.nei.config;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
|
||||
public class OptionIntegerField extends OptionTextField {
|
||||
|
||||
public final int min;
|
||||
public final int max;
|
||||
public static final long UNSIGNED_INT_MAX = 0xFFFFFFFFL;
|
||||
|
||||
public OptionIntegerField(String name, int min, int max) {
|
||||
public final long min;
|
||||
public final long max;
|
||||
|
||||
public OptionIntegerField(String name, long min, long max) {
|
||||
super(name);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
@@ -15,12 +19,26 @@ public class OptionIntegerField extends OptionTextField {
|
||||
this(name, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMaxInputWidth() {
|
||||
|
||||
if (renderTag().getValue().startsWith("0x")) {
|
||||
return GuiDraw.getStringWidth("0x" + Long.toHexString(this.max).toUpperCase()) + 32;
|
||||
}
|
||||
|
||||
return GuiDraw.getStringWidth(String.valueOf(this.max)) + 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInput(String s) {
|
||||
if (s.length() == 0) return true;
|
||||
if (s.isEmpty()) return true;
|
||||
|
||||
try {
|
||||
Integer.parseInt(s);
|
||||
if (s.startsWith("0x")) {
|
||||
Long.parseUnsignedLong(s.substring(2), 16);
|
||||
} else {
|
||||
Integer.parseInt(s);
|
||||
}
|
||||
return true;
|
||||
} catch (NumberFormatException nfe) {
|
||||
return false;
|
||||
@@ -29,9 +47,15 @@ public class OptionIntegerField extends OptionTextField {
|
||||
|
||||
@Override
|
||||
public boolean isValidValue(String s) {
|
||||
if (s.length() == 0 || !isValidInput(s)) return false;
|
||||
if (s.isEmpty() || !isValidInput(s)) return false;
|
||||
long i = 0;
|
||||
|
||||
int i = Integer.parseInt(s);
|
||||
return i >= min && i <= max;
|
||||
if (s.startsWith("0x")) {
|
||||
i = Long.parseUnsignedLong(s.substring(2), 16);
|
||||
} else {
|
||||
i = Integer.parseInt(s);
|
||||
}
|
||||
|
||||
return i >= this.min && i <= this.max;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import java.awt.Rectangle;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
|
||||
public class OptionKeyBind extends OptionButton {
|
||||
@@ -122,8 +121,12 @@ public class OptionKeyBind extends OptionButton {
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
final int metahash = Math.max(editing ? NEIClientUtils.getMetaHash() : getValue(), 0);
|
||||
return NEIClientConfig.getKeyName(metahash, useHash, editing);
|
||||
|
||||
if (editing) {
|
||||
return NEIClientUtils.getKeyHashName(NEIClientUtils.getMetaHash());
|
||||
}
|
||||
|
||||
return NEIClientUtils.getKeyName(Math.max(getValue(), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,51 +1,36 @@
|
||||
package codechicken.nei.config;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawString;
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.TextField;
|
||||
import codechicken.nei.config.GuiOptionList.OptionScrollSlot;
|
||||
|
||||
public class OptionTextField extends Option {
|
||||
|
||||
private boolean focused = false;
|
||||
private TextField textField = new TextField("test") {
|
||||
protected final TextField textField = new TextField("test") {
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
if (focused() && isValidValue(text())) if (!defaulting() || !text().equals(getTag().getValue())) // don't
|
||||
// override
|
||||
// global
|
||||
// if text
|
||||
// hasn't
|
||||
// changed
|
||||
getTag().setValue(text());
|
||||
{
|
||||
this.h = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean focused() {
|
||||
return focused;
|
||||
public void onTextChange(String oldText) {
|
||||
// don't override global if text hasn't changed
|
||||
if (focused() && isValidValue(text()) && (!defaulting() || !text().equals(getTag().getValue()))) {
|
||||
getTag().setValue(text());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
if (!focus && !isValidValue(text())) setText(renderTag().getValue());
|
||||
|
||||
focused = focus;
|
||||
super.setFocus(focus);
|
||||
}
|
||||
};
|
||||
|
||||
public OptionTextField(String name) {
|
||||
super(name);
|
||||
textField.h = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded(OptionScrollSlot slot) {
|
||||
super.onAdded(slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,11 +43,16 @@ public class OptionTextField extends Option {
|
||||
return translateN(name);
|
||||
}
|
||||
|
||||
protected int getMaxInputWidth() {
|
||||
return slot.slotWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
drawString(getPrefix(), 10, 6, -1);
|
||||
GuiDraw.drawString(getPrefix(), 10, 6, -1);
|
||||
|
||||
textField.w = slot.slotWidth() - getStringWidth(getPrefix()) - 16;
|
||||
textField.w = Math
|
||||
.max(60, Math.min(getMaxInputWidth(), slot.slotWidth() - GuiDraw.getStringWidth(getPrefix())) - 16);
|
||||
textField.x = slot.slotWidth() - textField.w;
|
||||
textField.draw(mousex, mousey);
|
||||
}
|
||||
@@ -86,7 +76,7 @@ public class OptionTextField extends Option {
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> currenttip) {
|
||||
if (new Rectangle4i(10, 0, textField.x - 10, 20).contains(mousex, mousey)) {
|
||||
String tip = translateN(name + ".tip");
|
||||
if (!tip.equals(name + ".tip")) currenttip.add(tip);
|
||||
if (!tip.equals(namespaced(name + ".tip"))) currenttip.add(tip);
|
||||
}
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ public class OptionToggleButton extends OptionButton {
|
||||
return renderTag().getBooleanValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
return translateN(name + (state() ? ".true" : ".false"));
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ public class OptionUtilities extends OptionStringSet {
|
||||
x += 24;
|
||||
LayoutManager.drawIcon(x + 4, 4, new Image(132, 12, 12, 12));
|
||||
x += 24;
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
ItemStack sword = new ItemStack(Items.diamond_sword);
|
||||
@@ -55,5 +57,6 @@ public class OptionUtilities extends OptionStringSet {
|
||||
GuiContainerManager.drawItem(x + 2, 2, new ItemStack(Items.potionitem));
|
||||
x += 24;
|
||||
GuiContainerManager.drawItem(x + 2, 2, new ItemStack(Blocks.stone));
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ public abstract class RegistryDumper<T> extends DataDumper {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<String[]> dump(int mode) {
|
||||
LinkedList<String[]> list = new LinkedList<>();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.LayoutManager;
|
||||
|
||||
public abstract class CheckboxButton extends Button {
|
||||
|
||||
protected boolean checked = false;
|
||||
|
||||
public CheckboxButton(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
this.onChange();
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return this.checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
int tex;
|
||||
|
||||
if ((this.state & 0x3) == 2) {
|
||||
tex = 0;
|
||||
} else if ((this.state & 0x4) == 0 && contains(mousex, mousey) || (this.state & 0x3) == 1) {
|
||||
tex = 2;
|
||||
} else {
|
||||
tex = 1;
|
||||
}
|
||||
|
||||
int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0;
|
||||
LayoutManager.drawButtonBackground(x, y, w, h, true, isChecked() ? 0 : tex);
|
||||
drawStringC(getRenderLabel(), x + w / 2, y + (h - 8) / 2, colour);
|
||||
}
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
this.setChecked(!isChecked());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void onChange();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.core.gui.GuiCCButton;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.config.GuiOptionPane;
|
||||
import codechicken.nei.config.Option;
|
||||
|
||||
public class GuiPresetList extends GuiOptionPane {
|
||||
|
||||
private final Option opt;
|
||||
protected static final int SLOT_HEIGHT = 24;
|
||||
protected static final int BUTTON_HEIGHT = 20;
|
||||
protected GuiCCButton createButton;
|
||||
protected GuiCCButton toggleButton;
|
||||
protected int sortingItemIndex = -1;
|
||||
|
||||
public GuiPresetList(Option opt) {
|
||||
this.opt = opt;
|
||||
this.createButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.new"))
|
||||
.setActionCommand("create");
|
||||
this.toggleButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.toggle"))
|
||||
.setActionCommand("toggle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
this.createButton.width = getStringWidth(this.createButton.text) + 15;
|
||||
this.createButton.x = width - this.createButton.width - 15;
|
||||
|
||||
this.toggleButton.width = getStringWidth(this.toggleButton.text) + 15;
|
||||
this.toggleButton.x = width - this.toggleButton.width - 15 - this.createButton.width - 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWidgets() {
|
||||
super.addWidgets();
|
||||
add(this.createButton);
|
||||
add(this.toggleButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(String ident, Object... params) {
|
||||
super.actionPerformed(ident, params);
|
||||
|
||||
if (ident.equals("create")) {
|
||||
cretePreset();
|
||||
}
|
||||
|
||||
if (ident.equals("toggle")) {
|
||||
togglePreset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseMovedOrUp(int x, int y, int button) {
|
||||
super.mouseMovedOrUp(x, y, button);
|
||||
|
||||
if (sortingItemIndex >= 0) {
|
||||
PresetsList.savePresets();
|
||||
} else if (button == 0) {
|
||||
int slot = getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != -1) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
int mx = x - w.x;
|
||||
|
||||
if (mx <= BUTTON_HEIGHT) {
|
||||
Preset preset = PresetsList.presets.get(slot);
|
||||
preset.enabled = !preset.enabled;
|
||||
PresetsList.savePresets();
|
||||
} else if (mx >= 26 && mx <= w.width - 26 * 2) {
|
||||
openPreset(slot);
|
||||
} else if (mx >= w.width - BUTTON_HEIGHT) {
|
||||
PresetsList.presets.remove(slot);
|
||||
PresetsList.savePresets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortingItemIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClickMove(int x, int y, int button, long time) {
|
||||
super.mouseClickMove(x, y, button, time);
|
||||
|
||||
if (sortingItemIndex == -1) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
int mx = x - w.x;
|
||||
|
||||
if (mx >= 26 && mx <= w.width - 26 * 2) {
|
||||
sortingItemIndex = getSlotMouseOver(x, y);
|
||||
} else {
|
||||
sortingItemIndex = -2;
|
||||
}
|
||||
} else if (sortingItemIndex >= 0) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
|
||||
if (y >= w.y && y <= w.y + w.height) {
|
||||
int my = y + pane.scrolledPixels() - w.y;
|
||||
int slot = my / SLOT_HEIGHT;
|
||||
|
||||
if (my % SLOT_HEIGHT < BUTTON_HEIGHT && slot < PresetsList.presets.size()
|
||||
&& slot != -1
|
||||
&& slot != sortingItemIndex) {
|
||||
PresetsList.presets.add(slot, PresetsList.presets.remove(sortingItemIndex));
|
||||
sortingItemIndex = slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int getSlotMouseOver(int x, int y) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
|
||||
if (x >= w.x && x <= w.x + w.width && y >= w.y && y <= w.y + w.height) {
|
||||
int my = y + pane.scrolledPixels() - w.y;
|
||||
int slot = my / SLOT_HEIGHT;
|
||||
|
||||
if (my % SLOT_HEIGHT < BUTTON_HEIGHT && slot < PresetsList.presets.size()) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void cretePreset() {
|
||||
Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, -1));
|
||||
}
|
||||
|
||||
protected void togglePreset() {
|
||||
boolean enabled = PresetsList.presets.stream().noneMatch(g -> g.enabled);
|
||||
|
||||
for (Preset preset : PresetsList.presets) {
|
||||
preset.enabled = enabled;
|
||||
}
|
||||
|
||||
PresetsList.savePresets();
|
||||
}
|
||||
|
||||
protected void openPreset(int slot) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, slot));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int contentHeight() {
|
||||
return PresetsList.presets.size() * SLOT_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawContent(int mx, int my, float frame) {
|
||||
int scrolled = pane.scrolledPixels();
|
||||
Rectangle w = pane.windowBounds();
|
||||
int y = 0;
|
||||
|
||||
for (int slot = 0; slot < PresetsList.presets.size(); ++slot) {
|
||||
|
||||
if (y + SLOT_HEIGHT > scrolled && y < scrolled + w.height) {
|
||||
|
||||
if (sortingItemIndex != slot) {
|
||||
drawSlot(w, slot, w.x, w.y + y - scrolled, mx, my - y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
y += SLOT_HEIGHT;
|
||||
}
|
||||
|
||||
if (sortingItemIndex >= 0) {
|
||||
drawSlot(w, sortingItemIndex, w.x, w.y + my - scrolled - BUTTON_HEIGHT / 2, mx, my - y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawSlot(Rectangle w, int slot, int x, int y, int mx, int my) {
|
||||
final Rectangle4i delete = new Rectangle4i(x + w.width - BUTTON_HEIGHT, y, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||
final Rectangle4i enabled = new Rectangle4i(x, y, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||
final Rectangle4i option = new Rectangle4i(x + 26, y, w.width - 26 * 2, BUTTON_HEIGHT);
|
||||
|
||||
final int enabledState = y + my >= w.y && y + my <= w.y + w.height && enabled.contains(x + mx, y + my) ? 2 : 1;
|
||||
final int optionState = y + my >= w.y && y + my <= w.y + w.height && option.contains(x + mx, y + my) ? 2 : 1;
|
||||
final int deleteState = y + my >= w.y && y + my <= w.y + w.height && delete.contains(x + mx, y + my) ? 2 : 1;
|
||||
final Preset preset = PresetsList.presets.get(slot);
|
||||
|
||||
final String displayName = preset.name;
|
||||
final String modeName;
|
||||
|
||||
switch (preset.mode) {
|
||||
case HIDE:
|
||||
modeName = EnumChatFormatting.GOLD + NEIClientUtils.translate("presets.mode.hide.char")
|
||||
+ EnumChatFormatting.RESET;
|
||||
break;
|
||||
case REMOVE:
|
||||
modeName = EnumChatFormatting.RED + NEIClientUtils.translate("presets.mode.remove.char")
|
||||
+ EnumChatFormatting.RESET;
|
||||
break;
|
||||
case GROUP:
|
||||
modeName = EnumChatFormatting.AQUA + NEIClientUtils.translate("presets.mode.group.char")
|
||||
+ EnumChatFormatting.RESET;
|
||||
break;
|
||||
default:
|
||||
modeName = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
// enabled icon
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(
|
||||
enabled.x,
|
||||
enabled.y,
|
||||
enabled.w,
|
||||
enabled.h,
|
||||
true,
|
||||
preset.enabled ? 0 : enabledState);
|
||||
GuiDraw.drawString("✔", enabled.x + 7, enabled.y + 6, enabledState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
|
||||
// preset name
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(option.x, option.y, option.w, option.h, true, optionState);
|
||||
GuiDraw.drawString("⋮⋮", option.x + 4, option.y + 5, optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
GuiDraw.drawString(
|
||||
NEIClientUtils.cropText(this.fontRendererObj, modeName + " " + displayName, option.w - 16),
|
||||
option.x + 6 + 4,
|
||||
option.y + 6,
|
||||
optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
|
||||
// remove icon
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(delete.x, delete.y, delete.w, delete.h, true, deleteState);
|
||||
GuiDraw.drawString("✕", delete.x + 7, delete.y + 6, deleteState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiScreen getParentScreen() {
|
||||
return opt.slot.getGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return opt.translateN(opt.name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.Rectangle;
|
||||
|
||||
import codechicken.core.gui.GuiScreenWidget;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.config.OptionScrollPane;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class GuiPresetSettings extends GuiScreenWidget {
|
||||
|
||||
protected final Preset preset;
|
||||
protected final GuiScreen parent;
|
||||
protected final int slotIndex;
|
||||
|
||||
public int marginleft;
|
||||
public int margintop;
|
||||
public int marginright;
|
||||
public int marginbottom;
|
||||
|
||||
protected LeftPanel leftPanel;
|
||||
protected RightPanel rightPanel;
|
||||
|
||||
protected Button backButton;
|
||||
protected Button saveButton;
|
||||
|
||||
public GuiPresetSettings(GuiScreen parent, int slotIndex) {
|
||||
this.parent = parent;
|
||||
this.setMargins(6, 20, 6, 30);
|
||||
|
||||
this.slotIndex = slotIndex;
|
||||
|
||||
if (slotIndex == -1) {
|
||||
preset = new Preset();
|
||||
} else {
|
||||
preset = PresetsList.presets.get(slotIndex).copy();
|
||||
}
|
||||
|
||||
leftPanel = new LeftPanel(preset) {
|
||||
|
||||
@Override
|
||||
protected void onItemsChanges() {
|
||||
leftPanel.grid.restartFilter();
|
||||
}
|
||||
};
|
||||
rightPanel = new RightPanel(preset, slotIndex) {
|
||||
|
||||
@Override
|
||||
protected void onItemsChanges() {
|
||||
leftPanel.grid.restartFilter();
|
||||
}
|
||||
};
|
||||
|
||||
backButton = new Button(NEIClientUtils.translate("options.back")) {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(parent);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
saveButton = new Button(NEIClientUtils.translate("options.save")) {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (state == 0) {
|
||||
|
||||
if (slotIndex == -1) {
|
||||
PresetsList.presets.add(preset);
|
||||
} else {
|
||||
PresetsList.presets.set(slotIndex, preset);
|
||||
}
|
||||
|
||||
PresetsList.savePresets();
|
||||
Minecraft.getMinecraft().displayGuiScreen(parent);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
add(this.leftPanel);
|
||||
add(this.rightPanel);
|
||||
}
|
||||
|
||||
protected void setMargins(int left, int top, int right, int bottom) {
|
||||
this.marginleft = left;
|
||||
this.margintop = top;
|
||||
this.marginright = right;
|
||||
this.marginbottom = bottom;
|
||||
}
|
||||
|
||||
protected Rectangle windowBounds() {
|
||||
return new Rectangle(
|
||||
this.marginleft,
|
||||
this.margintop,
|
||||
this.width - this.marginleft - this.marginright,
|
||||
this.height - this.margintop - this.marginbottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesGuiPauseGame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
final Rectangle bounds = windowBounds();
|
||||
final int panelWidth = bounds.getWidth() * 2 / 5;
|
||||
|
||||
this.leftPanel.setSize(bounds.getX(), bounds.getY() + 4, panelWidth, bounds.getHeight() - 6);
|
||||
this.rightPanel.setSize(
|
||||
bounds.getX() + bounds.getWidth() - panelWidth,
|
||||
bounds.getY() + 4,
|
||||
panelWidth,
|
||||
bounds.getHeight() - 6);
|
||||
|
||||
final int w = Math.min(200, width - 40);
|
||||
|
||||
backButton.w = w / 2 - 3;
|
||||
backButton.h = 20;
|
||||
backButton.x = (width - w) / 2;
|
||||
backButton.y = height - 25;
|
||||
|
||||
saveButton.state = preset.name.isEmpty() || preset.mode == null || preset.items.isEmpty() ? 2 : 0;
|
||||
|
||||
saveButton.w = w / 2 - 3;
|
||||
saveButton.h = 20;
|
||||
saveButton.x = width / 2 + 3;
|
||||
saveButton.y = height - 25;
|
||||
|
||||
super.updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize() {
|
||||
this.guiLeft = this.guiTop = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mousex, int mousey, float f) {
|
||||
Rectangle bounds = windowBounds();
|
||||
drawDefaultBackground();
|
||||
|
||||
drawOverlay(bounds.getY(), bounds.getHeight(), width, zLevel);
|
||||
drawCenteredString(
|
||||
Minecraft.getMinecraft().fontRenderer,
|
||||
NEIClientUtils.translate(this.slotIndex == -1 ? "presets.create" : "presets.update"),
|
||||
width / 2,
|
||||
6,
|
||||
-1);
|
||||
|
||||
backButton.draw(mousex, mousey);
|
||||
saveButton.draw(mousex, mousey);
|
||||
|
||||
super.drawScreen(mousex, mousey, f);
|
||||
|
||||
List<String> tooltip = new LinkedList<>();
|
||||
tooltip = leftPanel.handleTooltip(mousex, mousey, tooltip);
|
||||
tooltip = rightPanel.handleTooltip(mousex, mousey, tooltip);
|
||||
|
||||
GuiContainerManager.drawPagedTooltip(Minecraft.getMinecraft().fontRenderer, mousex + 12, mousey - 12, tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int button) {
|
||||
super.mouseClicked(x, y, button);
|
||||
|
||||
if (backButton.contains(x, y)) {
|
||||
backButton.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (saveButton.contains(x, y)) {
|
||||
saveButton.handleClick(x, y, button);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawOverlay(int y, int height, int screenwidth, float zLevel) {
|
||||
OptionScrollPane.drawOverlayTex(0, 0, screenwidth, y, zLevel);
|
||||
OptionScrollPane.drawOverlayTex(0, y + height, screenwidth, screenwidth - y - height, zLevel);
|
||||
OptionScrollPane.drawOverlayGrad(0, screenwidth, y, y + 4, zLevel);
|
||||
OptionScrollPane.drawOverlayGrad(0, screenwidth, y + height, y + height - 4, zLevel);
|
||||
}
|
||||
|
||||
public static void drawOverlayTex(int x, int y, int w, int h, float zLevel) {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(Gui.optionsBackground);
|
||||
Tessellator t = Tessellator.instance;
|
||||
t.startDrawingQuads();
|
||||
t.addVertexWithUV(x, y, zLevel, 0, 0);
|
||||
t.addVertexWithUV(x, y + h, zLevel, 0, h / 16D);
|
||||
t.addVertexWithUV(x + w, y + h, zLevel, w / 16D, h / 16D);
|
||||
t.addVertexWithUV(x + w, y, zLevel, w / 16D, 0);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
public static void drawOverlayGrad(int x1, int x2, int y1, int y2, float zLevel) {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
Tessellator t = Tessellator.instance;
|
||||
t.startDrawingQuads();
|
||||
t.setColorRGBA_I(0, 255);
|
||||
t.addVertex(x2, y1, zLevel);
|
||||
t.addVertex(x1, y1, zLevel);
|
||||
t.setColorRGBA_I(0, 0);
|
||||
t.addVertex(x1, y2, zLevel);
|
||||
t.addVertex(x2, y2, zLevel);
|
||||
t.draw();
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.gui.GuiWidget;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.Label;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.PresetsList.PresetMode;
|
||||
import codechicken.nei.TextField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class LeftPanel extends GuiWidget {
|
||||
|
||||
protected static class MouseSelection {
|
||||
|
||||
public int startX = -1;
|
||||
public int startY = -1;
|
||||
public int startIndex = -1;
|
||||
public int endIndex = -1;
|
||||
|
||||
public Set<ItemStack> items = new HashSet<>();
|
||||
|
||||
public MouseSelection(int slotIndex, Rectangle4i rec) {
|
||||
endIndex = slotIndex;
|
||||
startIndex = slotIndex;
|
||||
startX = rec.x;
|
||||
startY = rec.y;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final int INPUT_HEIGHT = 20;
|
||||
|
||||
public final PresetItemsGrid grid = new PresetItemsGrid() {
|
||||
|
||||
@Override
|
||||
protected ItemFilter getFilter() {
|
||||
Set<String> identifiers = preset.items;
|
||||
return item -> identifiers.contains(Preset.getIdentifier(item));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(ItemStack stack) {
|
||||
return mouseSelection != null && mouseSelection.items.contains(stack);
|
||||
}
|
||||
};
|
||||
|
||||
protected Label nameLabel = new Label(NEIClientUtils.translate("presets.name"), false);
|
||||
|
||||
protected TextField nameField = new TextField("name") {
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
preset.name = text();
|
||||
}
|
||||
};
|
||||
|
||||
protected Label modeLabel = new Label(NEIClientUtils.translate("presets.mode"), false);
|
||||
|
||||
protected CheckboxButton modeHide;
|
||||
protected CheckboxButton modeRemove;
|
||||
protected CheckboxButton modeGroup;
|
||||
|
||||
protected CheckboxButton enabledButton;
|
||||
|
||||
protected final Preset preset;
|
||||
protected MouseSelection mouseSelection;
|
||||
|
||||
public LeftPanel(Preset preset) {
|
||||
super(1, 0, 2, 2);
|
||||
|
||||
this.preset = preset;
|
||||
|
||||
nameField.setText(preset.name);
|
||||
|
||||
modeHide = new CheckboxButton(NEIClientUtils.translate("presets.mode.hide")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.HIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.HIDE : null;
|
||||
}
|
||||
};
|
||||
|
||||
modeRemove = new CheckboxButton(NEIClientUtils.translate("presets.mode.remove")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.REMOVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.REMOVE : null;
|
||||
}
|
||||
};
|
||||
|
||||
modeGroup = new CheckboxButton(NEIClientUtils.translate("presets.mode.group")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.GROUP : null;
|
||||
}
|
||||
};
|
||||
|
||||
enabledButton = new CheckboxButton(NEIClientUtils.translate("presets.enabled")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.enabled = this.checked;
|
||||
}
|
||||
};
|
||||
|
||||
grid.restartFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
grid.mouseClicked(x, y, button);
|
||||
|
||||
if (modeHide.contains(x, y)) {
|
||||
modeHide.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (modeRemove.contains(x, y)) {
|
||||
modeRemove.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (modeGroup.contains(x, y)) {
|
||||
modeGroup.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (enabledButton.contains(x, y)) {
|
||||
enabledButton.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (nameField.contains(x, y)) {
|
||||
nameField.handleClick(x, y, button);
|
||||
} else {
|
||||
nameField.onGuiClick(x, y);
|
||||
}
|
||||
|
||||
if (mouseSelection == null && button == 0) {
|
||||
ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null) {
|
||||
mouseSelection = new MouseSelection(slot.slotIndex, grid.getItemRect(slot.slotIndex));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void onItemsChanges() {}
|
||||
|
||||
@Override
|
||||
public void mouseMovedOrUp(int x, int y, int button) {
|
||||
nameField.mouseUp(x, y, button);
|
||||
|
||||
if (mouseSelection != null && button == 0) {
|
||||
ItemPanelSlot hoverSlot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseSelection.startIndex) {
|
||||
preset.items.remove(Preset.getIdentifier(hoverSlot.item));
|
||||
} else if (!mouseSelection.items.isEmpty()) {
|
||||
|
||||
for (ItemStack stack : mouseSelection.items) {
|
||||
preset.items.remove(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
mouseSelection = null;
|
||||
onItemsChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int x, int y, int button, long time) {
|
||||
nameField.mouseDragged(x, y, button, time);
|
||||
|
||||
if (mouseSelection != null && button == 0) {
|
||||
final ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null && slot.slotIndex != mouseSelection.endIndex) {
|
||||
mouseSelection.endIndex = slot.slotIndex;
|
||||
mouseSelection.items.clear();
|
||||
|
||||
final Rectangle4i rec = grid.getItemRect(slot.slotIndex);
|
||||
final Rectangle4i sel = new Rectangle4i(
|
||||
Math.min(rec.x, mouseSelection.startX),
|
||||
Math.min(rec.y, mouseSelection.startY),
|
||||
Math.max(rec.x, mouseSelection.startX) - Math.min(rec.x, mouseSelection.startX),
|
||||
Math.max(rec.y, mouseSelection.startY) - Math.min(rec.y, mouseSelection.startY));
|
||||
|
||||
for (int ix = sel.x; ix <= sel.x + sel.w; ix += ItemsGrid.SLOT_SIZE) {
|
||||
for (int iy = sel.y; iy <= sel.y + sel.h; iy += ItemsGrid.SLOT_SIZE) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(ix, iy);
|
||||
|
||||
if (over != null) {
|
||||
mouseSelection.items.add(over.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
int CHECKBOX_WIDTH = (this.width - 12) / 3;
|
||||
nameLabel.x = this.x + 2;
|
||||
nameLabel.y = this.y + 4;
|
||||
nameLabel.w = this.width;
|
||||
nameLabel.h = 10;
|
||||
|
||||
nameField.x = this.x;
|
||||
nameField.y = nameLabel.y + nameLabel.h;
|
||||
nameField.w = this.width - CHECKBOX_WIDTH - 6;
|
||||
nameField.h = INPUT_HEIGHT;
|
||||
|
||||
enabledButton.x = nameField.x + nameField.w + 6;
|
||||
enabledButton.y = nameField.y;
|
||||
enabledButton.w = CHECKBOX_WIDTH;
|
||||
enabledButton.h = INPUT_HEIGHT;
|
||||
|
||||
modeLabel.x = this.x + 2;
|
||||
modeLabel.y = nameField.y + nameField.h + 6;
|
||||
modeLabel.w = this.width;
|
||||
modeLabel.h = 10;
|
||||
|
||||
modeHide.w = modeRemove.w = modeGroup.w = CHECKBOX_WIDTH;
|
||||
modeHide.h = modeRemove.h = modeGroup.h = INPUT_HEIGHT;
|
||||
modeHide.y = modeRemove.y = modeGroup.y = modeLabel.y + modeLabel.h;
|
||||
|
||||
modeHide.x = this.x + 1;
|
||||
modeRemove.x = modeHide.x + modeHide.w + 6;
|
||||
modeGroup.x = modeRemove.x + modeRemove.w + 6;
|
||||
|
||||
grid.setGridSize(
|
||||
this.x + 1,
|
||||
modeHide.y + modeHide.h + 2,
|
||||
this.width - 2,
|
||||
this.height - (modeHide.y + modeHide.h + 2));
|
||||
grid.refresh(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
nameLabel.draw(mousex, mousey);
|
||||
nameField.draw(mousex, mousey);
|
||||
|
||||
modeLabel.draw(mousex, mousey);
|
||||
modeHide.draw(mousex, mousey);
|
||||
modeRemove.draw(mousex, mousey);
|
||||
modeGroup.draw(mousex, mousey);
|
||||
|
||||
enabledButton.draw(mousex, mousey);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glPopMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> tooltip) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (over != null) {
|
||||
tooltip = GuiContainerManager.itemDisplayNameMultiline(over.item, null, true);
|
||||
|
||||
synchronized (GuiContainerManager.tooltipHandlers) {
|
||||
for (IContainerTooltipHandler handler : GuiContainerManager.tooltipHandlers) {
|
||||
tooltip = handler.handleItemTooltip(null, over.item, mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tooltip.isEmpty()) {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
}
|
||||
|
||||
} else if (modeHide.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.hide.tip"));
|
||||
} else if (modeRemove.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.remove.tip"));
|
||||
} else if (modeGroup.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.group.tip"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int keycode) {
|
||||
nameField.handleKeyPress(keycode, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseScrolled(int x, int y, int scroll) {
|
||||
if (grid.contains(x, y)) {
|
||||
grid.shiftPage(-scroll);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemSorter;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.Label;
|
||||
import codechicken.nei.RestartableTask;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public abstract class PresetItemsGrid extends ItemsGrid {
|
||||
|
||||
protected static final int BUTTON_SIZE = 16;
|
||||
|
||||
public Button pagePrev;
|
||||
public Label pageLabel;
|
||||
public Button pageNext;
|
||||
|
||||
protected ArrayList<ItemStack> newItems;
|
||||
|
||||
protected final RestartableTask updateFilter = new RestartableTask("NEI Presets Item Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ArrayList<ItemStack> filtered;
|
||||
ItemFilter filter = getFilter();
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> ItemList.items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
filtered = new ArrayList<>();
|
||||
e.printStackTrace();
|
||||
stop();
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(filtered);
|
||||
if (interrupted()) return;
|
||||
updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
|
||||
protected PresetItemsGrid() {
|
||||
|
||||
pageLabel = new Label("0/0", true);
|
||||
|
||||
pagePrev = new Button("<") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
setPage(0);
|
||||
} else {
|
||||
shiftPage(-1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
pageNext = new Button(">") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
setPage(getNumPages() - 1);
|
||||
} else {
|
||||
shiftPage(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
protected String getLabelText() {
|
||||
return String.format("%d/%d", getPage(), Math.max(1, getNumPages()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGridSize(int mleft, int mtop, int w, int h) {
|
||||
pageLabel.text = getLabelText();
|
||||
|
||||
pagePrev.w = pageNext.w = BUTTON_SIZE;
|
||||
pagePrev.h = pageNext.h = BUTTON_SIZE;
|
||||
pagePrev.y = pageNext.y = mtop;
|
||||
|
||||
pagePrev.x = mleft;
|
||||
pageNext.x = mleft + w - pageNext.w;
|
||||
|
||||
pageLabel.x = mleft + w / 2;
|
||||
pageLabel.y = pagePrev.y + 5;
|
||||
|
||||
super.setGridSize(mleft, mtop + BUTTON_SIZE + 2, w, h - BUTTON_SIZE - 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
pagePrev.draw(mousex, mousey);
|
||||
pageNext.draw(mousex, mousey);
|
||||
pageLabel.draw(mousex, mousey);
|
||||
|
||||
super.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
|
||||
if (pagePrev.contains(x, y)) {
|
||||
pagePrev.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (pageNext.contains(x, y)) {
|
||||
pageNext.handleClick(x, y, button);
|
||||
}
|
||||
}
|
||||
|
||||
public void restartFilter() {
|
||||
updateFilter.restart();
|
||||
}
|
||||
|
||||
protected void updateItemList(List<ItemStack> newItems) {
|
||||
this.newItems = new ArrayList<>(newItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(GuiContainer gui) {
|
||||
|
||||
if (this.newItems != null) {
|
||||
this.realItems = this.newItems;
|
||||
this.newItems = null;
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
super.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (isSelected(getItem(slotIdx))) {
|
||||
GuiDraw.drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
} else {
|
||||
super.beforeDrawSlot(focused, slotIdx, rect);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean isSelected(ItemStack stack);
|
||||
|
||||
protected abstract ItemFilter getFilter();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.gui.GuiWidget;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.CollapsibleItems;
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.SearchField.GuiSearchField;
|
||||
import codechicken.nei.TextField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class RightPanel extends GuiWidget {
|
||||
|
||||
protected static class MouseSelection {
|
||||
|
||||
public int startX = -1;
|
||||
public int startY = -1;
|
||||
public int startIndex = -1;
|
||||
public int endIndex = -1;
|
||||
|
||||
public Set<ItemStack> items = new HashSet<>();
|
||||
public boolean append = true;
|
||||
|
||||
public MouseSelection(int slotIndex, Rectangle4i rec, boolean ppnd) {
|
||||
append = ppnd;
|
||||
endIndex = slotIndex;
|
||||
startIndex = slotIndex;
|
||||
startX = rec.x;
|
||||
startY = rec.y;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract static class PresetSearchField extends TextField {
|
||||
|
||||
private static final TextHistory history = new TextHistory();
|
||||
|
||||
protected PresetSearchField(String ident) {
|
||||
super(ident);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (!text().isEmpty()) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (!focused() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterText(String s) {
|
||||
return EnumChatFormatting.getTextWithoutFormattingCodes(s);
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
final boolean previousFocus = field.isFocused();
|
||||
|
||||
if (previousFocus != focus) {
|
||||
history.add(text());
|
||||
}
|
||||
|
||||
super.setFocus(focus);
|
||||
}
|
||||
|
||||
private boolean handleNavigateHistory(TextHistory.Direction direction) {
|
||||
if (focused()) {
|
||||
return history.get(direction, text()).map(newText -> {
|
||||
setText(newText);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static final int INPUT_HEIGHT = 20;
|
||||
protected static final int BUTTON_SIZE = 16;
|
||||
|
||||
protected final PresetItemsGrid grid = new PresetItemsGrid() {
|
||||
|
||||
@Override
|
||||
protected ItemFilter getFilter() {
|
||||
AllMultiItemFilter filter = new AllMultiItemFilter(searchField.getFilter());
|
||||
|
||||
if (enabledPresets.isChecked()) {
|
||||
AllMultiItemFilter andFilter = new AllMultiItemFilter();
|
||||
AnyMultiItemFilter orFilter = new AnyMultiItemFilter();
|
||||
Set<String> identifiers = PresetsList.presets.stream().flatMap(p -> p.items.stream())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
andFilter.filters.add(item -> !identifiers.contains(Preset.getIdentifier(item)));
|
||||
andFilter.filters.add(new NegatedItemFilter(CollapsibleItems.getItemFilter()));
|
||||
|
||||
if (slotIndex != -1) {
|
||||
orFilter.filters.add(PresetsList.presets.get(slotIndex));
|
||||
}
|
||||
|
||||
orFilter.filters.add(andFilter);
|
||||
filter.filters.add(orFilter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(ItemStack stack) {
|
||||
|
||||
if (mouseSelection != null && mouseSelection.items.contains(stack)) {
|
||||
return mouseSelection.append;
|
||||
}
|
||||
|
||||
return preset.items.contains(Preset.getIdentifier(stack));
|
||||
}
|
||||
};
|
||||
|
||||
protected CheckboxButton enabledPresets;
|
||||
|
||||
protected final Preset preset;
|
||||
protected final int slotIndex;
|
||||
protected MouseSelection mouseSelection;
|
||||
|
||||
protected final PresetSearchField searchField = new PresetSearchField("preset-search") {
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
final String newText = text();
|
||||
if (!newText.equals(oldText)) {
|
||||
grid.restartFilter();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public RightPanel(Preset preset, int slotIndex) {
|
||||
super(1, 0, 2, 2);
|
||||
|
||||
this.slotIndex = slotIndex;
|
||||
this.preset = preset;
|
||||
|
||||
enabledPresets = new CheckboxButton(NEIClientUtils.translate("presets.filter")) {
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
grid.restartFilter();
|
||||
}
|
||||
};
|
||||
|
||||
enabledPresets.setChecked(true);
|
||||
|
||||
grid.restartFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
grid.mouseClicked(x, y, button);
|
||||
|
||||
if (enabledPresets.contains(x, y)) {
|
||||
enabledPresets.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (searchField.contains(x, y)) {
|
||||
searchField.handleClick(x, y, button);
|
||||
} else {
|
||||
searchField.onGuiClick(x, y);
|
||||
}
|
||||
|
||||
if (mouseSelection == null && (button == 0 || button == 1)) {
|
||||
ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null) {
|
||||
mouseSelection = new MouseSelection(slot.slotIndex, grid.getItemRect(slot.slotIndex), button == 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void onItemsChanges() {}
|
||||
|
||||
@Override
|
||||
public void mouseMovedOrUp(int x, int y, int button) {
|
||||
searchField.mouseUp(x, y, button);
|
||||
|
||||
if (mouseSelection != null && (button == 0 || button == 1)) {
|
||||
ItemPanelSlot hoverSlot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseSelection.startIndex) {
|
||||
setHidden(hoverSlot.item, button == 0);
|
||||
} else if (!mouseSelection.items.isEmpty()) {
|
||||
|
||||
for (ItemStack stack : mouseSelection.items) {
|
||||
hideItem(stack, mouseSelection.append);
|
||||
}
|
||||
}
|
||||
|
||||
mouseSelection = null;
|
||||
onItemsChanges();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void setHidden(final ItemStack stack, final boolean append) {
|
||||
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
final List<ItemStack> items = grid.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (stack.getItem().equals(items.get(i).getItem())) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (NEIClientUtils.controlKey()) {
|
||||
final String modId = getModId(stack);
|
||||
|
||||
if (modId == null) {
|
||||
hideItem(stack, append);
|
||||
} else {
|
||||
final List<ItemStack> items = grid.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
final String mod = getModId(items.get(i));
|
||||
if (mod != null && mod.equals(modId)) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
hideItem(stack, append);
|
||||
}
|
||||
}
|
||||
|
||||
protected void hideItem(final ItemStack stack, boolean append) {
|
||||
if (append) {
|
||||
preset.items.add(Preset.getIdentifier(stack));
|
||||
} else {
|
||||
preset.items.remove(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getModId(final ItemStack stack) {
|
||||
try {
|
||||
return GameRegistry.findUniqueIdentifierFor(stack.getItem()).modId;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int x, int y, int button, long time) {
|
||||
searchField.mouseDragged(x, y, button, time);
|
||||
|
||||
if (mouseSelection != null && (button == 0 || button == 1)) {
|
||||
final ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null && slot.slotIndex != mouseSelection.endIndex) {
|
||||
mouseSelection.endIndex = slot.slotIndex;
|
||||
mouseSelection.items.clear();
|
||||
|
||||
final Rectangle4i rec = grid.getItemRect(slot.slotIndex);
|
||||
final Rectangle4i sel = new Rectangle4i(
|
||||
Math.min(rec.x, mouseSelection.startX),
|
||||
Math.min(rec.y, mouseSelection.startY),
|
||||
Math.max(rec.x, mouseSelection.startX) - Math.min(rec.x, mouseSelection.startX),
|
||||
Math.max(rec.y, mouseSelection.startY) - Math.min(rec.y, mouseSelection.startY));
|
||||
|
||||
for (int ix = sel.x; ix <= sel.x + sel.w; ix += ItemsGrid.SLOT_SIZE) {
|
||||
for (int iy = sel.y; iy <= sel.y + sel.h; iy += ItemsGrid.SLOT_SIZE) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(ix, iy);
|
||||
|
||||
if (over != null) {
|
||||
mouseSelection.items.add(over.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
enabledPresets.w = 20;
|
||||
enabledPresets.h = INPUT_HEIGHT;
|
||||
enabledPresets.x = this.x;
|
||||
enabledPresets.y = this.y + this.height - 2 - INPUT_HEIGHT;
|
||||
|
||||
searchField.w = this.width - enabledPresets.w - 3;
|
||||
searchField.h = INPUT_HEIGHT;
|
||||
searchField.x = enabledPresets.x + enabledPresets.w + 3;
|
||||
searchField.y = enabledPresets.y;
|
||||
|
||||
grid.setGridSize(this.x, this.y, this.width, searchField.y - this.y);
|
||||
grid.refresh(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
enabledPresets.draw(mousex, mousey);
|
||||
searchField.draw(mousex, mousey);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glPopMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> tooltip) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (over != null) {
|
||||
tooltip = GuiContainerManager.itemDisplayNameMultiline(over.item, null, true);
|
||||
|
||||
synchronized (GuiContainerManager.tooltipHandlers) {
|
||||
for (IContainerTooltipHandler handler : GuiContainerManager.tooltipHandlers) {
|
||||
tooltip = handler.handleItemTooltip(null, over.item, mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tooltip.isEmpty()) {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
}
|
||||
|
||||
} else if (enabledPresets.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.filter.tip"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int keycode) {
|
||||
searchField.handleKeyPress(keycode, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseScrolled(int x, int y, int scroll) {
|
||||
if (grid.contains(x, y)) {
|
||||
grid.shiftPage(-scroll);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import cpw.mods.fml.common.eventhandler.Event;
|
||||
* <br>
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class NEIRegisterHandlerInfosEvent extends Event {
|
||||
|
||||
public void registerHandlerInfo(HandlerInfo info) {
|
||||
|
||||
@@ -4,15 +4,21 @@ import static codechicken.lib.gui.GuiDraw.drawMultilineTip;
|
||||
import static codechicken.lib.gui.GuiDraw.fontRenderer;
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
import static codechicken.lib.gui.GuiDraw.renderEngine;
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -20,8 +26,12 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.entity.RenderItem;
|
||||
import net.minecraft.client.resources.IResourceManager;
|
||||
import net.minecraft.client.resources.IResourceManagerReloadListener;
|
||||
import net.minecraft.client.resources.SimpleReloadableResourceManager;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -34,12 +44,26 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIModContainer;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.ReadableNumberConverter;
|
||||
import codechicken.nei.util.RenderTooltipEventHelper;
|
||||
|
||||
public class GuiContainerManager {
|
||||
|
||||
private static class ResourcePackReloaded implements IResourceManagerReloadListener {
|
||||
|
||||
@Override
|
||||
public void onResourceManagerReload(IResourceManager p_110549_1_) {
|
||||
renderingErrorItems.clear();
|
||||
ItemList.loadItems.restart();
|
||||
}
|
||||
}
|
||||
|
||||
public GuiContainer window;
|
||||
|
||||
public static RenderItem drawItems = new RenderItem();
|
||||
@@ -138,13 +162,15 @@ public class GuiContainerManager {
|
||||
namelist = stack.getTooltip(
|
||||
Minecraft.getMinecraft().thePlayer,
|
||||
includeHandlers && Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
|
||||
} catch (Throwable ignored) {}
|
||||
} catch (Throwable ignored) {
|
||||
namelist = new ArrayList<>();
|
||||
}
|
||||
|
||||
if (namelist == null) namelist = new ArrayList<>();
|
||||
|
||||
if (namelist.size() == 0) namelist.add("Unnamed");
|
||||
|
||||
if (namelist.get(0) == null || namelist.get(0).equals("")) namelist.set(0, "Unnamed");
|
||||
if (namelist.isEmpty()) {
|
||||
namelist.add("Unnamed");
|
||||
} else if (namelist.get(0) == null || namelist.get(0).isEmpty()) {
|
||||
namelist.set(0, "Unnamed");
|
||||
}
|
||||
|
||||
if (includeHandlers) {
|
||||
for (IContainerTooltipHandler handler : tooltipHandlers) {
|
||||
@@ -217,8 +243,17 @@ public class GuiContainerManager {
|
||||
* @return The first line of the multiline display name.
|
||||
*/
|
||||
public static String itemDisplayNameShort(ItemStack itemstack) {
|
||||
List<String> list = itemDisplayNameMultiline(itemstack, null, false);
|
||||
return list.get(0);
|
||||
|
||||
try {
|
||||
List<String> namelist = itemstack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
|
||||
|
||||
if (!namelist.isEmpty() && !"".equals(namelist.get(0))) {
|
||||
return itemstack.getRarity().rarityColor.toString() + namelist.get(0) + EnumChatFormatting.RESET;
|
||||
}
|
||||
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return "Unnamed";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,105 +263,126 @@ public class GuiContainerManager {
|
||||
* @param itemstack The stack to get the name for
|
||||
* @return The multiline display name of this item separated by '#'
|
||||
*/
|
||||
@Deprecated
|
||||
public static String concatenatedDisplayName(ItemStack itemstack, boolean includeHandlers) {
|
||||
List<String> list = itemDisplayNameMultiline(itemstack, null, includeHandlers);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
StringJoiner sb = new StringJoiner("#");
|
||||
|
||||
for (String name : list) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append("#");
|
||||
if (!name.isEmpty()) {
|
||||
sb.add(name);
|
||||
}
|
||||
sb.append(name);
|
||||
}
|
||||
|
||||
return EnumChatFormatting.getTextWithoutFormattingCodes(sb.toString());
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack) {
|
||||
drawItem(i, j, itemstack, false);
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack) {
|
||||
drawItem(offsetX, offsetY, itemstack, false);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, boolean smallAmount) {
|
||||
drawItem(i, j, itemstack, smallAmount, null);
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack, boolean smallAmount) {
|
||||
drawItem(offsetX, offsetY, itemstack, smallAmount, null);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, boolean smallAmount, String stackSize) {
|
||||
drawItem(i, j, itemstack, getFontRenderer(itemstack), smallAmount, stackSize);
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack, boolean smallAmount, String quantity) {
|
||||
drawItem(offsetX, offsetY, itemstack, getFontRenderer(itemstack), smallAmount, quantity);
|
||||
}
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer) {
|
||||
drawItem(i, j, itemstack, fontRenderer, false, null);
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack, FontRenderer fontRenderer) {
|
||||
drawItem(offsetX, offsetY, itemstack, fontRenderer, false, null);
|
||||
}
|
||||
|
||||
private static int modelviewDepth = -1;
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static final ItemStackSet renderingErrorItems = new ItemStackSet();
|
||||
|
||||
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer, boolean smallAmount,
|
||||
String stackSize) {
|
||||
enable3DRender();
|
||||
// for lighting correction
|
||||
boolean glRescale = GL11.glGetBoolean(GL12.GL_RESCALE_NORMAL);
|
||||
public static void drawItem(int offsetX, int offsetY, ItemStack itemstack, FontRenderer fontRenderer,
|
||||
boolean smallAmount, String quantity) {
|
||||
|
||||
float zLevel = drawItems.zLevel += 100F;
|
||||
try {
|
||||
drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, i, j);
|
||||
safeItemRenderContext(itemstack, offsetX, offsetY, fontRenderer, () -> {
|
||||
float scale = smallAmount ? 0.5f : 1f;
|
||||
String stackSize = quantity;
|
||||
|
||||
if (stackSize == null) {
|
||||
stackSize = itemstack.stackSize > 1 ? String.valueOf(itemstack.stackSize) : "";
|
||||
}
|
||||
if (itemstack.stackSize > 1) {
|
||||
stackSize = ReadableNumberConverter.INSTANCE.toWideReadableForm(itemstack.stackSize);
|
||||
|
||||
if (smallAmount) {
|
||||
if (stackSize.length() == 3) {
|
||||
scale = 0.8f;
|
||||
} else if (stackSize.length() == 4) {
|
||||
scale = 0.6f;
|
||||
} else if (stackSize.length() > 4) {
|
||||
scale = 0.5f;
|
||||
}
|
||||
|
||||
if (!stackSize.isEmpty()) {
|
||||
drawBigStackSize(i, j, stackSize);
|
||||
} else {
|
||||
stackSize = "";
|
||||
}
|
||||
|
||||
// stackSize = "". it needed for correct draw item with alpha and blend
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, "");
|
||||
} else {
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, i, j, stackSize);
|
||||
}
|
||||
|
||||
if (!checkMatrixStack()) throw new IllegalStateException("Modelview matrix stack too deep");
|
||||
if (Tessellator.instance.isDrawing) throw new IllegalStateException("Still drawing");
|
||||
} catch (Exception e) {
|
||||
NEIClientUtils.reportErrorBuffered(e, stackTraces, itemstack);
|
||||
drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, itemstack, offsetX, offsetY);
|
||||
|
||||
restoreMatrixStack();
|
||||
if (Tessellator.instance.isDrawing) Tessellator.instance.draw();
|
||||
if (scale != 1f && !stackSize.isEmpty()) {
|
||||
drawBigStackSize(offsetX, offsetY, stackSize, scale);
|
||||
stackSize = "";
|
||||
}
|
||||
|
||||
drawItems.zLevel = zLevel;
|
||||
drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), i, j);
|
||||
}
|
||||
|
||||
if (glRescale) {
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
} else {
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
}
|
||||
|
||||
enable2DRender();
|
||||
drawItems.zLevel = zLevel - 100;
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, itemstack, offsetX, offsetY, stackSize);
|
||||
});
|
||||
}
|
||||
|
||||
// copy from appeng.client.render.AppEngRenderItem
|
||||
protected static void drawBigStackSize(int offsetX, int offsetY, String stackSize) {
|
||||
final float scaleFactor = fontRenderer.getUnicodeFlag() ? 0.85f : 0.5f;
|
||||
final float inverseScaleFactor = 1.0f / scaleFactor;
|
||||
protected static void drawBigStackSize(int offsetX, int offsetY, String stackSize, float scale) {
|
||||
final float inverseScaleFactor = 1.0f / scale;
|
||||
|
||||
enable2DRender();
|
||||
GL11.glScaled(scaleFactor, scaleFactor, scaleFactor);
|
||||
GL11.glScaled(scale, scale, scale);
|
||||
|
||||
final int X = (int) (((float) offsetX + 16.0f - fontRenderer.getStringWidth(stackSize) * scaleFactor)
|
||||
* inverseScaleFactor);
|
||||
final int Y = (int) (((float) offsetY + 16.0f - 7.0f * scaleFactor) * inverseScaleFactor);
|
||||
final int X = (int) ((offsetX + 16.0f - fontRenderer.getStringWidth(stackSize) * scale) * inverseScaleFactor);
|
||||
final int Y = (int) ((offsetY + 16.0f - 7.0f * scale) * inverseScaleFactor);
|
||||
fontRenderer.drawStringWithShadow(stackSize, X, Y, 16777215);
|
||||
|
||||
GL11.glScaled(inverseScaleFactor, inverseScaleFactor, inverseScaleFactor);
|
||||
enable3DRender();
|
||||
}
|
||||
|
||||
private static void safeItemRenderContext(ItemStack stack, int x, int y, FontRenderer fontRenderer,
|
||||
Runnable callback) {
|
||||
float zLevel = drawItems.zLevel += 100F;
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
enable3DRender();
|
||||
|
||||
if (!renderingErrorItems.contains(stack)) {
|
||||
try {
|
||||
callback.run();
|
||||
|
||||
if (!checkMatrixStack()) throw new IllegalStateException("Modelview matrix stack too deep");
|
||||
if (Tessellator.instance.isDrawing) throw new IllegalStateException("Still drawing");
|
||||
} catch (Exception e) {
|
||||
NEIClientUtils.reportErrorBuffered(e, stackTraces, stack);
|
||||
|
||||
restoreMatrixStack();
|
||||
if (Tessellator.instance.isDrawing) Tessellator.instance.draw();
|
||||
|
||||
drawItems.zLevel = zLevel;
|
||||
drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), x, y);
|
||||
renderingErrorItems.add(stack);
|
||||
}
|
||||
} else {
|
||||
drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), x, y);
|
||||
}
|
||||
|
||||
GL11.glPopAttrib();
|
||||
drawItems.zLevel = zLevel - 100;
|
||||
}
|
||||
|
||||
public static void registerReloadResourceListener() {
|
||||
if (Minecraft.getMinecraft().getResourceManager() instanceof SimpleReloadableResourceManager manager) {
|
||||
manager.registerReloadListener(new ResourcePackReloaded());
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableMatrixStackLogging() {
|
||||
modelviewDepth = GL11.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH);
|
||||
}
|
||||
@@ -363,9 +419,9 @@ public class GuiContainerManager {
|
||||
|
||||
public GuiContainerManager(GuiContainer screen) {
|
||||
window = screen;
|
||||
if (screen instanceof IContainerTooltipHandler) {
|
||||
if (screen instanceof IContainerTooltipHandler tooltipHandler) {
|
||||
instanceTooltipHandlers = Collections.synchronizedList(new LinkedList<>());
|
||||
instanceTooltipHandlers.add((IContainerTooltipHandler) screen);
|
||||
instanceTooltipHandlers.add(tooltipHandler);
|
||||
instanceTooltipHandlers.addAll(tooltipHandlers);
|
||||
} else instanceTooltipHandlers = tooltipHandlers;
|
||||
}
|
||||
@@ -497,8 +553,8 @@ public class GuiContainerManager {
|
||||
tooltip = handler.handleTooltip(window, mousex, mousey, tooltip);
|
||||
}
|
||||
|
||||
ItemStack stack = getStackMouseOver(window);
|
||||
if (tooltip.isEmpty() && shouldShowTooltip(window)) { // mouseover tip, not holding an item
|
||||
ItemStack stack = getStackMouseOver(window);
|
||||
font = getFontRenderer(stack);
|
||||
if (stack != null) {
|
||||
tooltip = itemDisplayNameMultiline(stack, window, true);
|
||||
@@ -511,15 +567,120 @@ public class GuiContainerManager {
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip.size() > 0) tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
if (!tooltip.isEmpty()) tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
|
||||
drawPagedTooltip(font, mousex + 12, mousey - 12, tooltip);
|
||||
if (shouldShowTooltip(window)) {
|
||||
List<String> hotkeystips = collectHotkeyTips(mousex, mousey);
|
||||
|
||||
if (!hotkeystips.isEmpty()) {
|
||||
|
||||
if (tooltip.isEmpty()) {
|
||||
tooltip.addAll(hotkeystips);
|
||||
} else {
|
||||
tooltip.addAll(1, hotkeystips);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIModContainer.isGTNHLibLoaded() && !tooltip.isEmpty()) {
|
||||
if (RenderTooltipEventHelper.post(stack, this.window, mousex, mousey, font)) {
|
||||
return;
|
||||
}
|
||||
Consumer<List<String>> alternativeRenderer = RenderTooltipEventHelper.getAlternativeRenderer();
|
||||
if (alternativeRenderer == null) {
|
||||
drawPagedTooltip(
|
||||
RenderTooltipEventHelper.getFont(),
|
||||
RenderTooltipEventHelper.getX() + 12,
|
||||
RenderTooltipEventHelper.getY() - 12,
|
||||
tooltip);
|
||||
} else {
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GuiDraw.gui.incZLevel(300.0f);
|
||||
alternativeRenderer.accept(tooltip);
|
||||
GuiDraw.gui.incZLevel(-300.0f);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
}
|
||||
RenderTooltipEventHelper.flush();
|
||||
} else {
|
||||
drawPagedTooltip(font, mousex + 12, mousey - 12, tooltip);
|
||||
}
|
||||
|
||||
for (IContainerDrawHandler drawHandler : drawHandlers) {
|
||||
drawHandler.postRenderTooltips(window, mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> collectHotkeyTips(int mousex, int mousey) {
|
||||
Map<String, String> hotkeys = new HashMap<>();
|
||||
|
||||
synchronized (instanceTooltipHandlers) {
|
||||
for (IContainerTooltipHandler handler : instanceTooltipHandlers) {
|
||||
hotkeys = handler.handleHotkeys(window, mousex, mousey, hotkeys);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hotkeys.isEmpty()) {
|
||||
List<String> hotkeystips = new ArrayList<>();
|
||||
|
||||
if (!NEIClientUtils.altKey()) {
|
||||
hotkeystips.add(
|
||||
EnumChatFormatting.GRAY + translate(
|
||||
"showHotkeys",
|
||||
EnumChatFormatting.GOLD + translate("key.alt") + EnumChatFormatting.GRAY));
|
||||
} else {
|
||||
Map<String, List<String>> messages = new HashMap<>();
|
||||
hotkeys.remove(null);
|
||||
hotkeys.remove("");
|
||||
|
||||
for (Map.Entry<String, String> entry : hotkeys.entrySet()) {
|
||||
messages.computeIfAbsent(entry.getValue(), m -> new ArrayList<>()).add(entry.getKey());
|
||||
}
|
||||
|
||||
for (List<String> keys : messages.values()) {
|
||||
Collections.sort(keys, (a, b) -> {
|
||||
if (a.length() != b.length()) {
|
||||
return Integer.compare(a.length(), b.length());
|
||||
}
|
||||
return a.compareTo(b);
|
||||
});
|
||||
}
|
||||
|
||||
messages.entrySet().stream().sorted((a, b) -> {
|
||||
String sa = String.join("/", a.getValue());
|
||||
String sb = String.join("/", b.getValue());
|
||||
|
||||
if (sa.length() != sb.length()) {
|
||||
return Integer.compare(sa.length(), sb.length());
|
||||
}
|
||||
|
||||
return sa.compareTo(sb);
|
||||
}).map(entry -> getHotkeyTip(entry.getValue(), entry.getKey()))
|
||||
.collect(Collectors.toCollection(() -> hotkeystips));
|
||||
|
||||
hotkeystips.set(
|
||||
hotkeystips.size() - 1,
|
||||
hotkeystips.get(hotkeystips.size() - 1) + GuiDraw.TOOLTIP_LINESPACE);
|
||||
}
|
||||
|
||||
return hotkeystips;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private String getHotkeyTip(List<String> keys, String message) {
|
||||
return EnumChatFormatting.GOLD
|
||||
+ String.join(EnumChatFormatting.DARK_GRAY + " / " + EnumChatFormatting.GOLD, keys)
|
||||
+ EnumChatFormatting.GRAY
|
||||
+ " - "
|
||||
+ message
|
||||
+ EnumChatFormatting.RESET;
|
||||
}
|
||||
|
||||
private static int tooltipPage;
|
||||
|
||||
public static void drawPagedTooltip(FontRenderer font, int x, int y, List<String> list) {
|
||||
@@ -532,7 +693,19 @@ public class GuiContainerManager {
|
||||
"inventory.tooltip.page",
|
||||
tooltipPage + 1,
|
||||
tooltips.size(),
|
||||
NEIClientConfig.getKeyName(NEIClientConfig.getKeyBinding("gui.next_tooltip"), true)));
|
||||
NEIClientConfig.getKeyName("gui.next_tooltip")));
|
||||
}
|
||||
if (NEIModContainer.isGTNHLibLoaded()) {
|
||||
drawMultilineTip(
|
||||
font,
|
||||
x,
|
||||
y,
|
||||
tooltips.get(tooltipPage),
|
||||
RenderTooltipEventHelper.getBackgroundStart(),
|
||||
RenderTooltipEventHelper.getBackgroundEnd(),
|
||||
RenderTooltipEventHelper.getBorderStart(),
|
||||
RenderTooltipEventHelper.getBorderEnd());
|
||||
return;
|
||||
}
|
||||
drawMultilineTip(font, x, y, tooltips.get(tooltipPage));
|
||||
}
|
||||
@@ -563,6 +736,7 @@ public class GuiContainerManager {
|
||||
}
|
||||
|
||||
public static boolean shouldShowTooltip(GuiContainer window) {
|
||||
if (window == null) return false;
|
||||
for (IContainerObjectHandler handler : objectHandlers) if (!handler.shouldShowTooltip(window)) return false;
|
||||
|
||||
return window.mc.thePlayer.inventory.getItemStack() == null;
|
||||
@@ -621,7 +795,7 @@ public class GuiContainerManager {
|
||||
if (Keyboard.getEventKeyState() || (k == 0 && Character.isDefined(c))) {
|
||||
try {
|
||||
keyTyped(c, k);
|
||||
} catch (java.lang.IndexOutOfBoundsException e) {
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
System.err.println("Caught out of bounds exception pressing " + c + " " + k);
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -644,38 +818,17 @@ public class GuiContainerManager {
|
||||
* Delegate for changing item rendering for certain slots. Eg. Shrinking text for large itemstacks
|
||||
*/
|
||||
public void drawSlotItem(Slot slot, ItemStack stack, int x, int y, String quantity) {
|
||||
// for lighting correction
|
||||
boolean glRescale = GL11.glGetBoolean(GL12.GL_RESCALE_NORMAL);
|
||||
float zLevel = drawItems.zLevel += 100F;
|
||||
|
||||
try {
|
||||
if (window instanceof IGuiSlotDraw) {
|
||||
((IGuiSlotDraw) window).drawSlotItem(slot, stack, x, y, quantity);
|
||||
} else {
|
||||
|
||||
if (quantity == null) {
|
||||
quantity = stack != null && stack.stackSize > 1 ? String.valueOf(stack.stackSize) : "";
|
||||
}
|
||||
|
||||
drawItems.renderItemAndEffectIntoGUI(fontRenderer, renderEngine, stack, x, y);
|
||||
drawItems.renderItemOverlayIntoGUI(fontRenderer, renderEngine, stack, x, y, quantity);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NEIClientUtils.reportErrorBuffered(e, stackTraces, stack);
|
||||
|
||||
restoreMatrixStack();
|
||||
if (Tessellator.instance.isDrawing) Tessellator.instance.draw();
|
||||
|
||||
drawItems.zLevel = zLevel;
|
||||
drawItems.renderItemIntoGUI(fontRenderer, renderEngine, new ItemStack(Blocks.fire), x, y);
|
||||
if (window instanceof IGuiSlotDraw) {
|
||||
safeItemRenderContext(
|
||||
stack,
|
||||
x,
|
||||
y,
|
||||
fontRenderer,
|
||||
() -> ((IGuiSlotDraw) window).drawSlotItem(slot, stack, x, y, quantity));
|
||||
} else if (stack != null) {
|
||||
drawItem(x, y, stack, false, quantity);
|
||||
}
|
||||
|
||||
if (glRescale) {
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
} else {
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
}
|
||||
drawItems.zLevel = zLevel - 100;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
final class HideousLinkedList<E> extends LinkedList<E> {
|
||||
|
||||
private static final long serialVersionUID = -8504433551965776915L;
|
||||
private final List<E> backing;
|
||||
|
||||
HideousLinkedList(List<E> backing) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei.guihook;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -15,36 +16,54 @@ public interface IContainerTooltipHandler {
|
||||
* Use this to add tooltips for other objects. If the current tip has lines in it after this call, the item tootip
|
||||
* will not be handled. GuiContainerManager.shouldShowTooltip is not enforced here. It is recommended that you make
|
||||
* this check yourself
|
||||
*
|
||||
*
|
||||
* @param gui An instance of the currentscreen
|
||||
* @param mousex The x position of the mouse in pixels from left
|
||||
* @param mousey The y position of the mouse in pixels from top
|
||||
* @param currenttip A list of strings, representing each line of the current tooltip as modified by other handlers
|
||||
* @return The modified list. NOTE: Do not return null
|
||||
*/
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip);
|
||||
default List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this for modifying the multiline display name of an item which may not necessarily be under the mouse.
|
||||
* GuiContainerManager.shouldShowTooltip is enforced here.
|
||||
*
|
||||
*
|
||||
* @param gui An instance of the currentscreen. If only general information about the item is wanted (Eg.
|
||||
* potion effects) then this may be null.
|
||||
* @param itemstack The ItemStack under the mouse
|
||||
* @param currenttip A list of strings, representing each line of the current tooltip as modified by other handlers
|
||||
* @return The modified list. NOTE: Do not return null
|
||||
*/
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip);
|
||||
default List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this for modifying the tooltips of items that are under the mouse. GuiContainerManager.shouldShowTooltip is
|
||||
* enforced here.
|
||||
*
|
||||
*
|
||||
* @param gui An instance of the currentscreen
|
||||
* @param itemstack The ItemStack under the mouse
|
||||
* @param currenttip A list of strings, representing each line of the current tooltip as modified by other handlers
|
||||
* @return The modified list. NOTE: Do not return null
|
||||
*/
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip);
|
||||
default List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to specify a list of hotkeys that will work when hovering over an element that is under the mouse
|
||||
* pointer.
|
||||
*
|
||||
* @param gui An instance of the currentscreen
|
||||
* @param mousex The x position of the mouse in pixels from left
|
||||
* @param mousey The y position of the mouse in pixels from top
|
||||
*/
|
||||
default Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
return hotkeys;
|
||||
}
|
||||
}
|
||||
@@ -25,16 +25,16 @@ public class BookmarkRecipeId {
|
||||
|
||||
for (Object pos : stacks) {
|
||||
|
||||
if (pos instanceof PositionedStack) {
|
||||
pos = StackInfo.getItemStackWithMinimumDamage(((PositionedStack) pos).items);
|
||||
if (pos instanceof PositionedStack item) {
|
||||
pos = StackInfo.getItemStackWithMinimumDamage(item.items);
|
||||
}
|
||||
|
||||
if (pos instanceof ItemStack) {
|
||||
pos = StackInfo.itemStackToNBT((ItemStack) pos);
|
||||
if (pos instanceof ItemStack item) {
|
||||
pos = StackInfo.itemStackToNBT(item);
|
||||
}
|
||||
|
||||
if (pos instanceof NBTTagCompound) {
|
||||
ingredients.add((NBTTagCompound) pos);
|
||||
if (pos instanceof NBTTagCompound item) {
|
||||
ingredients.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,19 @@ import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.nei.FastTransferManager;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
@SuppressWarnings("rawtypes, unchecked")
|
||||
public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
|
||||
public static Class gtItem;
|
||||
private static Class<?> gtItem;
|
||||
|
||||
static {
|
||||
try {
|
||||
gtItem = Class.forName("gregtech.api.items.GT_MetaBase_Item");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
gtItem = null;
|
||||
final ClassLoader loader = DefaultOverlayHandler.class.getClassLoader();
|
||||
gtItem = ReflectionHelper
|
||||
.getClass(loader, "gregtech.api.items.MetaBaseItem", "gregtech.api.items.GT_MetaBase_Item");
|
||||
} catch (Exception ignored) {
|
||||
/* Do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,20 +87,21 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
if (quantity != 0) moveIngredients(gui, assignedIngredients, quantity);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean clearIngredients(GuiContainer gui, List<PositionedStack> ingreds) {
|
||||
for (PositionedStack pstack : ingreds) for (Slot slot : (List<Slot>) gui.inventorySlots.inventorySlots)
|
||||
if (slot.xDisplayPosition == pstack.relx + offsetx && slot.yDisplayPosition == pstack.rely + offsety) {
|
||||
if (!slot.getHasStack()) continue;
|
||||
for (PositionedStack pstack : ingreds) {
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) {
|
||||
if (slot.xDisplayPosition == pstack.relx + offsetx && slot.yDisplayPosition == pstack.rely + offsety) {
|
||||
if (!slot.getHasStack()) continue;
|
||||
|
||||
FastTransferManager.clickSlot(gui, slot.slotNumber, 0, 1);
|
||||
if (slot.getHasStack()) return false;
|
||||
FastTransferManager.clickSlot(gui, slot.slotNumber, 0, 1);
|
||||
if (slot.getHasStack()) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void moveIngredients(GuiContainer gui, List<IngredientDistribution> assignedIngredients, int quantity) {
|
||||
for (IngredientDistribution distrib : assignedIngredients) {
|
||||
if (distrib.slots.length == 0) continue;
|
||||
@@ -112,7 +115,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
int slotTransferred = 0;
|
||||
int slotTransferCap = pstack.getMaxStackSize();
|
||||
|
||||
for (Slot slot : (List<Slot>) gui.inventorySlots.inventorySlots) {
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) {
|
||||
if (!slot.getHasStack() || !canMoveFrom(slot, gui)) continue;
|
||||
|
||||
ItemStack stack = slot.getStack();
|
||||
@@ -181,7 +184,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
assignedSlots.add(new LinkedList<>());
|
||||
}
|
||||
|
||||
while (avaliableSlots.size() > 0 && remainingIngreds.size() > 0) {
|
||||
while (!avaliableSlots.isEmpty() && !remainingIngreds.isEmpty()) {
|
||||
for (Iterator<Integer> iterator = remainingIngreds.iterator(); iterator.hasNext();) {
|
||||
int i = iterator.next();
|
||||
boolean assigned = false;
|
||||
@@ -199,8 +202,9 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (!assigned || istack.numSlots * istack.stack.getMaxStackSize() >= istack.invAmount)
|
||||
if (!assigned || istack.numSlots * istack.stack.getMaxStackSize() >= istack.invAmount) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,9 +249,8 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return assignedIngredients;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void findInventoryQuantities(GuiContainer gui, List<DistributedIngred> ingredStacks) {
|
||||
for (Slot slot : (List<Slot>) gui.inventorySlots.inventorySlots) /* work out how much we have to go round */ {
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) /* work out how much we have to go round */ {
|
||||
if (slot.getHasStack() && canMoveFrom(slot, gui)) {
|
||||
ItemStack pstack = slot.getStack();
|
||||
DistributedIngred istack = findIngred(ingredStacks, pstack);
|
||||
@@ -272,13 +275,12 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return slot.inventory instanceof InventoryPlayer;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Slot[][] mapIngredSlots(GuiContainer gui, List<PositionedStack> ingredients) {
|
||||
Slot[][] recipeSlotList = new Slot[ingredients.size()][];
|
||||
for (int i = 0; i < ingredients.size(); i++) /* identify slots */ {
|
||||
LinkedList<Slot> recipeSlots = new LinkedList<>();
|
||||
PositionedStack pstack = ingredients.get(i);
|
||||
for (Slot slot : (List<Slot>) gui.inventorySlots.inventorySlots) {
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) {
|
||||
if (slot.xDisplayPosition == pstack.relx + offsetx && slot.yDisplayPosition == pstack.rely + offsety) {
|
||||
recipeSlots.add(slot);
|
||||
break;
|
||||
|
||||
@@ -70,8 +70,7 @@ public class FillFluidContainerHandler extends INEIGuiAdapter {
|
||||
}
|
||||
|
||||
return FluidContainerRegistry.fillFluidContainer(fluidStack, draggedStack);
|
||||
} else if (draggedStack.getItem() instanceof IFluidContainerItem) {
|
||||
IFluidContainerItem item = (IFluidContainerItem) draggedStack.getItem();
|
||||
} else if (draggedStack.getItem() instanceof IFluidContainerItem item) {
|
||||
|
||||
if (item.getCapacity(draggedStack) > 0) {
|
||||
item.drain(draggedStack, item.getCapacity(draggedStack), true);
|
||||
|
||||
@@ -51,7 +51,6 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler {
|
||||
return NEIClientUtils.translate("recipe.fuel");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void loadAllSmelting() {
|
||||
// Note: Not safe as written for parallelStream
|
||||
final Map<ItemStack, ItemStack> smeltingRecipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting()
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.Set;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
@@ -24,6 +25,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
|
||||
public static ArrayList<ICraftingHandler> craftinghandlers = new ArrayList<>();
|
||||
public static ArrayList<ICraftingHandler> serialCraftingHandlers = new ArrayList<>();
|
||||
private static Set<String> existingHandlers = new HashSet<>();
|
||||
|
||||
public static boolean openRecipeGui(String outputId, Object... results) {
|
||||
return createRecipeGui(outputId, true, results) != null;
|
||||
@@ -34,12 +36,14 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
final BookmarkRecipeId recipeId;
|
||||
|
||||
if ("item".equals(outputId)) {
|
||||
results = Arrays.asList(results).stream().map(rslt -> normalizeItemStack((ItemStack) rslt)).toArray();
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
results[i] = normalizeItemStack((ItemStack) results[i]);
|
||||
}
|
||||
recipeId = getRecipeId(mc.currentScreen, (ItemStack) results[0]);
|
||||
} else if ("recipeId".equals(outputId)) {
|
||||
recipeId = (BookmarkRecipeId) results[1];
|
||||
} else {
|
||||
recipeId = getCurrentRecipe(mc.currentScreen);
|
||||
recipeId = getCurrentRecipeId(mc.currentScreen);
|
||||
}
|
||||
|
||||
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers(outputId, results);
|
||||
@@ -83,7 +87,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
public static ArrayList<ICraftingHandler> getCraftingHandlers(String outputId, Object... results) {
|
||||
ArrayList<ICraftingHandler> craftinghandlers = GuiCraftingRecipe.craftinghandlers;
|
||||
ArrayList<ICraftingHandler> serialCraftingHandlers = GuiCraftingRecipe.serialCraftingHandlers;
|
||||
Function<ICraftingHandler, ICraftingHandler> recipeHandlerFunction;
|
||||
UnaryOperator<ICraftingHandler> recipeHandlerFunction;
|
||||
|
||||
if ("recipeId".equals(outputId)) {
|
||||
ItemStack stack = (ItemStack) results[0];
|
||||
@@ -103,7 +107,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
"outputId: " + outputId,
|
||||
"results: " + Arrays.toString(results));
|
||||
|
||||
return recipeQuery.runWithProfiling("recipe.concurrent.crafting");
|
||||
return recipeQuery.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
|
||||
}
|
||||
|
||||
private static ArrayList<ICraftingHandler> filterByHandlerName(ArrayList<ICraftingHandler> craftinghandlers,
|
||||
@@ -134,7 +138,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
}
|
||||
}
|
||||
|
||||
final Point mouseover = getMousePosition();
|
||||
final Point mouseover = GuiDraw.getMousePosition();
|
||||
ItemPanelSlot panelSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseover.x, mouseover.y);
|
||||
|
||||
if (panelSlot != null) {
|
||||
@@ -153,12 +157,24 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
public static void registerRecipeHandler(ICraftingHandler handler) {
|
||||
final String handlerId = handler.getHandlerId();
|
||||
|
||||
if (craftinghandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId))
|
||||
|| serialCraftingHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)))
|
||||
if (existingHandlers.contains(handlerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (existingHandlers) {
|
||||
existingHandlers.add(handlerId);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.serialHandlers.contains(handlerId)) {
|
||||
synchronized (serialCraftingHandlers) {
|
||||
serialCraftingHandlers.add(handler);
|
||||
}
|
||||
} else {
|
||||
synchronized (craftinghandlers) {
|
||||
craftinghandlers.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.serialHandlers.contains(handlerId)) serialCraftingHandlers.add(handler);
|
||||
else craftinghandlers.add(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.BookmarkPanel.BookmarkRecipe;
|
||||
import codechicken.nei.GuiNEIButton;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemsTooltipLineHandler;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import cpw.mods.fml.common.eventhandler.Cancelable;
|
||||
|
||||
public class GuiOverlayButton extends GuiNEIButton {
|
||||
|
||||
public static class UpdateOverlayButtonsEvent extends GuiScreenEvent {
|
||||
|
||||
public List<GuiOverlayButton> buttonList;
|
||||
|
||||
public UpdateOverlayButtonsEvent(GuiRecipe<?> gui, List<GuiOverlayButton> buttonList) {
|
||||
super(gui);
|
||||
this.buttonList = new ArrayList<>(buttonList);
|
||||
}
|
||||
|
||||
@Cancelable
|
||||
public static class Pre extends UpdateOverlayButtonsEvent {
|
||||
|
||||
public int xOffset;
|
||||
public int yOffset;
|
||||
public int height;
|
||||
public HandlerInfo handlerInfo;
|
||||
|
||||
public Pre(GuiRecipe<?> gui, int xOffset, int yOffset, int height, HandlerInfo handlerInfo) {
|
||||
super(gui, new ArrayList<>());
|
||||
this.xOffset = xOffset;
|
||||
this.yOffset = yOffset;
|
||||
this.height = height;
|
||||
this.handlerInfo = handlerInfo;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Post extends UpdateOverlayButtonsEvent {
|
||||
|
||||
public Post(GuiRecipe<?> gui, List<GuiOverlayButton> buttonList) {
|
||||
super(gui, buttonList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ItemOverlayFormat {
|
||||
|
||||
BACKGROUND,
|
||||
ICON;
|
||||
|
||||
public static ItemOverlayFormat from(int overlay) {
|
||||
return overlay == 2 ? ItemOverlayFormat.BACKGROUND : ItemOverlayFormat.ICON;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemOverlayState {
|
||||
|
||||
protected PositionedStack slot;
|
||||
protected boolean isPresent;
|
||||
|
||||
public ItemOverlayState(PositionedStack slot, boolean isPresent) {
|
||||
this.slot = slot;
|
||||
this.isPresent = isPresent;
|
||||
}
|
||||
|
||||
public boolean isPresent() {
|
||||
return this.isPresent;
|
||||
}
|
||||
|
||||
public PositionedStack getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
|
||||
public void draw(ItemOverlayFormat format) {
|
||||
LayoutManager.drawItemPresenceOverlay(
|
||||
this.slot.relx,
|
||||
this.slot.rely,
|
||||
this.isPresent,
|
||||
format == ItemOverlayFormat.BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int OVERLAY_BUTTON_ID_START = 4;
|
||||
|
||||
public final GuiContainer firstGui;
|
||||
public final IRecipeHandler handler;
|
||||
public final int recipeIndex;
|
||||
|
||||
protected ItemsTooltipLineHandler missedMaterialsTooltipLineHandler;
|
||||
|
||||
protected final IOverlayHandler overlayHandler;
|
||||
protected final List<ItemOverlayState> itemPresenceCache = new ArrayList<>();
|
||||
protected boolean requireShiftForOverlayRecipe = true;
|
||||
protected boolean useOverlayRenderer = false;
|
||||
protected boolean hasOverlay = false;
|
||||
|
||||
public GuiOverlayButton(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex, int x, int y, int width,
|
||||
int height) {
|
||||
super(OVERLAY_BUTTON_ID_START + recipeIndex, x, y, width, height, "+");
|
||||
this.firstGui = firstGui != null && firstGui.inventorySlots != null ? firstGui : null;
|
||||
this.handler = handler;
|
||||
this.recipeIndex = recipeIndex;
|
||||
this.hasOverlay = this.firstGui != null
|
||||
&& handler.hasOverlay(this.firstGui, this.firstGui.inventorySlots, recipeIndex);
|
||||
this.useOverlayRenderer = this.hasOverlay && handler.getOverlayRenderer(firstGui, recipeIndex) != null;
|
||||
this.overlayHandler = this.hasOverlay ? handler.getOverlayHandler(firstGui, recipeIndex) : null;
|
||||
|
||||
setRequireShiftForOverlayRecipe(NEIClientConfig.requireShiftForOverlayRecipe());
|
||||
ingredientsOverlay();
|
||||
}
|
||||
|
||||
public List<String> handleTooltip(GuiRecipe<?> gui, List<String> currenttip) {
|
||||
currenttip.add(translate("recipe.overlay"));
|
||||
|
||||
if (!this.enabled && this.requireShiftForOverlayRecipe && this.overlayHandler == null) {
|
||||
currenttip.set(currenttip.size() - 1, currenttip.get(currenttip.size() - 1) + GuiDraw.TOOLTIP_LINESPACE);
|
||||
currenttip.add(EnumChatFormatting.RED + translate("recipe.overlay.mismatch") + EnumChatFormatting.RESET);
|
||||
} else if (this.missedMaterialsTooltipLineHandler != null) {
|
||||
|
||||
if ((!this.requireShiftForOverlayRecipe || NEIClientUtils.shiftKey()) && this.overlayHandler != null) {
|
||||
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.RED);
|
||||
} else {
|
||||
this.missedMaterialsTooltipLineHandler.setLabelColor(EnumChatFormatting.GRAY);
|
||||
}
|
||||
|
||||
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.missedMaterialsTooltipLineHandler));
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
|
||||
if (this.requireShiftForOverlayRecipe && this.useOverlayRenderer) {
|
||||
hotkeys.put(translate("recipe.overlay.fillCraftingGrid.key"), translate("recipe.overlay.fillCraftingGrid"));
|
||||
}
|
||||
|
||||
String keyName = NEIClientConfig.getKeyName("gui.bookmark");
|
||||
if (keyName != null) {
|
||||
hotkeys.put(keyName, translate("recipe.overlay.bookmark"));
|
||||
}
|
||||
|
||||
keyName = NEIClientConfig.getKeyName("gui.bookmark_recipe");
|
||||
if (keyName != null) {
|
||||
hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipe"));
|
||||
}
|
||||
|
||||
keyName = NEIClientConfig.getKeyName("gui.bookmark_count");
|
||||
if (keyName != null) {
|
||||
hotkeys.put(keyName, translate("recipe.overlay.bookmarkAmount"));
|
||||
}
|
||||
|
||||
keyName = NEIClientConfig.getKeyName("gui.bookmark_recipe_count");
|
||||
if (keyName != null) {
|
||||
hotkeys.put(keyName, translate("recipe.overlay.bookmarkRecipeAndAmount"));
|
||||
}
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
if (this.firstGui != null) {
|
||||
this.firstGui.mc.displayGuiScreen(this.firstGui);
|
||||
overlayRecipe(NEIClientUtils.shiftKey());
|
||||
}
|
||||
}
|
||||
|
||||
public void drawItemPresenceOverlay() {
|
||||
final int presenceOverlay = NEIClientConfig.itemPresenceOverlay();
|
||||
final boolean highlightPresentItem = NEIClientConfig.isSlotHighlightPresent();
|
||||
final ItemOverlayFormat format = ItemOverlayFormat.from(presenceOverlay);
|
||||
|
||||
for (ItemOverlayState overlay : ingredientsOverlay()) {
|
||||
if (highlightPresentItem || !overlay.isPresent()) {
|
||||
overlay.draw(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<ItemOverlayState> ingredientsOverlay() {
|
||||
List<PositionedStack> ingredients = this.handler.getIngredientStacks(recipeIndex);
|
||||
|
||||
if (this.itemPresenceCache.size() != ingredients.size()) {
|
||||
this.itemPresenceCache.clear();
|
||||
|
||||
if (this.overlayHandler != null) {
|
||||
this.itemPresenceCache
|
||||
.addAll(this.overlayHandler.presenceOverlay(this.firstGui, this.handler, this.recipeIndex));
|
||||
} else if (this.firstGui != null) {
|
||||
this.itemPresenceCache.addAll(presenceOverlay(ingredients));
|
||||
}
|
||||
|
||||
List<ItemStack> items = this.itemPresenceCache.stream().filter(state -> !state.isPresent())
|
||||
.map(state -> state.getSlot().item).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
if (!items.isEmpty()) {
|
||||
this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler(
|
||||
translate("recipe.overlay.missing"),
|
||||
items,
|
||||
true,
|
||||
Integer.MAX_VALUE);
|
||||
} else {
|
||||
this.missedMaterialsTooltipLineHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.itemPresenceCache;
|
||||
}
|
||||
|
||||
public void setRequireShiftForOverlayRecipe(boolean require) {
|
||||
this.requireShiftForOverlayRecipe = require;
|
||||
this.enabled = this.hasOverlay && (this.requireShiftForOverlayRecipe || this.overlayHandler != null);
|
||||
}
|
||||
|
||||
public void setUseOverlayRenderer(boolean use) {
|
||||
this.useOverlayRenderer = use;
|
||||
}
|
||||
|
||||
public boolean useOverlayRenderer() {
|
||||
return this.useOverlayRenderer;
|
||||
}
|
||||
|
||||
public boolean canFillCraftingGrid() {
|
||||
return this.missedMaterialsTooltipLineHandler == null;
|
||||
}
|
||||
|
||||
public boolean hasOverlay() {
|
||||
return this.hasOverlay;
|
||||
}
|
||||
|
||||
private List<ItemOverlayState> presenceOverlay(List<PositionedStack> ingredients) {
|
||||
final List<ItemOverlayState> itemPresenceSlots = new ArrayList<>();
|
||||
final List<ItemStack> invStacks = this.firstGui.inventorySlots.inventorySlots.stream()
|
||||
.filter(
|
||||
s -> s != null && s.getStack() != null
|
||||
&& s.getStack().stackSize > 0
|
||||
&& s.isItemValid(s.getStack())
|
||||
&& s.canTakeStack(this.firstGui.mc.thePlayer))
|
||||
.map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
for (PositionedStack stack : ingredients) {
|
||||
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
|
||||
.findAny();
|
||||
|
||||
itemPresenceSlots.add(new ItemOverlayState(stack, used.isPresent()));
|
||||
|
||||
if (used.isPresent()) {
|
||||
ItemStack is = used.get();
|
||||
is.stackSize -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return itemPresenceSlots;
|
||||
}
|
||||
|
||||
public void overlayRecipe(boolean shift) {
|
||||
if (!this.hasOverlay) return;
|
||||
|
||||
if (!this.useOverlayRenderer || !this.requireShiftForOverlayRecipe || shift) {
|
||||
if (this.overlayHandler != null) {
|
||||
this.overlayHandler.overlayRecipe(
|
||||
this.firstGui,
|
||||
this.handler,
|
||||
this.recipeIndex,
|
||||
!this.requireShiftForOverlayRecipe || shift);
|
||||
}
|
||||
} else {
|
||||
LayoutManager.overlayRenderer = this.handler.getOverlayRenderer(this.firstGui, this.recipeIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void lastKeyTyped(GuiRecipe<?> gui, char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark")) {
|
||||
saveRecipeInBookmark(false, false);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) {
|
||||
saveRecipeInBookmark(true, false);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_count")) {
|
||||
saveRecipeInBookmark(false, true);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.bookmark_recipe_count")) {
|
||||
saveRecipeInBookmark(true, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void saveRecipeInBookmark(boolean saveIngredients, boolean saveStackSize) {
|
||||
final HandlerInfo handlerInfo = GuiRecipeTab.getHandlerInfo(this.handler);
|
||||
final List<PositionedStack> ingredients = this.handler.getIngredientStacks(this.recipeIndex);
|
||||
final BookmarkRecipeId recipeId = new BookmarkRecipeId(handlerInfo.getHandlerName(), ingredients);
|
||||
|
||||
if (!ItemPanels.bookmarkPanel.removeBookmarkRecipeId(recipeId)) {
|
||||
BookmarkRecipe recipe = new BookmarkRecipe();
|
||||
recipe.handlerName = recipeId.handlerName;
|
||||
recipe.recipeId = recipeId;
|
||||
|
||||
if (saveIngredients) {
|
||||
for (PositionedStack stack : ingredients) {
|
||||
recipe.ingredients.add(stack.item);
|
||||
}
|
||||
}
|
||||
|
||||
PositionedStack result = this.handler.getResultStack(this.recipeIndex);
|
||||
|
||||
if (result != null) {
|
||||
recipe.result.add(result.item);
|
||||
} else {
|
||||
for (PositionedStack stack : this.handler.getOtherStacks(this.recipeIndex)) {
|
||||
recipe.result.add(stack.item);
|
||||
}
|
||||
}
|
||||
|
||||
ItemPanels.bookmarkPanel.addRecipe(recipe, saveStackSize);
|
||||
}
|
||||
}
|
||||
|
||||
public int getResultStackSize(ItemStack stackover) {
|
||||
final List<PositionedStack> stacks = this.handler.getOtherStacks(this.recipeIndex);
|
||||
int stackSize = stackover.stackSize;
|
||||
|
||||
for (PositionedStack pStack : stacks) {
|
||||
if (StackInfo.equalItemAndNBT(pStack.item, stackover, true)) {
|
||||
stackSize += pStack.item.stackSize;
|
||||
}
|
||||
}
|
||||
|
||||
return stackSize;
|
||||
}
|
||||
|
||||
public Rectangle4i bounds() {
|
||||
return new Rectangle4i(this.xPosition, this.yPosition, this.width, this.height);
|
||||
}
|
||||
|
||||
public boolean contains(int mx, int my) {
|
||||
return bounds().contains(mx, my);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.fontRenderer;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
@@ -9,10 +8,8 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -23,7 +20,7 @@ import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -31,6 +28,7 @@ import org.lwjgl.opengl.GL11;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.GuiNEIButton;
|
||||
import codechicken.nei.ItemsTooltipLineHandler;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEICPH;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
@@ -38,6 +36,7 @@ import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.RecipeSearchField;
|
||||
import codechicken.nei.RestartableTask;
|
||||
import codechicken.nei.SearchField;
|
||||
import codechicken.nei.VisiblityData;
|
||||
import codechicken.nei.api.IGuiContainerOverlay;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
@@ -53,6 +52,7 @@ import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.guihook.IGuiClientSide;
|
||||
import codechicken.nei.guihook.IGuiHandleMouseWheel;
|
||||
import codechicken.nei.recipe.GuiOverlayButton.UpdateOverlayButtonsEvent;
|
||||
|
||||
public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer implements IGuiContainerOverlay,
|
||||
IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler, INEIGuiHandler {
|
||||
@@ -74,6 +74,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
public static final List<IRecipeFilterProvider> recipeFilterers = new LinkedList<>();
|
||||
|
||||
protected boolean limitToOneRecipe = false;
|
||||
protected PermutationTooltipLineHandler permutationTooltipLineHandler;
|
||||
|
||||
// Background image
|
||||
final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT)
|
||||
@@ -105,8 +106,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private GuiButton nexttype;
|
||||
private GuiButton prevtype;
|
||||
|
||||
private final int OVERLAY_BUTTON_ID_START = 4;
|
||||
private GuiButton[] overlayButtons;
|
||||
private GuiOverlayButton[] overlayButtons = new GuiOverlayButton[0];
|
||||
|
||||
private final Rectangle area = new Rectangle();
|
||||
private final GuiRecipeTabs recipeTabs;
|
||||
@@ -116,6 +116,41 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
private int yShift = 0;
|
||||
|
||||
protected static class PermutationTooltipLineHandler extends ItemsTooltipLineHandler {
|
||||
|
||||
protected PositionedStack pStack = null;
|
||||
|
||||
public PermutationTooltipLineHandler(PositionedStack pStack, List<ItemStack> items) {
|
||||
super(NEIClientUtils.translate("recipe.accepts"), items, false, 5);
|
||||
this.pStack = pStack;
|
||||
}
|
||||
|
||||
public static PermutationTooltipLineHandler getInstance(PositionedStack pStack) {
|
||||
final List<ItemStack> items = pStack.getFilteredPermutations();
|
||||
|
||||
if (items.size() > 1) {
|
||||
return new PermutationTooltipLineHandler(pStack, items);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItem(int x, int y, ItemStack drawStack, String stackSize) {
|
||||
|
||||
if (StackInfo.equalItemAndNBT(drawStack, this.pStack.item, true)) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GuiDraw.drawRect(x - 1, y - 1, 18, 18, 0x66555555);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
super.drawItem(x, y, drawStack, stackSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ItemRecipeFilter implements IRecipeFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
@@ -213,7 +248,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
guiRecipe.changePage(0);
|
||||
} else {
|
||||
final IRecipeFilter filter = new ItemRecipeFilter(GuiRecipe.searchField.getFilter());
|
||||
ArrayList<Integer> filtered = searchHandler.getSearchResult(filter);
|
||||
List<Integer> filtered = searchHandler.getSearchResult(filter);
|
||||
|
||||
if (filtered == null) {
|
||||
stop();
|
||||
@@ -378,7 +413,6 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initGui() {
|
||||
xSize = 176;
|
||||
ySize = Math.min(Math.max(height - 68, 166), 370);
|
||||
@@ -386,7 +420,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
super.initGui();
|
||||
} else {
|
||||
this.guiLeft = (this.width - this.xSize) / 2;
|
||||
this.ySize = this.getHeightAsWidget();
|
||||
this.ySize = this.getWidgetSize().height;
|
||||
this.mc = NEIClientUtils.mc();
|
||||
this.fontRendererObj = mc.fontRenderer;
|
||||
ScaledResolution scaledresolution = new ScaledResolution(
|
||||
@@ -402,7 +436,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
if (handler == null) {
|
||||
setRecipePage(recipetype);
|
||||
} else {
|
||||
initOverlayButtons();
|
||||
updateOverlayButtons();
|
||||
}
|
||||
|
||||
checkYShift();
|
||||
@@ -410,16 +444,40 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
final int rightButtonX = guiLeft + xSize - borderPadding - buttonWidth;
|
||||
final int leftButtonX = guiLeft + borderPadding;
|
||||
|
||||
nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<");
|
||||
prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">");
|
||||
nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<") {
|
||||
|
||||
nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<");
|
||||
prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">");
|
||||
@Override
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
prevType();
|
||||
}
|
||||
};
|
||||
prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">") {
|
||||
|
||||
toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 38, 8, 8).setTextureSize(128, 128)
|
||||
.build();
|
||||
@Override
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
nextType();
|
||||
}
|
||||
};
|
||||
|
||||
buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage));
|
||||
nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<") {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
prevPage();
|
||||
}
|
||||
};
|
||||
prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">") {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
nextPage();
|
||||
}
|
||||
};
|
||||
|
||||
toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 76, 10, 10).build();
|
||||
|
||||
this.buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage));
|
||||
this.overlayButtons = new GuiOverlayButton[0];
|
||||
|
||||
if (currenthandlers.size() == 1) {
|
||||
nexttype.visible = false;
|
||||
@@ -430,35 +488,71 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
refreshPage();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void initOverlayButtons() {
|
||||
if (overlayButtons != null) {
|
||||
buttonList.removeIf(Arrays.asList(overlayButtons)::contains);
|
||||
private void updateOverlayButtons() {
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
|
||||
if (isDirtyOverlayButtons(indices)) {
|
||||
this.buttonList.removeIf(Arrays.asList(this.overlayButtons)::contains);
|
||||
|
||||
final int xOffset = (limitToOneRecipe ? 0 : guiLeft) + xSize - borderPadding;
|
||||
final int yOffset = (limitToOneRecipe ? -buttonHeight : guiTop - 18) + getRecipePosition(0).y;
|
||||
final int height = handlerInfo.getHeight() - yShift;
|
||||
final UpdateOverlayButtonsEvent.Pre preEvent = new UpdateOverlayButtonsEvent.Pre(
|
||||
this,
|
||||
xOffset,
|
||||
yOffset,
|
||||
height,
|
||||
handlerInfo);
|
||||
List<GuiOverlayButton> buttons = new ArrayList<>();
|
||||
|
||||
if (MinecraftForge.EVENT_BUS.post(preEvent)) {
|
||||
buttons = preEvent.buttonList;
|
||||
} else {
|
||||
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
final int recipeIndex = indices.get(refIndex);
|
||||
|
||||
if (handler.original.getResultStack(recipeIndex) == null
|
||||
&& handler.original.getOtherStacks(recipeIndex).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buttons.add(
|
||||
new GuiOverlayButton(
|
||||
firstGui,
|
||||
handler.original,
|
||||
recipeIndex,
|
||||
xOffset - buttonWidth,
|
||||
yOffset + height * (refIndex + 1),
|
||||
buttonWidth,
|
||||
buttonHeight));
|
||||
}
|
||||
|
||||
if (this.equals(this.mc.currentScreen)) {
|
||||
UpdateOverlayButtonsEvent.Post postEvent = new UpdateOverlayButtonsEvent.Post(this, buttons);
|
||||
MinecraftForge.EVENT_BUS.post(postEvent);
|
||||
buttons = postEvent.buttonList;
|
||||
}
|
||||
}
|
||||
|
||||
this.overlayButtons = buttons.toArray(new GuiOverlayButton[buttons.size()]);
|
||||
this.buttonList.addAll(buttons);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDirtyOverlayButtons(List<Integer> indices) {
|
||||
|
||||
if (this.overlayButtons.length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
overlayButtons = new GuiButton[recipesPerPage];
|
||||
final int xOffset = limitToOneRecipe ? ((xSize / 2) - 2) : (width / 2);
|
||||
final int yOffset = limitToOneRecipe ? 0 : guiTop - 18;
|
||||
final String overlayKeyName = NEIClientConfig
|
||||
.getKeyName(NEIClientConfig.getKeyBinding("gui.overlay_use"), true);
|
||||
for (int i = 0; i < recipesPerPage; i++) {
|
||||
overlayButtons[i] = new GuiNEIButton(
|
||||
OVERLAY_BUTTON_ID_START + i,
|
||||
xOffset + 65,
|
||||
yOffset + getRecipePosition(i).y + handlerInfo.getHeight(),
|
||||
buttonWidth,
|
||||
buttonHeight,
|
||||
"?");
|
||||
if (overlayKeyName != null && limitToOneRecipe) {
|
||||
overlayButtons[i].visible = true;
|
||||
overlayButtons[i].displayString = overlayKeyName;
|
||||
overlayButtons[i].width = fontRenderer.getStringWidth(overlayKeyName) + 6;
|
||||
overlayButtons[i].xPosition = xOffset + 85 - overlayButtons[i].width;
|
||||
for (GuiOverlayButton button : this.overlayButtons) {
|
||||
if (button.handler != handler.original || !indices.contains(button.recipeIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Collections.addAll(buttonList, overlayButtons);
|
||||
itemPresenceCacheRecipe = -1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IRecipeFilter getRecipeListFilter() {
|
||||
@@ -480,6 +574,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return recipeFilter.filters.size() == 1 ? recipeFilter.filters.get(0) : recipeFilter;
|
||||
}
|
||||
|
||||
public static ItemFilter getSearchItemFilter() {
|
||||
return searchField.getFilter();
|
||||
}
|
||||
|
||||
private void checkYShift() {
|
||||
yShift = handlerInfo == null ? 0 : handlerInfo.getYShift();
|
||||
}
|
||||
@@ -504,11 +602,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
changePage(0);
|
||||
recipeTabs.calcPageNumber();
|
||||
checkYShift();
|
||||
initOverlayButtons();
|
||||
}
|
||||
|
||||
public List<GuiButton> getOverlayButtons() {
|
||||
return Collections.unmodifiableList(Arrays.asList(overlayButtons));
|
||||
return Collections.unmodifiableList(Arrays.asList(this.overlayButtons));
|
||||
}
|
||||
|
||||
public int openTargetRecipe(BookmarkRecipeId recipeId) {
|
||||
@@ -543,9 +640,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
public List<PositionedStack> getFocusedRecipeIngredients() {
|
||||
List<Integer> indices = getRecipeIndices();
|
||||
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (recipeInFocus(recipeIndex)) {
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
final int recipeIndex = indices.get(refIndex);
|
||||
if (recipeInFocus(refIndex, recipeIndex)) {
|
||||
return handler.original.getIngredientStacks(recipeIndex);
|
||||
}
|
||||
}
|
||||
@@ -554,9 +653,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
public int prepareFocusedRecipeResultStackSize(ItemStack stackover) {
|
||||
List<Integer> indices = getRecipeIndices();
|
||||
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (recipeInFocus(recipeIndex)) {
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
final int recipeIndex = indices.get(refIndex);
|
||||
if (recipeInFocus(refIndex, recipeIndex)) {
|
||||
final PositionedStack result = handler.original.getResultStack(recipeIndex);
|
||||
int stackSize = 0;
|
||||
|
||||
@@ -578,15 +679,16 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return stackover.stackSize;
|
||||
}
|
||||
|
||||
protected boolean recipeInFocus(int recipeIndex) {
|
||||
protected boolean recipeInFocus(int refIndex, int recipeIndex) {
|
||||
final PositionedStack result = handler.original.getResultStack(recipeIndex);
|
||||
if (result != null && isMouseOver(result, recipeIndex)) {
|
||||
|
||||
if (result != null && isMouseOver(result, refIndex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<PositionedStack> stacks = handler.original.getOtherStacks(recipeIndex);
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (isMouseOver(stack, recipeIndex)) {
|
||||
if (isMouseOver(stack, refIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -647,6 +749,14 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Point mouse = GuiDraw.getMousePosition();
|
||||
|
||||
for (GuiOverlayButton button : this.overlayButtons) {
|
||||
if (button.contains(mouse.x, mouse.y)) {
|
||||
button.lastKeyTyped(this, c, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == mc.gameSettings.keyBindInventory.getKeyCode()) {
|
||||
@@ -732,44 +842,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
super.actionPerformed(guibutton);
|
||||
switch (guibutton.id) {
|
||||
case 0:
|
||||
prevType();
|
||||
return;
|
||||
case 1:
|
||||
nextType();
|
||||
return;
|
||||
case 2:
|
||||
prevPage();
|
||||
return;
|
||||
case 3:
|
||||
nextPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlayButtons != null && guibutton.id >= OVERLAY_BUTTON_ID_START
|
||||
&& guibutton.id < OVERLAY_BUTTON_ID_START + overlayButtons.length) {
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
final int refIndex = guibutton.id - OVERLAY_BUTTON_ID_START;
|
||||
|
||||
if (refIndex >= 0 && refIndex < indices.size()) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
overlayRecipe(indices.get(refIndex), NEIClientUtils.shiftKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
super.updateScreen();
|
||||
updateAsTooltip();
|
||||
}
|
||||
|
||||
/** updateScreen() that's safe to call when this isn't the currently open GUI */
|
||||
public void updateAsTooltip() {
|
||||
handler.original.onUpdate();
|
||||
refreshPage();
|
||||
}
|
||||
@@ -781,6 +856,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
currenttip = handler.original.handleTooltip(this, currenttip, recipeIndex);
|
||||
}
|
||||
|
||||
for (GuiOverlayButton button : this.overlayButtons) {
|
||||
if (button.contains(mousex, mousey)) {
|
||||
currenttip = button.handleTooltip(this, currenttip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recipeTabs.handleTooltip(mousex, mousey, currenttip);
|
||||
@@ -800,18 +881,66 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey,
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
|
||||
List<Integer> indices = getRecipeIndices();
|
||||
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
currenttip = handler.original.handleItemTooltip(this, stack, currenttip, recipeIndex);
|
||||
for (int recipeIndex : indices) {
|
||||
currenttip = handler.original.handleItemTooltip(this, itemstack, currenttip, recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.showCycledIngredientsTooltip()) {
|
||||
PositionedStack focused = null;
|
||||
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
final int recipeIndex = indices.get(refIndex);
|
||||
|
||||
if (itemstack != null && focused == null) {
|
||||
final List<PositionedStack> stacks = handler.original.getIngredientStacks(recipeIndex);
|
||||
|
||||
for (PositionedStack pStack : stacks) {
|
||||
if (isMouseOver(pStack, refIndex)) {
|
||||
focused = pStack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (focused == null || focused.items.length <= 1) {
|
||||
this.permutationTooltipLineHandler = null;
|
||||
} else if (this.permutationTooltipLineHandler == null
|
||||
|| this.permutationTooltipLineHandler.pStack != focused) {
|
||||
this.permutationTooltipLineHandler = PermutationTooltipLineHandler.getInstance(focused);
|
||||
}
|
||||
} else if (this.permutationTooltipLineHandler != null) {
|
||||
this.permutationTooltipLineHandler = null;
|
||||
}
|
||||
|
||||
if (this.permutationTooltipLineHandler != null) {
|
||||
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.permutationTooltipLineHandler));
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (GuiOverlayButton button : this.overlayButtons) {
|
||||
if (button.contains(mousex, mousey)) {
|
||||
hotkeys = button.handleHotkeys(gui, mousex, mousey, hotkeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
@@ -833,19 +962,20 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
setRecipePage(--recipetype);
|
||||
}
|
||||
|
||||
protected void overlayRecipe(int recipeIndex, final boolean shift) {
|
||||
protected void overlayRecipe(int recipeIndex, boolean shift) {
|
||||
|
||||
if (handler == null || !handler.original.hasOverlay(firstGui, firstGui.inventorySlots, recipeIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean moveItems = shift || !NEIClientConfig.requireShiftForOverlayRecipe();
|
||||
final IRecipeOverlayRenderer renderer = handler.original.getOverlayRenderer(firstGui, recipeIndex);
|
||||
final boolean requireShiftForOverlayRecipe = NEIClientConfig.requireShiftForOverlayRecipe();
|
||||
final IOverlayHandler overlayHandler = handler.original.getOverlayHandler(firstGui, recipeIndex);
|
||||
final IRecipeOverlayRenderer renderer = handler.original.getOverlayRenderer(firstGui, recipeIndex);
|
||||
|
||||
if (renderer == null || moveItems) {
|
||||
if (renderer == null || !requireShiftForOverlayRecipe || shift) {
|
||||
if (overlayHandler != null) {
|
||||
overlayHandler.overlayRecipe(firstGui, handler.original, recipeIndex, moveItems);
|
||||
overlayHandler
|
||||
.overlayRecipe(firstGui, handler.original, recipeIndex, !requireShiftForOverlayRecipe || shift);
|
||||
}
|
||||
} else {
|
||||
LayoutManager.overlayRenderer = renderer;
|
||||
@@ -863,11 +993,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
} else {
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void refreshPage() {
|
||||
RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2));
|
||||
changePage(0);
|
||||
refreshSlots();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
@@ -881,6 +1009,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
checkYShift();
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2));
|
||||
toggleSearch.w = toggleSearch.h = 12;
|
||||
toggleSearch.x = borderPadding + buttonWidth;
|
||||
toggleSearch.y = 17;
|
||||
@@ -893,22 +1022,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
nextpage.enabled = prevpage.enabled = multiplepages;
|
||||
|
||||
if (firstGui == null) {
|
||||
for (GuiButton overlay : overlayButtons) {
|
||||
overlay.visible = false;
|
||||
}
|
||||
} else {
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
for (int i = 0; i < overlayButtons.length; i++) {
|
||||
if (i >= indices.size()) {
|
||||
overlayButtons[i].visible = false;
|
||||
} else {
|
||||
overlayButtons[i].visible = handler.original
|
||||
.hasOverlay(firstGui, firstGui.inventorySlots, indices.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateOverlayButtons();
|
||||
recipeTabs.refreshPage();
|
||||
}
|
||||
|
||||
@@ -950,39 +1064,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
}
|
||||
|
||||
private int itemPresenceCacheRecipe = -1;
|
||||
private ArrayList<Boolean> itemPresenceCacheSlots;
|
||||
|
||||
private void updateItemPresenceCache(int recipeIndex) {
|
||||
if (itemPresenceCacheSlots == null) {
|
||||
itemPresenceCacheSlots = new ArrayList<>();
|
||||
}
|
||||
itemPresenceCacheRecipe = recipeIndex;
|
||||
itemPresenceCacheSlots.clear();
|
||||
List<PositionedStack> ingredients = handler.original.getIngredientStacks(recipeIndex);
|
||||
ArrayList<ItemStack> invStacks = ((List<Slot>) firstGui.inventorySlots.inventorySlots).stream()
|
||||
.filter(
|
||||
s -> s != null && s.getStack() != null
|
||||
&& s.getStack().stackSize > 0
|
||||
&& s.isItemValid(s.getStack())
|
||||
&& s.canTakeStack(mc.thePlayer))
|
||||
.map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new));
|
||||
for (PositionedStack stack : ingredients) {
|
||||
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
|
||||
.findFirst();
|
||||
itemPresenceCacheSlots.add(used.isPresent());
|
||||
if (used.isPresent()) {
|
||||
ItemStack is = used.get();
|
||||
is.stackSize -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
||||
GuiContainerManager.enable2DRender();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final int ySkip = limitToOneRecipe ? 25 : 0;
|
||||
final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32;
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
String s = handler.original.getRecipeName().trim();
|
||||
@@ -1010,47 +1096,62 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
}
|
||||
|
||||
final boolean drawItemPresence = NEIClientConfig.isJEIStyleItemPresenceOverlayVisible();
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(5, 32 - ySkip + yShift, 0);
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
List<Integer> indices = getRecipeIndices();
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(5, ySkip + yShift, 0);
|
||||
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
int recipeIndex = indices.get(refIndex);
|
||||
|
||||
handler.original.drawForeground(recipeIndex);
|
||||
|
||||
if (drawItemPresence && firstGui != null
|
||||
&& firstGui.inventorySlots != null
|
||||
&& (isMouseOverOverlayButton(refIndex) || limitToOneRecipe)) {
|
||||
if (limitToOneRecipe) {
|
||||
GuiOverlayButton overlayButton = Arrays.asList(this.overlayButtons).stream()
|
||||
.filter(b -> b.recipeIndex == recipeIndex).findAny().orElse(null);
|
||||
|
||||
List<PositionedStack> ingredients = handler.original.getIngredientStacks(recipeIndex);
|
||||
if (overlayButton != null && overlayButton.enabled) {
|
||||
final String overlayKeyName = NEIClientConfig.getKeyName("gui.overlay_use");
|
||||
|
||||
if (itemPresenceCacheRecipe != recipeIndex || itemPresenceCacheSlots == null
|
||||
|| itemPresenceCacheSlots.size() != ingredients.size()) {
|
||||
updateItemPresenceCache(recipeIndex);
|
||||
}
|
||||
if (overlayKeyName != null) {
|
||||
fontRendererObj.drawStringWithShadow(
|
||||
EnumChatFormatting.ITALIC + overlayKeyName,
|
||||
xSize - borderPadding - fontRendererObj.getStringWidth(overlayKeyName) - 10,
|
||||
handlerInfo.getHeight() - fontRendererObj.FONT_HEIGHT,
|
||||
0xffffff);
|
||||
}
|
||||
|
||||
for (int j = 0; j < ingredients.size(); j++) {
|
||||
PositionedStack stack = ingredients.get(j);
|
||||
boolean isPresent = itemPresenceCacheSlots.get(j);
|
||||
LayoutManager.drawItemPresenceOverlay(stack.relx, stack.rely, isPresent);
|
||||
overlayButton.drawItemPresenceOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(5, ySkip + yShift, 0);
|
||||
|
||||
if (!limitToOneRecipe && NEIClientConfig.itemPresenceOverlay() > 0) {
|
||||
for (GuiOverlayButton button : this.overlayButtons) {
|
||||
if (button.contains(mouseX, mouseY)) {
|
||||
GL11.glTranslatef(0, handlerInfo.getHeight() * indices.indexOf(button.recipeIndex), 0);
|
||||
button.drawItemPresenceOverlay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
|
||||
final int ySkip = limitToOneRecipe ? 25 : 0;
|
||||
final int ySkip = limitToOneRecipe ? BG_TOP_HEIGHT + 1 : 32;
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
|
||||
drawBackgroundTiled(guiLeft, guiTop);
|
||||
@@ -1079,7 +1180,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(guiLeft + 5, guiTop - ySkip + 32 + yShift, 0);
|
||||
GL11.glTranslatef(guiLeft + 5, guiTop + ySkip + yShift, 0);
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
@@ -1092,13 +1193,13 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
private void drawBackgroundTiled(int j, int k) {
|
||||
final int handlerHeight = getWidgetSize().height;
|
||||
|
||||
// Draw the top
|
||||
final int ySkip = limitToOneRecipe ? 25 : 0;
|
||||
final int handlerHeight = limitToOneRecipe ? getHeightAsWidget() : ySize;
|
||||
bgTop.draw(j, k + BG_TOP_Y);
|
||||
|
||||
// Maybe Tile the middle
|
||||
final int tiledHeight = handlerHeight - ySkip - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
|
||||
final int tiledHeight = handlerHeight - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
|
||||
|
||||
if (tiledHeight > 0) {
|
||||
final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT;
|
||||
@@ -1115,11 +1216,18 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
// Draw the bottom
|
||||
bgBottom.draw(j, k + handlerHeight - ySkip - BG_BOTTOM_HEIGHT);
|
||||
bgBottom.draw(j, k + handlerHeight - BG_BOTTOM_HEIGHT);
|
||||
}
|
||||
|
||||
public int getHeightAsWidget() {
|
||||
return (handlerInfo == null) ? ySize : (handlerInfo.getHeight() + 56);
|
||||
public Dimension getWidgetSize() {
|
||||
|
||||
if (handlerInfo == null) {
|
||||
return new Dimension(xSize, ySize);
|
||||
}
|
||||
|
||||
final int handlerHeight = limitToOneRecipe ? handlerInfo.getHeight() + yShift + BG_TOP_HEIGHT + BG_BOTTOM_HEIGHT
|
||||
: ySize;
|
||||
return new Dimension(xSize, handlerHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1141,19 +1249,6 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return stackSlot == mouseoverSlot;
|
||||
}
|
||||
|
||||
private boolean isMouseOverOverlayButton(int buttonId) {
|
||||
if (buttonId >= 0 && buttonId < overlayButtons.length) {
|
||||
GuiButton button = overlayButtons[buttonId];
|
||||
Point mousePos = GuiDraw.getMousePosition();
|
||||
return button.visible && mousePos.x >= button.xPosition
|
||||
&& mousePos.y >= button.yPosition
|
||||
&& mousePos.x < button.xPosition + button.width
|
||||
&& mousePos.y < button.yPosition + button.height;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int getRecipesPerPage() {
|
||||
return limitToOneRecipe ? 1 : getRecipesPerPage(handlerInfo);
|
||||
}
|
||||
@@ -1203,32 +1298,20 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
|
||||
|
||||
if (searchField.isVisible() && searchField.contains(mousex - guiLeft, mousey - guiTop)) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(draggedStack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
searchField.setText(formattingText(fluidStack.getLocalizedName()));
|
||||
} else {
|
||||
searchField.setText(formattingText(draggedStack.getDisplayName()));
|
||||
}
|
||||
|
||||
searchField.setText(SearchField.getEscapedSearchText(draggedStack));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String formattingText(String displayName) {
|
||||
return Pattern.compile("[{}()\\[\\].+*?^$\\\\|]")
|
||||
.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(displayName)).replaceAll("\\\\$0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
||||
// Because some of the handlers *cough avaritia* are oversized
|
||||
return area.intersects(x, y, w, h);
|
||||
}
|
||||
|
||||
protected static BookmarkRecipeId getCurrentRecipe(GuiScreen gui) {
|
||||
protected static BookmarkRecipeId getCurrentRecipeId(GuiScreen gui) {
|
||||
|
||||
if (gui instanceof GuiRecipe && ((GuiRecipe<?>) gui).handler.numRecipes() > 0) {
|
||||
final GuiRecipe<?> gRecipe = (GuiRecipe<?>) gui;
|
||||
|
||||
@@ -213,10 +213,9 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
File handlerFile = NEIClientConfig.handlerFile;
|
||||
if (!handlerFile.exists()) {
|
||||
NEIClientConfig.logger.info("Config file doesn't exist, creating");
|
||||
try {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(handlerFile.getAbsoluteFile())) {
|
||||
assert handlerUrl != null;
|
||||
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(handlerFile.getAbsoluteFile());
|
||||
FileChannel fileChannel = fileOutputStream.getChannel();
|
||||
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
|
||||
} catch (IOException e) {
|
||||
@@ -233,7 +232,7 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
}
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(reader);
|
||||
CSVParser csvParser = CSVFormat.EXCEL.builder().setHeader().setSkipHeaderRecord(true).build().parse(reader);
|
||||
for (CSVRecord record : csvParser) {
|
||||
final String handler = record.get("handler");
|
||||
final String modName = record.get("modName");
|
||||
|
||||
@@ -2,6 +2,8 @@ package codechicken.nei.recipe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -14,19 +16,21 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
|
||||
|
||||
public static ArrayList<IUsageHandler> usagehandlers = new ArrayList<>();
|
||||
public static ArrayList<IUsageHandler> serialUsageHandlers = new ArrayList<>();
|
||||
private static Set<String> existingHandlers = new HashSet<>();
|
||||
|
||||
public static boolean openRecipeGui(String inputId, Object... ingredients) {
|
||||
|
||||
if ("item".equals(inputId)) {
|
||||
ingredients = Arrays.asList(ingredients).stream().map(ingr -> normalizeItemStack((ItemStack) ingr))
|
||||
.toArray();
|
||||
for (int i = 0; i < ingredients.length; i++) {
|
||||
ingredients[i] = normalizeItemStack((ItemStack) ingredients[i]);
|
||||
}
|
||||
}
|
||||
|
||||
final ArrayList<IUsageHandler> handlers = getUsageHandlers(inputId, ingredients);
|
||||
|
||||
if (!handlers.isEmpty()) {
|
||||
final Minecraft mc = NEIClientUtils.mc();
|
||||
final BookmarkRecipeId recipeId = getCurrentRecipe(mc.currentScreen);
|
||||
final BookmarkRecipeId recipeId = getCurrentRecipeId(mc.currentScreen);
|
||||
final GuiUsageRecipe gui = new GuiUsageRecipe(handlers);
|
||||
|
||||
mc.displayGuiScreen(gui);
|
||||
@@ -52,7 +56,7 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
|
||||
"inputId: " + inputId,
|
||||
"ingredients: " + Arrays.toString(ingredients));
|
||||
|
||||
return recipeQuery.runWithProfiling("recipe.concurrent.usage");
|
||||
return recipeQuery.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.usage"));
|
||||
}
|
||||
|
||||
private static ItemStack normalizeItemStack(ItemStack stack) {
|
||||
@@ -64,12 +68,25 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
|
||||
|
||||
public static void registerUsageHandler(IUsageHandler handler) {
|
||||
final String handlerId = handler.getHandlerId();
|
||||
if (usagehandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId))
|
||||
|| serialUsageHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)))
|
||||
return;
|
||||
|
||||
if (NEIClientConfig.serialHandlers.contains(handlerId)) serialUsageHandlers.add(handler);
|
||||
else usagehandlers.add(handler);
|
||||
if (existingHandlers.contains(handlerId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (existingHandlers) {
|
||||
existingHandlers.add(handlerId);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.serialHandlers.contains(handlerId)) {
|
||||
synchronized (serialUsageHandlers) {
|
||||
serialUsageHandlers.add(handler);
|
||||
}
|
||||
} else {
|
||||
synchronized (usagehandlers) {
|
||||
usagehandlers.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static IUsageHandler getUsageOrCatalystHandler(IUsageHandler handler, String inputId,
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
|
||||
class ItemsHistoryHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public ICraftingHandler getRecipeHandler(String outputId, Object... results) {
|
||||
|
||||
if (NEIClientConfig.showHistoryPanelWidget() && "item".equals(outputId)
|
||||
&& results[0] instanceof ItemStack stack) {
|
||||
ItemPanels.itemPanel.historyPanel.addItem(stack);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUsageHandler getUsageHandler(String inputId, Object... ingredients) {
|
||||
|
||||
if (NEIClientConfig.showHistoryPanelWidget() && "item".equals(inputId)
|
||||
&& ingredients[0] instanceof ItemStack stack) {
|
||||
ItemPanels.itemPanel.historyPanel.addItem(stack);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOverlay(GuiContainer gui, Container container, int recipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int recipiesPerPage() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiRecipe<?> gui, List<String> currenttip, int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiRecipe<?> gui, ItemStack stack, List<String> currenttip, int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiRecipe<?> gui, char keyChar, int keyCode, int recipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiRecipe<?> gui, int button, int recipe) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRecipeName() {
|
||||
return "Items History";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numRecipes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBackground(int recipe) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawForeground(int recipe) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PositionedStack> getIngredientStacks(int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PositionedStack> getOtherStacks(int recipeType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PositionedStack getResultStack(int recipe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,29 +3,26 @@ package codechicken.nei.recipe;
|
||||
import static codechicken.lib.gui.GuiDraw.drawString;
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.core.TaskProfiler;
|
||||
import codechicken.core.TaskProfiler.ProfilerResult;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
import codechicken.nei.util.AsyncTaskProfiler;
|
||||
|
||||
public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
private static final TaskProfiler profiler = new TaskProfiler();
|
||||
private static final AsyncTaskProfiler profiler = new AsyncTaskProfiler();
|
||||
|
||||
public static TaskProfiler getProfiler() {
|
||||
profiler.clear();
|
||||
public static AsyncTaskProfiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
@@ -42,7 +39,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public int numRecipes() {
|
||||
if (!NEIClientConfig.getBooleanSetting("inventory.profileRecipes")) return 0;
|
||||
if (!NEIClientConfig.isProfileRecipeEnabled()) return 0;
|
||||
|
||||
return (int) Math.ceil(
|
||||
((crafting ? GuiCraftingRecipe.craftinghandlers.size() : GuiUsageRecipe.usagehandlers.size()) - 1)
|
||||
@@ -55,8 +52,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
@Override
|
||||
public void drawForeground(int recipe) {
|
||||
List<ProfilerResult> results = profiler.getResults();
|
||||
for (Iterator<ProfilerResult> it = results.iterator(); it.hasNext();)
|
||||
if (it.next().name.equals(getRecipeName())) it.remove();
|
||||
results.removeIf(profilerResult -> getRecipeName().equals(profilerResult.name));
|
||||
|
||||
results.sort((o1, o2) -> o1.time < o2.time ? 1 : -1);
|
||||
|
||||
@@ -65,10 +61,9 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
int y = (i % 6) * 20 + 6;
|
||||
drawString(r.name, 8, y, 0xFF808080, false);
|
||||
|
||||
DecimalFormat format = new DecimalFormat("0.00");
|
||||
String s = format.format(r.fraction * 100) + "%";
|
||||
if (r.time < 1000000L) s += " (" + (r.time / 1000) + "us)";
|
||||
else s += " (" + (r.time / 1000000) + "ms)";
|
||||
String s;
|
||||
if (r.time < 1000000L) s = (r.time / 1000) + "us";
|
||||
else s = (r.time / 1000000) + "ms";
|
||||
|
||||
drawString(s, 156 - getStringWidth(s), y + 10, 0xFF404040, false);
|
||||
}
|
||||
|
||||
@@ -145,10 +145,9 @@ public class RecipeCatalysts {
|
||||
File catalystFile = NEIClientConfig.catalystFile;
|
||||
if (!catalystFile.exists()) {
|
||||
NEIClientConfig.logger.info("Config file doesn't exist, creating");
|
||||
try {
|
||||
try (FileOutputStream fileOutputStream = new FileOutputStream(catalystFile.getAbsoluteFile())) {
|
||||
assert handlerUrl != null;
|
||||
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(catalystFile.getAbsoluteFile());
|
||||
FileChannel fileChannel = fileOutputStream.getChannel();
|
||||
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
|
||||
} catch (IOException e) {
|
||||
@@ -165,7 +164,7 @@ public class RecipeCatalysts {
|
||||
}
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(reader);
|
||||
CSVParser csvParser = CSVFormat.EXCEL.builder().setHeader().setSkipHeaderRecord(true).build().parse(reader);
|
||||
for (CSVRecord record : csvParser) {
|
||||
final String handler = record.get("handler");
|
||||
final String modId = record.get("modId");
|
||||
@@ -194,7 +193,7 @@ public class RecipeCatalysts {
|
||||
try {
|
||||
// gently handling copy&paste from handlers.csv
|
||||
Class<?> clazz = Class.forName(handler);
|
||||
Object object = clazz.newInstance();
|
||||
Object object = clazz.getConstructor().newInstance();
|
||||
if (object instanceof IRecipeHandler) {
|
||||
if (forceClassName) {
|
||||
forceClassNameList.add(handler);
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.util.IChatComponent;
|
||||
import codechicken.core.TaskProfiler;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.util.AsyncTaskProfiler;
|
||||
|
||||
class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
|
||||
@@ -34,7 +35,15 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
|
||||
ArrayList<T> runWithProfiling(String profilerSection) {
|
||||
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.start(profilerSection);
|
||||
|
||||
// Save the current config state here, as it may be altered
|
||||
// if getRecipeHandlesParallel took so long and player accidentally changed config.
|
||||
boolean profileRecipes = NEIClientConfig.isProfileRecipeEnabled();
|
||||
if (profileRecipes) {
|
||||
profiler.clear();
|
||||
profiler.start(profilerSection);
|
||||
}
|
||||
|
||||
try {
|
||||
ArrayList<T> handlers = getRecipeHandlersParallel();
|
||||
|
||||
@@ -47,7 +56,7 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
displayRecipeLookupError();
|
||||
return new ArrayList<>(0);
|
||||
} finally {
|
||||
profiler.end();
|
||||
if (profileRecipes) profiler.end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +72,17 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
private ArrayList<T> getSerialHandlersWithRecipes() {
|
||||
|
||||
return serialRecipeHandlers.stream().map(handler -> {
|
||||
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.clearCurrent();
|
||||
profiler.start(handler.getRecipeName());
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
} finally {
|
||||
profiler.end();
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
@@ -77,12 +91,17 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
private ArrayList<T> getHandlersWithRecipes() throws InterruptedException, ExecutionException {
|
||||
|
||||
return ItemList.forkJoinPool.submit(() -> recipeHandlers.parallelStream().map(handler -> {
|
||||
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.clearCurrent();
|
||||
profiler.start(handler.getRecipeName());
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
} finally {
|
||||
profiler.end();
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get();
|
||||
|
||||
@@ -29,9 +29,10 @@ public class RecipeInfo {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof OverlayKey)) return false;
|
||||
OverlayKey key = (OverlayKey) obj;
|
||||
return Objects.equal(ident, key.ident) && guiClass == key.guiClass;
|
||||
if (obj instanceof OverlayKey item) {
|
||||
return Objects.equal(ident, item.ident) && guiClass == item.guiClass;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,5 +114,7 @@ public class RecipeInfo {
|
||||
|
||||
API.registerRecipeHandler(new ProfilerRecipeHandler(true));
|
||||
API.registerUsageHandler(new ProfilerRecipeHandler(false));
|
||||
API.registerRecipeHandler(new ItemsHistoryHandler());
|
||||
API.registerUsageHandler(new ItemsHistoryHandler());
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,22 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.api.ShortcutInputHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class RecipeItemInputHandler implements IContainerInputHandler {
|
||||
public class RecipeItemInputHandler implements IContainerInputHandler, IContainerTooltipHandler {
|
||||
|
||||
public static void load() {
|
||||
RecipeItemInputHandler recipeHandler = new RecipeItemInputHandler();
|
||||
GuiContainerManager.addInputHandler(recipeHandler);
|
||||
GuiContainerManager.addTooltipHandler(recipeHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
@@ -21,9 +29,21 @@ public class RecipeItemInputHandler implements IContainerInputHandler {
|
||||
|| ItemPanels.bookmarkPanel.contains(mousex, mousey))
|
||||
return false;
|
||||
|
||||
ItemStack stackover = GuiContainerManager.getStackMouseOver(gui);
|
||||
return ShortcutInputHandler.handleMouseClick(GuiContainerManager.getStackMouseOver(gui));
|
||||
}
|
||||
|
||||
return ShortcutInputHandler.handleMouseClick(stackover);
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
|
||||
if ((gui instanceof GuiRecipe) || ItemPanels.itemPanel.contains(mousex, mousey)
|
||||
|| ItemPanels.bookmarkPanel.contains(mousex, mousey)
|
||||
|| ItemPanels.itemPanel.historyPanel.contains(mousex, mousey)) {
|
||||
hotkeys.putAll(
|
||||
ShortcutInputHandler
|
||||
.handleHotkeys(gui, mousex, mousey, GuiContainerManager.getStackMouseOver(gui)));
|
||||
}
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,8 +4,8 @@ import static codechicken.nei.LayoutManager.searchField;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.SearchField;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
|
||||
public class SearchInputDropHandler extends INEIGuiAdapter {
|
||||
@@ -14,14 +14,7 @@ public class SearchInputDropHandler extends INEIGuiAdapter {
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button) {
|
||||
|
||||
if (searchField.isVisible() && searchField.contains(mouseX, mouseY)) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(draggedStack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
searchField.setText(formattingText(fluidStack.getLocalizedName()));
|
||||
} else {
|
||||
searchField.setText(formattingText(draggedStack.getDisplayName()));
|
||||
}
|
||||
|
||||
searchField.setText(SearchField.getEscapedSearchText(draggedStack));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
@@ -14,9 +15,9 @@ class SearchRecipeHandler<H extends IRecipeHandler> {
|
||||
|
||||
public H original;
|
||||
|
||||
private ArrayList<Integer> filteredRecipes;
|
||||
private List<Integer> filteredRecipes;
|
||||
|
||||
private ArrayList<Integer> searchRecipes;
|
||||
private List<Integer> searchRecipes;
|
||||
|
||||
public SearchRecipeHandler(H handler) {
|
||||
this.original = handler;
|
||||
@@ -52,7 +53,7 @@ class SearchRecipeHandler<H extends IRecipeHandler> {
|
||||
return handler instanceof TemplateRecipeHandler;
|
||||
}
|
||||
|
||||
public static int findFirst(IRecipeHandler handler, Predicate<Integer> predicate) {
|
||||
public static int findFirst(IRecipeHandler handler, IntPredicate predicate) {
|
||||
final IRecipeFilter filter = searchingAvailable(handler) ? GuiRecipe.getRecipeListFilter() : null;
|
||||
int refIndex = -1;
|
||||
|
||||
@@ -69,14 +70,14 @@ class SearchRecipeHandler<H extends IRecipeHandler> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getSearchResult(IRecipeFilter filter) {
|
||||
public List<Integer> getSearchResult(IRecipeFilter filter) {
|
||||
|
||||
if (filteredRecipes.isEmpty() || !this.searchingAvailable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<Integer> filtered = null;
|
||||
final ArrayList<Integer> recipes = IntStream.range(0, filteredRecipes.size()).boxed()
|
||||
List<Integer> filtered = null;
|
||||
final List<Integer> recipes = IntStream.range(0, filteredRecipes.size()).boxed()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
try {
|
||||
@@ -95,7 +96,7 @@ class SearchRecipeHandler<H extends IRecipeHandler> {
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public void setSearchIndices(ArrayList<Integer> searchRecipes) {
|
||||
public void setSearchIndices(List<Integer> searchRecipes) {
|
||||
this.searchRecipes = searchRecipes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +1,35 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraftforge.fluids.FluidContainerRegistry;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.ClientHandler;
|
||||
import codechicken.nei.ItemStackMap;
|
||||
import codechicken.nei.LRUCache;
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler;
|
||||
import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler;
|
||||
import codechicken.nei.util.ItemStackKey;
|
||||
|
||||
public class StackInfo {
|
||||
|
||||
public static final ArrayList<IStackStringifyHandler> stackStringifyHandlers = new ArrayList<>();
|
||||
private static final HashMap<String, HashMap<String, String[]>> guidfilters = new HashMap<>();
|
||||
private static final WeakHashMap<ItemStack, String> guidcache = new WeakHashMap<>();
|
||||
private static final LinkedHashMap<ItemStack, FluidStack> fluidcache = new LinkedHashMap<ItemStack, FluidStack>() {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<ItemStack, FluidStack> eldest) {
|
||||
return size() > 20;
|
||||
}
|
||||
};
|
||||
private static final FluidStack NULL_FLUID = new FluidStack(FluidRegistry.WATER, 0);
|
||||
public static final List<IStackStringifyHandler> stackStringifyHandlers = new ArrayList<>();
|
||||
private static final Map<String, HashMap<String, String[]>> guidfilters = new HashMap<>();
|
||||
private static final ItemStackMap<String> guidcache = new ItemStackMap<>();
|
||||
private static final LRUCache<ItemStackKey, FluidStack> fluidcache = new LRUCache<>(200);
|
||||
|
||||
static {
|
||||
stackStringifyHandlers.add(new DefaultStackStringifyHandler());
|
||||
@@ -83,8 +73,20 @@ public class StackInfo {
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack withAmount(ItemStack stack, long customCount) {
|
||||
if (stack == null) return null;
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
|
||||
return nbTag != null ? loadFromNBT(nbTag, customCount) : null;
|
||||
}
|
||||
|
||||
public static int getAmount(ItemStack stack) {
|
||||
if (stack == null) return 0;
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
|
||||
return nbTag != null ? nbTag.getInteger("Count") : 0;
|
||||
}
|
||||
|
||||
public static boolean equalItemAndNBT(ItemStack stackA, ItemStack stackB, boolean useNBT) {
|
||||
if (!stackA.isItemEqual(stackB)) {
|
||||
if (stackA == null || stackB == null || !stackA.isItemEqual(stackB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,19 +101,20 @@ public class StackInfo {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static FluidStack getFluid(ItemStack stack) {
|
||||
FluidStack fluid = fluidcache.get(stack);
|
||||
public static synchronized FluidStack getFluid(ItemStack stack) {
|
||||
ItemStackKey key = new ItemStackKey(stack);
|
||||
FluidStack fluid = fluidcache.get(key);
|
||||
|
||||
if (fluid == null && !fluidcache.containsKey(stack)) {
|
||||
if (fluid == null) {
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) {
|
||||
fluid = stackStringifyHandlers.get(i).getFluid(stack);
|
||||
}
|
||||
|
||||
fluidcache.put(stack, fluid);
|
||||
fluidcache.put(key, fluid == null ? NULL_FLUID : fluid);
|
||||
}
|
||||
|
||||
return fluid;
|
||||
return fluid == NULL_FLUID ? null : fluid;
|
||||
}
|
||||
|
||||
public static boolean isFluidContainer(ItemStack stack) {
|
||||
@@ -119,64 +122,67 @@ public class StackInfo {
|
||||
}
|
||||
|
||||
public static String getItemStackGUID(ItemStack stack) {
|
||||
if (!guidcache.containsKey(stack)) {
|
||||
String guid = guidcache.get(stack);
|
||||
|
||||
final NBTTagCompound nbTag = itemStackToNBT(stack, false);
|
||||
if (guid != null) {
|
||||
return guid;
|
||||
}
|
||||
|
||||
if (nbTag == null) {
|
||||
return null;
|
||||
}
|
||||
final NBTTagCompound nbTag = itemStackToNBT(stack, false);
|
||||
|
||||
nbTag.removeTag("Count");
|
||||
if (nbTag == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (nbTag.getShort("Damage") == 0) {
|
||||
nbTag.removeTag("Damage");
|
||||
}
|
||||
nbTag.removeTag("Count");
|
||||
|
||||
if (nbTag.hasKey("tag") && nbTag.getCompoundTag("tag").hasNoTags()) {
|
||||
nbTag.removeTag("tag");
|
||||
}
|
||||
if (nbTag.getShort("Damage") == 0) {
|
||||
nbTag.removeTag("Damage");
|
||||
}
|
||||
|
||||
if (nbTag.hasKey("strId") && guidfilters.containsKey(nbTag.getString("strId"))) {
|
||||
final ArrayList<String> keys = new ArrayList<>();
|
||||
final String strId = nbTag.getString("strId");
|
||||
if (nbTag.hasKey("tag") && nbTag.getCompoundTag("tag").hasNoTags()) {
|
||||
nbTag.removeTag("tag");
|
||||
}
|
||||
|
||||
keys.add(strId);
|
||||
if (nbTag.hasKey("strId") && guidfilters.containsKey(nbTag.getString("strId"))) {
|
||||
final ArrayList<String> keys = new ArrayList<>();
|
||||
final String strId = nbTag.getString("strId");
|
||||
|
||||
guidfilters.get(strId).forEach((key, rule) -> {
|
||||
Object local = nbTag;
|
||||
keys.add(strId);
|
||||
|
||||
for (int i = 0; i < rule.length; i++) {
|
||||
guidfilters.get(strId).forEach((key, rule) -> {
|
||||
Object local = nbTag;
|
||||
|
||||
try {
|
||||
for (int i = 0; i < rule.length; i++) {
|
||||
|
||||
if (local instanceof NBTTagCompound) {
|
||||
local = ((NBTTagCompound) local).getTag(rule[i]);
|
||||
} else if (local instanceof NBTTagList) {
|
||||
local = ((NBTTagList) local).tagList.get(Integer.parseInt(rule[i]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (local instanceof NBTTagCompound item) {
|
||||
local = item.getTag(rule[i]);
|
||||
} else if (local instanceof NBTTagList item) {
|
||||
local = item.tagList.get(Integer.parseInt(rule[i]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (local instanceof NBTBase) {
|
||||
keys.add(((NBTBase) local).toString());
|
||||
} else if (local != null) {
|
||||
keys.add(String.valueOf(local));
|
||||
} catch (Throwable e) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, keys.toString());
|
||||
}
|
||||
} else {
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, nbTag.toString());
|
||||
if (local instanceof NBTBase item) {
|
||||
keys.add(item.toString());
|
||||
} else if (local != null) {
|
||||
keys.add(String.valueOf(local));
|
||||
}
|
||||
});
|
||||
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, keys.toString());
|
||||
}
|
||||
} else {
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, nbTag.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,37 +190,9 @@ public class StackInfo {
|
||||
}
|
||||
|
||||
public static void loadGuidFilters() {
|
||||
|
||||
guidfilters.clear();
|
||||
|
||||
final File guidFlitersFile = new File(NEIClientConfig.configDir, "guidfilters.cfg");
|
||||
List<String> itemStrings = new ArrayList<>();
|
||||
|
||||
if (guidFlitersFile.exists()) {
|
||||
|
||||
try (FileReader reader = new FileReader(guidFlitersFile)) {
|
||||
NEIClientConfig.logger.info("Loading guid filters from file {}", guidFlitersFile);
|
||||
itemStrings = IOUtils.readLines(reader);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load bookmarks from file {}", guidFlitersFile, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else {
|
||||
final URL filterUrl = StackInfo.class.getResource("/assets/nei/guidfilters.cfg");
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(filterUrl.openStream()))) {
|
||||
itemStrings = IOUtils.readLines(reader);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.info("Error parsing guid filters");
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.info("Error parsing guid filters");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (String guidStr : itemStrings) {
|
||||
ClientHandler.loadSettingsFile("guidfilters.cfg", lines -> lines.forEach(guidStr -> {
|
||||
final String[] parts = guidStr.split(",");
|
||||
final HashMap<String, String[]> rules = new HashMap<>();
|
||||
|
||||
@@ -223,7 +201,7 @@ public class StackInfo {
|
||||
}
|
||||
|
||||
guidfilters.put(parts[0], rules);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public static ItemStack getItemStackWithMinimumDamage(ItemStack[] stacks) {
|
||||
@@ -232,7 +210,7 @@ public class StackInfo {
|
||||
|
||||
if (stacks.length > 1) {
|
||||
for (ItemStack stack : stacks) {
|
||||
if (stack.getItem() != null && stack.getItemDamage() < damage) {
|
||||
if (stack.getItem() != null && !ItemInfo.isHidden(stack) && stack.getItemDamage() < damage) {
|
||||
damage = stack.getItemDamage();
|
||||
result = stack;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.changeTexture;
|
||||
import static codechicken.lib.gui.GuiDraw.drawTexturedModalRect;
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -32,10 +29,9 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
@@ -44,8 +40,6 @@ import codechicken.nei.api.DefaultOverlayRenderer;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
import codechicken.nei.api.IStackPositioner;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
@@ -187,50 +181,31 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public List<PositionedStack> getCycledIngredients(int cycle, List<PositionedStack> ingredients) {
|
||||
|
||||
if (!NEIClientUtils.shiftKey() && !disableCycledIngredients) {
|
||||
if (NEIClientConfig.useJEIStyledCycledIngredients()) {
|
||||
jeiStyledRenderPermutation(ingredients, cycle);
|
||||
} else {
|
||||
randomRenderPermutation(ingredients, cycle);
|
||||
}
|
||||
randomRenderPermutation(ingredients, cycle);
|
||||
}
|
||||
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
protected void randomRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
final int randCycle = Math.abs(new Random(cycle + offset).nextInt());
|
||||
public void randomRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
cycle = NEIClientConfig.useJEIStyledCycledIngredients() ? cycle
|
||||
: Math.abs(new Random(cycle + offset).nextInt());
|
||||
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (stack.items.length <= 1) continue;
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(stack, filter);
|
||||
if (filtered.isEmpty()) {
|
||||
stack.setPermutationToRender((int) (randCycle % stack.items.length));
|
||||
} else {
|
||||
stack.setPermutationToRender(filtered.get((int) (randCycle % filtered.size())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void jeiStyledRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (stack.items.length <= 1) continue;
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(stack, filter);
|
||||
if (filtered.isEmpty()) {
|
||||
stack.setPermutationToRender((int) (cycle % stack.items.length));
|
||||
} else {
|
||||
stack.setPermutationToRender(filtered.get((int) (cycle % filtered.size())));
|
||||
}
|
||||
for (PositionedStack pStack : stacks) {
|
||||
if (pStack.items.length <= 1) continue;
|
||||
final List<ItemStack> items = pStack.getFilteredPermutations();
|
||||
pStack.setPermutationToRender(items.get((int) (cycle % items.size())));
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void randomRenderPermutation(PositionedStack stack, long cycle) {
|
||||
Random rand = new Random(cycle + offset);
|
||||
stack.setPermutationToRender((int) (Math.abs(rand.nextInt()) % stack.items.length));
|
||||
public void randomRenderPermutation(PositionedStack stack, long cycle) {
|
||||
cycle = NEIClientConfig.useJEIStyledCycledIngredients() ? cycle
|
||||
: Math.abs(new Random(cycle + offset).nextInt());
|
||||
|
||||
if (stack.items.length <= 1) return;
|
||||
final List<ItemStack> items = stack.getFilteredPermutations();
|
||||
stack.setPermutationToRender(items.get((int) (cycle % items.size())));
|
||||
}
|
||||
|
||||
public void setIngredientPermutation(Collection<PositionedStack> ingredients, ItemStack ingredient) {
|
||||
@@ -311,7 +286,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
public static class RecipeTransferRectHandler implements IContainerInputHandler, IContainerTooltipHandler {
|
||||
|
||||
private static final HashMap<Class<? extends GuiContainer>, HashSet<RecipeTransferRect>> guiMap = new HashMap<>();
|
||||
private static final Map<Class<? extends GuiContainer>, HashSet<RecipeTransferRect>> guiMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void registerRectsToGuis(List<Class<? extends GuiContainer>> classes,
|
||||
List<RecipeTransferRect> rects) {
|
||||
@@ -430,25 +405,6 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
RecipeTransferRectHandler.registerRectsToGuis(getRecipeTransferRectGuis(), transferRects);
|
||||
}
|
||||
|
||||
protected static ItemFilter getItemFilter() {
|
||||
return new AllMultiItemFilter(
|
||||
item -> !ItemInfo.hiddenItems.contains(item),
|
||||
LayoutManager.presetsPanel != null ? LayoutManager.presetsPanel.getFilter() : null,
|
||||
GuiRecipe.searchField != null ? GuiRecipe.searchField.getFilter() : null);
|
||||
}
|
||||
|
||||
protected static ArrayList<Integer> getFilteredIngredientAlternatives(PositionedStack stack, ItemFilter filter) {
|
||||
final ArrayList<Integer> filtered = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < stack.items.length; i++) {
|
||||
if (filter.matches(stack.items[i])) {
|
||||
filtered.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all RecipeTransferRects to the transferRects list during this call. Afterward they may be added to the input
|
||||
* handler for the corresponding guis from getRecipeTransferRectGuis
|
||||
@@ -552,16 +508,16 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
switch (direction) {
|
||||
case 0: // right
|
||||
drawTexturedModalRect(x, y, tx, ty, var, h);
|
||||
GuiDraw.drawTexturedModalRect(x, y, tx, ty, var, h);
|
||||
break;
|
||||
case 1: // down
|
||||
drawTexturedModalRect(x, y, tx, ty, w, var);
|
||||
GuiDraw.drawTexturedModalRect(x, y, tx, ty, w, var);
|
||||
break;
|
||||
case 2: // left
|
||||
drawTexturedModalRect(x + w - var, y, tx + w - var, ty, var, h);
|
||||
GuiDraw.drawTexturedModalRect(x + w - var, y, tx + w - var, ty, var, h);
|
||||
break;
|
||||
case 3: // up
|
||||
drawTexturedModalRect(x, y + h - var, tx, ty + h - var, w, var);
|
||||
GuiDraw.drawTexturedModalRect(x, y + h - var, tx, ty + h - var, w, var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -594,7 +550,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
// available
|
||||
// This will ideally have been pre-cached elsewhere and will be a NOOP
|
||||
findFuelsOnce();
|
||||
return getClass().newInstance();
|
||||
return getClass().getConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -649,14 +605,14 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
public void drawBackground(int recipe) {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
changeTexture(getGuiTexture());
|
||||
drawTexturedModalRect(0, 0, 5, 11, 166, 65);
|
||||
GuiDraw.changeTexture(getGuiTexture());
|
||||
GuiDraw.drawTexturedModalRect(0, 0, 5, 11, 166, 65);
|
||||
}
|
||||
|
||||
public void drawForeground(int recipe) {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
changeTexture(getGuiTexture());
|
||||
GuiDraw.changeTexture(getGuiTexture());
|
||||
drawExtras(recipe);
|
||||
}
|
||||
|
||||
@@ -703,7 +659,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiRecipe<?> gui, List<String> currenttip, int recipe) {
|
||||
if (GuiContainerManager.shouldShowTooltip(gui) && currenttip.size() == 0) {
|
||||
if (GuiContainerManager.shouldShowTooltip(gui) && currenttip.isEmpty()) {
|
||||
Point offset = gui.getRecipePosition(recipe);
|
||||
currenttip = transferRectTooltip(gui, transferRects, offset.x, offset.y, currenttip);
|
||||
}
|
||||
@@ -743,21 +699,32 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public boolean mouseScrolled(GuiRecipe<?> gui, int scroll, int recipe) {
|
||||
if (!NEIClientUtils.shiftKey()) return false;
|
||||
|
||||
final Point pos = getMousePosition();
|
||||
final Point pos = GuiDraw.getMousePosition();
|
||||
final Point offset = gui.getRecipePosition(recipe);
|
||||
final Point relMouse = new Point(pos.x - gui.guiLeft - offset.x, pos.y - gui.guiTop - offset.y);
|
||||
final PositionedStack overStack = getIngredientMouseOver(relMouse.x, relMouse.y, recipe);
|
||||
|
||||
if (overStack != null && overStack.items.length > 1) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
final List<ItemStack> items = overStack.getFilteredPermutations();
|
||||
int stackIndex = 0;
|
||||
|
||||
for (int index = 0; index < items.size(); index++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(items.get(index), overStack.item)) {
|
||||
stackIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final ItemStack stack = items.get((items.size() - scroll + stackIndex) % items.size());
|
||||
|
||||
if (NEIClientConfig.useJEIStyledCycledIngredients()) {
|
||||
ItemStack stack = overStack.item;
|
||||
for (PositionedStack pStack : getIngredientStacks(recipe)) {
|
||||
shiftPermutationToRender(pStack, stack, scroll, filter);
|
||||
if (pStack.containsWithNBT(stack)) {
|
||||
pStack.setPermutationToRender(stack);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shiftPermutationToRender(overStack, overStack.item, scroll, filter);
|
||||
overStack.setPermutationToRender(stack);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -766,24 +733,6 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
return false;
|
||||
}
|
||||
|
||||
private void shiftPermutationToRender(PositionedStack pStack, ItemStack stack, int scroll, ItemFilter filter) {
|
||||
|
||||
for (int index = 0; index < pStack.items.length; index++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[index], stack)) {
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(pStack, filter);
|
||||
|
||||
if (filtered.isEmpty()) {
|
||||
pStack.setPermutationToRender((int) ((pStack.items.length + scroll + index) % pStack.items.length));
|
||||
} else {
|
||||
pStack.setPermutationToRender(
|
||||
filtered.get((int) ((filtered.size() + scroll + index) % filtered.size())));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PositionedStack getIngredientMouseOver(int mousex, int mousey, int recipe) {
|
||||
|
||||
for (PositionedStack pStack : getIngredientStacks(recipe)) {
|
||||
@@ -802,7 +751,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
private static boolean transferRect(GuiContainer gui, Collection<RecipeTransferRect> transferRects, int offsetx,
|
||||
int offsety, boolean usage) {
|
||||
Point pos = getMousePosition();
|
||||
Point pos = GuiDraw.getMousePosition();
|
||||
Point relMouse = new Point(pos.x - gui.guiLeft - offsetx, pos.y - gui.guiTop - offsety);
|
||||
for (RecipeTransferRect rect : transferRects) {
|
||||
if (rect.rect.contains(relMouse) && (usage ? GuiUsageRecipe.openRecipeGui(rect.outputId, rect.results)
|
||||
@@ -815,7 +764,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
private static List<String> transferRectTooltip(GuiContainer gui, Collection<RecipeTransferRect> transferRects,
|
||||
int offsetx, int offsety, List<String> currenttip) {
|
||||
Point pos = getMousePosition();
|
||||
Point pos = GuiDraw.getMousePosition();
|
||||
Point relMouse = new Point(pos.x - gui.guiLeft - offsetx, pos.y - gui.guiTop - offsety);
|
||||
for (RecipeTransferRect rect : transferRects) {
|
||||
if (rect.rect.contains(relMouse)) {
|
||||
|
||||
@@ -11,22 +11,27 @@ import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
|
||||
|
||||
protected static Class<?> GTDisplayFluid = null;
|
||||
protected static Class<?> itemFluidDisplay = null;
|
||||
protected static Method getFluidDisplayStack = null;
|
||||
protected static Method getFluidFromDisplayStack = null;
|
||||
public static boolean replaceAE2FCFluidDrop = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
final Class<?> gtUtility = Class.forName("gregtech.api.util.GT_Utility");
|
||||
final ClassLoader loader = GTFluidStackStringifyHandler.class.getClassLoader();
|
||||
final Class<?> gtUtility = ReflectionHelper
|
||||
.getClass(loader, "gregtech.api.util.GTUtility", "gregtech.api.util.GT_Utility");
|
||||
|
||||
GTDisplayFluid = Class.forName("gregtech.common.items.GT_FluidDisplayItem");
|
||||
itemFluidDisplay = ReflectionHelper.getClass(
|
||||
loader,
|
||||
"gregtech.common.items.ItemFluidDisplay",
|
||||
"gregtech.common.items.GT_FluidDisplayItem");
|
||||
getFluidFromDisplayStack = gtUtility.getMethod("getFluidFromDisplayStack", ItemStack.class);
|
||||
getFluidDisplayStack = gtUtility.getMethod("getFluidDisplayStack", FluidStack.class, boolean.class);
|
||||
|
||||
} catch (Exception ignored) {
|
||||
/* Do nothing */
|
||||
}
|
||||
@@ -72,7 +77,7 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
|
||||
final Item item = stack.getItem();
|
||||
|
||||
try {
|
||||
if (getFluidFromDisplayStack != null && GTDisplayFluid != null && GTDisplayFluid.isInstance(item)) {
|
||||
if (getFluidFromDisplayStack != null && itemFluidDisplay != null && itemFluidDisplay.isInstance(item)) {
|
||||
final Object obj = getFluidFromDisplayStack.invoke(null, stack);
|
||||
|
||||
if (obj != null) {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package codechicken.nei.search;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
|
||||
public class IdentifierFilter implements ItemFilter {
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
public IdentifierFilter(Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack stack) {
|
||||
return this.pattern.matcher(getStringIdentifier(stack) + "\n" + getIdentifier(stack)).find();
|
||||
}
|
||||
|
||||
protected String getIdentifier(ItemStack stack) {
|
||||
return Item.getIdFromItem(stack.getItem()) + ":" + stack.getItemDamage();
|
||||
}
|
||||
|
||||
protected String getStringIdentifier(ItemStack stack) {
|
||||
String name = GameData.getItemRegistry().getNameForObject(stack.getItem());
|
||||
return name == null || name.isEmpty() ? "Unknown:Unknown" : name;
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 134 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user