├── .gitignore ├── LICENSE ├── README.md ├── READNE_CN.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── settings.gradle └── src └── main ├── java └── com │ └── github │ └── vfyjxf │ └── nee │ ├── NEECommands.java │ ├── NotEnoughEnergistics.java │ ├── asm │ ├── AppengHooks.java │ ├── JeiHooks.java │ ├── NEEClassTransformer.java │ └── NEELoadingPlugin.java │ ├── block │ ├── BlockPatternInterface.java │ └── tile │ │ └── TilePatternInterface.java │ ├── client │ ├── GuiEventHandler.java │ └── gui │ │ ├── ConfirmWrapperGui.java │ │ ├── CraftingAmountGui.java │ │ ├── IInnerWidget.java │ │ ├── IngredientSwitcherWidget.java │ │ ├── PatternInterfaceGui.java │ │ ├── PreferenceDataGui.java │ │ ├── QuickPusherWidget.java │ │ ├── SuperPusherWidget.java │ │ ├── WirelessConfirmWrapperGui.java │ │ ├── elements │ │ ├── HighResolutionTexture.java │ │ ├── ITexture.java │ │ └── ResourceTexture.java │ │ └── widgets │ │ ├── AddPreferenceButton.java │ │ ├── GuiImageButton.java │ │ ├── ItemWidget.java │ │ ├── MergeConfigButton.java │ │ ├── OpenPreferenceDataButton.java │ │ ├── PatternRemoveButton.java │ │ └── QuicklyPusherButton.java │ ├── config │ ├── IngredientBlackList.java │ ├── IngredientMergeMode.java │ ├── KeyBindings.java │ ├── NEEConfig.java │ ├── NEEConfigGuiFactory.java │ └── PreferenceList.java │ ├── container │ ├── ContainerCraftingAmount.java │ ├── ContainerCraftingConfirmWrapper.java │ ├── ContainerPatternInterface.java │ └── WCTContainerCraftingConfirm.java │ ├── helper │ ├── BlackListHelper.java │ ├── CraftingHelper.java │ ├── IngredientMerger.java │ ├── IngredientRequester.java │ ├── PlatformHelper.java │ ├── PreferenceHelper.java │ ├── RecipeAnalyzer.java │ └── RecipeHelper.java │ ├── integration │ ├── GregTechToolHelper.java │ ├── IPatternProvider.java │ ├── IToolHelper.java │ ├── InterfacePatternProvider.java │ ├── PartInterfacePatternProvider.java │ ├── RecipeToolManager.java │ └── unofficial │ │ └── IRecipeTransformHandler.java │ ├── inventory │ └── InventoryPatternCrafter.java │ ├── jei │ ├── CraftingInfoError.java │ ├── CraftingTransferHandler.java │ ├── NEEGhostIngredientHandler.java │ ├── NEEJeiPlugin.java │ └── PatternTransferHandler.java │ ├── network │ ├── NEEGuiHandler.java │ ├── NEENetworkHandler.java │ ├── PlayerAction.java │ ├── SyncAction.java │ └── packet │ │ ├── PacketCraftingRequest.java │ │ ├── PacketOpenCraftAmount.java │ │ ├── PacketPlayerAction.java │ │ ├── PacketRecipeTransfer.java │ │ ├── PacketSetRecipe.java │ │ ├── PacketSlotStackSwitch.java │ │ ├── PacketStackSizeChange.java │ │ ├── PacketSyncInterfaceDataClient.java │ │ ├── PacketSyncInterfaceDataServer.java │ │ ├── PacketValueConfigClient.java │ │ └── PacketValueConfigServer.java │ ├── proxy │ ├── ClientProxy.java │ ├── CommonProxy.java │ └── ServerProxy.java │ └── utils │ ├── BlackIngredient.java │ ├── Globals.java │ ├── GuiUtils.java │ ├── IngredientStatus.java │ ├── ItemUtils.java │ ├── PatternContainerControl.java │ ├── PreferenceIngredient.java │ ├── ReflectionHelper.java │ └── StackWrapper.java └── resources ├── META-INF └── neenergistics_at.cfg ├── assets └── neenergistics │ ├── blockstates │ └── pattern_interface.json │ ├── lang │ ├── en_us.lang │ └── zh_cn.lang │ ├── meta │ └── logo.png │ ├── models │ ├── block │ │ └── pattern_interface.json │ └── item │ │ └── pattern_interface.json │ ├── recipes │ └── pattern_interface.json │ └── textures │ ├── blocks │ ├── pattern_interface_side.png │ └── pattern_interface_surface.png │ └── gui │ ├── arrow_down.png │ ├── arrow_up.png │ ├── ingredient_switcher_widget.png │ ├── pattern_interface.png │ ├── quickly_pusher_background.png │ ├── quickly_pusher_icon.png │ ├── search_ingredients.png │ ├── search_interface.png │ ├── states.png │ └── super_pusher_icon.png ├── mcmod.info └── pack.mcmeta /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gradle 3 | .idea 4 | .settings 5 | .metadata 6 | bin 7 | build 8 | run 9 | out 10 | minecraft 11 | eclipse 12 | .classpath 13 | .project 14 | .apt_generated 15 | .apt_generated_tests 16 | 17 | *.bat 18 | *.sh 19 | *.iml 20 | *.ipr 21 | *.iws 22 | *.launch 23 | .factorypath 24 | 25 | forge*changelog.txt 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [中文](READNE_CN.md) 2 | 3 | # Not Enough Energistics 4 | NotEnoughEnergistics-1.12.2 is an improved version of [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 5 | 6 | This mod replaces AE2's default JEI integration for the Pattern Terminal. 7 | 8 | By default, AE2 forces the player to either have the necessary items for a recipe in their personal inventory or in their ME network. 9 | 10 | This mod removes that functionality and allows the player to use JEI's transfer system (click [+] button) to create patterns whether the player possesses the items required by the recipe. 11 | 12 | 13 | ## Features 14 | 15 | - Automatically switch the mode of PatternTerminal. 16 | - Combine like stacks in processing patterns. 17 | - Allow you to add item blackList and item priority list, if item in them, it will not be transferred / transfer it first. 18 | - Allow you to add mod priority list,if the mod's has this item,it will be use first. 19 | - You can use the ctrl + mouse wheel to change the Pattern item input/output amount. 20 | - You can use shift + mouse wheel to choose ingredient. 21 | - you can use ctrl+ click [+] in crafting terminal to request the items while missing in AE and having existing pattern in AE(alt + click for no preview) 22 | 23 | ## Credits 24 | Thanks TheRealp455w0rd and his [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 25 | -------------------------------------------------------------------------------- /READNE_CN.md: -------------------------------------------------------------------------------- 1 | # Not Enough Energistics 2 | NotEnoughEnergistics 是[Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 的改进版本 3 | 4 | 它替换了AE2默认的JEI集成, 默认情况下ae只能识别玩家身上或者网络里的存储物品。 5 | 6 | 本MOD允许你直接从jei获取配方并写入样板终端(shift点击[+]按钮) 7 | 8 | ## Features 9 | 10 | - 根据配方自动切换样板终端的模式 11 | - 在处理模式中合并同类物品 12 | - 允许你设置转换黑名单和转换优先名单,如对应物品在里面,那么他们将不会被转移/优先被转移 13 | - 允许你设置mod优先级列表,优先使用该mod的物品 14 | - 你可以使用ctrl + 鼠标滚轮来修改样板的输入/输出数量 15 | - 你可以使用shift + 鼠标滚轮来选择材料 16 | - 你可以使用ctrl + 点击[+]按钮来在合成终端中请求有配方的缺失材料(alt + 点击[+]来跳过预览) 17 | 18 | ## Credits 19 | 感谢 TheRealp455w0rd 和他的 [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 20 | 21 | 22 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | } 6 | plugins { 7 | id 'eclipse' 8 | id 'maven-publish' 9 | id 'net.minecraftforge.gradle' version '5.1.+' 10 | id 'wtf.gofancy.fancygradle' version '1.1.+' 11 | } 12 | 13 | fancyGradle { 14 | patches { 15 | resources 16 | coremods 17 | codeChickenLib 18 | asm 19 | mergetool 20 | } 21 | } 22 | //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. 23 | 24 | version = mod_version 25 | group = mod_group 26 | archivesBaseName = mod_archives_name + '-' + mc_version 27 | 28 | sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' 29 | 30 | tasks.withType(JavaCompile).configureEach { 31 | options.encoding = "UTF-8" 32 | } 33 | 34 | minecraft { 35 | // the mappings can be changed at any time, and must be in the following format. 36 | // snapshot_YYYYMMDD snapshot are built nightly. 37 | // stable_# stables are built at the discretion of the MCP team. 38 | // Use non-default mappings at your own risk. they may not always work. 39 | // simply re-run your setup task after changing the mappings to update your workspace. 40 | mappings channel: 'stable', version: '39-1.12' 41 | // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. 42 | 43 | //replace '@VERSION@', project.version 44 | 45 | // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') 46 | 47 | // Default run configurations. 48 | // These can be tweaked, removed, or duplicated as needed. 49 | runs { 50 | client { 51 | workingDirectory project.file('run') 52 | 53 | // Recommended logging data for a userdev environment 54 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' 55 | 56 | // Recommended logging level for the console 57 | property 'forge.logging.console.level', 'debug' 58 | 59 | //JvmArgs += "-Dfml.coreMods.load=com.github.vfyjxf.nee.asm.NEELoadingPlugin" 60 | } 61 | 62 | server { 63 | workingDirectory project.file('run') 64 | 65 | // Recommended logging data for a userdev environment 66 | property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' 67 | 68 | // Recommended logging level for the console 69 | property 'forge.logging.console.level', 'debug' 70 | 71 | //JvmArgs += "-Dfml.coreMods.load=com.github.vfyjxf.nee.asm.NEELoadingPlugin" 72 | } 73 | } 74 | } 75 | 76 | // Include resources generated by data generators. 77 | sourceSets.main.resources { srcDir 'src/generated/resources' } 78 | 79 | repositories { 80 | maven { 81 | // location of the maven that hosts JEI files 82 | name = "Progwml6 maven" 83 | url = "https://dvs1.progwml6.com/files/maven/" 84 | } 85 | maven { 86 | // location of a maven mirror for JEI files, as a fallback 87 | name = "ModMaven" 88 | url = "https://modmaven.k-4u.nl" 89 | } 90 | maven { 91 | name = "covers Maven" 92 | url = "https://maven.covers1624.net" 93 | } 94 | maven { 95 | name = "CurseMaven" 96 | url = "https://www.cursemaven.com" 97 | } 98 | maven { url = "https://maven.cil.li/" } 99 | flatDir { 100 | dirs 'libs' 101 | } 102 | } 103 | 104 | dependencies { 105 | minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2860' 106 | 107 | compileOnly fg.deobf("mezz.jei:jei_${mc_version}:${jei_version}") 108 | runtimeOnly fg.deobf("mezz.jei:jei_${mc_version}:${jei_version}") 109 | // compile "curse.maven:modularui-624243:3895901" 110 | //AE2 Unofficial Extended Life 111 | // compileOnly fg.deobf("curse.maven:ae2-extended-life-570458:4463434") 112 | compileOnly fg.deobf("curse.maven:applied-energistics-2-223794:2747063") 113 | runtimeOnly fg.deobf("curse.maven:applied-energistics-2-223794:2747063") 114 | compileOnly "curse.maven:wireless-crafting-terminal-244559:2830252" 115 | compileOnly "curse.maven:ae2wtlib-304024:2830114" 116 | compileOnly "curse.maven:p455w0rds-library-255232:2830265" 117 | 118 | runtimeOnly "curse.maven:wireless-crafting-terminal-244559:2830252" 119 | runtimeOnly "curse.maven:ae2wtlib-304024:2830114" 120 | runtimeOnly "curse.maven:p455w0rds-library-255232:2830265" 121 | // deobfCompile "p455w0rd:WirelessCraftingTerminal:1.12.2-3.12.97" 122 | // deobfCompile "p455w0rd:AE2WTLib:1.12.2-1.0.34" 123 | // deobfCompile "p455w0rd:p455w0rdslib:1.12.2-2.3.161" 124 | //Big orediect test 125 | compileOnly fg.deobf("CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.680") 126 | 127 | } 128 | 129 | jar.finalizedBy('reobfJar') 130 | 131 | processResources { 132 | duplicatesStrategy = DuplicatesStrategy.INCLUDE 133 | // this will ensure that this task is redone when the versions change. 134 | inputs.property "version", project.version 135 | 136 | // replace stuff in mcmod.info, nothing else 137 | from(sourceSets.main.resources.srcDirs) { 138 | include 'mcmod.info' 139 | expand 'version': project.version, 140 | 'mod_id': mod_id, 141 | 'mod_name': mod_name, 142 | 'mod_credits': mod_credits, 143 | 'mod_author': mod_author, 144 | 'mod_description': mod_description, 145 | 'mc_version': mc_version, 146 | 'mod_version': mod_version, 147 | 'mod_logo': mod_logo 148 | } 149 | 150 | // copy everything else except the mcmod.info 151 | from(sourceSets.main.resources.srcDirs) { 152 | exclude 'mcmod.info' 153 | } 154 | } 155 | 156 | // workaround for userdev bug 157 | tasks.create("copyResourceToClasses", Copy.class) { 158 | tasks.classes.dependsOn(it) 159 | dependsOn(tasks.processResources) 160 | onlyIf { gradle.taskGraph.hasTask(tasks.prepareRuns) } 161 | 162 | into("$buildDir/classes/java/main") 163 | // if you write @Mod class in kotlin, please use code below 164 | // into("$buildDir/classes/kotlin/main") 165 | from(tasks.processResources.destinationDir) 166 | } 167 | 168 | jar { 169 | manifest.attributes( 170 | 'FMLAT': 'neenergistics_at.cfg', 171 | 'FMLCorePlugin': 'com.github.vfyjxf.nee.asm.NEELoadingPlugin', 172 | 'FMLCorePluginContainsFMLMod': 'true' 173 | ) 174 | } 175 | 176 | //task devJar(type: Jar) { 177 | // classifier = 'dev' 178 | // from sourceSets.main.output 179 | //} 180 | // 181 | //task sourcesJar(type: Jar) { 182 | // classifier = 'sources' 183 | // from sourceSets.main.allSource 184 | //} 185 | // 186 | //artifacts { 187 | // archives devJar 188 | // archives sourcesJar 189 | //} -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Gradle Specifications 2 | org.gradle.jvmargs=-Xmx2G -Xms2G 3 | org.gradle.daemon=false 4 | 5 | # General Specifications 6 | mc_version=1.12.2 7 | jei_version=4.16.1.302 8 | mod_version=2.0.9 9 | forge_version=14.23.5.2847 10 | mod_group=com.github.vfyjxf.neenergistics 11 | mod_id=neenergistics 12 | mod_name=NotEnoughEnergistics 13 | mod_archives_name=NotEnoughEnergistics 14 | mod_author=vfyjxf 15 | mod_description= 16 | mod_logo=assets/neenergistics/meta/logo.png 17 | mod_credits=Thanks TheRealp455w0rd 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven { 5 | name 'ForgeGradle Maven' 6 | url 'https://maven.minecraftforge.net' 7 | } 8 | maven { 9 | name 'Garden of Fancy' 10 | url 'https://maven.gofancy.wtf/releases' 11 | } 12 | maven { 13 | name 'MixinGradle Maven' 14 | url 'https://repo.spongepowered.org/repository/maven-public' 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/NEECommands.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee; 2 | 3 | import net.minecraft.command.CommandBase; 4 | import net.minecraft.command.ICommandSender; 5 | import net.minecraft.server.MinecraftServer; 6 | import net.minecraft.util.math.BlockPos; 7 | 8 | import javax.annotation.Nonnull; 9 | import javax.annotation.Nullable; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class NEECommands extends CommandBase { 14 | @Nonnull 15 | @Override 16 | public String getName() { 17 | return "nee"; 18 | } 19 | 20 | @Nonnull 21 | @Override 22 | public String getUsage(@Nonnull ICommandSender sender) { 23 | return ""; 24 | } 25 | 26 | @Override 27 | public int getRequiredPermissionLevel() { 28 | return 1; 29 | } 30 | 31 | @Nonnull 32 | @Override 33 | public List getTabCompletions(@Nonnull MinecraftServer server, @Nonnull ICommandSender sender, String[] args, @Nullable BlockPos targetPos) { 34 | if (args.length == 1) { 35 | return CommandBase.getListOfStringsMatchingLastWord(args, "add", "reload","help"); 36 | } else if (args.length == 2) { 37 | return CommandBase.getListOfStringsMatchingLastWord(args, "blacklist", "priorityItem", "priorityMod", "itemCombinationWhitelist"); 38 | } 39 | return Collections.emptyList(); 40 | } 41 | 42 | @Override 43 | public void execute(@Nonnull MinecraftServer server, @Nonnull ICommandSender sender, @Nonnull String[] args) { 44 | /* 45 | if (args.length > 0) { 46 | if("help".equalsIgnoreCase(args[0])){ 47 | sender.sendMessage(new TextComponentString("Usage:")); 48 | sender.sendMessage(new TextComponentString("/nee add blacklist/priorityItem processor_id identifier")); 49 | sender.sendMessage(new TextComponentString("/nee add blacklist/priorityItem/itemCombination identifier")); 50 | } 51 | if ("add".equalsIgnoreCase(args[0]) && args.length > 1) { 52 | if ("blacklist".equalsIgnoreCase(args[1]) || "priorityItem".equalsIgnoreCase(args[1])) { 53 | ItemStack currentStack = Minecraft.getMinecraft().player.getHeldItemMainhand(); 54 | if (!currentStack.isEmpty()) { 55 | String itemJsonString = ItemUtils.toItemJsonString(currentStack); 56 | if (args.length == 3) { 57 | JsonObject itemJsonObject = new JsonParser().parse(itemJsonString).getAsJsonObject(); 58 | String recipeType = args[2]; 59 | itemJsonObject.addProperty("recipeType", recipeType); 60 | itemJsonString = new Gson().toJson(itemJsonObject); 61 | } 62 | String[] itemList = "blacklist".equalsIgnoreCase(args[1]) ? NEEConfig.itemBlacklist : NEEConfig.itemPriorityList; 63 | List newItemList = new ArrayList<>(Arrays.asList(itemList)); 64 | for (String currentJsonString : itemList) { 65 | if (currentJsonString.equals(itemJsonString)) { 66 | return; 67 | } 68 | } 69 | newItemList.add(itemJsonString); 70 | if ("blacklist".equalsIgnoreCase(args[1])) { 71 | NEEConfig.setItemBlacklist(newItemList.toArray(new String[0])); 72 | } else { 73 | NEEConfig.setItemPriorityList(newItemList.toArray(new String[0])); 74 | } 75 | } 76 | } else if ("priorityMod".equalsIgnoreCase(args[1]) && args.length == 3) { 77 | String modid = args[2]; 78 | if (!ItemUtils.hasModId(modid)) { 79 | List newModIDList = new ArrayList<>(Arrays.asList(NEEConfig.modPriorityList)); 80 | newModIDList.add(modid); 81 | NEEConfig.setPriorityMods(newModIDList.toArray(new String[0])); 82 | } 83 | } else if ("itemCombinationWhitelist".equalsIgnoreCase(args[1]) && args.length == 3) { 84 | String recipeType = args[2]; 85 | if (!Arrays.asList(NEEConfig.itemCombinationWhitelist).contains(recipeType)) { 86 | List newLists = new ArrayList<>(Arrays.asList(NEEConfig.itemCombinationWhitelist)); 87 | newLists.add(recipeType); 88 | NEEConfig.setMergeBlacklist(newLists.toArray(new String[0])); 89 | } 90 | } 91 | } else if ("reload".equalsIgnoreCase(args[0])) { 92 | ConfigManager.sync(NotEnoughEnergistics.MOD_ID, Config.Type.INSTANCE); 93 | } 94 | } 95 | 96 | */ 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/NotEnoughEnergistics.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee; 2 | 3 | import com.github.vfyjxf.nee.integration.IPatternProvider; 4 | import com.github.vfyjxf.nee.integration.InterfacePatternProvider; 5 | import com.github.vfyjxf.nee.integration.PartInterfacePatternProvider; 6 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 7 | import com.github.vfyjxf.nee.proxy.CommonProxy; 8 | import com.github.vfyjxf.nee.utils.Globals; 9 | import net.minecraftforge.fml.common.Mod; 10 | import net.minecraftforge.fml.common.Mod.EventHandler; 11 | import net.minecraftforge.fml.common.SidedProxy; 12 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 13 | import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; 14 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 15 | import net.minecraftforge.fml.common.network.NetworkRegistry; 16 | import org.apache.logging.log4j.LogManager; 17 | import org.apache.logging.log4j.Logger; 18 | 19 | 20 | @Mod(modid = Globals.MOD_ID, 21 | version = Globals.VERSION, 22 | name = Globals.NAME, 23 | dependencies = Globals.DEPENDENCIES, 24 | guiFactory = Globals.GUI_FACTORY, 25 | useMetadata = true) 26 | public class NotEnoughEnergistics { 27 | public static final Logger logger = LogManager.getLogger("NotEnoughEnergistics"); 28 | 29 | @Mod.Instance(Globals.MOD_ID) 30 | public static NotEnoughEnergistics instance; 31 | 32 | @SidedProxy(clientSide = "com.github.vfyjxf.nee.proxy.ClientProxy", serverSide = "com.github.vfyjxf.nee.proxy.ServerProxy") 33 | public static CommonProxy proxy; 34 | 35 | @EventHandler 36 | public void preInit(FMLPreInitializationEvent event) { 37 | proxy.preInit(event); 38 | } 39 | 40 | @EventHandler 41 | public void postInit(FMLPostInitializationEvent event) { 42 | NetworkRegistry.INSTANCE.registerGuiHandler(this, new NEEGuiHandler()); 43 | IPatternProvider.PROVIDERS.add(new InterfacePatternProvider()); 44 | IPatternProvider.PROVIDERS.add(new PartInterfacePatternProvider()); 45 | } 46 | 47 | @EventHandler 48 | public void init(FMLInitializationEvent event) { 49 | proxy.init(event); 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/asm/AppengHooks.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.asm; 2 | 3 | import appeng.api.storage.data.IAEItemStack; 4 | import appeng.client.gui.implementations.GuiMEMonitorable; 5 | import appeng.core.sync.AppEngPacket; 6 | import appeng.core.sync.network.INetworkInfo; 7 | import com.github.vfyjxf.nee.utils.Globals; 8 | import mezz.jei.gui.recipes.RecipesGui; 9 | import net.minecraft.client.gui.GuiScreen; 10 | import net.minecraft.entity.player.EntityPlayer; 11 | import net.minecraft.inventory.Container; 12 | import net.minecraftforge.fml.common.Optional; 13 | import p455w0rd.wct.client.gui.GuiWCT; 14 | 15 | import java.util.List; 16 | 17 | @SuppressWarnings("unused") 18 | public class AppengHooks { 19 | 20 | /** 21 | * Before {@link appeng.core.sync.packets.PacketMEInventoryUpdate#clientPacketData(INetworkInfo, AppEngPacket, EntityPlayer)} Return 22 | */ 23 | public static void updateMeInventory(Object obj, final List list) { 24 | if (obj instanceof Container) return; 25 | 26 | if (obj instanceof RecipesGui) { 27 | GuiScreen parent = ((RecipesGui) obj).getParentScreen(); 28 | if (parent instanceof GuiMEMonitorable) { 29 | ((GuiMEMonitorable) parent).postUpdate(list); 30 | } 31 | } 32 | } 33 | 34 | /** 35 | * Before {@link appeng.client.gui.implementations.GuiMEMonitorable#postUpdate(List)} Return 36 | */ 37 | @Optional.Method(modid = Globals.WCT) 38 | public static void updateWirelessInventory(GuiScreen screen, final List list) { 39 | if (screen instanceof RecipesGui) { 40 | GuiScreen parent = ((RecipesGui) screen).getParentScreen(); 41 | if (parent instanceof GuiWCT) { 42 | ((GuiWCT) parent).postUpdate(list); 43 | } 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/asm/JeiHooks.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.asm; 2 | 3 | import com.github.vfyjxf.nee.jei.CraftingInfoError; 4 | import mezz.jei.api.recipe.transfer.IRecipeTransferError; 5 | import net.minecraft.client.gui.GuiButton; 6 | 7 | @SuppressWarnings("unused") 8 | public class JeiHooks { 9 | 10 | public static void setButtonEnable(GuiButton button, IRecipeTransferError error) { 11 | if (error instanceof CraftingInfoError) { 12 | button.enabled = true; 13 | } 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/asm/NEEClassTransformer.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.asm; 2 | 3 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 4 | import com.github.vfyjxf.nee.utils.Globals; 5 | import net.minecraft.launchwrapper.IClassTransformer; 6 | import net.minecraftforge.fml.common.Loader; 7 | import org.objectweb.asm.ClassReader; 8 | import org.objectweb.asm.ClassWriter; 9 | import org.objectweb.asm.tree.*; 10 | 11 | import static org.objectweb.asm.Opcodes.*; 12 | 13 | public class NEEClassTransformer implements IClassTransformer { 14 | 15 | @Override 16 | public byte[] transform(String name, String transformedName, byte[] basicClass) { 17 | String internalName = transformedName.replace('.', '/'); 18 | if ("mezz/jei/gui/recipes/RecipeTransferButton".equals(internalName)) { 19 | ClassNode classNode = new ClassNode(); 20 | ClassReader classReader = new ClassReader(basicClass); 21 | classReader.accept(classNode, 0); 22 | for (MethodNode methodNode : classNode.methods) { 23 | if ("init".equals(methodNode.name) && "(Lnet/minecraft/inventory/Container;Lnet/minecraft/entity/player/EntityPlayer;)V".equals(methodNode.desc)) { 24 | NotEnoughEnergistics.logger.info("Transforming : " + internalName + methodNode.name + methodNode.desc); 25 | /* 26 | *Add: JEIHooks.setButtonEnable(this, error); 27 | */ 28 | for (AbstractInsnNode instruction : methodNode.instructions.toArray()) { 29 | int opcode = instruction.getOpcode(); 30 | if (opcode == RETURN) { 31 | InsnList insnList = new InsnList(); 32 | insnList.add(new VarInsnNode(ALOAD, 0)); 33 | insnList.add(new VarInsnNode(ALOAD, 0)); 34 | insnList.add(new FieldInsnNode(GETFIELD, 35 | "mezz/jei/gui/recipes/RecipeTransferButton", 36 | "recipeTransferError", 37 | "Lmezz/jei/api/recipe/transfer/IRecipeTransferError;")); 38 | insnList.add(new MethodInsnNode(INVOKESTATIC, 39 | "com/github/vfyjxf/nee/asm/JeiHooks", 40 | "setButtonEnable", 41 | "(Lnet/minecraft/client/gui/GuiButton;Lmezz/jei/api/recipe/transfer/IRecipeTransferError;)V", 42 | false)); 43 | methodNode.instructions.insertBefore(instruction, insnList); 44 | } 45 | } 46 | } 47 | } 48 | ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 49 | classNode.accept(classWriter); 50 | return classWriter.toByteArray(); 51 | } 52 | if ("appeng/core/sync/packets/PacketMEInventoryUpdate".equals(internalName)) { 53 | if (checkUnOfficial()) return basicClass; 54 | 55 | ClassNode classNode = new ClassNode(); 56 | ClassReader classReader = new ClassReader(basicClass); 57 | classReader.accept(classNode, 0); 58 | for (MethodNode methodNode : classNode.methods) { 59 | if ("clientPacketData".equals(methodNode.name) && "(Lappeng/core/sync/network/INetworkInfo;Lappeng/core/sync/AppEngPacket;Lnet/minecraft/entity/player/EntityPlayer;)V".equals(methodNode.desc)) { 60 | NotEnoughEnergistics.logger.info("Transforming : " + internalName + methodNode.name + methodNode.desc); 61 | /* 62 | *Add: AppengHooks.updateMeInventory(gs, this.list); 63 | */ 64 | for (AbstractInsnNode instruction : methodNode.instructions.toArray()) { 65 | int opcode = instruction.getOpcode(); 66 | if (opcode == RETURN) { 67 | InsnList insnList = new InsnList(); 68 | insnList.add(new VarInsnNode(ALOAD, 4)); 69 | insnList.add(new VarInsnNode(ALOAD, 0)); 70 | insnList.add(new FieldInsnNode(GETFIELD, 71 | "appeng/core/sync/packets/PacketMEInventoryUpdate", 72 | "list", 73 | "Ljava/util/List;")); 74 | insnList.add(new MethodInsnNode(INVOKESTATIC, 75 | "com/github/vfyjxf/nee/asm/AppengHooks", 76 | "updateMeInventory", 77 | "(Ljava/lang/Object;Ljava/util/List;)V", 78 | false)); 79 | methodNode.instructions.insertBefore(instruction, insnList); 80 | } 81 | } 82 | } 83 | } 84 | ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 85 | classNode.accept(classWriter); 86 | return classWriter.toByteArray(); 87 | } 88 | if ("p455w0rd/wct/sync/packets/PacketMEInventoryUpdate".equals(internalName)) { 89 | ClassNode classNode = new ClassNode(); 90 | ClassReader classReader = new ClassReader(basicClass); 91 | classReader.accept(classNode, 0); 92 | for (MethodNode methodNode : classNode.methods) { 93 | if ("clientPacketData".equals(methodNode.name) && "(Lp455w0rd/ae2wtlib/api/networking/INetworkInfo;Lp455w0rd/wct/sync/WCTPacket;Lnet/minecraft/entity/player/EntityPlayer;)V".equals(methodNode.desc)) { 94 | NotEnoughEnergistics.logger.info("Transforming : " + internalName + methodNode.name + methodNode.desc); 95 | /* 96 | *Add: AppengHooks.updateWirelessInventory(gs, this.list); 97 | */ 98 | for (AbstractInsnNode instruction : methodNode.instructions.toArray()) { 99 | int opcode = instruction.getOpcode(); 100 | if (opcode == RETURN) { 101 | InsnList insnList = new InsnList(); 102 | insnList.add(new VarInsnNode(ALOAD, 4)); 103 | insnList.add(new VarInsnNode(ALOAD, 0)); 104 | insnList.add(new FieldInsnNode(GETFIELD, 105 | "p455w0rd/wct/sync/packets/PacketMEInventoryUpdate", 106 | "list", 107 | "Ljava/util/List;")); 108 | insnList.add(new MethodInsnNode(INVOKESTATIC, 109 | "com/github/vfyjxf/nee/asm/AppengHooks", 110 | "updateWirelessInventory", 111 | "(Lnet/minecraft/client/gui/GuiScreen;Ljava/util/List;)V", 112 | false)); 113 | methodNode.instructions.insertBefore(instruction, insnList); 114 | } 115 | } 116 | } 117 | } 118 | ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); 119 | classNode.accept(classWriter); 120 | return classWriter.toByteArray(); 121 | } 122 | return basicClass; 123 | } 124 | 125 | private static boolean checkUnOfficial() { 126 | return Loader.instance() 127 | .getModList() 128 | .stream() 129 | .anyMatch(modContainer -> (modContainer.getModId().equals(Globals.APPENG) && modContainer.getVersion().contains("extended_life"))); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/asm/NEELoadingPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.asm; 2 | 3 | import net.minecraftforge.common.ForgeVersion; 4 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 5 | 6 | import javax.annotation.Nullable; 7 | import java.util.Map; 8 | 9 | @IFMLLoadingPlugin.Name("NEELoadingPlugin") 10 | @IFMLLoadingPlugin.MCVersion(ForgeVersion.mcVersion) 11 | @IFMLLoadingPlugin.TransformerExclusions("com.github.vfyjxf.nee.asm") 12 | public class NEELoadingPlugin implements IFMLLoadingPlugin { 13 | @Override 14 | public String[] getASMTransformerClass() { 15 | return new String[]{"com.github.vfyjxf.nee.asm.NEEClassTransformer"}; 16 | } 17 | 18 | @Override 19 | public String getModContainerClass() { 20 | return null; 21 | } 22 | 23 | @Nullable 24 | @Override 25 | public String getSetupClass() { 26 | return null; 27 | } 28 | 29 | @Override 30 | public void injectData(Map data) { 31 | 32 | } 33 | 34 | @Override 35 | public String getAccessTransformerClass() { 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/block/BlockPatternInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.block; 2 | 3 | import appeng.api.util.AEPartLocation; 4 | import appeng.block.AEBaseItemBlock; 5 | import appeng.block.AEBaseTileBlock; 6 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 7 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 8 | import com.github.vfyjxf.nee.utils.Globals; 9 | import net.minecraft.block.material.Material; 10 | import net.minecraft.block.state.IBlockState; 11 | import net.minecraft.entity.player.EntityPlayer; 12 | import net.minecraft.item.Item; 13 | import net.minecraft.tileentity.TileEntity; 14 | import net.minecraft.util.EnumFacing; 15 | import net.minecraft.util.EnumHand; 16 | import net.minecraft.util.math.BlockPos; 17 | import net.minecraft.world.World; 18 | 19 | /** 20 | * @author vfyjxf 21 | */ 22 | public class BlockPatternInterface extends AEBaseTileBlock { 23 | 24 | public static BlockPatternInterface BLOCK_INSTANCE = new BlockPatternInterface(); 25 | public static Item ITEM_INSTANCE = new AEBaseItemBlock(BLOCK_INSTANCE).setRegistryName(Globals.MOD_ID, "pattern_interface").setTranslationKey(Globals.MOD_ID + "." + "pattern_interface"); 26 | 27 | public BlockPatternInterface() { 28 | super(Material.IRON); 29 | setRegistryName(Globals.MOD_ID, "pattern_interface"); 30 | setTranslationKey(Globals.MOD_ID + "." + "pattern_interface"); 31 | setTileEntity(TilePatternInterface.class); 32 | 33 | } 34 | 35 | @Override 36 | public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { 37 | if (playerIn.isSneaking()) { 38 | return false; 39 | } 40 | 41 | if (!worldIn.isRemote) { 42 | TileEntity tile = worldIn.getTileEntity(pos); 43 | if (tile != null) { 44 | NEEGuiHandler.openGui(playerIn, NEEGuiHandler.PATTERN_INTERFACE_ID, tile, AEPartLocation.INTERNAL); 45 | return true; 46 | } 47 | } 48 | 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/GuiEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client; 2 | 3 | import appeng.client.gui.implementations.GuiPatternTerm; 4 | import appeng.container.slot.SlotFake; 5 | import com.github.vfyjxf.nee.client.gui.IngredientSwitcherWidget; 6 | import com.github.vfyjxf.nee.client.gui.widgets.MergeConfigButton; 7 | import com.github.vfyjxf.nee.config.NEEConfig; 8 | import com.github.vfyjxf.nee.helper.CraftingHelper; 9 | import com.github.vfyjxf.nee.helper.RecipeAnalyzer; 10 | import com.github.vfyjxf.nee.jei.PatternTransferHandler; 11 | import com.github.vfyjxf.nee.utils.ItemUtils; 12 | import mezz.jei.gui.recipes.RecipesGui; 13 | import mezz.jei.input.MouseHelper; 14 | import net.minecraft.client.Minecraft; 15 | import net.minecraft.client.gui.GuiScreen; 16 | import net.minecraft.inventory.Container; 17 | import net.minecraft.inventory.Slot; 18 | import net.minecraft.item.ItemStack; 19 | import net.minecraftforge.client.event.GuiScreenEvent; 20 | import net.minecraftforge.client.event.RenderTooltipEvent; 21 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 22 | import org.lwjgl.input.Keyboard; 23 | import org.lwjgl.input.Mouse; 24 | 25 | import java.lang.reflect.Method; 26 | import java.util.List; 27 | 28 | import static com.github.vfyjxf.nee.utils.Globals.INPUT_KEY_HEAD; 29 | 30 | public class GuiEventHandler { 31 | 32 | private static final GuiEventHandler INSTANCE = new GuiEventHandler(); 33 | 34 | public static GuiEventHandler getInstance() { 35 | return INSTANCE; 36 | } 37 | 38 | private GuiEventHandler() { 39 | 40 | } 41 | 42 | private MergeConfigButton buttonCombination; 43 | private IngredientSwitcherWidget switcherWidget; 44 | 45 | @SubscribeEvent 46 | public void beforeScreenInit(GuiScreenEvent.InitGuiEvent.Pre event) { 47 | GuiScreen screen = event.getGui(); 48 | if (screen instanceof RecipesGui) { 49 | RecipesGui recipesGui = (RecipesGui) screen; 50 | GuiScreen parent = recipesGui.getParentScreen(); 51 | if (CraftingHelper.isSupportedGui(parent)) { 52 | RecipeAnalyzer.setCleanCache(true); 53 | } 54 | } else { 55 | RecipeAnalyzer.setCleanCache(false); 56 | } 57 | } 58 | 59 | @SubscribeEvent 60 | public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre event) { 61 | Minecraft mc = Minecraft.getMinecraft(); 62 | if (handleMouseInput(mc.currentScreen)) { 63 | event.setCanceled(true); 64 | } 65 | } 66 | 67 | @SubscribeEvent 68 | public void onKeyboardInput(GuiScreenEvent.KeyboardInputEvent.Pre event) { 69 | char typedChar = Keyboard.getEventCharacter(); 70 | int eventKey = Keyboard.getEventKey(); 71 | event.setCanceled(((eventKey == 0 && typedChar >= 32) || Keyboard.getEventKeyState()) 72 | && handleKeyInput(typedChar, eventKey, event.getGui())); 73 | } 74 | 75 | private boolean handleMouseInput(GuiScreen screen) { 76 | if (handleSwitcherMouseInput(screen)) { 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | private boolean handleKeyInput(char typedChar, int eventKey, GuiScreen screen) { 83 | if (handleSwitcherKeyInput(typedChar, eventKey)) { 84 | return true; 85 | } 86 | return false; 87 | } 88 | 89 | private boolean handleSwitcherMouseInput(GuiScreen screen) { 90 | if (screen instanceof GuiPatternTerm) { 91 | GuiPatternTerm patternTerm = (GuiPatternTerm) screen; 92 | if (GuiScreen.isShiftKeyDown() && Mouse.getEventButton() == 2) { 93 | Slot slot = patternTerm.getSlotUnderMouse(); 94 | if (slot instanceof SlotFake && slot.getHasStack()) { 95 | List ingredients = PatternTransferHandler.getSwitcherData().get(INPUT_KEY_HEAD + slot.getSlotIndex()); 96 | if (ingredients != null) { 97 | ItemStack slotStack = slot.getStack(); 98 | boolean findAny = ingredients.stream().anyMatch(itemStack -> ItemUtils.matches(slotStack, itemStack)); 99 | if (findAny) { 100 | this.switcherWidget = new IngredientSwitcherWidget( 101 | slot.xPos + patternTerm.getGuiLeft() + 18, 102 | slot.yPos, 103 | 94, 104 | 97, 105 | ingredients, 106 | patternTerm, 107 | slot, 108 | () -> this.switcherWidget = null); 109 | return true; 110 | } 111 | } 112 | } 113 | } 114 | } 115 | if (screen != null && screen.mc != null) { 116 | int mouseX = MouseHelper.getX(); 117 | int mouseY = MouseHelper.getY(); 118 | int eventButton = Mouse.getEventButton(); 119 | if (eventButton > -1 && Mouse.getEventButtonState()) { 120 | if (switcherWidget != null) { 121 | return switcherWidget.handleMouseClicked(eventButton, mouseX, mouseY); 122 | } 123 | } else if (Mouse.getEventDWheel() != 0) { 124 | return handleMouseScroll(Mouse.getEventDWheel(), mouseX, mouseY); 125 | } 126 | } 127 | return false; 128 | } 129 | 130 | private boolean handleSwitcherKeyInput(char typedChar, int eventKey) { 131 | return switcherWidget != null && switcherWidget.handleKeyPressed(typedChar, eventKey); 132 | } 133 | 134 | private boolean handleMouseScroll(int dWheel, int mouseX, int mouseY) { 135 | if (switcherWidget != null) { 136 | return switcherWidget.mouseScroll(dWheel, mouseX, mouseY); 137 | } 138 | return false; 139 | } 140 | 141 | 142 | /** 143 | * Cancel other tooltip rendering when Switcher renders Tooltip. 144 | */ 145 | @SubscribeEvent 146 | public void onTooltipRender(RenderTooltipEvent.Pre event) { 147 | if (switcherWidget != null) { 148 | event.setCanceled(!switcherWidget.isRenderingTooltip()); 149 | } 150 | } 151 | 152 | @SubscribeEvent 153 | public void onInitGui(GuiScreenEvent.InitGuiEvent.Post event) { 154 | if (event.getGui() instanceof GuiPatternTerm) { 155 | GuiPatternTerm gui = (GuiPatternTerm) event.getGui(); 156 | event.getButtonList().add(buttonCombination = new MergeConfigButton(gui.getGuiLeft() + 84, gui.getGuiTop() + gui.getYSize() - 163, NEEConfig.getMergeMode())); 157 | } 158 | } 159 | 160 | @SubscribeEvent 161 | public void onDrawScreen(GuiScreenEvent.DrawScreenEvent.Post event) { 162 | if (event.getGui() instanceof GuiPatternTerm) { 163 | try { 164 | //ContainerWirelessPatternTerminal; 165 | //ContainerPatternTerm; 166 | Container container = ((GuiPatternTerm) event.getGui()).inventorySlots; 167 | Method saveMethod = container.getClass().getMethod("isCraftingMode"); 168 | if ((boolean) saveMethod.invoke(container)) { 169 | buttonCombination.enabled = false; 170 | buttonCombination.visible = false; 171 | } else { 172 | buttonCombination.enabled = true; 173 | buttonCombination.visible = true; 174 | } 175 | } catch (Exception e) { 176 | e.printStackTrace(); 177 | } 178 | if (switcherWidget != null) { 179 | int mouseX = event.getMouseX(); 180 | int mouseY = event.getMouseY(); 181 | Minecraft mc = event.getGui().mc; 182 | if (switcherWidget.isMouseOverSlot(mouseX, mouseY) || switcherWidget.isMouseOver(mouseX, mouseY)) { 183 | switcherWidget.draw(mc, event.getMouseX(), event.getMouseY(), event.getRenderPartialTicks()); 184 | } else { 185 | switcherWidget = null; 186 | } 187 | } 188 | } else { 189 | switcherWidget = null; 190 | } 191 | } 192 | 193 | } 194 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/ConfirmWrapperGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import appeng.api.storage.ITerminalHost; 4 | import appeng.client.gui.implementations.GuiCraftConfirm; 5 | import com.github.vfyjxf.nee.helper.IngredientRequester; 6 | import net.minecraft.entity.player.InventoryPlayer; 7 | 8 | /** 9 | * The main purpose of creating this class is to solve 10 | * the problem regarding the CraftingHelper not being executed correctly. 11 | */ 12 | public class ConfirmWrapperGui extends GuiCraftConfirm { 13 | 14 | public ConfirmWrapperGui(InventoryPlayer inventoryPlayer, ITerminalHost te) { 15 | super(inventoryPlayer, te); 16 | } 17 | 18 | @Override 19 | public void onGuiClosed() { 20 | super.onGuiClosed(); 21 | IngredientRequester.getInstance().requestNext(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/IInnerWidget.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | 5 | public interface IInnerWidget { 6 | 7 | default boolean isFocused(){ 8 | return true; 9 | } 10 | default void setFocused(boolean focused){ 11 | 12 | } 13 | 14 | void draw(Minecraft mc, int mouseX, int mouseY, float partialTicks); 15 | 16 | void drawTooltips(Minecraft mc, int mouseX, int mouseY); 17 | 18 | boolean handleKeyPressed(char typedChar, int eventKey); 19 | 20 | boolean handleMouseClicked(int eventButton, int mouseX, int mouseY); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/PatternInterfaceGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import appeng.client.gui.AEBaseGui; 4 | import appeng.container.slot.SlotRestrictedInput; 5 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 6 | import com.github.vfyjxf.nee.client.gui.widgets.PatternRemoveButton; 7 | import com.github.vfyjxf.nee.container.ContainerPatternInterface; 8 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 9 | import com.github.vfyjxf.nee.network.packet.PacketValueConfigServer; 10 | import com.github.vfyjxf.nee.utils.Globals; 11 | import net.minecraft.client.gui.GuiButton; 12 | import net.minecraft.entity.player.InventoryPlayer; 13 | import net.minecraft.util.ResourceLocation; 14 | 15 | import java.io.IOException; 16 | 17 | public class PatternInterfaceGui extends AEBaseGui { 18 | 19 | private final ContainerPatternInterface container; 20 | private PatternRemoveButton removeButton; 21 | 22 | public PatternInterfaceGui(InventoryPlayer playerInventory, TilePatternInterface tile) { 23 | super(new ContainerPatternInterface(playerInventory, tile)); 24 | this.xSize = 211; 25 | this.ySize = 197; 26 | this.container = (ContainerPatternInterface) this.inventorySlots; 27 | } 28 | 29 | @Override 30 | public void initGui() { 31 | super.initGui(); 32 | this.removeButton = new PatternRemoveButton(this.guiLeft + 85, this.guiTop + this.ySize - 173); 33 | addButton(removeButton); 34 | } 35 | 36 | @Override 37 | public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) { 38 | 39 | } 40 | 41 | @Override 42 | public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { 43 | this.mc.getTextureManager().bindTexture(getBackground()); 44 | this.drawTexturedModalRect(offsetX, offsetY, 0, 0, 211 - 34, this.ySize); 45 | 46 | } 47 | 48 | @Override 49 | protected void actionPerformed(GuiButton button) throws IOException { 50 | super.actionPerformed(button); 51 | if (button == this.removeButton) { 52 | if(container.getSelectedSlot() != null) { 53 | NEENetworkHandler.getInstance().sendToServer(new PacketValueConfigServer("Gui.PatternInterface")); 54 | } 55 | } 56 | } 57 | 58 | @Override 59 | protected void mouseClicked(int mouseX, int mouseY, int btn) throws IOException { 60 | if (btn == 0 && this.getSlotUnderMouse() instanceof SlotRestrictedInput) { 61 | SlotRestrictedInput slot = (SlotRestrictedInput) this.getSlotUnderMouse(); 62 | NEENetworkHandler.getInstance().sendToServer(new PacketValueConfigServer("Container.selectedSlot", Integer.toString(slot.slotNumber))); 63 | container.setSelectedSlotIndex(slot.slotNumber); 64 | } 65 | super.mouseClicked(mouseX, mouseY, btn); 66 | } 67 | 68 | private ResourceLocation getBackground() { 69 | return new ResourceLocation(Globals.MOD_ID, "textures/gui/pattern_interface.png"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/PreferenceDataGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import net.minecraft.client.gui.GuiScreen; 4 | 5 | public class PreferenceDataGui extends GuiScreen { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/QuickPusherWidget.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import appeng.client.gui.widgets.MEGuiTextField; 4 | import com.github.vfyjxf.nee.helper.RecipeHelper; 5 | import com.github.vfyjxf.nee.jei.PatternTransferHandler; 6 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 7 | import com.github.vfyjxf.nee.network.PlayerAction; 8 | import com.github.vfyjxf.nee.network.packet.PacketPlayerAction; 9 | import com.github.vfyjxf.nee.utils.ItemUtils; 10 | import mezz.jei.api.recipe.VanillaRecipeCategoryUid; 11 | import net.minecraft.client.Minecraft; 12 | import net.minecraft.client.gui.Gui; 13 | import net.minecraft.client.gui.inventory.GuiContainer; 14 | import net.minecraft.item.ItemStack; 15 | import net.minecraft.nbt.NBTTagCompound; 16 | 17 | import java.util.*; 18 | import java.util.function.Supplier; 19 | 20 | import static com.github.vfyjxf.nee.utils.Globals.INPUT_KEY_HEAD; 21 | 22 | public class QuickPusherWidget extends Gui implements IInnerWidget { 23 | 24 | private final int x; 25 | private final int y; 26 | private final int width; 27 | private final int height; 28 | private final GuiContainer screen; 29 | private final MEGuiTextField searchField; 30 | private final Map allGroups = new HashMap<>(); 31 | private final Map recommend = new HashMap<>(); 32 | private final Supplier craftingMode; 33 | private PatternGroup focusedGroup; 34 | private int scrollOffset; 35 | private int maxScroll; 36 | 37 | public QuickPusherWidget(int x, int y, int width, int height, GuiContainer screen, Supplier craftingMode) { 38 | this.x = x; 39 | this.y = y; 40 | this.width = width; 41 | this.height = height; 42 | this.screen = screen; 43 | this.craftingMode = craftingMode; 44 | searchField = null; 45 | } 46 | 47 | @Override 48 | public void draw(Minecraft mc, int mouseX, int mouseY, float partialTicks) { 49 | 50 | } 51 | 52 | @Override 53 | public void drawTooltips(Minecraft mc, int mouseX, int mouseY) { 54 | 55 | } 56 | 57 | @Override 58 | public boolean handleKeyPressed(char typedChar, int eventKey) { 59 | return false; 60 | } 61 | 62 | @Override 63 | public boolean handleMouseClicked(int eventButton, int mouseX, int mouseY) { 64 | return false; 65 | } 66 | 67 | public void syncFromServer(NBTTagCompound tag) { 68 | allGroups.clear(); 69 | recommend.clear(); 70 | for (String uid : tag.getKeySet()) { 71 | NBTTagCompound faceTag = tag.getCompoundTag(uid); 72 | String name = faceTag.getString("name"); 73 | PatternGroup group = allGroups.computeIfAbsent(name, PatternGroup::new); 74 | NBTTagCompound patternTag = faceTag.getCompoundTag("pattern"); 75 | ItemStack[] patterns = new ItemStack[patternTag.getInteger("size")]; 76 | for (int i = 0; i < patterns.length; i++) { 77 | patterns[i] = ItemUtils.fromTagOrEmpty(patternTag.getCompoundTag(INPUT_KEY_HEAD + i)); 78 | } 79 | ItemStack identity = ItemUtils.fromTagOrEmpty(faceTag.getCompoundTag("identity")); 80 | ItemStack target = ItemUtils.fromTagOrEmpty(faceTag.getCompoundTag("target")); 81 | ClientPatternProvider provider = new ClientPatternProvider(uid, name, patterns, identity, target); 82 | group.getProviders().add(provider); 83 | if (isRecommend(provider)) { 84 | recommend.computeIfAbsent(name, PatternGroup::new).getProviders().add(provider); 85 | } 86 | } 87 | } 88 | 89 | private boolean isRecommend(ClientPatternProvider provider) { 90 | if (craftingMode.get()) { 91 | return RecipeHelper.checkCatalysts(provider.getTarget(), VanillaRecipeCategoryUid.CRAFTING); 92 | } else { 93 | return RecipeHelper.checkCatalysts(provider.getTarget(), PatternTransferHandler.getLastRecipeType()); 94 | } 95 | } 96 | 97 | public static class PatternGroup extends Gui implements IInnerWidget { 98 | /** 99 | * The name of the interfaces. 100 | */ 101 | private final String groupName; 102 | 103 | private final List providers; 104 | private boolean focused; 105 | 106 | public PatternGroup(String groupName) { 107 | this.groupName = groupName; 108 | this.providers = new ArrayList<>(); 109 | } 110 | 111 | 112 | public String getGroupName() { 113 | return groupName; 114 | } 115 | 116 | public List getProviders() { 117 | return providers; 118 | } 119 | 120 | @Override 121 | public boolean isFocused() { 122 | return focused; 123 | } 124 | 125 | @Override 126 | public void setFocused(boolean focused) { 127 | this.focused = focused; 128 | } 129 | 130 | @Override 131 | public void draw(Minecraft mc, int mouseX, int mouseY, float partialTicks) { 132 | 133 | } 134 | 135 | @Override 136 | public void drawTooltips(Minecraft mc, int mouseX, int mouseY) { 137 | 138 | } 139 | 140 | @Override 141 | public boolean handleKeyPressed(char typedChar, int eventKey) { 142 | return false; 143 | } 144 | 145 | @Override 146 | public boolean handleMouseClicked(int eventButton, int mouseX, int mouseY) { 147 | return false; 148 | } 149 | } 150 | 151 | public static class ClientPatternProvider { 152 | /** 153 | * Used to control pattern from client to server. 154 | */ 155 | private final String uid; 156 | private final String name; 157 | private final ItemStack identifier; 158 | private final ItemStack target; 159 | private final ItemStack[] patterns; 160 | 161 | public ClientPatternProvider(String uid, String name, ItemStack[] patterns, ItemStack identifier, ItemStack target) { 162 | this.uid = uid; 163 | this.name = name; 164 | this.identifier = identifier; 165 | this.target = target; 166 | this.patterns = patterns; 167 | } 168 | 169 | public String getName() { 170 | return name; 171 | } 172 | 173 | public ItemStack getIdentifier() { 174 | return identifier; 175 | } 176 | 177 | public ItemStack getTarget() { 178 | return target; 179 | } 180 | 181 | public ItemStack[] getPatterns() { 182 | return patterns; 183 | } 184 | 185 | public void pickPattern(int slot) { 186 | NBTTagCompound data = new NBTTagCompound(); 187 | data.setString("uid", uid); 188 | data.setInteger("slot", slot); 189 | NEENetworkHandler.getInstance().sendToServer(new PacketPlayerAction(PlayerAction.PICK, data)); 190 | } 191 | 192 | public void putPattern(ItemStack pattern, int slot) { 193 | NBTTagCompound data = new NBTTagCompound(); 194 | data.setString("uid", uid); 195 | data.setInteger("slot", slot); 196 | data.setTag("pattern", pattern.serializeNBT()); 197 | NEENetworkHandler.getInstance().sendToServer(new PacketPlayerAction(PlayerAction.PUT, data)); 198 | } 199 | 200 | public void dropPattern(int slot) { 201 | NBTTagCompound data = new NBTTagCompound(); 202 | data.setString("uid", uid); 203 | data.setInteger("slot", slot); 204 | NEENetworkHandler.getInstance().sendToServer(new PacketPlayerAction(PlayerAction.DROP, data)); 205 | } 206 | 207 | public boolean isFull() { 208 | return Arrays.stream(patterns).noneMatch(Objects::nonNull); 209 | } 210 | 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/SuperPusherWidget.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | public class SuperPusherWidget { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/WirelessConfirmWrapperGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import appeng.api.storage.ITerminalHost; 4 | import com.github.vfyjxf.nee.helper.IngredientRequester; 5 | import net.minecraft.entity.player.InventoryPlayer; 6 | import p455w0rd.wct.client.gui.GuiCraftConfirm; 7 | 8 | public class WirelessConfirmWrapperGui extends GuiCraftConfirm { 9 | 10 | public WirelessConfirmWrapperGui(InventoryPlayer inventoryPlayer, ITerminalHost te, boolean isBauble, int wctSlot) { 11 | super(inventoryPlayer, te, isBauble, wctSlot); 12 | } 13 | 14 | @Override 15 | public void onGuiClosed() { 16 | super.onGuiClosed(); 17 | IngredientRequester.getInstance().requestNext(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/elements/HighResolutionTexture.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.elements; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.GlStateManager; 5 | 6 | public class HighResolutionTexture implements ITexture { 7 | private final ITexture texture; 8 | private final int scale; 9 | 10 | public HighResolutionTexture(ITexture texture, int scale) { 11 | this.texture = texture; 12 | this.scale = scale; 13 | } 14 | 15 | 16 | @Override 17 | public int getWidth() { 18 | return texture.getWidth() / scale; 19 | } 20 | 21 | @Override 22 | public int getHeight() { 23 | return texture.getHeight() / scale; 24 | } 25 | 26 | @Override 27 | public void draw(Minecraft mc, int xOffset, int yOffset) { 28 | GlStateManager.pushMatrix(); 29 | GlStateManager.translate(xOffset, yOffset, 0.0F); 30 | GlStateManager.scale(1.0f / scale, 1.0f / scale, 1.0f / scale); 31 | texture.draw(mc, 0, 0); 32 | GlStateManager.popMatrix(); 33 | } 34 | 35 | @Override 36 | public void draw(Minecraft mc, int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight) { 37 | draw(mc, xOffset, yOffset); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/elements/ITexture.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.elements; 2 | 3 | import net.minecraft.client.Minecraft; 4 | 5 | public interface ITexture { 6 | int getWidth(); 7 | 8 | int getHeight(); 9 | 10 | void draw(Minecraft mc, int xOffset, int yOffset); 11 | 12 | void draw(Minecraft mc, int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/elements/ResourceTexture.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.elements; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.Gui; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | public class ResourceTexture implements ITexture { 8 | 9 | private final ResourceLocation resourceLocation; 10 | private final int width; 11 | private final int height; 12 | 13 | public ResourceTexture(ResourceLocation resourceLocation, int width, int height) { 14 | this.resourceLocation = resourceLocation; 15 | this.width = width; 16 | this.height = height; 17 | } 18 | 19 | @Override 20 | public int getWidth() { 21 | return width; 22 | } 23 | 24 | @Override 25 | public int getHeight() { 26 | return height; 27 | } 28 | 29 | @Override 30 | public void draw(Minecraft minecraft, int xOffset, int yOffset) { 31 | draw(minecraft, xOffset, yOffset, 0, 0, 0, 0); 32 | } 33 | 34 | 35 | @Override 36 | public void draw(Minecraft minecraft, int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight) { 37 | minecraft.getTextureManager().bindTexture(this.resourceLocation); 38 | int width = this.width - maskRight - maskLeft; 39 | int height = this.height - maskBottom - maskTop; 40 | Gui.drawModalRectWithCustomSizedTexture(xOffset, yOffset, 0, 0, width, height, width, height); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/AddPreferenceButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import com.github.vfyjxf.nee.client.gui.IngredientSwitcherWidget; 4 | import com.github.vfyjxf.nee.config.PreferenceList; 5 | import com.github.vfyjxf.nee.helper.PreferenceHelper; 6 | import mezz.jei.gui.TooltipRenderer; 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.resources.I18n; 9 | import net.minecraft.util.ResourceLocation; 10 | 11 | import javax.annotation.Nonnull; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class AddPreferenceButton extends GuiImageButton { 16 | 17 | private final IngredientSwitcherWidget widget; 18 | private boolean ingredientExists; 19 | 20 | public AddPreferenceButton(IngredientSwitcherWidget switcherWidget, int x, int y) { 21 | super(x, y, 11, 11, false); 22 | this.widget = switcherWidget; 23 | } 24 | 25 | @Override 26 | public void drawImage(Minecraft mc) { 27 | mc.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 28 | this.drawTexturedModalRect(0, 0, 18, 2, 11, 11); 29 | if (ingredientExists) { 30 | this.drawTexturedModalRect(1, 1, 3, 84, 9, 9); 31 | } else { 32 | this.drawTexturedModalRect(1, 1, 3, 100, 9, 9); 33 | } 34 | } 35 | 36 | @Override 37 | public boolean mousePressed(@Nonnull Minecraft mc, int mouseX, int mouseY) { 38 | if (this.hovered) { 39 | if (widget.getSelectedWidget() != null) { 40 | if (ingredientExists) { 41 | PreferenceList.INSTANCE.removePreference(widget.getSelectedWidget().getIngredient()); 42 | } else { 43 | PreferenceList.INSTANCE.addPreference(widget.getSelectedWidget().getIngredient(), null); 44 | } 45 | ingredientExists = !ingredientExists; 46 | } 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | public void update() { 53 | this.ingredientExists = widget.getSelectedWidget() != null && 54 | PreferenceHelper.isPreferItem(widget.getSelectedWidget().getIngredient()); 55 | } 56 | 57 | @Override 58 | public void drawTooltip(Minecraft mc, int mouseX, int mouseY) { 59 | if (this.hovered) { 60 | List tooltips = new ArrayList<>(); 61 | tooltips.add(ingredientExists ? I18n.format("gui.neenergistics.button.tooltip.preference.remove") : I18n.format("gui.neenergistics.button.tooltip.preference.add")); 62 | tooltips.add(I18n.format("gui.neenergistics.button.tooltip.preference.text1")); 63 | TooltipRenderer.drawHoveringText(mc, tooltips, mouseX, mouseY); 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/GuiImageButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import com.github.vfyjxf.nee.utils.Globals; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.gui.GuiButton; 6 | import net.minecraft.client.renderer.GlStateManager; 7 | import net.minecraft.util.ResourceLocation; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | public abstract class GuiImageButton extends GuiButton { 12 | public static final ResourceLocation STATES = new ResourceLocation(Globals.MOD_ID, "textures/gui/states.png"); 13 | 14 | private final boolean halfSize; 15 | 16 | public GuiImageButton(int x, int y, int width, int height, boolean halfSize) { 17 | super(0, x, y, width, height, ""); 18 | this.halfSize = halfSize; 19 | } 20 | 21 | @Override 22 | public void drawButton(@Nonnull Minecraft mc, int mouseX, int mouseY, float partialTicks) { 23 | if (this.visible) { 24 | this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; 25 | GlStateManager.pushMatrix(); 26 | GlStateManager.translate(this.x, this.y, 0.0F); 27 | if (halfSize) { 28 | GlStateManager.scale(0.5f, 0.5f, 0.5f); 29 | } 30 | if (this.enabled) { 31 | GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); 32 | } else { 33 | GlStateManager.color(0.5f, 0.5f, 0.5f, 1.0f); 34 | } 35 | GlStateManager.enableAlpha(); 36 | this.drawImage(mc); 37 | this.mouseDragged(mc, mouseX, mouseY); 38 | GlStateManager.popMatrix(); 39 | } 40 | GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); 41 | } 42 | 43 | public abstract void drawImage(Minecraft mc); 44 | 45 | public void drawTooltip(Minecraft mc, int mouseX, int mouseY) { 46 | 47 | } 48 | 49 | @Override 50 | public boolean mousePressed(@Nonnull Minecraft mc, int mouseX, int mouseY) { 51 | if (this.hovered) { 52 | return true; 53 | } 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/ItemWidget.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import com.github.vfyjxf.nee.helper.PreferenceHelper; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.gui.FontRenderer; 6 | import net.minecraft.client.gui.Gui; 7 | import net.minecraft.client.gui.GuiScreen; 8 | import net.minecraft.client.renderer.GlStateManager; 9 | import net.minecraft.client.renderer.RenderHelper; 10 | import net.minecraft.item.ItemStack; 11 | 12 | public class ItemWidget extends Gui { 13 | 14 | private boolean visible; 15 | private boolean isSelected; 16 | private int posX; 17 | private int posY; 18 | private int width; 19 | private int height; 20 | private boolean isPreferred; 21 | private final ItemStack ingredient; 22 | 23 | public ItemWidget(ItemStack ingredient, int posX, int posY) { 24 | this.ingredient = ingredient; 25 | this.posX = posX; 26 | this.posY = posY; 27 | this.width = 18; 28 | this.height = 18; 29 | this.visible = true; 30 | this.isPreferred = PreferenceHelper.isPreferItem(ingredient); 31 | } 32 | 33 | public void setVisible(boolean visible) { 34 | this.visible = visible; 35 | } 36 | 37 | public void updatePosition(int posX, int posY) { 38 | this.posX = posX; 39 | this.posY = posY; 40 | } 41 | 42 | public ItemStack getIngredient() { 43 | return ingredient; 44 | } 45 | 46 | public boolean isMouseOver(int mouseX, int mouseY) { 47 | return visible && (mouseX >= posX && mouseX <= posX + width && mouseY >= posY && mouseY <= posY + height); 48 | } 49 | 50 | public void drawWidget(Minecraft mc, int mouseX, int mouseY) { 51 | if (visible) { 52 | FontRenderer fontRenderer = ingredient.getItem().getFontRenderer(ingredient); 53 | if (fontRenderer == null) { 54 | fontRenderer = mc.fontRenderer; 55 | } 56 | GlStateManager.enableDepth(); 57 | this.zLevel += 300; 58 | mc.getRenderItem().zLevel += 300; 59 | RenderHelper.enableGUIStandardItemLighting(); 60 | mc.getRenderItem().renderItemAndEffectIntoGUI(null, ingredient, posX, posY); 61 | mc.getRenderItem().renderItemOverlayIntoGUI(fontRenderer, ingredient, mouseX, mouseY, null); 62 | GlStateManager.disableBlend(); 63 | RenderHelper.disableStandardItemLighting(); 64 | this.zLevel -= 300; 65 | mc.getRenderItem().zLevel -= 300; 66 | 67 | if (isPreferred){ 68 | 69 | } 70 | 71 | if (isSelected) { 72 | GlStateManager.disableDepth(); 73 | RenderHelper.disableStandardItemLighting(); 74 | drawRect(posX, posY, posX + 16, posY + 16, 0x660000ff); 75 | GlStateManager.enableDepth(); 76 | } 77 | } 78 | } 79 | 80 | public void drawTooltips(Minecraft mc, GuiScreen screen, int mouseX, int mouseY) { 81 | GlStateManager.disableDepth(); 82 | RenderHelper.disableStandardItemLighting(); 83 | if (!isSelected) { 84 | drawRect(posX, posY, posX + 16, posY + 16, 0x80FFFFFF); 85 | } 86 | GlStateManager.color(1f, 1f, 1f, 1f); 87 | screen.drawHoveringText(screen.getItemToolTip(ingredient), mouseX, mouseY); 88 | GlStateManager.enableDepth(); 89 | } 90 | 91 | public void setSelected(boolean selected) { 92 | isSelected = selected; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/MergeConfigButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import appeng.client.gui.widgets.ITooltip; 4 | import com.github.vfyjxf.nee.config.IngredientMergeMode; 5 | import com.github.vfyjxf.nee.config.NEEConfig; 6 | import net.minecraft.client.Minecraft; 7 | import net.minecraft.client.resources.I18n; 8 | import net.minecraft.util.ResourceLocation; 9 | import org.lwjgl.input.Mouse; 10 | 11 | import javax.annotation.Nonnull; 12 | 13 | public class MergeConfigButton extends GuiImageButton implements ITooltip { 14 | private IngredientMergeMode mergeMode; 15 | 16 | public MergeConfigButton(int x, int y, IngredientMergeMode value) { 17 | super(x, y, 8, 8, true); 18 | this.x = x; 19 | this.y = y; 20 | this.mergeMode = value; 21 | } 22 | 23 | public void setMode(IngredientMergeMode mergeMode) { 24 | this.mergeMode = mergeMode; 25 | } 26 | 27 | public IngredientMergeMode getMergeMode() { 28 | return mergeMode; 29 | } 30 | 31 | @Override 32 | public void drawImage(Minecraft mc) { 33 | mc.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 34 | this.drawTexturedModalRect(0, 0, 0, 0, 16, 16); 35 | if (this.mergeMode == IngredientMergeMode.DISABLED) { 36 | this.drawTexturedModalRect(0, 0, 0, 16, 16, 16); 37 | } 38 | if (this.mergeMode == IngredientMergeMode.ENABLED) { 39 | this.drawTexturedModalRect(0, 0, 0, 32, 16, 16); 40 | } 41 | 42 | } 43 | 44 | @Override 45 | public String getMessage() { 46 | return I18n.format("gui.neenergistics.button.title.combination") + 47 | "\n" + 48 | I18n.format("gui.neenergistics.button.tooltip.combination", mergeMode.getLocalName()); 49 | } 50 | 51 | @Override 52 | public boolean mousePressed(@Nonnull Minecraft mc, int mouseX, int mouseY) { 53 | if (this.hovered) { 54 | int ordinal = Mouse.getEventButton() != 2 ? this.getMergeMode().ordinal() + 1 : this.getMergeMode().ordinal() - 1; 55 | 56 | if (ordinal >= IngredientMergeMode.values().length) { 57 | ordinal = 0; 58 | } 59 | if (ordinal < 0) { 60 | ordinal = IngredientMergeMode.values().length - 1; 61 | } 62 | this.setMode(IngredientMergeMode.values()[ordinal]); 63 | NEEConfig.setMergeMode(IngredientMergeMode.values()[ordinal]); 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | @Override 70 | public int xPos() { 71 | return this.x; 72 | } 73 | 74 | @Override 75 | public int yPos() { 76 | return this.y; 77 | } 78 | 79 | @Override 80 | public int getWidth() { 81 | return this.width; 82 | } 83 | 84 | @Override 85 | public int getHeight() { 86 | return this.height; 87 | } 88 | 89 | @Override 90 | public boolean isVisible() { 91 | return this.visible; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/OpenPreferenceDataButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import mezz.jei.gui.TooltipRenderer; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.resources.I18n; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | public class OpenPreferenceDataButton extends GuiImageButton { 9 | public OpenPreferenceDataButton(int x, int y) { 10 | super(x, y, 11, 11, false); 11 | } 12 | 13 | @Override 14 | public void drawImage(Minecraft mc) { 15 | mc.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 16 | this.drawTexturedModalRect(0, 0, 18, 2, 11, 11); 17 | this.drawTexturedModalRect(1, 1, 3, 116, 9, 9); 18 | } 19 | 20 | @Override 21 | public void drawTooltip(Minecraft mc, int mouseX, int mouseY) { 22 | if (this.hovered) { 23 | String tooltip = I18n.format("gui.neenergistics.button.tooltip.preference.open"); 24 | TooltipRenderer.drawHoveringText(mc, tooltip, mouseX, mouseY); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/PatternRemoveButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import appeng.client.gui.widgets.ITooltip; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.resources.I18n; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | public class PatternRemoveButton extends GuiImageButton implements ITooltip { 9 | 10 | public PatternRemoveButton(int x, int y) { 11 | super(x, y, 8, 8, true); 12 | } 13 | 14 | @Override 15 | public void drawImage(Minecraft mc) { 16 | mc.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 17 | this.drawTexturedModalRect(0, 0, 0, 0, 16, 16); 18 | this.drawTexturedModalRect(0, 0, 0, 64, 16, 16); 19 | } 20 | 21 | @Override 22 | public String getMessage() { 23 | return I18n.format("gui.neenergistics.button.title.remove") + 24 | "\n" + 25 | I18n.format("gui.neenergistics.button.tooltip.remove"); 26 | } 27 | 28 | @Override 29 | public int xPos() { 30 | return this.x; 31 | } 32 | 33 | @Override 34 | public int yPos() { 35 | return this.y; 36 | } 37 | 38 | @Override 39 | public int getWidth() { 40 | return this.width; 41 | } 42 | 43 | @Override 44 | public int getHeight() { 45 | return this.height; 46 | } 47 | 48 | @Override 49 | public boolean isVisible() { 50 | return this.visible; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/QuicklyPusherButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import com.github.vfyjxf.nee.client.gui.QuickPusherWidget; 4 | import com.github.vfyjxf.nee.client.gui.elements.HighResolutionTexture; 5 | import com.github.vfyjxf.nee.client.gui.elements.ITexture; 6 | import com.github.vfyjxf.nee.client.gui.elements.ResourceTexture; 7 | import com.github.vfyjxf.nee.utils.Globals; 8 | import net.minecraft.client.Minecraft; 9 | import net.minecraft.client.gui.inventory.GuiContainer; 10 | import net.minecraft.util.ResourceLocation; 11 | 12 | import javax.annotation.Nonnull; 13 | import javax.annotation.Nullable; 14 | 15 | public class QuicklyPusherButton extends GuiImageButton { 16 | 17 | private static final ITexture QUICKLY_PUSHER_ICON = new HighResolutionTexture(new ResourceTexture(new ResourceLocation(Globals.MOD_ID, "textures/gui/quickly_pusher_icon.png"), 16, 16), 1); 18 | private static final ITexture SUPER_PUSHER_ICON = new HighResolutionTexture(new ResourceTexture(new ResourceLocation(Globals.MOD_ID, "textures/gui/super_pusher_icon.png"), 16, 16), 1); 19 | 20 | private boolean isSuper; 21 | @Nullable 22 | private QuickPusherWidget widget; 23 | 24 | public QuicklyPusherButton(int x, int y) { 25 | super(x, y, 16, 16, false); 26 | } 27 | 28 | @Override 29 | public boolean mousePressed(@Nonnull Minecraft mc, int mouseX, int mouseY) { 30 | if (this.hovered) { 31 | if (widget == null) { 32 | return false; 33 | } 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | @Override 40 | public void drawImage(Minecraft mc) { 41 | mc.renderEngine.bindTexture(STATES); 42 | this.drawTexturedModalRect(0, 0, 0, 0, 16, 16); 43 | if (GuiContainer.isShiftKeyDown()) { 44 | this.isSuper = true; 45 | SUPER_PUSHER_ICON.draw(mc, x, y); 46 | } else { 47 | this.isSuper = false; 48 | QUICKLY_PUSHER_ICON.draw(mc, x, y); 49 | } 50 | } 51 | 52 | @Override 53 | public void drawTooltip(Minecraft mc, int mouseX, int mouseY) { 54 | if (this.hovered) { 55 | 56 | } 57 | } 58 | 59 | public boolean isSuper() { 60 | return isSuper; 61 | } 62 | 63 | public void setWidget(@Nullable QuickPusherWidget widget) { 64 | this.widget = widget; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/IngredientBlackList.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import com.github.vfyjxf.nee.utils.BlackIngredient; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.nbt.JsonToNBT; 6 | import net.minecraft.nbt.NBTException; 7 | import org.apache.commons.io.IOUtils; 8 | import org.apache.logging.log4j.LogManager; 9 | import org.apache.logging.log4j.Logger; 10 | 11 | import java.io.File; 12 | import java.io.FileReader; 13 | import java.io.FileWriter; 14 | import java.io.IOException; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | public class IngredientBlackList { 20 | 21 | private static final Logger LOGGER = LogManager.getLogger(); 22 | 23 | public static final IngredientBlackList INSTANCE = new IngredientBlackList(); 24 | 25 | private final List blackList = new ArrayList<>(); 26 | 27 | private IngredientBlackList() { 28 | 29 | } 30 | 31 | public void addPreference(ItemStack stack, String acceptedType) { 32 | BlackIngredient ingredient = new BlackIngredient(stack, acceptedType); 33 | if (!blackList.contains(ingredient)) { 34 | blackList.add(ingredient); 35 | saveList(); 36 | } 37 | } 38 | 39 | public List getBlackList() { 40 | return blackList; 41 | } 42 | 43 | public void loadList() { 44 | 45 | File file = NEEConfig.getBlacklistFile(); 46 | if (file == null || !file.exists()) { 47 | return; 48 | } 49 | 50 | List strings; 51 | try (FileReader reader = new FileReader(file)) { 52 | strings = IOUtils.readLines(reader); 53 | } catch (IOException e) { 54 | LOGGER.error("Failed to load blacklist from file {}", file, e); 55 | return; 56 | } 57 | 58 | List list = strings.stream() 59 | .map(jsonString -> { 60 | try { 61 | return JsonToNBT.getTagFromJson(jsonString); 62 | } catch (NBTException e) { 63 | throw new RuntimeException(e); 64 | } 65 | }) 66 | .map(tagCompound -> { 67 | ItemStack identifier = new ItemStack(tagCompound.getCompoundTag("identifier")); 68 | String acceptedType = tagCompound.hasKey("acceptedType") ? tagCompound.getString("acceptedType") : null; 69 | return new BlackIngredient(identifier, acceptedType); 70 | }) 71 | .collect(Collectors.toList()); 72 | 73 | this.blackList.clear(); 74 | this.blackList.addAll(list); 75 | } 76 | 77 | public void saveList() { 78 | File file = NEEConfig.getBlacklistFile(); 79 | if (file != null) { 80 | List strings = blackList.stream() 81 | .map(blackIngredient -> blackIngredient.toTag().toString()) 82 | .collect(Collectors.toList()); 83 | try (FileWriter writer = new FileWriter(file)) { 84 | IOUtils.writeLines(strings, "\n", writer); 85 | } catch (IOException e) { 86 | LOGGER.error("Failed to save blacklist to file {}", file, e); 87 | } 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/IngredientMergeMode.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import net.minecraft.client.resources.I18n; 4 | 5 | import java.util.Locale; 6 | 7 | public enum IngredientMergeMode { 8 | DISABLED, ENABLED; 9 | 10 | public String getLocalName() { 11 | return I18n.format("gui.neenergistics.button.name" + "." + this.name().toLowerCase(Locale.ROOT)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/KeyBindings.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import net.minecraft.client.settings.KeyBinding; 4 | import net.minecraftforge.client.settings.KeyConflictContext; 5 | import org.lwjgl.input.Keyboard; 6 | 7 | public final class KeyBindings { 8 | 9 | public static final KeyBinding SWITCH_INGREDIENT = new KeyBinding("key.neenergistics.ingredient.switch", KeyConflictContext.GUI, Keyboard.KEY_LSHIFT, "neenergistics.category"); 10 | public static final KeyBinding MODIFY_COUNT = new KeyBinding("key.neenergistics.stack.count.change", KeyConflictContext.GUI, Keyboard.KEY_LCONTROL, "neenergistics.category"); 11 | public static final KeyBinding AUTO_CRAFT_WITH_PREVIEW = new KeyBinding("key.neenergistics.crafting.helper.preview", KeyConflictContext.GUI, Keyboard.KEY_LCONTROL, "neenergistics.category"); 12 | public static final KeyBinding AUTO_CRAFT_NON_PREVIEW = new KeyBinding("key.neenergistics.crafting.helper.noPreview", KeyConflictContext.GUI, Keyboard.KEY_LMENU, "neenergistics.category"); 13 | 14 | public static boolean isSwitchIngredientKeyDown() { 15 | return Keyboard.isKeyDown(SWITCH_INGREDIENT.getKeyCode()); 16 | } 17 | 18 | public static boolean isModifyCountKeyDown() { 19 | return Keyboard.isKeyDown(MODIFY_COUNT.getKeyCode()); 20 | } 21 | 22 | public static boolean isPreviewKeyDown() { 23 | return Keyboard.isKeyDown(AUTO_CRAFT_WITH_PREVIEW.getKeyCode()); 24 | } 25 | 26 | public static boolean isNonPreviewKeyDown() { 27 | return Keyboard.isKeyDown(AUTO_CRAFT_NON_PREVIEW.getKeyCode()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/NEEConfigGuiFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import com.github.vfyjxf.nee.utils.Globals; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.gui.GuiScreen; 6 | import net.minecraftforge.common.config.ConfigElement; 7 | import net.minecraftforge.common.config.Configuration; 8 | import net.minecraftforge.fml.client.IModGuiFactory; 9 | import net.minecraftforge.fml.client.config.GuiConfig; 10 | import net.minecraftforge.fml.client.config.IConfigElement; 11 | 12 | import java.util.List; 13 | import java.util.Set; 14 | import java.util.stream.Collectors; 15 | 16 | @SuppressWarnings("unused") 17 | public class NEEConfigGuiFactory implements IModGuiFactory { 18 | @Override 19 | public void initialize(Minecraft minecraftInstance) { 20 | 21 | } 22 | 23 | @Override 24 | public boolean hasConfigGui() { 25 | return true; 26 | } 27 | 28 | @Override 29 | public GuiScreen createConfigGui(GuiScreen parentScreen) { 30 | return new GuiConfig(parentScreen, getConfigElements(), Globals.MOD_ID, false, false, Globals.NAME); 31 | } 32 | 33 | @Override 34 | public Set runtimeGuiCategories() { 35 | return null; 36 | } 37 | 38 | private static List getConfigElements() { 39 | Configuration config = NEEConfig.getConfig(); 40 | return config.getCategoryNames() 41 | .stream() 42 | .map(name -> new ConfigElement(config.getCategory(name))) 43 | .collect(Collectors.toList()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/PreferenceList.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import com.github.vfyjxf.nee.helper.PreferenceHelper; 4 | import com.github.vfyjxf.nee.integration.IToolHelper; 5 | import com.github.vfyjxf.nee.integration.RecipeToolManager; 6 | import com.github.vfyjxf.nee.utils.PreferenceIngredient; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.nbt.JsonToNBT; 9 | import net.minecraft.nbt.NBTException; 10 | import org.apache.commons.io.IOUtils; 11 | import org.apache.logging.log4j.LogManager; 12 | import org.apache.logging.log4j.Logger; 13 | 14 | import java.io.File; 15 | import java.io.FileReader; 16 | import java.io.FileWriter; 17 | import java.io.IOException; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.stream.Collectors; 21 | 22 | public class PreferenceList { 23 | 24 | private static final Logger LOGGER = LogManager.getLogger(); 25 | 26 | public static final PreferenceList INSTANCE = new PreferenceList(); 27 | 28 | private final List preferenceList = new ArrayList<>(); 29 | 30 | private PreferenceList() { 31 | 32 | } 33 | 34 | public List getPreferenceList() { 35 | return preferenceList; 36 | } 37 | 38 | public void addPreference(ItemStack stack, String acceptedType) { 39 | IToolHelper toolHelper = RecipeToolManager.INSTANCE.getToolHelper(stack.getItem()); 40 | boolean isTool = toolHelper != null; 41 | PreferenceIngredient ingredient = new PreferenceIngredient(stack.copy(), isTool, acceptedType); 42 | if (!preferenceList.contains(ingredient)) { 43 | preferenceList.add(ingredient); 44 | saveList(); 45 | } 46 | } 47 | 48 | public void removePreference(ItemStack stack) { 49 | PreferenceIngredient ingredient = PreferenceHelper.getPreferIngredient(stack, null); 50 | if (ingredient != null) { 51 | preferenceList.remove(ingredient); 52 | saveList(); 53 | } 54 | } 55 | 56 | public void loadList() { 57 | 58 | File file = NEEConfig.getPreferenceConfigFile(); 59 | if (file == null || !file.exists()) { 60 | return; 61 | } 62 | 63 | List strings; 64 | try (FileReader reader = new FileReader(file)) { 65 | strings = IOUtils.readLines(reader); 66 | } catch (IOException e) { 67 | LOGGER.error("Failed to load preference list from file {}", file, e); 68 | return; 69 | } 70 | 71 | List list = strings.stream() 72 | .map(jsonString -> { 73 | try { 74 | return JsonToNBT.getTagFromJson(jsonString); 75 | } catch (NBTException e) { 76 | throw new RuntimeException(e); 77 | } 78 | }) 79 | .map(tagCompound -> { 80 | ItemStack identifier = new ItemStack(tagCompound.getCompoundTag("identifier")); 81 | boolean isTool = tagCompound.getBoolean("isTool"); 82 | String acceptedType = tagCompound.hasKey("acceptedType") ? tagCompound.getString("acceptedType") : null; 83 | return new PreferenceIngredient(identifier, isTool, acceptedType); 84 | }) 85 | .collect(Collectors.toList()); 86 | 87 | this.preferenceList.clear(); 88 | this.preferenceList.addAll(list); 89 | 90 | } 91 | 92 | public void saveList() { 93 | File file = NEEConfig.getPreferenceConfigFile(); 94 | if (file != null) { 95 | List strings = preferenceList.stream() 96 | .map(preferenceIngredient -> preferenceIngredient.toTag().toString()) 97 | .collect(Collectors.toList()); 98 | try (FileWriter writer = new FileWriter(file)) { 99 | IOUtils.writeLines(strings, "\n", writer); 100 | } catch (IOException e) { 101 | LOGGER.error("Failed to save preference list to file {}", file, e); 102 | } 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/container/ContainerCraftingAmount.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.container; 2 | 3 | import appeng.api.config.SecurityPermissions; 4 | import appeng.api.networking.IGrid; 5 | import appeng.api.networking.security.IActionHost; 6 | import appeng.api.networking.security.IActionSource; 7 | import appeng.container.AEBaseContainer; 8 | import appeng.container.slot.SlotInaccessible; 9 | import appeng.me.helpers.PlayerSource; 10 | import appeng.tile.inventory.AppEngInternalInventory; 11 | import net.minecraft.entity.player.InventoryPlayer; 12 | import net.minecraft.inventory.Slot; 13 | import net.minecraft.item.ItemStack; 14 | import net.minecraft.nbt.NBTTagCompound; 15 | import net.minecraft.world.World; 16 | 17 | public class ContainerCraftingAmount extends AEBaseContainer { 18 | 19 | private final Slot resultSlot; 20 | private ItemStack resultStack; 21 | private boolean isBauble; 22 | private int wctSlot = -1; 23 | private NBTTagCompound recipe; 24 | 25 | public ContainerCraftingAmount(InventoryPlayer ip, Object anchor) { 26 | super(ip, anchor); 27 | this.resultSlot = new SlotInaccessible(new AppEngInternalInventory(null, 1), 0, 34, 53); 28 | this.addSlotToContainer(resultSlot); 29 | } 30 | 31 | @Override 32 | public void detectAndSendChanges() { 33 | super.detectAndSendChanges(); 34 | this.verifyPermissions(SecurityPermissions.CRAFT, false); 35 | } 36 | 37 | public IGrid getGrid() { 38 | final IActionHost h = ((IActionHost) this.getTarget()); 39 | return h.getActionableNode().getGrid(); 40 | } 41 | 42 | public World getWorld() { 43 | return this.getPlayerInv().player.world; 44 | } 45 | 46 | public IActionSource getActionSrc() { 47 | return new PlayerSource(this.getPlayerInv().player, (IActionHost) this.getTarget()); 48 | } 49 | 50 | public Slot getResultSlot() { 51 | return resultSlot; 52 | } 53 | 54 | public ItemStack getResultStack() { 55 | if (resultStack == null) { 56 | return ItemStack.EMPTY; 57 | } 58 | return resultStack; 59 | } 60 | 61 | public NBTTagCompound getRecipe() { 62 | return recipe; 63 | } 64 | 65 | public boolean isBauble() { 66 | return isBauble; 67 | } 68 | 69 | public int getWctSlot() { 70 | return wctSlot; 71 | } 72 | 73 | public void setBauble(boolean bauble) { 74 | isBauble = bauble; 75 | } 76 | 77 | public void setWctSlot(int wctSlot) { 78 | this.wctSlot = wctSlot; 79 | } 80 | 81 | public boolean isWirelessTerm() { 82 | return this.wctSlot >= 0; 83 | } 84 | 85 | public void setRecipe(NBTTagCompound recipe) { 86 | this.recipe = recipe; 87 | } 88 | 89 | public void setResultStack(ItemStack resultStack) { 90 | this.resultStack = resultStack; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/container/ContainerCraftingConfirmWrapper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.container; 2 | 3 | import appeng.api.storage.ITerminalHost; 4 | import appeng.container.implementations.ContainerCraftConfirm; 5 | import appeng.util.Platform; 6 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 7 | import net.minecraft.entity.player.EntityPlayer; 8 | import net.minecraft.entity.player.InventoryPlayer; 9 | import net.minecraft.item.ItemStack; 10 | 11 | public class ContainerCraftingConfirmWrapper extends ContainerCraftConfirm { 12 | 13 | private TilePatternInterface tile; 14 | private int patternIndex; 15 | private boolean hasWorkCommitted = false; 16 | 17 | public ContainerCraftingConfirmWrapper(InventoryPlayer ip, ITerminalHost te) { 18 | super(ip, te); 19 | } 20 | 21 | @Override 22 | public void startJob() { 23 | if (Platform.isServer() && tile != null) { 24 | hasWorkCommitted = true; 25 | } 26 | super.startJob(); 27 | } 28 | 29 | @Override 30 | public void onContainerClosed(EntityPlayer entityPlayer) { 31 | super.onContainerClosed(entityPlayer); 32 | if (Platform.isServer() && tile != null && !hasWorkCommitted) { 33 | tile.getPatternInventory().setStackInSlot(patternIndex, ItemStack.EMPTY); 34 | tile.updateCraftingList(); 35 | } 36 | } 37 | 38 | public void setTile(TilePatternInterface tile) { 39 | this.tile = tile; 40 | } 41 | 42 | public void setPatternIndex(int patternIndex) { 43 | this.patternIndex = patternIndex; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/container/ContainerPatternInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.container; 2 | 3 | import appeng.api.implementations.ICraftingPatternItem; 4 | import appeng.api.networking.crafting.ICraftingPatternDetails; 5 | import appeng.api.storage.data.IAEItemStack; 6 | import appeng.container.AEBaseContainer; 7 | import appeng.container.ContainerNull; 8 | import appeng.container.guisync.GuiSync; 9 | import appeng.container.slot.AppEngSlot; 10 | import appeng.container.slot.SlotDisabled; 11 | import appeng.container.slot.SlotRestrictedInput; 12 | import appeng.tile.inventory.AppEngInternalInventory; 13 | import appeng.util.Platform; 14 | import appeng.util.inv.IAEAppEngInventory; 15 | import appeng.util.inv.InvOperation; 16 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 17 | import net.minecraft.entity.player.EntityPlayer; 18 | import net.minecraft.entity.player.InventoryPlayer; 19 | import net.minecraft.inventory.InventoryCrafting; 20 | import net.minecraft.inventory.Slot; 21 | import net.minecraft.item.ItemStack; 22 | import net.minecraftforge.items.IItemHandler; 23 | 24 | import static appeng.container.slot.SlotRestrictedInput.PlacableItemType.ENCODED_PATTERN; 25 | 26 | public class ContainerPatternInterface extends AEBaseContainer implements IAEAppEngInventory { 27 | 28 | private final InventoryPlayer playerInventory; 29 | private final AppEngInternalInventory recipeInv; 30 | private final AppEngInternalInventory patterns; 31 | private final SlotRestrictedInput[] patternSlots = new SlotRestrictedInput[9]; 32 | private final AppEngSlot[] recipeSlots = new AppEngSlot[10]; 33 | 34 | @GuiSync(0) 35 | private int selectedSlotIndex = -1; 36 | 37 | public ContainerPatternInterface(InventoryPlayer playerInventory, TilePatternInterface tile) { 38 | super(playerInventory, tile); 39 | this.playerInventory = playerInventory; 40 | this.recipeInv = tile.getGirdInventory(); 41 | this.patterns = tile.getPatternInventory(); 42 | 43 | for (int i = 0; i < patterns.getSlots(); i++) { 44 | addSlotToContainer(patternSlots[i] = new SlotRestrictedInput(ENCODED_PATTERN, patterns, i, 8 + 18 * i, 90 + 5, playerInventory) { 45 | @Override 46 | public boolean isItemValid(ItemStack i) { 47 | return false; 48 | } 49 | 50 | @Override 51 | public boolean canTakeStack(EntityPlayer par1EntityPlayer) { 52 | return false; 53 | } 54 | }); 55 | } 56 | 57 | for (int y = 0; y < 3; y++) { 58 | for (int x = 0; x < 3; x++) { 59 | this.addSlotToContainer(recipeSlots[x + y * 3] = new SlotDisabled(recipeInv, x + y * 3, 29 + x * 18, 30 + y * 18)); 60 | } 61 | } 62 | 63 | this.addSlotToContainer(recipeSlots[9] = new SlotDisabled(recipeInv, 9, 126, 48)); 64 | 65 | this.bindPlayerInventory(playerInventory, 0, 184 - 69); 66 | } 67 | 68 | 69 | @Override 70 | public void detectAndSendChanges() { 71 | super.detectAndSendChanges(); 72 | } 73 | 74 | @Override 75 | public void onContainerClosed(EntityPlayer playerIn) { 76 | super.onContainerClosed(playerIn); 77 | clearRecipe(); 78 | } 79 | 80 | @Override 81 | public boolean canInteractWith(EntityPlayer playerIn) { 82 | return isValidContainer(); 83 | } 84 | 85 | public Slot getSelectedSlot() { 86 | return selectedSlotIndex >= 0 && selectedSlotIndex <= 9 ? patternSlots[selectedSlotIndex] : null; 87 | } 88 | 89 | public AppEngInternalInventory getRecipeInventory() { 90 | return recipeInv; 91 | } 92 | 93 | public int getSelectedSlotIndex() { 94 | return selectedSlotIndex; 95 | } 96 | 97 | public void setSelectedSlotIndex(int index) { 98 | this.selectedSlotIndex = index; 99 | 100 | if (Platform.isServer()) { 101 | Slot slot = this.getSelectedSlot(); 102 | if (slot instanceof SlotRestrictedInput) { 103 | if (slot.getHasStack()) { 104 | ItemStack maybePattern = slot.getStack(); 105 | if (maybePattern.getItem() instanceof ICraftingPatternItem) { 106 | ICraftingPatternDetails details = ((ICraftingPatternItem) maybePattern.getItem()).getPatternForItem(maybePattern, getTileEntity().getWorld()); 107 | 108 | if ((details.getInputs().length == 9) && (details.getOutputs().length > 0)) { 109 | InventoryCrafting ic = new InventoryCrafting(new ContainerNull(), 3, 3); 110 | for (int i = 0; i < details.getInputs().length; i++) { 111 | IAEItemStack stack = details.getInputs()[i]; 112 | Slot currentSlot = getSlotFromInventory(this.getRecipeInventory(), i); 113 | if (currentSlot != null) { 114 | if (stack != null) { 115 | ItemStack is = stack.createItemStack(); 116 | currentSlot.putStack(is); 117 | ic.setInventorySlotContents(i, is); 118 | } else { 119 | currentSlot.putStack(ItemStack.EMPTY); 120 | } 121 | } 122 | } 123 | Slot outSlot = getSlotFromInventory(this.getRecipeInventory(), 9); 124 | if (outSlot != null) { 125 | outSlot.putStack(details.getOutput(ic, getTileEntity().getWorld())); 126 | } 127 | } 128 | } 129 | } 130 | } 131 | } 132 | 133 | this.detectAndSendChanges(); 134 | } 135 | 136 | public void removeCurrentRecipe() { 137 | Slot patternSlot = this.getSelectedSlot(); 138 | if (patternSlot != null && patternSlot.getHasStack()) { 139 | patternSlot.putStack(ItemStack.EMPTY); 140 | clearRecipe(); 141 | } 142 | this.detectAndSendChanges(); 143 | } 144 | 145 | private void clearRecipe() { 146 | for (Slot slot : this.recipeSlots) { 147 | slot.putStack(ItemStack.EMPTY); 148 | } 149 | } 150 | 151 | private Slot getSlotFromInventory(IItemHandler inv, int slotIn) { 152 | for (Slot slot : this.inventorySlots) { 153 | if (slot instanceof AppEngSlot) { 154 | if (((AppEngSlot) slot).getItemHandler().equals(inv) && slot.getSlotIndex() == slotIn) { 155 | return slot; 156 | } 157 | } 158 | 159 | } 160 | return null; 161 | } 162 | 163 | @Override 164 | public void saveChanges() { 165 | 166 | } 167 | 168 | @Override 169 | public void onChangeInventory(IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack) { 170 | 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/container/WCTContainerCraftingConfirm.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.container; 2 | 3 | import appeng.api.storage.ITerminalHost; 4 | import appeng.util.Platform; 5 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.entity.player.InventoryPlayer; 8 | import net.minecraft.item.ItemStack; 9 | import p455w0rd.wct.container.ContainerCraftConfirm; 10 | 11 | public class WCTContainerCraftingConfirm extends ContainerCraftConfirm { 12 | 13 | private TilePatternInterface tile; 14 | private int patternIndex; 15 | private boolean hasWorkCommitted = false; 16 | 17 | public WCTContainerCraftingConfirm(InventoryPlayer ip, ITerminalHost te, boolean isBauble, int wctSlot) { 18 | super(ip, te, isBauble, wctSlot); 19 | } 20 | 21 | @Override 22 | public void startJob() { 23 | if (Platform.isServer() && this.tile != null) { 24 | hasWorkCommitted = true; 25 | } 26 | super.startJob(); 27 | } 28 | 29 | @Override 30 | public void onContainerClosed(EntityPlayer entityPlayer) { 31 | super.onContainerClosed(entityPlayer); 32 | if (Platform.isServer() && this.tile != null && !hasWorkCommitted) { 33 | this.tile.getPatternInventory().setStackInSlot(patternIndex, ItemStack.EMPTY); 34 | this.tile.updateCraftingList(); 35 | } 36 | } 37 | 38 | public void setTile(TilePatternInterface tile) { 39 | this.tile = tile; 40 | } 41 | 42 | public void setPatternIndex(int patternIndex) { 43 | this.patternIndex = patternIndex; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/BlackListHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import com.github.vfyjxf.nee.config.IngredientBlackList; 4 | import net.minecraft.item.ItemStack; 5 | 6 | public class BlackListHelper { 7 | 8 | private BlackListHelper() { 9 | 10 | } 11 | 12 | public static boolean isBlacklistItem(ItemStack stack, String recipeType) { 13 | return IngredientBlackList.INSTANCE.getBlackList() 14 | .stream() 15 | .anyMatch(blackIngredient -> blackIngredient.matches(stack, recipeType)); 16 | } 17 | 18 | public static boolean isBlacklistItem(ItemStack stack) { 19 | return isBlacklistItem(stack, null); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/CraftingHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import appeng.client.gui.AEBaseGui; 4 | import appeng.client.gui.implementations.GuiCraftingTerm; 5 | import appeng.client.gui.implementations.GuiPatternTerm; 6 | import appeng.container.slot.AppEngSlot; 7 | import appeng.helpers.IContainerCraftingPacket; 8 | import com.github.vfyjxf.nee.utils.GuiUtils; 9 | import net.minecraft.client.Minecraft; 10 | import net.minecraft.client.gui.GuiScreen; 11 | import net.minecraft.client.gui.inventory.GuiContainer; 12 | import net.minecraft.inventory.Container; 13 | import net.minecraft.inventory.IInventory; 14 | import net.minecraft.inventory.Slot; 15 | import net.minecraft.item.ItemStack; 16 | import net.minecraftforge.items.IItemHandler; 17 | 18 | import javax.annotation.Nonnull; 19 | import javax.annotation.Nullable; 20 | import java.util.Collections; 21 | import java.util.List; 22 | import java.util.stream.Collectors; 23 | import java.util.stream.IntStream; 24 | 25 | public class CraftingHelper { 26 | 27 | private CraftingHelper() { 28 | 29 | } 30 | 31 | public static boolean isSupportedGui(GuiScreen screen) { 32 | return screen instanceof GuiCraftingTerm || 33 | screen instanceof GuiPatternTerm || 34 | GuiUtils.isGuiWirelessCrafting(screen); 35 | } 36 | 37 | public static List getCraftingSlots(AEBaseGui gui) { 38 | Container container = gui.inventorySlots; 39 | if (container instanceof IContainerCraftingPacket) { 40 | IItemHandler craftMatrix = ((IContainerCraftingPacket) container).getInventoryByName("crafting"); 41 | return container.inventorySlots.stream() 42 | .filter(slot -> slot instanceof AppEngSlot && ((AppEngSlot) slot).getItemHandler().equals(craftMatrix)) 43 | .collect(Collectors.toList()); 44 | } 45 | return Collections.emptyList(); 46 | } 47 | 48 | @Nullable 49 | public static IItemHandler getCraftMatrix(GuiContainer gui) { 50 | Container container = gui.inventorySlots; 51 | if (container instanceof IContainerCraftingPacket) { 52 | return ((IContainerCraftingPacket) container).getInventoryByName("crafting"); 53 | } 54 | return null; 55 | } 56 | 57 | public static List copyAllNonEmpty(@Nonnull IItemHandler handler) { 58 | return IntStream.range(0, handler.getSlots()) 59 | .filter(slotIndex -> !handler.getStackInSlot(slotIndex).isEmpty()) 60 | .mapToObj(slotIndex -> handler.getStackInSlot(slotIndex).copy()) 61 | .collect(Collectors.toList()); 62 | } 63 | 64 | public static List copyAllNonEmpty(@Nonnull IInventory inventory) { 65 | return IntStream.range(0, inventory.getSizeInventory()) 66 | .filter(slotIndex -> !inventory.getStackInSlot(slotIndex).isEmpty()) 67 | .mapToObj(slotIndex -> inventory.getStackInSlot(slotIndex).copy()) 68 | .collect(Collectors.toList()); 69 | } 70 | 71 | public static boolean isCraftingSlot(Slot slot) { 72 | Container container = Minecraft.getMinecraft().player.openContainer; 73 | if (container instanceof IContainerCraftingPacket && slot instanceof AppEngSlot) { 74 | IItemHandler craftMatrix = ((IContainerCraftingPacket) container).getInventoryByName("crafting"); 75 | return ((AppEngSlot) slot).getItemHandler().equals(craftMatrix); 76 | } 77 | return false; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/IngredientMerger.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import com.github.vfyjxf.nee.utils.ItemUtils; 4 | import net.minecraft.item.ItemStack; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class IngredientMerger { 10 | 11 | private IngredientMerger() { 12 | 13 | } 14 | 15 | /** 16 | * @param allStacks A List of elements that need to be merged after copying. 17 | * @return A merged list 18 | */ 19 | public static List merge(List allStacks) { 20 | List merged = new ArrayList<>(); 21 | for (ItemStack current : allStacks) { 22 | boolean mergedFlag = merged.stream().anyMatch(stack -> mergeStack(stack, current)); 23 | if (!mergedFlag) merged.add(current); 24 | } 25 | return merged; 26 | } 27 | 28 | /** 29 | * The unrestricted count form of {@link IngredientMerger#merge(List)}. 30 | * 31 | * @param allStacks A List of elements that need to be merged after copying. 32 | * @return A merged list 33 | */ 34 | public static List unlimitedMerge(List allStacks) { 35 | List merged = new ArrayList<>(); 36 | for (ItemStack current : allStacks) { 37 | boolean mergedFlag = merged.stream().anyMatch(stack -> unlimitedMergeStack(stack, current)); 38 | if (!mergedFlag) merged.add(current); 39 | } 40 | return merged; 41 | } 42 | 43 | public static boolean mergeStack(ItemStack main, ItemStack other) { 44 | if (ItemUtils.matches(main, other) && main.getCount() + other.getCount() <= main.getMaxStackSize()) { 45 | main.setCount(main.getCount() + other.getCount()); 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | public static boolean unlimitedMergeStack(ItemStack main, ItemStack other) { 52 | if (ItemUtils.matches(main, other)) { 53 | main.setCount(main.getCount() + other.getCount()); 54 | return true; 55 | } 56 | return false; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/IngredientRequester.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 4 | import com.github.vfyjxf.nee.network.packet.PacketCraftingRequest; 5 | import com.github.vfyjxf.nee.utils.IngredientStatus; 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | public class IngredientRequester { 13 | 14 | private final static Logger LOGGER = LogManager.getLogger(); 15 | private final static IngredientRequester INSTANCE = new IngredientRequester(); 16 | 17 | private boolean isWireless; 18 | private boolean nonPreview; 19 | private List requested; 20 | private int currentIndex; 21 | private boolean finished; 22 | 23 | private IngredientRequester() { 24 | 25 | } 26 | 27 | public static IngredientRequester getInstance() { 28 | return INSTANCE; 29 | } 30 | 31 | public boolean requestNext() { 32 | if (finished) return false; 33 | RecipeAnalyzer.RecipeIngredient ingredient = requested.get(currentIndex); 34 | try { 35 | NEENetworkHandler.getInstance().sendToServer(new PacketCraftingRequest(ingredient.createAeStack(), nonPreview)); 36 | currentIndex++; 37 | } catch (Exception e) { 38 | LOGGER.error("Fail to request ingredient: {} ,try to request next ingredient.", ingredient.getIdentifier().getDisplayName()); 39 | currentIndex++; 40 | finished = currentIndex >= requested.size(); 41 | return requestNext(); 42 | } 43 | finished = currentIndex >= requested.size(); 44 | return true; 45 | } 46 | 47 | public void setRequested(boolean isWireless, boolean nonPreview, List ingredients) { 48 | this.isWireless = isWireless; 49 | this.nonPreview = nonPreview; 50 | this.requested = ingredients.stream() 51 | .filter(ingredient -> ingredient.getStatus() == IngredientStatus.CRAFTABLE) 52 | .collect(Collectors.toList()); 53 | this.currentIndex = 0; 54 | this.finished = currentIndex >= requested.size(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/PlatformHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import appeng.client.gui.implementations.GuiMEMonitorable; 4 | import appeng.client.me.ItemRepo; 5 | import com.github.vfyjxf.nee.utils.Globals; 6 | import com.github.vfyjxf.nee.utils.ReflectionHelper; 7 | import com.google.common.collect.Lists; 8 | import net.minecraft.client.gui.GuiScreen; 9 | import net.minecraft.client.gui.inventory.GuiContainer; 10 | import net.minecraft.inventory.Container; 11 | import net.minecraftforge.fml.common.Loader; 12 | 13 | /** 14 | * A helper to adapt official ae2 and pae2. 15 | */ 16 | public class PlatformHelper { 17 | 18 | private PlatformHelper() { 19 | 20 | } 21 | 22 | private static boolean unofficial; 23 | public static Class containerPatternEncoderClass = null; 24 | public static Class containerPatternTermClass = null; 25 | public static Class guiWCTClass = null; 26 | 27 | public static Class guiMEMonitorable = null; 28 | public static Class containerWirelessCraftingTermClass = null; 29 | public static Class wirelessCraftingGuiClass = null; 30 | 31 | public static void init() { 32 | unofficial = Loader.instance() 33 | .getModList() 34 | .stream() 35 | .anyMatch(modContainer -> (modContainer.getModId().equals(Globals.APPENG) && modContainer.getVersion().contains("extended_life"))); 36 | containerPatternEncoderClass = ReflectionHelper.getClassForName("appeng.container.implementations.ContainerPatternEncoder"); 37 | guiWCTClass = ReflectionHelper.getClassForName("p455w0rd.wct.client.gui.GuiWCT"); 38 | containerWirelessCraftingTermClass = ReflectionHelper.getClassForName("appeng.container.implementations.ContainerWirelessCraftingTerminal"); 39 | wirelessCraftingGuiClass = ReflectionHelper.getClassForName("appeng.client.gui.implementations.GuiWirelessCraftingTerminal"); 40 | guiMEMonitorable = ReflectionHelper.getClassForName("appeng.client.gui.implementations.GuiMEMonitorable"); 41 | containerPatternTermClass = ReflectionHelper.getClassForName("appeng.container.implementations.ContainerPatternTerm"); 42 | } 43 | 44 | public static boolean issUnofficial() { 45 | return unofficial; 46 | } 47 | 48 | public static boolean isCraftingMode(Container container) { 49 | return Boolean.TRUE.equals(ReflectionHelper.compositeInvoker(Lists.newArrayList(containerPatternEncoderClass, containerPatternTermClass), container, false, "isCraftingMode")); 50 | } 51 | 52 | public static ItemRepo getRepo(GuiContainer gui) { 53 | return ReflectionHelper.possibleValueGetter(Lists.newArrayList(guiWCTClass, guiMEMonitorable), gui, "repo"); 54 | } 55 | 56 | public static ItemRepo getRepo(GuiMEMonitorable term) { 57 | return ReflectionHelper.getFieldValue(GuiMEMonitorable.class, term, "repo"); 58 | } 59 | 60 | public static boolean isWirelessContainer(Container container) { 61 | return containerWirelessCraftingTermClass != null && containerWirelessCraftingTermClass.isInstance(container); 62 | } 63 | 64 | public static boolean isWirelessGui(GuiScreen gui) { 65 | return wirelessCraftingGuiClass != null && wirelessCraftingGuiClass.isInstance(gui); 66 | } 67 | 68 | public static boolean isWctGui(GuiScreen screen) { 69 | return guiWCTClass != null && guiWCTClass.isInstance(screen); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/PreferenceHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import com.github.vfyjxf.nee.config.NEEConfig; 4 | import com.github.vfyjxf.nee.config.PreferenceList; 5 | import com.github.vfyjxf.nee.utils.PreferenceIngredient; 6 | import net.minecraft.item.ItemStack; 7 | 8 | import javax.annotation.Nonnull; 9 | import java.util.List; 10 | import java.util.Objects; 11 | 12 | /** 13 | * A list for storing player-preferred Ingredient 14 | */ 15 | public class PreferenceHelper { 16 | 17 | private PreferenceHelper() { 18 | 19 | } 20 | 21 | public static ItemStack getFromPreference(List ingredients, ItemStack origin, String recipeType) { 22 | 23 | PreferenceIngredient preference = PreferenceList.INSTANCE.getPreferenceList().stream() 24 | .filter(preferenceIngredient -> ingredients.stream() 25 | .anyMatch(itemStack -> preferenceIngredient.matches(itemStack, recipeType)) 26 | ).findAny() 27 | .orElse(null); 28 | 29 | 30 | ItemStack preferItem = preference != null ? preference.getIdentifier() : ItemStack.EMPTY; 31 | 32 | if (!preferItem.isEmpty()) { 33 | return preferItem; 34 | } 35 | 36 | return ingredients.stream() 37 | .filter(Objects::nonNull) 38 | .filter(stack -> !stack.isEmpty()) 39 | .filter(PreferenceHelper::isPreferMod) 40 | .findAny() 41 | .map(is -> { 42 | ItemStack stack = is.copy(); 43 | stack.setCount(origin.getCount()); 44 | return stack; 45 | }) 46 | .orElse(origin); 47 | } 48 | 49 | public static boolean isPreferMod(@Nonnull ItemStack stack) { 50 | return NEEConfig.getPriorityMods().contains(stack.getItem().getRegistryName().getNamespace()); 51 | } 52 | 53 | public static boolean isPreferItem(@Nonnull ItemStack stack) { 54 | return PreferenceList.INSTANCE.getPreferenceList() 55 | .stream() 56 | .anyMatch(preference -> preference.matches(stack, null)); 57 | } 58 | 59 | public static PreferenceIngredient getPreferIngredient(ItemStack stack, String recipeType) { 60 | return PreferenceList.INSTANCE.getPreferenceList() 61 | .stream() 62 | .filter(preference -> preference.matches(stack, recipeType)) 63 | .findAny() 64 | .orElse(null); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/helper/RecipeHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.helper; 2 | 3 | import com.github.vfyjxf.nee.jei.NEEJeiPlugin; 4 | import com.github.vfyjxf.nee.utils.ItemUtils; 5 | import mezz.jei.api.recipe.IRecipeCategory; 6 | import net.minecraft.item.ItemStack; 7 | 8 | public class RecipeHelper { 9 | 10 | private RecipeHelper() { 11 | 12 | } 13 | 14 | public static boolean checkCatalysts(ItemStack stack, IRecipeCategory category) { 15 | if (stack == null || stack.isEmpty() || category == null) 16 | return false; 17 | 18 | return NEEJeiPlugin.recipeRegistry.getRecipeCatalysts(category).stream() 19 | .filter(ItemStack.class::isInstance) 20 | .map(ItemStack.class::cast) 21 | .anyMatch(catalyst -> ItemUtils.matches(catalyst, stack)); 22 | } 23 | 24 | public static boolean checkCatalysts(ItemStack stack, String categoryUid) { 25 | if (stack == null || stack.isEmpty() || categoryUid == null || categoryUid.isEmpty()) 26 | return false; 27 | IRecipeCategory category = NEEJeiPlugin.recipeRegistry.getRecipeCategory(categoryUid); 28 | return checkCatalysts(stack, category); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/GregTechToolHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | public class GregTechToolHelper implements IToolHelper{ 6 | @Override 7 | public boolean isSupport(Class toolClass) { 8 | return false; 9 | } 10 | 11 | @Override 12 | public ItemStack getToolStack(ItemStack stack) { 13 | return stack; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/IPatternProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import appeng.api.networking.IGridHost; 4 | import appeng.helpers.DualityInterface; 5 | import com.github.vfyjxf.nee.utils.ReflectionHelper; 6 | import net.minecraft.item.ItemStack; 7 | import net.minecraftforge.items.IItemHandler; 8 | 9 | import javax.annotation.Nonnull; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * All block like ME interface. 16 | */ 17 | public interface IPatternProvider { 18 | 19 | List> PROVIDERS = new ArrayList<>(); 20 | 21 | @Nonnull 22 | Class getHostClass(); 23 | 24 | IItemHandler getPatterns(T tileEntity); 25 | 26 | default ItemStack getTarget(T tileEntity){ 27 | return ItemStack.EMPTY; 28 | } 29 | 30 | String getName(T tileEntity); 31 | 32 | String uid(T tileEntity); 33 | 34 | static boolean sameGird(DualityInterface dual1, DualityInterface dual2){ 35 | try { 36 | return (boolean) ReflectionHelper.getMethod(DualityInterface.class, "sameGrid", DualityInterface.class).invoke(dual1, dual2); 37 | } catch (IllegalAccessException | InvocationTargetException e) { 38 | return false; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/IToolHelper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | public interface IToolHelper { 6 | 7 | boolean isSupport(Class toolClass); 8 | 9 | /** 10 | * @return A generic tool used in the pattern for recipes based on the OreDictionary. 11 | */ 12 | default ItemStack getToolStack(ItemStack stack) { 13 | return stack; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/InterfacePatternProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import appeng.api.config.Settings; 4 | import appeng.api.config.YesNo; 5 | import appeng.api.implementations.tiles.ICraftingMachine; 6 | import appeng.api.networking.IGridHost; 7 | import appeng.api.networking.IGridNode; 8 | import appeng.api.util.AEPartLocation; 9 | import appeng.helpers.DualityInterface; 10 | import appeng.helpers.ICustomNameObject; 11 | import appeng.helpers.IInterfaceHost; 12 | import appeng.tile.grid.AENetworkInvTile; 13 | import appeng.tile.misc.TileInterface; 14 | import appeng.util.InventoryAdaptor; 15 | import net.minecraft.block.Block; 16 | import net.minecraft.block.state.IBlockState; 17 | import net.minecraft.init.Items; 18 | import net.minecraft.item.Item; 19 | import net.minecraft.item.ItemStack; 20 | import net.minecraft.tileentity.TileEntity; 21 | import net.minecraft.util.EnumFacing; 22 | import net.minecraft.util.math.BlockPos; 23 | import net.minecraft.util.math.RayTraceResult; 24 | import net.minecraft.util.math.Vec3d; 25 | import net.minecraft.world.World; 26 | import net.minecraftforge.items.IItemHandler; 27 | 28 | import javax.annotation.Nonnull; 29 | import java.util.EnumSet; 30 | 31 | public class InterfacePatternProvider implements IPatternProvider { 32 | 33 | @Nonnull 34 | @Override 35 | public Class getHostClass() { 36 | return TileInterface.class; 37 | } 38 | 39 | @Override 40 | public IItemHandler getPatterns(TileInterface tileEntity) { 41 | DualityInterface dual = tileEntity.getInterfaceDuality(); 42 | IGridNode node = tileEntity.getGridNode(AEPartLocation.INTERNAL); 43 | if (node != null && node.isActive() && dual.getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.YES) { 44 | return null; 45 | } 46 | return dual.getPatterns(); 47 | } 48 | 49 | @Override 50 | public ItemStack getTarget(TileInterface tileEntity) { 51 | DualityInterface dual = tileEntity.getInterfaceDuality(); 52 | IInterfaceHost iHost = (IInterfaceHost) dual.getHost(); 53 | { 54 | final TileEntity hostTile = iHost.getTile(); 55 | final World hostWorld = hostTile.getWorld(); 56 | 57 | if (((ICustomNameObject) iHost).hasCustomInventoryName()) { 58 | IBlockState blockState = hostWorld.getBlockState(hostTile.getPos()); 59 | return new ItemStack(blockState.getBlock(), 1, blockState.getBlock().getMetaFromState(blockState)); 60 | } 61 | 62 | final EnumSet possibleDirections = iHost.getTargets(); 63 | for (final EnumFacing direction : possibleDirections) { 64 | final BlockPos target = hostTile.getPos().offset(direction); 65 | final TileEntity directedTile = hostWorld.getTileEntity(target); 66 | 67 | if (directedTile == null) { 68 | continue; 69 | } 70 | 71 | if (directedTile instanceof IInterfaceHost && directedTile instanceof AENetworkInvTile) { 72 | if (IPatternProvider.sameGird(dual, ((IInterfaceHost) directedTile).getInterfaceDuality())) { 73 | continue; 74 | } 75 | } 76 | 77 | final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor(directedTile, direction.getOpposite()); 78 | if (directedTile instanceof ICraftingMachine || adaptor != null) { 79 | if (adaptor != null && !adaptor.hasSlots()) { 80 | continue; 81 | } 82 | 83 | final IBlockState directedBlockState = hostWorld.getBlockState(target); 84 | final Block directedBlock = directedBlockState.getBlock(); 85 | ItemStack what = new ItemStack(directedBlock, 1, directedBlock.getMetaFromState(directedBlockState)); 86 | Vec3d from = new Vec3d(hostTile.getPos().getX() + 0.5, hostTile.getPos().getY() + 0.5, hostTile.getPos().getZ() + 0.5); 87 | from = from.add(direction.getXOffset() * 0.501, direction.getYOffset() * 0.501, direction.getZOffset() * 0.501); 88 | final Vec3d to = from.add(direction.getXOffset(), direction.getYOffset(), direction.getZOffset()); 89 | final RayTraceResult mop = hostWorld.rayTraceBlocks(from, to, true); 90 | if (mop != null) { 91 | if (mop.getBlockPos().equals(directedTile.getPos())) { 92 | final ItemStack g = directedBlock.getPickBlock(directedBlockState, mop, hostWorld, directedTile.getPos(), null); 93 | if (!g.isEmpty()) { 94 | what = g; 95 | } 96 | } 97 | } 98 | 99 | if (what.getItem() != Items.AIR) { 100 | return what.copy(); 101 | } 102 | 103 | final Item item = Item.getItemFromBlock(directedBlock); 104 | if (item == Items.AIR) { 105 | return new ItemStack(directedBlock, 1, directedBlock.getMetaFromState(directedBlockState)); 106 | } 107 | } 108 | } 109 | 110 | return ItemStack.EMPTY; 111 | } 112 | } 113 | 114 | @Override 115 | public String getName(TileInterface tileEntity) { 116 | return tileEntity.getInterfaceDuality().getTermName(); 117 | } 118 | 119 | @Override 120 | public String uid(TileInterface tileEntity) { 121 | return Long.toString(tileEntity.getInterfaceDuality().getSortValue()); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/PartInterfacePatternProvider.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import appeng.api.config.Settings; 4 | import appeng.api.config.YesNo; 5 | import appeng.api.implementations.tiles.ICraftingMachine; 6 | import appeng.api.networking.IGridHost; 7 | import appeng.api.networking.IGridNode; 8 | import appeng.helpers.DualityInterface; 9 | import appeng.helpers.ICustomNameObject; 10 | import appeng.helpers.IInterfaceHost; 11 | import appeng.parts.misc.PartInterface; 12 | import appeng.tile.grid.AENetworkInvTile; 13 | import appeng.util.InventoryAdaptor; 14 | import net.minecraft.block.Block; 15 | import net.minecraft.block.state.IBlockState; 16 | import net.minecraft.init.Items; 17 | import net.minecraft.item.Item; 18 | import net.minecraft.item.ItemStack; 19 | import net.minecraft.tileentity.TileEntity; 20 | import net.minecraft.util.EnumFacing; 21 | import net.minecraft.util.math.BlockPos; 22 | import net.minecraft.util.math.RayTraceResult; 23 | import net.minecraft.util.math.Vec3d; 24 | import net.minecraft.world.World; 25 | import net.minecraftforge.items.IItemHandler; 26 | 27 | import javax.annotation.Nonnull; 28 | import java.util.EnumSet; 29 | 30 | public class PartInterfacePatternProvider implements IPatternProvider { 31 | 32 | @Nonnull 33 | @Override 34 | public Class getHostClass() { 35 | return PartInterface.class; 36 | } 37 | 38 | @Override 39 | public IItemHandler getPatterns(PartInterface tileEntity) { 40 | DualityInterface dual = tileEntity.getInterfaceDuality(); 41 | IGridNode node = tileEntity.getGridNode(tileEntity.getSide()); 42 | if (node != null && node.isActive() && dual.getConfigManager().getSetting(Settings.INTERFACE_TERMINAL) == YesNo.YES) { 43 | return null; 44 | } 45 | return dual.getPatterns(); 46 | } 47 | 48 | @Override 49 | public ItemStack getTarget(PartInterface tileEntity) { 50 | DualityInterface dual = tileEntity.getInterfaceDuality(); 51 | IInterfaceHost iHost = (IInterfaceHost) dual.getHost(); 52 | { 53 | final TileEntity hostTile = iHost.getTile(); 54 | final World hostWorld = hostTile.getWorld(); 55 | 56 | if (((ICustomNameObject) iHost).hasCustomInventoryName()) { 57 | IBlockState blockState = hostWorld.getBlockState(hostTile.getPos()); 58 | return new ItemStack(blockState.getBlock(), 1, blockState.getBlock().getMetaFromState(blockState)); 59 | } 60 | 61 | final EnumSet possibleDirections = iHost.getTargets(); 62 | for (final EnumFacing direction : possibleDirections) { 63 | final BlockPos target = hostTile.getPos().offset(direction); 64 | final TileEntity directedTile = hostWorld.getTileEntity(target); 65 | 66 | if (directedTile == null) { 67 | continue; 68 | } 69 | 70 | if (directedTile instanceof IInterfaceHost && directedTile instanceof AENetworkInvTile) { 71 | if (IPatternProvider.sameGird(dual, ((IInterfaceHost) directedTile).getInterfaceDuality())) { 72 | continue; 73 | } 74 | } 75 | 76 | final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor(directedTile, direction.getOpposite()); 77 | if (directedTile instanceof ICraftingMachine || adaptor != null) { 78 | if (adaptor != null && !adaptor.hasSlots()) { 79 | continue; 80 | } 81 | 82 | final IBlockState directedBlockState = hostWorld.getBlockState(target); 83 | final Block directedBlock = directedBlockState.getBlock(); 84 | ItemStack what = new ItemStack(directedBlock, 1, directedBlock.getMetaFromState(directedBlockState)); 85 | Vec3d from = new Vec3d(hostTile.getPos().getX() + 0.5, hostTile.getPos().getY() + 0.5, hostTile.getPos().getZ() + 0.5); 86 | from = from.add(direction.getXOffset() * 0.501, direction.getYOffset() * 0.501, direction.getZOffset() * 0.501); 87 | final Vec3d to = from.add(direction.getXOffset(), direction.getYOffset(), direction.getZOffset()); 88 | final RayTraceResult mop = hostWorld.rayTraceBlocks(from, to, true); 89 | if (mop != null) { 90 | if (mop.getBlockPos().equals(directedTile.getPos())) { 91 | final ItemStack g = directedBlock.getPickBlock(directedBlockState, mop, hostWorld, directedTile.getPos(), null); 92 | if (!g.isEmpty()) { 93 | what = g; 94 | } 95 | } 96 | } 97 | 98 | if (what.getItem() != Items.AIR) { 99 | return what.copy(); 100 | } 101 | 102 | final Item item = Item.getItemFromBlock(directedBlock); 103 | if (item == Items.AIR) { 104 | return new ItemStack(directedBlock, 1, directedBlock.getMetaFromState(directedBlockState)); 105 | } 106 | } 107 | } 108 | 109 | return ItemStack.EMPTY; 110 | } 111 | } 112 | 113 | @Override 114 | public String getName(PartInterface tileEntity) { 115 | return tileEntity.getInterfaceDuality().getTermName(); 116 | } 117 | 118 | @Override 119 | public String uid(PartInterface tileEntity) { 120 | return Long.toString(tileEntity.getInterfaceDuality().getSortValue()); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/RecipeToolManager.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration; 2 | 3 | import net.minecraft.item.Item; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class RecipeToolManager { 9 | 10 | public static final RecipeToolManager INSTANCE = new RecipeToolManager(); 11 | 12 | private final List toolHelpers = new ArrayList<>(); 13 | 14 | private RecipeToolManager() { 15 | 16 | } 17 | 18 | public IToolHelper getToolHelper(Item tool) { 19 | return toolHelpers.stream() 20 | .filter(helper -> helper.isSupport(tool.getClass())) 21 | .findAny() 22 | .orElse(null); 23 | } 24 | 25 | public void registerToolHelper(IToolHelper toolHelper) { 26 | if (!toolHelpers.contains(toolHelper)) { 27 | toolHelpers.add(toolHelper); 28 | } 29 | } 30 | 31 | public List getToolHelpers() { 32 | return toolHelpers; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/integration/unofficial/IRecipeTransformHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.integration.unofficial; 2 | 3 | public interface IRecipeTransformHandler { 4 | 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/inventory/InventoryPatternCrafter.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.inventory; 2 | 3 | import net.minecraft.item.ItemStack; 4 | import net.minecraftforge.items.ItemStackHandler; 5 | 6 | import javax.annotation.Nonnull; 7 | import java.util.Collections; 8 | import java.util.Iterator; 9 | 10 | public class InventoryPatternCrafter extends ItemStackHandler implements Iterable { 11 | 12 | 13 | @Override 14 | public void setStackInSlot(int slot, @Nonnull ItemStack stack) { 15 | super.setStackInSlot(slot, stack); 16 | } 17 | 18 | @Override 19 | public int getSlotLimit(int slot) { 20 | return 1; 21 | } 22 | 23 | @Override 24 | public Iterator iterator() { 25 | return Collections.unmodifiableList(super.stacks).iterator(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/jei/CraftingInfoError.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.jei; 2 | 3 | import appeng.api.storage.data.IAEItemStack; 4 | import appeng.container.AEBaseContainer; 5 | import appeng.core.sync.network.NetworkHandler; 6 | import appeng.core.sync.packets.PacketInventoryAction; 7 | import appeng.helpers.InventoryAction; 8 | import appeng.util.item.AEItemStack; 9 | import com.github.vfyjxf.nee.config.NEEConfig; 10 | import com.github.vfyjxf.nee.helper.RecipeAnalyzer; 11 | import com.github.vfyjxf.nee.utils.IngredientStatus; 12 | import com.google.common.base.Stopwatch; 13 | import mezz.jei.api.gui.IRecipeLayout; 14 | import mezz.jei.api.gui.ITooltipCallback; 15 | import mezz.jei.api.recipe.transfer.IRecipeTransferError; 16 | import mezz.jei.gui.TooltipRenderer; 17 | import net.minecraft.client.Minecraft; 18 | import net.minecraft.client.resources.I18n; 19 | import net.minecraft.item.ItemStack; 20 | import net.minecraft.util.text.TextFormatting; 21 | import org.lwjgl.input.Keyboard; 22 | import org.lwjgl.input.Mouse; 23 | 24 | import javax.annotation.Nonnull; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.concurrent.TimeUnit; 28 | 29 | import static com.github.vfyjxf.nee.config.KeyBindings.AUTO_CRAFT_WITH_PREVIEW; 30 | import static com.github.vfyjxf.nee.jei.CraftingTransferHandler.isIsPatternInterfaceExists; 31 | import static mezz.jei.api.recipe.transfer.IRecipeTransferError.Type.USER_FACING; 32 | 33 | public class CraftingInfoError implements IRecipeTransferError { 34 | 35 | private final boolean crafting; 36 | private final RecipeAnalyzer analyzer; 37 | 38 | public CraftingInfoError(RecipeAnalyzer analyzer, IRecipeLayout recipeLayout, boolean isCrafting) { 39 | this.analyzer = analyzer; 40 | this.crafting = isCrafting; 41 | recipeLayout.getItemStacks().addTooltipCallback(new CraftingInfoCallback(analyzer)); 42 | //TODO:AE2FC supports 43 | } 44 | 45 | /** 46 | * Since the 1.12.2 jei does not have a third type, we use asm to set the button enable. 47 | */ 48 | @Nonnull 49 | @Override 50 | public Type getType() { 51 | return USER_FACING; 52 | } 53 | 54 | @Override 55 | public void showError(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @Nonnull IRecipeLayout recipeLayout, int recipeX, int recipeY) { 56 | analyzer.update(); 57 | List ingredients = analyzer.analyzeRecipe(recipeLayout); 58 | for (RecipeAnalyzer.RecipeIngredient ingredient : ingredients) { 59 | if (ingredient.getStatus() == IngredientStatus.CRAFTABLE) { 60 | ingredient.drawHighlight(minecraft, NEEConfig.getCraftableHighlightColor(), recipeX, recipeY); 61 | } else if (ingredient.getStatus() == IngredientStatus.MISSING) { 62 | ingredient.drawHighlight(minecraft, NEEConfig.getMissingHighlightColor(), recipeX, recipeY); 63 | } 64 | } 65 | 66 | boolean autoCraftingAvailable = false; 67 | boolean patternExists = false; 68 | boolean missingItems = false; 69 | List tooltips = new ArrayList<>(); 70 | if (crafting) { 71 | if (!isIsPatternInterfaceExists()) { 72 | autoCraftingAvailable = ingredients.stream().anyMatch(ingredient -> ingredient.getStatus() == IngredientStatus.CRAFTABLE); 73 | missingItems = ingredients.stream().anyMatch(ingredient -> ingredient.getStatus() == IngredientStatus.MISSING); 74 | } else { 75 | //TODO:Pattern Interface support 76 | } 77 | } else { 78 | patternExists = ingredients.stream().anyMatch(ingredient -> ingredient.getStatus() == IngredientStatus.CRAFTABLE); 79 | } 80 | if (autoCraftingAvailable) { 81 | tooltips.add(String.format("%s" + TextFormatting.GRAY + " + " + 82 | TextFormatting.BLUE + I18n.format("jei.tooltip.nee.helper.crafting.text1"), 83 | TextFormatting.YELLOW + Keyboard.getKeyName(AUTO_CRAFT_WITH_PREVIEW.getKeyCode()))); 84 | } 85 | if (patternExists) { 86 | tooltips.add(TextFormatting.BLUE + I18n.format("jei.tooltip.nee.helper.pattern")); 87 | } 88 | if (missingItems) { 89 | tooltips.add(TextFormatting.RED + I18n.format("jei.tooltip.error.recipe.transfer.missing")); 90 | } 91 | if (isIsPatternInterfaceExists()) { 92 | tooltips.add(String.format("%s" + TextFormatting.GRAY + " + " + 93 | TextFormatting.BLUE + I18n.format("jei.tooltip.nee.helper.crafting.text2"), 94 | TextFormatting.YELLOW + Keyboard.getKeyName(AUTO_CRAFT_WITH_PREVIEW.getKeyCode()))); 95 | } 96 | 97 | TooltipRenderer.drawHoveringText(minecraft, tooltips, mouseX, mouseY); 98 | } 99 | 100 | /** 101 | * Feature from pae2 102 | */ 103 | private static class CraftingInfoCallback implements ITooltipCallback { 104 | 105 | private static final List SUCCESS = new ArrayList<>(); 106 | private final Stopwatch lastClicked = Stopwatch.createStarted(); 107 | private final RecipeAnalyzer analyzer; 108 | private List craftables; 109 | 110 | private CraftingInfoCallback(RecipeAnalyzer analyzer) { 111 | this.analyzer = analyzer; 112 | this.craftables = analyzer.getCraftables(); 113 | analyzer.addUpdateListener(pair -> { 114 | craftables = analyzer.getCraftables(); 115 | SUCCESS.clear(); 116 | }); 117 | } 118 | 119 | @Override 120 | public void onTooltip(int slotIndex, boolean input, @Nonnull ItemStack ingredient, @Nonnull List tooltip) { 121 | analyzer.update(); 122 | if (!input | ingredient.isEmpty() | craftables.isEmpty()) return; 123 | boolean isCache = SUCCESS.stream().anyMatch(ingredient::isItemEqual); 124 | boolean anyMatch = isCache || craftables.stream().anyMatch(craftable -> { 125 | boolean match = craftable.isSameType(ingredient); 126 | if (match) SUCCESS.add(ingredient); 127 | return match; 128 | }); 129 | if (anyMatch) { 130 | tooltip.add(TextFormatting.BLUE + String.format("[%s]", I18n.format("jei.tooltip.nee.helper.craftable"))); 131 | if (Mouse.isButtonDown(2) && this.lastClicked.elapsed(TimeUnit.MILLISECONDS) > 200) { 132 | this.lastClicked.reset().start(); 133 | IAEItemStack target = AEItemStack.fromItemStack(ingredient); 134 | if (target != null && analyzer.getTerm().inventorySlots instanceof AEBaseContainer) { 135 | AEBaseContainer container = (AEBaseContainer) analyzer.getTerm().inventorySlots; 136 | container.setTargetStack(target); 137 | NetworkHandler.instance().sendToServer( 138 | new PacketInventoryAction(InventoryAction.AUTO_CRAFT, container.getInventory().size(), 0) 139 | ); 140 | } 141 | } 142 | } 143 | } 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/jei/NEEGhostIngredientHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.jei; 2 | 3 | import appeng.client.gui.AEBaseGui; 4 | import appeng.client.gui.implementations.GuiPatternTerm; 5 | import appeng.client.gui.widgets.GuiCustomSlot; 6 | import appeng.container.slot.AppEngSlot; 7 | import appeng.container.slot.SlotFake; 8 | import appeng.fluids.client.gui.widgets.GuiFluidSlot; 9 | import appeng.fluids.util.AEFluidStack; 10 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 11 | import com.github.vfyjxf.nee.network.packet.PacketSlotStackSwitch; 12 | import mezz.jei.api.gui.IGhostIngredientHandler; 13 | import net.minecraft.client.gui.inventory.GuiContainer; 14 | import net.minecraft.inventory.Slot; 15 | import net.minecraft.item.ItemStack; 16 | import net.minecraftforge.fluids.FluidStack; 17 | import net.minecraftforge.fml.common.ObfuscationReflectionHelper; 18 | 19 | import javax.annotation.Nonnull; 20 | import java.awt.*; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | public class NEEGhostIngredientHandler implements IGhostIngredientHandler { 25 | 26 | @Nonnull 27 | @Override 28 | public List> getTargets(@Nonnull AEBaseGui gui, @Nonnull I ingredient, boolean doStart) { 29 | List> targets = new ArrayList<>(); 30 | if (ingredient instanceof ItemStack) { 31 | if (gui instanceof GuiPatternTerm) { 32 | if (GuiContainer.isShiftKeyDown()) { 33 | addItemStackTargets(gui, targets); 34 | } 35 | } else { 36 | addItemStackTargets(gui, targets); 37 | } 38 | } 39 | if (ingredient instanceof FluidStack) { 40 | addFluidStackTargets(gui, targets); 41 | } 42 | return targets; 43 | } 44 | 45 | @Override 46 | public void onComplete() { 47 | 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | private static void addItemStackTargets(AEBaseGui gui, List> targets) { 52 | for (Slot slot : gui.inventorySlots.inventorySlots) { 53 | if (slot instanceof AppEngSlot) { 54 | AppEngSlot aeSlot = (AppEngSlot) slot; 55 | if (aeSlot.isSlotEnabled()) { 56 | if (aeSlot instanceof SlotFake) { 57 | targets.add((Target) new ItemSlotTarget(gui, aeSlot)); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | 64 | @SuppressWarnings("unchecked") 65 | private static void addFluidStackTargets(AEBaseGui gui, List> targets) { 66 | for (GuiCustomSlot slot : getGuiSlots(gui)) { 67 | if (slot.isSlotEnabled() && slot instanceof GuiFluidSlot) { 68 | targets.add((Target) new FluidSlotTarget(gui, (GuiFluidSlot) slot)); 69 | } 70 | } 71 | } 72 | 73 | private static class ItemSlotTarget implements Target { 74 | private final AppEngSlot slot; 75 | private final Rectangle rectangle; 76 | 77 | public ItemSlotTarget(AEBaseGui gui, AppEngSlot slot) { 78 | this.slot = slot; 79 | this.rectangle = new Rectangle(gui.getGuiLeft() + slot.xPos, gui.getGuiTop() + slot.yPos, 16, 16); 80 | } 81 | 82 | @Nonnull 83 | @Override 84 | public Rectangle getArea() { 85 | return this.rectangle; 86 | } 87 | 88 | @Override 89 | public void accept(@Nonnull ItemStack ingredient) { 90 | List slots = new ArrayList<>(); 91 | slots.add(this.slot.slotNumber); 92 | NEENetworkHandler.getInstance().sendToServer(new PacketSlotStackSwitch(ingredient, slots)); 93 | } 94 | } 95 | 96 | private static class FluidSlotTarget implements Target { 97 | 98 | private final GuiFluidSlot slot; 99 | private final Rectangle rectangle; 100 | 101 | private FluidSlotTarget(AEBaseGui gui, GuiFluidSlot slot) { 102 | this.slot = slot; 103 | this.rectangle = new Rectangle(slot.xPos() + gui.getGuiLeft(), slot.yPos() + gui.getGuiTop(), slot.getWidth(), slot.getHeight()); 104 | } 105 | 106 | @Nonnull 107 | @Override 108 | public Rectangle getArea() { 109 | return this.rectangle; 110 | } 111 | 112 | @Override 113 | public void accept(@Nonnull FluidStack ingredient) { 114 | slot.setFluidStack(AEFluidStack.fromFluidStack(ingredient)); 115 | } 116 | 117 | } 118 | 119 | private static List getGuiSlots(AEBaseGui gui) { 120 | return new ArrayList<>(ObfuscationReflectionHelper.getPrivateValue(AEBaseGui.class, gui, "guiSlots")); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/NEENetworkHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network; 2 | 3 | import com.github.vfyjxf.nee.network.packet.*; 4 | import com.github.vfyjxf.nee.utils.Globals; 5 | import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; 6 | import net.minecraftforge.fml.relauncher.Side; 7 | 8 | public class NEENetworkHandler { 9 | 10 | private static final SimpleNetworkWrapper INSTANCE = new SimpleNetworkWrapper(Globals.MOD_ID); 11 | private static int packId = 0; 12 | 13 | public static SimpleNetworkWrapper getInstance() { 14 | return INSTANCE; 15 | } 16 | 17 | private static int nextId() { 18 | return packId++; 19 | } 20 | 21 | public static void init() { 22 | INSTANCE.registerMessage(PacketRecipeTransfer.Handler.class, PacketRecipeTransfer.class, nextId(), Side.SERVER); 23 | INSTANCE.registerMessage(PacketStackSizeChange.Handler.class, PacketStackSizeChange.class, nextId(), Side.SERVER); 24 | INSTANCE.registerMessage(PacketSlotStackSwitch.Handler.class, PacketSlotStackSwitch.class, nextId(), Side.SERVER); 25 | INSTANCE.registerMessage(PacketCraftingRequest.Handler.class, PacketCraftingRequest.class, nextId(), Side.SERVER); 26 | INSTANCE.registerMessage(PacketOpenCraftAmount.Handler.class, PacketOpenCraftAmount.class, nextId(), Side.SERVER); 27 | INSTANCE.registerMessage(PacketValueConfigServer.Handler.class, PacketValueConfigServer.class, nextId(), Side.SERVER); 28 | INSTANCE.registerMessage(PacketValueConfigClient.Handler.class, PacketValueConfigClient.class, nextId(), Side.CLIENT); 29 | INSTANCE.registerMessage(PacketSetRecipe.Handler.class, PacketSetRecipe.class, nextId(), Side.SERVER); 30 | INSTANCE.registerMessage(PacketSyncInterfaceDataServer.Handler.class, PacketSyncInterfaceDataServer.class, nextId(), Side.SERVER); 31 | INSTANCE.registerMessage(PacketSyncInterfaceDataClient.Handler.class, PacketSyncInterfaceDataClient.class, nextId(), Side.CLIENT); 32 | INSTANCE.registerMessage(PacketPlayerAction.Handler.class, PacketPlayerAction.class, nextId(), Side.SERVER); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/PlayerAction.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network; 2 | 3 | public enum PlayerAction { 4 | PICK, PUT, DROP 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/SyncAction.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network; 2 | 3 | public enum SyncAction { 4 | SYNC_INTERFACE_DATA 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketOpenCraftAmount.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.container.ContainerOpenContext; 4 | import appeng.container.implementations.ContainerCraftingTerm; 5 | import com.github.vfyjxf.nee.container.ContainerCraftingAmount; 6 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 7 | import com.github.vfyjxf.nee.utils.GuiUtils; 8 | import io.netty.buffer.ByteBuf; 9 | import net.minecraft.entity.player.EntityPlayerMP; 10 | import net.minecraft.inventory.Container; 11 | import net.minecraft.item.ItemStack; 12 | import net.minecraft.nbt.NBTTagCompound; 13 | import net.minecraft.tileentity.TileEntity; 14 | import net.minecraftforge.fml.common.network.ByteBufUtils; 15 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 16 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 17 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 18 | 19 | import static com.github.vfyjxf.nee.network.NEEGuiHandler.CRAFTING_AMOUNT_ID; 20 | import static com.github.vfyjxf.nee.network.NEEGuiHandler.WIRELESS_CRAFTING_AMOUNT_ID; 21 | import static com.github.vfyjxf.nee.utils.Globals.OUTPUT_KEY_HEAD; 22 | 23 | public class PacketOpenCraftAmount implements IMessage { 24 | 25 | private NBTTagCompound recipe; 26 | private boolean isWirelessTerm; 27 | private boolean isBauble; 28 | private int wctSlot = -1; 29 | 30 | public PacketOpenCraftAmount() { 31 | 32 | } 33 | 34 | public PacketOpenCraftAmount(NBTTagCompound recipe) { 35 | this.recipe = recipe; 36 | } 37 | 38 | public PacketOpenCraftAmount(NBTTagCompound recipe, boolean isBauble, int wctSlot) { 39 | this.recipe = recipe; 40 | this.isBauble = isBauble; 41 | this.wctSlot = wctSlot; 42 | } 43 | 44 | @Override 45 | public void fromBytes(ByteBuf buf) { 46 | this.recipe = ByteBufUtils.readTag(buf); 47 | this.isWirelessTerm = buf.readBoolean(); 48 | if (isWirelessTerm) { 49 | this.isBauble = buf.readBoolean(); 50 | this.wctSlot = buf.readInt(); 51 | } 52 | } 53 | 54 | @Override 55 | public void toBytes(ByteBuf buf) { 56 | ByteBufUtils.writeTag(buf, this.recipe); 57 | if (this.wctSlot >= 0) { 58 | buf.writeBoolean(true); 59 | buf.writeBoolean(this.isBauble); 60 | buf.writeInt(this.wctSlot); 61 | } else { 62 | buf.writeBoolean(false); 63 | } 64 | } 65 | 66 | public static class Handler implements IMessageHandler { 67 | 68 | @Override 69 | public IMessage onMessage(PacketOpenCraftAmount message, MessageContext ctx) { 70 | EntityPlayerMP player = ctx.getServerHandler().player; 71 | Container container = player.openContainer; 72 | player.getServerWorld().addScheduledTask(() -> { 73 | if (container instanceof ContainerCraftingTerm) { 74 | final ContainerOpenContext context = ((ContainerCraftingTerm) container).getOpenContext(); 75 | if (context != null) { 76 | final TileEntity tile = context.getTile(); 77 | 78 | NEEGuiHandler.openGui(player, CRAFTING_AMOUNT_ID, tile, context.getSide()); 79 | 80 | if (player.openContainer instanceof ContainerCraftingAmount) { 81 | ContainerCraftingAmount cca = (ContainerCraftingAmount) player.openContainer; 82 | if (message.recipe != null && !message.recipe.isEmpty()) { 83 | NBTTagCompound resultTag = message.recipe.getCompoundTag(OUTPUT_KEY_HEAD); 84 | ItemStack result = resultTag.isEmpty() ? ItemStack.EMPTY : new ItemStack(resultTag); 85 | cca.setResultStack(result); 86 | cca.getResultSlot().putStack(result); 87 | cca.setRecipe(message.recipe); 88 | } 89 | cca.detectAndSendChanges(); 90 | } 91 | 92 | } 93 | } else if (GuiUtils.isWirelessCraftingTermContainer(container)) { 94 | NEEGuiHandler.openGui(player, WIRELESS_CRAFTING_AMOUNT_ID, player.world); 95 | 96 | if (player.openContainer instanceof ContainerCraftingAmount) { 97 | ContainerCraftingAmount cca = (ContainerCraftingAmount) player.openContainer; 98 | if (message.recipe != null) { 99 | NBTTagCompound resultTag = message.recipe.getCompoundTag(OUTPUT_KEY_HEAD); 100 | ItemStack result = resultTag.isEmpty() ? ItemStack.EMPTY : new ItemStack(resultTag); 101 | cca.setResultStack(result); 102 | cca.getResultSlot().putStack(result); 103 | cca.setRecipe(message.recipe); 104 | } 105 | if (message.isWirelessTerm) { 106 | cca.setBauble(message.isBauble); 107 | cca.setWctSlot(message.wctSlot); 108 | } 109 | cca.detectAndSendChanges(); 110 | } 111 | } 112 | }); 113 | return null; 114 | } 115 | 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketPlayerAction.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import com.github.vfyjxf.nee.network.PlayerAction; 4 | import com.github.vfyjxf.nee.utils.PatternContainerControl; 5 | import io.netty.buffer.ByteBuf; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.nbt.NBTTagCompound; 9 | import net.minecraftforge.fml.common.network.ByteBufUtils; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 11 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 12 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 13 | 14 | public class PacketPlayerAction implements IMessage { 15 | 16 | private int action; 17 | private NBTTagCompound data; 18 | 19 | public PacketPlayerAction() { 20 | 21 | } 22 | 23 | public PacketPlayerAction(PlayerAction action, NBTTagCompound data) { 24 | this.action = action.ordinal(); 25 | this.data = data; 26 | } 27 | 28 | @Override 29 | public void fromBytes(ByteBuf buf) { 30 | this.action = buf.readInt(); 31 | this.data = ByteBufUtils.readTag(buf); 32 | } 33 | 34 | @Override 35 | public void toBytes(ByteBuf buf) { 36 | buf.writeInt(this.action); 37 | ByteBufUtils.writeTag(buf, this.data); 38 | } 39 | 40 | 41 | public static class Handler implements IMessageHandler { 42 | @Override 43 | public IMessage onMessage(PacketPlayerAction message, MessageContext ctx) { 44 | EntityPlayerMP player = ctx.getServerHandler().player; 45 | player.getServerWorld().addScheduledTask(() -> { 46 | PlayerAction action = PlayerAction.values()[(message.action)]; 47 | switch (action) { 48 | case PICK: 49 | pick(player, message.data); 50 | break; 51 | case PUT: 52 | put(player, message.data); 53 | break; 54 | case DROP: 55 | drop(player, message.data); 56 | break; 57 | default: 58 | break; 59 | } 60 | }); 61 | return null; 62 | } 63 | 64 | private static void pick(EntityPlayerMP player, NBTTagCompound data) { 65 | int slot = data.getInteger("slot"); 66 | String uid = data.getString("uid"); 67 | ItemStack extract = PatternContainerControl.extractPattern(uid, slot); 68 | if (!extract.isEmpty()) { 69 | player.inventory.setItemStack(extract); 70 | player.openContainer.detectAndSendChanges(); 71 | } 72 | } 73 | 74 | private static void put(EntityPlayerMP player, NBTTagCompound data) { 75 | int slot = data.getInteger("slot"); 76 | String uid = data.getString("uid"); 77 | ItemStack stack = player.inventory.getItemStack(); 78 | if (!stack.isEmpty()) { 79 | ItemStack left = PatternContainerControl.insertPattern(uid, slot, stack); 80 | if (left != null) { 81 | player.inventory.setItemStack(left); 82 | player.openContainer.detectAndSendChanges(); 83 | } 84 | } 85 | } 86 | 87 | private static void drop(EntityPlayerMP player, NBTTagCompound data) { 88 | int slot = data.getInteger("slot"); 89 | String uid = data.getString("uid"); 90 | ItemStack extract = PatternContainerControl.extractPattern(uid, slot); 91 | if (!extract.isEmpty()) { 92 | player.dropItem(extract, false); 93 | } 94 | } 95 | 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketSetRecipe.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.api.AEApi; 4 | import appeng.api.networking.IGrid; 5 | import appeng.api.networking.IGridNode; 6 | import appeng.api.networking.security.IActionHost; 7 | import appeng.container.AEBaseContainer; 8 | import appeng.container.ContainerNull; 9 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 10 | import io.netty.buffer.ByteBuf; 11 | import net.minecraft.entity.player.EntityPlayer; 12 | import net.minecraft.entity.player.EntityPlayerMP; 13 | import net.minecraft.inventory.Container; 14 | import net.minecraft.inventory.InventoryCrafting; 15 | import net.minecraft.item.ItemStack; 16 | import net.minecraft.item.crafting.CraftingManager; 17 | import net.minecraft.item.crafting.IRecipe; 18 | import net.minecraft.nbt.NBTTagCompound; 19 | import net.minecraft.nbt.NBTTagList; 20 | import net.minecraftforge.fml.common.network.ByteBufUtils; 21 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 22 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 23 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 24 | 25 | import java.util.Optional; 26 | 27 | import static com.github.vfyjxf.nee.jei.CraftingTransferHandler.RECIPE_LENGTH; 28 | import static com.github.vfyjxf.nee.utils.Globals.INPUT_KEY_HEAD; 29 | import static com.github.vfyjxf.nee.utils.Globals.OUTPUT_KEY_HEAD; 30 | 31 | public class PacketSetRecipe implements IMessage { 32 | 33 | private NBTTagCompound recipe; 34 | 35 | public PacketSetRecipe() { 36 | 37 | } 38 | 39 | public PacketSetRecipe(NBTTagCompound recipe) { 40 | this.recipe = recipe; 41 | } 42 | 43 | @Override 44 | public void fromBytes(ByteBuf buf) { 45 | this.recipe = ByteBufUtils.readTag(buf); 46 | } 47 | 48 | @Override 49 | public void toBytes(ByteBuf buf) { 50 | ByteBufUtils.writeTag(buf, this.recipe); 51 | } 52 | 53 | public static class Handler implements IMessageHandler { 54 | 55 | @Override 56 | public IMessage onMessage(PacketSetRecipe message, MessageContext ctx) { 57 | EntityPlayerMP player = ctx.getServerHandler().player; 58 | Container container = player.openContainer; 59 | player.getServerWorld().addScheduledTask(() -> { 60 | if (container instanceof AEBaseContainer) { 61 | AEBaseContainer aeContainer = (AEBaseContainer) container; 62 | IGrid grid = getNetwork(aeContainer); 63 | if (grid != null) { 64 | for (IGridNode gridNode : grid.getMachines(TilePatternInterface.class)) { 65 | 66 | if (gridNode.getMachine() instanceof TilePatternInterface) { 67 | 68 | TilePatternInterface tpi = (TilePatternInterface) gridNode.getMachine(); 69 | NBTTagCompound currentTag = message.recipe.getCompoundTag(OUTPUT_KEY_HEAD); 70 | ItemStack result = currentTag.isEmpty() ? ItemStack.EMPTY : new ItemStack(currentTag); 71 | 72 | if (tpi.getProxy().isActive() && tpi.canPutPattern(result)) { 73 | 74 | ItemStack patternStack = getPatternStack(player, message.recipe); 75 | 76 | if (!patternStack.isEmpty()) { 77 | 78 | if (tpi.putPattern(patternStack) >= 0) { 79 | return; 80 | } 81 | } 82 | 83 | } 84 | 85 | } 86 | } 87 | } 88 | } 89 | }); 90 | return null; 91 | } 92 | 93 | private IGrid getNetwork(AEBaseContainer container) { 94 | if (container.getTarget() instanceof IActionHost) { 95 | IActionHost ah = (IActionHost) container.getTarget(); 96 | IGridNode gn = ah.getActionableNode(); 97 | return gn.getGrid(); 98 | } 99 | return null; 100 | } 101 | 102 | private ItemStack getPatternStack(EntityPlayer player, NBTTagCompound recipe) { 103 | ItemStack[] recipeInputs = new ItemStack[RECIPE_LENGTH]; 104 | NBTTagCompound currentStack; 105 | for (int i = 0; i < recipeInputs.length; i++) { 106 | currentStack = recipe.getCompoundTag(INPUT_KEY_HEAD + i); 107 | recipeInputs[i] = currentStack.isEmpty() ? ItemStack.EMPTY : new ItemStack(currentStack); 108 | } 109 | InventoryCrafting ic = new InventoryCrafting(new ContainerNull(), 3, 3); 110 | for (int i = 0; i < RECIPE_LENGTH; i++) { 111 | ic.setInventorySlotContents(i, recipeInputs[i]); 112 | } 113 | 114 | IRecipe iRecipe = CraftingManager.findMatchingRecipe(ic, player.world); 115 | if (iRecipe != null) { 116 | ItemStack outputStack = iRecipe.getCraftingResult(ic); 117 | if (!outputStack.isEmpty()) { 118 | ItemStack patternStack = null; 119 | Optional maybePattern = AEApi.instance().definitions().items().encodedPattern().maybeStack(1); 120 | if (maybePattern.isPresent()) { 121 | patternStack = maybePattern.get(); 122 | } 123 | if (patternStack != null && !patternStack.isEmpty()) { 124 | final NBTTagCompound patternValue = new NBTTagCompound(); 125 | final NBTTagList tagIn = new NBTTagList(); 126 | for (ItemStack stack : recipeInputs) { 127 | tagIn.appendTag(crateItemTag(stack)); 128 | } 129 | patternValue.setTag("in", tagIn); 130 | patternValue.setTag("out", outputStack.writeToNBT(new NBTTagCompound())); 131 | patternValue.setBoolean("crafting", true); 132 | patternValue.setBoolean("substitute", false); 133 | 134 | patternStack.setTagCompound(patternValue); 135 | return patternStack; 136 | } 137 | } 138 | } 139 | 140 | return ItemStack.EMPTY; 141 | } 142 | 143 | private NBTTagCompound crateItemTag(ItemStack itemStack) { 144 | NBTTagCompound tag = new NBTTagCompound(); 145 | if (!itemStack.isEmpty()) { 146 | itemStack.writeToNBT(tag); 147 | } 148 | return tag; 149 | } 150 | 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketSlotStackSwitch.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.container.AEBaseContainer; 4 | import appeng.container.slot.SlotFake; 5 | import io.netty.buffer.ByteBuf; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.inventory.Container; 8 | import net.minecraft.inventory.Slot; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraftforge.fml.common.network.ByteBufUtils; 11 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 12 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 13 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * @author vfyjxf 20 | */ 21 | public class PacketSlotStackSwitch implements IMessage { 22 | 23 | private ItemStack stack; 24 | private List slots; 25 | 26 | public PacketSlotStackSwitch() { 27 | 28 | } 29 | 30 | public ItemStack getStack() { 31 | return stack; 32 | } 33 | 34 | public List getSlots() { 35 | return slots; 36 | } 37 | 38 | public PacketSlotStackSwitch(ItemStack stack, List craftingSlots) { 39 | this.stack = stack; 40 | this.slots = craftingSlots; 41 | } 42 | 43 | @Override 44 | public void fromBytes(ByteBuf buf) { 45 | this.stack = ByteBufUtils.readItemStack(buf); 46 | int craftingSlotsSize = buf.readInt(); 47 | this.slots = new ArrayList<>(craftingSlotsSize); 48 | for (int i = 0; i < craftingSlotsSize; i++) { 49 | int slotNumber = buf.readInt(); 50 | this.slots.add(slotNumber); 51 | } 52 | } 53 | 54 | @Override 55 | public void toBytes(ByteBuf buf) { 56 | ByteBufUtils.writeItemStack(buf, this.stack); 57 | buf.writeInt(this.slots.size()); 58 | for (Integer craftingSlot : this.slots) { 59 | buf.writeInt(craftingSlot); 60 | } 61 | } 62 | 63 | public static class Handler implements IMessageHandler { 64 | 65 | @Override 66 | public IMessage onMessage(PacketSlotStackSwitch message, MessageContext ctx) { 67 | EntityPlayerMP player = ctx.getServerHandler().player; 68 | Container container = player.openContainer; 69 | player.getServerWorld().addScheduledTask(() -> { 70 | if (!(container instanceof AEBaseContainer)) { 71 | return; 72 | } 73 | ItemStack nextStack = message.getStack(); 74 | if (nextStack == null) { 75 | return; 76 | } 77 | for (Integer craftingSlot : message.getSlots()) { 78 | Slot currentSlot = container.getSlot(craftingSlot); 79 | if (!(currentSlot instanceof SlotFake)) { 80 | continue; 81 | } 82 | ItemStack next = nextStack.copy(); 83 | ItemStack stackInSlot = currentSlot.getStack(); 84 | next.setCount(!stackInSlot.isEmpty() ? stackInSlot.getCount() : 1); 85 | currentSlot.putStack(next); 86 | } 87 | }); 88 | return null; 89 | } 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketStackSizeChange.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.container.AEBaseContainer; 4 | import appeng.container.implementations.ContainerPatternTerm; 5 | import appeng.container.slot.SlotFake; 6 | import com.github.vfyjxf.nee.helper.PlatformHelper; 7 | import io.netty.buffer.ByteBuf; 8 | import net.minecraft.entity.player.EntityPlayerMP; 9 | import net.minecraft.inventory.Container; 10 | import net.minecraft.inventory.Slot; 11 | import net.minecraft.item.ItemStack; 12 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 13 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 14 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 15 | 16 | /** 17 | * @author vfyjxf 18 | */ 19 | public class PacketStackSizeChange implements IMessage { 20 | 21 | private int slotIndex; 22 | private int changeCount; 23 | 24 | public int getSlotIndex() { 25 | return slotIndex; 26 | } 27 | 28 | public int getChangeCount() { 29 | return changeCount; 30 | } 31 | 32 | public PacketStackSizeChange() { 33 | 34 | } 35 | 36 | public PacketStackSizeChange(int slotIndex, int changeCount) { 37 | this.slotIndex = slotIndex; 38 | this.changeCount = changeCount; 39 | } 40 | 41 | @Override 42 | public void fromBytes(ByteBuf buf) { 43 | this.slotIndex = buf.readInt(); 44 | this.changeCount = buf.readInt(); 45 | } 46 | 47 | @Override 48 | public void toBytes(ByteBuf buf) { 49 | buf.writeInt(this.slotIndex); 50 | buf.writeInt(this.changeCount); 51 | } 52 | 53 | public static class Handler implements IMessageHandler { 54 | 55 | @Override 56 | public IMessage onMessage(PacketStackSizeChange message, MessageContext ctx) { 57 | EntityPlayerMP player = ctx.getServerHandler().player; 58 | Container container = player.openContainer; 59 | player.getServerWorld().addScheduledTask(() -> { 60 | if (container instanceof AEBaseContainer) { 61 | 62 | if (container instanceof ContainerPatternTerm && PlatformHelper.isCraftingMode(container)) { 63 | return; 64 | } 65 | 66 | Slot currentSlot = container.getSlot(message.getSlotIndex()); 67 | if (currentSlot instanceof SlotFake && currentSlot.getHasStack()) { 68 | for (int i = 0; i < Math.abs(message.getChangeCount()); i++) { 69 | int currentStackSize = message.getChangeCount() > 0 ? currentSlot.getStack().getCount() + 1 : currentSlot.getStack().getCount() - 1; 70 | if (currentStackSize <= currentSlot.getStack().getMaxStackSize() && currentStackSize > 0) { 71 | ItemStack nextStack = currentSlot.getStack().copy(); 72 | nextStack.setCount(currentStackSize); 73 | currentSlot.putStack(nextStack); 74 | } else { 75 | break; 76 | } 77 | } 78 | } 79 | } 80 | }); 81 | return null; 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketSyncInterfaceDataClient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import com.github.vfyjxf.nee.network.SyncAction; 4 | import io.netty.buffer.ByteBuf; 5 | import net.minecraft.nbt.NBTTagCompound; 6 | import net.minecraftforge.fml.common.network.ByteBufUtils; 7 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 8 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 9 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 10 | 11 | import java.util.Objects; 12 | 13 | public class PacketSyncInterfaceDataClient implements IMessage { 14 | 15 | 16 | private int actionId; 17 | private NBTTagCompound data; 18 | 19 | public PacketSyncInterfaceDataClient() { 20 | } 21 | 22 | public PacketSyncInterfaceDataClient(SyncAction action, NBTTagCompound data) { 23 | this.actionId = action.ordinal(); 24 | this.data = data; 25 | } 26 | 27 | @Override 28 | public void fromBytes(ByteBuf byteBuf) { 29 | this.actionId = byteBuf.readInt(); 30 | this.data = ByteBufUtils.readTag(byteBuf); 31 | } 32 | 33 | @Override 34 | public void toBytes(ByteBuf byteBuf) { 35 | byteBuf.writeInt(this.actionId); 36 | ByteBufUtils.writeTag(byteBuf, this.data); 37 | } 38 | 39 | public static class Handler implements IMessageHandler { 40 | 41 | @Override 42 | public IMessage onMessage(PacketSyncInterfaceDataClient packet, MessageContext ctx) { 43 | SyncAction action = SyncAction.values()[packet.actionId]; 44 | if (Objects.requireNonNull(action) == SyncAction.SYNC_INTERFACE_DATA) { 45 | handleSyncInterfaceData(packet, ctx); 46 | } else { 47 | return null; 48 | } 49 | return null; 50 | } 51 | 52 | private void handleSyncInterfaceData(PacketSyncInterfaceDataClient packet, MessageContext ctx) { 53 | // QuickPusherWidget pusher = GuiEventHandler.getInstance().getPusherWidget(); 54 | // if (pusher != null) { 55 | // Minecraft.getMinecraft().addScheduledTask(() -> pusher.syncFromServer(packet.data)); 56 | // } 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketSyncInterfaceDataServer.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.api.networking.IGrid; 4 | import appeng.api.networking.IGridHost; 5 | import appeng.api.networking.IGridNode; 6 | import appeng.container.implementations.ContainerPatternTerm; 7 | import com.github.vfyjxf.nee.integration.IPatternProvider; 8 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 9 | import com.github.vfyjxf.nee.network.SyncAction; 10 | import com.github.vfyjxf.nee.utils.Globals; 11 | import com.github.vfyjxf.nee.utils.PatternContainerControl; 12 | import io.netty.buffer.ByteBuf; 13 | import net.minecraft.entity.player.EntityPlayerMP; 14 | import net.minecraft.inventory.Container; 15 | import net.minecraft.nbt.NBTTagCompound; 16 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 17 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 18 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 19 | import net.minecraftforge.items.IItemHandler; 20 | 21 | import java.util.Objects; 22 | 23 | public class PacketSyncInterfaceDataServer implements IMessage { 24 | 25 | private int actionId; 26 | 27 | public PacketSyncInterfaceDataServer() { 28 | } 29 | 30 | public PacketSyncInterfaceDataServer(SyncAction action) { 31 | this.actionId = action.ordinal(); 32 | } 33 | 34 | @Override 35 | public void fromBytes(ByteBuf byteBuf) { 36 | 37 | } 38 | 39 | @Override 40 | public void toBytes(ByteBuf byteBuf) { 41 | 42 | } 43 | 44 | public static class Handler implements IMessageHandler { 45 | @Override 46 | public IMessage onMessage(PacketSyncInterfaceDataServer packet, MessageContext cxt) { 47 | EntityPlayerMP player = cxt.getServerHandler().player; 48 | Container container = player.openContainer; 49 | SyncAction action = SyncAction.values()[packet.actionId]; 50 | if (Objects.requireNonNull(action) == SyncAction.SYNC_INTERFACE_DATA) { 51 | handleInterfaceSync(container, player); 52 | } else { 53 | return null; 54 | } 55 | return null; 56 | } 57 | 58 | private void handleInterfaceSync(Container container, EntityPlayerMP player) { 59 | if (container instanceof ContainerPatternTerm) { 60 | ContainerPatternTerm patternTerm = (ContainerPatternTerm) container; 61 | NBTTagCompound tag = packInterfaceData(patternTerm); 62 | NEENetworkHandler.getInstance().sendTo( 63 | new PacketSyncInterfaceDataClient(SyncAction.SYNC_INTERFACE_DATA, tag), 64 | player 65 | ); 66 | } 67 | 68 | } 69 | 70 | @SuppressWarnings("unchecked") 71 | private NBTTagCompound packInterfaceData(ContainerPatternTerm term) { 72 | NBTTagCompound interfaceTag = new NBTTagCompound(); 73 | for (IPatternProvider p : IPatternProvider.PROVIDERS) { 74 | IPatternProvider provider = (IPatternProvider) p; 75 | IGrid grid = term.getNetworkNode().getGrid(); 76 | for (IGridNode node : grid.getMachines(provider.getHostClass())) { 77 | if (node.isActive()) { 78 | NBTTagCompound tag = new NBTTagCompound(); 79 | IGridHost host = node.getMachine(); 80 | IItemHandler patterns = provider.getPatterns((T) host); 81 | tag.setString("uid", provider.uid((T) host)); 82 | tag.setTag("patterns", packPatterns(patterns)); 83 | tag.setTag("identifier", node.getGridBlock().getMachineRepresentation().writeToNBT(new NBTTagCompound())); 84 | tag.setTag("target", provider.getTarget((T) host).writeToNBT(new NBTTagCompound())); 85 | tag.setString("name", provider.getName((T) host)); 86 | interfaceTag.setTag(provider.uid((T) host), tag); 87 | PatternContainerControl.putHandler(provider.uid((T) host), patterns); 88 | } 89 | } 90 | } 91 | return interfaceTag; 92 | } 93 | 94 | private static NBTTagCompound packPatterns(IItemHandler patterns) { 95 | NBTTagCompound tag = new NBTTagCompound(); 96 | tag.setInteger("size", patterns.getSlots()); 97 | for (int i = 0; i < patterns.getSlots(); i++) { 98 | NBTTagCompound pattern = new NBTTagCompound(); 99 | patterns.getStackInSlot(i).writeToNBT(pattern); 100 | tag.setTag(Globals.INPUT_KEY_HEAD + i, pattern); 101 | } 102 | return tag; 103 | } 104 | 105 | } 106 | 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketValueConfigClient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.container.AEBaseContainer; 4 | import com.github.vfyjxf.nee.jei.CraftingTransferHandler; 5 | import io.netty.buffer.ByteBuf; 6 | import net.minecraft.client.Minecraft; 7 | import net.minecraft.client.entity.EntityPlayerSP; 8 | import net.minecraft.inventory.Container; 9 | import net.minecraftforge.fml.common.network.ByteBufUtils; 10 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 11 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 12 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 13 | 14 | public class PacketValueConfigClient implements IMessage { 15 | 16 | private String name; 17 | private String value; 18 | 19 | public PacketValueConfigClient() { 20 | 21 | } 22 | 23 | public PacketValueConfigClient(String name, String value) { 24 | this.name = name; 25 | this.value = value; 26 | } 27 | 28 | public PacketValueConfigClient(String name) { 29 | this.name = name; 30 | this.value = ""; 31 | } 32 | 33 | @Override 34 | public void fromBytes(ByteBuf buf) { 35 | this.name = ByteBufUtils.readUTF8String(buf); 36 | this.value = ByteBufUtils.readUTF8String(buf); 37 | } 38 | 39 | @Override 40 | public void toBytes(ByteBuf buf) { 41 | ByteBufUtils.writeUTF8String(buf, this.name); 42 | ByteBufUtils.writeUTF8String(buf, this.value); 43 | } 44 | 45 | public static class Handler implements IMessageHandler { 46 | 47 | @Override 48 | public IMessage onMessage(PacketValueConfigClient message, MessageContext ctx) { 49 | EntityPlayerSP player = Minecraft.getMinecraft().player; 50 | Container container = player.openContainer; 51 | Minecraft.getMinecraft().addScheduledTask(() -> { 52 | if ("PatternInterface.check".equals(message.name)) { 53 | if (container instanceof AEBaseContainer) { 54 | CraftingTransferHandler.setIsPatternInterfaceExists(Boolean.parseBoolean(message.value)); 55 | } 56 | } 57 | }); 58 | return null; 59 | } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketValueConfigServer.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import appeng.api.networking.IGrid; 4 | import appeng.api.networking.IGridNode; 5 | import appeng.api.networking.security.IActionHost; 6 | import appeng.container.AEBaseContainer; 7 | import appeng.container.slot.SlotRestrictedInput; 8 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 9 | import com.github.vfyjxf.nee.container.ContainerPatternInterface; 10 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 11 | import io.netty.buffer.ByteBuf; 12 | import net.minecraft.entity.player.EntityPlayerMP; 13 | import net.minecraft.inventory.Container; 14 | import net.minecraft.inventory.Slot; 15 | import net.minecraftforge.fml.common.network.ByteBufUtils; 16 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 17 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 18 | import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; 19 | 20 | public class PacketValueConfigServer implements IMessage { 21 | 22 | private String name; 23 | private String value; 24 | 25 | public PacketValueConfigServer() { 26 | 27 | } 28 | 29 | public PacketValueConfigServer(String name, String value) { 30 | this.name = name; 31 | this.value = value; 32 | } 33 | 34 | public PacketValueConfigServer(String name) { 35 | this.name = name; 36 | this.value = ""; 37 | } 38 | 39 | @Override 40 | public void fromBytes(ByteBuf buf) { 41 | this.name = ByteBufUtils.readUTF8String(buf); 42 | this.value = ByteBufUtils.readUTF8String(buf); 43 | } 44 | 45 | @Override 46 | public void toBytes(ByteBuf buf) { 47 | ByteBufUtils.writeUTF8String(buf, this.name); 48 | ByteBufUtils.writeUTF8String(buf, this.value); 49 | } 50 | 51 | public static class Handler implements IMessageHandler { 52 | 53 | @Override 54 | public IMessage onMessage(PacketValueConfigServer message, MessageContext ctx) { 55 | EntityPlayerMP player = ctx.getServerHandler().player; 56 | Container container = player.openContainer; 57 | player.getServerWorld().addScheduledTask(() -> { 58 | if ("Container.selectedSlot".equals(message.name)) { 59 | if (container instanceof ContainerPatternInterface) { 60 | ContainerPatternInterface cpc = (ContainerPatternInterface) container; 61 | int slotIndex = Integer.parseInt(message.value); 62 | Slot slot = container.getSlot(slotIndex); 63 | if (slot instanceof SlotRestrictedInput) { 64 | cpc.setSelectedSlotIndex(slot.slotNumber); 65 | } 66 | } 67 | } else if ("Gui.PatternInterface".equals(message.name)) { 68 | if (container instanceof ContainerPatternInterface) { 69 | ContainerPatternInterface cpc = (ContainerPatternInterface) container; 70 | TilePatternInterface tile = (TilePatternInterface) cpc.getTileEntity(); 71 | tile.cancelWork(cpc.getSelectedSlotIndex()); 72 | cpc.removeCurrentRecipe(); 73 | tile.updateCraftingList(); 74 | } 75 | } else if ("PatternInterface.check".equals(message.name)) { 76 | if (container instanceof AEBaseContainer) { 77 | AEBaseContainer abc = (AEBaseContainer) container; 78 | IGrid grid = getNetwork(abc); 79 | if (grid != null) { 80 | for (IGridNode gridNode : grid.getMachines(TilePatternInterface.class)) { 81 | 82 | if (gridNode.getMachine() instanceof TilePatternInterface) { 83 | NEENetworkHandler.getInstance().sendTo(new PacketValueConfigClient("PatternInterface.check", "true"), player); 84 | return; 85 | } 86 | 87 | } 88 | NEENetworkHandler.getInstance().sendTo(new PacketValueConfigClient("PatternInterface.check", "false"), player); 89 | } 90 | } 91 | } 92 | 93 | 94 | }); 95 | return null; 96 | } 97 | 98 | private IGrid getNetwork(AEBaseContainer container) { 99 | if (container.getTarget() instanceof IActionHost) { 100 | IActionHost ah = (IActionHost) container.getTarget(); 101 | IGridNode gn = ah.getActionableNode(); 102 | return gn.getGrid(); 103 | } 104 | return null; 105 | } 106 | 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/ClientProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import com.github.vfyjxf.nee.NEECommands; 4 | import com.github.vfyjxf.nee.client.GuiEventHandler; 5 | import com.github.vfyjxf.nee.config.KeyBindings; 6 | import com.github.vfyjxf.nee.config.NEEConfig; 7 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 8 | import com.github.vfyjxf.nee.utils.Globals; 9 | import net.minecraft.client.renderer.block.model.ModelResourceLocation; 10 | import net.minecraftforge.client.ClientCommandHandler; 11 | import net.minecraftforge.client.event.ModelRegistryEvent; 12 | import net.minecraftforge.client.model.ModelLoader; 13 | import net.minecraftforge.common.MinecraftForge; 14 | import net.minecraftforge.fml.client.registry.ClientRegistry; 15 | import net.minecraftforge.fml.common.Mod; 16 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 17 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 18 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 19 | 20 | import static com.github.vfyjxf.nee.block.BlockPatternInterface.ITEM_INSTANCE; 21 | 22 | @Mod.EventBusSubscriber(modid = Globals.MOD_ID) 23 | public class ClientProxy extends CommonProxy { 24 | @Override 25 | public void init(FMLInitializationEvent event) { 26 | super.init(event); 27 | ClientRegistry.registerKeyBinding(KeyBindings.SWITCH_INGREDIENT); 28 | ClientRegistry.registerKeyBinding(KeyBindings.MODIFY_COUNT); 29 | ClientRegistry.registerKeyBinding(KeyBindings.AUTO_CRAFT_NON_PREVIEW); 30 | ClientRegistry.registerKeyBinding(KeyBindings.AUTO_CRAFT_NON_PREVIEW); 31 | ClientCommandHandler.instance.registerCommand(new NEECommands()); 32 | MinecraftForge.EVENT_BUS.register(GuiEventHandler.getInstance()); 33 | } 34 | 35 | @Override 36 | public void preInit(FMLPreInitializationEvent event) { 37 | super.preInit(event); 38 | NEEConfig.preInit(event); 39 | NEENetworkHandler.init(); 40 | } 41 | 42 | @SubscribeEvent 43 | public static void onModelRegister(ModelRegistryEvent event) { 44 | ModelLoader.setCustomModelResourceLocation(ITEM_INSTANCE, 0, new ModelResourceLocation(ITEM_INSTANCE.getRegistryName(), "inventory")); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/CommonProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import appeng.core.features.ActivityState; 4 | import appeng.core.features.BlockStackSrc; 5 | import appeng.tile.AEBaseTile; 6 | import com.github.vfyjxf.nee.block.BlockPatternInterface; 7 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 8 | import com.github.vfyjxf.nee.utils.Globals; 9 | import net.minecraft.block.Block; 10 | import net.minecraft.item.Item; 11 | import net.minecraft.util.ResourceLocation; 12 | import net.minecraftforge.event.RegistryEvent; 13 | import net.minecraftforge.fml.common.Mod; 14 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 15 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 16 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 17 | import net.minecraftforge.fml.common.registry.GameRegistry; 18 | 19 | @Mod.EventBusSubscriber(modid = Globals.MOD_ID) 20 | public class CommonProxy { 21 | 22 | public void init(FMLInitializationEvent event) { 23 | AEBaseTile.registerTileItem(BlockPatternInterface.BLOCK_INSTANCE.getTileEntityClass(), 24 | new BlockStackSrc(BlockPatternInterface.BLOCK_INSTANCE, 0, ActivityState.Enabled)); 25 | } 26 | 27 | public void preInit(FMLPreInitializationEvent event) { 28 | 29 | } 30 | 31 | @SubscribeEvent 32 | public static void onItemRegister(RegistryEvent.Register event) { 33 | event.getRegistry().register(BlockPatternInterface.ITEM_INSTANCE); 34 | } 35 | 36 | @SubscribeEvent 37 | public static void onBlockRegister(RegistryEvent.Register event) { 38 | event.getRegistry().register(BlockPatternInterface.BLOCK_INSTANCE); 39 | GameRegistry.registerTileEntity(TilePatternInterface.class, new ResourceLocation(Globals.MOD_ID, "patterninterface")); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/ServerProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 4 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 5 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 6 | 7 | public class ServerProxy extends CommonProxy { 8 | @Override 9 | public void init(FMLInitializationEvent event) { 10 | super.init(event); 11 | } 12 | 13 | @Override 14 | public void preInit(FMLPreInitializationEvent event) { 15 | super.preInit(event); 16 | NEENetworkHandler.init(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/BlackIngredient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import net.minecraft.item.ItemStack; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | 6 | import javax.annotation.Nullable; 7 | import java.util.Objects; 8 | 9 | public class BlackIngredient { 10 | 11 | private final ItemStack identifier; 12 | @Nullable 13 | private final String acceptedType; 14 | 15 | public BlackIngredient(ItemStack identifier, @Nullable String acceptedType) { 16 | this.identifier = identifier; 17 | this.acceptedType = acceptedType; 18 | } 19 | 20 | 21 | public ItemStack getIdentifier() { 22 | return identifier; 23 | } 24 | 25 | @Nullable 26 | public String getAcceptedType() { 27 | return acceptedType; 28 | } 29 | 30 | public boolean matches(ItemStack stack, String recipeType) { 31 | if (acceptedType == null || recipeType == null || acceptedType.equals(recipeType)) { 32 | return ItemUtils.contains(identifier, stack); 33 | } else { 34 | return false; 35 | } 36 | } 37 | 38 | public NBTTagCompound toTag() { 39 | NBTTagCompound tag = new NBTTagCompound(); 40 | tag.setTag("identifier", identifier.writeToNBT(new NBTTagCompound())); 41 | if (acceptedType != null) { 42 | tag.setString("acceptedType", acceptedType); 43 | } 44 | return tag; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object o) { 49 | if (this == o) return true; 50 | if (o == null || getClass() != o.getClass()) return false; 51 | BlackIngredient that = (BlackIngredient) o; 52 | return identifier.equals(that.identifier) && Objects.equals(acceptedType, that.acceptedType); 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | return Objects.hash(identifier, acceptedType); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/Globals.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | public class Globals { 4 | public static final String MOD_ID = "neenergistics"; 5 | public static final String NAME = "NotEnoughEnergistics"; 6 | public static final String VERSION = "@VERSION@"; 7 | public static final String DEPENDENCIES = "required-after:jei;required-after:appliedenergistics2"; 8 | public static final String GUI_FACTORY = "com.github.vfyjxf.nee.config.NEEConfigGuiFactory"; 9 | 10 | public static final String WCT = "wct"; 11 | public static final String APPENG = "appliedenergistics2"; 12 | public static final String INPUT_KEY_HEAD = "#"; 13 | public static final String OUTPUT_KEY_HEAD = "O"; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/GuiUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import appeng.client.gui.implementations.GuiCraftingTerm; 4 | import appeng.container.slot.AppEngSlot; 5 | import appeng.helpers.IContainerCraftingPacket; 6 | import com.github.vfyjxf.nee.helper.PlatformHelper; 7 | import mezz.jei.gui.recipes.RecipesGui; 8 | import net.minecraft.client.Minecraft; 9 | import net.minecraft.client.gui.GuiScreen; 10 | import net.minecraft.inventory.Container; 11 | import net.minecraft.inventory.Slot; 12 | import net.minecraftforge.items.IItemHandler; 13 | 14 | import javax.annotation.Nullable; 15 | 16 | /** 17 | * @author vfyjxf 18 | */ 19 | public class GuiUtils { 20 | 21 | private GuiUtils(){ 22 | 23 | } 24 | 25 | public static boolean isCraftingSlot(Slot slot) { 26 | Container container = Minecraft.getMinecraft().player.openContainer; 27 | if (container instanceof IContainerCraftingPacket && slot instanceof AppEngSlot) { 28 | IItemHandler craftMatrix = ((IContainerCraftingPacket) container).getInventoryByName("crafting"); 29 | return ((AppEngSlot) slot).getItemHandler().equals(craftMatrix); 30 | } 31 | return false; 32 | } 33 | 34 | public static boolean isGuiWirelessCrafting(Object gui) { 35 | try { 36 | Class wirelessCraftingGui = Class.forName("p455w0rd.wct.client.gui.GuiWCT"); 37 | return wirelessCraftingGui.isInstance(gui); 38 | } catch (ClassNotFoundException e) { 39 | return false; 40 | } 41 | } 42 | 43 | public static boolean isWirelessCraftingTermContainer(Object container) { 44 | try { 45 | Class wirelessCraftingContainer = Class.forName("p455w0rd.wct.container.ContainerWCT"); 46 | return wirelessCraftingContainer.isInstance(container); 47 | } catch (ClassNotFoundException e) { 48 | return false; 49 | } 50 | } 51 | 52 | public static boolean isWirelessGuiCraftConfirm(Object gui) { 53 | try { 54 | Class guiCraftConfirm = Class.forName("p455w0rd.wct.client.gui.GuiCraftConfirm"); 55 | return guiCraftConfirm.isInstance(gui); 56 | } catch (ClassNotFoundException e) { 57 | return false; 58 | } 59 | } 60 | 61 | public static boolean isWirelessTerminalGuiObject(Object guiObj) { 62 | try { 63 | Class wirelessTerminalGuiObjClass = Class.forName("p455w0rd.ae2wtlib.api.WTGuiObject"); 64 | return wirelessTerminalGuiObjClass.isInstance(guiObj); 65 | } catch (ClassNotFoundException e) { 66 | return false; 67 | } 68 | } 69 | 70 | public static boolean isCraftingTerm(GuiScreen gui) { 71 | return gui instanceof GuiCraftingTerm || isGuiWirelessCrafting(gui) || PlatformHelper.isWirelessGui(gui); 72 | } 73 | 74 | @Nullable 75 | public static GuiScreen getParentScreen() { 76 | if (Minecraft.getMinecraft().currentScreen instanceof RecipesGui) { 77 | return ((RecipesGui) Minecraft.getMinecraft().currentScreen).getParentScreen(); 78 | } else { 79 | return null; 80 | } 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/IngredientStatus.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | /** 4 | * Represents an Ingredient in its most prominent state. 5 | */ 6 | public enum IngredientStatus { 7 | CRAFTABLE, EXISTS, MISSING 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/ItemUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import appeng.api.storage.data.IAEItemStack; 4 | import appeng.api.storage.data.IItemList; 5 | import appeng.client.me.ItemRepo; 6 | import mezz.jei.api.gui.IGuiIngredient; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.nbt.NBTTagCompound; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | import java.util.stream.StreamSupport; 14 | 15 | import static net.minecraftforge.fml.common.ObfuscationReflectionHelper.getPrivateValue; 16 | 17 | /** 18 | * @author vfyjxf 19 | */ 20 | public final class ItemUtils { 21 | 22 | public static boolean matches(ItemStack stack1, ItemStack stack2) { 23 | if (stack1 == null || stack2 == null) return false; 24 | return ItemStack.areItemsEqual(stack1, stack2) && ItemStack.areItemStackTagsEqual(stack1, stack2); 25 | } 26 | 27 | public static boolean contains(ItemStack based, ItemStack stack) { 28 | if (based == null || stack == null) return false; 29 | if (ItemStack.areItemsEqual(based, stack)) { 30 | if (based.getTagCompound() == null && stack.getTagCompound() == null) { 31 | return based.areCapsCompatible(stack); 32 | } else if (based.getTagCompound() == null) { 33 | return based.areCapsCompatible(stack); 34 | } else if (stack.getTagCompound() != null) { 35 | NBTTagCompound tagCompound = stack.getTagCompound(); 36 | return based.areCapsCompatible(stack) && 37 | based.getTagCompound() 38 | .getKeySet() 39 | .stream() 40 | .allMatch(keyName -> { 41 | if (!tagCompound.hasKey(keyName)) { 42 | return false; 43 | } else { 44 | return tagCompound.getTag(keyName).equals(based.getTagCompound().getTag(keyName)); 45 | } 46 | } 47 | ); 48 | } 49 | } 50 | return false; 51 | } 52 | 53 | public static ItemStack getFirstStack(IGuiIngredient ingredient) { 54 | if (ingredient == null || ingredient.getAllIngredients().isEmpty()) { 55 | return ItemStack.EMPTY; 56 | } 57 | return ingredient.getAllIngredients() 58 | .stream() 59 | .filter(stack -> stack != null && !stack.isEmpty()) 60 | .findFirst() 61 | .map(ItemStack::copy) 62 | .orElse(ItemStack.EMPTY); 63 | } 64 | 65 | public static ItemStack getFirstStack(List ingredients) { 66 | if (ingredients == null || ingredients.isEmpty()) { 67 | return ItemStack.EMPTY; 68 | } 69 | return ingredients 70 | .stream() 71 | .filter(stack -> stack != null && !stack.isEmpty()) 72 | .findFirst() 73 | .map(ItemStack::copy) 74 | .orElse(ItemStack.EMPTY); 75 | } 76 | 77 | public static List getStorage(ItemRepo repo) { 78 | if (repo == null) return Collections.emptyList(); 79 | IItemList all = getPrivateValue(ItemRepo.class, repo, "list"); 80 | if (all == null) return Collections.emptyList(); 81 | else return StreamSupport.stream(all.spliterator(), false).collect(Collectors.toList()); 82 | } 83 | 84 | public static ItemStack fromTagOrEmpty(NBTTagCompound tag) { 85 | return tag == null ? ItemStack.EMPTY : tag.isEmpty() ? ItemStack.EMPTY : new ItemStack(tag); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/PatternContainerControl.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraftforge.items.IItemHandler; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class PatternContainerControl { 11 | 12 | /** 13 | * Use in server side to store the container's item handler. 14 | * and we can use item handler to put item into container. 15 | */ 16 | private static final Map containerHandlers = new HashMap<>(); 17 | 18 | 19 | public static void putHandler(String containerId, IItemHandler handler) { 20 | containerHandlers.put(containerId, handler); 21 | } 22 | 23 | public static ItemStack insertPattern(String containerId, int slot, ItemStack stack) { 24 | IItemHandler handler = containerHandlers.get(containerId); 25 | if (handler != null) { 26 | return handler.insertItem(slot, stack, false); 27 | } 28 | return ItemStack.EMPTY; 29 | } 30 | 31 | public static ItemStack insertPattern(long containerId, int slot, ItemStack stack) { 32 | return insertPattern(Long.toString(containerId), slot, stack); 33 | } 34 | 35 | public static void addPattern(String containerId, ItemStack stack) { 36 | IItemHandler handler = containerHandlers.get(containerId); 37 | if (handler != null) { 38 | for (int i = 0; i < handler.getSlots(); i++) { 39 | if (handler.insertItem(i, stack, true).isEmpty()) { 40 | handler.insertItem(i, stack, false); 41 | break; 42 | } 43 | } 44 | } 45 | } 46 | 47 | public static void addPattern(long containerId, ItemStack stack) { 48 | addPattern(Long.toString(containerId), stack); 49 | } 50 | 51 | public static ItemStack extractPattern(String containerId, int slot) { 52 | IItemHandler handler = containerHandlers.get(containerId); 53 | if (handler != null) { 54 | return handler.extractItem(slot, 1, false); 55 | } 56 | return ItemStack.EMPTY; 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/PreferenceIngredient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import com.github.vfyjxf.nee.integration.IToolHelper; 4 | import com.github.vfyjxf.nee.integration.RecipeToolManager; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.nbt.NBTTagCompound; 7 | 8 | import javax.annotation.Nullable; 9 | import java.util.Objects; 10 | 11 | public class PreferenceIngredient { 12 | 13 | private final ItemStack identifier; 14 | private final boolean isTool; 15 | @Nullable 16 | private final String acceptedType; 17 | 18 | public PreferenceIngredient(ItemStack identifier, boolean isTool, @Nullable String acceptedType) { 19 | this.identifier = identifier; 20 | this.isTool = isTool; 21 | this.acceptedType = acceptedType; 22 | } 23 | 24 | public ItemStack create(int count) { 25 | if (isTool) { 26 | IToolHelper helper = RecipeToolManager.INSTANCE.getToolHelper(identifier.getItem()); 27 | if (helper != null) { 28 | ItemStack toolStack = helper.getToolStack(identifier); 29 | toolStack.setCount(1); 30 | return toolStack; 31 | } 32 | } else { 33 | ItemStack stack = identifier.copy(); 34 | stack.setCount(count); 35 | return stack; 36 | } 37 | return ItemStack.EMPTY; 38 | } 39 | 40 | public boolean matches(ItemStack stack, String recipeType) { 41 | if (acceptedType == null || recipeType == null || acceptedType.equals(recipeType)) { 42 | return ItemUtils.contains(identifier, stack); 43 | } else { 44 | return false; 45 | } 46 | } 47 | 48 | public ItemStack getIdentifier() { 49 | return identifier; 50 | } 51 | 52 | public boolean isTool() { 53 | return isTool; 54 | } 55 | 56 | @Nullable 57 | public String getAcceptedType() { 58 | return acceptedType; 59 | } 60 | 61 | public NBTTagCompound toTag() { 62 | NBTTagCompound tag = new NBTTagCompound(); 63 | tag.setTag("identifier", identifier.writeToNBT(new NBTTagCompound())); 64 | tag.setBoolean("isTool", isTool); 65 | if (acceptedType != null) { 66 | tag.setString("acceptedType", acceptedType); 67 | } 68 | return tag; 69 | } 70 | 71 | @Override 72 | public boolean equals(Object o) { 73 | if (this == o) return true; 74 | if (o == null || getClass() != o.getClass()) return false; 75 | PreferenceIngredient that = (PreferenceIngredient) o; 76 | return isTool == that.isTool && identifier.equals(that.identifier) && Objects.equals(acceptedType, that.acceptedType); 77 | } 78 | 79 | @Override 80 | public int hashCode() { 81 | return Objects.hash(identifier, isTool, acceptedType); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/StackWrapper.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | import javax.annotation.Nonnull; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class StackWrapper { 10 | 11 | @Nonnull 12 | private final ItemStack stack; 13 | private final List ingredients; 14 | private int count; 15 | 16 | public StackWrapper(@Nonnull ItemStack stack, List ingredients) { 17 | this.stack = stack; 18 | this.ingredients = new ArrayList<>(ingredients); 19 | this.count = stack.getCount(); 20 | } 21 | 22 | public StackWrapper(@Nonnull ItemStack stack, List ingredients, int count) { 23 | this.stack = stack; 24 | this.ingredients = new ArrayList<>(ingredients); 25 | this.count = count; 26 | } 27 | 28 | public boolean merge(ItemStack other) { 29 | if (ItemUtils.matches(stack, other) && count + other.getCount() <= stack.getMaxStackSize()) { 30 | count += other.getCount(); 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | public boolean merge(StackWrapper other) { 37 | return merge(other.stack); 38 | } 39 | 40 | public void addCount(int count) { 41 | this.count += count; 42 | } 43 | 44 | @Nonnull 45 | public ItemStack getStack() { 46 | return stack; 47 | } 48 | 49 | public List getIngredients() { 50 | return ingredients; 51 | } 52 | 53 | public int getCount() { 54 | return count; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/neenergistics_at.cfg: -------------------------------------------------------------------------------- 1 | public net.minecraft.client.gui.inventory.GuiContainer field_147003_i #guiLeft 2 | public net.minecraft.client.gui.inventory.GuiContainer field_147009_r #guiTop 3 | public net.minecraft.client.gui.inventory.GuiContainer field_147000_g # ySize 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/blockstates/pattern_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "normal": { 4 | "model": "neenergistics:pattern_interface" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/lang/en_us.lang: -------------------------------------------------------------------------------- 1 | jei.tooltip.nee.helper.crafting.text1=click to request missing items. 2 | jei.tooltip.nee.helper.crafting.text2=click to request the recipe result. 3 | jei.tooltip.nee.helper.pattern=Autocrafting available 4 | jei.tooltip.nee.helper.craftable=Craftable 5 | jei.tooltip.nee.helper.waiting=Matching Recipe... 6 | 7 | key.neenergistics.crafting.helper.preview=Crafting Help 8 | key.neenergistics.crafting.helper.noPreview=Crafting Help(No Preview) 9 | key.neenergistics.recipe.ingredient.change=Change Ingredient 10 | key.neenergistics.stack.count.change=Change Count 11 | 12 | gui.neenergistics.button.title.combination=Combine Items 13 | gui.neenergistics.button.tooltip.combination=Current Mode: %s 14 | gui.neenergistics.button.name.enabled=Enabled 15 | gui.neenergistics.button.name.disabled=Disabled 16 | gui.neenergistics.button.name.whitelist=Whitelist 17 | gui.neenergistics.button.title.remove=Remove 18 | gui.neenergistics.button.tooltip.remove=Remove and cancel the current recipe 19 | gui.neenergistics.button.tooltip.preference.remove=Remove selected stack from preference list. 20 | gui.neenergistics.button.tooltip.preference.add=Add selected stack from preference list. 21 | gui.neenergistics.button.tooltip.preference.text1=Use middle click to select slot. 22 | gui.neenergistics.button.tooltip.preference.open=Open preference list(WIP). 23 | 24 | tile.neenergistics.pattern_interface.name=Pattern Interface(WIP) 25 | 26 | neenergistics.category=Not Enough Energistics -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/lang/zh_cn.lang: -------------------------------------------------------------------------------- 1 | jei.tooltip.nee.helper.crafting.text1=点击来请求缺失的物品。 2 | jei.tooltip.nee.helper.crafting.text2=点击来请求配方成品。 3 | jei.tooltip.nee.helper.pattern=自动合成已可用 4 | jei.tooltip.nee.helper.craftable=可合成 5 | jei.tooltip.nee.helper.waiting=正在匹配配方... 6 | 7 | key.neenergistics.crafting.helper.preview=合成帮助 8 | key.neenergistics.crafting.helper.noPreview=合成帮助(无预览) 9 | key.neenergistics.recipe.ingredient.change=更改材料 10 | key.neenergistics.stack.count.change=更改物品数量 11 | 12 | gui.neenergistics.button.title.combination=合并同类物品 13 | gui.neenergistics.button.tooltip.combination=当前模式: %s 14 | gui.neenergistics.button.name.enabled=开启 15 | gui.neenergistics.button.name.disabled=关闭 16 | gui.neenergistics.button.name.whitelist=白名单 17 | gui.neenergistics.button.title.remove=删除 18 | gui.neenergistics.button.tooltip.remove=删除并取消当前配方 19 | gui.neenergistics.button.tooltip.preference.remove=从偏好列表中删除选中的物品 20 | gui.neenergistics.button.tooltip.preference.add=将选中的物品添加到偏好列表中 21 | gui.neenergistics.button.tooltip.preference.text1=使用鼠标中键选中物品。 22 | gui.neenergistics.button.tooltip.preference.open=打开偏好列表(WIP)。 23 | 24 | tile.neenergistics.pattern_interface.name=样板接口(WIP) 25 | 26 | neenergistics.category=Not Enough Energistics 27 | 28 | -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/meta/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/meta/logo.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/models/block/pattern_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube", 3 | "textures": { 4 | "particle": "neenergistics:blocks/pattern_interface", 5 | "down": "neenergistics:blocks/pattern_interface_surface", 6 | "up": "neenergistics:blocks/pattern_interface_surface", 7 | "north": "neenergistics:blocks/pattern_interface_side", 8 | "east": "neenergistics:blocks/pattern_interface_side", 9 | "south": "neenergistics:blocks/pattern_interface_side", 10 | "west": "neenergistics:blocks/pattern_interface_side" 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/models/item/pattern_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "neenergistics:block/pattern_interface" 3 | } -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/recipes/pattern_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "forge:ore_shaped", 3 | "pattern": [ 4 | "aba", 5 | "cdc", 6 | "eee" 7 | ], 8 | "key": { 9 | "a": { 10 | "item": "appliedenergistics2:material", 11 | "data": 52 12 | }, 13 | "b": { 14 | "item": "appliedenergistics2:part", 15 | "data": 340 16 | }, 17 | "c": { 18 | "item": "appliedenergistics2:interface" 19 | }, 20 | "d": { 21 | "item": "appliedenergistics2:crafting_monitor" 22 | }, 23 | "e": { 24 | "item": "appliedenergistics2:part", 25 | "data": 56 26 | } 27 | }, 28 | "result": { 29 | "item": "neenergistics:pattern_interface" 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/blocks/pattern_interface_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/blocks/pattern_interface_side.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/blocks/pattern_interface_surface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/blocks/pattern_interface_surface.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/arrow_down.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/arrow_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/arrow_up.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/ingredient_switcher_widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/ingredient_switcher_widget.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/pattern_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/pattern_interface.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/quickly_pusher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/quickly_pusher_background.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/quickly_pusher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/quickly_pusher_icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/search_ingredients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/search_ingredients.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/search_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/search_interface.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/states.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/super_pusher_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vfyjxf/NotEnoughEnergistics/c5726ebfaa89a87fc07b256979fb47afa5c6a8c7/src/main/resources/assets/neenergistics/textures/gui/super_pusher_icon.png -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [{ 2 | "modid": "${mod_id}", 3 | "name": "${mod_name}", 4 | "description": "${mod_description}", 5 | "version": "${mod_version}", 6 | "mcversion": "${mc_version}", 7 | "url": "", 8 | "updateUrl": "", 9 | "authorList": ["${mod_author}"], 10 | "credits": "${mod_credits}", 11 | "logoFile": "${mod_logo}", 12 | "screenshots": [], 13 | "dependencies": [] 14 | }] -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "", 4 | "pack_format": 3 5 | } 6 | } 7 | --------------------------------------------------------------------------------