├── .git-blame-ignore-revs ├── CODEOWNERS ├── src └── main │ ├── resources │ ├── pack.mcmeta │ ├── assets │ │ └── neenergistics │ │ │ ├── meta │ │ │ └── logo.png │ │ │ ├── textures │ │ │ ├── gui │ │ │ │ ├── states.png │ │ │ │ └── pattern_interface.png │ │ │ └── blocks │ │ │ │ └── pattern_interface.png │ │ │ └── lang │ │ │ ├── ru_RU.lang │ │ │ ├── zh_CN.lang │ │ │ └── en_US.lang │ ├── mcmod.info │ └── META-INF │ │ └── neenergistics_at.cfg │ └── java │ └── com │ └── github │ └── vfyjxf │ └── nee │ ├── utils │ ├── ModIDs.java │ ├── StackProcessor.java │ ├── Ingredient.java │ ├── GuiUtils.java │ └── IngredientTracker.java │ ├── proxy │ ├── ServerProxy.java │ ├── ClientProxy.java │ └── CommonProxy.java │ ├── config │ ├── ItemCombination.java │ ├── NEEConfigGuiFactory.java │ └── NEEConfigGui.java │ ├── processor │ ├── IRecipeProcessor.java │ ├── AppengRecipeProcessor.java │ ├── AvaritiaRecipeProcessor.java │ ├── VanillaRecipeProcessor.java │ ├── BloodMagicRecipeProcessor.java │ ├── ForestryRecipeProcessor.java │ ├── BotaniaRecipeProcessor.java │ ├── TCNEIPluginRecipeProcessor.java │ ├── GoodGeneratorRecipeProcessor.java │ ├── ICRecipeProcessor.java │ ├── BuildCraftRecipeProcessor.java │ ├── MekanismRecipeProcessor.java │ ├── EnderIORecipeProcessor.java │ ├── ImmersiveEngineeringRecipeProcessor.java │ ├── GTPPRecipeProcessor.java │ ├── GregTech6RecipeProcessor.java │ ├── ThermalExpansionRecipeProcessor.java │ ├── RecipeProcessor.java │ └── GregTech5RecipeProcessor.java │ ├── network │ ├── packet │ │ ├── PacketOpenGui.java │ │ ├── PacketValueConfigClient.java │ │ ├── PacketSlotStackChange.java │ │ ├── PacketStackCountChange.java │ │ ├── PacketValueConfigServer.java │ │ ├── PacketExtremeRecipe.java │ │ ├── PacketArcaneRecipe.java │ │ ├── PacketNEIBookmark.java │ │ └── PacketNEIPatternRecipe.java │ ├── NEEGuiHandler.java │ └── NEENetworkHandler.java │ ├── nei │ ├── NEETerminalBookmarkContainerHandler.java │ ├── NEEExtremeAutoCrafterHandler.java │ ├── NEETerminalOverlayButton.java │ ├── NEEKnowledgeInscriberHandler.java │ └── NEECraftingTerminalHandler.java │ ├── block │ └── BlockPatternInterface.java │ ├── client │ └── gui │ │ ├── widgets │ │ ├── GuiImgButtonRemove.java │ │ └── GuiImgButtonEnableCombination.java │ │ └── GuiPatternInterface.java │ ├── NotEnoughEnergistics.java │ ├── container │ └── ContainerPatternInterface.java │ ├── NEECommands.java │ └── NEINeeConfig.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── repositories.gradle ├── .github └── workflows │ ├── release-tags.yml │ └── build-and-test.yml ├── settings.gradle ├── .gitignore ├── LICENSE ├── .gitattributes ├── dependencies.gradle ├── README_CN.md ├── README.md ├── gradlew.bat └── gradlew /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Ignore spotlessApply reformat 2 | 42e704a5d8f47b22dde1dd5b8ea8869087cbd065 3 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Any Github changes require admin approval 2 | /.github/** @GTNewHorizons/admin 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "pack_format": 1, 4 | "description": "" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GTNewHorizons/NotEnoughEnergistics/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /repositories.gradle: -------------------------------------------------------------------------------- 1 | // Add any additional repositories for your dependencies here 2 | 3 | repositories { 4 | mavenLocal() 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/meta/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GTNewHorizons/NotEnoughEnergistics/HEAD/src/main/resources/assets/neenergistics/meta/logo.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GTNewHorizons/NotEnoughEnergistics/HEAD/src/main/resources/assets/neenergistics/textures/gui/states.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/gui/pattern_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GTNewHorizons/NotEnoughEnergistics/HEAD/src/main/resources/assets/neenergistics/textures/gui/pattern_interface.png -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/textures/blocks/pattern_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GTNewHorizons/NotEnoughEnergistics/HEAD/src/main/resources/assets/neenergistics/textures/blocks/pattern_interface.png -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/ModIDs.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | public class ModIDs { 4 | 5 | public static final String WCT = "ae2wct"; 6 | public static final String FC = "ae2fc"; 7 | public static final String ThE = "thaumicenergistics"; 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.github/workflows/release-tags.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Release tagged build 3 | 4 | on: 5 | push: 6 | tags: [ '*' ] 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | release-tags: 13 | uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master 14 | secrets: inherit 15 | -------------------------------------------------------------------------------- /.github/workflows/build-and-test.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Build and test 3 | 4 | on: 5 | pull_request: 6 | branches: [ master, main ] 7 | push: 8 | branches: [ master, main ] 9 | 10 | jobs: 11 | build-and-test: 12 | uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/ServerProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import cpw.mods.fml.common.event.FMLInitializationEvent; 4 | 5 | public class ServerProxy extends CommonProxy { 6 | 7 | @Override 8 | public void init(FMLInitializationEvent event) { 9 | super.init(event); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/ItemCombination.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import java.util.Locale; 4 | 5 | import net.minecraft.client.resources.I18n; 6 | 7 | public enum ItemCombination { 8 | 9 | DISABLED, 10 | ENABLED, 11 | WHITELIST; 12 | 13 | public String getLocalName() { 14 | return I18n.format("gui.neenergistics.button.name" + "." + this.name().toLowerCase(Locale.ROOT)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/lang/ru_RU.lang: -------------------------------------------------------------------------------- 1 | neenergistics.gui.tooltip.crafting.preview=Запоросить отсутсвующие предметы 2 | neenergistics.gui.tooltip.crafting.nopreview=Запоросить отсутсвующие предметы (без превью) 3 | 4 | nei.options.keys.nee=NotEnoughEnergistics 5 | nei.options.keys.nee.count=Изменить кол-во 6 | nei.options.keys.nee.ingredient=Выбрать ингредиент 7 | nei.options.keys.nee.preview=Помощь по крафту 8 | nei.options.keys.nee.nopreview=Помощь по крафту(без превью) -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "${modId}", 4 | "name": "${modName}", 5 | "description": "This mod replaces AE2's default NEI integration for the Pattern Terminal.", 6 | "version": "${modVersion}", 7 | "mcversion": "${minecraftVersion}", 8 | "url": "", 9 | "updateUrl": "", 10 | "authorList": [ 11 | "vfyjxf" 12 | ], 13 | "credits": "Thanks TheRealp455w0rd", 14 | "logoFile": "assets/neenergistics/meta/logo.png", 15 | "screenshots": [], 16 | "dependencies": [] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /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 | public net.minecraft.client.gui.inventory.GuiContainer func_146975_c(II)Lnet/minecraft/inventory/Slot; #getSlotAtPositionv 5 | public net.minecraft.client.gui.GuiScreen func_146283_a(Ljava/util/List;II)V #drawHoveringText 6 | public net.minecraft.client.gui.inventory.GuiContainer field_147006_u # theSlot -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | 2 | pluginManagement { 3 | repositories { 4 | maven { 5 | // RetroFuturaGradle 6 | name "GTNH Maven" 7 | url "https://nexus.gtnewhorizons.com/repository/public/" 8 | mavenContent { 9 | includeGroup("com.gtnewhorizons") 10 | includeGroupByRegex("com\\.gtnewhorizons\\..+") 11 | } 12 | } 13 | gradlePluginPortal() 14 | mavenCentral() 15 | mavenLocal() 16 | } 17 | } 18 | 19 | plugins { 20 | id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.48' 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .settings 3 | /.idea/ 4 | /.vscode/ 5 | /run/ 6 | /build/ 7 | /eclipse/ 8 | .classpath 9 | .project 10 | /bin/ 11 | /config/ 12 | /crash-reports/ 13 | /logs/ 14 | options.txt 15 | /saves/ 16 | usernamecache.json 17 | banned-ips.json 18 | banned-players.json 19 | eula.txt 20 | ops.json 21 | server.properties 22 | servers.dat 23 | usercache.json 24 | whitelist.json 25 | /out/ 26 | *.iml 27 | *.ipr 28 | *.iws 29 | src/main/resources/mixins.*([!.]).json 30 | *.bat 31 | *.DS_Store 32 | !gradlew.bat 33 | .factorypath 34 | addon.local.gradle 35 | addon.local.gradle.kts 36 | addon.late.local.gradle 37 | addon.late.local.gradle.kts 38 | layout.json -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/lang/zh_CN.lang: -------------------------------------------------------------------------------- 1 | nei.options.keys.nee=NotEnoughEnergistics 2 | nei.options.keys.nee.count=修改物品数量 3 | nei.options.keys.nee.ingredient=选择材料 4 | nei.options.keys.nee.preview=合成帮助 5 | nei.options.keys.nee.nopreview=合成帮助(无预览) 6 | 7 | gui.neenergistics.button.title.combination=合并同类物品 8 | gui.neenergistics.button.tooltip.combination=当前模式: %s 9 | gui.neenergistics.button.name.enabled=开启 10 | gui.neenergistics.button.name.disabled=关闭 11 | gui.neenergistics.button.name.whitelist=白名单 12 | gui.neenergistics.button.title.remove=删除 13 | gui.neenergistics.button.tooltip.remove=删除并取消当前配方 14 | tile.neenergistics.pattern_interface.name=样板接口 -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/NEEConfigGuiFactory.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import java.util.Set; 4 | 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.gui.GuiScreen; 7 | 8 | import cpw.mods.fml.client.IModGuiFactory; 9 | 10 | public class NEEConfigGuiFactory implements IModGuiFactory { 11 | 12 | @Override 13 | public void initialize(Minecraft minecraftInstance) {} 14 | 15 | @Override 16 | public Class mainConfigGuiClass() { 17 | return NEEConfigGui.class; 18 | } 19 | 20 | @Override 21 | public Set runtimeGuiCategories() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/IRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import javax.annotation.Nonnull; 8 | 9 | import codechicken.nei.PositionedStack; 10 | import codechicken.nei.recipe.IRecipeHandler; 11 | 12 | /** 13 | * @author vfyjxf 14 | */ 15 | public interface IRecipeProcessor { 16 | 17 | @Nonnull 18 | default Set getAllOverlayIdentifier() { 19 | return Collections.emptySet(); 20 | } 21 | 22 | @Nonnull 23 | String getRecipeProcessorId(); 24 | 25 | @Nonnull 26 | List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier); 27 | 28 | @Nonnull 29 | List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier); 30 | 31 | default boolean mergeStacks(IRecipeHandler recipe, int recipeIndex, String identifier) { 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/config/NEEConfigGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.config; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import net.minecraft.client.gui.GuiScreen; 7 | import net.minecraftforge.common.config.ConfigElement; 8 | 9 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 10 | 11 | import cpw.mods.fml.client.config.GuiConfig; 12 | import cpw.mods.fml.client.config.IConfigElement; 13 | 14 | public class NEEConfigGui extends GuiConfig { 15 | 16 | public NEEConfigGui(GuiScreen parentScreen) { 17 | super(parentScreen, getConfigElements(), NotEnoughEnergistics.MODID, false, false, NotEnoughEnergistics.NAME); 18 | } 19 | 20 | private static List getConfigElements() { 21 | List list = new ArrayList<>(); 22 | for (String name : NEEConfig.config.getCategoryNames()) { 23 | list.add(new ConfigElement(NEEConfig.config.getCategory(name))); 24 | } 25 | return list; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/resources/assets/neenergistics/lang/en_US.lang: -------------------------------------------------------------------------------- 1 | neenergistics.gui.tooltip.crafting.preview=Request missing items 2 | neenergistics.gui.tooltip.crafting.preview.result=Request the recipe result 3 | neenergistics.gui.tooltip.crafting.nopreview=Request missing items (No Preview) 4 | neenergistics.gui.tooltip.crafting.nopreview.result=Request the recipe result (No Preview) 5 | 6 | neenergistics.gui.tooltip.ingredient.permutation=Change Item 7 | neenergistics.gui.tooltip.ingredient.count=Change Count 8 | 9 | nei.options.keys.nee=NotEnoughEnergistics 10 | nei.options.keys.nee.count=Change Item Count 11 | nei.options.keys.nee.ingredient=Choose ingredient 12 | nei.options.keys.nee.preview=Crafting Help 13 | nei.options.keys.nee.nopreview=Crafting Help(No Preview) 14 | 15 | gui.neenergistics.button.title.combination=Combine Items 16 | gui.neenergistics.button.tooltip.combination=Current Mode: %s 17 | gui.neenergistics.button.name.enabled=Enabled 18 | gui.neenergistics.button.name.disabled=Disabled 19 | gui.neenergistics.button.name.whitelist=Whitelist 20 | gui.neenergistics.button.title.remove=Remove 21 | gui.neenergistics.button.tooltip.remove=Remove and cancel the current recipe 22 | 23 | tile.neenergistics.pattern_interface.name=Pattern Interface 24 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/StackProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import net.minecraft.item.Item; 4 | import net.minecraft.item.ItemStack; 5 | 6 | public class StackProcessor { 7 | 8 | public String modid; 9 | public String name; 10 | public String meta; 11 | public String nbt; 12 | public ItemStack itemStack; 13 | public Item item; 14 | public String recipeProcessor; 15 | public String identifier; 16 | 17 | public StackProcessor(String modid, String name, String meta, String nbt) { 18 | this.modid = modid; 19 | this.name = name; 20 | this.meta = meta; 21 | this.nbt = nbt; 22 | } 23 | 24 | public StackProcessor(String modid, String name, String meta) { 25 | this.modid = modid; 26 | this.name = name; 27 | this.meta = meta; 28 | } 29 | 30 | public StackProcessor(String modid, String name) { 31 | this.modid = modid; 32 | this.name = name; 33 | } 34 | 35 | public StackProcessor(ItemStack itemStack, Item item, String recipeProcessor, String identifier) { 36 | this.itemStack = itemStack; 37 | this.item = item; 38 | this.recipeProcessor = recipeProcessor; 39 | this.identifier = identifier; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.[jJ][aA][rR] binary 4 | 5 | *.[pP][nN][gG] binary 6 | *.[jJ][pP][gG] binary 7 | *.[jJ][pP][eE][gG] binary 8 | *.[gG][iI][fF] binary 9 | *.[tT][iI][fF] binary 10 | *.[tT][iI][fF][fF] binary 11 | *.[iI][cC][oO] binary 12 | *.[sS][vV][gG] text 13 | *.[eE][pP][sS] binary 14 | *.[xX][cC][fF] binary 15 | 16 | *.[kK][aA][rR] binary 17 | *.[mM]4[aA] binary 18 | *.[mM][iI][dD] binary 19 | *.[mM][iI][dD][iI] binary 20 | *.[mM][pP]3 binary 21 | *.[oO][gG][gG] binary 22 | *.[rR][aA] binary 23 | 24 | *.7[zZ] binary 25 | *.[gG][zZ] binary 26 | *.[tT][aA][rR] binary 27 | *.[tT][gG][zZ] binary 28 | *.[zZ][iI][pP] binary 29 | 30 | *.[tT][cC][nN] binary 31 | *.[sS][oO] binary 32 | *.[dD][lL][lL] binary 33 | *.[dD][yY][lL][iI][bB] binary 34 | *.[pP][sS][dD] binary 35 | *.[tT][tT][fF] binary 36 | *.[oO][tT][fF] binary 37 | 38 | *.[pP][aA][tT][cC][hH] -text 39 | 40 | *.[bB][aA][tT] text eol=crlf 41 | *.[cC][mM][dD] text eol=crlf 42 | *.[pP][sS]1 text eol=crlf 43 | 44 | *[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary 45 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/ClientProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import net.minecraftforge.client.ClientCommandHandler; 4 | import net.minecraftforge.common.MinecraftForge; 5 | 6 | import com.github.vfyjxf.nee.NEECommands; 7 | import com.github.vfyjxf.nee.client.GuiEventHandler; 8 | import com.github.vfyjxf.nee.nei.NEECraftingPreviewHandler; 9 | import com.github.vfyjxf.nee.nei.NEECraftingTerminalHandler; 10 | import com.github.vfyjxf.nee.nei.NEEExtremeAutoCrafterHandler; 11 | import com.github.vfyjxf.nee.nei.NEEKnowledgeInscriberHandler; 12 | import com.github.vfyjxf.nee.nei.NEEPatternTerminalHandler; 13 | 14 | import cpw.mods.fml.common.FMLCommonHandler; 15 | import cpw.mods.fml.common.event.FMLInitializationEvent; 16 | 17 | public class ClientProxy extends CommonProxy { 18 | 19 | @Override 20 | public void init(FMLInitializationEvent event) { 21 | super.init(event); 22 | ClientCommandHandler.instance.registerCommand(new NEECommands()); 23 | FMLCommonHandler.instance().bus().register(GuiEventHandler.instance); 24 | MinecraftForge.EVENT_BUS.register(GuiEventHandler.instance); 25 | MinecraftForge.EVENT_BUS.register(NEECraftingTerminalHandler.instance); 26 | MinecraftForge.EVENT_BUS.register(NEEPatternTerminalHandler.instance); 27 | MinecraftForge.EVENT_BUS.register(NEEExtremeAutoCrafterHandler.instance); 28 | MinecraftForge.EVENT_BUS.register(NEEKnowledgeInscriberHandler.instance); 29 | MinecraftForge.EVENT_BUS.register(NEECraftingPreviewHandler.instance); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/AppengRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | public class AppengRecipeProcessor implements IRecipeProcessor { 15 | 16 | @Nonnull 17 | @Override 18 | public Set getAllOverlayIdentifier() { 19 | return new HashSet<>(Arrays.asList("inscriber", "grindstone")); 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public String getRecipeProcessorId() { 25 | return "appliedenergistics2"; 26 | } 27 | 28 | @Nonnull 29 | @Override 30 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 31 | List recipeInputs = new ArrayList<>(); 32 | if (this.getAllOverlayIdentifier().contains(identifier)) { 33 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 34 | } 35 | return recipeInputs; 36 | } 37 | 38 | @Nonnull 39 | @Override 40 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 41 | List recipeOutputs = new ArrayList<>(); 42 | if (this.getAllOverlayIdentifier().contains(identifier)) { 43 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 44 | } 45 | return recipeOutputs; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/AvaritiaRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | public class AvaritiaRecipeProcessor implements IRecipeProcessor { 15 | 16 | @Nonnull 17 | @Override 18 | public Set getAllOverlayIdentifier() { 19 | return new HashSet<>(Arrays.asList("extreme", "extreme_compression")); 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public String getRecipeProcessorId() { 25 | return "Avaritia"; 26 | } 27 | 28 | @Nonnull 29 | @Override 30 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 31 | List recipeInputs = new ArrayList<>(); 32 | if (this.getAllOverlayIdentifier().contains(identifier)) { 33 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 34 | return recipeInputs; 35 | } 36 | return recipeInputs; 37 | } 38 | 39 | @Nonnull 40 | @Override 41 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 42 | List recipeOutput = new ArrayList<>(); 43 | if (this.getAllOverlayIdentifier().contains(identifier)) { 44 | recipeOutput.add(recipe.getResultStack(recipeIndex)); 45 | return recipeOutput; 46 | } 47 | return recipeOutput; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dependencies.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | 3 | api("com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta-754-GTNH:dev") 4 | api("com.github.GTNewHorizons:NotEnoughItems:2.8.40-GTNH:dev") 5 | api('com.github.GTNewHorizons:CodeChickenCore:1.4.10:dev') 6 | 7 | implementation("com.github.GTNewHorizons:Baubles-Expanded:2.2.4-GTNH:dev") 8 | implementation("com.github.GTNewHorizons:WirelessCraftingTerminal:1.12.10:dev") 9 | implementation("com.github.GTNewHorizons:AE2FluidCraft-Rework:1.5.30-gtnh:dev") 10 | 11 | compileOnly("com.github.GTNewHorizons:GT5-Unofficial:5.09.52.138:dev") { transitive = false } 12 | compileOnly("com.github.GTNewHorizons:Avaritia:1.78:dev") { transitive = false } 13 | compileOnly("com.github.GTNewHorizons:Avaritiaddons:1.9.3-GTNH:dev") { transitive = false } 14 | compileOnly("com.github.GTNewHorizons:BuildCraftCompat:7.1.18:dev") { transitive = false } 15 | compileOnly('com.github.GTNewHorizons:EnderIO:2.10.8:dev') {transitive=false} 16 | compileOnly("com.github.GTNewHorizons:ForestryMC:4.11.2:dev") { transitive = false } 17 | compileOnly("com.github.GTNewHorizons:GTplusplus:1.12.11:dev") { transitive = false } 18 | compileOnly("com.github.GTNewHorizons:ThaumicEnergistics:1.7.16-GTNH:dev") { transitive = false } 19 | compileOnly("com.github.GTNewHorizons:Botania:1.13.6-GTNH:dev") { transitive = false } 20 | compileOnly("com.gregoriust.gregtech:gregtech_1.7.10:6.14.23:dev") { transitive = false } 21 | compileOnly("curse.maven:thaumcraft-nei-plugin-225095:2241913") { transitive = false } 22 | compileOnly("curse.maven:thermal-expansion-69163:2388759") { transitive = false } 23 | 24 | runtimeOnly("curse.maven:cofh-core-69162:2388751") 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/VanillaRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class VanillaRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public Set getAllOverlayIdentifier() { 22 | return new HashSet<>(Arrays.asList("brewing", "smelting", "fuel")); 23 | } 24 | 25 | @Nonnull 26 | @Override 27 | public String getRecipeProcessorId() { 28 | return "Vanilla"; 29 | } 30 | 31 | @Nonnull 32 | @Override 33 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 34 | List recipeInputs = new ArrayList<>(); 35 | if (this.getAllOverlayIdentifier().contains(identifier)) { 36 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 37 | recipeInputs.addAll(recipe.getOtherStacks(recipeIndex)); 38 | } 39 | return recipeInputs; 40 | } 41 | 42 | @Nonnull 43 | @Override 44 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 45 | List recipeOutput = new ArrayList<>(); 46 | if (this.getAllOverlayIdentifier().contains(identifier)) { 47 | recipeOutput.add(recipe.getResultStack(recipeIndex)); 48 | return recipeOutput; 49 | } 50 | return recipeOutput; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # Not Enough Energistics 2 | 3 | [![Downloads](https://cf.way2muchnoise.eu/full_515565_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/not-enough-energistics) ![MCVsrsion](https://cf.way2muchnoise.eu/versions/515565.svg) 4 | 5 | ---- 6 | 7 | NotEnoughEnergistics 是[Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 的逆向移植版本 8 | 9 | 它替换了AE2默认的NEI集成, 默认情况下ae只能识别玩家身上或者网络里的存储物品。 10 | 11 | 本MOD允许你直接从nei获取配方并写入样板终端(shift点击[?]按钮) 12 | 13 | ## Features 14 | 15 | - 根据配方自动切换样板终端的模式 16 | - 如果一个物品输出为概率输出,那么NEE不会将它写入样板终端 17 | - 在处理模式中合并同类物品 18 | - 支持增广样板终端(16 -> 4模式) 19 | - 允许你设置转换黑名单和转换优先名单,如对应物品在里面,那么他们将不会被转移/优先被转移 20 | - 允许你设置mod优先级列表,优先使用该mod的物品 21 | - 你可以使用ctrl + 鼠标滚轮来修改样板的输入/输出数量 22 | - 你可以使用shift + 鼠标滚轮来选择材料 23 | - 你可以使用ctrl + 点击[?]按钮来在合成终端中请求有配方的缺失材料(alt + 点击[?]来跳过预览) 24 | 25 | ## 当前支持的Mod列表: 26 | 27 | - [x] AppliedEnergistics2 28 | - [x] Vanilla 29 | - [x] GregTech5 30 | - [x] GregTech6 31 | - [x] IndustrialCraft2 32 | - [x] Avaritia 33 | - [x] EnderIO 34 | - [x] Forestry(不支持发酵机和蒸馏器,因为它们没有物品输出) 35 | - [x] Thaumcraft NEI Plugin 36 | - [x] Thaumic Energistics(允许你从NEI转移奥术合成台配方到知识记录仪,需要Thaumcraft NEI Plugin) 37 | - [x] ThermalExpansion 38 | - [x] ImmersiveEngineering 39 | - [x] Mekanism 40 | - [x] BloodMagic 41 | - [x] BuildCraft 42 | - [x] Avaritiaddons(允许你从nei转移终极工作台配方到梦魇工作台) 43 | - [x] GT++ 44 | 45 | 如果你想要别的Mod的支持,请看[RecipeProcessor](./src/main/java/com/github/vfyjxf/nee/processor/RecipeProcessor.java) 或者[模组支持处理区](https://github.com/vfyjxf/NotEnoughEnergistics/issues/1) 46 | 47 | ## TODO 48 | - [x] 添加转换黑名单,使在黑名单里的物品不会被转移到样板终端 49 | - [x] 添加优先转换列表,在优先转换列表的物品会替换配方里的同类物品 50 | - [x] 在有多个同类物品的情况下,合并同类物品 51 | 52 | ## Credits 53 | 感谢 TheRealp455w0rd 和他的 [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketOpenGui.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.tileentity.TileEntity; 5 | 6 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 7 | 8 | import appeng.container.AEBaseContainer; 9 | import appeng.container.ContainerOpenContext; 10 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 11 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 12 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 13 | import io.netty.buffer.ByteBuf; 14 | 15 | public class PacketOpenGui implements IMessage { 16 | 17 | private int guiId; 18 | 19 | public PacketOpenGui() {} 20 | 21 | public PacketOpenGui(int guiId) { 22 | this.guiId = guiId; 23 | } 24 | 25 | @Override 26 | public void fromBytes(ByteBuf buf) { 27 | this.guiId = buf.readInt(); 28 | } 29 | 30 | @Override 31 | public void toBytes(ByteBuf buf) { 32 | buf.writeInt(this.guiId); 33 | } 34 | 35 | public static final class Handler implements IMessageHandler { 36 | 37 | @Override 38 | public IMessage onMessage(PacketOpenGui message, MessageContext ctx) { 39 | final EntityPlayerMP player = ctx.getServerHandler().playerEntity; 40 | 41 | if (player.openContainer instanceof AEBaseContainer baseContainer) { 42 | final ContainerOpenContext context = baseContainer.getOpenContext(); 43 | if (context != null) { 44 | final TileEntity tile = context.getTile(); 45 | NEEGuiHandler.openGui(player, message.guiId, tile, context.getSide()); 46 | } 47 | } 48 | 49 | return null; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/BloodMagicRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class BloodMagicRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public Set getAllOverlayIdentifier() { 22 | return new HashSet<>( 23 | Arrays.asList("altarrecipes", "alchemicalwizardry.alchemy", "alchemicalwizardry.bindingritual")); 24 | } 25 | 26 | @Nonnull 27 | @Override 28 | public String getRecipeProcessorId() { 29 | return "BloodMagic"; 30 | } 31 | 32 | @Nonnull 33 | @Override 34 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 35 | List recipeInputs = new ArrayList<>(); 36 | if (this.getAllOverlayIdentifier().contains(identifier)) { 37 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 38 | return recipeInputs; 39 | } 40 | return recipeInputs; 41 | } 42 | 43 | @Nonnull 44 | @Override 45 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 46 | List recipeOutputs = new ArrayList<>(); 47 | if (this.getAllOverlayIdentifier().contains(identifier)) { 48 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 49 | return recipeOutputs; 50 | } 51 | return recipeOutputs; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/nei/NEETerminalBookmarkContainerHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.nei; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | import net.minecraft.client.gui.inventory.GuiContainer; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.nbt.NBTTagCompound; 10 | 11 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 12 | import com.github.vfyjxf.nee.network.packet.PacketNEIBookmark; 13 | import com.github.vfyjxf.nee.utils.GuiUtils; 14 | 15 | import codechicken.nei.api.IBookmarkContainerHandler; 16 | 17 | public class NEETerminalBookmarkContainerHandler implements IBookmarkContainerHandler { 18 | 19 | public static final NEETerminalBookmarkContainerHandler instance = new NEETerminalBookmarkContainerHandler(); 20 | 21 | private NEETerminalBookmarkContainerHandler() {} 22 | 23 | @Override 24 | public List getStorageStacks(GuiContainer guiContainer) { 25 | return GuiUtils.getStorageStacks(guiContainer, stack -> stack.getStackSize() > 0).stream() 26 | .map(stack -> stack.getItemStack().copy()).collect(Collectors.toList()); 27 | } 28 | 29 | @Override 30 | public void pullBookmarkItemsFromContainer(GuiContainer guiContainer, ArrayList bookmarkItems) { 31 | final NBTTagCompound nbtBookmarkItems = new NBTTagCompound(); 32 | 33 | for (int i = 0; i < bookmarkItems.size(); i++) { 34 | nbtBookmarkItems.setTag("#" + i, packBookmarkItem(bookmarkItems.get(i))); 35 | } 36 | 37 | NEENetworkHandler.getInstance().sendToServer(new PacketNEIBookmark(nbtBookmarkItems)); 38 | } 39 | 40 | private NBTTagCompound packBookmarkItem(ItemStack bookmarkItem) { 41 | return bookmarkItem.writeToNBT(new NBTTagCompound()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/block/BlockPatternInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.block; 2 | 3 | import java.util.EnumSet; 4 | 5 | import net.minecraft.block.material.Material; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.item.Item; 8 | import net.minecraft.world.World; 9 | import net.minecraftforge.common.util.ForgeDirection; 10 | 11 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 12 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 13 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 14 | 15 | import appeng.block.AEBaseItemBlock; 16 | import appeng.block.AEBaseTileBlock; 17 | import appeng.core.features.AEFeature; 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); 26 | 27 | public BlockPatternInterface() { 28 | super(Material.iron); 29 | this.setTileEntity(TilePatternInterface.class); 30 | this.setFeature(EnumSet.of(AEFeature.Core)); 31 | this.setBlockName(NotEnoughEnergistics.MODID + "." + "pattern_interface"); 32 | this.setBlockTextureName(NotEnoughEnergistics.MODID + ":" + "pattern_interface"); 33 | } 34 | 35 | @Override 36 | public boolean onActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, 37 | float hitZ) { 38 | if (player.isSneaking()) { 39 | return false; 40 | } 41 | 42 | final TilePatternInterface tile = this.getTileEntity(world, x, y, z); 43 | if (tile != null) { 44 | if (!world.isRemote) { 45 | NEEGuiHandler.openGui(player, NEEGuiHandler.PATTERN_INTERFACE_ID, tile, ForgeDirection.UNKNOWN); 46 | } 47 | return true; 48 | } 49 | 50 | return false; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/Ingredient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | import codechicken.nei.PositionedStack; 6 | 7 | public class Ingredient { 8 | 9 | private long requireCount; 10 | private final long defaultRequireCount; 11 | private final PositionedStack ingredient; 12 | private ItemStack craftableIngredient; 13 | private long currentCount = 0; 14 | 15 | public Ingredient(PositionedStack ingredients) { 16 | this.ingredient = ingredients; 17 | this.requireCount = ingredients.items[0].stackSize; 18 | this.defaultRequireCount = ingredients.items[0].stackSize; 19 | } 20 | 21 | public PositionedStack getIngredient() { 22 | return ingredient; 23 | } 24 | 25 | public ItemStack getCraftableIngredient() { 26 | return craftableIngredient; 27 | } 28 | 29 | public void setCraftableIngredient(ItemStack craftableIngredient) { 30 | this.craftableIngredient = craftableIngredient; 31 | } 32 | 33 | public long getMissingCount() { 34 | return requireCount - currentCount; 35 | } 36 | 37 | public long getDefaultRequireCount() { 38 | return defaultRequireCount; 39 | } 40 | 41 | public long getRequireCount() { 42 | return requireCount; 43 | } 44 | 45 | public void setRequireCount(long requireCount) { 46 | this.requireCount = requireCount; 47 | } 48 | 49 | public void setCurrentCount(long currentCount) { 50 | this.currentCount = currentCount; 51 | } 52 | 53 | public boolean isCraftable() { 54 | return this.craftableIngredient != null; 55 | } 56 | 57 | public boolean requiresToCraft() { 58 | return this.getMissingCount() > 0; 59 | } 60 | 61 | public void addCount(long count) { 62 | if (currentCount + count < requireCount) { 63 | currentCount += count; 64 | } else { 65 | currentCount = requireCount; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/ForestryRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | public class ForestryRecipeProcessor implements IRecipeProcessor { 15 | 16 | @Nonnull 17 | @Override 18 | public Set getAllOverlayIdentifier() { 19 | return new HashSet<>( 20 | Arrays.asList( 21 | "forestry.bottler", 22 | "forestry.carpenter", 23 | "forestry.centrifuge", 24 | "forestry.fabricator", 25 | "forestry.fermenter", 26 | "forestry.moistener", 27 | "forestry.squeezer", 28 | "forestry.still", 29 | RecipeProcessor.NULL_IDENTIFIER)); 30 | } 31 | 32 | @Nonnull 33 | @Override 34 | public String getRecipeProcessorId() { 35 | return "Forestry"; 36 | } 37 | 38 | @Nonnull 39 | @Override 40 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 41 | List recipeInputs = new ArrayList<>(); 42 | if (this.getAllOverlayIdentifier().contains(identifier)) { 43 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 44 | } 45 | return recipeInputs; 46 | } 47 | 48 | @Nonnull 49 | @Override 50 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 51 | List recipeOutput = new ArrayList<>(); 52 | if (this.getAllOverlayIdentifier().contains(identifier)) { 53 | recipeOutput.add(recipe.getResultStack(recipeIndex)); 54 | } 55 | return recipeOutput; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/BotaniaRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import javax.annotation.Nonnull; 9 | 10 | import codechicken.nei.PositionedStack; 11 | import codechicken.nei.recipe.IRecipeHandler; 12 | import vazkii.botania.client.integration.nei.recipe.RecipeHandlerLexicaBotania; 13 | 14 | public class BotaniaRecipeProcessor implements IRecipeProcessor { 15 | 16 | @Nonnull 17 | @Override 18 | public Set getAllOverlayIdentifier() { 19 | return Collections.singleton(RecipeProcessor.NULL_IDENTIFIER); 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public String getRecipeProcessorId() { 25 | return " Botania"; 26 | } 27 | 28 | @Nonnull 29 | @Override 30 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 31 | List recipeInputs = new ArrayList<>(); 32 | if (recipe instanceof RecipeHandlerLexicaBotania) { 33 | // we don't need to get recipe from a book. 34 | // but botania doesn't provide an identifier for each recipe handler, so the button will still show. 35 | return recipeInputs; 36 | } 37 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 38 | return recipeInputs; 39 | } 40 | 41 | @Nonnull 42 | @Override 43 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 44 | List recipeOutputs = new ArrayList<>(); 45 | if (recipe instanceof RecipeHandlerLexicaBotania) { 46 | // we don't need to get recipe from a book. 47 | // but botania doesn't provide an identifier for each recipe handler, so the button will still show. 48 | return recipeOutputs; 49 | } 50 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 51 | return recipeOutputs; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/TCNEIPluginRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import com.djgiannuzz.thaumcraftneiplugin.items.ItemAspect; 12 | 13 | import codechicken.nei.PositionedStack; 14 | import codechicken.nei.recipe.IRecipeHandler; 15 | 16 | /** 17 | * @author vfyjxf 18 | */ 19 | public class TCNEIPluginRecipeProcessor implements IRecipeProcessor { 20 | 21 | @Nonnull 22 | @Override 23 | public Set getAllOverlayIdentifier() { 24 | return new HashSet<>( 25 | Arrays.asList( 26 | "arcaneshapedrecipes", 27 | "arcaneshapelessrecipes", 28 | "aspectsRecipe", 29 | "cruciblerecipe", 30 | "infusionCrafting")); 31 | } 32 | 33 | @Nonnull 34 | @Override 35 | public String getRecipeProcessorId() { 36 | return "TCNEIPlugin"; 37 | } 38 | 39 | @Nonnull 40 | @Override 41 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 42 | List recipeInputs = new ArrayList<>(); 43 | if (this.getAllOverlayIdentifier().contains(identifier)) { 44 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 45 | recipeInputs.removeIf(positionedStack -> positionedStack.item.getItem() instanceof ItemAspect); 46 | return recipeInputs; 47 | } 48 | return recipeInputs; 49 | } 50 | 51 | @Nonnull 52 | @Override 53 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 54 | List recipeOutputs = new ArrayList<>(); 55 | if (this.getAllOverlayIdentifier().contains(identifier)) { 56 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 57 | return recipeOutputs; 58 | } 59 | return recipeOutputs; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/GoodGeneratorRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | public class GoodGeneratorRecipeProcessor implements IRecipeProcessor { 15 | 16 | @Nonnull 17 | @Override 18 | public Set getAllOverlayIdentifier() { 19 | return new HashSet<>(Arrays.asList("gg.recipe.neutron_activator", "gg.recipe.precise_assembler")); 20 | } 21 | 22 | @Nonnull 23 | @Override 24 | public String getRecipeProcessorId() { 25 | return "Good Generator"; 26 | } 27 | 28 | @Nonnull 29 | @Override 30 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 31 | List recipeInputs = new ArrayList<>(); 32 | if (this.getAllOverlayIdentifier().contains(identifier)) { 33 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 34 | recipeInputs.removeIf( 35 | positionedStack -> GregTech5RecipeProcessor.getFluidFromDisplayStack(positionedStack.items[0]) 36 | != null || positionedStack.item.stackSize == 0); 37 | return recipeInputs; 38 | } 39 | return recipeInputs; 40 | } 41 | 42 | @Nonnull 43 | @Override 44 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 45 | List recipeOutputs = new ArrayList<>(); 46 | if (this.getAllOverlayIdentifier().contains(identifier)) { 47 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 48 | recipeOutputs.removeIf( 49 | positionedStack -> GregTech5RecipeProcessor.getFluidFromDisplayStack(positionedStack.items[0]) 50 | != null); 51 | return recipeOutputs; 52 | } 53 | return recipeOutputs; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/ICRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class ICRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public Set getAllOverlayIdentifier() { 22 | return new HashSet<>( 23 | Arrays.asList( 24 | "blastfurnace", 25 | "BlockCutter", 26 | "centrifuge", 27 | "compressor", 28 | "extractor", 29 | "fluidcanner", 30 | "macerator", 31 | "metalformer", 32 | "oreWashing", 33 | "solidcanner")); 34 | } 35 | 36 | @Nonnull 37 | @Override 38 | public String getRecipeProcessorId() { 39 | return "IC2"; 40 | } 41 | 42 | @Nonnull 43 | @Override 44 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 45 | List recipeInputs = new ArrayList<>(); 46 | if (this.getAllOverlayIdentifier().contains(identifier)) { 47 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 48 | return recipeInputs; 49 | } 50 | return recipeInputs; 51 | } 52 | 53 | @Nonnull 54 | @Override 55 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 56 | List recipeOutputs = new ArrayList<>(); 57 | if (this.getAllOverlayIdentifier().contains(identifier)) { 58 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 59 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 60 | return recipeOutputs; 61 | } 62 | return recipeOutputs; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/GuiImgButtonRemove.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.GuiButton; 5 | import net.minecraft.client.resources.I18n; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | import org.lwjgl.opengl.GL11; 9 | 10 | import appeng.client.gui.widgets.ITooltip; 11 | 12 | public class GuiImgButtonRemove extends GuiButton implements ITooltip { 13 | 14 | public GuiImgButtonRemove(int x, int y) { 15 | super(0, x, y, ""); 16 | this.width = 8; 17 | this.height = 8; 18 | } 19 | 20 | @Override 21 | public void drawButton(Minecraft mc, int mouseX, int mouseY) { 22 | if (this.visible) { 23 | 24 | GL11.glPushMatrix(); 25 | GL11.glTranslatef(this.xPosition, this.yPosition, 0.0F); 26 | GL11.glScalef(0.5f, 0.5f, 0.5f); 27 | if (this.enabled) { 28 | GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 29 | } else { 30 | GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); 31 | } 32 | mc.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 33 | this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition 34 | && mouseX < this.xPosition + this.width 35 | && mouseY < this.yPosition + this.height; 36 | this.drawTexturedModalRect(0, 0, 0, 0, 16, 16); 37 | this.drawTexturedModalRect(0, 0, 0, 32, 16, 16); 38 | this.mouseDragged(mc, mouseX, mouseY); 39 | GL11.glPopMatrix(); 40 | } 41 | GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 42 | } 43 | 44 | @Override 45 | public String getMessage() { 46 | return I18n.format("gui.neenergistics.button.title.remove") + "\n" 47 | + I18n.format("gui.neenergistics.button.tooltip.remove"); 48 | } 49 | 50 | @Override 51 | public int xPos() { 52 | return this.xPosition; 53 | } 54 | 55 | @Override 56 | public int yPos() { 57 | return this.yPosition; 58 | } 59 | 60 | @Override 61 | public int getWidth() { 62 | return this.width; 63 | } 64 | 65 | @Override 66 | public int getHeight() { 67 | return this.height; 68 | } 69 | 70 | @Override 71 | public boolean isVisible() { 72 | return this.visible; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketValueConfigClient.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.GuiScreen; 5 | 6 | import com.github.vfyjxf.nee.nei.NEECraftingPreviewHandler; 7 | 8 | import codechicken.nei.recipe.GuiRecipe; 9 | import cpw.mods.fml.common.FMLCommonHandler; 10 | import cpw.mods.fml.common.network.ByteBufUtils; 11 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 12 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 13 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 14 | import cpw.mods.fml.relauncher.Side; 15 | import cpw.mods.fml.relauncher.SideOnly; 16 | import io.netty.buffer.ByteBuf; 17 | 18 | /** 19 | * @author vfyjxf 20 | */ 21 | public class PacketValueConfigClient implements IMessage { 22 | 23 | private String name; 24 | private boolean value; 25 | 26 | public PacketValueConfigClient() {} 27 | 28 | public PacketValueConfigClient(String name, boolean value) { 29 | this.name = name; 30 | this.value = value; 31 | } 32 | 33 | public PacketValueConfigClient(String name) { 34 | this.name = name; 35 | this.value = false; 36 | } 37 | 38 | @Override 39 | public void fromBytes(ByteBuf buf) { 40 | this.name = ByteBufUtils.readUTF8String(buf); 41 | this.value = buf.readBoolean(); 42 | } 43 | 44 | @Override 45 | public void toBytes(ByteBuf buf) { 46 | ByteBufUtils.writeUTF8String(buf, this.name); 47 | buf.writeBoolean(this.value); 48 | } 49 | 50 | public static final class Handler implements IMessageHandler { 51 | 52 | @Override 53 | public IMessage onMessage(PacketValueConfigClient message, MessageContext ctx) { 54 | if (FMLCommonHandler.instance().getEffectiveSide().isClient()) { 55 | handMessage(message, ctx); 56 | } 57 | return null; 58 | } 59 | 60 | @SideOnly(Side.CLIENT) 61 | private void handMessage(PacketValueConfigClient message, MessageContext ctx) { 62 | final GuiScreen gui = Minecraft.getMinecraft().currentScreen; 63 | 64 | if ("PatternInterface.check".equals(message.name) && gui instanceof GuiRecipe) { 65 | NEECraftingPreviewHandler.instance.setIsPatternInterfaceExists(message.value); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/NEEGuiHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network; 2 | 3 | import static com.github.vfyjxf.nee.NotEnoughEnergistics.instance; 4 | 5 | import javax.annotation.Nullable; 6 | 7 | import net.minecraft.entity.player.EntityPlayer; 8 | import net.minecraft.tileentity.TileEntity; 9 | import net.minecraft.world.World; 10 | import net.minecraftforge.common.util.ForgeDirection; 11 | 12 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 13 | import com.github.vfyjxf.nee.client.gui.GuiPatternInterface; 14 | import com.github.vfyjxf.nee.container.ContainerPatternInterface; 15 | 16 | import cpw.mods.fml.common.network.IGuiHandler; 17 | 18 | public class NEEGuiHandler implements IGuiHandler { 19 | 20 | public static final int PATTERN_INTERFACE_ID = 0; 21 | 22 | @Nullable 23 | @Override 24 | public Object getServerGuiElement(int ordinal, EntityPlayer player, World world, int x, int y, int z) { 25 | final int guiId = ordinal >> 4; 26 | 27 | if (guiId == PATTERN_INTERFACE_ID) { 28 | final TileEntity tile = world.getTileEntity(x, y, z); 29 | 30 | if (tile instanceof TilePatternInterface pattern) { 31 | return new ContainerPatternInterface(player.inventory, pattern); 32 | } 33 | 34 | } 35 | 36 | return null; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public Object getClientGuiElement(int ordinal, EntityPlayer player, World world, int x, int y, int z) { 42 | final int guiId = ordinal >> 4; 43 | 44 | if (guiId == PATTERN_INTERFACE_ID) { 45 | final TileEntity tile = world.getTileEntity(x, y, z); 46 | 47 | if (tile instanceof TilePatternInterface pattern) { 48 | return new GuiPatternInterface(player.inventory, pattern); 49 | } 50 | 51 | } 52 | 53 | return null; 54 | } 55 | 56 | public static void openGui(EntityPlayer player, int ID, TileEntity tile, ForgeDirection side) { 57 | int x = tile.xCoord; 58 | int y = tile.yCoord; 59 | int z = tile.zCoord; 60 | player.openGui(instance, ID << 4 | (side.ordinal()), tile.getWorldObj(), x, y, z); 61 | } 62 | 63 | public static void openGui(EntityPlayer player, int ID) { 64 | int x = (int) player.posX; 65 | int y = (int) player.posY; 66 | int z = (int) player.posZ; 67 | player.openGui(instance, (ID << 4), player.worldObj, x, y, z); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/BuildCraftRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import javax.annotation.Nonnull; 8 | 9 | import buildcraft.compat.nei.RecipeHandlerAssemblyTable; 10 | import buildcraft.compat.nei.RecipeHandlerIntegrationTable; 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class BuildCraftRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public String getRecipeProcessorId() { 22 | return "BuildCraft"; 23 | } 24 | 25 | @Nonnull 26 | @Override 27 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 28 | if (recipe instanceof RecipeHandlerAssemblyTable) { 29 | return handlerAssemblyTableRecipe((RecipeHandlerAssemblyTable) recipe, recipeIndex, true); 30 | } else if (recipe instanceof RecipeHandlerIntegrationTable) { 31 | return handlerIntegrationTableRecipe((RecipeHandlerIntegrationTable) recipe, recipeIndex, true); 32 | } 33 | return new ArrayList<>(); 34 | } 35 | 36 | @Nonnull 37 | @Override 38 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 39 | if (recipe instanceof RecipeHandlerAssemblyTable) { 40 | return handlerAssemblyTableRecipe((RecipeHandlerAssemblyTable) recipe, recipeIndex, false); 41 | } else if (recipe instanceof RecipeHandlerIntegrationTable) { 42 | return handlerIntegrationTableRecipe((RecipeHandlerIntegrationTable) recipe, recipeIndex, false); 43 | } 44 | return new ArrayList<>(); 45 | } 46 | 47 | private List handlerAssemblyTableRecipe(RecipeHandlerAssemblyTable recipe, int recipeIndex, 48 | boolean getInput) { 49 | return getInput ? recipe.getIngredientStacks(recipeIndex) 50 | : Collections.singletonList(recipe.getResultStack(recipeIndex)); 51 | } 52 | 53 | private List handlerIntegrationTableRecipe(RecipeHandlerIntegrationTable recipe, int recipeIndex, 54 | boolean getInput) { 55 | return getInput ? recipe.getIngredientStacks(recipeIndex) 56 | : Collections.singletonList(recipe.getResultStack(recipeIndex)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/MekanismRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class MekanismRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public Set getAllOverlayIdentifier() { 22 | return new HashSet<>( 23 | Arrays.asList( 24 | "chemicalinfuser", 25 | "chemicalinjectionchamber", 26 | "chemicaloxidizer", 27 | "chemicalwasher", 28 | "combiner", 29 | "crusher", 30 | "electrolyticseparator", 31 | "chamber", 32 | "infuser", 33 | "compressor", 34 | "prc", 35 | "precisionsawmill", 36 | "purificationchamber", 37 | "rotarycondensentrator", 38 | "solarneutron", 39 | "thermalevaporation")); 40 | } 41 | 42 | @Nonnull 43 | @Override 44 | public String getRecipeProcessorId() { 45 | return "Mekanism"; 46 | } 47 | 48 | @Nonnull 49 | @Override 50 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 51 | List recipeInputs = new ArrayList<>(); 52 | if (this.getAllOverlayIdentifier().contains(identifier)) { 53 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 54 | if (!recipe.getOtherStacks(recipeIndex).isEmpty()) { 55 | recipeInputs.addAll(recipe.getOtherStacks(recipeIndex)); 56 | } 57 | return recipeInputs; 58 | } 59 | return recipeInputs; 60 | } 61 | 62 | @Nonnull 63 | @Override 64 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 65 | List recipeOutputs = new ArrayList<>(); 66 | if (this.getAllOverlayIdentifier().contains(identifier)) { 67 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 68 | return recipeOutputs; 69 | } 70 | return recipeOutputs; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/EnderIORecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | import crazypants.enderio.nei.SagMillRecipeHandler; 14 | 15 | public class EnderIORecipeProcessor implements IRecipeProcessor { 16 | 17 | @Nonnull 18 | @Override 19 | public Set getAllOverlayIdentifier() { 20 | return new HashSet<>( 21 | Arrays.asList( 22 | "EnderIOAlloySmelter", 23 | "EIOEnchanter", 24 | "EnderIOSagMill", 25 | "EnderIOSliceAndSplice", 26 | "EnderIOSoulBinder", 27 | "EnderIOVat")); 28 | } 29 | 30 | @Nonnull 31 | @Override 32 | public String getRecipeProcessorId() { 33 | return "EnderIO"; 34 | } 35 | 36 | @Nonnull 37 | @Override 38 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 39 | List recipeInputs = new ArrayList<>(); 40 | if (this.getAllOverlayIdentifier().contains(identifier)) { 41 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 42 | return recipeInputs; 43 | } 44 | return recipeInputs; 45 | } 46 | 47 | @Nonnull 48 | @Override 49 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 50 | List recipeOutputs = new ArrayList<>(); 51 | if (identifier != null) { 52 | if (this.getAllOverlayIdentifier().contains(identifier)) { 53 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 54 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 55 | // remove output if it's chance != 1 56 | if (recipe instanceof SagMillRecipeHandler) { 57 | SagMillRecipeHandler.MillRecipe millRecipe = (SagMillRecipeHandler.MillRecipe) ((SagMillRecipeHandler) recipe).arecipes 58 | .get(recipeIndex); 59 | recipeOutputs 60 | .removeIf(positionedStack -> millRecipe.getChanceForOutput(positionedStack.item) != 1.0F); 61 | } 62 | return recipeOutputs; 63 | } 64 | } 65 | 66 | return recipeOutputs; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/ImmersiveEngineeringRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class ImmersiveEngineeringRecipeProcessor implements IRecipeProcessor { 18 | 19 | @Nonnull 20 | @Override 21 | public Set getAllOverlayIdentifier() { 22 | return new HashSet<>( 23 | Arrays.asList( 24 | "ieArcFurnace", 25 | "ieBlastFurnace", 26 | "ieBlueprintCrafting", 27 | "ieBottlingMachine", 28 | "ieCokeOven", 29 | "ieCrusher", 30 | "ieFermenter", 31 | "ieHammerCrushing", 32 | "ieMetalPress", 33 | "ieRefinery", 34 | "ieShaderBag", 35 | "ieSqueezer")); 36 | } 37 | 38 | @Nonnull 39 | @Override 40 | public String getRecipeProcessorId() { 41 | return "ImmersiveEngineering"; 42 | } 43 | 44 | @Nonnull 45 | @Override 46 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 47 | List recipeInputs = new ArrayList<>(); 48 | if (this.getAllOverlayIdentifier().contains(identifier)) { 49 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 50 | if (!("ieArcFurnace".equals(identifier) || "ieCrusher".equals(identifier) 51 | || "ieBlastFurnace".equals(identifier))) { 52 | recipeInputs.addAll(recipe.getOtherStacks(recipeIndex)); 53 | } 54 | return recipeInputs; 55 | } 56 | return recipeInputs; 57 | } 58 | 59 | @Nonnull 60 | @Override 61 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 62 | List recipeOutputs = new ArrayList<>(); 63 | if (this.getAllOverlayIdentifier().contains(identifier)) { 64 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 65 | if ("ieArcFurnace".equals(identifier) || "ieCrusher".equals(identifier)) { 66 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 67 | } 68 | return recipeOutputs; 69 | } 70 | return recipeOutputs; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/NotEnoughEnergistics.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee; 2 | 3 | import java.io.File; 4 | 5 | import net.minecraft.launchwrapper.Launch; 6 | 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | 10 | import com.github.vfyjxf.nee.config.NEEConfig; 11 | import com.github.vfyjxf.nee.network.NEEGuiHandler; 12 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 13 | import com.github.vfyjxf.nee.proxy.CommonProxy; 14 | 15 | import cpw.mods.fml.common.FMLCommonHandler; 16 | import cpw.mods.fml.common.Mod; 17 | import cpw.mods.fml.common.Mod.EventHandler; 18 | import cpw.mods.fml.common.SidedProxy; 19 | import cpw.mods.fml.common.event.FMLInitializationEvent; 20 | import cpw.mods.fml.common.event.FMLPostInitializationEvent; 21 | import cpw.mods.fml.common.event.FMLPreInitializationEvent; 22 | import cpw.mods.fml.common.network.NetworkRegistry; 23 | 24 | @Mod( 25 | modid = NotEnoughEnergistics.MODID, 26 | version = NotEnoughEnergistics.VERSION, 27 | name = NotEnoughEnergistics.NAME, 28 | dependencies = NotEnoughEnergistics.DEPENDENCIES, 29 | guiFactory = NotEnoughEnergistics.GUI_FACTORY, 30 | useMetadata = true) 31 | public class NotEnoughEnergistics { 32 | 33 | public static final String MODID = "neenergistics"; 34 | public static final String NAME = "NotEnoughEnergistics"; 35 | public static final String VERSION = Tags.VERSION; 36 | public static final String DEPENDENCIES = "required-after:" + "NotEnoughItems;required-after:" 37 | + "appliedenergistics2@[rv3-beta-754-GTNH,);after:" 38 | + "ae2wct@[1.12.10,);after:" 39 | + "ae2fc@[1.5.30-gtnh,);"; 40 | public static final String GUI_FACTORY = "com.github.vfyjxf.nee.config.NEEConfigGuiFactory"; 41 | public static final Logger logger = LogManager.getLogger("NotEnoughEnergistics"); 42 | 43 | @SidedProxy( 44 | clientSide = "com.github.vfyjxf.nee.proxy.ClientProxy", 45 | serverSide = "com.github.vfyjxf.nee.proxy.ServerProxy") 46 | public static CommonProxy proxy; 47 | 48 | @Mod.Instance(MODID) 49 | public static NotEnoughEnergistics instance; 50 | 51 | @EventHandler 52 | public void preInit(FMLPreInitializationEvent event) { 53 | proxy.preInit(event); 54 | NEENetworkHandler.init(); 55 | NEEConfig.loadConfig(new File(Launch.minecraftHome, "config/NotEnoughEnergistics.cfg")); 56 | FMLCommonHandler.instance().bus().register(new NEEConfig()); 57 | } 58 | 59 | @EventHandler 60 | public void init(FMLInitializationEvent event) { 61 | proxy.init(event); 62 | } 63 | 64 | @EventHandler 65 | public void postInit(FMLPostInitializationEvent event) { 66 | NetworkRegistry.INSTANCE.registerGuiHandler(this, new NEEGuiHandler()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [中文](READNE_CN.md) 2 | 3 | # Not Enough Energistics 4 | 5 | [![Downloads](https://cf.way2muchnoise.eu/full_515565_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/not-enough-energistics) ![MCVsrsion](https://cf.way2muchnoise.eu/versions/515565.svg) 6 | 7 | ---- 8 | 9 | NotEnoughEnergistics is a port of [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) to Minecraft 1.7.10 10 | 11 | This mod replaces AE2's default NEI integration for the Pattern Terminal. 12 | 13 | By default, AE2 forces the player to either have the necessary items for a recipe in their personal inventory or in their ME network. 14 | 15 | This mod removes that functionality and allows the player to use NEI's transfer system (shift + click [?] button) to create patterns whether the player possesses the items required by the recipe. 16 | 17 | 18 | ## Features 19 | 20 | - Automatically switch the mode of PatternTerminal. 21 | - If an item is a probability output, then nee will not transfer it. 22 | - Combine like stacks in processing patterns. 23 | - Support Processing Pattern Terminal(16 -> 4 mode). 24 | - Allow you to add item blackList and item priority list, if item in them, it will not be transferred / transfer it first.(use /nee RecipeProcessor to get RecipeProcessor and identifier in log) 25 | - Allow you to add mod priority list,if the mod's has this item,it will be use first. 26 | - You can use the ctrl + mouse wheel to change the Pattern item input/output amount. 27 | - You can use shift + mouse wheel to choose ingredient. 28 | - 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) 29 | 30 | ## Compatible Modslist as followed: 31 | 32 | - [x] AppliedEnergistics2 33 | - [x] Vanilla 34 | - [x] GregTech5 35 | - [x] GregTech6 36 | - [x] IndustrialCraft2 37 | - [x] Avaritia 38 | - [x] EnderIO 39 | - [x] Forestry (Doesn't support Fermenter and Still,because they don't have an item output) 40 | - [x] Thaumcraft NEI Plugin 41 | - [x] Thaumic Energistics (Allows you to transfer ArcaneRecipe from NEI to Knowledge Inscriber, it requires Thaumcraft NEI Plugin) 42 | - [x] ThermalExpansion 43 | - [x] ImmersiveEngineering 44 | - [x] Mekanism 45 | - [x] BloodMagic 46 | - [x] BuildCraft 47 | - [x] Avaritiaddons (auto extreme crafting table support) 48 | - [x] GT++ 49 | 50 | If you want other Mod support, see [RecipeProcessor](./src/main/java/com/github/vfyjxf/nee/processor/RecipeProcessor.java) and [Mod support Issue](https://github.com/vfyjxf/NotEnoughEnergistics/issues/1) 51 | 52 | ## TODO 53 | 54 | - [x] Add item blackList, if item in the blacklist, it will not be transferred. 55 | - [x] Add item priority list, if item in tne priority list, it will be transferred first. 56 | - [x] Combine like stacks in processing patterns. 57 | 58 | ## Credits 59 | Thanks TheRealp455w0rd and his [Just Enough Energistics](https://www.curseforge.com/minecraft/mc-mods/just-enough-energistics-jee) 60 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/GuiPatternInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.entity.player.InventoryPlayer; 5 | import net.minecraft.util.ResourceLocation; 6 | 7 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 8 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 9 | import com.github.vfyjxf.nee.client.gui.widgets.GuiImgButtonRemove; 10 | import com.github.vfyjxf.nee.container.ContainerPatternInterface; 11 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 12 | import com.github.vfyjxf.nee.network.packet.PacketValueConfigServer; 13 | 14 | import appeng.client.gui.AEBaseGui; 15 | import appeng.container.slot.SlotRestrictedInput; 16 | 17 | public class GuiPatternInterface extends AEBaseGui { 18 | 19 | private final ContainerPatternInterface container; 20 | private GuiImgButtonRemove removeButton; 21 | 22 | public GuiPatternInterface(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 | @SuppressWarnings("unchecked") 30 | @Override 31 | public void initGui() { 32 | super.initGui(); 33 | this.removeButton = new GuiImgButtonRemove(this.guiLeft + 85, this.guiTop + this.ySize - 173); 34 | this.buttonList.add(removeButton); 35 | } 36 | 37 | @Override 38 | public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY) {} 39 | 40 | @Override 41 | public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY) { 42 | this.mc.getTextureManager().bindTexture(getBackground()); 43 | this.drawTexturedModalRect(offsetX, offsetY, 0, 0, 211 - 34, this.ySize); 44 | } 45 | 46 | @Override 47 | protected void actionPerformed(GuiButton button) { 48 | super.actionPerformed(button); 49 | if (button == this.removeButton) { 50 | // We shouldn't delete a null, right? 51 | if (container.getSelectedSlot() != null) { 52 | NEENetworkHandler.getInstance().sendToServer(new PacketValueConfigServer("Gui.PatternInterface")); 53 | } 54 | } 55 | } 56 | 57 | @Override 58 | protected void mouseClicked(int mouseX, int mouseY, int btn) { 59 | if (btn == 0 && this.theSlot instanceof SlotRestrictedInput) { 60 | SlotRestrictedInput slot = (SlotRestrictedInput) this.theSlot; 61 | NEENetworkHandler.getInstance().sendToServer( 62 | 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(NotEnoughEnergistics.MODID, "textures/gui/pattern_interface.png"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketSlotStackChange.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import net.minecraft.item.ItemStack; 7 | 8 | import com.github.vfyjxf.nee.utils.ItemUtils; 9 | 10 | import appeng.api.storage.StorageName; 11 | import appeng.api.storage.data.IAEStack; 12 | import appeng.container.implementations.ContainerPatternTerm; 13 | import appeng.util.item.AEItemStack; 14 | import cpw.mods.fml.common.network.ByteBufUtils; 15 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 16 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 17 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 18 | import io.netty.buffer.ByteBuf; 19 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 20 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 21 | 22 | /** 23 | * @author vfyjxf 24 | */ 25 | public class PacketSlotStackChange implements IMessage { 26 | 27 | private ItemStack stack; 28 | private List craftingSlots; 29 | 30 | public PacketSlotStackChange() {} 31 | 32 | public PacketSlotStackChange(ItemStack stack, List craftingSlots) { 33 | this.stack = stack; 34 | this.craftingSlots = craftingSlots; 35 | } 36 | 37 | public ItemStack getStack() { 38 | return stack; 39 | } 40 | 41 | public List getCraftingSlots() { 42 | return craftingSlots; 43 | } 44 | 45 | @Override 46 | public void fromBytes(ByteBuf buf) { 47 | this.stack = ItemUtils.loadItemStackFromNBT(ByteBufUtils.readTag(buf)); 48 | int craftingSlotsSize = buf.readInt(); 49 | this.craftingSlots = new ArrayList<>(craftingSlotsSize); 50 | for (int i = 0; i < craftingSlotsSize; i++) { 51 | int slotNumber = buf.readInt(); 52 | craftingSlots.add(slotNumber); 53 | } 54 | } 55 | 56 | @Override 57 | public void toBytes(ByteBuf buf) { 58 | ByteBufUtils.writeTag(buf, ItemUtils.writeItemStackToNBT(this.stack, this.stack.stackSize)); 59 | buf.writeInt(this.craftingSlots.size()); 60 | for (Integer craftingSlot : this.craftingSlots) { 61 | buf.writeInt(craftingSlot); 62 | } 63 | } 64 | 65 | public static final class Handler implements IMessageHandler { 66 | 67 | @Override 68 | public IMessage onMessage(PacketSlotStackChange message, MessageContext ctx) { 69 | final IAEStack nextStack = AEItemStack.create(message.getStack()); 70 | if (nextStack != null 71 | && ctx.getServerHandler().playerEntity.openContainer instanceof ContainerPatternTerm cpt) { 72 | final Int2ObjectMap> temp = new Int2ObjectOpenHashMap<>(); 73 | for (int craftingSlot : message.getCraftingSlots()) { 74 | temp.put(craftingSlot, nextStack); 75 | } 76 | cpt.receiveSlotStacks(StorageName.CRAFTING_INPUT, temp); 77 | } 78 | return null; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketStackCountChange.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.inventory.Container; 5 | 6 | import appeng.api.storage.StorageName; 7 | import appeng.api.storage.data.IAEStack; 8 | import appeng.container.implementations.ContainerPatternTerm; 9 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 10 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 11 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 12 | import io.netty.buffer.ByteBuf; 13 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap; 14 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 15 | 16 | /** 17 | * @author vfyjxf 18 | */ 19 | public class PacketStackCountChange implements IMessage { 20 | 21 | private int slotIndex; 22 | private int changeCount; 23 | private StorageName sn; 24 | 25 | public PacketStackCountChange() {} 26 | 27 | public PacketStackCountChange(int slotIndex, StorageName sn, int changeCount) { 28 | this.slotIndex = slotIndex; 29 | this.changeCount = changeCount; 30 | this.sn = sn; 31 | } 32 | 33 | public int getSlotIndex() { 34 | return slotIndex; 35 | } 36 | 37 | public int getChangeCount() { 38 | return changeCount; 39 | } 40 | 41 | public StorageName getStorageName() { 42 | return sn; 43 | } 44 | 45 | @Override 46 | public void fromBytes(ByteBuf buf) { 47 | this.slotIndex = buf.readInt(); 48 | this.changeCount = buf.readInt(); 49 | this.sn = StorageName.values()[buf.readInt()]; 50 | } 51 | 52 | @Override 53 | public void toBytes(ByteBuf buf) { 54 | buf.writeInt(this.slotIndex); 55 | buf.writeInt(this.changeCount); 56 | buf.writeInt(this.sn.ordinal()); 57 | } 58 | 59 | public static final class Handler implements IMessageHandler { 60 | 61 | @Override 62 | public IMessage onMessage(PacketStackCountChange message, MessageContext ctx) { 63 | EntityPlayerMP player = ctx.getServerHandler().playerEntity; 64 | Container container = player.openContainer; 65 | if (container instanceof ContainerPatternTerm cpt && !cpt.isCraftingMode()) { 66 | handleMessage(message, cpt); 67 | } 68 | return null; 69 | } 70 | 71 | private void handleMessage(PacketStackCountChange message, ContainerPatternTerm cpt) { 72 | final IAEStack aes = cpt.getPatternTerminal().getAEInventoryByName(message.getStorageName()) 73 | .getAEStackInSlot(message.getSlotIndex()); 74 | if (aes != null) { 75 | final IAEStack newAes = aes.copy(); 76 | final Int2ObjectMap> temp = new Int2ObjectOpenHashMap<>(); 77 | newAes.setStackSize(Math.max(1, aes.getStackSize()) + message.getChangeCount()); 78 | temp.put(message.getSlotIndex(), newAes); 79 | cpt.receiveSlotStacks(message.getStorageName(), temp); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/NEENetworkHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network; 2 | 3 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 4 | import com.github.vfyjxf.nee.network.packet.PacketArcaneRecipe; 5 | import com.github.vfyjxf.nee.network.packet.PacketCraftingRequest; 6 | import com.github.vfyjxf.nee.network.packet.PacketExtremeRecipe; 7 | import com.github.vfyjxf.nee.network.packet.PacketNEIBookmark; 8 | import com.github.vfyjxf.nee.network.packet.PacketNEIPatternRecipe; 9 | import com.github.vfyjxf.nee.network.packet.PacketOpenGui; 10 | import com.github.vfyjxf.nee.network.packet.PacketSlotStackChange; 11 | import com.github.vfyjxf.nee.network.packet.PacketStackCountChange; 12 | import com.github.vfyjxf.nee.network.packet.PacketValueConfigClient; 13 | import com.github.vfyjxf.nee.network.packet.PacketValueConfigServer; 14 | 15 | import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; 16 | import cpw.mods.fml.relauncher.Side; 17 | 18 | public class NEENetworkHandler { 19 | 20 | private static final SimpleNetworkWrapper INSTANCE = new SimpleNetworkWrapper(NotEnoughEnergistics.MODID); 21 | private static int packId = 0; 22 | 23 | private static int nextId() { 24 | return packId++; 25 | } 26 | 27 | private NEENetworkHandler() { 28 | throw new IllegalStateException("Utility class"); 29 | } 30 | 31 | public static SimpleNetworkWrapper getInstance() { 32 | return INSTANCE; 33 | } 34 | 35 | public static void init() { 36 | INSTANCE.registerMessage( 37 | PacketNEIPatternRecipe.Handler.class, 38 | PacketNEIPatternRecipe.class, 39 | nextId(), 40 | Side.SERVER); 41 | INSTANCE.registerMessage(PacketArcaneRecipe.Handler.class, PacketArcaneRecipe.class, nextId(), Side.SERVER); 42 | INSTANCE.registerMessage(PacketExtremeRecipe.Handler.class, PacketExtremeRecipe.class, nextId(), Side.SERVER); 43 | INSTANCE.registerMessage( 44 | PacketStackCountChange.Handler.class, 45 | PacketStackCountChange.class, 46 | nextId(), 47 | Side.SERVER); 48 | INSTANCE.registerMessage( 49 | PacketSlotStackChange.Handler.class, 50 | PacketSlotStackChange.class, 51 | nextId(), 52 | Side.SERVER); 53 | INSTANCE.registerMessage( 54 | PacketCraftingRequest.Handler.class, 55 | PacketCraftingRequest.class, 56 | nextId(), 57 | Side.SERVER); 58 | INSTANCE.registerMessage(PacketNEIBookmark.Handler.class, PacketNEIBookmark.class, nextId(), Side.SERVER); 59 | INSTANCE.registerMessage(PacketOpenGui.Handler.class, PacketOpenGui.class, nextId(), Side.SERVER); 60 | INSTANCE.registerMessage( 61 | PacketValueConfigServer.Handler.class, 62 | PacketValueConfigServer.class, 63 | nextId(), 64 | Side.SERVER); 65 | INSTANCE.registerMessage( 66 | PacketValueConfigClient.Handler.class, 67 | PacketValueConfigClient.class, 68 | nextId(), 69 | Side.CLIENT); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH= 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/GTPPRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import codechicken.nei.PositionedStack; 12 | import codechicken.nei.recipe.IRecipeHandler; 13 | 14 | /** 15 | * @author vfyjxf 16 | */ 17 | public class GTPPRecipeProcessor implements IRecipeProcessor { 18 | 19 | private final boolean isNH; 20 | 21 | public GTPPRecipeProcessor(boolean isNH) { 22 | this.isNH = isNH; 23 | } 24 | 25 | @Nonnull 26 | @Override 27 | public Set getAllOverlayIdentifier() { 28 | HashSet identifiers = new HashSet<>(); 29 | identifiers.add("GTPP_Decayables"); 30 | if (isNH) { 31 | return identifiers; 32 | } 33 | 34 | try { 35 | Class gtRecipeMapClazz = Class.forName("gregtech.api.util.GTRecipe$GT_Recipe_Map"); 36 | Class gtppRecipeMapClazz = Class.forName("gregtech.api.util.GTPPRecipe$GTPP_Recipe_Map_Internal"); 37 | Collection sMappingsEx = (Collection) gtppRecipeMapClazz.getDeclaredField("sMappingsEx").get(null); 38 | for (Object gtppMap : sMappingsEx) { 39 | boolean mNEIAllowed = gtRecipeMapClazz.getDeclaredField("mNEIAllowed").getBoolean(gtppMap); 40 | if (mNEIAllowed) { 41 | String mNEIName = (String) gtRecipeMapClazz.getDeclaredField("mNEIName").get(gtppMap); 42 | identifiers.add(mNEIName); 43 | } 44 | } 45 | } catch (Exception e) { 46 | throw new RuntimeException(e); 47 | } 48 | 49 | return identifiers; 50 | } 51 | 52 | @Nonnull 53 | @Override 54 | public String getRecipeProcessorId() { 55 | return "GT++"; 56 | } 57 | 58 | @Nonnull 59 | @Override 60 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 61 | List recipeInputs = new ArrayList<>(); 62 | if (this.getAllOverlayIdentifier().contains(identifier)) { 63 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 64 | recipeInputs.removeIf( 65 | positionedStack -> GregTech5RecipeProcessor.getFluidFromDisplayStack(positionedStack.items[0]) 66 | != null || positionedStack.item.stackSize == 0); 67 | return recipeInputs; 68 | } 69 | return recipeInputs; 70 | } 71 | 72 | @Nonnull 73 | @Override 74 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 75 | List recipeOutputs = new ArrayList<>(); 76 | if (this.getAllOverlayIdentifier().contains(identifier)) { 77 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 78 | recipeOutputs.removeIf( 79 | positionedStack -> GregTech5RecipeProcessor.getFluidFromDisplayStack(positionedStack.items[0]) 80 | != null); 81 | return recipeOutputs; 82 | } 83 | return recipeOutputs; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/client/gui/widgets/GuiImgButtonEnableCombination.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.client.gui.widgets; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.GuiButton; 5 | import net.minecraft.client.resources.I18n; 6 | import net.minecraft.util.ResourceLocation; 7 | 8 | import org.lwjgl.opengl.GL11; 9 | 10 | import com.github.vfyjxf.nee.config.ItemCombination; 11 | 12 | import appeng.client.gui.widgets.ITooltip; 13 | 14 | public class GuiImgButtonEnableCombination extends GuiButton implements ITooltip { 15 | 16 | private ItemCombination currentValue; 17 | 18 | public GuiImgButtonEnableCombination(int x, int y, ItemCombination value) { 19 | super(0, x, y, ""); 20 | this.xPosition = x; 21 | this.yPosition = y; 22 | this.width = 8; 23 | this.height = 8; 24 | this.currentValue = value; 25 | } 26 | 27 | @Override 28 | public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { 29 | if (this.visible) { 30 | GL11.glPushMatrix(); 31 | GL11.glTranslatef(this.xPosition, this.yPosition, 0.0F); 32 | GL11.glScalef(0.5f, 0.5f, 0.5f); 33 | if (this.enabled) { 34 | GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 35 | } else { 36 | GL11.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); 37 | } 38 | minecraft.renderEngine.bindTexture(new ResourceLocation("neenergistics", "textures/gui/states.png")); 39 | this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition 40 | && mouseX < this.xPosition + this.width 41 | && mouseY < this.yPosition + this.height; 42 | this.drawTexturedModalRect(0, 0, 0, 0, 16, 16); 43 | if (this.currentValue == ItemCombination.ENABLED) { 44 | this.drawTexturedModalRect(0, 0, 16, 16, 16, 16); 45 | } 46 | if (this.currentValue == ItemCombination.DISABLED) { 47 | this.drawTexturedModalRect(0, 0, 16, 0, 16, 16); 48 | } 49 | if (this.currentValue == ItemCombination.WHITELIST) { 50 | this.drawTexturedModalRect(0, 0, 0, 16, 16, 16); 51 | } 52 | this.mouseDragged(minecraft, mouseX, mouseY); 53 | GL11.glPopMatrix(); 54 | } 55 | } 56 | 57 | public void setValue(ItemCombination currentValue) { 58 | this.currentValue = currentValue; 59 | } 60 | 61 | public ItemCombination getCurrentValue() { 62 | return currentValue; 63 | } 64 | 65 | @Override 66 | public String getMessage() { 67 | return I18n.format("gui.neenergistics.button.title.combination") + "\n" 68 | + I18n.format("gui.neenergistics.button.tooltip.combination", currentValue.getLocalName()); 69 | } 70 | 71 | @Override 72 | public int xPos() { 73 | return this.xPosition; 74 | } 75 | 76 | @Override 77 | public int yPos() { 78 | return this.yPosition; 79 | } 80 | 81 | @Override 82 | public int getWidth() { 83 | return this.width; 84 | } 85 | 86 | @Override 87 | public int getHeight() { 88 | return this.height; 89 | } 90 | 91 | @Override 92 | public boolean isVisible() { 93 | return this.visible; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/nei/NEEExtremeAutoCrafterHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.nei; 2 | 3 | import java.util.List; 4 | 5 | import net.minecraft.client.gui.inventory.GuiContainer; 6 | import net.minecraft.item.ItemStack; 7 | import net.minecraft.nbt.NBTTagCompound; 8 | 9 | import com.github.vfyjxf.nee.config.NEEConfig; 10 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 11 | import com.github.vfyjxf.nee.network.packet.PacketExtremeRecipe; 12 | import com.github.vfyjxf.nee.utils.ItemUtils; 13 | 14 | import codechicken.nei.PositionedStack; 15 | import codechicken.nei.api.IOverlayHandler; 16 | import codechicken.nei.recipe.GuiOverlayButton; 17 | import codechicken.nei.recipe.GuiRecipe; 18 | import codechicken.nei.recipe.GuiRecipeButton; 19 | import codechicken.nei.recipe.IRecipeHandler; 20 | import cpw.mods.fml.common.eventhandler.SubscribeEvent; 21 | 22 | /** 23 | * @author vfyjxf 24 | */ 25 | public class NEEExtremeAutoCrafterHandler implements IOverlayHandler { 26 | 27 | public static final NEEExtremeAutoCrafterHandler instance = new NEEExtremeAutoCrafterHandler(); 28 | 29 | private NEEExtremeAutoCrafterHandler() {} 30 | 31 | @Override 32 | public void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift) { 33 | NEENetworkHandler.getInstance().sendToServer(packetExtremeRecipe(recipe, recipeIndex)); 34 | } 35 | 36 | private PacketExtremeRecipe packetExtremeRecipe(IRecipeHandler recipe, int recipeIndex) { 37 | NBTTagCompound recipeInputs = new NBTTagCompound(); 38 | List ingredients = recipe.getIngredientStacks(recipeIndex); 39 | 40 | for (PositionedStack positionedStack : ingredients) { 41 | int col = (positionedStack.relx - 3) / 18; 42 | int row = (positionedStack.rely - 3) / 18; 43 | 44 | if (positionedStack.rely == 129) { 45 | col = (positionedStack.relx - 2) / 18; 46 | } 47 | 48 | int slotIndex = col + row * 9; 49 | ItemStack currentStack = positionedStack.item; 50 | ItemStack preferModItem = ItemUtils.getPreferModItem(positionedStack.items); 51 | 52 | if (preferModItem != null) { 53 | currentStack = preferModItem; 54 | } 55 | 56 | for (ItemStack stack : positionedStack.items) { 57 | if (ItemUtils.isPreferItems(stack)) { 58 | currentStack = stack.copy(); 59 | } 60 | } 61 | 62 | recipeInputs.setTag("#" + slotIndex, ItemUtils.writeItemStackToNBT(currentStack, currentStack.stackSize)); 63 | } 64 | 65 | return new PacketExtremeRecipe(recipeInputs); 66 | } 67 | 68 | @SubscribeEvent 69 | public void onActionPerformedEventPost(GuiRecipeButton.UpdateRecipeButtonsEvent.Post event) { 70 | if (NEEConfig.noShift && event.gui instanceof GuiRecipe guiRecipe && isGuiExtremeTerm(guiRecipe)) { 71 | for (int i = 0; i < event.buttonList.size(); i++) { 72 | if (event.buttonList.get(i) instanceof GuiOverlayButton btn) { 73 | btn.setRequireShiftForOverlayRecipe(false); 74 | } 75 | } 76 | } 77 | } 78 | 79 | private boolean isGuiExtremeTerm(GuiRecipe gui) { 80 | return gui.firstGui != null && this.getClass().isInstance(gui.getHandler().getOverlayHandler(gui.firstGui, 0)); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/proxy/CommonProxy.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.proxy; 2 | 3 | import static com.github.vfyjxf.nee.block.BlockPatternInterface.BLOCK_INSTANCE; 4 | 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraftforge.oredict.ShapedOreRecipe; 7 | 8 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 9 | import com.github.vfyjxf.nee.block.BlockPatternInterface; 10 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 11 | 12 | import appeng.api.AEApi; 13 | import appeng.api.definitions.IBlocks; 14 | import appeng.api.definitions.IDefinitions; 15 | import appeng.api.definitions.IMaterials; 16 | import appeng.api.definitions.IParts; 17 | import appeng.api.util.AEColor; 18 | import appeng.core.features.ActivityState; 19 | import appeng.core.features.BlockStackSrc; 20 | import appeng.tile.AEBaseTile; 21 | import cpw.mods.fml.common.event.FMLInitializationEvent; 22 | import cpw.mods.fml.common.event.FMLPreInitializationEvent; 23 | import cpw.mods.fml.common.registry.GameRegistry; 24 | 25 | public class CommonProxy { 26 | 27 | public void init(FMLInitializationEvent event) { 28 | AEBaseTile.registerTileItem( 29 | TilePatternInterface.class, 30 | new BlockStackSrc(BLOCK_INSTANCE, 0, ActivityState.Enabled)); 31 | registerRecipe(); 32 | } 33 | 34 | public void preInit(FMLPreInitializationEvent event) { 35 | registerBlocks(); 36 | registerItems(); 37 | registerTileEntities(); 38 | } 39 | 40 | public void registerItems() { 41 | GameRegistry.registerItem(BlockPatternInterface.ITEM_INSTANCE, "tile.pattern_interface"); 42 | } 43 | 44 | public void registerBlocks() { 45 | GameRegistry.registerBlock(BLOCK_INSTANCE, null, "tile.pattern_interface"); 46 | } 47 | 48 | public void registerTileEntities() { 49 | GameRegistry.registerTileEntity( 50 | TilePatternInterface.class, 51 | NotEnoughEnergistics.MODID + "." + "tile.pattern_interface"); 52 | } 53 | 54 | public void registerRecipe() { 55 | final IDefinitions definitions = AEApi.instance().definitions(); 56 | final IMaterials materials = definitions.materials(); 57 | final IParts parts = definitions.parts(); 58 | final IBlocks blocks = definitions.blocks(); 59 | 60 | ItemStack blankPattern = null; 61 | ItemStack patternTerm = null; 62 | ItemStack meInterface = null; 63 | ItemStack monitor = null; 64 | ItemStack cableSmart = parts.cableSmart().stack(AEColor.Transparent, 1); 65 | if (materials.blankPattern().maybeStack(1).isPresent()) { 66 | blankPattern = materials.blankPattern().maybeStack(1).get(); 67 | } 68 | if (parts.patternTerminal().maybeStack(1).isPresent()) { 69 | patternTerm = parts.patternTerminal().maybeStack(1).get(); 70 | } 71 | if (blocks.iface().maybeStack(1).isPresent()) { 72 | meInterface = blocks.iface().maybeStack(1).get(); 73 | } 74 | if (blocks.craftingMonitor().maybeStack(1).isPresent()) { 75 | monitor = blocks.craftingMonitor().maybeStack(1).get(); 76 | } 77 | 78 | GameRegistry.addRecipe( 79 | new ShapedOreRecipe( 80 | BLOCK_INSTANCE, 81 | "aba", 82 | "cdc", 83 | "eee", 84 | 'a', 85 | blankPattern, 86 | 'b', 87 | patternTerm, 88 | 'c', 89 | meInterface, 90 | 'd', 91 | monitor, 92 | 'e', 93 | cableSmart)); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketValueConfigServer.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import net.minecraft.entity.player.EntityPlayerMP; 4 | import net.minecraft.inventory.Container; 5 | import net.minecraft.inventory.Slot; 6 | 7 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 8 | import com.github.vfyjxf.nee.container.ContainerPatternInterface; 9 | import com.github.vfyjxf.nee.utils.GuiUtils; 10 | 11 | import appeng.api.networking.IGrid; 12 | import appeng.api.networking.IGridNode; 13 | import appeng.container.slot.SlotRestrictedInput; 14 | import cpw.mods.fml.common.network.ByteBufUtils; 15 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 16 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 17 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 18 | import io.netty.buffer.ByteBuf; 19 | 20 | public class PacketValueConfigServer implements IMessage { 21 | 22 | private String name; 23 | private String value; 24 | 25 | public PacketValueConfigServer() {} 26 | 27 | public PacketValueConfigServer(String name, String value) { 28 | this.name = name; 29 | this.value = value; 30 | } 31 | 32 | public PacketValueConfigServer(String name) { 33 | this.name = name; 34 | this.value = ""; 35 | } 36 | 37 | @Override 38 | public void fromBytes(ByteBuf buf) { 39 | this.name = ByteBufUtils.readUTF8String(buf); 40 | this.value = ByteBufUtils.readUTF8String(buf); 41 | } 42 | 43 | @Override 44 | public void toBytes(ByteBuf buf) { 45 | ByteBufUtils.writeUTF8String(buf, this.name); 46 | ByteBufUtils.writeUTF8String(buf, this.value); 47 | } 48 | 49 | public static final class Handler implements IMessageHandler { 50 | 51 | @Override 52 | public IMessage onMessage(PacketValueConfigServer message, MessageContext ctx) { 53 | EntityPlayerMP player = ctx.getServerHandler().playerEntity; 54 | Container container = player.openContainer; 55 | 56 | if ("Container.selectedSlot".equals(message.name)) { 57 | if (container instanceof ContainerPatternInterface) { 58 | ContainerPatternInterface cpc = (ContainerPatternInterface) container; 59 | int slotIndex = Integer.parseInt(message.value); 60 | Slot slot = container.getSlot(slotIndex); 61 | if (slot instanceof SlotRestrictedInput) { 62 | cpc.setSelectedSlotIndex(slot.slotNumber); 63 | } 64 | } 65 | } else if ("Gui.PatternInterface".equals(message.name)) { 66 | if (container instanceof ContainerPatternInterface) { 67 | ContainerPatternInterface cpc = (ContainerPatternInterface) container; 68 | TilePatternInterface tile = (TilePatternInterface) cpc.getTileEntity(); 69 | tile.cancelWork(cpc.getSelectedSlotIndex()); 70 | cpc.removeCurrentRecipe(); 71 | tile.updateCraftingList(); 72 | } 73 | } else if ("PatternInterface.check".equals(message.name)) { 74 | final IGrid grid = GuiUtils.getGrid(container); 75 | 76 | if (grid != null) { 77 | 78 | for (IGridNode gridNode : grid.getMachines(TilePatternInterface.class)) { 79 | if (gridNode.getMachine() instanceof TilePatternInterface) { 80 | return new PacketValueConfigClient("PatternInterface.check", true); 81 | } 82 | } 83 | 84 | return new PacketValueConfigClient("PatternInterface.check", false); 85 | } 86 | } 87 | 88 | return null; 89 | } 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/GregTech6RecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import javax.annotation.Nonnull; 10 | 11 | import net.minecraft.item.ItemStack; 12 | 13 | import codechicken.nei.PositionedStack; 14 | import codechicken.nei.recipe.IRecipeHandler; 15 | import cpw.mods.fml.relauncher.ReflectionHelper; 16 | import gregapi.NEI_RecipeMap; 17 | import gregapi.NEI_RecipeMap.FixedPositionedStack; 18 | import gregapi.data.FL; 19 | import gregapi.recipes.Recipe; 20 | 21 | /** 22 | * @author vfyjxf 23 | */ 24 | public class GregTech6RecipeProcessor implements IRecipeProcessor { 25 | 26 | @Nonnull 27 | @Override 28 | public Set getAllOverlayIdentifier() { 29 | Set identifiers = new HashSet<>(); 30 | for (Recipe.RecipeMap tMap : Recipe.RecipeMap.RECIPE_MAPS.values()) { 31 | if (tMap.mNEIAllowed) { 32 | identifiers.add(tMap.mNameNEI); 33 | } 34 | } 35 | return identifiers; 36 | } 37 | 38 | @Nonnull 39 | @Override 40 | public String getRecipeProcessorId() { 41 | return "GregTech6"; 42 | } 43 | 44 | @Nonnull 45 | @Override 46 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 47 | List recipeInputs = new ArrayList<>(); 48 | if (this.getAllOverlayIdentifier().contains(identifier)) { 49 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 50 | // remove fluid 51 | recipeInputs.removeIf( 52 | positionedStack -> FL.getFluid(positionedStack.item, true) != null 53 | || positionedStack.item.stackSize == 0); 54 | // try to remove machine 55 | if (recipe instanceof NEI_RecipeMap) { 56 | Field mRecipeMapField = ReflectionHelper.findField(NEI_RecipeMap.class, "mRecipeMap"); 57 | Recipe.RecipeMap mRecipeMap = null; 58 | try { 59 | mRecipeMap = (Recipe.RecipeMap) mRecipeMapField.get(recipe); 60 | } catch (IllegalAccessException e) { 61 | e.printStackTrace(); 62 | } 63 | if (mRecipeMap != null) { 64 | ItemStack lastItem = (recipeInputs.get(recipeInputs.size() - 1)).items[0]; 65 | for (ItemStack stack : mRecipeMap.mRecipeMachineList) { 66 | if (ItemStack.areItemStackTagsEqual(lastItem, stack)) { 67 | recipeInputs.remove(recipeInputs.size() - 1); 68 | break; 69 | } 70 | } 71 | } 72 | } 73 | return recipeInputs; 74 | } 75 | return recipeInputs; 76 | } 77 | 78 | @Nonnull 79 | @Override 80 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 81 | List recipeOutput = new ArrayList<>(); 82 | if (this.getAllOverlayIdentifier().contains(identifier)) { 83 | recipeOutput.addAll(recipe.getOtherStacks(recipeIndex)); 84 | recipeOutput.removeIf( 85 | positionedStack -> FL.getFluid(positionedStack.item, true) != null 86 | || positionedStack.item.stackSize == 0); 87 | // try to remove item output if it's chance != 100% 88 | recipeOutput.removeIf( 89 | positionedStack -> positionedStack instanceof FixedPositionedStack 90 | && ((FixedPositionedStack) positionedStack).mChance > 0 91 | && ((FixedPositionedStack) positionedStack).mChance 92 | != ((FixedPositionedStack) positionedStack).mMaxChance); 93 | return recipeOutput; 94 | } 95 | return recipeOutput; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketExtremeRecipe.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import javax.annotation.Nonnull; 6 | 7 | import net.minecraft.entity.player.EntityPlayerMP; 8 | import net.minecraft.inventory.Container; 9 | import net.minecraft.inventory.InventoryCrafting; 10 | import net.minecraft.inventory.Slot; 11 | import net.minecraft.item.ItemStack; 12 | import net.minecraft.nbt.NBTTagCompound; 13 | 14 | import com.github.vfyjxf.nee.utils.ItemUtils; 15 | 16 | import cpw.mods.fml.common.network.ByteBufUtils; 17 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 18 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 19 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 20 | import cpw.mods.fml.relauncher.ReflectionHelper; 21 | import io.netty.buffer.ByteBuf; 22 | import wanion.avaritiaddons.block.extremeautocrafter.ContainerExtremeAutoCrafter; 23 | import wanion.avaritiaddons.block.extremeautocrafter.TileEntityExtremeAutoCrafter; 24 | 25 | /** 26 | * @author vfyjxf 27 | */ 28 | public class PacketExtremeRecipe implements IMessage { 29 | 30 | private NBTTagCompound input; 31 | 32 | public PacketExtremeRecipe() {} 33 | 34 | public PacketExtremeRecipe(@Nonnull NBTTagCompound input) { 35 | this.input = input; 36 | } 37 | 38 | public NBTTagCompound getInput() { 39 | return input; 40 | } 41 | 42 | @Override 43 | public void fromBytes(ByteBuf buf) { 44 | this.input = ByteBufUtils.readTag(buf); 45 | } 46 | 47 | @Override 48 | public void toBytes(ByteBuf buf) { 49 | ByteBufUtils.writeTag(buf, this.input); 50 | } 51 | 52 | public static final class Handler implements IMessageHandler { 53 | 54 | @Override 55 | public IMessage onMessage(PacketExtremeRecipe message, MessageContext ctx) { 56 | EntityPlayerMP player = ctx.getServerHandler().playerEntity; 57 | Container container = player.openContainer; 58 | if (container instanceof ContainerExtremeAutoCrafter) { 59 | ItemStack[] recipeInputs = new ItemStack[81]; 60 | NBTTagCompound currentStack; 61 | for (int i = 0; i < recipeInputs.length; i++) { 62 | currentStack = (NBTTagCompound) message.input.getTag("#" + i); 63 | recipeInputs[i] = currentStack == null ? null : ItemUtils.loadItemStackFromNBT(currentStack); 64 | } 65 | int inputIndex = 0; 66 | for (int i = 81; i < 162; i++) { 67 | Slot fakeSlot = container.getSlot(i); 68 | ItemStack currentItem = recipeInputs[inputIndex]; 69 | fakeSlot.putStack(currentItem); 70 | inputIndex++; 71 | } 72 | InventoryCrafting craftingMatrix = getCraftingMatrix((ContainerExtremeAutoCrafter) container); 73 | if (craftingMatrix != null) { 74 | container.onCraftMatrixChanged(craftingMatrix); 75 | } 76 | } 77 | return null; 78 | } 79 | 80 | private InventoryCrafting getCraftingMatrix(ContainerExtremeAutoCrafter container) { 81 | Field tileEntityExtremeAutoCrafterField = ReflectionHelper 82 | .findField(ContainerExtremeAutoCrafter.class, "tileEntityExtremeAutoCrafter"); 83 | TileEntityExtremeAutoCrafter tileEntityExtremeAutoCrafter = null; 84 | 85 | try { 86 | tileEntityExtremeAutoCrafter = (TileEntityExtremeAutoCrafter) tileEntityExtremeAutoCrafterField 87 | .get(container); 88 | } catch (IllegalAccessException e) { 89 | e.printStackTrace(); 90 | } 91 | if (tileEntityExtremeAutoCrafter != null) { 92 | Field craftingMatrixField = ReflectionHelper 93 | .findField(TileEntityExtremeAutoCrafter.class, "craftingMatrix"); 94 | InventoryCrafting craftingMatrix = null; 95 | try { 96 | craftingMatrix = (InventoryCrafting) craftingMatrixField.get(tileEntityExtremeAutoCrafter); 97 | } catch (IllegalAccessException e) { 98 | e.printStackTrace(); 99 | } 100 | return craftingMatrix; 101 | } 102 | return null; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/ThermalExpansionRecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | import javax.annotation.Nonnull; 11 | 12 | import codechicken.nei.PositionedStack; 13 | import codechicken.nei.recipe.IRecipeHandler; 14 | import cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerBase; 15 | import cpw.mods.fml.relauncher.ReflectionHelper; 16 | 17 | public class ThermalExpansionRecipeProcessor implements IRecipeProcessor { 18 | 19 | private static Class thermalNeiRecipeBaseClass; 20 | 21 | static { 22 | try { 23 | thermalNeiRecipeBaseClass = Class 24 | .forName("cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerBase$NEIRecipeBase"); 25 | } catch (ClassNotFoundException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | @Nonnull 31 | @Override 32 | public Set getAllOverlayIdentifier() { 33 | return new HashSet<>( 34 | Arrays.asList( 35 | "thermalexpansion.charger", 36 | "thermalexpansion.crucible", 37 | "thermalexpansion.furnace", 38 | "thermalexpansion.insolator", 39 | "thermalexpansion.pulverizer", 40 | "thermalexpansion.sawmill", 41 | "thermalexpansion.smelter", 42 | "thermalexpansion.transposer")); 43 | } 44 | 45 | @Nonnull 46 | @Override 47 | public String getRecipeProcessorId() { 48 | return "ThermalExpansion"; 49 | } 50 | 51 | @Nonnull 52 | @Override 53 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 54 | List recipeInputs = new ArrayList<>(); 55 | if (this.getAllOverlayIdentifier().contains(identifier)) { 56 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 57 | if (recipe instanceof RecipeHandlerBase) { 58 | if (thermalNeiRecipeBaseClass != null) { 59 | Field secondaryInputField = ReflectionHelper.findField(thermalNeiRecipeBaseClass, "secondaryInput"); 60 | PositionedStack secondaryInput = null; 61 | try { 62 | secondaryInput = (PositionedStack) secondaryInputField 63 | .get(((RecipeHandlerBase) recipe).arecipes.get(recipeIndex)); 64 | } catch (IllegalAccessException e) { 65 | e.printStackTrace(); 66 | } 67 | if (secondaryInput != null) { 68 | recipeInputs.add(secondaryInput); 69 | } 70 | } 71 | } 72 | return recipeInputs; 73 | } 74 | 75 | return recipeInputs; 76 | } 77 | 78 | @Nonnull 79 | @Override 80 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 81 | List recipeOutputs = new ArrayList<>(); 82 | if (this.getAllOverlayIdentifier().contains(identifier)) { 83 | recipeOutputs.add(recipe.getResultStack(recipeIndex)); 84 | if (recipe instanceof RecipeHandlerBase) { 85 | if (thermalNeiRecipeBaseClass != null) { 86 | Field secondaryOutputField = ReflectionHelper 87 | .findField(thermalNeiRecipeBaseClass, "secondaryOutput"); 88 | Field secondaryOutputChanceField = ReflectionHelper 89 | .findField(thermalNeiRecipeBaseClass, "secondaryOutputChance"); 90 | PositionedStack secondaryOutput = null; 91 | int secondaryOutputChance = 0; 92 | try { 93 | secondaryOutput = (PositionedStack) secondaryOutputField 94 | .get(((RecipeHandlerBase) recipe).arecipes.get(recipeIndex)); 95 | secondaryOutputChance = (int) secondaryOutputChanceField 96 | .get(((RecipeHandlerBase) recipe).arecipes.get(recipeIndex)); 97 | } catch (IllegalAccessException e) { 98 | e.printStackTrace(); 99 | } 100 | if (secondaryOutput != null && secondaryOutputChance >= 100) { 101 | recipeOutputs.add(secondaryOutput); 102 | } 103 | } 104 | } 105 | return recipeOutputs; 106 | } 107 | return recipeOutputs; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/RecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 7 | 8 | import cpw.mods.fml.common.Loader; 9 | 10 | public class RecipeProcessor { 11 | 12 | public static final String NULL_IDENTIFIER = "null"; 13 | public static List recipeProcessors = new ArrayList<>(); 14 | 15 | public static void init() { 16 | NotEnoughEnergistics.logger.info("-----Not Enough Energistics Init Start-----"); 17 | NotEnoughEnergistics.logger.info("Install Vanilla Support"); 18 | recipeProcessors.add(new VanillaRecipeProcessor()); 19 | 20 | if (Loader.isModLoaded("appliedenergistics2")) { 21 | NotEnoughEnergistics.logger.info("Found Applied Energistics 2,install Applied Energistics 2 support"); 22 | recipeProcessors.add(new AppengRecipeProcessor()); 23 | } 24 | 25 | if (Loader.isModLoaded("Botania")) { 26 | NotEnoughEnergistics.logger.info("Found Botania,install Botania support"); 27 | recipeProcessors.add(new BotaniaRecipeProcessor()); 28 | } 29 | 30 | boolean isNH = false; 31 | if (Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi")) { 32 | try { 33 | Class.forName("gregtech.api.recipe.RecipeMap"); 34 | isNH = true; 35 | NotEnoughEnergistics.logger.info("Found NH version of GregTech5, install GregTech5 support"); 36 | } catch (ClassNotFoundException ignored) { 37 | NotEnoughEnergistics.logger.info("Found GregTech5, install GregTech5 support"); 38 | } 39 | recipeProcessors.add(new GregTech5RecipeProcessor(isNH)); 40 | } 41 | if (Loader.isModLoaded("gregapi") && Loader.isModLoaded("gregapi_post")) { 42 | NotEnoughEnergistics.logger.info("Found GregTech6,install GregTech6 support"); 43 | recipeProcessors.add(new GregTech6RecipeProcessor()); 44 | } 45 | if (Loader.isModLoaded("IC2")) { 46 | NotEnoughEnergistics.logger.info("Found IC2,install IC2 Support"); 47 | recipeProcessors.add(new ICRecipeProcessor()); 48 | } 49 | if (Loader.isModLoaded("Avaritia")) { 50 | NotEnoughEnergistics.logger.info("Found Avaritia, install Avaritia support"); 51 | recipeProcessors.add(new AvaritiaRecipeProcessor()); 52 | } 53 | if (Loader.isModLoaded("EnderIO")) { 54 | NotEnoughEnergistics.logger.info("Found EnderIO, install EnderIO support"); 55 | recipeProcessors.add(new EnderIORecipeProcessor()); 56 | } 57 | if (Loader.isModLoaded("Forestry")) { 58 | NotEnoughEnergistics.logger.info("Found Forestry, install Forestry support"); 59 | recipeProcessors.add(new ForestryRecipeProcessor()); 60 | } 61 | if (Loader.isModLoaded("thaumcraftneiplugin")) { 62 | NotEnoughEnergistics.logger.info("Found TCNEIPlugin, install TCNEIPlugin support"); 63 | recipeProcessors.add(new TCNEIPluginRecipeProcessor()); 64 | } 65 | if (Loader.isModLoaded("ThermalExpansion")) { 66 | NotEnoughEnergistics.logger.info("Found ThermalExpansion, install ThermalExpansion support"); 67 | recipeProcessors.add(new ThermalExpansionRecipeProcessor()); 68 | } 69 | if (Loader.isModLoaded("ImmersiveEngineering")) { 70 | NotEnoughEnergistics.logger.info("Found ImmersiveEngineering, install ImmersiveEngineering support"); 71 | recipeProcessors.add(new ImmersiveEngineeringRecipeProcessor()); 72 | } 73 | if (Loader.isModLoaded("Mekanism")) { 74 | NotEnoughEnergistics.logger.info("Found Mekanism, install Mekanism support"); 75 | recipeProcessors.add(new MekanismRecipeProcessor()); 76 | } 77 | if (Loader.isModLoaded("AWWayofTime")) { 78 | NotEnoughEnergistics.logger.info("Found BloodMagic, install BloodMagic support"); 79 | recipeProcessors.add(new BloodMagicRecipeProcessor()); 80 | } 81 | if (Loader.isModLoaded("BuildCraft|Compat")) { 82 | NotEnoughEnergistics.logger.info("Found BuildCraft-Compat, install BuildCraft-Compat support"); 83 | recipeProcessors.add(new BuildCraftRecipeProcessor()); 84 | } 85 | if (Loader.isModLoaded("miscutils")) { 86 | NotEnoughEnergistics.logger.info("Found GT++, install GT++ support"); 87 | recipeProcessors.add(new GTPPRecipeProcessor(isNH)); 88 | } 89 | if (!isNH && Loader.isModLoaded("GoodGenerator")) { 90 | NotEnoughEnergistics.logger.info("Found Good Generator, install Good Generator support"); 91 | recipeProcessors.add(new GoodGeneratorRecipeProcessor()); 92 | } 93 | 94 | NotEnoughEnergistics.logger.info("-----Not Enough Energistics Init Finished-----"); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/GuiUtils.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.function.Predicate; 6 | 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraft.client.gui.GuiScreen; 9 | import net.minecraft.client.gui.inventory.GuiContainer; 10 | import net.minecraft.inventory.Container; 11 | import net.minecraft.inventory.IInventory; 12 | import net.minecraft.inventory.Slot; 13 | import net.minecraftforge.common.util.ForgeDirection; 14 | 15 | import appeng.api.networking.IGrid; 16 | import appeng.api.networking.IGridHost; 17 | import appeng.api.networking.IGridNode; 18 | import appeng.api.storage.data.IAEItemStack; 19 | import appeng.api.storage.data.IItemList; 20 | import appeng.client.gui.implementations.GuiPatternTerm; 21 | import appeng.client.me.ItemRepo; 22 | import appeng.container.AEBaseContainer; 23 | import appeng.container.implementations.ContainerPatternTerm; 24 | import appeng.helpers.IContainerCraftingPacket; 25 | import cpw.mods.fml.common.Loader; 26 | import cpw.mods.fml.relauncher.ReflectionHelper; 27 | import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException; 28 | import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal; 29 | 30 | /** 31 | * @author vfyjxf 32 | */ 33 | public class GuiUtils { 34 | 35 | public static boolean isCraftingSlot(Slot slot) { 36 | if (slot == null) { 37 | return false; 38 | } 39 | Container container = Minecraft.getMinecraft().thePlayer.openContainer; 40 | if (!isPatternContainer(container)) { 41 | return false; 42 | } 43 | IContainerCraftingPacket cct = (IContainerCraftingPacket) container; 44 | IInventory craftMatrix = cct.getInventoryByName("crafting"); 45 | return craftMatrix.equals(slot.inventory); 46 | } 47 | 48 | public static boolean isPatternContainer(Container container) { 49 | return container instanceof ContainerPatternTerm; 50 | } 51 | 52 | public static boolean isPatternTerm(GuiScreen guiScreen) { 53 | return guiScreen instanceof GuiPatternTerm; 54 | } 55 | 56 | public static ItemRepo getItemRepo(GuiContainer termGui) { 57 | Class clazz = termGui.getClass(); 58 | ItemRepo repo = null; 59 | 60 | while (repo == null && clazz != null) { 61 | try { 62 | repo = (ItemRepo) ReflectionHelper.findField(clazz, "repo").get(termGui); 63 | } catch (UnableToFindFieldException | IllegalAccessException e) { 64 | clazz = clazz.getSuperclass(); 65 | } 66 | } 67 | 68 | return repo; 69 | } 70 | 71 | public static List getStorageStacks(GuiContainer termGui, Predicate predicate) { 72 | final List storageStacks = new ArrayList<>(); 73 | 74 | if (termGui != null) { 75 | final ItemRepo repo = GuiUtils.getItemRepo(termGui); 76 | 77 | if (repo != null) { 78 | 79 | try { 80 | @SuppressWarnings("unchecked") 81 | final IItemList list = (IItemList) ReflectionHelper 82 | .findField(ItemRepo.class, "list").get(repo); 83 | 84 | for (IAEItemStack stack : list) { 85 | if (predicate.test(stack)) { 86 | storageStacks.add(stack.copy()); 87 | } 88 | } 89 | 90 | } catch (Exception e) {} 91 | 92 | try { 93 | final IAEItemStack[] pins = (IAEItemStack[]) ReflectionHelper.findField(ItemRepo.class, "pinsRepo") 94 | .get(repo); 95 | 96 | for (int i = 0; i < pins.length; i++) { 97 | final IAEItemStack stack = pins[i]; 98 | if (stack != null && predicate.test(stack)) { 99 | storageStacks.add(stack.copy()); 100 | } 101 | } 102 | 103 | } catch (Exception e) {} 104 | 105 | } 106 | } 107 | 108 | return storageStacks; 109 | } 110 | 111 | public static IGrid getGrid(Container container) { 112 | 113 | if (Loader.isModLoaded(ModIDs.ThE) && container instanceof ContainerPartArcaneCraftingTerminal act) { 114 | final IGridNode gridNode = act.terminal.getGridNode(ForgeDirection.UNKNOWN); 115 | 116 | if (gridNode == null) { 117 | return null; 118 | } 119 | 120 | return gridNode.getGrid(); 121 | } else if (container instanceof AEBaseContainer baseContainer 122 | && baseContainer.getTarget() instanceof IGridHost gridHost) { 123 | final IGridNode gridNode = gridHost.getGridNode(ForgeDirection.UNKNOWN); 124 | 125 | if (gridNode == null) { 126 | return null; 127 | } 128 | 129 | return gridNode.getGrid(); 130 | } 131 | 132 | return null; 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketArcaneRecipe.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import net.minecraft.entity.player.EntityPlayerMP; 6 | import net.minecraft.inventory.Container; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.nbt.NBTTagCompound; 9 | 10 | import com.github.vfyjxf.nee.utils.ItemUtils; 11 | 12 | import appeng.container.slot.SlotFakeCraftingMatrix; 13 | import cpw.mods.fml.common.network.ByteBufUtils; 14 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 15 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 16 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 17 | import cpw.mods.fml.relauncher.ReflectionHelper; 18 | import io.netty.buffer.ByteBuf; 19 | import thaumicenergistics.client.gui.GuiArcaneCraftingTerminal; 20 | import thaumicenergistics.common.container.ContainerKnowledgeInscriber; 21 | 22 | /** 23 | * @author vfyjxf 24 | */ 25 | public class PacketArcaneRecipe implements IMessage { 26 | 27 | NBTTagCompound input; 28 | 29 | public PacketArcaneRecipe() {} 30 | 31 | public PacketArcaneRecipe(NBTTagCompound input) { 32 | this.input = input; 33 | } 34 | 35 | @Override 36 | public void fromBytes(ByteBuf buf) { 37 | this.input = ByteBufUtils.readTag(buf); 38 | } 39 | 40 | @Override 41 | public void toBytes(ByteBuf buf) { 42 | ByteBufUtils.writeTag(buf, this.input); 43 | } 44 | 45 | public static final class Handler implements IMessageHandler { 46 | 47 | @Override 48 | public IMessage onMessage(PacketArcaneRecipe message, MessageContext ctx) { 49 | EntityPlayerMP player = ctx.getServerHandler().playerEntity; 50 | Container container = player.openContainer; 51 | if (container instanceof ContainerKnowledgeInscriber) { 52 | ItemStack[] recipeInput = new ItemStack[9]; 53 | NBTTagCompound currentStack; 54 | for (int i = 0; i < recipeInput.length; i++) { 55 | currentStack = (NBTTagCompound) message.input.getTag("#" + i); 56 | recipeInput[i] = currentStack == null ? null : ItemUtils.loadItemStackFromNBT(currentStack); 57 | } 58 | 59 | Field craftingSlots = ReflectionHelper.findField(ContainerKnowledgeInscriber.class, "craftingSlots"); 60 | SlotFakeCraftingMatrix[] craftMatrix = this 61 | .getCraftingSlots(craftingSlots, (ContainerKnowledgeInscriber) container); 62 | if (craftMatrix != null && message.input != null) { 63 | for (int i = 0; i < recipeInput.length; i++) { 64 | ItemStack currentItem = null; 65 | if (recipeInput[i] != null) { 66 | currentItem = recipeInput[i].copy(); 67 | } 68 | craftMatrix[i].putStack(currentItem); 69 | } 70 | container.onCraftMatrixChanged(craftMatrix[0].inventory); 71 | } 72 | } else if (container.inventorySlots instanceof GuiArcaneCraftingTerminal) { 73 | ItemStack[] recipeInput = new ItemStack[9]; 74 | NBTTagCompound currentStack; 75 | for (int i = 0; i < recipeInput.length; i++) { 76 | currentStack = (NBTTagCompound) message.input.getTag("#" + i); 77 | recipeInput[i] = currentStack == null ? null : ItemUtils.loadItemStackFromNBT(currentStack); 78 | } 79 | Field craftingSlots = ReflectionHelper.findField(GuiArcaneCraftingTerminal.class, "craftingSlots"); 80 | SlotFakeCraftingMatrix[] craftMatrix = this 81 | .getCraftingSlots(craftingSlots, (GuiArcaneCraftingTerminal) container.inventorySlots); 82 | 83 | if (craftMatrix != null && message.input != null) { 84 | for (int i = 0; i < recipeInput.length; i++) { 85 | ItemStack currentItem = null; 86 | if (recipeInput[i] != null) { 87 | currentItem = recipeInput[i].copy(); 88 | } 89 | craftMatrix[i].putStack(currentItem); 90 | } 91 | container.onCraftMatrixChanged(craftMatrix[0].inventory); 92 | } 93 | 94 | } 95 | 96 | return null; 97 | } 98 | 99 | private SlotFakeCraftingMatrix[] getCraftingSlots(Field field, ContainerKnowledgeInscriber container) { 100 | try { 101 | return (SlotFakeCraftingMatrix[]) field.get(container); 102 | } catch (IllegalAccessException e) { 103 | e.printStackTrace(); 104 | } 105 | return null; 106 | } 107 | 108 | private SlotFakeCraftingMatrix[] getCraftingSlots(Field field, GuiArcaneCraftingTerminal container) { 109 | try { 110 | return (SlotFakeCraftingMatrix[]) field.get(container); 111 | } catch (IllegalAccessException e) { 112 | e.printStackTrace(); 113 | } 114 | return null; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/processor/GregTech5RecipeProcessor.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.processor; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | import java.util.stream.Collectors; 9 | 10 | import javax.annotation.Nonnull; 11 | 12 | import net.minecraft.item.ItemStack; 13 | import net.minecraftforge.fluids.Fluid; 14 | import net.minecraftforge.fluids.FluidRegistry; 15 | import net.minecraftforge.fluids.FluidStack; 16 | 17 | import codechicken.nei.PositionedStack; 18 | import codechicken.nei.recipe.IRecipeHandler; 19 | import gregtech.api.enums.ItemList; 20 | import gregtech.api.recipe.RecipeCategory; 21 | import gregtech.nei.GTNEIDefaultHandler.FixedPositionedStack; 22 | 23 | /** 24 | * @author vfyjxf 25 | */ 26 | public class GregTech5RecipeProcessor implements IRecipeProcessor { 27 | 28 | private static final Class gtDefaultClz, gtAssLineClz; 29 | 30 | private final boolean isNH; 31 | 32 | static { 33 | Class gtDH = null; 34 | Class gtAL = null; 35 | try { 36 | gtDH = Class.forName("gregtech.nei.GTNEIDefaultHandler"); 37 | gtAL = Class.forName("gregtech.nei.GT_NEI_AssLineHandler"); 38 | } catch (ClassNotFoundException ignored) {} 39 | gtDefaultClz = gtDH; 40 | gtAssLineClz = gtAL; 41 | } 42 | 43 | public GregTech5RecipeProcessor(boolean isNH) { 44 | this.isNH = isNH; 45 | } 46 | 47 | /** 48 | * For resolving NoSuchMethodError Copied from GTNewHorizons/GT5-Unofficial. 49 | */ 50 | public static FluidStack getFluidFromDisplayStack(ItemStack aDisplayStack) { 51 | if (!isStackValid(aDisplayStack) || aDisplayStack.getItem() != ItemList.Display_Fluid.getItem() 52 | || !aDisplayStack.hasTagCompound()) { 53 | return null; 54 | } 55 | Fluid tFluid = FluidRegistry.getFluid(ItemList.Display_Fluid.getItem().getDamage(aDisplayStack)); 56 | return new FluidStack(tFluid, (int) aDisplayStack.getTagCompound().getLong("mFluidDisplayAmount")); 57 | } 58 | 59 | public static boolean isStackValid(Object aStack) { 60 | return (aStack instanceof ItemStack) && ((ItemStack) aStack).getItem() != null 61 | && ((ItemStack) aStack).stackSize >= 0; 62 | } 63 | 64 | @Nonnull 65 | @Override 66 | public Set getAllOverlayIdentifier() { 67 | if (isNH) { 68 | return RecipeCategory.ALL_RECIPE_CATEGORIES.values().stream() 69 | .filter(category -> category.recipeMap.getFrontend().getNEIProperties().registerNEI) 70 | .map(category -> category.unlocalizedName).collect(Collectors.toSet()); 71 | } 72 | 73 | try { 74 | Set identifiers = new HashSet<>(); 75 | Class recipeMapClazz = Class.forName("gregtech.api.util.GT_Recipe$GT_Recipe_Map"); 76 | Collection sMappings = (Collection) recipeMapClazz.getDeclaredField("sMappings").get(null); 77 | for (Object tMap : sMappings) { 78 | boolean mNEIAllowed = recipeMapClazz.getDeclaredField("mNEIAllowed").getBoolean(tMap); 79 | if (mNEIAllowed) { 80 | String mNEIName = (String) recipeMapClazz.getDeclaredField("mNEIName").get(tMap); 81 | identifiers.add(mNEIName); 82 | } 83 | } 84 | identifiers.add("gt.recipe.fakeAssemblylineProcess"); 85 | return identifiers; 86 | } catch (Exception e) { 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | 91 | @Nonnull 92 | @Override 93 | public String getRecipeProcessorId() { 94 | return "GregTech5"; 95 | } 96 | 97 | @Nonnull 98 | @Override 99 | public List getRecipeInput(IRecipeHandler recipe, int recipeIndex, String identifier) { 100 | List recipeInputs = new ArrayList<>(); 101 | if (canProcessRecipe(recipe)) { 102 | recipeInputs.addAll(recipe.getIngredientStacks(recipeIndex)); 103 | recipeInputs.removeIf(positionedStack -> positionedStack.item.stackSize == 0); 104 | } 105 | 106 | return recipeInputs; 107 | } 108 | 109 | @Nonnull 110 | @Override 111 | public List getRecipeOutput(IRecipeHandler recipe, int recipeIndex, String identifier) { 112 | List recipeOutputs = new ArrayList<>(); 113 | if (canProcessRecipe(recipe)) { 114 | recipeOutputs.addAll(recipe.getOtherStacks(recipeIndex)); 115 | // remove output if it's chance != 10000 116 | recipeOutputs.removeIf( 117 | stack -> stack instanceof FixedPositionedStack && !(((FixedPositionedStack) stack).mChance == 10000 118 | || ((FixedPositionedStack) stack).mChance <= 0)); 119 | return recipeOutputs; 120 | } 121 | return recipeOutputs; 122 | } 123 | 124 | @Override 125 | public boolean mergeStacks(IRecipeHandler recipe, int recipeIndex, String identifier) { 126 | return !"gt.recipe.fakeAssemblylineProcess".equals(identifier); 127 | } 128 | 129 | private boolean canProcessRecipe(IRecipeHandler recipe) { 130 | return (gtDefaultClz != null && gtDefaultClz.isInstance(recipe)) 131 | || (gtAssLineClz != null && gtAssLineClz.isInstance(recipe)); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/nei/NEETerminalOverlayButton.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.nei; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import net.minecraft.client.gui.inventory.GuiContainer; 7 | import net.minecraft.client.resources.I18n; 8 | 9 | import org.lwjgl.opengl.GL11; 10 | 11 | import com.github.vfyjxf.nee.config.NEEConfig; 12 | import com.github.vfyjxf.nee.utils.Ingredient; 13 | 14 | import codechicken.lib.gui.GuiDraw; 15 | import codechicken.nei.Image; 16 | import codechicken.nei.LayoutManager; 17 | import codechicken.nei.NEIClientConfig; 18 | import codechicken.nei.drawable.DrawableBuilder; 19 | import codechicken.nei.recipe.GuiOverlayButton; 20 | import codechicken.nei.recipe.GuiRecipe; 21 | import codechicken.nei.recipe.GuiRecipeButton; 22 | import codechicken.nei.recipe.RecipeHandlerRef; 23 | import codechicken.nei.util.NEIMouseUtils; 24 | 25 | public class NEETerminalOverlayButton extends GuiOverlayButton { 26 | 27 | public static class NEEItemOverlayState extends ItemOverlayState { 28 | 29 | private static final Image crossIcon = new DrawableBuilder( 30 | "neenergistics:textures/gui/states.png", 31 | 16, 32 | 36, 33 | 8, 34 | 8).build(); 35 | 36 | private static final Image checkIcon = new DrawableBuilder( 37 | "neenergistics:textures/gui/states.png", 38 | 24, 39 | 36, 40 | 8, 41 | 8).build(); 42 | 43 | protected Ingredient ingredient; 44 | protected boolean isCraftingTerm = true; 45 | 46 | public NEEItemOverlayState(Ingredient ingredient, boolean isCraftingTerm) { 47 | super(ingredient.getIngredient(), !ingredient.requiresToCraft()); 48 | this.ingredient = ingredient; 49 | this.isCraftingTerm = isCraftingTerm; 50 | } 51 | 52 | public Ingredient getIngredient() { 53 | return this.ingredient; 54 | } 55 | 56 | public boolean isCraftingTerm() { 57 | return this.isCraftingTerm; 58 | } 59 | 60 | public void setIsCraftingTerm(boolean isCraftingTerm) { 61 | this.isCraftingTerm = isCraftingTerm; 62 | } 63 | 64 | public void draw(ItemOverlayFormat format) { 65 | final boolean doCraftingHelp = NEIClientConfig.isKeyHashDown("nee.nopreview") 66 | || NEIClientConfig.isKeyHashDown("nee.preview"); 67 | 68 | if (this.ingredient.isCraftable() 69 | && (!this.isCraftingTerm || doCraftingHelp && this.ingredient.requiresToCraft())) { 70 | final Image icon = this.isPresent ? checkIcon : crossIcon; 71 | 72 | if (format == ItemOverlayFormat.BACKGROUND) { 73 | GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); 74 | GL11.glDisable(GL11.GL_LIGHTING); 75 | GL11.glDisable(GL11.GL_DEPTH_TEST); 76 | GuiDraw.drawRect(this.slot.relx, this.slot.rely, 16, 16, 0x660000AA); 77 | GL11.glPopAttrib(); 78 | } else { 79 | LayoutManager.drawIcon(this.slot.relx + 16 - icon.width, this.slot.rely + 16 - icon.height, icon); 80 | } 81 | 82 | } else { 83 | super.draw(format); 84 | } 85 | } 86 | } 87 | 88 | public NEETerminalOverlayButton(GuiContainer firstGui, RecipeHandlerRef handlerRef, int xPosition, int yPosition) { 89 | super(firstGui, handlerRef, xPosition, yPosition); 90 | if (NEEConfig.noShift) { 91 | setRequireShiftForOverlayRecipe(false); 92 | } 93 | } 94 | 95 | public NEETerminalOverlayButton(GuiOverlayButton button) { 96 | this(button.firstGui, button.handlerRef, button.xPosition, button.yPosition); 97 | } 98 | 99 | @Override 100 | public void mouseReleased(int mousex, int mousey) { 101 | if (this.firstGui != null && !NEECraftingPreviewHandler.instance 102 | .handle(this.firstGui, this.handlerRef.handler, this.handlerRef.recipeIndex)) { 103 | super.mouseReleased(mousex, mousey); 104 | } 105 | } 106 | 107 | @Override 108 | public Map handleHotkeys(int mousex, int mousey, Map hotkeys) { 109 | hotkeys = super.handleHotkeys(mousex, mousey, hotkeys); 110 | 111 | if (ingredientsOverlay().stream().allMatch( 112 | state -> state.isPresent() 113 | || state instanceof NEEItemOverlayState overlayState && showCraftingHotkeys(overlayState))) { 114 | 115 | if (NEECraftingPreviewHandler.instance 116 | .canCraftRecipeResult(this.firstGui, this.handlerRef.handler, handlerRef.recipeIndex)) { 117 | hotkeys.put( 118 | NEIClientConfig.getKeyName("nee.preview", 0, NEIMouseUtils.MOUSE_BTN_LMB), 119 | I18n.format("neenergistics.gui.tooltip.crafting.preview.result")); 120 | 121 | hotkeys.put( 122 | NEIClientConfig.getKeyName("nee.nopreview", 0, NEIMouseUtils.MOUSE_BTN_LMB), 123 | I18n.format("neenergistics.gui.tooltip.crafting.nopreview.result")); 124 | } else { 125 | hotkeys.put( 126 | NEIClientConfig.getKeyName("nee.preview", 0, NEIMouseUtils.MOUSE_BTN_LMB), 127 | I18n.format("neenergistics.gui.tooltip.crafting.preview")); 128 | 129 | hotkeys.put( 130 | NEIClientConfig.getKeyName("nee.nopreview", 0, NEIMouseUtils.MOUSE_BTN_LMB), 131 | I18n.format("neenergistics.gui.tooltip.crafting.nopreview")); 132 | } 133 | 134 | } 135 | 136 | return hotkeys; 137 | } 138 | 139 | private static boolean showCraftingHotkeys(NEEItemOverlayState button) { 140 | return button.getIngredient().isCraftable() || !button.getIngredient().requiresToCraft(); 141 | } 142 | 143 | public static void updateRecipeButtons(GuiRecipe guiRecipe, List buttonList) { 144 | for (int i = 0; i < buttonList.size(); i++) { 145 | if (buttonList.get(i) instanceof GuiOverlayButton btn) { 146 | buttonList.set(i, new NEETerminalOverlayButton(btn)); 147 | } 148 | } 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketNEIBookmark.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.entity.player.EntityPlayerMP; 5 | import net.minecraft.inventory.Container; 6 | import net.minecraft.item.ItemStack; 7 | import net.minecraft.nbt.NBTTagCompound; 8 | import net.minecraftforge.common.util.ForgeDirection; 9 | 10 | import com.github.vfyjxf.nee.utils.ItemUtils; 11 | import com.github.vfyjxf.nee.utils.ModIDs; 12 | 13 | import appeng.api.networking.IGrid; 14 | import appeng.api.networking.energy.IEnergyGrid; 15 | import appeng.api.networking.energy.IEnergySource; 16 | import appeng.api.networking.security.BaseActionSource; 17 | import appeng.api.networking.security.PlayerSource; 18 | import appeng.api.storage.IMEMonitor; 19 | import appeng.api.storage.data.IAEItemStack; 20 | import appeng.container.implementations.ContainerMEMonitorable; 21 | import appeng.util.InventoryAdaptor; 22 | import appeng.util.Platform; 23 | import appeng.util.item.AEItemStack; 24 | import cpw.mods.fml.common.Loader; 25 | import cpw.mods.fml.common.network.ByteBufUtils; 26 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 27 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 28 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 29 | import cpw.mods.fml.relauncher.ReflectionHelper; 30 | import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException; 31 | import io.netty.buffer.ByteBuf; 32 | import thaumicenergistics.common.container.ContainerPartArcaneCraftingTerminal; 33 | 34 | public class PacketNEIBookmark implements IMessage { 35 | 36 | private NBTTagCompound bookmarkItems; 37 | 38 | public PacketNEIBookmark() {} 39 | 40 | public PacketNEIBookmark(NBTTagCompound bookmarkItems) { 41 | this.bookmarkItems = bookmarkItems; 42 | } 43 | 44 | @Override 45 | public void fromBytes(ByteBuf buf) { 46 | this.bookmarkItems = ByteBufUtils.readTag(buf); 47 | } 48 | 49 | @Override 50 | public void toBytes(ByteBuf buf) { 51 | ByteBufUtils.writeTag(buf, this.bookmarkItems); 52 | } 53 | 54 | public static final class Handler implements IMessageHandler { 55 | 56 | @Override 57 | public IMessage onMessage(PacketNEIBookmark message, MessageContext ctx) { 58 | final EntityPlayerMP player = ctx.getServerHandler().playerEntity; 59 | final Container container = player.openContainer; 60 | 61 | if (message.bookmarkItems == null) { 62 | return null; 63 | } 64 | 65 | if (container instanceof ContainerMEMonitorable monitorable) { 66 | final IMEMonitor monitor = monitorable.getMonitor(); 67 | if (monitor != null) { 68 | final IEnergySource energy = monitorable.getPowerSource(); 69 | final BaseActionSource actionSource = monitorable.getActionSource(); 70 | 71 | for (Object key : message.bookmarkItems.func_150296_c()) { 72 | final ItemStack bookmarkItem = ItemUtils 73 | .loadItemStackFromNBT(message.bookmarkItems.getCompoundTag((String) key)); 74 | bookmarkItem.stackSize = getFreeStackSize(player, bookmarkItem); 75 | 76 | if (bookmarkItem.stackSize > 0) { 77 | final AEItemStack requestStack = AEItemStack.create(bookmarkItem); 78 | final IAEItemStack extractedStack = Platform 79 | .poweredExtraction(energy, monitor, requestStack, actionSource); 80 | 81 | if (extractedStack != null) { 82 | InventoryAdaptor.getAdaptor(player, ForgeDirection.UNKNOWN) 83 | .addItems(extractedStack.getItemStack()); 84 | } 85 | } 86 | } 87 | } 88 | 89 | } else if (Loader.isModLoaded(ModIDs.ThE) && container instanceof ContainerPartArcaneCraftingTerminal act) { 90 | final IMEMonitor monitor = getMonitor(container); 91 | final IGrid grid = act.getHostGrid(); 92 | if (grid == null || monitor == null) return null; 93 | final IEnergyGrid energy = grid.getCache(IEnergyGrid.class); 94 | final BaseActionSource actionSource = new PlayerSource(player, act.terminal); 95 | 96 | for (Object key : message.bookmarkItems.func_150296_c()) { 97 | final ItemStack bookmarkItem = ItemUtils 98 | .loadItemStackFromNBT(message.bookmarkItems.getCompoundTag((String) key)); 99 | bookmarkItem.stackSize = getFreeStackSize(player, bookmarkItem); 100 | 101 | if (bookmarkItem.stackSize > 0) { 102 | final AEItemStack requestStack = AEItemStack.create(bookmarkItem); 103 | final IAEItemStack extractedStack = Platform 104 | .poweredExtraction(energy, monitor, requestStack, actionSource); 105 | 106 | if (extractedStack != null) { 107 | InventoryAdaptor.getAdaptor(player, ForgeDirection.UNKNOWN) 108 | .addItems(extractedStack.getItemStack()); 109 | } 110 | } 111 | } 112 | 113 | } 114 | 115 | return null; 116 | } 117 | 118 | private int getFreeStackSize(EntityPlayer player, ItemStack itemStack) { 119 | int freeStackSize = 0; 120 | 121 | for (ItemStack slotStack : player.inventory.mainInventory) { 122 | if (slotStack == null) { // Empty slot, stack fits completely 123 | freeStackSize += itemStack.getMaxStackSize(); 124 | } else if (slotStack.isItemEqual(itemStack)) { 125 | freeStackSize += itemStack.getMaxStackSize() - slotStack.stackSize; 126 | } 127 | } 128 | 129 | return Math.min(itemStack.stackSize, freeStackSize); 130 | } 131 | 132 | private IMEMonitor getMonitor(Container container) { 133 | 134 | try { 135 | return (IMEMonitor) ReflectionHelper.findField(container.getClass(), "monitor") 136 | .get(container); 137 | } catch (UnableToFindFieldException | IllegalAccessException e) {} 138 | 139 | return null; 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/container/ContainerPatternInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.container; 2 | 3 | import static appeng.container.slot.SlotRestrictedInput.PlacableItemType.ENCODED_PATTERN; 4 | 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.entity.player.InventoryPlayer; 7 | import net.minecraft.inventory.IInventory; 8 | import net.minecraft.inventory.InventoryCrafting; 9 | import net.minecraft.inventory.Slot; 10 | import net.minecraft.item.ItemStack; 11 | 12 | import com.github.vfyjxf.nee.block.tile.TilePatternInterface; 13 | 14 | import appeng.api.implementations.ICraftingPatternItem; 15 | import appeng.api.networking.crafting.ICraftingPatternDetails; 16 | import appeng.api.storage.data.IAEItemStack; 17 | import appeng.container.AEBaseContainer; 18 | import appeng.container.ContainerNull; 19 | import appeng.container.guisync.GuiSync; 20 | import appeng.container.slot.AppEngSlot; 21 | import appeng.container.slot.SlotDisabled; 22 | import appeng.container.slot.SlotRestrictedInput; 23 | import appeng.tile.inventory.AppEngInternalInventory; 24 | import appeng.tile.inventory.IAEAppEngInventory; 25 | import appeng.tile.inventory.InvOperation; 26 | import appeng.util.Platform; 27 | 28 | public class ContainerPatternInterface extends AEBaseContainer implements IAEAppEngInventory { 29 | 30 | private final AppEngInternalInventory recipeInv; 31 | private final AppEngInternalInventory patterns; 32 | private final SlotRestrictedInput[] patternSlots = new SlotRestrictedInput[9]; 33 | private final AppEngSlot[] recipeSlots = new AppEngSlot[10]; 34 | 35 | @GuiSync(0) 36 | private int selectedSlotIndex = -1; 37 | 38 | public ContainerPatternInterface(InventoryPlayer playerInventory, TilePatternInterface tile) { 39 | super(playerInventory, tile); 40 | this.recipeInv = tile.getGirdInventory(); 41 | this.patterns = tile.getPatternInventory(); 42 | 43 | for (int i = 0; i < patterns.getSizeInventory(); i++) { 44 | addSlotToContainer( 45 | patternSlots[i] = new SlotRestrictedInput( 46 | ENCODED_PATTERN, 47 | patterns, 48 | i, 49 | 8 + 18 * i, 50 | 90 + 5, 51 | playerInventory) { 52 | 53 | @Override 54 | public boolean isItemValid(ItemStack i) { 55 | return false; 56 | } 57 | 58 | @Override 59 | public boolean canTakeStack(EntityPlayer par1EntityPlayer) { 60 | return false; 61 | } 62 | }); 63 | } 64 | 65 | for (int y = 0; y < 3; y++) { 66 | for (int x = 0; x < 3; x++) { 67 | this.addSlotToContainer( 68 | recipeSlots[x + y * 3] = new SlotDisabled(recipeInv, x + y * 3, 29 + x * 18, 30 + y * 18)); 69 | } 70 | } 71 | 72 | this.addSlotToContainer(recipeSlots[9] = new SlotDisabled(recipeInv, 9, 126, 48)); 73 | 74 | this.bindPlayerInventory(playerInventory, 0, 184 - 69); 75 | } 76 | 77 | @Override 78 | public void onContainerClosed(EntityPlayer playerIn) { 79 | super.onContainerClosed(playerIn); 80 | clearRecipe(); 81 | } 82 | 83 | @Override 84 | public boolean canInteractWith(EntityPlayer playerIn) { 85 | return isValidContainer(); 86 | } 87 | 88 | public Slot getSelectedSlot() { 89 | return selectedSlotIndex >= 0 && selectedSlotIndex <= 9 ? patternSlots[selectedSlotIndex] : null; 90 | } 91 | 92 | public AppEngInternalInventory getRecipeInventory() { 93 | return recipeInv; 94 | } 95 | 96 | public int getSelectedSlotIndex() { 97 | return selectedSlotIndex; 98 | } 99 | 100 | public void setSelectedSlotIndex(int index) { 101 | this.selectedSlotIndex = index; 102 | 103 | if (Platform.isServer()) { 104 | Slot slot = this.getSelectedSlot(); 105 | if (slot instanceof SlotRestrictedInput) { 106 | if (slot.getHasStack()) { 107 | ItemStack maybePattern = slot.getStack(); 108 | if (maybePattern.getItem() instanceof ICraftingPatternItem) { 109 | ICraftingPatternDetails details = ((ICraftingPatternItem) maybePattern.getItem()) 110 | .getPatternForItem(maybePattern, getTileEntity().getWorldObj()); 111 | 112 | if ((details.getInputs().length == 9) && (details.getOutputs().length > 0)) { 113 | InventoryCrafting ic = new InventoryCrafting(new ContainerNull(), 3, 3); 114 | for (int i = 0; i < details.getInputs().length; i++) { 115 | IAEItemStack stack = details.getInputs()[i]; 116 | Slot currentSlot = getSlotFromInventory(this.getRecipeInventory(), i); 117 | if (currentSlot != null) { 118 | if (stack != null) { 119 | ItemStack is = stack.getItemStack(); 120 | currentSlot.putStack(is); 121 | ic.setInventorySlotContents(i, is); 122 | } else { 123 | currentSlot.putStack(null); 124 | } 125 | } 126 | } 127 | Slot outSlot = getSlotFromInventory(this.getRecipeInventory(), 9); 128 | if (outSlot != null) { 129 | outSlot.putStack(details.getOutput(ic, getTileEntity().getWorldObj())); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | } 136 | 137 | this.detectAndSendChanges(); 138 | } 139 | 140 | public void removeCurrentRecipe() { 141 | Slot patternSlot = this.getSelectedSlot(); 142 | if (patternSlot != null && patternSlot.getHasStack()) { 143 | patternSlot.putStack(null); 144 | clearRecipe(); 145 | } 146 | this.detectAndSendChanges(); 147 | } 148 | 149 | private void clearRecipe() { 150 | for (Slot slot : this.recipeSlots) { 151 | slot.putStack(null); 152 | } 153 | } 154 | 155 | @Override 156 | public void saveChanges() {} 157 | 158 | @Override 159 | public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removedStack, 160 | ItemStack newStack) {} 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/utils/IngredientTracker.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import net.minecraft.client.Minecraft; 7 | import net.minecraft.client.gui.inventory.GuiContainer; 8 | import net.minecraft.inventory.Slot; 9 | import net.minecraft.item.ItemStack; 10 | 11 | import com.github.vfyjxf.nee.config.NEEConfig; 12 | 13 | import appeng.api.storage.data.IAEItemStack; 14 | import codechicken.nei.PositionedStack; 15 | import codechicken.nei.recipe.IRecipeHandler; 16 | 17 | public class IngredientTracker { 18 | 19 | private final List ingredients = new ArrayList<>(); 20 | private final GuiContainer termGui; 21 | private List requireStacks; 22 | private final int recipeIndex; 23 | private int currentIndex = 0; 24 | 25 | public IngredientTracker(GuiContainer termGui, IRecipeHandler recipe, int recipeIndex) { 26 | this.termGui = termGui; 27 | this.recipeIndex = recipeIndex; 28 | 29 | for (PositionedStack requiredIngredient : recipe.getIngredientStacks(recipeIndex)) { 30 | this.ingredients.add(new Ingredient(requiredIngredient)); 31 | } 32 | 33 | for (Ingredient ingredient : this.ingredients) { 34 | for (IAEItemStack stack : GuiUtils.getStorageStacks(this.termGui, IAEItemStack::isCraftable)) { 35 | if (ingredient.getIngredient().contains(stack.getItemStack())) { 36 | ingredient.setCraftableIngredient(stack.getItemStack()); 37 | } 38 | } 39 | } 40 | 41 | this.calculateIngredients(); 42 | } 43 | 44 | public List getIngredients() { 45 | return this.ingredients; 46 | } 47 | 48 | public List getRequireToCraftStacks() { 49 | List requireToCraftStacks = new ArrayList<>(); 50 | for (Ingredient ingredient : this.getIngredients()) { 51 | boolean find = false; 52 | if (ingredient.isCraftable() && ingredient.requiresToCraft()) { 53 | for (ItemStack stack : requireToCraftStacks) { 54 | boolean areStackEqual = stack.isItemEqual(ingredient.getCraftableIngredient()) 55 | && ItemStack.areItemStackTagsEqual(stack, ingredient.getCraftableIngredient()); 56 | if (areStackEqual) { 57 | stack.stackSize = (int) (stack.stackSize + ingredient.getMissingCount()); 58 | find = true; 59 | } 60 | } 61 | 62 | if (!find) { 63 | ItemStack requireStack = ingredient.getCraftableIngredient().copy(); 64 | requireStack.stackSize = ((int) ingredient.getMissingCount()); 65 | requireToCraftStacks.add(requireStack); 66 | } 67 | } 68 | } 69 | return requireToCraftStacks; 70 | } 71 | 72 | public List getRequireStacks() { 73 | return this.requireStacks; 74 | } 75 | 76 | public boolean hasNext() { 77 | return this.currentIndex < getRequireStacks().size(); 78 | } 79 | 80 | public ItemStack getNextIngredient() { 81 | return getRequiredStack(this.currentIndex++); 82 | } 83 | 84 | public ItemStack getRequiredStack(int index) { 85 | return getRequireStacks().get(index); 86 | } 87 | 88 | public int getRecipeIndex() { 89 | return this.recipeIndex; 90 | } 91 | 92 | public void addAvailableStack(ItemStack stack) { 93 | for (Ingredient ingredient : this.ingredients) { 94 | if (ingredient.requiresToCraft()) { 95 | if (NEEConfig.matchOtherItems) { 96 | if (stack.stackSize > 0 && ingredient.getIngredient().contains(stack)) { 97 | int missingCount = (int) ingredient.getMissingCount(); 98 | ingredient.addCount(stack.stackSize); 99 | if (ingredient.requiresToCraft()) { 100 | stack.stackSize = 0; 101 | } else { 102 | stack.stackSize -= missingCount; 103 | } 104 | break; 105 | } 106 | } else { 107 | ItemStack craftableStack = ingredient.getCraftableIngredient(); 108 | if (craftableStack != null && craftableStack.isItemEqual(stack) 109 | && ItemStack.areItemStackTagsEqual(craftableStack, stack) 110 | && stack.stackSize > 0) { 111 | int missingCount = (int) ingredient.getMissingCount(); 112 | ingredient.addCount(stack.stackSize); 113 | if (ingredient.requiresToCraft()) { 114 | stack.stackSize = 0; 115 | } else { 116 | stack.stackSize -= missingCount; 117 | } 118 | break; 119 | } 120 | } 121 | } 122 | } 123 | } 124 | 125 | public void calculateIngredients() { 126 | final List stacks = GuiUtils 127 | .getStorageStacks(this.termGui, stack -> NEEConfig.matchOtherItems || stack.isCraftable()); 128 | 129 | for (Ingredient ingredient : this.ingredients) { 130 | ingredient.setCurrentCount(0); 131 | for (IAEItemStack stack : stacks) { 132 | if (stack.getStackSize() > 0 && ingredient.getIngredient().contains(stack.getItemStack())) { 133 | ingredient.addCount(stack.getStackSize()); 134 | if (ingredient.requiresToCraft()) { 135 | stack.setStackSize(0); 136 | } else { 137 | stack.setStackSize(stack.getStackSize() - ingredient.getRequireCount()); 138 | } 139 | } 140 | } 141 | } 142 | 143 | final List inventoryStacks = new ArrayList<>(); 144 | 145 | for (Slot slot : (List) termGui.inventorySlots.inventorySlots) { 146 | final boolean canGetStack = slot != null && slot.getHasStack() 147 | && slot.getStack().stackSize > 0 148 | && slot.isItemValid(slot.getStack()) 149 | && slot.canTakeStack(Minecraft.getMinecraft().thePlayer); 150 | if (canGetStack) { 151 | inventoryStacks.add(slot.getStack().copy()); 152 | } 153 | } 154 | 155 | for (int i = 0; i < getIngredients().size(); i++) { 156 | for (ItemStack stack : inventoryStacks) { 157 | addAvailableStack(stack); 158 | } 159 | } 160 | 161 | this.requireStacks = this.getRequireToCraftStacks(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/NEECommands.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee; 2 | 3 | import static com.github.vfyjxf.nee.NotEnoughEnergistics.logger; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import net.minecraft.client.Minecraft; 10 | import net.minecraft.command.CommandBase; 11 | import net.minecraft.command.ICommandSender; 12 | import net.minecraft.command.WrongUsageException; 13 | import net.minecraft.item.ItemStack; 14 | import net.minecraft.util.ChatComponentText; 15 | 16 | import com.github.vfyjxf.nee.config.NEEConfig; 17 | import com.github.vfyjxf.nee.processor.IRecipeProcessor; 18 | import com.github.vfyjxf.nee.processor.RecipeProcessor; 19 | import com.github.vfyjxf.nee.utils.ItemUtils; 20 | import com.google.gson.Gson; 21 | import com.google.gson.JsonObject; 22 | import com.google.gson.JsonParser; 23 | 24 | public class NEECommands extends CommandBase { 25 | 26 | @Override 27 | public String getCommandName() { 28 | return "nee"; 29 | } 30 | 31 | @Override 32 | public String getCommandUsage(ICommandSender sender) { 33 | return "See /nee help"; 34 | } 35 | 36 | @Override 37 | public void processCommand(ICommandSender sender, String[] args) { 38 | if (args.length != 0) { 39 | if ("help".equalsIgnoreCase(args[0])) { 40 | sender.addChatMessage(new ChatComponentText("Usage:")); 41 | sender.addChatMessage(new ChatComponentText("/nee add blacklist/priorityItem processor_id identifier")); 42 | sender.addChatMessage( 43 | new ChatComponentText("/nee add blacklist/priorityItem/itemCombination identifier")); 44 | } else if ("processor".equalsIgnoreCase(args[0])) { 45 | for (IRecipeProcessor processor : RecipeProcessor.recipeProcessors) { 46 | logger.info("RecipeProcessor:" + processor.getRecipeProcessorId() + " identifier:"); 47 | for (String ident : processor.getAllOverlayIdentifier()) { 48 | logger.info(ident); 49 | } 50 | } 51 | } else if ("add".equalsIgnoreCase(args[0]) && args.length > 1) { 52 | if ("blacklist".equalsIgnoreCase(args[1]) || "priorityItem".equalsIgnoreCase(args[1])) { 53 | ItemStack currentStack = Minecraft.getMinecraft().thePlayer.getCurrentEquippedItem(); 54 | if (currentStack != null) { 55 | String currentItemJsonString = ItemUtils.toItemJsonString(currentStack); 56 | JsonObject itemJsonObject = new JsonParser().parse(currentItemJsonString).getAsJsonObject(); 57 | if (args.length >= 3) { 58 | boolean hasRecipeProcessor = ItemUtils.hasRecipeProcessor(args[2]); 59 | boolean hasOverlayIdentifier = ItemUtils.hasOverlayIdentifier(args[2]); 60 | 61 | if (args.length == 4) { 62 | hasOverlayIdentifier = ItemUtils.hasOverlayIdentifier(args[3]); 63 | } 64 | 65 | if (hasRecipeProcessor) { 66 | itemJsonObject.addProperty("recipeProcessor", args[2]); 67 | } else if (!hasOverlayIdentifier) { 68 | sender.addChatMessage(new ChatComponentText("Can't find processor: " + args[2])); 69 | } 70 | 71 | if (hasOverlayIdentifier) { 72 | itemJsonObject.addProperty("identifier", args.length == 4 ? args[3] : args[2]); 73 | } else if (!hasRecipeProcessor) { 74 | sender.addChatMessage(new ChatComponentText("Can't find identifier: " + args[2])); 75 | } 76 | } 77 | String newJsonString = new Gson().toJson(itemJsonObject); 78 | String[] oldList = "blacklist".equalsIgnoreCase(args[1]) ? NEEConfig.transformBlacklist 79 | : NEEConfig.transformPriorityList; 80 | List newList = new ArrayList<>(Arrays.asList(oldList)); 81 | for (String currentJsonString : oldList) { 82 | if (currentJsonString.equals(newJsonString)) { 83 | return; 84 | } 85 | } 86 | newList.add(newJsonString); 87 | if ("blacklist".equalsIgnoreCase(args[1])) { 88 | NEEConfig.setTransformBlacklist(newList.toArray(new String[0])); 89 | } else { 90 | NEEConfig.setTransformPriorityList(newList.toArray(new String[0])); 91 | } 92 | } 93 | } else if ("priorityMod".equalsIgnoreCase(args[1]) && args.length == 3) { 94 | String modid = args[2]; 95 | if (!ItemUtils.hasModId(modid)) { 96 | List newList = new ArrayList<>(Arrays.asList(NEEConfig.transformPriorityModList)); 97 | newList.add(modid); 98 | NEEConfig.setTransformPriorityModList(newList.toArray(new String[0])); 99 | } 100 | } else if ("itemCombination".equalsIgnoreCase(args[1]) && args.length == 3) { 101 | String identifier = args[2]; 102 | if (!Arrays.asList(NEEConfig.itemCombinationWhitelist).contains(identifier)) { 103 | if (ItemUtils.hasOverlayIdentifier(args[2])) { 104 | List newLists = new ArrayList<>(Arrays.asList(NEEConfig.itemCombinationWhitelist)); 105 | newLists.add(identifier); 106 | NEEConfig.setItemCombinationWhitelist(newLists.toArray(new String[0])); 107 | } else { 108 | sender.addChatMessage(new ChatComponentText("Can't find identifier: " + args[2])); 109 | } 110 | } 111 | } 112 | } else if ("reload".equalsIgnoreCase(args[0])) { 113 | NEEConfig.reload(); 114 | } 115 | } else { 116 | throw new WrongUsageException(""); 117 | } 118 | } 119 | 120 | @Override 121 | public List addTabCompletionOptions(ICommandSender sender, String[] args) { 122 | return args.length <= 1 123 | ? CommandBase.getListOfStringsMatchingLastWord(args, "help", "reload", "add", "processor") 124 | : args.length == 2 ? CommandBase.getListOfStringsMatchingLastWord( 125 | args, 126 | "blacklist", 127 | "priorityItem", 128 | "priorityMod", 129 | "itemCombination") : null; 130 | } 131 | 132 | @Override 133 | public int getRequiredPermissionLevel() { 134 | return 1; 135 | } 136 | 137 | @Override 138 | public boolean canCommandSenderUseCommand(ICommandSender sender) { 139 | return true; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/nei/NEEKnowledgeInscriberHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.nei; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import net.minecraft.client.gui.inventory.GuiContainer; 7 | import net.minecraft.item.ItemStack; 8 | import net.minecraft.nbt.NBTTagCompound; 9 | 10 | import com.github.vfyjxf.nee.config.NEEConfig; 11 | import com.github.vfyjxf.nee.network.NEENetworkHandler; 12 | import com.github.vfyjxf.nee.network.packet.PacketArcaneRecipe; 13 | import com.github.vfyjxf.nee.utils.Ingredient; 14 | import com.github.vfyjxf.nee.utils.IngredientTracker; 15 | import com.github.vfyjxf.nee.utils.ItemUtils; 16 | import com.github.vfyjxf.nee.utils.ModIDs; 17 | 18 | import appeng.util.Platform; 19 | import codechicken.nei.ItemsTooltipLineHandler; 20 | import codechicken.nei.NEIClientUtils; 21 | import codechicken.nei.PositionedStack; 22 | import codechicken.nei.api.IOverlayHandler; 23 | import codechicken.nei.recipe.GuiOverlayButton; 24 | import codechicken.nei.recipe.GuiRecipe; 25 | import codechicken.nei.recipe.GuiRecipeButton; 26 | import codechicken.nei.recipe.IRecipeHandler; 27 | import cpw.mods.fml.common.Loader; 28 | import cpw.mods.fml.common.eventhandler.SubscribeEvent; 29 | 30 | /** 31 | * @author vfyjxf 32 | */ 33 | public class NEEKnowledgeInscriberHandler implements IOverlayHandler { 34 | 35 | public class NEEArcaneOverlayButton extends NEETerminalOverlayButton { 36 | 37 | public NEEArcaneOverlayButton(GuiOverlayButton button) { 38 | super(button.firstGui, button.handlerRef, button.xPosition, button.yPosition); 39 | } 40 | 41 | @Override 42 | protected List ingredientsOverlay() { 43 | List ingredients = this.handlerRef.handler 44 | .getIngredientStacks(this.handlerRef.recipeIndex); 45 | 46 | if (this.itemPresenceCache.size() != ingredients.size()) { 47 | this.itemPresenceCache.clear(); 48 | 49 | final IngredientTracker tracker = new IngredientTracker( 50 | firstGui, 51 | this.handlerRef.handler, 52 | this.handlerRef.recipeIndex); 53 | 54 | for (Ingredient ingredient : tracker.getIngredients()) { 55 | this.itemPresenceCache.add(new NEEItemOverlayState(ingredient, true)); 56 | } 57 | 58 | List items = this.itemPresenceCache.stream().filter(state -> !state.isPresent()) 59 | .map(state -> state.getSlot().item).collect(Collectors.toList()); 60 | 61 | if (!items.isEmpty()) { 62 | this.missedMaterialsTooltipLineHandler = new ItemsTooltipLineHandler( 63 | NEIClientUtils.translate("recipe.overlay.missing"), 64 | items, 65 | true, 66 | Integer.MAX_VALUE); 67 | } else { 68 | this.missedMaterialsTooltipLineHandler = null; 69 | } 70 | } 71 | 72 | return this.itemPresenceCache; 73 | } 74 | 75 | } 76 | 77 | public static final NEEKnowledgeInscriberHandler instance = new NEEKnowledgeInscriberHandler(); 78 | 79 | private Class knowledgeInscriberClz; 80 | private Class itemAspectClz; 81 | 82 | private NEEKnowledgeInscriberHandler() { 83 | 84 | try { 85 | // "Knowledge Inscriber" 86 | knowledgeInscriberClz = Class.forName("thaumicenergistics.client.gui.GuiKnowledgeInscriber"); 87 | } catch (ClassNotFoundException ignored) {} 88 | 89 | try { 90 | itemAspectClz = Class.forName("com.djgiannuzz.thaumcraftneiplugin.items.ItemAspect"); 91 | } catch (ClassNotFoundException ignored) {} 92 | 93 | } 94 | 95 | @Override 96 | public void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift) { 97 | if (knowledgeInscriberClz != null && knowledgeInscriberClz.isInstance(firstGui)) { 98 | NEENetworkHandler.getInstance().sendToServer(packetArcaneRecipe(recipe, recipeIndex)); 99 | } 100 | } 101 | 102 | private PacketArcaneRecipe packetArcaneRecipe(IRecipeHandler recipe, int recipeIndex) { 103 | final NBTTagCompound recipeInputs = new NBTTagCompound(); 104 | final List ingredients = recipe.getIngredientStacks(recipeIndex); 105 | 106 | if (itemAspectClz != null) { 107 | ingredients.removeIf(positionedStack -> itemAspectClz.isInstance(positionedStack.item.getItem())); 108 | } 109 | 110 | for (PositionedStack positionedStack : ingredients) { 111 | if (positionedStack.items != null && positionedStack.items.length > 0) { 112 | final int slotIndex = getSlotIndex(positionedStack.relx * 100 + positionedStack.rely); 113 | final ItemStack[] currentStackList = positionedStack.items; 114 | ItemStack stack = positionedStack.item; 115 | 116 | for (ItemStack currentStack : currentStackList) { 117 | if (Platform.isRecipePrioritized(currentStack)) { 118 | stack = currentStack.copy(); 119 | } 120 | } 121 | 122 | recipeInputs.setTag("#" + slotIndex, ItemUtils.writeItemStackToNBT(stack, stack.stackSize)); 123 | } 124 | } 125 | 126 | return new PacketArcaneRecipe(recipeInputs); 127 | } 128 | 129 | private int getSlotIndex(int xy) { 130 | switch (xy) { 131 | case 7533: 132 | return 1; 133 | case 10333: 134 | return 2; 135 | case 4960: 136 | return 3; 137 | case 7660: 138 | return 4; 139 | case 10360: 140 | return 5; 141 | case 4987: 142 | return 6; 143 | case 7687: 144 | return 7; 145 | case 10387: 146 | return 8; 147 | case 4832: 148 | default: 149 | return 0; 150 | } 151 | } 152 | 153 | @SubscribeEvent 154 | public void onActionPerformedEventPost(GuiRecipeButton.UpdateRecipeButtonsEvent.Post event) { 155 | 156 | if (NEEConfig.noShift && event.gui instanceof GuiRecipe guiRecipe) { 157 | 158 | if (isGuiArcaneCraftingTerm(guiRecipe)) { 159 | for (int i = 0; i < event.buttonList.size(); i++) { 160 | if (event.buttonList.get(i) instanceof GuiOverlayButton btn) { 161 | event.buttonList.set(i, new NEEArcaneOverlayButton(btn)); 162 | } 163 | } 164 | } else if (isGuiKnowledgeInscriber(guiRecipe)) { 165 | for (int i = 0; i < event.buttonList.size(); i++) { 166 | if (event.buttonList.get(i) instanceof GuiOverlayButton btn) { 167 | btn.setRequireShiftForOverlayRecipe(false); 168 | } 169 | } 170 | } 171 | } 172 | 173 | } 174 | 175 | private boolean isGuiKnowledgeInscriber(GuiRecipe gui) { 176 | return gui.firstGui != null && this.getClass().isInstance(gui.getHandler().getOverlayHandler(gui.firstGui, 0)); 177 | } 178 | 179 | private boolean isGuiArcaneCraftingTerm(GuiRecipe gui) { 180 | return Loader.isModLoaded(ModIDs.ThE) 181 | && gui.firstGui instanceof thaumicenergistics.client.gui.GuiArcaneCraftingTerminal; 182 | } 183 | 184 | } 185 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/network/packet/PacketNEIPatternRecipe.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.network.packet; 2 | 3 | import static com.github.vfyjxf.nee.nei.NEEPatternTerminalHandler.INPUT_KEY; 4 | import static com.github.vfyjxf.nee.nei.NEEPatternTerminalHandler.OUTPUT_KEY; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | import net.minecraft.entity.player.EntityPlayerMP; 9 | import net.minecraft.inventory.Container; 10 | import net.minecraft.item.ItemStack; 11 | import net.minecraft.nbt.NBTTagCompound; 12 | 13 | import com.github.vfyjxf.nee.utils.GuiUtils; 14 | import com.github.vfyjxf.nee.utils.ItemUtils; 15 | 16 | import appeng.api.networking.IGrid; 17 | import appeng.api.networking.IGridNode; 18 | import appeng.api.networking.security.ISecurityGrid; 19 | import appeng.api.networking.storage.IStorageGrid; 20 | import appeng.api.storage.StorageName; 21 | import appeng.api.storage.data.IAEStack; 22 | import appeng.container.AEBaseContainer; 23 | import appeng.container.implementations.ContainerPatternTerm; 24 | import appeng.helpers.IContainerCraftingPacket; 25 | import appeng.util.item.AEFluidStack; 26 | import appeng.util.item.AEItemStack; 27 | import codechicken.nei.recipe.StackInfo; 28 | import cpw.mods.fml.common.network.ByteBufUtils; 29 | import cpw.mods.fml.common.network.simpleimpl.IMessage; 30 | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; 31 | import cpw.mods.fml.common.network.simpleimpl.MessageContext; 32 | import io.netty.buffer.ByteBuf; 33 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 34 | 35 | public class PacketNEIPatternRecipe implements IMessage { 36 | 37 | NBTTagCompound input; 38 | NBTTagCompound output; 39 | 40 | public PacketNEIPatternRecipe() {} 41 | 42 | public PacketNEIPatternRecipe(@Nonnull NBTTagCompound input, NBTTagCompound output) { 43 | this.input = input; 44 | this.output = output; 45 | } 46 | 47 | @Override 48 | public void fromBytes(ByteBuf buf) { 49 | this.input = ByteBufUtils.readTag(buf); 50 | if (buf.readBoolean()) { 51 | this.output = ByteBufUtils.readTag(buf); 52 | } 53 | } 54 | 55 | @Override 56 | public void toBytes(ByteBuf buf) { 57 | ByteBufUtils.writeTag(buf, this.input); 58 | if (this.output != null) { 59 | buf.writeBoolean(true); 60 | ByteBufUtils.writeTag(buf, this.output); 61 | } else { 62 | buf.writeBoolean(false); 63 | } 64 | } 65 | 66 | public static final class Handler implements IMessageHandler { 67 | 68 | @Override 69 | public IMessage onMessage(PacketNEIPatternRecipe message, MessageContext ctx) { 70 | EntityPlayerMP player = ctx.getServerHandler().playerEntity; 71 | Container container = player.openContainer; 72 | 73 | if (message.input != null && GuiUtils.isPatternContainer(container) 74 | && container instanceof IContainerCraftingPacket) { 75 | ContainerPatternTerm baseContainer = (ContainerPatternTerm) container; 76 | setCraftingRecipe(baseContainer, message.output == null); 77 | 78 | if (message.output == null) { 79 | craftingRecipe(baseContainer, message); 80 | } else { 81 | processRecipe(baseContainer, message); 82 | } 83 | } 84 | 85 | return null; 86 | } 87 | 88 | private void setCraftingRecipe(AEBaseContainer container, boolean craftingMode) { 89 | 90 | if (container instanceof ContainerPatternTerm cpt) { 91 | cpt.setCraftingMode(craftingMode); 92 | } 93 | 94 | } 95 | 96 | private ItemStack[] getMatrix(NBTTagCompound items, String prefix, int size) { 97 | ItemStack[] matrix = new ItemStack[size]; 98 | 99 | for (int i = 0; i < size; i++) { 100 | NBTTagCompound currentStack = (NBTTagCompound) items.getTag(prefix + i); 101 | matrix[i] = currentStack == null ? null : ItemUtils.loadItemStackFromNBT(currentStack); 102 | } 103 | 104 | return matrix; 105 | } 106 | 107 | private void craftingRecipe(ContainerPatternTerm container, PacketNEIPatternRecipe message) { 108 | final IGridNode node = container.getNetworkNode(); 109 | 110 | if (node == null) { 111 | return; 112 | } 113 | 114 | final IGrid grid = node.getGrid(); 115 | 116 | if (grid == null) { 117 | return; 118 | } 119 | 120 | final IStorageGrid inv = grid.getCache(IStorageGrid.class); 121 | final ISecurityGrid security = grid.getCache(ISecurityGrid.class); 122 | 123 | if (inv != null && security != null) { 124 | var list = new Int2ObjectOpenHashMap>(); 125 | final ItemStack[] recipeInput = getMatrix(message.input, INPUT_KEY, 9); 126 | 127 | for (int i = 0; i < recipeInput.length; i++) { 128 | IAEStack aes = AEItemStack.create(recipeInput[i]); 129 | list.put(i, aes); 130 | } 131 | 132 | container.receiveSlotStacks(StorageName.CRAFTING_INPUT, list); 133 | } 134 | } 135 | 136 | private void processRecipe(ContainerPatternTerm container, PacketNEIPatternRecipe message) { 137 | final IGridNode node = container.getNetworkNode(); 138 | 139 | if (node == null) { 140 | return; 141 | } 142 | 143 | final IGrid grid = node.getGrid(); 144 | 145 | if (grid == null) { 146 | return; 147 | } 148 | 149 | final IStorageGrid inv = grid.getCache(IStorageGrid.class); 150 | final ISecurityGrid security = grid.getCache(ISecurityGrid.class); 151 | 152 | if (inv != null && security != null) { 153 | var input = new Int2ObjectOpenHashMap>(); 154 | var output = new Int2ObjectOpenHashMap>(); 155 | 156 | final ItemStack[] recipeInput = getMatrix( 157 | message.input, 158 | INPUT_KEY, 159 | container.getPatternInputsWidth() * container.getPatternInputsHeigh() 160 | * container.getPatternInputPages()); 161 | final ItemStack[] recipeOutput = getMatrix( 162 | message.output, 163 | OUTPUT_KEY, 164 | container.getPatternOutputsWidth() * container.getPatternOutputsHeigh() 165 | * container.getPatternOutputPages()); 166 | 167 | for (int i = 0; i < recipeInput.length; i++) { 168 | final ItemStack nextStack = recipeInput[i]; 169 | if (nextStack == null) continue; 170 | 171 | final IAEStack aes; 172 | if (StackInfo.itemStackToNBT(nextStack).hasKey("gtFluidName")) { 173 | aes = AEFluidStack.create(StackInfo.getFluid(nextStack)); 174 | } else { 175 | aes = AEItemStack.create(nextStack); 176 | } 177 | 178 | input.put(i, aes); 179 | } 180 | 181 | for (int i = 0; i < recipeOutput.length; i++) { 182 | final ItemStack nextStack = recipeOutput[i]; 183 | if (nextStack == null) continue; 184 | 185 | IAEStack aes; 186 | if (StackInfo.itemStackToNBT(nextStack).hasKey("gtFluidName")) { 187 | aes = AEFluidStack.create(StackInfo.getFluid(nextStack)); 188 | } else { 189 | aes = AEItemStack.create(nextStack); 190 | } 191 | 192 | output.put(i, aes); 193 | } 194 | 195 | container.clear(); 196 | container.receiveSlotStacks(StorageName.CRAFTING_INPUT, input); 197 | container.receiveSlotStacks(StorageName.CRAFTING_OUTPUT, output); 198 | } 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/nei/NEECraftingTerminalHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee.nei; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.util.ArrayList; 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | import net.minecraft.client.gui.inventory.GuiContainer; 11 | import net.minecraft.inventory.Slot; 12 | import net.minecraft.item.ItemStack; 13 | import net.minecraft.nbt.CompressedStreamTools; 14 | import net.minecraft.nbt.NBTTagCompound; 15 | import net.minecraft.nbt.NBTTagList; 16 | import net.p455w0rd.wirelesscraftingterminal.client.gui.GuiWirelessCraftingTerminal; 17 | 18 | import com.github.vfyjxf.nee.NotEnoughEnergistics; 19 | import com.github.vfyjxf.nee.nei.NEETerminalOverlayButton.NEEItemOverlayState; 20 | import com.github.vfyjxf.nee.utils.Ingredient; 21 | import com.github.vfyjxf.nee.utils.IngredientTracker; 22 | import com.github.vfyjxf.nee.utils.ModIDs; 23 | 24 | import appeng.container.slot.SlotCraftingMatrix; 25 | import appeng.container.slot.SlotFakeCraftingMatrix; 26 | import appeng.core.AELog; 27 | import appeng.core.sync.AppEngPacket; 28 | import appeng.core.sync.network.NetworkHandler; 29 | import appeng.core.sync.packets.PacketNEIRecipe; 30 | import appeng.util.Platform; 31 | import codechicken.nei.PositionedStack; 32 | import codechicken.nei.api.IOverlayHandler; 33 | import codechicken.nei.recipe.GuiOverlayButton.ItemOverlayState; 34 | import codechicken.nei.recipe.GuiRecipe; 35 | import codechicken.nei.recipe.GuiRecipeButton; 36 | import codechicken.nei.recipe.IRecipeHandler; 37 | import cpw.mods.fml.common.Loader; 38 | import cpw.mods.fml.common.Optional; 39 | import cpw.mods.fml.common.eventhandler.SubscribeEvent; 40 | import cpw.mods.fml.relauncher.ReflectionHelper; 41 | import io.netty.buffer.ByteBuf; 42 | 43 | public class NEECraftingTerminalHandler implements IOverlayHandler { 44 | 45 | public static final NEECraftingTerminalHandler instance = new NEECraftingTerminalHandler(); 46 | 47 | private NEECraftingTerminalHandler() {} 48 | 49 | /** 50 | * Copied from GTNewHorizons/Applied-Energistics-2-Unofficialr 51 | */ 52 | @Override 53 | public void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift) { 54 | try { 55 | final List ingredients = recipe.getIngredientStacks(recipeIndex); 56 | 57 | if (Loader.isModLoaded(ModIDs.WCT) && firstGui instanceof GuiWirelessCraftingTerminal) { 58 | moveItemsForWirelessCrafting(firstGui, ingredients); 59 | } else { 60 | PacketNEIRecipe packet = new PacketNEIRecipe(packIngredients(firstGui, ingredients, false)); 61 | // don't use gtnh ae2's method; 62 | int packetSize = getPacketSize(packet); 63 | if (packetSize >= 32 * 1024) { 64 | AELog.warn( 65 | "Recipe for " + recipe.getRecipeName() 66 | + " has too many variants, reduced version will be used"); 67 | packet = new PacketNEIRecipe(packIngredients(firstGui, ingredients, true)); 68 | } 69 | 70 | if (packetSize >= 0) { 71 | NetworkHandler.instance.sendToServer(packet); 72 | } else { 73 | NotEnoughEnergistics.logger.error("Can't get packet size!"); 74 | } 75 | } 76 | } catch (final Exception | Error ignored) {} 77 | } 78 | 79 | @Override 80 | public boolean canFillCraftingGrid(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex) { 81 | return true; 82 | } 83 | 84 | /** 85 | * Copied from GTNewHorizons/Applied-Energistics-2-Unofficial 86 | */ 87 | private boolean testSize(final NBTTagCompound recipe) throws IOException { 88 | final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 89 | final DataOutputStream outputStream = new DataOutputStream(bytes); 90 | CompressedStreamTools.writeCompressed(recipe, outputStream); 91 | return bytes.size() > 3 * 1024; 92 | } 93 | 94 | @Override 95 | public List presenceOverlay(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex) { 96 | final IngredientTracker tracker = new IngredientTracker(firstGui, handler, recipeIndex); 97 | final List itemPresenceSlots = new ArrayList<>(); 98 | 99 | for (Ingredient ingredient : tracker.getIngredients()) { 100 | itemPresenceSlots.add(new NEEItemOverlayState(ingredient, true)); 101 | } 102 | 103 | return itemPresenceSlots; 104 | } 105 | 106 | /** 107 | * Copied from GTNewHorizons/Applied-Energistics-2-Unofficial 108 | */ 109 | @SuppressWarnings("unchecked") 110 | private NBTTagCompound packIngredients(GuiContainer gui, List ingredients, boolean limited) 111 | throws IOException { 112 | final NBTTagCompound recipe = new NBTTagCompound(); 113 | 114 | for (final PositionedStack positionedStack : ingredients) { 115 | if (positionedStack.items != null && positionedStack.items.length > 0) { 116 | final int col = (positionedStack.relx - 25) / 18; 117 | final int row = (positionedStack.rely - 6) / 18; 118 | for (final Slot slot : (List) gui.inventorySlots.inventorySlots) { 119 | if (isCraftingMatrixSlot(gui, slot) && slot.getSlotIndex() == col + row * 3) { 120 | final NBTTagList tags = new NBTTagList(); 121 | final List list = new LinkedList<>(); 122 | 123 | // prefer pure crystals. 124 | for (ItemStack stack : positionedStack.getFilteredPermutations()) { 125 | stack = stack.copy(); 126 | if (Platform.isRecipePrioritized(stack)) { 127 | list.add(0, stack); 128 | } else { 129 | list.add(stack); 130 | } 131 | } 132 | 133 | for (final ItemStack is : list) { 134 | tags.appendTag(is.writeToNBT(new NBTTagCompound())); 135 | 136 | if (limited) { 137 | final NBTTagCompound test = new NBTTagCompound(); 138 | test.setTag("#" + slot.getSlotIndex(), tags); 139 | if (testSize(test)) { 140 | break; 141 | } 142 | } 143 | } 144 | 145 | recipe.setTag("#" + slot.getSlotIndex(), tags); 146 | break; 147 | } 148 | } 149 | } 150 | } 151 | 152 | return recipe; 153 | } 154 | 155 | private boolean isCraftingMatrixSlot(GuiContainer gui, Slot slot) { 156 | return slot instanceof SlotCraftingMatrix || slot instanceof SlotFakeCraftingMatrix; 157 | } 158 | 159 | private int getPacketSize(AppEngPacket packet) { 160 | try { 161 | ByteBuf p = (ByteBuf) ReflectionHelper.findField(AppEngPacket.class, "p").get(packet); 162 | return p.array().length; 163 | } catch (IllegalAccessException e) { 164 | return -1; 165 | } 166 | } 167 | 168 | @Optional.Method(modid = ModIDs.WCT) 169 | private void moveItemsForWirelessCrafting(GuiContainer firstGui, List ingredients) { 170 | try { 171 | net.p455w0rd.wirelesscraftingterminal.core.sync.network.NetworkHandler.instance.sendToServer( 172 | new net.p455w0rd.wirelesscraftingterminal.core.sync.packets.PacketNEIRecipe( 173 | packIngredients(firstGui, ingredients, false))); 174 | } catch (IOException e) { 175 | e.printStackTrace(); 176 | } 177 | } 178 | 179 | @SubscribeEvent 180 | public void onActionPerformedEventPost(GuiRecipeButton.UpdateRecipeButtonsEvent.Post event) { 181 | if (event.gui instanceof GuiRecipe guiRecipe && isGuiCraftingTerm(guiRecipe)) { 182 | NEETerminalOverlayButton.updateRecipeButtons(guiRecipe, event.buttonList); 183 | } 184 | } 185 | 186 | public static boolean isGuiCraftingTerm(GuiRecipe gui) { 187 | return gui.firstGui != null 188 | && NEECraftingTerminalHandler.class.isInstance(gui.getHandler().getOverlayHandler(gui.firstGui, 0)); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH="\\\"\\\"" 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | if ! command -v java >/dev/null 2>&1 137 | then 138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | fi 144 | 145 | # Increase the maximum file descriptors if we can. 146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 147 | case $MAX_FD in #( 148 | max*) 149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 150 | # shellcheck disable=SC2039,SC3045 151 | MAX_FD=$( ulimit -H -n ) || 152 | warn "Could not query maximum file descriptor limit" 153 | esac 154 | case $MAX_FD in #( 155 | '' | soft) :;; #( 156 | *) 157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 158 | # shellcheck disable=SC2039,SC3045 159 | ulimit -n "$MAX_FD" || 160 | warn "Could not set maximum file descriptor limit to $MAX_FD" 161 | esac 162 | fi 163 | 164 | # Collect all arguments for the java command, stacking in reverse order: 165 | # * args from the command line 166 | # * the main class name 167 | # * -classpath 168 | # * -D...appname settings 169 | # * --module-path (only if needed) 170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 171 | 172 | # For Cygwin or MSYS, switch paths to Windows format before running java 173 | if "$cygwin" || "$msys" ; then 174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 176 | 177 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 178 | 179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 180 | for arg do 181 | if 182 | case $arg in #( 183 | -*) false ;; # don't mess with options #( 184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 185 | [ -e "$t" ] ;; #( 186 | *) false ;; 187 | esac 188 | then 189 | arg=$( cygpath --path --ignore --mixed "$arg" ) 190 | fi 191 | # Roll the args list around exactly as many times as the number of 192 | # args, so each arg winds up back in the position where it started, but 193 | # possibly modified. 194 | # 195 | # NB: a `for` loop captures its iteration list before it begins, so 196 | # changing the positional parameters here affects neither the number of 197 | # iterations, nor the values presented in `arg`. 198 | shift # remove old arg 199 | set -- "$@" "$arg" # push replacement arg 200 | done 201 | fi 202 | 203 | 204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 206 | 207 | # Collect all arguments for the java command: 208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 209 | # and any embedded shellness will be escaped. 210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 211 | # treated as '${Hostname}' itself on the command line. 212 | 213 | set -- \ 214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 215 | -classpath "$CLASSPATH" \ 216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ 217 | "$@" 218 | 219 | # Stop when "xargs" is not available. 220 | if ! command -v xargs >/dev/null 2>&1 221 | then 222 | die "xargs is not available" 223 | fi 224 | 225 | # Use "xargs" to parse quoted args. 226 | # 227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 228 | # 229 | # In Bash we could simply go: 230 | # 231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 232 | # set -- "${ARGS[@]}" "$@" 233 | # 234 | # but POSIX shell has neither arrays nor command substitution, so instead we 235 | # post-process each arg (as a line of input to sed) to backslash-escape any 236 | # character that might be a shell metacharacter, then use eval to reverse 237 | # that process (while maintaining the separation between arguments), and wrap 238 | # the whole thing up as a single "set" statement. 239 | # 240 | # This will of course break if any of these variables contains a newline or 241 | # an unmatched quote. 242 | # 243 | 244 | eval "set -- $( 245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 246 | xargs -n1 | 247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 248 | tr '\n' ' ' 249 | )" '"$@"' 250 | 251 | exec "$JAVACMD" "$@" 252 | -------------------------------------------------------------------------------- /src/main/java/com/github/vfyjxf/nee/NEINeeConfig.java: -------------------------------------------------------------------------------- 1 | package com.github.vfyjxf.nee; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | import net.minecraft.client.gui.inventory.GuiContainer; 10 | import net.p455w0rd.wirelesscraftingterminal.client.gui.GuiWirelessCraftingTerminal; 11 | 12 | import org.lwjgl.input.Keyboard; 13 | 14 | import com.github.vfyjxf.nee.client.GuiEventHandler; 15 | import com.github.vfyjxf.nee.nei.NEECraftingTerminalHandler; 16 | import com.github.vfyjxf.nee.nei.NEEExtremeAutoCrafterHandler; 17 | import com.github.vfyjxf.nee.nei.NEEKnowledgeInscriberHandler; 18 | import com.github.vfyjxf.nee.nei.NEEPatternTerminalHandler; 19 | import com.github.vfyjxf.nee.nei.NEETerminalBookmarkContainerHandler; 20 | import com.github.vfyjxf.nee.processor.IRecipeProcessor; 21 | import com.github.vfyjxf.nee.processor.RecipeProcessor; 22 | import com.github.vfyjxf.nee.utils.ModIDs; 23 | 24 | import appeng.client.gui.implementations.GuiCraftingTerm; 25 | import appeng.client.gui.implementations.GuiInterface; 26 | import appeng.client.gui.implementations.GuiMEMonitorable; 27 | import appeng.client.gui.implementations.GuiMEPortableCell; 28 | import appeng.client.gui.implementations.GuiPatternTerm; 29 | import appeng.client.gui.implementations.GuiPatternTermEx; 30 | import codechicken.nei.NEIController; 31 | import codechicken.nei.api.API; 32 | import codechicken.nei.api.IConfigureNEI; 33 | import codechicken.nei.guihook.GuiContainerManager; 34 | import codechicken.nei.guihook.IContainerInputHandler; 35 | import codechicken.nei.recipe.DefaultOverlayHandler; 36 | import cpw.mods.fml.common.Loader; 37 | import fox.spiteful.avaritia.gui.GUIExtremeCrafting; 38 | import thaumicenergistics.client.gui.GuiArcaneCraftingTerminal; 39 | import thaumicenergistics.client.gui.GuiKnowledgeInscriber; 40 | import wanion.avaritiaddons.block.extremeautocrafter.GuiExtremeAutoCrafter; 41 | 42 | public class NEINeeConfig implements IConfigureNEI { 43 | 44 | private static final List> transferBlacklist = new ArrayList<>( 45 | Arrays.asList(GuiInterface.class, GuiPatternTerm.class)); 46 | 47 | @Override 48 | public void loadConfig() { 49 | 50 | RecipeProcessor.init(); 51 | 52 | registerKeyBindings(); 53 | 54 | registerGuiHandler(); 55 | 56 | Set defaultIdentifiers = new HashSet<>( 57 | Arrays.asList("crafting", "crafting2x2", "brewing", "smelting", "fuel", null)); 58 | Set identifiers = new HashSet<>(defaultIdentifiers); 59 | 60 | RecipeProcessor.recipeProcessors.stream().map(IRecipeProcessor::getAllOverlayIdentifier) 61 | .forEach(identifiers::addAll); 62 | 63 | for (String ident : identifiers) { 64 | API.registerGuiOverlay(GuiPatternTerm.class, ident); 65 | API.registerGuiOverlayHandler(GuiPatternTerm.class, NEEPatternTerminalHandler.instance, ident); 66 | } 67 | 68 | installCraftingTermSupport(); 69 | 70 | installWirelessCraftingTermSupport(); 71 | 72 | installThaumicEnergisticsSupport(); 73 | 74 | installAvaritiaSupport(); 75 | 76 | installAvaritiaddonsSupport(); 77 | 78 | installPatternTerminalExSupport(new HashSet<>(identifiers)); 79 | 80 | installlBookmarkContainerHandler(); 81 | } 82 | 83 | private void installlBookmarkContainerHandler() { 84 | API.registerBookmarkContainerHandler(GuiPatternTerm.class, NEETerminalBookmarkContainerHandler.instance); 85 | API.registerBookmarkContainerHandler(GuiPatternTermEx.class, NEETerminalBookmarkContainerHandler.instance); 86 | API.registerBookmarkContainerHandler(GuiCraftingTerm.class, NEETerminalBookmarkContainerHandler.instance); 87 | API.registerBookmarkContainerHandler(GuiMEMonitorable.class, NEETerminalBookmarkContainerHandler.instance); 88 | API.registerBookmarkContainerHandler(GuiMEPortableCell.class, NEETerminalBookmarkContainerHandler.instance); 89 | 90 | if (Loader.isModLoaded(ModIDs.WCT)) { 91 | API.registerBookmarkContainerHandler( 92 | GuiWirelessCraftingTerminal.class, 93 | NEETerminalBookmarkContainerHandler.instance); 94 | } 95 | 96 | if (Loader.isModLoaded(ModIDs.ThE)) { 97 | API.registerBookmarkContainerHandler( 98 | GuiArcaneCraftingTerminal.class, 99 | NEETerminalBookmarkContainerHandler.instance); 100 | } 101 | 102 | } 103 | 104 | @Override 105 | public String getName() { 106 | return NotEnoughEnergistics.NAME; 107 | } 108 | 109 | @Override 110 | public String getVersion() { 111 | return NotEnoughEnergistics.VERSION; 112 | } 113 | 114 | private void registerKeyBindings() { 115 | API.addKeyBind("nee.count", Keyboard.KEY_LCONTROL); 116 | API.addKeyBind("nee.ingredient", Keyboard.KEY_LSHIFT); 117 | API.addKeyBind("nee.preview", Keyboard.KEY_LCONTROL); 118 | API.addKeyBind("nee.nopreview", Keyboard.KEY_LMENU); 119 | } 120 | 121 | private void registerGuiHandler() { 122 | API.registerNEIGuiHandler(GuiEventHandler.instance); 123 | GuiContainerManager.addTooltipHandler(GuiEventHandler.instance); 124 | // disable MouseScrollTransfer in some gui 125 | replaceNEIController(); 126 | } 127 | 128 | private void replaceNEIController() { 129 | int controllerIndex = -1; 130 | for (IContainerInputHandler inputHandler : GuiContainerManager.inputHandlers) { 131 | if (inputHandler instanceof NEIController) { 132 | controllerIndex = GuiContainerManager.inputHandlers.indexOf(inputHandler); 133 | break; 134 | } 135 | } 136 | if (controllerIndex > 0) { 137 | GuiContainerManager.inputHandlers.remove(controllerIndex); 138 | GuiContainerManager.inputHandlers.add(controllerIndex, new NEIController() { 139 | 140 | @Override 141 | public boolean mouseScrolled(GuiContainer gui, int mouseX, int mouseY, int scrolled) { 142 | if (transferBlacklist.contains(gui.getClass())) { 143 | return false; 144 | } 145 | return super.mouseScrolled(gui, mouseX, mouseY, scrolled); 146 | } 147 | }); 148 | NotEnoughEnergistics.logger.info("NEIController replaced success"); 149 | } 150 | } 151 | 152 | private void installCraftingTermSupport() { 153 | API.registerGuiOverlay(GuiCraftingTerm.class, "crafting"); 154 | API.registerGuiOverlay(GuiCraftingTerm.class, "crafting2x2"); 155 | API.registerGuiOverlayHandler(GuiCraftingTerm.class, NEECraftingTerminalHandler.instance, "crafting"); 156 | API.registerGuiOverlayHandler(GuiCraftingTerm.class, NEECraftingTerminalHandler.instance, "crafting2x2"); 157 | } 158 | 159 | private void installWirelessCraftingTermSupport() { 160 | if (Loader.isModLoaded(ModIDs.WCT)) { 161 | API.registerGuiOverlayHandler( 162 | GuiWirelessCraftingTerminal.class, 163 | NEECraftingTerminalHandler.instance, 164 | "crafting"); 165 | API.registerGuiOverlayHandler( 166 | GuiWirelessCraftingTerminal.class, 167 | NEECraftingTerminalHandler.instance, 168 | "crafting2x2"); 169 | } 170 | } 171 | 172 | private void installThaumicEnergisticsSupport() { 173 | 174 | if (Loader.isModLoaded(ModIDs.ThE)) { 175 | NotEnoughEnergistics.logger.info("Install ThaumicEnergistics support"); 176 | 177 | try { 178 | Class.forName("thaumicenergistics.client.gui.GuiKnowledgeInscriber"); 179 | 180 | API.registerGuiOverlay(GuiKnowledgeInscriber.class, "arcaneshapedrecipes"); 181 | API.registerGuiOverlay(GuiKnowledgeInscriber.class, "arcaneshapelessSrecipes"); 182 | API.registerGuiOverlayHandler( 183 | GuiKnowledgeInscriber.class, 184 | NEEKnowledgeInscriberHandler.instance, 185 | "arcaneshapedrecipes"); 186 | API.registerGuiOverlayHandler( 187 | GuiKnowledgeInscriber.class, 188 | NEEKnowledgeInscriberHandler.instance, 189 | "arcaneshapelessrecipes"); 190 | 191 | } catch (ClassNotFoundException e) { 192 | 193 | } 194 | 195 | } 196 | } 197 | 198 | private void installPatternTerminalExSupport(Set identifiers) { 199 | identifiers.remove("crafting"); 200 | identifiers.remove("crafting2x2"); 201 | // PatternTermEx Support 202 | for (String ident : identifiers) { 203 | API.registerGuiOverlay(GuiPatternTermEx.class, ident); 204 | API.registerGuiOverlayHandler(GuiPatternTermEx.class, NEEPatternTerminalHandler.instance, ident); 205 | } 206 | } 207 | 208 | private void installAvaritiaddonsSupport() { 209 | try { 210 | Class.forName("wanion.avaritiaddons.block.extremeautocrafter.GuiExtremeAutoCrafter"); 211 | } catch (ClassNotFoundException e) { 212 | return; 213 | } 214 | 215 | if (Loader.isModLoaded("avaritiaddons")) { 216 | NotEnoughEnergistics.logger.info("Install Avaritiaddons support"); 217 | API.registerGuiOverlay(GuiExtremeAutoCrafter.class, "extreme", 181, 15); 218 | API.registerGuiOverlayHandler( 219 | GuiExtremeAutoCrafter.class, 220 | NEEExtremeAutoCrafterHandler.instance, 221 | "extreme"); 222 | } 223 | } 224 | 225 | private void installAvaritiaSupport() { 226 | try { 227 | Class.forName("fox.spiteful.avaritia.gui.GUIExtremeCrafting"); 228 | } catch (ClassNotFoundException e) { 229 | return; 230 | } 231 | 232 | if (Loader.isModLoaded("Avaritia")) { 233 | API.registerGuiOverlay(GUIExtremeCrafting.class, "extreme", 9, 5); 234 | API.registerGuiOverlayHandler(GUIExtremeCrafting.class, new DefaultOverlayHandler(9, 5), "extreme"); 235 | } 236 | } 237 | } 238 | --------------------------------------------------------------------------------