├── jitpack.yml ├── repositories.gradle ├── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src └── main │ ├── java │ └── com │ │ └── github │ │ └── vfyjxf │ │ └── neiutilities │ │ ├── config │ │ ├── SplittingMode.java │ │ └── NeiUtilitiesConfig.java │ │ ├── mixins │ │ └── ItemPanels.java │ │ ├── MixinPlugin.java │ │ ├── nei │ │ ├── NEIConfig.java │ │ └── AdvancedItemPanel.java │ │ ├── NEIUtilities.java │ │ └── gui │ │ └── ItemInfoHelper.java │ └── resources │ ├── assets │ └── neiutilities │ │ └── lang │ │ ├── zh_CN.lang │ │ └── en_US.lang │ ├── mixins.neiutilities.json │ └── mcmod.info ├── .github └── workflows │ ├── release-tags.yml │ └── build-and-test.yml ├── .editorconfig ├── settings.gradle ├── .gitignore ├── LICENSE ├── .gitattributes ├── gradlew.bat ├── dependencies.gradle ├── gradlew └── gradle.properties /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - ./gradlew setupCIWorkspace -------------------------------------------------------------------------------- /repositories.gradle: -------------------------------------------------------------------------------- 1 | // Add any additional repositories for your dependencies here 2 | 3 | repositories {} 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NEI-Utilities 2 | More enhancements for NEI 3 | 4 | 5 | ## Credits 6 | Thanks for the idea from NEI easy search 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RealSilverMoon/NEI-Utilities/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/config/SplittingMode.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.config; 2 | 3 | public enum SplittingMode { 4 | BACKGROUND, 5 | DOTTED_LINE 6 | } 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/neiutilities/lang/zh_CN.lang: -------------------------------------------------------------------------------- 1 | nei.options.keys.neiutilities=NEI Utilities 2 | nei.options.keys.neiutilities.utils=实用功能 3 | nei.options.keys.neiutilities.utils.copy_name=复制物品名称 4 | nei.options.keys.neiutilities.utils.copy_oredict=复制物品矿词词典 -------------------------------------------------------------------------------- /src/main/resources/assets/neiutilities/lang/en_US.lang: -------------------------------------------------------------------------------- 1 | nei.options.keys.neiutilities=NEI Utilities 2 | nei.options.keys.neiutilities.utils=Utils 3 | nei.options.keys.neiutilities.utils.copy_name=Copy Item Name 4 | nei.options.keys.neiutilities.utils.copy_oredict=Copy Item OreDictionary 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.github/workflows/release-tags.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Release tagged build 3 | 4 | on: 5 | push: 6 | tags: [ '*' ] 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | release-tags: 13 | uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Build and test 3 | 4 | on: 5 | pull_request: 6 | branches: [ master, main ] 7 | push: 8 | branches: [ master, main ] 9 | 10 | jobs: 11 | build-and-test: 12 | uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /src/main/resources/mixins.neiutilities.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8.5-GTNH", 4 | "package": "com.github.vfyjxf.neiutilities.mixins", 5 | "refmap": "mixins.neiutilities.refmap.json", 6 | "target": "@env(DEFAULT)", 7 | "compatibilityLevel": "JAVA_8", 8 | "client": [ 9 | "ItemPanels" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [{ 2 | "modid": "${modId}", 3 | "name": "${modName}", 4 | "description": "", 5 | "version": "0.1.8", 6 | "mcversion": "1.7.10", 7 | "url": "", 8 | "updateUrl": "", 9 | "authorList": ["vfyjxf_"], 10 | "credits": "Thanks for the idea from NEI easy search", 11 | "logoFile": "logo.png", 12 | "screenshots": [], 13 | "dependencies": [] 14 | }] 15 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/mixins/ItemPanels.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.mixins; 2 | 3 | import org.spongepowered.asm.mixin.Mixin; 4 | import org.spongepowered.asm.mixin.gen.Accessor; 5 | 6 | import codechicken.nei.ItemPanel; 7 | 8 | @Mixin(value = codechicken.nei.ItemPanels.class) 9 | public interface ItemPanels { 10 | 11 | @Accessor(remap = false) 12 | public static void setItemPanel(ItemPanel itemPanel) {} 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This is the universal Text Editor Configuration 2 | # for all GTNewHorizons projects 3 | # See: https://editorconfig.org/ 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 4 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.{bat,ini}] 16 | end_of_line = crlf 17 | 18 | [*.{dtd,json,info,mcmeta,md,sh,svg,xml,xsd,xsl,yaml,yml}] 19 | indent_size = 2 20 | 21 | [*.lang] 22 | trim_trailing_whitespace = false 23 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | 2 | pluginManagement { 3 | repositories { 4 | maven { 5 | // RetroFuturaGradle 6 | name "GTNH Maven" 7 | url "https://nexus.gtnewhorizons.com/repository/public/" 8 | mavenContent { 9 | includeGroup("com.gtnewhorizons") 10 | includeGroupByRegex("com\\.gtnewhorizons\\..+") 11 | } 12 | } 13 | gradlePluginPortal() 14 | mavenCentral() 15 | mavenLocal() 16 | } 17 | } 18 | 19 | plugins { 20 | id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.14' 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .settings 3 | /.idea/ 4 | /.vscode/ 5 | /run/ 6 | /build/ 7 | /eclipse/ 8 | .classpath 9 | .project 10 | /bin/ 11 | /config/ 12 | /crash-reports/ 13 | /logs/ 14 | options.txt 15 | /saves/ 16 | usernamecache.json 17 | banned-ips.json 18 | banned-players.json 19 | eula.txt 20 | ops.json 21 | server.properties 22 | servers.dat 23 | usercache.json 24 | whitelist.json 25 | /out/ 26 | *.iml 27 | *.ipr 28 | *.iws 29 | src/main/resources/mixins.*([!.]).json 30 | *.bat 31 | *.DS_Store 32 | !gradlew.bat 33 | .factorypath 34 | addon.local.gradle 35 | addon.local.gradle.kts 36 | addon.late.local.gradle 37 | addon.late.local.gradle.kts 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/MixinPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; 8 | import com.gtnewhorizon.gtnhmixins.LateMixin; 9 | 10 | @LateMixin 11 | public class MixinPlugin implements ILateMixinLoader { 12 | 13 | @Override 14 | public String getMixinConfig() { 15 | return "mixins.neiutilities.json"; 16 | } 17 | 18 | @Override 19 | public List getMixins(Set loadedMods) { 20 | return Arrays.asList("ItemPanels"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 vfyjxf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.[jJ][aA][rR] binary 4 | 5 | *.[pP][nN][gG] binary 6 | *.[jJ][pP][gG] binary 7 | *.[jJ][pP][eE][gG] binary 8 | *.[gG][iI][fF] binary 9 | *.[tT][iI][fF] binary 10 | *.[tT][iI][fF][fF] binary 11 | *.[iI][cC][oO] binary 12 | *.[sS][vV][gG] text 13 | *.[eE][pP][sS] binary 14 | *.[xX][cC][fF] binary 15 | 16 | *.[kK][aA][rR] binary 17 | *.[mM]4[aA] binary 18 | *.[mM][iI][dD] binary 19 | *.[mM][iI][dD][iI] binary 20 | *.[mM][pP]3 binary 21 | *.[oO][gG][gG] binary 22 | *.[rR][aA] binary 23 | 24 | *.7[zZ] binary 25 | *.[gG][zZ] binary 26 | *.[tT][aA][rR] binary 27 | *.[tT][gG][zZ] binary 28 | *.[zZ][iI][pP] binary 29 | 30 | *.[tT][cC][nN] binary 31 | *.[sS][oO] binary 32 | *.[dD][lL][lL] binary 33 | *.[dD][yY][lL][iI][bB] binary 34 | *.[pP][sS][dD] binary 35 | *.[tT][tT][fF] binary 36 | *.[oO][tT][fF] binary 37 | 38 | *.[pP][aA][tT][cC][hH] -text 39 | 40 | *.[bB][aA][tT] text eol=crlf 41 | *.[cC][mM][dD] text eol=crlf 42 | *.[pP][sS]1 text eol=crlf 43 | 44 | *[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary 45 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/nei/NEIConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.nei; 2 | 3 | import org.lwjgl.input.Keyboard; 4 | 5 | import com.github.vfyjxf.neiutilities.NEIUtilities; 6 | import com.github.vfyjxf.neiutilities.Tags; 7 | import com.github.vfyjxf.neiutilities.gui.ItemInfoHelper; 8 | import com.github.vfyjxf.neiutilities.mixins.ItemPanels; 9 | 10 | import codechicken.nei.api.API; 11 | import codechicken.nei.api.IConfigureNEI; 12 | import codechicken.nei.guihook.GuiContainerManager; 13 | 14 | public class NEIConfig implements IConfigureNEI { 15 | 16 | public static final String COPY_NAME_KEY = "neiutilities.utils.copy_name"; 17 | public static final String COPY_OREDICT_KEY = "neiutilities.utils.copy_oredict"; 18 | 19 | @Override 20 | public void loadConfig() { 21 | { 22 | API.registerUsageHandler(AdvancedItemPanel.INSTANCE); 23 | API.registerRecipeHandler(AdvancedItemPanel.INSTANCE); 24 | GuiContainerManager.addInputHandler(AdvancedItemPanel.INSTANCE); 25 | } 26 | { 27 | GuiContainerManager.addInputHandler(new ItemInfoHelper()); 28 | API.addKeyBind(COPY_NAME_KEY, Keyboard.KEY_C); 29 | API.addKeyBind(COPY_OREDICT_KEY, Keyboard.KEY_D); 30 | } 31 | } 32 | 33 | public static void setItemPanel() { 34 | try { 35 | ItemPanels.setItemPanel(AdvancedItemPanel.INSTANCE); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | @Override 42 | public String getName() { 43 | return NEIUtilities.NAME; 44 | } 45 | 46 | @Override 47 | public String getVersion() { 48 | return Tags.VERSION; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/config/NeiUtilitiesConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.config; 2 | 3 | import java.io.File; 4 | 5 | import net.minecraftforge.common.config.Configuration; 6 | 7 | public class NeiUtilitiesConfig { 8 | 9 | public static Configuration config; 10 | 11 | private static final String CATEGORY_HISTORY = "history"; 12 | 13 | public static int historyColor = 0xee555555; 14 | public static int useRows = 2; 15 | private static SplittingMode splittingMode = SplittingMode.BACKGROUND; 16 | 17 | public static void initConfig(File configFile) { 18 | config = new Configuration(configFile); 19 | config.load(); 20 | { 21 | historyColor = Integer.parseUnsignedInt( 22 | config.getString("historyColor", CATEGORY_HISTORY, "ee555555", "Color of the history area display"), 23 | 16); 24 | useRows = config.getInt("useRows", "rows", 2, 1, 5, "Rows used in historical areas"); 25 | try { 26 | splittingMode = SplittingMode.valueOf( 27 | config.getString( 28 | "splittingMode", 29 | CATEGORY_HISTORY, 30 | SplittingMode.DOTTED_LINE.name(), 31 | "Splitting mode for the browsing history.\n" + "Mode : BACKGROUND,DOTTED_LINE")); 32 | } catch (IllegalArgumentException | NullPointerException e) { 33 | // set default mode 34 | splittingMode = SplittingMode.BACKGROUND; 35 | } 36 | } 37 | if (config.hasChanged()) { 38 | config.save(); 39 | } 40 | } 41 | 42 | public static SplittingMode getSplittingMode() { 43 | return splittingMode; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/NEIUtilities.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities; 2 | 3 | import java.io.File; 4 | 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | 8 | import com.github.vfyjxf.neiutilities.config.NeiUtilitiesConfig; 9 | import com.github.vfyjxf.neiutilities.nei.AdvancedItemPanel; 10 | import com.github.vfyjxf.neiutilities.nei.NEIConfig; 11 | 12 | import codechicken.nei.ItemPanels; 13 | import cpw.mods.fml.common.Mod; 14 | import cpw.mods.fml.common.Mod.EventHandler; 15 | import cpw.mods.fml.common.event.FMLInitializationEvent; 16 | import cpw.mods.fml.common.event.FMLPreInitializationEvent; 17 | import cpw.mods.fml.relauncher.Side; 18 | import cpw.mods.fml.relauncher.SideOnly; 19 | 20 | @Mod( 21 | modid = NEIUtilities.MODID, 22 | version = Tags.VERSION, 23 | name = NEIUtilities.NAME, 24 | dependencies = NEIUtilities.DEPENDENCIES) 25 | public class NEIUtilities { 26 | 27 | public static final String MODID = "neiutilities"; 28 | public static final String NAME = "NEI Utilities"; 29 | public static final String DEPENDENCIES = "required-after:NotEnoughItems"; 30 | 31 | public static final Logger logger = LogManager.getLogger(NEIUtilities.NAME); 32 | 33 | @SideOnly(Side.CLIENT) 34 | @EventHandler 35 | public void preInit(FMLPreInitializationEvent event) { 36 | NeiUtilitiesConfig.initConfig( 37 | new File( 38 | event.getModConfigurationDirectory() 39 | .getPath(), 40 | "neiutilities.cfg")); 41 | } 42 | 43 | @SideOnly(Side.CLIENT) 44 | @EventHandler 45 | public void init(FMLInitializationEvent event) { 46 | if (!(ItemPanels.itemPanel instanceof AdvancedItemPanel)) { 47 | NEIConfig.setItemPanel(); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /dependencies.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Add your dependencies here. Supported configurations: 3 | * - api("group:name:version:classifier"): if you use the types from this dependency in the public API of this mod 4 | * Available at runtime and compiletime for mods depending on this mod 5 | * - implementation("g:n:v:c"): if you need this for internal implementation details of the mod, but none of it is visible via the public API 6 | * Available at runtime but not compiletime for mods depending on this mod 7 | * - compileOnly("g:n:v:c"): if the mod you're building doesn't need this dependency during runtime at all, e.g. for optional mods 8 | * Not available at all for mods depending on this mod, only visible at compiletime for this mod 9 | * - compileOnlyApi("g:n:v:c"): like compileOnly, but also visible at compiletime for mods depending on this mod 10 | * Available at compiletime but not runtime for mods depending on this mod 11 | * - runtimeOnlyNonPublishable("g:n:v:c"): if you want to include a mod in this mod's runClient/runServer runs, but not publish it as a dependency 12 | * Not available at all for mods depending on this mod, only visible at runtime for this mod 13 | * - devOnlyNonPublishable("g:n:v:c"): a combination of runtimeOnlyNonPublishable and compileOnly for dependencies present at both compiletime and runtime, 14 | * but not published as Maven dependencies - useful for RFG-deobfuscated dependencies or local testing 15 | * - runtimeOnly("g:n:v:c"): if you don't need this at compile time, but want it to be present at runtime 16 | * Available at runtime for mods depending on this mod 17 | * - annotationProcessor("g:n:v:c"): mostly for java compiler plugins, if you know you need this, use it, otherwise don't worry 18 | * - testCONFIG("g:n:v:c") - replace CONFIG by one of the above (except api), same as above but for the test sources instead of main 19 | * 20 | * - shadowImplementation("g:n:v:c"): effectively the same as API, but the dependency is included in your jar under a renamed package name 21 | * Requires you to enable usesShadowedDependencies in gradle.properties 22 | * 23 | * - compile("g:n:v:c"): deprecated, replace with "api" (works like the old "compile") or "implementation" (can be more efficient) 24 | * 25 | * You can exclude transitive dependencies (dependencies of the chosen dependency) by appending { transitive = false } if needed, 26 | * but use this sparingly as it can break using your mod as another mod's dependency if you're not careful. 27 | * 28 | * To depend on obfuscated jars you can use `devOnlyNonPublishable(rfg.deobf("dep:spec:1.2.3"))` to fetch an obfuscated jar from maven, 29 | * or `devOnlyNonPublishable(rfg.deobf(project.files("libs/my-mod-jar.jar")))` to use a file. 30 | * 31 | * Gradle names for some of the configuration can be misleading, compileOnlyApi and runtimeOnly both get published as dependencies in Maven, but compileOnly does not. 32 | * The buildscript adds runtimeOnlyNonPublishable to also have a runtime dependency that's not published. 33 | * 34 | * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph 35 | */ 36 | dependencies { 37 | api('com.github.GTNewHorizons:CodeChickenLib:1.2.1:dev') 38 | api('com.github.GTNewHorizons:CodeChickenCore:1.2.1:dev') 39 | api("com.github.GTNewHorizons:NotEnoughItems:2.5.17-GTNH:dev") 40 | 41 | api('io.github.legacymoddingmc:unimixins:0.1.7.1:dev') 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/gui/ItemInfoHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.gui; 2 | 3 | import static codechicken.nei.NEIClientConfig.getKeyBinding; 4 | 5 | import java.awt.Toolkit; 6 | import java.awt.datatransfer.StringSelection; 7 | 8 | import net.minecraft.client.gui.inventory.GuiContainer; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraftforge.oredict.OreDictionary; 11 | 12 | import com.github.vfyjxf.neiutilities.nei.NEIConfig; 13 | 14 | import codechicken.nei.guihook.GuiContainerManager; 15 | import codechicken.nei.guihook.IContainerInputHandler; 16 | 17 | public class ItemInfoHelper implements IContainerInputHandler { 18 | 19 | @Override 20 | public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyId) { 21 | if (keyId == getKeyBinding(NEIConfig.COPY_NAME_KEY) || keyId == getKeyBinding(NEIConfig.COPY_OREDICT_KEY)) { 22 | if (GuiContainer.isCtrlKeyDown()) { 23 | ItemStack stackUnderMouse = GuiContainerManager.getStackMouseOver(gui); 24 | if (stackUnderMouse != null) { 25 | if (keyId == getKeyBinding(NEIConfig.COPY_NAME_KEY)) { 26 | Toolkit.getDefaultToolkit() 27 | .getSystemClipboard() 28 | .setContents(new StringSelection(stackUnderMouse.getDisplayName()), null); 29 | } else { 30 | StringBuilder builder = new StringBuilder(); 31 | for (int id : OreDictionary.getOreIDs(stackUnderMouse)) { 32 | String oreDictionaryName = OreDictionary.getOreName(id); 33 | if (!"Unknown".equals(oreDictionaryName)) { 34 | builder.append(oreDictionaryName) 35 | .append(","); 36 | } 37 | } 38 | if (builder.length() > 0) { 39 | builder.deleteCharAt(builder.length() - 1); 40 | } 41 | Toolkit.getDefaultToolkit() 42 | .getSystemClipboard() 43 | .setContents(new StringSelection(builder.toString()), null); 44 | } 45 | return true; 46 | } 47 | } 48 | } 49 | return false; 50 | } 51 | 52 | @Override 53 | public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { 54 | return false; 55 | } 56 | 57 | @Override 58 | public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) { 59 | 60 | } 61 | 62 | @Override 63 | public boolean mouseClicked(GuiContainer gui, int mouseX, int mouseY, int button) { 64 | return false; 65 | } 66 | 67 | @Override 68 | public void onMouseClicked(GuiContainer gui, int mouseX, int mouseY, int button) { 69 | 70 | } 71 | 72 | @Override 73 | public void onMouseUp(GuiContainer gui, int mouseX, int mouseY, int button) { 74 | 75 | } 76 | 77 | @Override 78 | public boolean mouseScrolled(GuiContainer gui, int mouseX, int mouseY, int scrolled) { 79 | return false; 80 | } 81 | 82 | @Override 83 | public void onMouseScrolled(GuiContainer gui, int mouseX, int mouseY, int scrolled) { 84 | 85 | } 86 | 87 | @Override 88 | public void onMouseDragged(GuiContainer gui, int mouseX, int mouseY, int button, long heldTime) { 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable. 2 | # LOCAL to test local config updates. 3 | gtnh.settings.blowdryerTag = 0.2.2 4 | 5 | # Human-readable mod name, available for mcmod.info population. 6 | modName = NEI Utilities 7 | 8 | # Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation. 9 | # Conventionally lowercase. 10 | modId = neiutilities 11 | 12 | # Root package of the mod, used to find various classes in other properties, 13 | # mcmod.info substitution, enabling assertions in run tasks, etc. 14 | modGroup = com.github.vfyjxf.neiutilities 15 | 16 | # Whether to use modGroup as the maven publishing group. 17 | # Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods. 18 | useModGroupForPublishing = false 19 | 20 | # Updates your build.gradle and settings.gradle automatically whenever an update is available. 21 | autoUpdateBuildScript = false 22 | 23 | # Version of Minecraft to target 24 | minecraftVersion = 1.7.10 25 | 26 | # Version of Minecraft Forge to target 27 | forgeVersion = 10.13.4.1614 28 | 29 | # Specify an MCP channel for dependency deobfuscation and the deobfParams task. 30 | channel = stable 31 | 32 | # Specify an MCP mappings version for dependency deobfuscation and the deobfParams task. 33 | mappingsVersion = 12 34 | 35 | # Defines other MCP mappings for dependency deobfuscation. 36 | remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ 37 | 38 | # Select a default username for testing your mod. You can always override this per-run by running 39 | # `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. 40 | developmentEnvironmentUserName = Developer 41 | 42 | # Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8. 43 | # See https://github.com/bsideup/jabel for details on how this works. 44 | enableModernJavaSyntax = true 45 | 46 | # Enables injecting missing generics into the decompiled source code for a better coding experience. 47 | # Turns most publicly visible List, Map, etc. into proper List, Map types. 48 | enableGenericInjection = false 49 | 50 | # Generate a class with a String field for the mod version named as defined below. 51 | # If generateGradleTokenClass is empty or not missing, no such class will be generated. 52 | # If gradleTokenVersion is empty or missing, the field will not be present in the class. 53 | generateGradleTokenClass = com.github.vfyjxf.neiutilities.Tags 54 | 55 | # Name of the token containing the project's current version to generate/replace. 56 | gradleTokenVersion = VERSION 57 | 58 | # [DEPRECATED] Mod ID replacement token. 59 | gradleTokenModId = 60 | 61 | # [DEPRECATED] Mod name replacement token. 62 | gradleTokenModName = 63 | 64 | # [DEPRECATED] Mod Group replacement token. 65 | gradleTokenGroupName = 66 | 67 | # [DEPRECATED] 68 | # Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java 69 | # public static final String VERSION = "GRADLETOKEN_VERSION"; 70 | # The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's 71 | # version in @Mod([...], version = VERSION, [...]). 72 | # Leave these properties empty to skip individual token replacements. 73 | replaceGradleTokenInFile = 74 | 75 | # In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can 76 | # leave this property empty. 77 | # Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api 78 | apiPackage = 79 | 80 | # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ 81 | # There can be multiple files in a space-separated list. 82 | # Example value: mymodid_at.cfg nei_at.cfg 83 | accessTransformersFile = 84 | 85 | # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! 86 | usesMixins = true 87 | 88 | # Adds some debug arguments like verbose output and class export. 89 | usesMixinDebug = false 90 | 91 | # Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. 92 | mixinPlugin = 93 | 94 | # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! 95 | mixinsPackage = mixins 96 | 97 | # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! 98 | # This parameter is for legacy compatibility only 99 | # Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin 100 | coreModClass = 101 | 102 | # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class 103 | # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! 104 | containsMixinsAndOrCoreModOnly = false 105 | 106 | # Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins. 107 | forceEnableMixins = false 108 | 109 | # If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your 110 | # responsibility to check the license and request permission for distribution if required. 111 | usesShadowedDependencies = false 112 | 113 | # If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access 114 | # their own classes, making the minimization unreliable. 115 | minimizeShadowedDependencies = true 116 | 117 | # If disabled, won't rename the shadowed classes. 118 | relocateShadowedDependencies = true 119 | 120 | # Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. 121 | includeWellKnownRepositories = true 122 | 123 | # Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. 124 | # Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables. 125 | # If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle. 126 | usesMavenPublishing = true 127 | 128 | # Maven repository to publish the mod to. 129 | # mavenPublishUrl = https\://nexus.gtnewhorizons.com/repository/releases/ 130 | 131 | # Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token. 132 | # 133 | # The project's ID on Modrinth. Can be either the slug or the ID. 134 | # Leave this empty if you don't want to publish to Modrinth. 135 | modrinthProjectId = 136 | 137 | # The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. 138 | # Syntax: scope1-type1:name1;scope2-type2:name2;... 139 | # Where scope can be one of [required, optional, incompatible, embedded], 140 | # type can be one of [project, version], 141 | # and the name is the Modrinth project or version slug/id of the other mod. 142 | # Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech 143 | # Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true 144 | modrinthRelations = 145 | 146 | # Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. 147 | # 148 | # The project's numeric ID on CurseForge. You can find this in the About Project box. 149 | # Leave this empty if you don't want to publish on CurseForge. 150 | curseForgeProjectId = 151 | 152 | # The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. 153 | # Syntax: type1:name1;type2:name2;... 154 | # Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], 155 | # and the name is the CurseForge project slug of the other mod. 156 | # Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft 157 | # Note: UniMixins is automatically set as a required dependency if usesMixins = true. 158 | curseForgeRelations = 159 | 160 | # Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older 161 | # projects. New projects should not use this parameter. 162 | # customArchiveBaseName = 163 | 164 | # Optional parameter to have the build automatically fail if an illegal version is used. 165 | # This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'. 166 | # The check is ONLY performed if the version is a git tag. 167 | # Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+ 168 | # versionPattern = 169 | 170 | # Uncomment to prevent the source code from being published. 171 | # noPublishedSources = true 172 | 173 | # Uncomment this to disable Spotless checks. 174 | # This should only be uncommented to keep it easier to sync with upstream/other forks. 175 | # That is, if there is no other active fork/upstream, NEVER change this. 176 | # disableSpotless = true 177 | 178 | # Uncomment this to disable Checkstyle checks (currently wildcard import check). 179 | # disableCheckstyle = true 180 | 181 | # Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle" 182 | # (force use delegated build). 183 | # This is meant to be set in $HOME/.gradle/gradle.properties. 184 | # e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build. 185 | # WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want! 186 | # Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you. 187 | # ideaOverrideBuildType = idea 188 | 189 | # Whether IDEA should run spotless checks when pressing the Build button. 190 | # This is meant to be set in $HOME/.gradle/gradle.properties. 191 | # ideaCheckSpotlessOnBuild = true 192 | 193 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/neiutilities/nei/AdvancedItemPanel.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.neiutilities.nei; 2 | 3 | import static codechicken.lib.gui.GuiDraw.getMousePosition; 4 | import static com.github.vfyjxf.neiutilities.config.NeiUtilitiesConfig.useRows; 5 | 6 | import java.awt.Point; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import net.minecraft.client.gui.inventory.GuiContainer; 11 | import net.minecraft.inventory.Container; 12 | import net.minecraft.item.ItemStack; 13 | 14 | import org.lwjgl.opengl.GL11; 15 | 16 | import com.github.vfyjxf.neiutilities.config.NeiUtilitiesConfig; 17 | import com.github.vfyjxf.neiutilities.config.SplittingMode; 18 | 19 | import codechicken.lib.gui.GuiDraw; 20 | import codechicken.lib.vec.Rectangle4i; 21 | import codechicken.nei.ItemPanel; 22 | import codechicken.nei.NEIClientConfig; 23 | import codechicken.nei.NEIClientUtils; 24 | import codechicken.nei.NEIServerUtils; 25 | import codechicken.nei.PositionedStack; 26 | import codechicken.nei.api.GuiInfo; 27 | import codechicken.nei.api.INEIGuiHandler; 28 | import codechicken.nei.api.IOverlayHandler; 29 | import codechicken.nei.api.IRecipeOverlayRenderer; 30 | import codechicken.nei.guihook.GuiContainerManager; 31 | import codechicken.nei.guihook.IContainerInputHandler; 32 | import codechicken.nei.recipe.GuiRecipe; 33 | import codechicken.nei.recipe.ICraftingHandler; 34 | import codechicken.nei.recipe.IUsageHandler; 35 | 36 | public class AdvancedItemPanel extends ItemPanel implements ICraftingHandler, IUsageHandler, IContainerInputHandler { 37 | 38 | public static final AdvancedItemPanel INSTANCE = new AdvancedItemPanel(); 39 | 40 | public boolean isMouseOverHistory = false; 41 | 42 | public AdvancedItemPanel() { 43 | this.grid = new AdvancedItemPanelGrid(); 44 | } 45 | 46 | public void addHistoryItem(Object... results) { 47 | if (results.length > 0 && results[0] instanceof ItemStack) { 48 | this.getAdvancedGrid() 49 | .addHistoryItem((ItemStack) results[0]); 50 | } 51 | } 52 | 53 | public AdvancedItemPanelGrid getAdvancedGrid() { 54 | return (AdvancedItemPanelGrid) this.grid; 55 | } 56 | 57 | protected static class AdvancedItemPanelGrid extends ItemPanelGrid { 58 | 59 | private int startIndex; 60 | private final List historyItems = new ArrayList<>(); 61 | private boolean[] validSlotMap; 62 | 63 | public ItemStack getHistoryItem(int slotIndex) { 64 | return this.historyItems.get(slotIndex - startIndex); 65 | } 66 | 67 | public Rectangle4i getHistoryRect() { 68 | 69 | if (columns > 0 && rows > 0) { 70 | Rectangle4i rect = getSlotRect(startIndex); 71 | rect.w = rect.w * this.columns; 72 | rect.h = rect.h * useRows; 73 | return rect; 74 | } else { 75 | // Some guis are too big so there is no place to display the history 76 | return new Rectangle4i(0, 0, 0, 0); 77 | } 78 | 79 | } 80 | 81 | @Override 82 | public boolean contains(int px, int py) { 83 | if (!(new Rectangle4i(marginLeft + paddingLeft, marginTop, columns * SLOT_SIZE, height)).contains(px, py)) { 84 | return false; 85 | } 86 | 87 | final int r = (py - marginTop) / SLOT_SIZE; 88 | final int c = (px - marginLeft - paddingLeft) / SLOT_SIZE; 89 | final int slt = columns * r + c; 90 | 91 | return r >= rows || c >= columns || !isInvalidSlot(slt); 92 | } 93 | 94 | @Override 95 | public void setGridSize(int mLeft, int mTop, int w, int h) { 96 | super.setGridSize(mLeft, mTop, w, h); 97 | rows = (height / SLOT_SIZE) - useRows; 98 | this.startIndex = this.columns * this.rows; 99 | } 100 | 101 | @Override 102 | public ItemPanelSlot getSlotMouseOver(int mouseX, int mouseY) { 103 | ItemPanelSlot result = super.getSlotMouseOver(mouseX, mouseY); 104 | 105 | if (result == null) { 106 | final int overRow = (mouseY - marginTop) / SLOT_SIZE; 107 | if (overRow <= rows + useRows) { 108 | for (int i = 0; i < validSlotMap.length && i < historyItems.size(); i++) { 109 | if (validSlotMap[i]) { 110 | if (getSlotRect(startIndex + i).contains(mouseX, mouseY)) { 111 | return new ItemPanelSlot(startIndex + i, historyItems.get(i)); 112 | } 113 | } 114 | } 115 | } 116 | } 117 | 118 | return result; 119 | } 120 | 121 | @Override 122 | public void refresh(GuiContainer gui) { 123 | super.refresh(gui); 124 | updateValidSlots(); 125 | } 126 | 127 | public void addHistoryItem(ItemStack itemStack) { 128 | if (itemStack != null) { 129 | ItemStack is = itemStack.copy(); 130 | is.stackSize = 1; 131 | historyItems.removeIf(stack -> stack.isItemEqual(is)); 132 | historyItems.add(0, is); 133 | if (historyItems.size() > (useRows * columns)) { 134 | historyItems.remove(useRows * columns); 135 | } 136 | } 137 | } 138 | 139 | public void updateValidSlots() { 140 | this.validSlotMap = new boolean[this.columns * useRows]; 141 | for (int i = 0; i < validSlotMap.length; i++) { 142 | if (slotValid(NEIClientUtils.getGuiContainer(), i)) { 143 | this.validSlotMap[i] = true; 144 | } 145 | } 146 | } 147 | 148 | private boolean slotValid(GuiContainer gui, int idx) { 149 | Rectangle4i rect = getSlotRect(this.startIndex + idx); 150 | for (INEIGuiHandler handler : GuiInfo.guiHandlers) { 151 | if (handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) { 152 | return false; 153 | } 154 | } 155 | return true; 156 | } 157 | 158 | @Override 159 | public void draw(int mouseX, int mouseY) { 160 | super.draw(mouseX, mouseY); 161 | GuiContainerManager.enableMatrixStackLogging(); 162 | // draw history highlighted area 163 | Rectangle4i firstRect = getSlotRect(this.startIndex); 164 | if (NeiUtilitiesConfig.getSplittingMode() == SplittingMode.BACKGROUND) { 165 | GuiDraw.drawRect( 166 | firstRect.x, 167 | firstRect.y, 168 | this.columns * firstRect.w, 169 | useRows * firstRect.h, 170 | NeiUtilitiesConfig.historyColor); 171 | } else { 172 | drawSplittingArea( 173 | firstRect.x, 174 | firstRect.y, 175 | this.columns * firstRect.w, 176 | useRows * firstRect.h, 177 | NeiUtilitiesConfig.historyColor); 178 | } 179 | for (int i = 0; i < this.validSlotMap.length && i < historyItems.size(); i++) { 180 | if (validSlotMap[i]) { 181 | Rectangle4i rect = getSlotRect(startIndex + i); 182 | ItemPanelSlot slot = getSlotMouseOver(mouseX, mouseY); 183 | if (slot != null && slot.slotIndex == startIndex + i) { 184 | GuiDraw.drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);// highlight 185 | } 186 | GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, historyItems.get(i)); 187 | } 188 | } 189 | GuiContainerManager.disableMatrixStackLogging(); 190 | } 191 | 192 | private void drawSplittingArea(int x, int y, int width, int height, int color) { 193 | 194 | float alpha = (float) (color >> 24 & 255) / 255.0F; 195 | float red = (float) (color >> 16 & 255) / 255.0F; 196 | float green = (float) (color >> 8 & 255) / 255.0F; 197 | float blue = (float) (color & 255) / 255.0F; 198 | 199 | GL11.glPushMatrix(); 200 | 201 | GL11.glDisable(GL11.GL_TEXTURE_2D); 202 | GL11.glEnable(GL11.GL_LINE_STIPPLE); 203 | GL11.glColor4f(red, green, blue, alpha); 204 | GL11.glLineWidth(2F); 205 | GL11.glLineStipple(2, (short) 0x00FF); 206 | 207 | GL11.glBegin(GL11.GL_LINE_LOOP); 208 | 209 | GL11.glVertex2i(x, y); 210 | GL11.glVertex2i(x + width, y); 211 | GL11.glVertex2i(x + width, y + height); 212 | GL11.glVertex2i(x, y + height); 213 | 214 | GL11.glEnd(); 215 | 216 | GL11.glLineStipple(1, (short) 0xFFFF); 217 | GL11.glLineWidth(1F); 218 | GL11.glDisable(GL11.GL_LINE_STIPPLE); 219 | GL11.glEnable(GL11.GL_TEXTURE_2D); 220 | GL11.glColor4f(1F, 1F, 1F, 1F); 221 | 222 | GL11.glPopMatrix(); 223 | 224 | } 225 | 226 | } 227 | 228 | @Override 229 | public boolean handleClick(int mouseX, int mouseY, int button) { 230 | boolean result = super.handleClick(mouseX, mouseY, button); 231 | this.isMouseOverHistory = this.getAdvancedGrid() 232 | .getHistoryRect() 233 | .contains(mouseX, mouseY); 234 | return result; 235 | } 236 | 237 | @Override 238 | public void mouseDragged(int mouseX, int mouseY, int button, long heldTime) { 239 | if (mouseDownSlot >= 0 && draggedStack == null 240 | && NEIClientUtils.getHeldItem() == null 241 | && NEIClientConfig.hasSMPCounterPart() 242 | && !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) { 243 | ItemPanelSlot mouseOverSlot = getSlotMouseOver(mouseX, mouseY); 244 | 245 | if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) { 246 | draggedStack = this.getDraggedStackWithQuantity(isMouseOverHistory, mouseDownSlot); 247 | mouseDownSlot = -1; 248 | isMouseOverHistory = false; 249 | } 250 | 251 | } 252 | } 253 | 254 | /** 255 | * In fact, this method is specifically designed for {@link AdvancedItemPanel#mouseDragged(int, int, int, long)}, 256 | * because it is not credible to determine whether the mouse 257 | * is over the history area in {@link AdvancedItemPanel#getDraggedStackWithQuantity(int)} 258 | */ 259 | public ItemStack getDraggedStackWithQuantity(boolean isHistory, int mouseDownSlot) { 260 | ItemStack stack = isHistory ? this.getAdvancedGrid() 261 | .getHistoryItem(mouseDownSlot) : grid.getItem(mouseDownSlot); 262 | 263 | if (stack != null) { 264 | int amount = NEIClientConfig.getItemQuantity(); 265 | 266 | if (amount == 0) { 267 | amount = stack.getMaxStackSize(); 268 | } 269 | 270 | return NEIServerUtils.copyStack(stack, amount); 271 | } 272 | 273 | return null; 274 | } 275 | 276 | @Override 277 | protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) { 278 | Point mousePos = getMousePosition(); 279 | boolean isMouseOverHistoryItem = this.getAdvancedGrid() 280 | .getHistoryRect() 281 | .contains(mousePos.x, mousePos.y); 282 | ItemStack stack = isMouseOverHistoryItem ? this.getAdvancedGrid() 283 | .getHistoryItem(mouseDownSlot) : grid.getItem(mouseDownSlot); 284 | 285 | if (stack != null) { 286 | int amount = NEIClientConfig.getItemQuantity(); 287 | 288 | if (amount == 0) { 289 | amount = stack.getMaxStackSize(); 290 | } 291 | 292 | return NEIServerUtils.copyStack(stack, amount); 293 | } 294 | 295 | return null; 296 | } 297 | 298 | @Override 299 | public boolean mouseClicked(GuiContainer gui, int mouseX, int mouseY, int button) { 300 | return this.getAdvancedGrid() 301 | .getHistoryRect() 302 | .contains(mouseX, mouseY); 303 | } 304 | 305 | @Override 306 | public ICraftingHandler getRecipeHandler(String outputId, Object... results) { 307 | this.addHistoryItem(results); 308 | return this; 309 | } 310 | 311 | @Override 312 | public IUsageHandler getUsageHandler(String inputId, Object... ingredients) { 313 | this.addHistoryItem(ingredients); 314 | return this; 315 | } 316 | 317 | @Override 318 | public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { 319 | return false; 320 | } 321 | 322 | @Override 323 | public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) { 324 | 325 | } 326 | 327 | @Override 328 | public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { 329 | return false; 330 | } 331 | 332 | @Override 333 | public void onMouseClicked(GuiContainer gui, int mouseX, int mouseY, int button) { 334 | 335 | } 336 | 337 | @Override 338 | public void onMouseUp(GuiContainer gui, int mouseX, int mouseY, int button) { 339 | 340 | } 341 | 342 | @Override 343 | public boolean mouseScrolled(GuiContainer gui, int mouseX, int mouseY, int scrolled) { 344 | return false; 345 | } 346 | 347 | @Override 348 | public void onMouseScrolled(GuiContainer gui, int mouseX, int mouseY, int scrolled) { 349 | 350 | } 351 | 352 | @Override 353 | public void onMouseDragged(GuiContainer gui, int mouseX, int mouseY, int button, long heldTime) { 354 | 355 | } 356 | 357 | @Override 358 | public String getRecipeName() { 359 | return null; 360 | } 361 | 362 | @Override 363 | public int numRecipes() { 364 | return 0; 365 | } 366 | 367 | @Override 368 | public void drawBackground(int recipe) { 369 | 370 | } 371 | 372 | @Override 373 | public void drawForeground(int recipe) { 374 | 375 | } 376 | 377 | @Override 378 | public List getIngredientStacks(int recipe) { 379 | return null; 380 | } 381 | 382 | @Override 383 | public List getOtherStacks(int recipeType) { 384 | return null; 385 | } 386 | 387 | @Override 388 | public PositionedStack getResultStack(int recipe) { 389 | return null; 390 | } 391 | 392 | @Override 393 | public void onUpdate() { 394 | 395 | } 396 | 397 | @Override 398 | public boolean hasOverlay(GuiContainer gui, Container container, int recipe) { 399 | return false; 400 | } 401 | 402 | @Override 403 | public IRecipeOverlayRenderer getOverlayRenderer(GuiContainer gui, int recipe) { 404 | return null; 405 | } 406 | 407 | @Override 408 | public IOverlayHandler getOverlayHandler(GuiContainer gui, int recipe) { 409 | return null; 410 | } 411 | 412 | @Override 413 | public int recipiesPerPage() { 414 | return 0; 415 | } 416 | 417 | @Override 418 | public List handleTooltip(GuiRecipe gui, List currenttip, int recipe) { 419 | return null; 420 | } 421 | 422 | @Override 423 | public List handleItemTooltip(GuiRecipe gui, ItemStack stack, List currenttip, int recipe) { 424 | return null; 425 | } 426 | 427 | @Override 428 | public boolean keyTyped(GuiRecipe gui, char keyChar, int keyCode, int recipe) { 429 | return false; 430 | } 431 | 432 | @Override 433 | public boolean mouseClicked(GuiRecipe gui, int button, int recipe) { 434 | return true; 435 | } 436 | 437 | } 438 | --------------------------------------------------------------------------------