Compare commits

...
69 Commits
Author SHA1 Message Date
Jason Mitchell a8919dcd95 Fixes
* Handle NBTByte Arrays
* Update height for OC handlers
2021-04-18 16:06:17 -07:00
Jason Mitchell a88a13e7cf Use a config file instead of a hardcoded list so modpacks can customize it. Defaults to BloodMagic "NEIAlchemyRecipeHandler" for non GTNH usage. 2021-04-13 20:54:11 -07:00
Jason Mitchell 8bdcf65250 Add the ability to force recipe/usage handlers to run in serial. Should fix the BM CME. 2021-04-13 20:54:11 -07:00
Jason Mitchell 2e786d1807 2.1.0-GTNH Release 2021-04-12 20:20:36 -07:00
Jason Mitchell 61d6525756 Extend the xor NBT NULL check for any items with a max stack of 1, which should also catch gt6 tools 2021-04-12 20:20:36 -07:00
Jason Mitchell 8790c7f541 Overlap Adjustment
* (Hopefully) Properly handle ItemPanel overlap with multiple recipes on the page
2021-04-12 20:20:36 -07:00
Jason Mitchell 461ac036df Backport Add ability to disable and invert inventory scroll transfer. https://github.com/TheCBProject/NotEnoughItems/commit/7943831c2a8898fd6805d39fba57397742ba37f9 2021-04-12 20:20:36 -07:00
Jason Mitchell d575de33fe IMCHandler
* Add IMCHandler w/ `registerHandlerInfo` & `removeHandlerInfo` (NBT) message handling
2021-04-12 20:20:36 -07:00
Jason Mitchell c3e35f8643 Make overlay handlers work with GT items 2021-04-12 20:20:36 -07:00
Jason Mitchell f94395f453 New mod support
* Botania * Project E - Thanks to Glowredman
* TFC+ & Immersive Engineering - Thanks to FaceTorched
2021-04-12 20:20:36 -07:00
Jason Mitchell 63d6d20c96 Beta13:
* @Mod->item searching has been added using item subsets, allowing for things like `@Blocks.MobSpawners->zombie`
* DoubleFilteredFilter - Requires both filters to apply (Subset & Pattern)
* Finally updated the README.md
2021-04-12 20:20:36 -07:00
Jason Mitchell 427793b41d Better subset layout fix 2021-04-12 20:20:36 -07:00
Jason Mitchell f6c59d7a18 Fix NPE during data dump 2021-04-12 20:20:36 -07:00
Jason Mitchell 0e3507de0a Hax to fix fluid tooltip rendering for forestry & ticon 2021-04-12 20:20:36 -07:00
Jason Mitchell 5bfbf250cc The subset dropdown now shows only when the bookmarks aren't visible (there isn't enough room for it otherwise). 2021-04-12 20:20:36 -07:00
Jason Mitchell c0be69f85f handler updates 2021-04-12 20:20:36 -07:00
Jason Mitchell 934eb26249 Overlay buttons visible again 2021-04-12 20:20:36 -07:00
Jason Mitchell 69ab51bd22 Hopefully fix backwards compat
* Revert an unnecessary field movement
2021-04-12 20:20:36 -07:00
Jason Mitchell b679b65beb Handler tweaks
* Add GT6 handler info (Thanks @Miradae)
* Move afuels back to FurnaceHandler and statically reference it from TemplateRecipeHandler  **Should** fix #84
2021-04-12 20:20:36 -07:00
Jason Mitchell 9a21acd283 Default HandlerInfo if it can't be found. 2021-04-12 20:20:36 -07:00
Jason Mitchell 429f2f36a9 Introduce HandlerInfo
* Switch handler info loading from code to CSV
 * Add option to load from config or JAR
 * handlers.csv is still a WIP
2021-04-12 20:20:36 -07:00
Jason Mitchell 509078da35 GUI Scaling
* Recipe GUI now scales with window size, and displays more than 2 recipes per page, depending on height.
* Hacks to implement recipes per page, based on some assumptions since the height of the handlers are not exposed and are hardcoded
* _Temporarily_ disabled the overlay buttons; they were hardcoded to expect at most 2, need to make them dynamic and actually work again.
2021-04-12 20:20:36 -07:00
Prometheus0000 a6b306263d Fixes some handler bugs (#73)
* Fixes some handler images
* Fixed some handlers not having the right image or being in the right section

Basically just GT/BW/GT++. I also added some spaces to look nicer, and reorganized the GT/BW/GT++ a little.
2021-04-12 20:20:36 -07:00
Jason Mitchell 2162b43aa7 Reorg & restyle GuiRecipe to look a bit more like JEI
Add gregtech hax to avoid overlapping
2021-04-12 20:20:36 -07:00
Jason Mitchell 7c334d32c2 Shift everything instead of conditionally 2021-04-12 20:20:36 -07:00
Lex 8a8f2fd87a shift of the bookmark border 2021-04-12 20:20:36 -07:00
Jason Mitchell 2ae5607a60 fixes beta3 2021-04-12 20:20:36 -07:00
Jason Mitchell 0f1333b308 Bugfixes 2021-04-12 20:20:36 -07:00
Jason Mitchell d645732eb3 Fix IOOBE. 2021-04-12 20:20:36 -07:00
Jason Mitchell 371337cf77 Angry Boubs 2021-04-12 20:20:36 -07:00
Jason Mitchell 4fb83ddea6 Add option to switch between JEI tab style and Creative tab style 2021-04-12 20:20:36 -07:00
Léa Gris a14d70ee8f impr(tab): user creative inventory tab asset and layout
This allow proprely textured GUI without the need to update a resourcepack.
2021-04-12 20:20:36 -07:00
Jason Mitchell 6279149b21 DrawableResource from JEI. Swap out tab & tab icon drawing. 2021-04-12 20:20:36 -07:00
Léa Gris 2a667e1942 refactor: override draw with correct signature 2021-04-12 20:20:36 -07:00
Jason Mitchell c9bf943fb9 Fix crash on bookmark toggle
Fixes #53
2021-04-12 20:20:36 -07:00
Jason Mitchell 14a2dec34e JEI Style Tabs 2021-04-12 20:20:36 -07:00
Jason Mitchell 368a134f92 Prevent bookmarks from overlapping the armor slots on Creative+ mode 2021-04-12 20:20:36 -07:00
Jason Mitchell 68becd6fd6 Add bookmark toggle button.
Switch config button to JEI style, and add ctrl+click to cycle recipe, utility, and cheat mode.
2021-04-12 20:20:36 -07:00
Jason Mitchell fe83411c57 Enable bookmark panel hiding 2021-04-12 20:20:36 -07:00
Jason Mitchell 40ff91a908 Update build script and gradle 2021-04-12 20:20:36 -07:00
Jason Mitchell ca9c2a4052 Switch hiddenItems from synchronized to using a ReentrantReadWriteLock with a tryLock. 2021-02-20 21:19:18 -08:00
Jason Mitchell 34b9998ba3 Don't crash with divide by zero error 2021-02-14 15:42:22 -08:00
Jason Mitchell ebbfd349f2 Custom NBT <> JSON Encoder - Fix bookmark saving of items that require escaping 2021-02-14 10:10:53 -08:00
Martin Robertz 127f422e39 Update build.properties 2021-02-02 18:07:13 +01:00
Martin Robertz 3f3ce46301 Merge pull request #38 from GTNewHorizons/classloading-order-fix
Prevent NEIClientConfig being loaded too early
2021-02-02 18:06:53 +01:00
Glease 6fb48eaac4 Prevent NEIClientConfig being loaded too early
Signed-off-by: Glease <[email protected]>
2021-02-02 23:56:42 +08:00
Glease fda24ff453 Add javadoc on what the patch does
Signed-off-by: Glease <[email protected]>
2021-01-30 13:27:25 -08:00
Glease 42445c61e7 Merge OreDictBandAid fix
https://github.com/Glease/OreDictBandAid

Signed-off-by: Glease <[email protected]>
2021-01-30 13:27:25 -08:00
Jason Mitchell 3bb7b6722a Fixes thread starvation issue with parallelStream in findFuels() being called from within another parallelStream on the same ForkJoinPool
Introduces a `findFuelsOnceParallel` that is called before the parallel recipe/usage handlers are run (which now call the non parallel version of findFuels())
2021-01-30 12:38:45 -08:00
Jason Mitchell 03ede1773c Backwards Compat
* Some mods (GC, for example) rely on FuelPair in FurnaceRecipeHandler so add it back as deprecated and switch to TemplateFuelPair
2021-01-17 14:57:58 -08:00
Jason Mitchell f534b6ed0d Some reorganization and bugfixes
* Moved findFuels to TemplateRecipeHandler and made it thread safe.
* Several for loops -> streams
* Slight refactor on Item Filtering.execute()
2021-01-17 14:05:11 -08:00
Martin Robertz 7cfa4ae4ca Merge pull request #31 from GTNewHorizons/small_bug_fixes
Too many ingredients, and apparently an empty fuel?
2020-12-13 22:47:08 +01:00
Jason Mitchell 8c858b5842 Too many ingredients, and apparently an empty fuel? 2020-12-13 12:00:33 -08:00
DreamMasterXXL 6734326ec9 update(NEI)bump version 2020-09-20 20:13:11 +02:00
Martin Robertz 4dc5832d34 Merge pull request #28 from dvdmandt/master
[NEEDS CAREFUL REVIEW] Highly experimental support for backing to BetterQuesting from recipe view
2020-09-03 11:25:07 +02:00
David Lindström abfcdbb3f2 Highly experimental support for backing to BQ when coming from there
This is a highly exprimental solution to backing out of NEI's recipe view back to whatever opened it, such as BetterQuesting. It seems highly likely that this will break something somewhere, but extremely quick testing did not find any such case.
2020-09-03 03:39:30 +02:00
Martin Robertz 2fae9f0968 Merge pull request #27 from TataTawa/patch-1
Update NEIClientConfig.java
2020-08-01 09:56:14 +02:00
TataTawa 2fe5ad7275 Update NEIClientConfig.java
This reduce server start time for about 1 min. Very helpful to GTNH ssp player.
2020-07-29 08:03:43 +00:00
Jason Mitchell e67e134726 Bump version 2020-05-30 09:57:07 -07:00
Jason Mitchell 5b35ce5575 Mark itemlist dirty after adjusting ItemInfo (hidden, overrides, etc). Should fix craft tweaker item hiding. 2020-05-30 09:57:07 -07:00
DreamMasterXXL a2d469b411 update gitignore 2020-05-27 14:49:35 +02:00
Jason Mitchell 5ddfdeafcc Bump version 2020-05-25 13:58:45 -07:00
Jason Mitchell 2062a79a2a Gitignore and should be buildable 2020-05-25 13:54:38 -07:00
Jason Mitchell 23173070c9 lambda 2020-05-25 13:54:38 -07:00
Balthild 4c37971a2b Reuse the ForkJoinPool in ItemList 2020-05-25 13:54:38 -07:00
Balthild 458947628c Add TaskProfiler back 2020-05-25 13:54:38 -07:00
Balthild 6e23c51868 Use a dedicated ForkJoinPool 2020-05-25 13:54:38 -07:00
Balthild c2acfb7d8a Parallelize recipe handlers 2020-05-25 13:54:38 -07:00
DreamMasterXXL edcd410ee1 did it build now ? 2020-05-24 18:47:05 +02:00
51 changed files with 2993 additions and 425 deletions

No files matched your search

+11 -2
View File
@@ -1,6 +1,15 @@
.gradle/
build/
./build/
NotEnoughItems.iml
NotEnoughItems.ipr
NotEnoughItems.iws
*.ipr
*.iml
*.iws
.idea/**
run/*
.gradle/
*.bat
.classpath
.project
.settings/**
+11 -3
View File
@@ -1,4 +1,4 @@
# NotEnoughItems - GTNH
# NotEnoughItems Unofficial - By the GTNH Team
A continuation of NotEnoughItems for 1.7.10 by the developers of Gregtech: New Horizons modpack, with features either inspired and/or backported from JustEnoughItems
@@ -10,12 +10,20 @@ We've tested this against all of the mods included in GTNH, as well as a limited
## New Features:
* Speed - Uses a parallel stream to search the item list over multiple cores, resulting in 2-6x faster searches on average [Feels instantaneous]
* Speed
- Uses a parallel stream to search the item list over multiple cores, resulting in 2-6x faster searches on average
- Loads the recipe handlers in parallel
* A textbox for search with most of the features you'd expect - moving forward, backwards, selection, etc
* Bookmarks! What are you in the process of crafting? Bookmark it using either 'A' or configure your own key.
* Toggle bookmark pane. Default shortcut key `B`. Item Subsets menu is only available if bookmarks are not visible.
* Utility/Cheat buttons line up and wrap based on GUI size
* ItemList is no longer regenerated from the ItemRegistry on every inventory load
* JEI (Or Creative) Style tabs [Optional] Note: Requires explicit support to be added for an ItemStack to render, otherwise falls back to the first two letters of the handler name.
* Tabs/Handlers are loaded from a CSV config in the JAR (or optionally from the config folder). NBT IMCEvents `registerHandlerInfo` and `removeHandlerInfo` are available for mod authors to add handler information, using the same fields as the CSV file
* `@[Mod]->[item]` searching. ex: `@Mod.gregtech->iron ingot`
* Cycle between Recipe, Utility, and Cheat mode by ctrl clicking on the Wrench Icon
* GT5u Tools/Items and GT6 tools should now properly work with the Overlay Recipe Transfer
## Other items of note:
* Licensed under LGPL - Use this however you want, but please give back any modifications
+58 -30
View File
@@ -1,20 +1,29 @@
buildscript {
repositories {
mavenCentral()
jcenter()
maven {
name = "gt"
url = "https://gregtech.overminddl1.com/"
}
maven {
name = "forge"
url = "http://files.minecraftforge.net/maven"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
name = "jitpack"
url = "https://jitpack.io"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
classpath "com.github.GTNH2:ForgeGradle:FG_1.2-SNAPSHOT"
}
}
plugins {
id("org.ajoberstar.grgit") version("3.1.1")
}
//add dependency repositories
repositories {
maven {
@@ -23,9 +32,24 @@ repositories {
}
}
apply plugin: "java"
apply plugin: "idea"
apply plugin: 'forge'
group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
idea {
module {
inheritOutputDirs = true
downloadJavadoc = true
downloadSources = true
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
group = "codechicken"
archivesBaseName = "NotEnoughItems"
// Define properties file
@@ -37,18 +61,25 @@ configFile.withReader {
prop.load(it)
project.ext.config = new ConfigSlurper().parse prop
}
//
//configurations.all {
// resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
// setTransitive(false)
//}
configurations {
shade
compile.extendsFrom shade
}
dependencies {
compile "codechicken:CodeChickenLib:${config.mc_version}-${config.ccl_version}:dev"
compile "codechicken:CodeChickenCore:${config.mc_version}-${config.ccc_version}:dev"
shade "org.apache.commons:commons-csv:1.5"
}
version = "${project.config.mod_version}"
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = "${project.config.mod_version}"
println config.mc_version + "-" + config.forge_version
// Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here
@@ -56,7 +87,7 @@ minecraft {
version = config.mc_version + "-" + config.forge_version
}
def root = project.projectDir.parentFile
def root = project.projectDir;
sourceSets {
main {
java {
@@ -81,6 +112,11 @@ processResources {
// Move access transformer to META-INF
rename '(.+_at.cfg)', 'META-INF/$1'
//
// // copy everything else, that's not the mcmod.info
// from(sourceSets.main.resources.srcDirs) {
// exclude "mcmod.info"
// }
}
version = "${project.minecraft.version}-${project.version}"
@@ -90,19 +126,24 @@ def commonManifest = {
}
jar {
classifier = 'universal'
getArchiveClassifier().set("universal")
manifest commonManifest
configurations.shade.each { dep ->
from(project.zipTree(dep)){
exclude 'META-INF', 'META-INF/**'
}
}
}
task sourceJar(type: Jar) {
from sourceSets.main.java
from new File(root, "dev")
classifier = 'src'
getArchiveClassifier().set("src")
}
task devJar(type: Jar) {
from sourceSets.main.output
classifier = 'dev'
getArchiveClassifier().set("dev")
manifest commonManifest
}
@@ -111,20 +152,7 @@ artifacts {
archives sourceJar, devJar
}
sourceSets {
main { output.resourcesDir = output.classesDir }
}
// Configure an upload task.
uploadArchives {
dependsOn 'reobf'
if (project.hasProperty("local_maven")) {
repositories {
logger.info('Publishing to local maven repo')
mavenDeployer {
repository(url: "file://${local_maven}")
}
}
}
}
minecraft {
srgExtra "PK: org/apache/commons/csv nei/org/apache/commons/csv"
srgExtra "PK: org/apache/commons/csv/CSVFormat nei/org/apache/commons/csv/CSVFormat"
}
+1 -1
View File
@@ -2,4 +2,4 @@ mc_version=1.7.10
forge_version=10.13.4.1614-1.7.10
ccl_version=1.1.3.138
ccc_version=1.0.7.+
mod_version=2.0.2-GTNH
mod_version=2.1.2-GTNH
Binary file not shown.
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
Vendored Regular → Executable
+19 -3
View File
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
@@ -109,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
Vendored
+17 -1
View File
@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
+387
View File
@@ -0,0 +1,387 @@
handler,modName,itemName,nbtInfo,modId,modRequired,excludedModId,yShift,handlerHeight,handlerWidth,maxRecipesPerPage,imageResource,imageX,imageY,imageWidth,imageHeight,itemNotes
codechicken.nei.recipe.BrewingRecipeHandler,minecraft,minecraft:brewing_stand,,minecraft,FALSE,,,65,166,5,,,,,,
codechicken.nei.recipe.FireworkRecipeHandler,minecraft,minecraft:fireworks,,minecraft,FALSE,,,65,166,5,,,,,,
codechicken.nei.recipe.FurnaceRecipeHandler,minecraft,minecraft:furnace,,minecraft,FALSE,,,65,166,5,,,,,,
codechicken.nei.recipe.ShapedRecipeHandler,minecraft,minecraft:crafting_table,,minecraft,FALSE,,,65,166,5,,,,,,
codechicken.nei.recipe.ShapelessRecipeHandler,minecraft,minecraft:crafting_table,,minecraft,FALSE,,,65,166,5,,,,,,
codechicken.nei.recipe.FuelRecipeHandler,minecraft,,,minecraft,FALSE,,,65,166,5,nei:textures/nei_tabbed_sprites.png,80,0,14,14,
advsolar.client.nei.MTRecipeHandler,AdvancedSolarPanel,AdvancedSolarPanel:BlockMolecularTransformer,,AdvancedSolarPanel,TRUE,,,68,,5,,,,,,
appeng.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler,AppliedEnergistics2,appliedenergistics2:item.ItemMultiPart:380,,appliedenergistics2,TRUE,,,65,,5,,,,,,
appeng.integration.modules.NEIHelpers.NEIAEShapelessRecipeHandler,AppliedEnergistics2,appliedenergistics2:item.ItemMultiPart:380,,appliedenergistics2,TRUE,,,65,,5,,,,,,
appeng.integration.modules.NEIHelpers.NEIFacadeRecipeHandler,AppliedEnergistics2,appliedenergistics2:item.ItemFacade:192,,appliedenergistics2,TRUE,,,65,,5,,,,,,
appeng.integration.modules.NEIHelpers.NEIGrinderRecipeHandler,AppliedEnergistics2,appliedenergistics2:item.ItemMultiMaterial:8,,appliedenergistics2,TRUE,,,,,,,,,,,
appeng.integration.modules.NEIHelpers.NEIInscriberRecipeHandler,AppliedEnergistics2,appliedenergistics2:tile.BlockInscriber,,appliedenergistics2,TRUE,,,70,,5,,,,,,
appeng.integration.modules.NEIHelpers.NEIWorldCraftingHandler,AppliedEnergistics2,appliedenergistics2:item.ItemMultiMaterial:9,,appliedenergistics2,TRUE,,,85,,5,,,,,,There's only some explanatory text for fluix crystals and QEDs
aroma1997.core.recipes.nei.ShapedAromicRecipeHandler,AromaBackup,minecraft:crafting_table,,AromaBackup,TRUE,,,65,,5,,,,,,
aroma1997.core.recipes.nei.ShapelessAromicRecipeHandler,AromaBackup,minecraft:crafting_table,,AromaBackup,TRUE,,,,,,,,,,,
fox.spiteful.avaritia.compat.nei.CompressionHandler,Avaritia,Avaritia:Neutronium_Compressor,,Avaritia,TRUE,,,50,,6,,,,,,
fox.spiteful.avaritia.compat.nei.ExtremeShapedRecipeHandler,Avaritia,Avaritia:Dire_Crafting,,Avaritia,TRUE,,,208,256,1,,,,,,Part of it even goes off the left side (included)
fox.spiteful.avaritia.compat.nei.ExtremeShapelessRecipeHandler,Avaritia,Avaritia:Dire_Crafting,,Avaritia,TRUE,,,208,256,1,,,,,,"If you can cut off/place over the jaggedness at the bottom, you could barely get a second one"
WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler,BloodMagic,AWWayofTime:blockWritingTable,,AWWayofTime,TRUE,,,68,,5,,,,,,
WayofTime.alchemicalWizardry.client.nei.NEIAltarRecipeHandler,BloodMagic,AWWayofTime:Altar,,AWWayofTime,TRUE,,,65,,5,,,,,,Handler name needs shifting left
WayofTime.alchemicalWizardry.client.nei.NEIBindingRitualHandler,BloodMagic,AWWayofTime:sacrificialKnife,,AWWayofTime,TRUE,,,50,,6,,,,,,
WayofTime.alchemicalWizardry.client.nei.NEIBloodOrbShapedHandler,BloodMagic,AWWayofTime:AlchemicalWizardrybloodRune:3,,AWWayofTime,TRUE,,,65,,5,,,,,,
WayofTime.alchemicalWizardry.client.nei.NEIBloodOrbShapelessHandler,BloodMagic,AWWayofTime:AlchemicalWizardrybloodRune:4,,AWWayofTime,TRUE,,,65,,5,,,,,,
bw.fuels.acidgens,BartWorks,gregtech:gt.blockmachines:12726,,bartworks,TRUE,,,145,,2,,,,,,
bw.recipe.cal,BartWorks,gregtech:gt.blockmachines:12735,,bartworks,TRUE,,,135,,2,,,,,,
com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_BioLabHandler,BartWorks,gregtech:gt.blockmachines:12699,,bartworks,TRUE,,,145,,2,,,,,,
com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_BioVatHandler,BartWorks,gregtech:gt.blockmachines:12712,,bartworks,TRUE,,,140,,2,,,,,,
com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_OreHandler,BartWorks,bartworks:bw.blockores.01:89,,bartworks,TRUE,,,135,,2,,,,,,
gt.recipe.electricimplosioncompressor,BartWorks,gregtech:gt.blockmachines:12734,,bartworks,TRUE,,,135,,2,,,,,,
net.bdew.neiaddons.botany.flowers.FlowerBreedingHandler,Botany,Botany:flower,,Botany,TRUE,,,65,,5,,,,,,
buildcraft.compat.nei.RecipeHandlerRefinery,BuildCraft,BuildCraft|Factory:refineryBlock,,BuildCraft|Factory,TRUE,,,60,,5,,,,,,There's only 2 recipes though
buildcraft.compat.nei.RecipeHandlerAssemblyTable,BuildCraft,BuildCraft|Silicon:laserTableBlock,,BuildCraft|Silicon,TRUE,,,100,,3,,,,,,
buildcraft.compat.nei.RecipeHandlerIntegrationTable,BuildCraft,BuildCraft|Silicon:laserTableBlock:2,,BuildCraft|Silicon,TRUE,,,85,,4,,,,,,
team.chisel.compat.nei.RecipeHandlerChisel,Chisel,chisel:chisel,,chisel,TRUE,,,135,,2,,,,,,
crazypants.enderio.nei.AlloySmelterRecipeHandler,EnderIO,EnderIO:blockAlloySmelter,,EnderIO,TRUE,,,65,,5,,,,,,
crazypants.enderio.nei.EnchanterRecipeHandler,EnderIO,EnderIO:blockEnchanter,,EnderIO,TRUE,,,65,,5,,,,,,
crazypants.enderio.nei.SagMillRecipeHandler,EnderIO,EnderIO:blockSagMill,,EnderIO,TRUE,,,68,,5,,,,,,
crazypants.enderio.nei.SliceAndSpliceRecipeHandler,EnderIO,EnderIO:blockSliceAndSplice,,EnderIO,TRUE,,,65,,5,,,,,,
crazypants.enderio.nei.SoulBinderRecipeHandler,EnderIO,EnderIO:blockSoulBinder,,EnderIO,TRUE,,,68,,5,,,,,,
crazypants.enderio.nei.VatRecipeHandler,EnderIO,EnderIO:blockVat,,EnderIO,TRUE,,,65,,5,,,,,,
extracells.integration.nei.UniversalTerminalRecipe,ExtraCells,extracells:part.base:9,,extracells,TRUE,,,65,,5,,,,,,
com.rwtema.extrautils.nei.EnderConstructorHandler,ExtraUtilities,ExtraUtilities:endConstructor,,ExtraUtilities,TRUE,,,68,,5,,,,,,
com.rwtema.extrautils.nei.FMPMicroBlocksHandler,ExtraUtilities,ForgeMicroblock:sawIron,,ExtraUtilities,TRUE,,,65,,5,,,,,,
com.rwtema.extrautils.nei.InfoHandler,ExtraUtilities,ExtraUtilities:chandelier,,ExtraUtilities,TRUE,,,135,,2,,,,,,"Info on blocks, can vary wildly. EQ was this length, there might be a longer one"
com.rwtema.extrautils.nei.MicroBlocksHandler,ExtraUtilities,ExtraUtilities:microblocks:1,,ExtraUtilities,TRUE,,,,,,,,,,,
com.rwtema.extrautils.nei.SoulHandler,ExtraUtilities,ExtraUtilities:mini-soul,,ExtraUtilities,TRUE,,,,,,,,,,,
hellfirepvp.beebetteratbees.client.gui.BBABGuiRecipeTreeHandler,Bees,Forestry:beeQueenGE,,Forestry,TRUE,,,140,,2,,,,,,
forestry.factory.recipes.nei.NEIHandlerBottler,Forestry,Forestry:factory,,Forestry,TRUE,,,68,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerCarpenter,Forestry,Forestry:factory:1,,Forestry,TRUE,,,65,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerCentrifuge,Forestry,Forestry:factory:2,,Forestry,TRUE,,,65,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerFabricator,Forestry,Forestry:factory2,,Forestry,TRUE,,,,,,,,,,,
forestry.factory.recipes.nei.NEIHandlerFermenter,Forestry,Forestry:factory:3,,Forestry,TRUE,,,65,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerMoistener,Forestry,Forestry:factory:4,,Forestry,TRUE,,,68,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerSqueezer,Forestry,Forestry:factory:5,,Forestry,TRUE,,,68,,5,,,,,,
forestry.factory.recipes.nei.NEIHandlerStill,Forestry,Forestry:factory:6,,Forestry,TRUE,,,65,,5,,,,,,
net.bdew.neiaddons.forestry.bees.BeeBreedingHandler,Forestry,Forestry:beeQueenGE,,Forestry,TRUE,,,65,,5,,,,,,
net.bdew.neiaddons.forestry.bees.BeeProduceHandler,Forestry,Forestry:beeQueenGE,,Forestry,TRUE,,,65,,5,,,,,,
net.bdew.neiaddons.forestry.butterflies.ButterflyBreedingHandler,Forestry,Forestry:butterflyGE,,Forestry,TRUE,,,,,,,,,,,
net.bdew.neiaddons.forestry.trees.TreeBreedingHandler,Forestry,Forestry:saplingGE,,Forestry,TRUE,,,65,,5,,,,,,
net.bdew.neiaddons.forestry.trees.TreeProduceHandler,Forestry,Forestry:saplingGE,,Forestry,TRUE,,,65,,5,,,,,,
galaxyspace.core.nei.rocket.RocketT1RecipeHandler,Galacticraft,GalacticraftCore:item.spaceship,,GalacticraftCore,TRUE,,,125,,2,,,,,,
micdoodle8.mods.galacticraft.core.nei.BuggyRecipeHandler,Galacticraft,GalacticraftCore:tile.rocketWorkbench,,GalacticraftCore,TRUE,,10,135,,2,,,,,,
micdoodle8.mods.galacticraft.core.nei.CircuitFabricatorRecipeHandler,Galacticraft,GalacticraftCore:tile.machine2:4,,GalacticraftCore,TRUE,,,,,,,,,,,
micdoodle8.mods.galacticraft.core.nei.ElectricIngotCompressorRecipeHandler,Galacticraft,GalacticraftCore:tile.machine2,,GalacticraftCore,TRUE,,,,,,,,,,,
micdoodle8.mods.galacticraft.core.nei.IngotCompressorRecipeHandler,Galacticraft,GalacticraftCore:tile.machine:12,,GalacticraftCore,TRUE,,,,,,,,,,,
micdoodle8.mods.galacticraft.core.nei.RefineryRecipeHandler,Galacticraft,GalacticraftCore:tile.refinery,,GalacticraftCore,TRUE,,,,,,,,,,,
micdoodle8.mods.galacticraft.planets.asteroids.nei.AstroMinerRecipeHandler,Galacticraft,GalacticraftCore:tile.rocketWorkbench,,GalacticraftCore,TRUE,,,100,,3,,,,,,
micdoodle8.mods.galacticraft.planets.mars.nei.CargoRocketRecipeHandler,Galacticraft,GalacticraftCore:tile.rocketWorkbench,,GalacticraftCore,TRUE,,10,125,,2,,,,,,
micdoodle8.mods.galacticraft.planets.mars.nei.GasLiquefierRecipeHandler,Galacticraft,GalacticraftMars:tile.marsMachineT2,,GalacticraftCore,TRUE,,,,,,,,,,,
micdoodle8.mods.galacticraft.planets.mars.nei.MethaneSynthesizerRecipeHandler,Galacticraft,GalacticraftMars:tile.marsMachineT2:4,,GalacticraftCore,TRUE,,,,,,,,,,,
galaxyspace.core.nei.rocket.RocketT2RecipeHandler,Galacticraft,GalacticraftMars:item.spaceshipTier2:1,,GalacticraftMars,TRUE,,5,145,,2,,,,,,
galaxyspace.core.nei.rocket.RocketT3RecipeHandler,Galacticraft,GalacticraftMars:item.itemTier3Rocket,,GalacticraftMars,TRUE,,5,145,,2,,,,,,
galaxyspace.core.nei.AssemblyMachineRecipeHandler,GalaxySpace,GalaxySpace:assemblymachine,,GalaxySpace,TRUE,,,,,,,,,,,
galaxyspace.core.nei.rocket.RocketT4RecipeHandler,GalaxySpace,GalaxySpace:item.Tier4Rocket,,GalaxySpace,TRUE,,10,160,,2,,,,,,
galaxyspace.core.nei.rocket.RocketT5RecipeHandler,GalaxySpace,GalaxySpace:item.Tier5Rocket,,GalaxySpace,TRUE,,10,160,,2,,,,,,
galaxyspace.core.nei.rocket.RocketT6RecipeHandler,GalaxySpace,GalaxySpace:item.Tier6Rocket,,GalaxySpace,TRUE,,10,160,,2,,,,,,
galaxyspace.core.nei.rocket.RocketT7RecipeHandler,GalaxySpace,GalaxySpace:item.Tier7Rocket,,GalaxySpace,TRUE,,10,180,,1,,,,,,
galaxyspace.core.nei.rocket.RocketT8RecipeHandler,GalaxySpace,GalaxySpace:item.Tier8Rocket,,GalaxySpace,TRUE,,10,180,,1,,,,,,
net.bdew.gendustry.nei.ExtractorHandler,Gendustry,gendustry:Extractor,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.ImprinterHandler,Gendustry,gendustry:Imprinter,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.LiquifierHandler,Gendustry,gendustry:Liquifier,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.MutagenProducerHandler,Gendustry,gendustry:MutagenProducer,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.MutatronHandler,Gendustry,gendustry:Mutatron,,gendustry,TRUE,,,65,,5,,,,,,
net.bdew.gendustry.nei.ReplicatorHandler,Gendustry,gendustry:Replicator,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.SamplerHandler,Gendustry,gendustry:Sampler,,gendustry,TRUE,,,68,,5,,,,,,
net.bdew.gendustry.nei.TemplateCraftingHandler,Gendustry,gendustry:GeneTemplate,,gendustry,TRUE,,,105,,3,,,,,,
net.bdew.gendustry.nei.TransposerHandler,Gendustry,gendustry:Transposer,,gendustry,TRUE,,,68,,5,,,,,,
gt.recipe.alloysmelter,gregtech,gregtech:gt.blockmachines:201,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.arcfurnace,gregtech,gregtech:gt.blockmachines:651,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.assembler,gregtech,gregtech:gt.blockmachines:211,,gregtech,TRUE,gregapi_post,6,145,166,2,,,,,,
gt.recipe.autoclave,gregtech,gregtech:gt.blockmachines:571,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.blastfurnace,gregtech,gregtech:gt.blockmachines:1000,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.brewer,gregtech,gregtech:gt.blockmachines:491,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.byproductlist,gregtech,gregtech:gt.metaitem.01:2019,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.canner,gregtech,gregtech:gt.blockmachines:231,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.centrifuge,gregtech,gregtech:gt.blockmachines:361,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.chemicalbath,gregtech,gregtech:gt.blockmachines:541,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.chemicalreactor,gregtech,gregtech:gt.blockmachines:421,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.circuitassembler,gregtech,gregtech:gt.blockmachines:1180,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.cncmachine,gregtech,gregtech:gt.metaitem.01:23305,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.cokeoven,gregtech,gregtech:gt.blockmachines:791,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.componentassembler,gregtech,gregtech:gt.blockmachines:211,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.compressor,gregtech,gregtech:gt.blockmachines:241,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.craker,gregtech,gregtech:gt.blockmachines:1160,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.cuttingsaw,gregtech,gregtech:gt.blockmachines:251,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.dieselgeneratorfuel,gregtech,gregtech:gt.blockmachines:1110,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.distillationtower,gregtech,gregtech:gt.blockmachines:1126,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.distillery,gregtech,gregtech:gt.blockmachines:531,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.electrolyzer,gregtech,gregtech:gt.blockmachines:371,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.electromagneticseparator,gregtech,gregtech:gt.blockmachines:561,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.extractor,gregtech,gregtech:gt.blockmachines:271,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.extrahugenaquadahreactor,gregtech,gregtech:gt.blockmachines:1189,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.extremedieselgeneratorfuel,gregtech,gregtech:gt.blockmachines:2105,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.extruder,gregtech,gregtech:gt.blockmachines:281,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fakeAssemblylineProcess,gregtech,gregtech:gt.blockmachines:1170,,gregtech,TRUE,gregapi_post,12,135,166,2,,,,,,
gt.recipe.fermenter,gregtech,gregtech:gt.blockmachines:501,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fluidcanner,gregtech,gregtech:gt.blockmachines:431,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fluidextractor,gregtech,gregtech:gt.blockmachines:511,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fluidheater,gregtech,gregtech:gt.blockmachines:621,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fluidnaquadahreactor,gregtech,gregtech:gt.blockmachines:1192,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fluidsolidifier,gregtech,gregtech:gt.blockmachines:521,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.fusionreactor,gregtech,gregtech:gt.blockmachines:1193,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.gasturbinefuel,gregtech,gregtech:gt.blockmachines:1115,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.hammer,gregtech,gregtech:gt.blockmachines:611,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.hugenaquadahreactor,gregtech,gregtech:gt.blockmachines:1188,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.implosioncompressor,gregtech,gregtech:gt.blockmachines:12734,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.largeboilerfakefuels,gregtech,gregtech:gt.blockmachines:1020,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.largechemicalreactor,gregtech,gregtech:gt.blockmachines:1169,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.largenaquadahreactor,gregtech,gregtech:gt.blockmachines:1191,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.laserengraver,gregtech,gregtech:gt.blockmachines:591,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.lathe,gregtech,gregtech:gt.blockmachines:291,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.macerator,gregtech,gregtech:gt.blockmachines:301,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.magicfuels,gregtech,gregtech:gt.blockmachines:1123,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.massfab,gregtech,gregtech:gt.blockmachines:461,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.metalbender,gregtech,gregtech:gt.blockmachines:221,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.microwave,gregtech,gregtech:gt.blockmachines:311,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.mixer,gregtech,gregtech:gt.blockmachines:581,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.orewasher,gregtech,gregtech:gt.blockmachines:391,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.packager,gregtech,gregtech:gt.blockmachines:401,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.plasmaarcfurnace,gregtech,gregtech:gt.blockmachines:661,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.plasmageneratorfuels,gregtech,gregtech:gt.blockmachines:1196,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.polarizer,gregtech,gregtech:gt.blockmachines:551,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.press,gregtech,gregtech:gt.blockmachines:601,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.primitiveblastfurnace,gregtech,gregtech:gt.blockmachines:140,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.printer,gregtech,gregtech:gt.blockmachines:321,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.pyro,gregtech,gregtech:gt.blockmachines:1159,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.replicator,gregtech,gregtech:gt.blockmachines:481,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.rockbreaker,gregtech,gregtech:gt.blockmachines:441,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.scanner,gregtech,gregtech:gt.blockmachines:341,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.semifluidboilerfuels,gregtech,gregtech:gt.blockmachines:1020,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.sifter,gregtech,gregtech:gt.blockmachines:641,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.slicer,gregtech,gregtech:gt.blockmachines:631,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.smallnaquadahreactor,gregtech,gregtech:gt.blockmachines:1190,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.thermalcentrifuge,gregtech,gregtech:gt.blockmachines:381,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.thermalgeneratorfuel,gregtech,IC2:blockGenerator:1,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.unpackager,gregtech,gregtech:gt.blockmachines:411,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.uuamplifier,gregtech,gregtech:gt.blockmachines:471,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.vacuumfreezer,gregtech,gregtech:gt.blockmachines:1002,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
gt.recipe.wiremill,gregtech,gregtech:gt.blockmachines:351,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
ic.recipe.recycler,gregtech,gregtech:gt.blockmachines:331,,gregtech,TRUE,gregapi_post,6,135,166,2,,,,,,
pers.gwyog.gtneioreplugin.plugin.gregtech5.PluginGT5SmallOreStat,Gregtech,gregtech:gt.blockores:85,,gregtech,TRUE,,,145,,2,,,,,,
pers.gwyog.gtneioreplugin.plugin.gregtech5.PluginGT5VeinStat,Gregtech,gregtech:gt.blockores:386,,gregtech,TRUE,,,135,,2,,,,,,
ic2.neiIntegration.core.recipehandler.AdvRecipeHandler,IC2,IC2:blockreactorvessel,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.AdvShapelessRecipeHandler,IC2,IC2:blockreactorvessel,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.BlastFurnaceRecipeHandler,IC2,IC2:blockMachine3:1,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.BlockCutterRecipeHandler,IC2,IC2:blockMachine3:2,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.CentrifugeRecipeHandler,IC2,IC2:blockMachine2:3,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.CompressorRecipeHandler,IC2,IC2:blockMachine:5,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.ExtractorRecipeHandler,IC2,IC2:blockMachine:4,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.FluidCannerRecipeHandler,IC2,IC2:blockMachine:6,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.LatheRecipeHandler,IC2,IC2:blockMachine3:8,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.MaceratorRecipeHandler,IC2,IC2:blockMachine:3,,IC2,TRUE,,,65,,5,,,,,,
ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerCutting,IC2,IC2:blockMachine2:4,,IC2,TRUE,,,55,,6,,,,,,
ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerExtruding,IC2,IC2:blockMachine2:4,,IC2,TRUE,,,55,,6,,,,,,
ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerRolling,IC2,IC2:blockMachine2:4,,IC2,TRUE,,,55,,6,,,,,,
ic2.neiIntegration.core.recipehandler.OreWashingRecipeHandler,IC2,IC2:blockMachine2:5,,IC2,TRUE,,,,,,,,,,,
ic2.neiIntegration.core.recipehandler.ScrapboxRecipeHandler,IC2,IC2:itemScrapbox,,IC2,TRUE,,,50,,6,,,,,,
ic2.neiIntegration.core.recipehandler.SolidCannerRecipeHandler,IC2,IC2:blockMachine2:9,,IC2,TRUE,,,,,,,,,,,
speiger.src.crops.prediction.NEIPlugin,IC2CropsNEI,IC2:blockCrop,,Ic2Nei,TRUE,,,135,,2,,,,,,"Not actual recipes, just info"
tonius.neiintegration.mods.mcforge.RecipeHandlerFluidRegistry,Minecraft,minecraft:water,,minecraft,FALSE,,,,,,,,,,,
tonius.neiintegration.mods.mcforge.RecipeHandlerOreDictionary,Minecraft,minecraft:iron_ore,,minecraft,FALSE,,,,,,,,,,,
gt.recipe.alloyblastsmelter,GT++,gregtech:gt.blockmachines:810,,miscutils,TRUE,,6,135,166,2,,,,,,ABS
gt.recipe.rocketenginefuel,GT++,gregtech:gt.blockmachines:793,,miscutils,TRUE,,6,135,166,2,,,,,,Basic (EV) rocket fuel gen
gt.recipe.cyclotron,GT++,gregtech:gt.blockmachines:828,,miscutils,TRUE,,6,135,166,2,,,,,,Cyclotron
gt.recipe.chemicaldehydrator,GT++,gregtech:gt.blockmachines:911,,miscutils,TRUE,,6,135,166,2,,,,,,Dehydrator
gt.recipe.slowfusionreactor,GT++,gregtech:gt.blockmachines:31015,,miscutils,TRUE,,6,135,166,2,,,,,,gt.blockmachines.gtplusplus.fusion.single
gt.recipe.RTGgenerators,GT++,gregtech:gt.blockmachines:869,,miscutils,TRUE,,6,135,166,2,,,,,,GT++ version of the RTG
gt.recipe.cokeoven,GT++,gregtech:gt.blockmachines:791,,miscutils,TRUE,,6,135,166,2,,,,,,ICO
gt.recipe.semifluidgeneratorfuels,GT++,gregtech:gt.blockmachines:837,,miscutils,TRUE,,6,135,166,2,,,,,,Semifluid gen
gt.recipe.fishpond,GT++,gregtech:gt.blockmachines:829,,miscutils,TRUE,,6,135,166,2,,,,,,Zhuhai
gt.recipe.advanced.mixer,GT++,gregtech:gt.blockmachines:811,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.cryogenicfreezer,GT++,gregtech:gt.blockmachines:910,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.fissionfuel,GT++,gregtech:gt.blockmachines:835,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.geothermalfuel,GT++,gregtech:gt.blockmachines:830,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.lftr,GT++,gregtech:gt.blockmachines:751,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.lftr.2,GT++,gregtech:gt.blockmachines:751,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.matterfab2,GT++,gregtech:gt.blockmachines:799,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.multicentrifuge,GT++,gregtech:gt.blockmachines:790,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.multielectro,GT++,gregtech:gt.blockmachines:796,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.simplewasher,GT++,gregtech:gt.blockmachines:767,,miscutils,TRUE,,6,135,166,2,,,,,,
gt.recipe.vacfurnace,GT++,gregtech:gt.blockmachines:995,,miscutils,TRUE,,6,135,166,2,,,,,,
gtPlusPlus.nei.DecayableRecipeHandler,GT++,miscutils:dustRadium226,,miscutils,TRUE,,,75,,4,,,,,,
gtPlusPlus.nei.GT_NEI_FlotationCell,GT++,gregtech:gt.blockmachines:31028,,miscutils,TRUE,,,120,,2,,,,,,
gtPlusPlus.nei.GT_NEI_FluidReactor,GT++,gregtech:gt.blockmachines:998,,miscutils,TRUE,,,120,,2,,,,,,
gtPlusPlus.nei.GT_NEI_MillingMachine,GT++,gregtech:gt.blockmachines:31027,,miscutils,TRUE,,,120,,2,,,,,,
li.cil.oc.integration.nei.CallbackDocHandler,OpenComputers,OpenComputers:item:98,,OpenComputers,TRUE,,,120,,2,,,,,,
li.cil.oc.integration.nei.ManualUsageHandler,OpenComputers,OpenComputers:item:98,,OpenComputers,TRUE,,,120,,2,,,,,,
tonius.neiintegration.mods.harvestcraft.RecipeHandlerApiary,Pam's Harvestcraft,harvestcraft:apiary,,harvestcraft,TRUE,,,70,,5,,,,,,There's only 1 though
tonius.neiintegration.mods.harvestcraft.RecipeHandlerChurn,Pam's Harvestcraft,harvestcraft:churn,,harvestcraft,TRUE,,,65,,5,,,,,,Same as above
tonius.neiintegration.mods.harvestcraft.RecipeHandlerOven,Pam's Harvestcraft,harvestcraft:oven,,harvestcraft,TRUE,,,65,,5,,,,,,
tonius.neiintegration.mods.harvestcraft.RecipeHandlerPresser,Pam's Harvestcraft,harvestcraft:presser,,harvestcraft,TRUE,,,65,,5,,,,,,
tonius.neiintegration.mods.harvestcraft.RecipeHandlerQuern,Pam's Harvestcraft,harvestcraft:quern,,harvestcraft,TRUE,,,65,,5,,,,,,
gcewing.projectblue.nei.NEIRecipeHandler,ProjectBlue,ProjectBlue:sprayCan,,ProjectBlue,TRUE,,,65,,5,,,,,,
mrtjp.projectred.core.libmc.recipe.PRShapedRecipeHandler,ProjectRed,ProjRed|Transmission:projectred.transmission.wire:7,,ProjRed|Transmission,TRUE,,,,,,,,,,,
mrtjp.projectred.core.libmc.recipe.PRShapelessRecipeHandler,ProjectRed,ProjRed|Transmission:projectred.transmission.wire:7,,ProjRed|Transmission,TRUE,,,,,,,,,,,
tonius.neiintegration.mods.railcraft.RecipeHandlerBlastFurnace,Railcraft,Railcraft:machine.alpha:12,,Railcraft,TRUE,,,,,,,,,,,
tonius.neiintegration.mods.railcraft.RecipeHandlerCokeOven,Railcraft,Railcraft:machine.alpha:7,,Railcraft,TRUE,,,65,,5,,,,,,
tonius.neiintegration.mods.railcraft.RecipeHandlerRockCrusher,Railcraft,Railcraft:machine.alpha:15,,Railcraft,TRUE,,,,,,,,,,,
tonius.neiintegration.mods.railcraft.RecipeHandlerRollingMachineShaped,Railcraft,Railcraft:machine.alpha:8,,Railcraft,TRUE,,,65,,5,,,,,,
tonius.neiintegration.mods.railcraft.RecipeHandlerRollingMachineShapeless,Railcraft,Railcraft:machine.alpha:8,,Railcraft,TRUE,,,,,,,,,,,
lumien.randomthings.Handler.ModCompability.NEI.ImbuingStationRecipeHandler,RandomThings,RandomThings:imbuingStation,,RandomThings,TRUE,,,120,,2,,,,,,
com.github.technus.tectech.nei.TT_NEI_ResearchHandler,TecTech,gregtech:gt.blockmachines:15331,,tectech,TRUE,,6,140,,2,,,,,,
com.github.technus.tectech.nei.TT_NEI_ScannerHandler,TecTech,tectech:item.em.definitionScanStorage,,tectech,TRUE,,,,,,,,,,,
com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.ArcaneShapedRecipeHandler,Thaumcraft,Thaumcraft:blockTable:15,,Thaumcraft,TRUE,,,140,,2,,,,,,
com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.ArcaneShapelessRecipeHandler,Thaumcraft,Thaumcraft:blockTable:15,,Thaumcraft,TRUE,,,140,,2,,,,,,
com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.CrucibleRecipeHandler,Thaumcraft,Thaumcraft:blockMetalDevice,,Thaumcraft,TRUE,,,140,,2,,,,,,Using R on an item you get from the crucible basically never works
com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.InfusionRecipeHandler,Thaumcraft,Thaumcraft:blockStoneDevice:2,,Thaumcraft,TRUE,,,140,,2,,,,,,
ru.timeconqueror.tcneiadditions.nei.arcaneworkbench.ArcaneCraftingShapedHandler,Thaumcraft,Thaumcraft:blockTable:15,,Thaumcraft,TRUE,,,140,,2,,,,,,
ru.timeconqueror.tcneiadditions.nei.AspectCombinationHandler,Thaumcraft,Thaumcraft:ItemResearchNotes,,Thaumcraft,TRUE,,,130,,2,,,,,,In sets of 5. Each one is ~30 height
ru.timeconqueror.tcneiadditions.nei.AspectFromItemStackHandler,Thaumcraft,Thaumcraft:ItemResearchNotes,,Thaumcraft,TRUE,,,140,,2,,,,,,
tconstruct.plugins.nei.RecipeHandlerAlloying,Tinker's Construct,TConstruct:Smeltery,,TConstruct,TRUE,,,65,,5,,,,,,
tconstruct.plugins.nei.RecipeHandlerCastingBasin,Tinker's Construct,TConstruct:SearedBlock:2,,TConstruct,TRUE,,,65,,5,,,,,,
tconstruct.plugins.nei.RecipeHandlerCastingTable,Tinker's Construct,TConstruct:SearedBlock,,TConstruct,TRUE,,,65,,5,,,,,,
tconstruct.plugins.nei.RecipeHandlerDryingRack,Tinker's Construct,TConstruct:Armor.DryingRack,,TConstruct,TRUE,,,55,,5,,,,,,
tconstruct.plugins.nei.RecipeHandlerMelting,Tinker's Construct,TConstruct:LavaTank:2,,TConstruct,TRUE,,,65,,5,,,,,,
tconstruct.plugins.nei.RecipeHandlerToolMaterials,Tinker's Construct,TConstruct:ToolStationBlock,,TConstruct,TRUE,,,110,,3,,,,,,"Longer if more modifiers, I went through the whole list"
net.p455w0rd.wirelesscraftingterminal.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler,WirelessCraftingTerminal,ae2wct:wirelessCraftingTerminal,,ae2wct,TRUE,,,,,,,,,,,
alkalus.main.nei.NEI_Handler_Cauldron,witchery,witchery:cauldron,,WitcheryExtras,TRUE,,,65,,5,,,,,,
alkalus.main.nei.NEI_Handler_Distillery,witchery,witchery:distilleryidle,,WitcheryExtras,TRUE,,,140,,2,,,,,,
alkalus.main.nei.NEI_Handler_Kettle,witchery,witchery:kettle,,WitcheryExtras,TRUE,,,65,,5,,,,,,
alkalus.main.nei.NEI_Handler_Oven,witchery,witchery:witchesovenidle,,WitcheryExtras,TRUE,,,,,,,,,,,Not working at all now
alkalus.main.nei.NEI_Handler_SpinningWheel,witchery,witchery:spinningwheel,,WitcheryExtras,TRUE,,,65,,5,,,,,,
com.emoniph.witchery.integration.NEICauldronRecipeHandler,witchery,witchery:cauldron,,witchery,TRUE,,,65,,5,,,,,,Replaced by WE presumably
com.emoniph.witchery.integration.NEIDistilleryRecipeHandler,witchery,witchery:distilleryidle,,witchery,TRUE,,,140,,2,,,,,,Replaced by WE presumably
com.emoniph.witchery.integration.NEIKettleRecipeHandler,witchery,witchery:kettle,,witchery,TRUE,,,65,,5,,,,,,Replaced by WE presumably
com.emoniph.witchery.integration.NEISpinningWheelRecipeHandler,witchery,witchery:spinningwheel,,witchery,TRUE,,,,,,,,,,,Replaced by WE presumably
com.emoniph.witchery.integration.NEIWitchesOvenRecipeHandler,witchery,witchery:witchesovenidle,,witchery,TRUE,,,65,,5,,,,,,Replaced by WE presumably
witchinggadgets.client.nei.NEIInfernalBlastfurnaceHandler,WitchingGadgets,WitchingGadgets:WG_StoneDevice:2,,WitchingGadgets,TRUE,,,65,,5,,,,,,
witchinggadgets.client.nei.NEISpinningWheelHandler,WitchingGadgets,WitchingGadgets:WG_WoodenDevice,,WitchingGadgets,TRUE,,,110,,3,,,,,,
gt.recipe.anvil,Gregtech 6,gregtech:gt.multitileentity:32031,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.anvil.bend.big,Gregtech 6,gregtech:gt.multitileentity:32031,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.anvil.bend.small,Gregtech 6,gregtech:gt.multitileentity:32031,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.aquaticfarm,Gregtech 6,gregtech:gt.multitileentity:17131,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.assembler,Gregtech 6,gregtech:gt.multitileentity:20621,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.autoclave,Gregtech 6,gregtech:gt.multitileentity:22004,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.bath,Gregtech 6,gregtech:gt.multitileentity:22002,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.bedrockorelist,Gregtech 6,gregtech:gt.multitileentity:17999,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.biolab,Gregtech 6,gregtech:gt.multitileentity:17127,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.boxinator,Gregtech 6,gregtech:gt.multitileentity:20581,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.bumblelyzer,Gregtech 6,gregtech:gt.multitileentity:20541,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.bumblequeen,Gregtech 6,gregtech:gt.multiitem.bumblebee:1,"{""gt.bumble"": {}}",gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.burnmixer,Gregtech 6,gregtech:gt.multitileentity:20521,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.byproductlist,Gregtech 6,minecraft:diamond_ore,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.canner,Gregtech 6,gregtech:gt.multitileentity:20161,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.catalyticcracking,Gregtech 6,gregtech:gt.multitileentity:20481,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.centrifuge,Gregtech 6,gregtech:gt.multitileentity:20081,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.clustermill,Gregtech 6,gregtech:gt.multitileentity:20141,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.coagulator,Gregtech 6,gregtech:gt.multitileentity:22000,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cokeoven,Gregtech 6,gregtech:gt.multitileentity:17000,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.compressor,Gregtech 6,gregtech:gt.multitileentity:20101,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.crackingtower,Gregtech 6,gregtech:gt.multitileentity:17115,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cruciblealloying,Gregtech 6,gregtech:gt.multitileentity:1005,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cruciblesmelting,Gregtech 6,gregtech:gt.multitileentity:1005,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.crusher,Gregtech 6,gregtech:gt.multitileentity:20021,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cryodistillationtower,Gregtech 6,gregtech:gt.multitileentity:17111,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cryomixer,Gregtech 6,gregtech:gt.multitileentity:20571,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.crystallisationcrucible,Gregtech 6,gregtech:gt.multitileentity:20251,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.cutter,Gregtech 6,gregtech:gt.multitileentity:20061,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.debarker,Gregtech 6,gregtech:gt.multitileentity:20551,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.distillationtower,Gregtech 6,gregtech:gt.multitileentity:20191,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.distillery,Gregtech 6,gregtech:gt.multitileentity:20191,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.drying,Gregtech 6,gregtech:gt.multitileentity:20311,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.electrolyzer,Gregtech 6,gregtech:gt.multitileentity:20091,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.extruder,Gregtech 6,gregtech:gt.multitileentity:20202,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fermenter,Gregtech 6,gregtech:gt.multitileentity:22003,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fluidsolidifier,Gregtech 6,gregtech:gt.multitileentity:20611,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.freezer,Gregtech 6,gregtech:gt.multitileentity:20561,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.burn,Gregtech 6,gregtech:gt.multitileentity:1109,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.engine,Gregtech 6,gregtech:gt.multitileentity:9147,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.fluidbed,Gregtech 6,gregtech:gt.multitileentity:9009,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.gas,Gregtech 6,gregtech:gt.multitileentity:1609,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.plasma,Gregtech 6,gregtech:gt.multitileentity:17251,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fuels.turbine,Gregtech 6,gregtech:gt.multitileentity:17231,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.fusionreactor,Gregtech 6,gregtech:gt.multitileentity:17198,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.generifier,Gregtech 6,gregtech:gt.multitileentity:22001,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.heatmixer,Gregtech 6,gregtech:gt.multitileentity:20506,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.implosioncompressor,Gregtech 6,gregtech:gt.multitileentity:17110,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.incubator,Gregtech 6,gregtech:gt.multitileentity:22005,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.injector,Gregtech 6,gregtech:gt.multitileentity:20261,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.ionizer,Gregtech 6,gregtech:gt.multitileentity:17315,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.juicer,Gregtech 6,gregtech:gt.multitileentity:32722,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.laminator,Gregtech 6,gregtech:gt.multitileentity:20391,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.lasercutter,Gregtech 6,gregtech:gt.multitileentity:20631,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.laserengraver,Gregtech 6,gregtech:gt.multitileentity:20321,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.lathe,Gregtech 6,gregtech:gt.multitileentity:20041,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.lightning,Gregtech 6,gregtech:gt.multitileentity:20501,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.loom,Gregtech 6,gregtech:gt.multitileentity:20211,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.magneticseparator,Gregtech 6,gregtech:gt.multitileentity:20301,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.maskaligner,Gregtech 6,gregtech:gt.multitileentity:17122,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.massfab,Gregtech 6,gregtech:gt.multitileentity:20411,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.mixer,Gregtech 6,gregtech:gt.multitileentity:20181,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.mortar,Gregtech 6,gregtech:gt.multitileentity:32735,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.nanofab,Gregtech 6,gregtech:gt.multitileentity:20441,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.oilcleaner,Gregtech 6,gregtech:gt.multitileentity:17116,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.particlecollider,Gregtech 6,gregtech:gt.multitileentity:17200,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.plantalyzer,Gregtech 6,gregtech:gt.multitileentity:20531,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.polarizer,Gregtech 6,gregtech:gt.multitileentity:20221,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.press,Gregtech 6,gregtech:gt.multitileentity:20231,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.printer,Gregtech 6,gregtech:gt.multitileentity:20271,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.replicator,Gregtech 6,gregtech:gt.multitileentity:20431,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.roaster,Gregtech 6,gregtech:gt.multitileentity:20171,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.rollbender,Gregtech 6,gregtech:gt.multitileentity:20121,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.rollformer,Gregtech 6,gregtech:gt.multitileentity:20131,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.rollingmill,Gregtech 6,gregtech:gt.multitileentity:20111,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.scannermolecular,Gregtech 6,gregtech:gt.multitileentity:20423,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.scannervisuals,Gregtech 6,gregtech:gt.multitileentity:20281,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.sharpener,Gregtech 6,gregtech:gt.multitileentity:20511,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.shredder,Gregtech 6,gregtech:gt.multitileentity:20011,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.sifter,Gregtech 6,gregtech:gt.multitileentity:20051,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.slicer,Gregtech 6,gregtech:gt.multitileentity:20381,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.sluice,Gregtech 6,gregtech:gt.multitileentity:20291,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.smelter,Gregtech 6,gregtech:gt.multitileentity:20241,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.squeezer,Gregtech 6,gregtech:gt.multitileentity:20071,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.steamcracking,Gregtech 6,gregtech:gt.multitileentity:20491,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.toolhead,Gregtech 6,gregtech:gt.meta.toolHeadPickaxe:260,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.unboxinator,Gregtech 6,gregtech:gt.multitileentity:20591,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.welder,Gregtech 6,gregtech:gt.multitileentity:20331,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.well,Gregtech 6,gregtech:gt.multitileentity:17124,,gregapi_post,TRUE,,15,145,166,2,,,,,,
gt.recipe.wiremill,Gregtech 6,gregtech:gt.multitileentity:20151,,gregapi_post,TRUE,,15,145,166,2,,,,,,
smelting,Gregtech 6,gregtech:gt.multitileentity:20001,,gregapi_post,TRUE,,15,145,166,2,,,,,,This uses the same recipe map as the MC furnace
gt.recipe.trees,Gregtech 6,minecraft:sapling,,gregapi_post,TRUE,,15,145,166,2,,,,,,
moze_intel.projecte.integration.NEI.NEIWorldTransmuteHandler,ProjectE,ProjectE:item.pe_philosophers_stone,,ProjectE,TRUE,,,45,,10,,,,,,
moze_intel.projecte.integration.NEI.NEIPhiloSmeltingHandler,ProjectE,ProjectE:item.pe_philosophers_stone,,ProjectE,TRUE,,,,,5,,,,,,
moze_intel.projecte.integration.NEI.NEIKleinStarHandler,ProjectE,ProjectE:item.pe_klein_star,,ProjectE,TRUE,,,,,5,,,,,,
moze_intel.projecte.integration.NEI.NEIAlchBagHandler,ProjectE,ProjectE:item.pe_alchemical_bag,,ProjectE,TRUE,,,,,5,,,,,,
de.katzenpapst.amunra.nei.recipehandler.ARCircuitFab,Pra's Galacticraft Mod,GalacticraftCore:tile.machine2:4,,GalacticraftAmunRa,TRUE,,,,,,,,,,,
de.katzenpapst.amunra.nei.recipehandler.ARNasaWorkbenchShuttle,Pra's Galacticraft Mod,GalacticraftAmunRa:item.itemShuttle,,GalacticraftAmunRa,TRUE,,,130,168,16,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerFloatingFlowers,Botania,Botania:miniIsland,,Botania,TRUE,,,,,5,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerPetalApothecary,Botania,Botania:altar,,Botania,TRUE,,,102,137,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerRunicAltar,Botania,Botania:runeAltar,,Botania,TRUE,,,122,137,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerManaPool,Botania,Botania:pool,,Botania,TRUE,,,90,137,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerElvenTrade,Botania,Botania:alfheimPortal,,Botania,TRUE,,,90,130,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerBrewery,Botania,Botania:brewery,,Botania,TRUE,,,,,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerPureDaisy,Botania,Botania:specialFlower,"{""type"": ""puredaisy""}",Botania,TRUE,,,,,4,,,,,,
vazkii.botania.client.integration.nei.recipe.RecipeHandlerLexicaBotania,Botania,Botania:lexicon,,Botania,TRUE,,,,,,,,,,,
com.jaquadro.minecraft.storagedrawers.integration.notenoughitems.UpgradeItemRecipeHandler,Storage Drawers,minecraft:crafting_table,,StorageDrawers,TRUE,,,65,166,5,,,,,,
ieArcFurnace,Immersive Engineering,ImmersiveEngineering:graphiteElectrode,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerAlloying,Immersive Engineering,terrafirmacraftplus:item.Bronze Ingot,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerOres,Immersive Engineering,minecraft:iron_ore,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerSmelting,Immersive Engineering,terrafirmacraftplus:item.Ore:100,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerGlassworking,Immersive Engineering,minecraft:glass,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerDecarburization,Immersive Engineering,terrafirmacraftplus:item.Wrought Iron Ingot,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerCarburization,Immersive Engineering,terrafirmacraftplus:item.HC Steel Ingot,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerHeating,Immersive Engineering,,,ImmersiveEngineering,TRUE,,,65,166,5,nei:textures/nei_tabbed_sprites.png,80,0,14,14,
NEIArcFurnaceHandlerMelting,Immersive Engineering,terrafirmacraftplus:item.Molten Glass,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerWelding,Immersive Engineering,terrafirmacraftplus:item.Bismuth Double Ingot,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
NEIArcFurnaceHandlerElectrolysis,Immersive Engineering,teloaddon:Alumina,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIShaderBagHandler,Immersive Engineering,ImmersiveEngineering:shaderBag,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlueprintHandler,Immersive Engineering,ImmersiveEngineering:blueprint,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:1,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:2,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEISqueezerHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:2,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIFermenterHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:3,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIRefineryHandler,Immersive Engineering,ImmersiveEngineering:metalDevice2:5,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler,Immersive Engineering,minecraft:glass_bottle,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler,Immersive Engineering,ImmersiveEngineering:mold,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICrusherHandler,Immersive Engineering,minecraft:hopper,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.AnvilRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:Anvil,,terrafirmacraftplus,TRUE,,10,138,208,2,,,,,,
net.dries007.tfcnei.recipeHandlers.QuernRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:item.Quern,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.KilnRecipeHandler,TerraFirmaCraft+,,,terrafirmacraftplus,TRUE,,,65,166,5,terrafirmacraftneiplugin:textures/gui/pitkiln.png,47,38,14,14,
net.dries007.tfcnei.recipeHandlers.LoomRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:Loom,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.KnappingRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:item.LooseRock,,terrafirmacraftplus,TRUE,,,96,166,3,,,,,,
net.dries007.tfcnei.recipeHandlers.ClothingRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:item.Bone Needle Thread,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.BarrelRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:Barrel,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.AlloyRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:Crucible,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
net.dries007.tfcnei.recipeHandlers.HeatRecipeHandler,TerraFirmaCraft+,terrafirmacraftplus:Firepit,,terrafirmacraftplus,TRUE,,,65,166,5,,,,,,
1 handler modName itemName nbtInfo modId modRequired excludedModId yShift handlerHeight handlerWidth maxRecipesPerPage imageResource imageX imageY imageWidth imageHeight itemNotes
2 codechicken.nei.recipe.BrewingRecipeHandler minecraft minecraft:brewing_stand minecraft FALSE 65 166 5
3 codechicken.nei.recipe.FireworkRecipeHandler minecraft minecraft:fireworks minecraft FALSE 65 166 5
4 codechicken.nei.recipe.FurnaceRecipeHandler minecraft minecraft:furnace minecraft FALSE 65 166 5
5 codechicken.nei.recipe.ShapedRecipeHandler minecraft minecraft:crafting_table minecraft FALSE 65 166 5
6 codechicken.nei.recipe.ShapelessRecipeHandler minecraft minecraft:crafting_table minecraft FALSE 65 166 5
7 codechicken.nei.recipe.FuelRecipeHandler minecraft minecraft FALSE 65 166 5 nei:textures/nei_tabbed_sprites.png 80 0 14 14
8 advsolar.client.nei.MTRecipeHandler AdvancedSolarPanel AdvancedSolarPanel:BlockMolecularTransformer AdvancedSolarPanel TRUE 68 5
9 appeng.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler AppliedEnergistics2 appliedenergistics2:item.ItemMultiPart:380 appliedenergistics2 TRUE 65 5
10 appeng.integration.modules.NEIHelpers.NEIAEShapelessRecipeHandler AppliedEnergistics2 appliedenergistics2:item.ItemMultiPart:380 appliedenergistics2 TRUE 65 5
11 appeng.integration.modules.NEIHelpers.NEIFacadeRecipeHandler AppliedEnergistics2 appliedenergistics2:item.ItemFacade:192 appliedenergistics2 TRUE 65 5
12 appeng.integration.modules.NEIHelpers.NEIGrinderRecipeHandler AppliedEnergistics2 appliedenergistics2:item.ItemMultiMaterial:8 appliedenergistics2 TRUE
13 appeng.integration.modules.NEIHelpers.NEIInscriberRecipeHandler AppliedEnergistics2 appliedenergistics2:tile.BlockInscriber appliedenergistics2 TRUE 70 5
14 appeng.integration.modules.NEIHelpers.NEIWorldCraftingHandler AppliedEnergistics2 appliedenergistics2:item.ItemMultiMaterial:9 appliedenergistics2 TRUE 85 5 There's only some explanatory text for fluix crystals and QEDs
15 aroma1997.core.recipes.nei.ShapedAromicRecipeHandler AromaBackup minecraft:crafting_table AromaBackup TRUE 65 5
16 aroma1997.core.recipes.nei.ShapelessAromicRecipeHandler AromaBackup minecraft:crafting_table AromaBackup TRUE
17 fox.spiteful.avaritia.compat.nei.CompressionHandler Avaritia Avaritia:Neutronium_Compressor Avaritia TRUE 50 6
18 fox.spiteful.avaritia.compat.nei.ExtremeShapedRecipeHandler Avaritia Avaritia:Dire_Crafting Avaritia TRUE 208 256 1 Part of it even goes off the left side (included)
19 fox.spiteful.avaritia.compat.nei.ExtremeShapelessRecipeHandler Avaritia Avaritia:Dire_Crafting Avaritia TRUE 208 256 1 If you can cut off/place over the jaggedness at the bottom, you could barely get a second one
20 WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler BloodMagic AWWayofTime:blockWritingTable AWWayofTime TRUE 68 5
21 WayofTime.alchemicalWizardry.client.nei.NEIAltarRecipeHandler BloodMagic AWWayofTime:Altar AWWayofTime TRUE 65 5 Handler name needs shifting left
22 WayofTime.alchemicalWizardry.client.nei.NEIBindingRitualHandler BloodMagic AWWayofTime:sacrificialKnife AWWayofTime TRUE 50 6
23 WayofTime.alchemicalWizardry.client.nei.NEIBloodOrbShapedHandler BloodMagic AWWayofTime:AlchemicalWizardrybloodRune:3 AWWayofTime TRUE 65 5
24 WayofTime.alchemicalWizardry.client.nei.NEIBloodOrbShapelessHandler BloodMagic AWWayofTime:AlchemicalWizardrybloodRune:4 AWWayofTime TRUE 65 5
25 bw.fuels.acidgens BartWorks gregtech:gt.blockmachines:12726 bartworks TRUE 145 2
26 bw.recipe.cal BartWorks gregtech:gt.blockmachines:12735 bartworks TRUE 135 2
27 com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_BioLabHandler BartWorks gregtech:gt.blockmachines:12699 bartworks TRUE 145 2
28 com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_BioVatHandler BartWorks gregtech:gt.blockmachines:12712 bartworks TRUE 140 2
29 com.github.bartimaeusnek.bartworks.neiHandler.BW_NEI_OreHandler BartWorks bartworks:bw.blockores.01:89 bartworks TRUE 135 2
30 gt.recipe.electricimplosioncompressor BartWorks gregtech:gt.blockmachines:12734 bartworks TRUE 135 2
31 net.bdew.neiaddons.botany.flowers.FlowerBreedingHandler Botany Botany:flower Botany TRUE 65 5
32 buildcraft.compat.nei.RecipeHandlerRefinery BuildCraft BuildCraft|Factory:refineryBlock BuildCraft|Factory TRUE 60 5 There's only 2 recipes though
33 buildcraft.compat.nei.RecipeHandlerAssemblyTable BuildCraft BuildCraft|Silicon:laserTableBlock BuildCraft|Silicon TRUE 100 3
34 buildcraft.compat.nei.RecipeHandlerIntegrationTable BuildCraft BuildCraft|Silicon:laserTableBlock:2 BuildCraft|Silicon TRUE 85 4
35 team.chisel.compat.nei.RecipeHandlerChisel Chisel chisel:chisel chisel TRUE 135 2
36 crazypants.enderio.nei.AlloySmelterRecipeHandler EnderIO EnderIO:blockAlloySmelter EnderIO TRUE 65 5
37 crazypants.enderio.nei.EnchanterRecipeHandler EnderIO EnderIO:blockEnchanter EnderIO TRUE 65 5
38 crazypants.enderio.nei.SagMillRecipeHandler EnderIO EnderIO:blockSagMill EnderIO TRUE 68 5
39 crazypants.enderio.nei.SliceAndSpliceRecipeHandler EnderIO EnderIO:blockSliceAndSplice EnderIO TRUE 65 5
40 crazypants.enderio.nei.SoulBinderRecipeHandler EnderIO EnderIO:blockSoulBinder EnderIO TRUE 68 5
41 crazypants.enderio.nei.VatRecipeHandler EnderIO EnderIO:blockVat EnderIO TRUE 65 5
42 extracells.integration.nei.UniversalTerminalRecipe ExtraCells extracells:part.base:9 extracells TRUE 65 5
43 com.rwtema.extrautils.nei.EnderConstructorHandler ExtraUtilities ExtraUtilities:endConstructor ExtraUtilities TRUE 68 5
44 com.rwtema.extrautils.nei.FMPMicroBlocksHandler ExtraUtilities ForgeMicroblock:sawIron ExtraUtilities TRUE 65 5
45 com.rwtema.extrautils.nei.InfoHandler ExtraUtilities ExtraUtilities:chandelier ExtraUtilities TRUE 135 2 Info on blocks, can vary wildly. EQ was this length, there might be a longer one
46 com.rwtema.extrautils.nei.MicroBlocksHandler ExtraUtilities ExtraUtilities:microblocks:1 ExtraUtilities TRUE
47 com.rwtema.extrautils.nei.SoulHandler ExtraUtilities ExtraUtilities:mini-soul ExtraUtilities TRUE
48 hellfirepvp.beebetteratbees.client.gui.BBABGuiRecipeTreeHandler Bees Forestry:beeQueenGE Forestry TRUE 140 2
49 forestry.factory.recipes.nei.NEIHandlerBottler Forestry Forestry:factory Forestry TRUE 68 5
50 forestry.factory.recipes.nei.NEIHandlerCarpenter Forestry Forestry:factory:1 Forestry TRUE 65 5
51 forestry.factory.recipes.nei.NEIHandlerCentrifuge Forestry Forestry:factory:2 Forestry TRUE 65 5
52 forestry.factory.recipes.nei.NEIHandlerFabricator Forestry Forestry:factory2 Forestry TRUE
53 forestry.factory.recipes.nei.NEIHandlerFermenter Forestry Forestry:factory:3 Forestry TRUE 65 5
54 forestry.factory.recipes.nei.NEIHandlerMoistener Forestry Forestry:factory:4 Forestry TRUE 68 5
55 forestry.factory.recipes.nei.NEIHandlerSqueezer Forestry Forestry:factory:5 Forestry TRUE 68 5
56 forestry.factory.recipes.nei.NEIHandlerStill Forestry Forestry:factory:6 Forestry TRUE 65 5
57 net.bdew.neiaddons.forestry.bees.BeeBreedingHandler Forestry Forestry:beeQueenGE Forestry TRUE 65 5
58 net.bdew.neiaddons.forestry.bees.BeeProduceHandler Forestry Forestry:beeQueenGE Forestry TRUE 65 5
59 net.bdew.neiaddons.forestry.butterflies.ButterflyBreedingHandler Forestry Forestry:butterflyGE Forestry TRUE
60 net.bdew.neiaddons.forestry.trees.TreeBreedingHandler Forestry Forestry:saplingGE Forestry TRUE 65 5
61 net.bdew.neiaddons.forestry.trees.TreeProduceHandler Forestry Forestry:saplingGE Forestry TRUE 65 5
62 galaxyspace.core.nei.rocket.RocketT1RecipeHandler Galacticraft GalacticraftCore:item.spaceship GalacticraftCore TRUE 125 2
63 micdoodle8.mods.galacticraft.core.nei.BuggyRecipeHandler Galacticraft GalacticraftCore:tile.rocketWorkbench GalacticraftCore TRUE 10 135 2
64 micdoodle8.mods.galacticraft.core.nei.CircuitFabricatorRecipeHandler Galacticraft GalacticraftCore:tile.machine2:4 GalacticraftCore TRUE
65 micdoodle8.mods.galacticraft.core.nei.ElectricIngotCompressorRecipeHandler Galacticraft GalacticraftCore:tile.machine2 GalacticraftCore TRUE
66 micdoodle8.mods.galacticraft.core.nei.IngotCompressorRecipeHandler Galacticraft GalacticraftCore:tile.machine:12 GalacticraftCore TRUE
67 micdoodle8.mods.galacticraft.core.nei.RefineryRecipeHandler Galacticraft GalacticraftCore:tile.refinery GalacticraftCore TRUE
68 micdoodle8.mods.galacticraft.planets.asteroids.nei.AstroMinerRecipeHandler Galacticraft GalacticraftCore:tile.rocketWorkbench GalacticraftCore TRUE 100 3
69 micdoodle8.mods.galacticraft.planets.mars.nei.CargoRocketRecipeHandler Galacticraft GalacticraftCore:tile.rocketWorkbench GalacticraftCore TRUE 10 125 2
70 micdoodle8.mods.galacticraft.planets.mars.nei.GasLiquefierRecipeHandler Galacticraft GalacticraftMars:tile.marsMachineT2 GalacticraftCore TRUE
71 micdoodle8.mods.galacticraft.planets.mars.nei.MethaneSynthesizerRecipeHandler Galacticraft GalacticraftMars:tile.marsMachineT2:4 GalacticraftCore TRUE
72 galaxyspace.core.nei.rocket.RocketT2RecipeHandler Galacticraft GalacticraftMars:item.spaceshipTier2:1 GalacticraftMars TRUE 5 145 2
73 galaxyspace.core.nei.rocket.RocketT3RecipeHandler Galacticraft GalacticraftMars:item.itemTier3Rocket GalacticraftMars TRUE 5 145 2
74 galaxyspace.core.nei.AssemblyMachineRecipeHandler GalaxySpace GalaxySpace:assemblymachine GalaxySpace TRUE
75 galaxyspace.core.nei.rocket.RocketT4RecipeHandler GalaxySpace GalaxySpace:item.Tier4Rocket GalaxySpace TRUE 10 160 2
76 galaxyspace.core.nei.rocket.RocketT5RecipeHandler GalaxySpace GalaxySpace:item.Tier5Rocket GalaxySpace TRUE 10 160 2
77 galaxyspace.core.nei.rocket.RocketT6RecipeHandler GalaxySpace GalaxySpace:item.Tier6Rocket GalaxySpace TRUE 10 160 2
78 galaxyspace.core.nei.rocket.RocketT7RecipeHandler GalaxySpace GalaxySpace:item.Tier7Rocket GalaxySpace TRUE 10 180 1
79 galaxyspace.core.nei.rocket.RocketT8RecipeHandler GalaxySpace GalaxySpace:item.Tier8Rocket GalaxySpace TRUE 10 180 1
80 net.bdew.gendustry.nei.ExtractorHandler Gendustry gendustry:Extractor gendustry TRUE 68 5
81 net.bdew.gendustry.nei.ImprinterHandler Gendustry gendustry:Imprinter gendustry TRUE 68 5
82 net.bdew.gendustry.nei.LiquifierHandler Gendustry gendustry:Liquifier gendustry TRUE 68 5
83 net.bdew.gendustry.nei.MutagenProducerHandler Gendustry gendustry:MutagenProducer gendustry TRUE 68 5
84 net.bdew.gendustry.nei.MutatronHandler Gendustry gendustry:Mutatron gendustry TRUE 65 5
85 net.bdew.gendustry.nei.ReplicatorHandler Gendustry gendustry:Replicator gendustry TRUE 68 5
86 net.bdew.gendustry.nei.SamplerHandler Gendustry gendustry:Sampler gendustry TRUE 68 5
87 net.bdew.gendustry.nei.TemplateCraftingHandler Gendustry gendustry:GeneTemplate gendustry TRUE 105 3
88 net.bdew.gendustry.nei.TransposerHandler Gendustry gendustry:Transposer gendustry TRUE 68 5
89 gt.recipe.alloysmelter gregtech gregtech:gt.blockmachines:201 gregtech TRUE gregapi_post 6 135 166 2
90 gt.recipe.arcfurnace gregtech gregtech:gt.blockmachines:651 gregtech TRUE gregapi_post 6 135 166 2
91 gt.recipe.assembler gregtech gregtech:gt.blockmachines:211 gregtech TRUE gregapi_post 6 145 166 2
92 gt.recipe.autoclave gregtech gregtech:gt.blockmachines:571 gregtech TRUE gregapi_post 6 135 166 2
93 gt.recipe.blastfurnace gregtech gregtech:gt.blockmachines:1000 gregtech TRUE gregapi_post 6 135 166 2
94 gt.recipe.brewer gregtech gregtech:gt.blockmachines:491 gregtech TRUE gregapi_post 6 135 166 2
95 gt.recipe.byproductlist gregtech gregtech:gt.metaitem.01:2019 gregtech TRUE gregapi_post 6 135 166 2
96 gt.recipe.canner gregtech gregtech:gt.blockmachines:231 gregtech TRUE gregapi_post 6 135 166 2
97 gt.recipe.centrifuge gregtech gregtech:gt.blockmachines:361 gregtech TRUE gregapi_post 6 135 166 2
98 gt.recipe.chemicalbath gregtech gregtech:gt.blockmachines:541 gregtech TRUE gregapi_post 6 135 166 2
99 gt.recipe.chemicalreactor gregtech gregtech:gt.blockmachines:421 gregtech TRUE gregapi_post 6 135 166 2
100 gt.recipe.circuitassembler gregtech gregtech:gt.blockmachines:1180 gregtech TRUE gregapi_post 6 135 166 2
101 gt.recipe.cncmachine gregtech gregtech:gt.metaitem.01:23305 gregtech TRUE gregapi_post 6 135 166 2
102 gt.recipe.cokeoven gregtech gregtech:gt.blockmachines:791 gregtech TRUE gregapi_post 6 135 166 2
103 gt.recipe.componentassembler gregtech gregtech:gt.blockmachines:211 gregtech TRUE gregapi_post 6 135 166 2
104 gt.recipe.compressor gregtech gregtech:gt.blockmachines:241 gregtech TRUE gregapi_post 6 135 166 2
105 gt.recipe.craker gregtech gregtech:gt.blockmachines:1160 gregtech TRUE gregapi_post 6 135 166 2
106 gt.recipe.cuttingsaw gregtech gregtech:gt.blockmachines:251 gregtech TRUE gregapi_post 6 135 166 2
107 gt.recipe.dieselgeneratorfuel gregtech gregtech:gt.blockmachines:1110 gregtech TRUE gregapi_post 6 135 166 2
108 gt.recipe.distillationtower gregtech gregtech:gt.blockmachines:1126 gregtech TRUE gregapi_post 6 135 166 2
109 gt.recipe.distillery gregtech gregtech:gt.blockmachines:531 gregtech TRUE gregapi_post 6 135 166 2
110 gt.recipe.electrolyzer gregtech gregtech:gt.blockmachines:371 gregtech TRUE gregapi_post 6 135 166 2
111 gt.recipe.electromagneticseparator gregtech gregtech:gt.blockmachines:561 gregtech TRUE gregapi_post 6 135 166 2
112 gt.recipe.extractor gregtech gregtech:gt.blockmachines:271 gregtech TRUE gregapi_post 6 135 166 2
113 gt.recipe.extrahugenaquadahreactor gregtech gregtech:gt.blockmachines:1189 gregtech TRUE gregapi_post 6 135 166 2
114 gt.recipe.extremedieselgeneratorfuel gregtech gregtech:gt.blockmachines:2105 gregtech TRUE gregapi_post 6 135 166 2
115 gt.recipe.extruder gregtech gregtech:gt.blockmachines:281 gregtech TRUE gregapi_post 6 135 166 2
116 gt.recipe.fakeAssemblylineProcess gregtech gregtech:gt.blockmachines:1170 gregtech TRUE gregapi_post 12 135 166 2
117 gt.recipe.fermenter gregtech gregtech:gt.blockmachines:501 gregtech TRUE gregapi_post 6 135 166 2
118 gt.recipe.fluidcanner gregtech gregtech:gt.blockmachines:431 gregtech TRUE gregapi_post 6 135 166 2
119 gt.recipe.fluidextractor gregtech gregtech:gt.blockmachines:511 gregtech TRUE gregapi_post 6 135 166 2
120 gt.recipe.fluidheater gregtech gregtech:gt.blockmachines:621 gregtech TRUE gregapi_post 6 135 166 2
121 gt.recipe.fluidnaquadahreactor gregtech gregtech:gt.blockmachines:1192 gregtech TRUE gregapi_post 6 135 166 2
122 gt.recipe.fluidsolidifier gregtech gregtech:gt.blockmachines:521 gregtech TRUE gregapi_post 6 135 166 2
123 gt.recipe.fusionreactor gregtech gregtech:gt.blockmachines:1193 gregtech TRUE gregapi_post 6 135 166 2
124 gt.recipe.gasturbinefuel gregtech gregtech:gt.blockmachines:1115 gregtech TRUE gregapi_post 6 135 166 2
125 gt.recipe.hammer gregtech gregtech:gt.blockmachines:611 gregtech TRUE gregapi_post 6 135 166 2
126 gt.recipe.hugenaquadahreactor gregtech gregtech:gt.blockmachines:1188 gregtech TRUE gregapi_post 6 135 166 2
127 gt.recipe.implosioncompressor gregtech gregtech:gt.blockmachines:12734 gregtech TRUE gregapi_post 6 135 166 2
128 gt.recipe.largeboilerfakefuels gregtech gregtech:gt.blockmachines:1020 gregtech TRUE gregapi_post 6 135 166 2
129 gt.recipe.largechemicalreactor gregtech gregtech:gt.blockmachines:1169 gregtech TRUE gregapi_post 6 135 166 2
130 gt.recipe.largenaquadahreactor gregtech gregtech:gt.blockmachines:1191 gregtech TRUE gregapi_post 6 135 166 2
131 gt.recipe.laserengraver gregtech gregtech:gt.blockmachines:591 gregtech TRUE gregapi_post 6 135 166 2
132 gt.recipe.lathe gregtech gregtech:gt.blockmachines:291 gregtech TRUE gregapi_post 6 135 166 2
133 gt.recipe.macerator gregtech gregtech:gt.blockmachines:301 gregtech TRUE gregapi_post 6 135 166 2
134 gt.recipe.magicfuels gregtech gregtech:gt.blockmachines:1123 gregtech TRUE gregapi_post 6 135 166 2
135 gt.recipe.massfab gregtech gregtech:gt.blockmachines:461 gregtech TRUE gregapi_post 6 135 166 2
136 gt.recipe.metalbender gregtech gregtech:gt.blockmachines:221 gregtech TRUE gregapi_post 6 135 166 2
137 gt.recipe.microwave gregtech gregtech:gt.blockmachines:311 gregtech TRUE gregapi_post 6 135 166 2
138 gt.recipe.mixer gregtech gregtech:gt.blockmachines:581 gregtech TRUE gregapi_post 6 135 166 2
139 gt.recipe.orewasher gregtech gregtech:gt.blockmachines:391 gregtech TRUE gregapi_post 6 135 166 2
140 gt.recipe.packager gregtech gregtech:gt.blockmachines:401 gregtech TRUE gregapi_post 6 135 166 2
141 gt.recipe.plasmaarcfurnace gregtech gregtech:gt.blockmachines:661 gregtech TRUE gregapi_post 6 135 166 2
142 gt.recipe.plasmageneratorfuels gregtech gregtech:gt.blockmachines:1196 gregtech TRUE gregapi_post 6 135 166 2
143 gt.recipe.polarizer gregtech gregtech:gt.blockmachines:551 gregtech TRUE gregapi_post 6 135 166 2
144 gt.recipe.press gregtech gregtech:gt.blockmachines:601 gregtech TRUE gregapi_post 6 135 166 2
145 gt.recipe.primitiveblastfurnace gregtech gregtech:gt.blockmachines:140 gregtech TRUE gregapi_post 6 135 166 2
146 gt.recipe.printer gregtech gregtech:gt.blockmachines:321 gregtech TRUE gregapi_post 6 135 166 2
147 gt.recipe.pyro gregtech gregtech:gt.blockmachines:1159 gregtech TRUE gregapi_post 6 135 166 2
148 gt.recipe.replicator gregtech gregtech:gt.blockmachines:481 gregtech TRUE gregapi_post 6 135 166 2
149 gt.recipe.rockbreaker gregtech gregtech:gt.blockmachines:441 gregtech TRUE gregapi_post 6 135 166 2
150 gt.recipe.scanner gregtech gregtech:gt.blockmachines:341 gregtech TRUE gregapi_post 6 135 166 2
151 gt.recipe.semifluidboilerfuels gregtech gregtech:gt.blockmachines:1020 gregtech TRUE gregapi_post 6 135 166 2
152 gt.recipe.sifter gregtech gregtech:gt.blockmachines:641 gregtech TRUE gregapi_post 6 135 166 2
153 gt.recipe.slicer gregtech gregtech:gt.blockmachines:631 gregtech TRUE gregapi_post 6 135 166 2
154 gt.recipe.smallnaquadahreactor gregtech gregtech:gt.blockmachines:1190 gregtech TRUE gregapi_post 6 135 166 2
155 gt.recipe.thermalcentrifuge gregtech gregtech:gt.blockmachines:381 gregtech TRUE gregapi_post 6 135 166 2
156 gt.recipe.thermalgeneratorfuel gregtech IC2:blockGenerator:1 gregtech TRUE gregapi_post 6 135 166 2
157 gt.recipe.unpackager gregtech gregtech:gt.blockmachines:411 gregtech TRUE gregapi_post 6 135 166 2
158 gt.recipe.uuamplifier gregtech gregtech:gt.blockmachines:471 gregtech TRUE gregapi_post 6 135 166 2
159 gt.recipe.vacuumfreezer gregtech gregtech:gt.blockmachines:1002 gregtech TRUE gregapi_post 6 135 166 2
160 gt.recipe.wiremill gregtech gregtech:gt.blockmachines:351 gregtech TRUE gregapi_post 6 135 166 2
161 ic.recipe.recycler gregtech gregtech:gt.blockmachines:331 gregtech TRUE gregapi_post 6 135 166 2
162 pers.gwyog.gtneioreplugin.plugin.gregtech5.PluginGT5SmallOreStat Gregtech gregtech:gt.blockores:85 gregtech TRUE 145 2
163 pers.gwyog.gtneioreplugin.plugin.gregtech5.PluginGT5VeinStat Gregtech gregtech:gt.blockores:386 gregtech TRUE 135 2
164 ic2.neiIntegration.core.recipehandler.AdvRecipeHandler IC2 IC2:blockreactorvessel IC2 TRUE 65 5
165 ic2.neiIntegration.core.recipehandler.AdvShapelessRecipeHandler IC2 IC2:blockreactorvessel IC2 TRUE 65 5
166 ic2.neiIntegration.core.recipehandler.BlastFurnaceRecipeHandler IC2 IC2:blockMachine3:1 IC2 TRUE 65 5
167 ic2.neiIntegration.core.recipehandler.BlockCutterRecipeHandler IC2 IC2:blockMachine3:2 IC2 TRUE 65 5
168 ic2.neiIntegration.core.recipehandler.CentrifugeRecipeHandler IC2 IC2:blockMachine2:3 IC2 TRUE 65 5
169 ic2.neiIntegration.core.recipehandler.CompressorRecipeHandler IC2 IC2:blockMachine:5 IC2 TRUE 65 5
170 ic2.neiIntegration.core.recipehandler.ExtractorRecipeHandler IC2 IC2:blockMachine:4 IC2 TRUE 65 5
171 ic2.neiIntegration.core.recipehandler.FluidCannerRecipeHandler IC2 IC2:blockMachine:6 IC2 TRUE 65 5
172 ic2.neiIntegration.core.recipehandler.LatheRecipeHandler IC2 IC2:blockMachine3:8 IC2 TRUE 65 5
173 ic2.neiIntegration.core.recipehandler.MaceratorRecipeHandler IC2 IC2:blockMachine:3 IC2 TRUE 65 5
174 ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerCutting IC2 IC2:blockMachine2:4 IC2 TRUE 55 6
175 ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerExtruding IC2 IC2:blockMachine2:4 IC2 TRUE 55 6
176 ic2.neiIntegration.core.recipehandler.MetalFormerRecipeHandlerRolling IC2 IC2:blockMachine2:4 IC2 TRUE 55 6
177 ic2.neiIntegration.core.recipehandler.OreWashingRecipeHandler IC2 IC2:blockMachine2:5 IC2 TRUE
178 ic2.neiIntegration.core.recipehandler.ScrapboxRecipeHandler IC2 IC2:itemScrapbox IC2 TRUE 50 6
179 ic2.neiIntegration.core.recipehandler.SolidCannerRecipeHandler IC2 IC2:blockMachine2:9 IC2 TRUE
180 speiger.src.crops.prediction.NEIPlugin IC2CropsNEI IC2:blockCrop Ic2Nei TRUE 135 2 Not actual recipes, just info
181 tonius.neiintegration.mods.mcforge.RecipeHandlerFluidRegistry Minecraft minecraft:water minecraft FALSE
182 tonius.neiintegration.mods.mcforge.RecipeHandlerOreDictionary Minecraft minecraft:iron_ore minecraft FALSE
183 gt.recipe.alloyblastsmelter GT++ gregtech:gt.blockmachines:810 miscutils TRUE 6 135 166 2 ABS
184 gt.recipe.rocketenginefuel GT++ gregtech:gt.blockmachines:793 miscutils TRUE 6 135 166 2 Basic (EV) rocket fuel gen
185 gt.recipe.cyclotron GT++ gregtech:gt.blockmachines:828 miscutils TRUE 6 135 166 2 Cyclotron
186 gt.recipe.chemicaldehydrator GT++ gregtech:gt.blockmachines:911 miscutils TRUE 6 135 166 2 Dehydrator
187 gt.recipe.slowfusionreactor GT++ gregtech:gt.blockmachines:31015 miscutils TRUE 6 135 166 2 gt.blockmachines.gtplusplus.fusion.single
188 gt.recipe.RTGgenerators GT++ gregtech:gt.blockmachines:869 miscutils TRUE 6 135 166 2 GT++ version of the RTG
189 gt.recipe.cokeoven GT++ gregtech:gt.blockmachines:791 miscutils TRUE 6 135 166 2 ICO
190 gt.recipe.semifluidgeneratorfuels GT++ gregtech:gt.blockmachines:837 miscutils TRUE 6 135 166 2 Semifluid gen
191 gt.recipe.fishpond GT++ gregtech:gt.blockmachines:829 miscutils TRUE 6 135 166 2 Zhuhai
192 gt.recipe.advanced.mixer GT++ gregtech:gt.blockmachines:811 miscutils TRUE 6 135 166 2
193 gt.recipe.cryogenicfreezer GT++ gregtech:gt.blockmachines:910 miscutils TRUE 6 135 166 2
194 gt.recipe.fissionfuel GT++ gregtech:gt.blockmachines:835 miscutils TRUE 6 135 166 2
195 gt.recipe.geothermalfuel GT++ gregtech:gt.blockmachines:830 miscutils TRUE 6 135 166 2
196 gt.recipe.lftr GT++ gregtech:gt.blockmachines:751 miscutils TRUE 6 135 166 2
197 gt.recipe.lftr.2 GT++ gregtech:gt.blockmachines:751 miscutils TRUE 6 135 166 2
198 gt.recipe.matterfab2 GT++ gregtech:gt.blockmachines:799 miscutils TRUE 6 135 166 2
199 gt.recipe.multicentrifuge GT++ gregtech:gt.blockmachines:790 miscutils TRUE 6 135 166 2
200 gt.recipe.multielectro GT++ gregtech:gt.blockmachines:796 miscutils TRUE 6 135 166 2
201 gt.recipe.simplewasher GT++ gregtech:gt.blockmachines:767 miscutils TRUE 6 135 166 2
202 gt.recipe.vacfurnace GT++ gregtech:gt.blockmachines:995 miscutils TRUE 6 135 166 2
203 gtPlusPlus.nei.DecayableRecipeHandler GT++ miscutils:dustRadium226 miscutils TRUE 75 4
204 gtPlusPlus.nei.GT_NEI_FlotationCell GT++ gregtech:gt.blockmachines:31028 miscutils TRUE 120 2
205 gtPlusPlus.nei.GT_NEI_FluidReactor GT++ gregtech:gt.blockmachines:998 miscutils TRUE 120 2
206 gtPlusPlus.nei.GT_NEI_MillingMachine GT++ gregtech:gt.blockmachines:31027 miscutils TRUE 120 2
207 li.cil.oc.integration.nei.CallbackDocHandler OpenComputers OpenComputers:item:98 OpenComputers TRUE 120 2
208 li.cil.oc.integration.nei.ManualUsageHandler OpenComputers OpenComputers:item:98 OpenComputers TRUE 120 2
209 tonius.neiintegration.mods.harvestcraft.RecipeHandlerApiary Pam's Harvestcraft harvestcraft:apiary harvestcraft TRUE 70 5 There's only 1 though
210 tonius.neiintegration.mods.harvestcraft.RecipeHandlerChurn Pam's Harvestcraft harvestcraft:churn harvestcraft TRUE 65 5 Same as above
211 tonius.neiintegration.mods.harvestcraft.RecipeHandlerOven Pam's Harvestcraft harvestcraft:oven harvestcraft TRUE 65 5
212 tonius.neiintegration.mods.harvestcraft.RecipeHandlerPresser Pam's Harvestcraft harvestcraft:presser harvestcraft TRUE 65 5
213 tonius.neiintegration.mods.harvestcraft.RecipeHandlerQuern Pam's Harvestcraft harvestcraft:quern harvestcraft TRUE 65 5
214 gcewing.projectblue.nei.NEIRecipeHandler ProjectBlue ProjectBlue:sprayCan ProjectBlue TRUE 65 5
215 mrtjp.projectred.core.libmc.recipe.PRShapedRecipeHandler ProjectRed ProjRed|Transmission:projectred.transmission.wire:7 ProjRed|Transmission TRUE
216 mrtjp.projectred.core.libmc.recipe.PRShapelessRecipeHandler ProjectRed ProjRed|Transmission:projectred.transmission.wire:7 ProjRed|Transmission TRUE
217 tonius.neiintegration.mods.railcraft.RecipeHandlerBlastFurnace Railcraft Railcraft:machine.alpha:12 Railcraft TRUE
218 tonius.neiintegration.mods.railcraft.RecipeHandlerCokeOven Railcraft Railcraft:machine.alpha:7 Railcraft TRUE 65 5
219 tonius.neiintegration.mods.railcraft.RecipeHandlerRockCrusher Railcraft Railcraft:machine.alpha:15 Railcraft TRUE
220 tonius.neiintegration.mods.railcraft.RecipeHandlerRollingMachineShaped Railcraft Railcraft:machine.alpha:8 Railcraft TRUE 65 5
221 tonius.neiintegration.mods.railcraft.RecipeHandlerRollingMachineShapeless Railcraft Railcraft:machine.alpha:8 Railcraft TRUE
222 lumien.randomthings.Handler.ModCompability.NEI.ImbuingStationRecipeHandler RandomThings RandomThings:imbuingStation RandomThings TRUE 120 2
223 com.github.technus.tectech.nei.TT_NEI_ResearchHandler TecTech gregtech:gt.blockmachines:15331 tectech TRUE 6 140 2
224 com.github.technus.tectech.nei.TT_NEI_ScannerHandler TecTech tectech:item.em.definitionScanStorage tectech TRUE
225 com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.ArcaneShapedRecipeHandler Thaumcraft Thaumcraft:blockTable:15 Thaumcraft TRUE 140 2
226 com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.ArcaneShapelessRecipeHandler Thaumcraft Thaumcraft:blockTable:15 Thaumcraft TRUE 140 2
227 com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.CrucibleRecipeHandler Thaumcraft Thaumcraft:blockMetalDevice Thaumcraft TRUE 140 2 Using R on an item you get from the crucible basically never works
228 com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.InfusionRecipeHandler Thaumcraft Thaumcraft:blockStoneDevice:2 Thaumcraft TRUE 140 2
229 ru.timeconqueror.tcneiadditions.nei.arcaneworkbench.ArcaneCraftingShapedHandler Thaumcraft Thaumcraft:blockTable:15 Thaumcraft TRUE 140 2
230 ru.timeconqueror.tcneiadditions.nei.AspectCombinationHandler Thaumcraft Thaumcraft:ItemResearchNotes Thaumcraft TRUE 130 2 In sets of 5. Each one is ~30 height
231 ru.timeconqueror.tcneiadditions.nei.AspectFromItemStackHandler Thaumcraft Thaumcraft:ItemResearchNotes Thaumcraft TRUE 140 2
232 tconstruct.plugins.nei.RecipeHandlerAlloying Tinker's Construct TConstruct:Smeltery TConstruct TRUE 65 5
233 tconstruct.plugins.nei.RecipeHandlerCastingBasin Tinker's Construct TConstruct:SearedBlock:2 TConstruct TRUE 65 5
234 tconstruct.plugins.nei.RecipeHandlerCastingTable Tinker's Construct TConstruct:SearedBlock TConstruct TRUE 65 5
235 tconstruct.plugins.nei.RecipeHandlerDryingRack Tinker's Construct TConstruct:Armor.DryingRack TConstruct TRUE 55 5
236 tconstruct.plugins.nei.RecipeHandlerMelting Tinker's Construct TConstruct:LavaTank:2 TConstruct TRUE 65 5
237 tconstruct.plugins.nei.RecipeHandlerToolMaterials Tinker's Construct TConstruct:ToolStationBlock TConstruct TRUE 110 3 Longer if more modifiers, I went through the whole list
238 net.p455w0rd.wirelesscraftingterminal.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler WirelessCraftingTerminal ae2wct:wirelessCraftingTerminal ae2wct TRUE
239 alkalus.main.nei.NEI_Handler_Cauldron witchery witchery:cauldron WitcheryExtras TRUE 65 5
240 alkalus.main.nei.NEI_Handler_Distillery witchery witchery:distilleryidle WitcheryExtras TRUE 140 2
241 alkalus.main.nei.NEI_Handler_Kettle witchery witchery:kettle WitcheryExtras TRUE 65 5
242 alkalus.main.nei.NEI_Handler_Oven witchery witchery:witchesovenidle WitcheryExtras TRUE Not working at all now
243 alkalus.main.nei.NEI_Handler_SpinningWheel witchery witchery:spinningwheel WitcheryExtras TRUE 65 5
244 com.emoniph.witchery.integration.NEICauldronRecipeHandler witchery witchery:cauldron witchery TRUE 65 5 Replaced by WE presumably
245 com.emoniph.witchery.integration.NEIDistilleryRecipeHandler witchery witchery:distilleryidle witchery TRUE 140 2 Replaced by WE presumably
246 com.emoniph.witchery.integration.NEIKettleRecipeHandler witchery witchery:kettle witchery TRUE 65 5 Replaced by WE presumably
247 com.emoniph.witchery.integration.NEISpinningWheelRecipeHandler witchery witchery:spinningwheel witchery TRUE Replaced by WE presumably
248 com.emoniph.witchery.integration.NEIWitchesOvenRecipeHandler witchery witchery:witchesovenidle witchery TRUE 65 5 Replaced by WE presumably
249 witchinggadgets.client.nei.NEIInfernalBlastfurnaceHandler WitchingGadgets WitchingGadgets:WG_StoneDevice:2 WitchingGadgets TRUE 65 5
250 witchinggadgets.client.nei.NEISpinningWheelHandler WitchingGadgets WitchingGadgets:WG_WoodenDevice WitchingGadgets TRUE 110 3
251 gt.recipe.anvil Gregtech 6 gregtech:gt.multitileentity:32031 gregapi_post TRUE 15 145 166 2
252 gt.recipe.anvil.bend.big Gregtech 6 gregtech:gt.multitileentity:32031 gregapi_post TRUE 15 145 166 2
253 gt.recipe.anvil.bend.small Gregtech 6 gregtech:gt.multitileentity:32031 gregapi_post TRUE 15 145 166 2
254 gt.recipe.aquaticfarm Gregtech 6 gregtech:gt.multitileentity:17131 gregapi_post TRUE 15 145 166 2
255 gt.recipe.assembler Gregtech 6 gregtech:gt.multitileentity:20621 gregapi_post TRUE 15 145 166 2
256 gt.recipe.autoclave Gregtech 6 gregtech:gt.multitileentity:22004 gregapi_post TRUE 15 145 166 2
257 gt.recipe.bath Gregtech 6 gregtech:gt.multitileentity:22002 gregapi_post TRUE 15 145 166 2
258 gt.recipe.bedrockorelist Gregtech 6 gregtech:gt.multitileentity:17999 gregapi_post TRUE 15 145 166 2
259 gt.recipe.biolab Gregtech 6 gregtech:gt.multitileentity:17127 gregapi_post TRUE 15 145 166 2
260 gt.recipe.boxinator Gregtech 6 gregtech:gt.multitileentity:20581 gregapi_post TRUE 15 145 166 2
261 gt.recipe.bumblelyzer Gregtech 6 gregtech:gt.multitileentity:20541 gregapi_post TRUE 15 145 166 2
262 gt.recipe.bumblequeen Gregtech 6 gregtech:gt.multiitem.bumblebee:1 {"gt.bumble": {}} gregapi_post TRUE 15 145 166 2
263 gt.recipe.burnmixer Gregtech 6 gregtech:gt.multitileentity:20521 gregapi_post TRUE 15 145 166 2
264 gt.recipe.byproductlist Gregtech 6 minecraft:diamond_ore gregapi_post TRUE 15 145 166 2
265 gt.recipe.canner Gregtech 6 gregtech:gt.multitileentity:20161 gregapi_post TRUE 15 145 166 2
266 gt.recipe.catalyticcracking Gregtech 6 gregtech:gt.multitileentity:20481 gregapi_post TRUE 15 145 166 2
267 gt.recipe.centrifuge Gregtech 6 gregtech:gt.multitileentity:20081 gregapi_post TRUE 15 145 166 2
268 gt.recipe.clustermill Gregtech 6 gregtech:gt.multitileentity:20141 gregapi_post TRUE 15 145 166 2
269 gt.recipe.coagulator Gregtech 6 gregtech:gt.multitileentity:22000 gregapi_post TRUE 15 145 166 2
270 gt.recipe.cokeoven Gregtech 6 gregtech:gt.multitileentity:17000 gregapi_post TRUE 15 145 166 2
271 gt.recipe.compressor Gregtech 6 gregtech:gt.multitileentity:20101 gregapi_post TRUE 15 145 166 2
272 gt.recipe.crackingtower Gregtech 6 gregtech:gt.multitileentity:17115 gregapi_post TRUE 15 145 166 2
273 gt.recipe.cruciblealloying Gregtech 6 gregtech:gt.multitileentity:1005 gregapi_post TRUE 15 145 166 2
274 gt.recipe.cruciblesmelting Gregtech 6 gregtech:gt.multitileentity:1005 gregapi_post TRUE 15 145 166 2
275 gt.recipe.crusher Gregtech 6 gregtech:gt.multitileentity:20021 gregapi_post TRUE 15 145 166 2
276 gt.recipe.cryodistillationtower Gregtech 6 gregtech:gt.multitileentity:17111 gregapi_post TRUE 15 145 166 2
277 gt.recipe.cryomixer Gregtech 6 gregtech:gt.multitileentity:20571 gregapi_post TRUE 15 145 166 2
278 gt.recipe.crystallisationcrucible Gregtech 6 gregtech:gt.multitileentity:20251 gregapi_post TRUE 15 145 166 2
279 gt.recipe.cutter Gregtech 6 gregtech:gt.multitileentity:20061 gregapi_post TRUE 15 145 166 2
280 gt.recipe.debarker Gregtech 6 gregtech:gt.multitileentity:20551 gregapi_post TRUE 15 145 166 2
281 gt.recipe.distillationtower Gregtech 6 gregtech:gt.multitileentity:20191 gregapi_post TRUE 15 145 166 2
282 gt.recipe.distillery Gregtech 6 gregtech:gt.multitileentity:20191 gregapi_post TRUE 15 145 166 2
283 gt.recipe.drying Gregtech 6 gregtech:gt.multitileentity:20311 gregapi_post TRUE 15 145 166 2
284 gt.recipe.electrolyzer Gregtech 6 gregtech:gt.multitileentity:20091 gregapi_post TRUE 15 145 166 2
285 gt.recipe.extruder Gregtech 6 gregtech:gt.multitileentity:20202 gregapi_post TRUE 15 145 166 2
286 gt.recipe.fermenter Gregtech 6 gregtech:gt.multitileentity:22003 gregapi_post TRUE 15 145 166 2
287 gt.recipe.fluidsolidifier Gregtech 6 gregtech:gt.multitileentity:20611 gregapi_post TRUE 15 145 166 2
288 gt.recipe.freezer Gregtech 6 gregtech:gt.multitileentity:20561 gregapi_post TRUE 15 145 166 2
289 gt.recipe.fuels.burn Gregtech 6 gregtech:gt.multitileentity:1109 gregapi_post TRUE 15 145 166 2
290 gt.recipe.fuels.engine Gregtech 6 gregtech:gt.multitileentity:9147 gregapi_post TRUE 15 145 166 2
291 gt.recipe.fuels.fluidbed Gregtech 6 gregtech:gt.multitileentity:9009 gregapi_post TRUE 15 145 166 2
292 gt.recipe.fuels.gas Gregtech 6 gregtech:gt.multitileentity:1609 gregapi_post TRUE 15 145 166 2
293 gt.recipe.fuels.plasma Gregtech 6 gregtech:gt.multitileentity:17251 gregapi_post TRUE 15 145 166 2
294 gt.recipe.fuels.turbine Gregtech 6 gregtech:gt.multitileentity:17231 gregapi_post TRUE 15 145 166 2
295 gt.recipe.fusionreactor Gregtech 6 gregtech:gt.multitileentity:17198 gregapi_post TRUE 15 145 166 2
296 gt.recipe.generifier Gregtech 6 gregtech:gt.multitileentity:22001 gregapi_post TRUE 15 145 166 2
297 gt.recipe.heatmixer Gregtech 6 gregtech:gt.multitileentity:20506 gregapi_post TRUE 15 145 166 2
298 gt.recipe.implosioncompressor Gregtech 6 gregtech:gt.multitileentity:17110 gregapi_post TRUE 15 145 166 2
299 gt.recipe.incubator Gregtech 6 gregtech:gt.multitileentity:22005 gregapi_post TRUE 15 145 166 2
300 gt.recipe.injector Gregtech 6 gregtech:gt.multitileentity:20261 gregapi_post TRUE 15 145 166 2
301 gt.recipe.ionizer Gregtech 6 gregtech:gt.multitileentity:17315 gregapi_post TRUE 15 145 166 2
302 gt.recipe.juicer Gregtech 6 gregtech:gt.multitileentity:32722 gregapi_post TRUE 15 145 166 2
303 gt.recipe.laminator Gregtech 6 gregtech:gt.multitileentity:20391 gregapi_post TRUE 15 145 166 2
304 gt.recipe.lasercutter Gregtech 6 gregtech:gt.multitileentity:20631 gregapi_post TRUE 15 145 166 2
305 gt.recipe.laserengraver Gregtech 6 gregtech:gt.multitileentity:20321 gregapi_post TRUE 15 145 166 2
306 gt.recipe.lathe Gregtech 6 gregtech:gt.multitileentity:20041 gregapi_post TRUE 15 145 166 2
307 gt.recipe.lightning Gregtech 6 gregtech:gt.multitileentity:20501 gregapi_post TRUE 15 145 166 2
308 gt.recipe.loom Gregtech 6 gregtech:gt.multitileentity:20211 gregapi_post TRUE 15 145 166 2
309 gt.recipe.magneticseparator Gregtech 6 gregtech:gt.multitileentity:20301 gregapi_post TRUE 15 145 166 2
310 gt.recipe.maskaligner Gregtech 6 gregtech:gt.multitileentity:17122 gregapi_post TRUE 15 145 166 2
311 gt.recipe.massfab Gregtech 6 gregtech:gt.multitileentity:20411 gregapi_post TRUE 15 145 166 2
312 gt.recipe.mixer Gregtech 6 gregtech:gt.multitileentity:20181 gregapi_post TRUE 15 145 166 2
313 gt.recipe.mortar Gregtech 6 gregtech:gt.multitileentity:32735 gregapi_post TRUE 15 145 166 2
314 gt.recipe.nanofab Gregtech 6 gregtech:gt.multitileentity:20441 gregapi_post TRUE 15 145 166 2
315 gt.recipe.oilcleaner Gregtech 6 gregtech:gt.multitileentity:17116 gregapi_post TRUE 15 145 166 2
316 gt.recipe.particlecollider Gregtech 6 gregtech:gt.multitileentity:17200 gregapi_post TRUE 15 145 166 2
317 gt.recipe.plantalyzer Gregtech 6 gregtech:gt.multitileentity:20531 gregapi_post TRUE 15 145 166 2
318 gt.recipe.polarizer Gregtech 6 gregtech:gt.multitileentity:20221 gregapi_post TRUE 15 145 166 2
319 gt.recipe.press Gregtech 6 gregtech:gt.multitileentity:20231 gregapi_post TRUE 15 145 166 2
320 gt.recipe.printer Gregtech 6 gregtech:gt.multitileentity:20271 gregapi_post TRUE 15 145 166 2
321 gt.recipe.replicator Gregtech 6 gregtech:gt.multitileentity:20431 gregapi_post TRUE 15 145 166 2
322 gt.recipe.roaster Gregtech 6 gregtech:gt.multitileentity:20171 gregapi_post TRUE 15 145 166 2
323 gt.recipe.rollbender Gregtech 6 gregtech:gt.multitileentity:20121 gregapi_post TRUE 15 145 166 2
324 gt.recipe.rollformer Gregtech 6 gregtech:gt.multitileentity:20131 gregapi_post TRUE 15 145 166 2
325 gt.recipe.rollingmill Gregtech 6 gregtech:gt.multitileentity:20111 gregapi_post TRUE 15 145 166 2
326 gt.recipe.scannermolecular Gregtech 6 gregtech:gt.multitileentity:20423 gregapi_post TRUE 15 145 166 2
327 gt.recipe.scannervisuals Gregtech 6 gregtech:gt.multitileentity:20281 gregapi_post TRUE 15 145 166 2
328 gt.recipe.sharpener Gregtech 6 gregtech:gt.multitileentity:20511 gregapi_post TRUE 15 145 166 2
329 gt.recipe.shredder Gregtech 6 gregtech:gt.multitileentity:20011 gregapi_post TRUE 15 145 166 2
330 gt.recipe.sifter Gregtech 6 gregtech:gt.multitileentity:20051 gregapi_post TRUE 15 145 166 2
331 gt.recipe.slicer Gregtech 6 gregtech:gt.multitileentity:20381 gregapi_post TRUE 15 145 166 2
332 gt.recipe.sluice Gregtech 6 gregtech:gt.multitileentity:20291 gregapi_post TRUE 15 145 166 2
333 gt.recipe.smelter Gregtech 6 gregtech:gt.multitileentity:20241 gregapi_post TRUE 15 145 166 2
334 gt.recipe.squeezer Gregtech 6 gregtech:gt.multitileentity:20071 gregapi_post TRUE 15 145 166 2
335 gt.recipe.steamcracking Gregtech 6 gregtech:gt.multitileentity:20491 gregapi_post TRUE 15 145 166 2
336 gt.recipe.toolhead Gregtech 6 gregtech:gt.meta.toolHeadPickaxe:260 gregapi_post TRUE 15 145 166 2
337 gt.recipe.unboxinator Gregtech 6 gregtech:gt.multitileentity:20591 gregapi_post TRUE 15 145 166 2
338 gt.recipe.welder Gregtech 6 gregtech:gt.multitileentity:20331 gregapi_post TRUE 15 145 166 2
339 gt.recipe.well Gregtech 6 gregtech:gt.multitileentity:17124 gregapi_post TRUE 15 145 166 2
340 gt.recipe.wiremill Gregtech 6 gregtech:gt.multitileentity:20151 gregapi_post TRUE 15 145 166 2
341 smelting Gregtech 6 gregtech:gt.multitileentity:20001 gregapi_post TRUE 15 145 166 2 This uses the same recipe map as the MC furnace
342 gt.recipe.trees Gregtech 6 minecraft:sapling gregapi_post TRUE 15 145 166 2
343 moze_intel.projecte.integration.NEI.NEIWorldTransmuteHandler ProjectE ProjectE:item.pe_philosophers_stone ProjectE TRUE 45 10
344 moze_intel.projecte.integration.NEI.NEIPhiloSmeltingHandler ProjectE ProjectE:item.pe_philosophers_stone ProjectE TRUE 5
345 moze_intel.projecte.integration.NEI.NEIKleinStarHandler ProjectE ProjectE:item.pe_klein_star ProjectE TRUE 5
346 moze_intel.projecte.integration.NEI.NEIAlchBagHandler ProjectE ProjectE:item.pe_alchemical_bag ProjectE TRUE 5
347 de.katzenpapst.amunra.nei.recipehandler.ARCircuitFab Pra's Galacticraft Mod GalacticraftCore:tile.machine2:4 GalacticraftAmunRa TRUE
348 de.katzenpapst.amunra.nei.recipehandler.ARNasaWorkbenchShuttle Pra's Galacticraft Mod GalacticraftAmunRa:item.itemShuttle GalacticraftAmunRa TRUE 130 168 16
349 vazkii.botania.client.integration.nei.recipe.RecipeHandlerFloatingFlowers Botania Botania:miniIsland Botania TRUE 5
350 vazkii.botania.client.integration.nei.recipe.RecipeHandlerPetalApothecary Botania Botania:altar Botania TRUE 102 137 4
351 vazkii.botania.client.integration.nei.recipe.RecipeHandlerRunicAltar Botania Botania:runeAltar Botania TRUE 122 137 4
352 vazkii.botania.client.integration.nei.recipe.RecipeHandlerManaPool Botania Botania:pool Botania TRUE 90 137 4
353 vazkii.botania.client.integration.nei.recipe.RecipeHandlerElvenTrade Botania Botania:alfheimPortal Botania TRUE 90 130 4
354 vazkii.botania.client.integration.nei.recipe.RecipeHandlerBrewery Botania Botania:brewery Botania TRUE 4
355 vazkii.botania.client.integration.nei.recipe.RecipeHandlerPureDaisy Botania Botania:specialFlower {"type": "puredaisy"} Botania TRUE 4
356 vazkii.botania.client.integration.nei.recipe.RecipeHandlerLexicaBotania Botania Botania:lexicon Botania TRUE
357 com.jaquadro.minecraft.storagedrawers.integration.notenoughitems.UpgradeItemRecipeHandler Storage Drawers minecraft:crafting_table StorageDrawers TRUE 65 166 5
358 ieArcFurnace Immersive Engineering ImmersiveEngineering:graphiteElectrode ImmersiveEngineering TRUE 65 166 5
359 NEIArcFurnaceHandlerAlloying Immersive Engineering terrafirmacraftplus:item.Bronze Ingot ImmersiveEngineering TRUE 65 166 5
360 NEIArcFurnaceHandlerOres Immersive Engineering minecraft:iron_ore ImmersiveEngineering TRUE 65 166 5
361 NEIArcFurnaceHandlerSmelting Immersive Engineering terrafirmacraftplus:item.Ore:100 ImmersiveEngineering TRUE 65 166 5
362 NEIArcFurnaceHandlerGlassworking Immersive Engineering minecraft:glass ImmersiveEngineering TRUE 65 166 5
363 NEIArcFurnaceHandlerDecarburization Immersive Engineering terrafirmacraftplus:item.Wrought Iron Ingot ImmersiveEngineering TRUE 65 166 5
364 NEIArcFurnaceHandlerCarburization Immersive Engineering terrafirmacraftplus:item.HC Steel Ingot ImmersiveEngineering TRUE 65 166 5
365 NEIArcFurnaceHandlerHeating Immersive Engineering ImmersiveEngineering TRUE 65 166 5 nei:textures/nei_tabbed_sprites.png 80 0 14 14
366 NEIArcFurnaceHandlerMelting Immersive Engineering terrafirmacraftplus:item.Molten Glass ImmersiveEngineering TRUE 65 166 5
367 NEIArcFurnaceHandlerWelding Immersive Engineering terrafirmacraftplus:item.Bismuth Double Ingot ImmersiveEngineering TRUE 65 166 5
368 NEIArcFurnaceHandlerElectrolysis Immersive Engineering teloaddon:Alumina ImmersiveEngineering TRUE 65 166 5
369 blusunrize.immersiveengineering.client.nei.NEIShaderBagHandler Immersive Engineering ImmersiveEngineering:shaderBag ImmersiveEngineering TRUE 65 166 5
370 blusunrize.immersiveengineering.client.nei.NEIBlueprintHandler Immersive Engineering ImmersiveEngineering:blueprint ImmersiveEngineering TRUE 65 166 5
371 blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:1 ImmersiveEngineering TRUE 71 166 5
372 blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:2 ImmersiveEngineering TRUE 71 166 5
373 blusunrize.immersiveengineering.client.nei.NEISqueezerHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:2 ImmersiveEngineering TRUE 71 166 5
374 blusunrize.immersiveengineering.client.nei.NEIFermenterHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:3 ImmersiveEngineering TRUE 71 166 5
375 blusunrize.immersiveengineering.client.nei.NEIRefineryHandler Immersive Engineering ImmersiveEngineering:metalDevice2:5 ImmersiveEngineering TRUE 65 166 5
376 blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler Immersive Engineering minecraft:glass_bottle ImmersiveEngineering TRUE 65 166 5
377 blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler Immersive Engineering ImmersiveEngineering:mold ImmersiveEngineering TRUE 65 166 5
378 blusunrize.immersiveengineering.client.nei.NEICrusherHandler Immersive Engineering minecraft:hopper ImmersiveEngineering TRUE 71 166 5
379 net.dries007.tfcnei.recipeHandlers.AnvilRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:Anvil terrafirmacraftplus TRUE 10 138 208 2
380 net.dries007.tfcnei.recipeHandlers.QuernRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:item.Quern terrafirmacraftplus TRUE 65 166 5
381 net.dries007.tfcnei.recipeHandlers.KilnRecipeHandler TerraFirmaCraft+ terrafirmacraftplus TRUE 65 166 5 terrafirmacraftneiplugin:textures/gui/pitkiln.png 47 38 14 14
382 net.dries007.tfcnei.recipeHandlers.LoomRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:Loom terrafirmacraftplus TRUE 65 166 5
383 net.dries007.tfcnei.recipeHandlers.KnappingRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:item.LooseRock terrafirmacraftplus TRUE 96 166 3
384 net.dries007.tfcnei.recipeHandlers.ClothingRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:item.Bone Needle Thread terrafirmacraftplus TRUE 65 166 5
385 net.dries007.tfcnei.recipeHandlers.BarrelRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:Barrel terrafirmacraftplus TRUE 65 166 5
386 net.dries007.tfcnei.recipeHandlers.AlloyRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:Crucible terrafirmacraftplus TRUE 65 166 5
387 net.dries007.tfcnei.recipeHandlers.HeatRecipeHandler TerraFirmaCraft+ terrafirmacraftplus:Firepit terrafirmacraftplus TRUE 65 166 5
+44 -7
View File
@@ -1,6 +1,13 @@
nei.load=Load
nei.save=Save
# PC/Linux Control Key
nei.key.ctrl=CTRL
# Mac Command Key
nei.key.ctrl.mac=CMD
nei.bookmark.toggle=Bookmarks
nei.bookmark.toggle.tip=Toggle visibility of the Bookmark Panel
nei.enchant=Enchant
nei.enchant.level=Level
@@ -12,6 +19,11 @@ nei.potion.duration=Duration
nei.potion.level=Level
nei.inventory.options=Options
nei.inventory.options.tip=NEI Config
nei.inventory.options.tip.cheatmode.0=Recipe Mode
nei.inventory.options.tip.cheatmode.1=Utility Mode
nei.inventory.options.tip.cheatmode.2=Cheat Mode
nei.inventory.options.tip.cheatmode.disable=%s-click here to cycle between Recipe, Utility, and Cheat Mode.
nei.inventory.prev=Prev
nei.inventory.next=Next
nei.inventory.item_subsets=Item Subsets
@@ -36,10 +48,15 @@ nei.inventory.dusk.set=Set time to dusk
nei.inventory.midnight.enable=Enable midnight-dawn
nei.inventory.midnight.set=Set time to midnight
nei.inventory.heal=Heal the player
nei.inventory.gamemode.0=Set gamemode to survival
nei.inventory.gamemode.1=Set gamemode to creative
nei.inventory.gamemode.2=Set gamemode to creative+
nei.inventory.gamemode.3=Set gamemode to adventure
nei.inventory.current.gamemode.0=Current gamemode: survival
nei.inventory.current.gamemode.1=Current gamemode: creative
nei.inventory.current.gamemode.2=Current gamemode: creative+
nei.inventory.current.gamemode.3=Current gamemode: adventure
nei.inventory.gamemode.0=Click: Set gamemode to survival
nei.inventory.gamemode.1=Click: Set gamemode to creative
nei.inventory.gamemode.2=Click: Set gamemode to creative+
nei.inventory.gamemode.3=Click: Set gamemode to adventure
nei.chat.gamemode.0=You are now playing survival
nei.chat.gamemode.1=You are now playing creative
@@ -76,6 +93,7 @@ nei.options.keys.gui.next_machine=Next Machine
nei.options.keys.gui.prev_machine=Prev Machine
nei.options.keys.gui.search=Focus Search Bar
nei.options.keys.gui.bookmark=Add Bookmark
nei.options.keys.gui.hide_bookmarks=Toggle Bookmark Panel Visibility
nei.options.keys.world=World
nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay
nei.options.keys.world.moboverlay=Mob Spawn Overlay
@@ -90,6 +108,15 @@ nei.options.keys.world.creative=Gamemode
nei.options.keys.world.creative.tip=Cycle Gamemode
nei.options.inventory=Inventory
nei.options.inventory.bookmarksEnabled=Bookmarks Panel Visibility
nei.options.inventory.bookmarksEnabled.true=Visible
nei.options.inventory.bookmarksEnabled.false=Hidden
nei.options.inventory.jei_style_tabs=JEI Style Tabs
nei.options.inventory.jei_style_tabs.true=Yes
nei.options.inventory.jei_style_tabs.false=No [Weirdo]
nei.options.inventory.creative_tab_style=Creative or JEI tab style
nei.options.inventory.creative_tab_style.true=Creative
nei.options.inventory.creative_tab_style.false=JEI
nei.options.inventory.widgetsenabled.true=NEI Enabled
nei.options.inventory.widgetsenabled.false=NEI Disabled
nei.options.inventory.cheatmode.0=Recipe Mode
@@ -123,6 +150,12 @@ nei.options.inventory.gamemodes.tip=Select the gamemodes to cycle through
nei.options.inventory.gamemodes.creative=Creative
nei.options.inventory.gamemodes.creative+=Creative+
nei.options.inventory.gamemodes.adventure=Adventure
nei.options.inventory.disableMouseScrollTransfer=Disable Mouse Wheel Transfer
nei.options.inventory.disableMouseScrollTransfer.true=True
nei.options.inventory.disableMouseScrollTransfer.false=False
nei.options.inventory.invertMouseScrollTransfer=Invert Mouse Wheel Transfer Direction
nei.options.inventory.invertMouseScrollTransfer.true=True
nei.options.inventory.invertMouseScrollTransfer.false=False
nei.options.command=Commands
nei.options.command.creative=Gamemode
@@ -142,6 +175,9 @@ nei.options.world.highlight_tips.show=Shown
nei.options.world.highlight_tips.sample=Sample
nei.options.tools=Tools
nei.options.tools.handler_load_from_config=Load handlers from Config
nei.options.tools.handler_load_from_config.true=Config
nei.options.tools.handler_load_from_config.false=JAR
nei.options.tools.dump=Data Dumps
nei.options.tools.dump.dump=Dump
nei.options.tools.dump.dumped=%s IDs dumped to %s
@@ -166,9 +202,10 @@ nei.options.tools.dump.itempanel.mode.2=Json
nei.options.tools.dump.itempanel.mode.3=PNG
nei.options.tools.dump.itempanel.icon.dumped=Item Panel icons were dumped to %s
nei.options.tools.dump.itempanel.icon.cancelled=Dump cancelled
nei.options.tools.dump.handlers=NEI Handlers
nei.options.tools.dump.handlers.dumped=handlers were dumped to %s
nei.options.tools.dump.handlers.mode.0=CSV
nei.options.tools.dump.handlers.mode.1=Json
nei.recipe.page=Page %s/%s
nei.recipe.tooltip=Recipes
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

+2
View File
@@ -11,3 +11,5 @@ public net.minecraft.client.gui.GuiScreen field_146292_n #buttonList
public net.minecraft.entity.EntityList field_75624_e #classToIDMapping
public net.minecraft.client.renderer.Tessellator field_78415_z #isDrawing
public net.minecraft.client.multiplayer.PlayerControllerMP field_78779_k #currentGameType
public net.minecraft.nbt.NBTTagCompound field_74784_a #tagMap
public net.minecraft.nbt.NBTTagList field_74747_a #taglist
+11 -10
View File
@@ -1,11 +1,12 @@
package codechicken.nei;
import codechicken.nei.util.NBTJson;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import cpw.mods.fml.common.registry.GameData;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
import org.apache.commons.io.IOUtils;
@@ -71,7 +72,7 @@ public class BookmarkPanel extends ItemPanel {
public void saveBookmarks() {
List<String> strings = new ArrayList<>();
for (ItemStack item:_items) {
strings.add(itemStackToNBT(item, new NBTTagCompound()).toString());
strings.add(NBTJson.toJson(itemStackToNBT(item, new NBTTagCompound())));
}
File file = NEIClientConfig.bookmarkFile;
if(file != null) {
@@ -97,17 +98,18 @@ public class BookmarkPanel extends ItemPanel {
return;
}
_items.clear();
JsonParser parser = new JsonParser();
for (String itemStr: itemStrings) {
try {
NBTTagCompound itemStackNBT = (NBTTagCompound)JsonToNBT.func_150315_a(itemStr);
NBTTagCompound itemStackNBT = (NBTTagCompound) NBTJson.toNbt(parser.parse(itemStr));
ItemStack itemStack = loadFromNBT(itemStackNBT);
if (itemStack != null) {
_items.add(itemStack);
} else {
NEIClientConfig.logger.warn("Failed to load bookmarked ItemStack from json string, the item no longer exists:\n{}", itemStr);
}
} catch (NBTException e) {
NEIClientConfig.logger.error("Failed to load bookmarked ItemStack from json string:\n{}", itemStr, e);
} catch (IllegalArgumentException | JsonSyntaxException e) {
NEIClientConfig.logger.error("Failed to load bookmarked ItemStack from json string:\n{}", itemStr);
}
}
}
@@ -148,7 +150,7 @@ public class BookmarkPanel extends ItemPanel {
@Override
public int getNextX(GuiContainer gui) {
return gui.width - prev.w - 2 - ((gui.xSize + gui.width) /2 + 2);
return gui.width - prev.w - 2 - ((gui.xSize + gui.width) /2 + 2) - 16;
}
@Override
@@ -158,7 +160,7 @@ public class BookmarkPanel extends ItemPanel {
@Override
public int getPageX(GuiContainer gui) {
return gui.guiLeft * 3 / 2 + gui.xSize + 1 - ((gui.xSize + gui.width) /2 + 2);
return gui.guiLeft * 3 / 2 + gui.xSize + 1 - ((gui.xSize + gui.width) / 2 + 2) - 16;
}
public int getHightAdjustment() {
@@ -166,8 +168,7 @@ public class BookmarkPanel extends ItemPanel {
}
public int getWidth(GuiContainer gui) {
return LayoutManager.getLeftSize(gui) - ( (gui.xSize + gui.width) / 2 + 3 );
return LayoutManager.getLeftSize(gui) - ( (gui.xSize + gui.width) / 2 + 3 ) - 16;
}
}
+6 -1
View File
@@ -42,15 +42,20 @@ public abstract class Button extends Widget
if (!contains(mx, my))
return tooltip;
String tip = getButtonTip();
final String tip = getButtonTip();
if (tip != null)
tooltip.add(tip);
addTooltips(tooltip);
return tooltip;
}
public String getButtonTip() {
return null;
}
public void addTooltips(List<String> tooltip) {}
public String getRenderLabel() {
return label;
+7
View File
@@ -2,12 +2,19 @@ package codechicken.nei;
public abstract class ButtonCycled extends Button
{
public ButtonCycled() {}
public ButtonCycled(int num) {
icons = new Image[num];
init();
}
@Override
public Image getRenderIcon()
{
return icons[index];
}
public void init() {}
public int index;
public Image[] icons;
}
+34
View File
@@ -7,6 +7,7 @@ import codechicken.nei.api.API;
import codechicken.nei.api.ItemInfo;
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
@@ -23,13 +24,25 @@ import net.minecraft.entity.item.EntityItem;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.common.MinecraftForge;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
public class ClientHandler
{
private static String[] defaultSerialHandlers = {
"WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler"
};
private static ClientHandler instance;
private ArrayList<EntityItem> SMPmagneticItems = new ArrayList<>();
@@ -114,8 +127,29 @@ public class ClientHandler
}
public static void preInit() {
loadSerialHandlers();
ItemInfo.preInit();
}
public static void loadSerialHandlers() {
File file = NEIClientConfig.serialHandlersFile;
if(!file.exists()) {
try(FileWriter writer = new FileWriter(file)) {
NEIClientConfig.logger.info("Creating default serial handlers list {}", file);
Collection<String> toSave = Loader.isModLoaded("dreamcraft") ? Collections.singletonList("") : Arrays.asList(defaultSerialHandlers);
IOUtils.writeLines(toSave, "\n", writer);
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to save default serial handlers list to file {}", file, e);
}
}
try (FileReader reader = new FileReader(file)) {
NEIClientConfig.logger.info("Loading serial handlers from file {}", file);
NEIClientConfig.serialHandlers = new HashSet<>(IOUtils.readLines(reader));
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e);
}
}
public static void load() {
instance = new ClientHandler();
@@ -0,0 +1,22 @@
package codechicken.nei;
import codechicken.nei.api.ItemFilter;
import net.minecraft.item.ItemStack;
public class DoubleFilteredFilter implements ItemFilter {
private ItemFilter filter;
private ItemList.PatternItemFilter patternFilter;
public DoubleFilteredFilter(ItemFilter filter, String itemFilter) {
this.filter = filter;
this.patternFilter = new ItemList.PatternItemFilter(SearchField.getPattern(itemFilter));
}
@Override
public boolean matches(ItemStack item) {
if(filter.matches(item)) {
return patternFilter.matches(item);
}
return false;
}
}
+7 -10
View File
@@ -18,6 +18,7 @@ import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class ItemList
{
@@ -181,6 +182,7 @@ public class ItemList
}
@Override
@SuppressWarnings("unchecked")
public void execute() {
// System.out.println("Executing NEI Item Loading");
ThreadOperationTimer timer = getTimer(500);
@@ -245,20 +247,15 @@ public class ItemList
@Override
public void execute() {
// System.out.println("Executing NEI Item Filtering");
ArrayList<ItemStack> filtered = new ArrayList<>();
ArrayList<ItemStack> filtered;
ItemFilter filter = getItemListFilter();
try {
ItemList.forkJoinPool.submit(() -> items.parallelStream().forEach(item -> {
if (interrupted()) return;
if(filter.matches(item)) {
synchronized (filtered){
filtered.add(item);
}
}
})).get();
filtered = ItemList.forkJoinPool.submit(() -> items.parallelStream()
.filter(filter::matches)
.collect(Collectors.toCollection(ArrayList::new))).get();
} catch (InterruptedException | ExecutionException e) {
filtered = new ArrayList<>();
e.printStackTrace();
stop();
}
+112 -40
View File
@@ -8,11 +8,14 @@ import codechicken.nei.api.INEIGuiHandler;
import codechicken.nei.api.IRecipeOverlayRenderer;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.api.LayoutStyle;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerDrawHandler;
import codechicken.nei.guihook.IContainerInputHandler;
import codechicken.nei.guihook.IContainerObjectHandler;
import codechicken.nei.guihook.IContainerTooltipHandler;
import codechicken.nei.recipe.GuiRecipeTab;
import cpw.mods.fml.common.Loader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
@@ -22,6 +25,8 @@ import net.minecraft.client.renderer.InventoryEffectRenderer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import java.util.HashMap;
@@ -39,6 +44,7 @@ import static codechicken.nei.NEIClientConfig.getOptionList;
import static codechicken.nei.NEIClientConfig.getSearchExpression;
import static codechicken.nei.NEIClientConfig.hasSMPCounterPart;
import static codechicken.nei.NEIClientConfig.invCreativeMode;
import static codechicken.nei.NEIClientConfig.isBookmarkPanelHidden;
import static codechicken.nei.NEIClientConfig.isEnabled;
import static codechicken.nei.NEIClientConfig.isHidden;
import static codechicken.nei.NEIClientConfig.showIDs;
@@ -50,6 +56,7 @@ import static codechicken.nei.NEIClientUtils.decreaseSlotStack;
import static codechicken.nei.NEIClientUtils.deleteEverything;
import static codechicken.nei.NEIClientUtils.deleteHeldItem;
import static codechicken.nei.NEIClientUtils.deleteItemsOfType;
import static codechicken.nei.NEIClientUtils.getGamemode;
import static codechicken.nei.NEIClientUtils.getGuiContainer;
import static codechicken.nei.NEIClientUtils.getHeldItem;
import static codechicken.nei.NEIClientUtils.getNextGamemode;
@@ -81,8 +88,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
public static SubsetWidget dropDown;
public static TextField searchField;
public static Button options;
public static Button bookmarks;
public static ButtonCycled options;
public static ButtonCycled bookmarksButton;
public static Button more;
public static Button less;
@@ -99,12 +106,9 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
public static HashMap<Integer, LayoutStyle> layoutStyles = new HashMap<>();
public static boolean ftbUtilsLoaded = false;
public static boolean itemsLoaded = false;
public static void load() {
ftbUtilsLoaded = Loader.isModLoaded("FTBU");
API.addLayoutStyle(0, new LayoutStyleMinecraft());
instance = new LayoutManager();
@@ -136,7 +140,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
return gui.width - 3;
}
public static int getLeftSize(GuiContainer gui) {
return getSideWidth(gui) - (ftbUtilsLoaded ? 18 : 0);
return getSideWidth(gui);
}
@Override
@@ -198,6 +202,11 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
toggleBooleanSetting("inventory.hidden");
return true;
}
if (keyID == getKeyBinding("gui.hide_bookmarks")) {
toggleBooleanSetting("inventory.bookmarksEnabled");
return true;
}
if (isEnabled() && !isHidden()) {
for (Widget widget : controlWidgets)
if (inputFocused == null)
@@ -242,13 +251,14 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
widget.draw(mousex, mousey);
} else {
options.draw(mousex, mousey);
bookmarksButton.draw(mousex, mousey);
}
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_DEPTH_TEST);
}
}
@Override
public void postRenderObjects(GuiContainer gui, int mousex, int mousey) {
if (!isHidden() && isEnabled()) {
@@ -293,8 +303,13 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
VisiblityData visiblity = new VisiblityData();
if (isHidden())
visiblity.showNEI = false;
if (isBookmarkPanelHidden())
visiblity.showBookmarkPanel = false;
if (gui.height - gui.ySize <= 40)
visiblity.showSearchSection = false;
if (gui.guiLeft - 4 < 76)
visiblity.showWidgets = false;
@@ -318,28 +333,68 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
dropDown = new SubsetWidget();
searchField = new SearchField("search");
options = new Button("Options")
options = new ButtonCycled(3)
{
@Override
public void init() {
this.icons[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 32, 0, 16, 16).build();
this.icons[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 48, 0, 16, 16).build();
this.icons[2] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 64, 0, 16, 16).build();
}
@Override
public boolean onButtonPress(boolean rightclick) {
if (!rightclick) {
getOptionList().openGui(getGuiContainer(), false);
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LCONTROL || Keyboard.getEventKey() == Keyboard.KEY_RCONTROL)) {
NEIClientConfig.cycleSetting("inventory.cheatmode", 3);
} else {
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT || Keyboard.getEventKey() == Keyboard.KEY_RSHIFT)) {
GuiRecipeTab.loadHandlerInfo();
}
getOptionList().openGui(getGuiContainer(), false);
}
return true;
}
return false;
}
@Override
public void addTooltips(List<String> tooltip) {
tooltip.add(translate("inventory.options.tip"));
String modeColor = "";
final int cheatMode = NEIClientConfig.getCheatMode();
if (cheatMode == 1)
modeColor = EnumChatFormatting.GOLD.toString();
else if (cheatMode == 2)
modeColor = EnumChatFormatting.RED.toString();
String controlKeyLocalization = translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl");
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode." + cheatMode));
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
}
@Override
public String getRenderLabel() {
return translate("inventory.options");
}
};
bookmarks = new Button("Bookmarks")
bookmarksButton = new ButtonCycled(2)
{
@Override
public void init() {
this.icons[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 0, 16, 16).build();
this.icons[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 16, 0, 16, 16).build();
}
@Override
public boolean onButtonPress(boolean rightclick) {
return false;
NEIClientConfig.toggleBooleanSetting("inventory.bookmarksEnabled");
return true;
}
public String getButtonTip() {
return translate("bookmark.toggle.tip");
}
@Override
@@ -424,7 +479,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
GuiDraw.drawTip(mousex + 9, mousey, translate("inventory.delete." + (shiftKey() ? "all" : "one"), GuiContainerManager.itemDisplayNameShort(getHeldItem())));
}
};
gamemode = new ButtonCycled()
gamemode = new ButtonCycled(3)
{
@Override
public boolean onButtonPress(boolean rightclick) {
@@ -434,12 +489,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
}
return false;
}
public String getButtonTip() {
return translate("inventory.gamemode." + getNextGamemode());
public void addTooltips(List<String> tooltip) {
tooltip.add(translate("inventory.current.gamemode." + getGamemode()));
tooltip.add(EnumChatFormatting.GRAY + translate("inventory.gamemode." + getNextGamemode()));
}
};
gamemode.icons = new Image[3];
rain = new Button()
{
@Override
@@ -554,6 +609,11 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
return true;
}
public static void markItemsDirty() {
// If anything has modified data this depends on, we'll need to reload the item list
itemsLoaded = false;
}
@Override
public void load(GuiContainer gui) {
@@ -600,6 +660,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
addWidget(options);
addWidget(bookmarksButton);
if (visiblity.showItemPanel) {
addWidget(itemPanel);
itemPanel.setVisible();
@@ -614,10 +675,9 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
if (visiblity.showBookmarkPanel) {
addWidget(bookmarkPanel);
bookmarkPanel.setVisible();
}
}
if (visiblity.showSearchSection) {
addWidget(dropDown);
addWidget(searchField);
}
@@ -639,6 +699,11 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
if (canPerformAction("delete"))
addWidget(delete);
}
if (!visiblity.showBookmarkPanel) {
// Bookmarks or Subset/dropdown
addWidget(dropDown);
}
}
@@ -723,48 +788,55 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
}
public static void drawIcon(int x, int y, Image image) {
changeTexture("nei:textures/nei_sprites.png");
final boolean isDrawableResource = image instanceof DrawableResource;
if (!isDrawableResource)
changeTexture("nei:textures/nei_sprites.png");
GL11.glColor4f(1, 1, 1, 1);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
drawTexturedModalRect(x, y, image.x, image.y, image.width, image.height);
if(!isDrawableResource)
drawTexturedModalRect(x, y, image.x, image.y, image.width, image.height);
else
((DrawableResource)image).draw(x, y);
GL11.glDisable(GL11.GL_BLEND);
}
public static void drawButtonBackground(int x, int y, int w, int h, boolean edges, int type) {
int wtiles = 0;
int wTiles = 0;
int ew = w;//end width
if (w / 2 > 100) {
wtiles = (w - 200) / 50 + 1;
wTiles = (w - 200) / 50 + 1;
ew = 200;
}
int w1 = ew / 2;
int h1 = h / 2;
int w2 = (ew + 1) / 2;
int h2 = (h + 1) / 2;
final int w1 = ew / 2;
final int h1 = h / 2;
final int w2 = (ew + 1) / 2;
final int h2 = (h + 1) / 2;
int x2 = x + w - w2;
int y2 = y + h - h2;
final int x2 = x + w - w2;
final int y2 = y + h - h2;
int ty = 46 + type * 20;
int te = (edges ? 0 : 1);//tex edges
final int ty = 46 + type * 20;
final int te = (edges ? 0 : 1);//tex edges
int ty1 = ty + te;
int tx1 = te;
int tx3 = 75;
final int ty1 = ty + te;
final int tx1 = te;
final int tx3 = 75;
//halfway the 1 is for odd number adjustment
int ty2 = ty + 20 - h2 - te;
int tx2 = 200 - w2 - te;
final int ty2 = ty + 20 - h2 - te;
final int tx2 = 200 - w2 - te;
changeTexture("textures/gui/widgets.png");
drawTexturedModalRect(x, y, tx1, ty1, w1, h1);//top left
drawTexturedModalRect(x, y2, tx1, ty2, w1, h2);//bottom left
for (int tile = 0; tile < wtiles; tile++) {
int tilex = x + w1 + 50 * tile;
drawTexturedModalRect(tilex, y, tx3, ty1, 50, h1);//top
drawTexturedModalRect(tilex, y2, tx3, ty2, 50, h2);//bottom
for (int tile = 0; tile < wTiles; tile++) {
final int tileX = x + w1 + 50 * tile;
drawTexturedModalRect(tileX, y, tx3, ty1, 50, h1);//top
drawTexturedModalRect(tileX, y2, tx3, ty2, 50, h2);//bottom
}
drawTexturedModalRect(x2, y, tx2, ty1, w2, h1);//top right
+18 -10
View File
@@ -6,6 +6,7 @@ import org.lwjgl.opengl.GL11;
import static codechicken.lib.gui.GuiDraw.drawStringC;
import static codechicken.nei.LayoutManager.bookmarkPanel;
import static codechicken.nei.LayoutManager.bookmarksButton;
import static codechicken.nei.LayoutManager.delete;
import static codechicken.nei.LayoutManager.dropDown;
import static codechicken.nei.LayoutManager.gamemode;
@@ -59,7 +60,6 @@ public class LayoutStyleMinecraft extends LayoutStyle
public void layout(GuiContainer gui, VisiblityData visiblity) {
reset();
//leftSize = ((gui.width - gui.xSize) / 2) - 3;
leftSize = ItemPanels.bookmarkPanel.getWidth(gui);
numButtons = Math.max(leftSize / 18, 1);
@@ -87,6 +87,8 @@ public class LayoutStyleMinecraft extends LayoutStyle
else if (NEIClientUtils.isValidGamemode("adventure"))
gamemode.index = 2;
}
bookmarksButton.index = NEIClientConfig.isBookmarkPanelHidden() ? 0 : 1;
options.index = NEIClientConfig.getCheatMode();
magnet.state = 0x4 | (getMagnetMode() ? 1 : 0);
@@ -124,14 +126,20 @@ public class LayoutStyleMinecraft extends LayoutStyle
options.x = isEnabled() ? 0 : 6;
options.y = isEnabled() ? gui.height - 22 : gui.height - 28;
options.w = 80;
options.w = 22;
options.h = 22;
bookmarksButton.x = 24 + (isEnabled() ? 0 : 6);
bookmarksButton.y = isEnabled() ? gui.height - 22 : gui.height - 28;
bookmarksButton.w = 22;
bookmarksButton.h = 22;
searchField.y = gui.height - searchField.h - 2;
dropDown.x = itemPanel.x - 150;
dropDown.x = Math.min(numButtons, buttonCount) * 20 + 3;
dropDown.h = 20;
dropDown.w = Math.min(itemPanel.prev.x - dropDown.x - 3, 100);
dropDown.w = itemPanel.x - dropDown.x - 3;
searchField.h = 20;
searchField.w = 150;
searchField.x = (gui.width - searchField.w) / 2;
@@ -144,7 +152,7 @@ public class LayoutStyleMinecraft extends LayoutStyle
public void layoutButton(Button button) {
button.x = 2 + (buttonCount % numButtons) * 20;
button.y = 3 + (buttonCount / numButtons) * 18;
button.y = (buttonCount / numButtons) * 18;
button.h = 17;
button.w = button.contentWidth() + 6;
@@ -169,16 +177,16 @@ public class LayoutStyleMinecraft extends LayoutStyle
Image icon = b.getRenderIcon();
if (icon == null) {
int colour = tex == 2 ? 0xffffa0 :
tex == 0 ? 0x601010 : 0xe0e0e0;
int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0;
drawStringC(b.getRenderLabel(), b.x + b.w / 2, b.y + (b.h - 8) / 2, colour);
} else {
GL11.glColor4f(1, 1, 1, 1);
int iconx = b.x + (b.w - icon.width) / 2;
int icony = b.y + (b.h - icon.height) / 2;
LayoutManager.drawIcon(iconx, icony, icon);
final int iconX = b.x + (b.w - icon.width) / 2;
final int iconY = b.y + (b.h - icon.height) / 2;
LayoutManager.drawIcon(iconX, iconY, icon);
}
}
+76 -16
View File
@@ -22,7 +22,9 @@ import codechicken.nei.config.OptionList;
import codechicken.nei.config.OptionOpenGui;
import codechicken.nei.config.OptionTextField;
import codechicken.nei.config.OptionToggleButton;
import codechicken.nei.config.OptionToggleButtonBoubs;
import codechicken.nei.config.OptionUtilities;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.RecipeInfo;
import codechicken.obfuscator.ObfuscationRun;
import net.minecraft.client.Minecraft;
@@ -39,8 +41,7 @@ import java.io.File;
import java.util.HashSet;
import java.util.List;
public class NEIClientConfig
{
public class NEIClientConfig {
private static boolean configLoaded;
private static boolean enabledOverride;
@@ -51,6 +52,12 @@ public class NEIClientConfig
new ConfigFile(new File(configDir, "client.cfg")));
public static ConfigSet world;
public static final File bookmarkFile = new File(configDir, "bookmarks.ini");
public static final File handlerFile = new File(configDir, "handlers.csv");
public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg");
// Set of handlers that need to be run in serial
public static HashSet<String> serialHandlers = new HashSet<>();
public static ItemStack[] creativeInv;
@@ -77,7 +84,7 @@ public class NEIClientConfig
tag.getTag("inventory.widgetsenabled").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.widgetsenabled"));
tag.getTag("inventory.hidden").getBooleanValue(false);
tag.getTag("inventory.cheatmode").getIntValue(2);
tag.getTag("inventory.lockmode").setComment("For those who can't help themselves.\nSet this to a mode and you will be unable to change it ingame").getIntValue(-1);
@@ -113,6 +120,17 @@ public class NEIClientConfig
tag.getTag("inventory.profileRecipes").getBooleanValue(false);
API.addOption(new OptionToggleButton("inventory.profileRecipes", true));
tag.getTag("inventory.disableMouseScrollTransfer").getBooleanValue(false);
API.addOption(new OptionToggleButton("inventory.disableMouseScrollTransfer", true));
tag.getTag("inventory.invertMouseScrollTransfer").getBooleanValue(false);
API.addOption(new OptionToggleButton("inventory.invertMouseScrollTransfer", true) {
@Override
public boolean isEnabled() {
return isMouseScrollTransferEnabled();
}
});
tag.getTag("command.creative").setDefaultValue("/gamemode {0} {1}");
API.addOption(new OptionTextField("command.creative"));
tag.getTag("command.item").setDefaultValue("/give {0} {1} {2} {3} {4}");
@@ -123,7 +141,24 @@ public class NEIClientConfig
API.addOption(new OptionTextField("command.rain"));
tag.getTag("command.heal").setDefaultValue("");
API.addOption(new OptionTextField("command.heal"));
tag.getTag("inventory.bookmarksEnabled").setComment("Enable/disable bookmarks").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.bookmarksEnabled", true));
tag.getTag("inventory.jei_style_tabs").setComment("Enable/disable JEI Style Tabs").getBooleanValue(true);
API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true));
tag.getTag("inventory.creative_tab_style").setComment("Creative or JEI style tabs").getBooleanValue(false);
API.addOption(new OptionToggleButton("inventory.creative_tab_style", true));
tag.getTag("tools.handler_load_from_config").setComment("ADVANCED: Load handlers from config").getBooleanValue(false);
API.addOption(new OptionToggleButton("tools.handler_load_from_config", true) {
@Override
public boolean onClick(int button) {
super.onClick(button);
GuiRecipeTab.loadHandlerInfo();
return true;
}
});
setDefaultKeyBindings();
}
@@ -167,6 +202,7 @@ public class NEIClientConfig
API.addKeyBind("gui.hide", Keyboard.KEY_O);
API.addKeyBind("gui.search", Keyboard.KEY_F);
API.addKeyBind("gui.bookmark", Keyboard.KEY_A);
API.addKeyBind("gui.hide_bookmarks", Keyboard.KEY_B);
API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9);
API.addKeyBind("world.moboverlay", Keyboard.KEY_F7);
API.addKeyBind("world.highlight_tips", Keyboard.KEY_NUMPAD0);
@@ -242,21 +278,25 @@ public class NEIClientConfig
configLoaded = true;
ClassDiscoverer classDiscoverer = new ClassDiscoverer(test -> test.startsWith("NEI") && test.endsWith("Config.class"), IConfigureNEI.class);
new Thread("NEI Plugin Loader") {
@Override
public void run() {
ClassDiscoverer classDiscoverer = new ClassDiscoverer(test -> test.startsWith("NEI") && test.endsWith("Config.class"), IConfigureNEI.class);
classDiscoverer.findClasses();
classDiscoverer.findClasses();
for (Class<?> clazz : classDiscoverer.classes) {
try {
IConfigureNEI config = (IConfigureNEI) clazz.newInstance();
config.loadConfig();
NEIModContainer.plugins.add(config);
logger.debug("Loaded " + clazz.getName());
} catch (Exception e) {
logger.error("Failed to Load " + clazz.getName(), e);
for (Class<?> clazz : classDiscoverer.classes) {
try {
IConfigureNEI config = (IConfigureNEI) clazz.newInstance();
config.loadConfig();
NEIModContainer.plugins.add(config);
logger.debug("Loaded " + clazz.getName());
} catch (Exception e) {
logger.error("Failed to Load " + clazz.getName(), e);
}
}
}
}
}.start();
ItemSorter.loadConfig();
}
@@ -277,10 +317,21 @@ public class NEIClientConfig
public static boolean isHidden() {
return !enabledOverride || getBooleanSetting("inventory.hidden");
}
public static boolean isBookmarkPanelHidden() {
return !getBooleanSetting("inventory.bookmarksEnabled");
}
public static boolean areJEIStyleTabsVisible() {
return getBooleanSetting("inventory.jei_style_tabs");
}
public static boolean useCreativeTabStyle() {
return getBooleanSetting("inventory.creative_tab_style");
}
public static boolean isEnabled() {
return enabledOverride && getBooleanSetting("inventory.widgetsenabled");
}
public static boolean loadHandlersFromJar() {
return !getBooleanSetting("tools.handler_load_from_config");
}
public static void setEnabled(boolean flag) {
getSetting("inventory.widgetsenabled").setBooleanValue(flag);
@@ -343,6 +394,14 @@ public class NEIClientConfig
world.saveNBT();
}
public static boolean isMouseScrollTransferEnabled() {
return !getBooleanSetting("inventory.disableMouseScrollTransfer");
}
public static boolean shouldInvertMouseScrollTransfer() {
return !getBooleanSetting("inventory.invertMouseScrollTransfer");
}
public static boolean getMagnetMode() {
return enabledActions.contains("magnet");
}
@@ -429,4 +488,5 @@ public class NEIClientConfig
if (file.isDirectory() && !saveFileNames.contains(file.getName()))
ObfuscationRun.deleteDir(file, true);
}
}
+4 -1
View File
@@ -224,12 +224,15 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
@Override
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
if (!NEIClientConfig.isEnabled() || GuiInfo.hasCustomSlots(gui))
if (!NEIClientConfig.isEnabled() || GuiInfo.hasCustomSlots(gui) || !NEIClientConfig.isMouseScrollTransferEnabled())
return false;
Point mousePos = getMousePosition();
Slot mouseover = manager.window.getSlotAtPosition(mousePos.x, mousePos.y);
if (mouseover != null && mouseover.getHasStack()) {
if(NEIClientConfig.shouldInvertMouseScrollTransfer()) {
scrolled = -scrolled;
}
if (scrolled > 0)
fastTransferManager.transferItem(manager.window, mouseover.slotNumber);
else
+28
View File
@@ -4,6 +4,10 @@ import codechicken.core.CommonUtils;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.nei.api.IConfigureNEI;
import codechicken.nei.asm.NEICorePlugin;
import codechicken.nei.config.IMCHandler;
import codechicken.nei.recipe.GuiRecipeTab;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.client.FMLFileResourcePack;
@@ -13,13 +17,16 @@ import cpw.mods.fml.common.LoadController;
import cpw.mods.fml.common.MetadataCollection;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLInterModComms;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
import cpw.mods.fml.common.versioning.VersionRange;
import net.minecraft.util.EnumChatFormatting;
import java.io.File;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -91,7 +98,28 @@ public class NEIModContainer extends DummyModContainer
ServerHandler.load();
}
@Subscribe
public void postInit(FMLPostInitializationEvent event) {
if (CommonUtils.isClient())
GuiRecipeTab.loadHandlerInfo();
handleIMCMessages();
}
@SuppressWarnings("unchecked")
private void handleIMCMessages() {
try {
/* Pay no attention to these unholy hacks:
* NEI Apparently doesn't have a registered mod container, so let's use some reflection to simulate what `fetchRuntimeMessages` does
*/
Field modMessagesField = FMLInterModComms.class.getDeclaredField("modMessages");
modMessagesField.setAccessible(true);
IMCHandler.processIMC(ImmutableList.copyOf(((ArrayListMultimap<String, FMLInterModComms.IMCMessage>)modMessagesField.get(FMLInterModComms.class)).removeAll("NotEnoughItems")));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
@Override
public VersionRange acceptableMinecraftVersionRange() {
return VersionParser.parseRange(CodeChickenCorePlugin.mcVersion);
+158 -32
View File
@@ -26,13 +26,20 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Pattern;
import static codechicken.nei.NEIClientUtils.translate;
public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoadedCallback, ISearchProvider
{
public static ReentrantReadWriteLock hiddenItemLock = new ReentrantReadWriteLock();
public static Lock writeLock = hiddenItemLock.writeLock();
public static Lock readLock = hiddenItemLock.readLock();
public static class SubsetState
{
int state = 2;
@@ -210,7 +217,18 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
for(SubsetTag tag : sorted)
tag.cacheState();
}
public void addFiltersWithItem(List<ItemFilter> filters, String itemSearch) {
if(itemSearch == null) {
addFilters(filters);
} else {
if(filter != null)
filters.add(new DoubleFilteredFilter(filter, itemSearch));
for(SubsetTag child : sorted)
child.addFiltersWithItem(filters, itemSearch);
}
}
public void addFilters(List<ItemFilter> filters) {
if(filter != null)
filters.add(filter);
@@ -397,9 +415,20 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
}
public static boolean isHidden(ItemStack item) {
synchronized (hiddenItems) {
return hiddenItems.contains(item);
try {
if(readLock.tryLock(5, TimeUnit.SECONDS)) {
try {
return hiddenItems.contains(item);
} finally {
readLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain read lock in 'isHidden'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
private static void _setHidden(SubsetTag tag, boolean hidden) {
@@ -410,38 +439,80 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
}
private static void _setHidden(ItemStack item, boolean hidden) {
if(hidden)
hiddenItems.add(item);
else
hiddenItems.remove(item);
if (hiddenItemLock.isWriteLockedByCurrentThread()) {
if (hidden)
hiddenItems.add(item);
else
hiddenItems.remove(item);
}
}
public static void showOnly(SubsetTag tag) {
synchronized (hiddenItems) {
for(ItemStack item : ItemList.items)
_setHidden(item, true);
setHidden(tag, false);
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
for (ItemStack item : ItemList.items)
_setHidden(item, true);
setHidden(tag, false);
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain write lock in 'showOnly'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void setHidden(SubsetTag tag, boolean hidden) {
synchronized (hiddenItems) {
_setHidden(tag, hidden);
updateHiddenItems();
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
_setHidden(tag, hidden);
updateHiddenItems();
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain write lock in 'setHidden'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void setHidden(ItemStack item, boolean hidden) {
synchronized (hiddenItems) {
_setHidden(item, hidden);
updateHiddenItems();
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
_setHidden(item, hidden);
updateHiddenItems();
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain write lock in 'setHidden'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void unhideAll() {
synchronized (hiddenItems) {
hiddenItems.clear();
updateHiddenItems();
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
hiddenItems.clear();
updateHiddenItems();
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain write lock in 'unhideAll'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@@ -451,8 +522,19 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
}
public static void loadHidden() {
synchronized (hiddenItems) {
hiddenItems.clear();
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
hiddenItems.clear();
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain write lock in 'loadHidden'");
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
List<ItemStack> itemList = new LinkedList<>();
@@ -466,9 +548,19 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
return;
}
synchronized (hiddenItems) {
for(ItemStack item : itemList)
hiddenItems.add(item);
try {
if(writeLock.tryLock(5, TimeUnit.SECONDS)) {
try {
for (ItemStack item : itemList)
hiddenItems.add(item);
} finally {
writeLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain second write lock in 'loadHidden'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
updateState.restart();
}
@@ -484,9 +576,20 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
private static final RestartableTask prepareDirtyHiddenItems = new RestartableTask("NEI Subset Save Thread")
{
private List<ItemStack> getList() {
synchronized (hiddenItems) {
return hiddenItems.values();
try {
if(readLock.tryLock(5, TimeUnit.SECONDS)) {
try {
return hiddenItems.values();
} finally {
readLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain read lock in 'NEI Subset Save Thread'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
@Override
@@ -706,9 +809,20 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
public ItemFilter getFilter() {
//synchronise access on hiddenItems
return item -> {
synchronized (hiddenItems) {
return !hiddenItems.matches(item);
try {
if(readLock.tryLock(5, TimeUnit.SECONDS)) {
try {
return !hiddenItems.matches(item);
} finally {
readLock.unlock();
}
} else {
NEIClientConfig.logger.error("Unable to obtain read lock in 'getFilter'");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
};
}
@@ -723,20 +837,32 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
return null;
searchText = searchText.substring(1);
String itemSearch = null;
if(searchText.contains("->")) {
String[] split = searchText.split("->");
searchText = split[0];
if(split.length > 1) itemSearch = split[1];
}
AnyMultiItemFilter filter = new AnyMultiItemFilter();
SubsetTag tag = getTag(searchText);
if(tag != null)
tag.addFilters(filter.filters);
if(tag != null) {
// We've got an exact match
tag.addFiltersWithItem(filter.filters, itemSearch);
}
else {
// Try searching for a substring
Pattern p = SearchField.getPattern(searchText);
if(p == null) return null;
List<SubsetTag> matching = new LinkedList<>();
root.search(matching, p);
if(matching.isEmpty()) return null;
for(SubsetTag tag2 : matching)
tag2.addFilters(filter.filters);
for(SubsetTag tag2 : matching) {
tag2.addFiltersWithItem(filter.filters, itemSearch);
}
}
return filter;
}
+5
View File
@@ -121,6 +121,7 @@ public class API
*/
public static void hideItem(ItemStack item) {
ItemInfo.hiddenItems.add(item);
LayoutManager.markItemsDirty();
}
/**
@@ -128,6 +129,7 @@ public class API
*/
public static void setOverrideName(ItemStack item, String name) {
ItemInfo.nameOverrides.put(item, name);
LayoutManager.markItemsDirty();
}
/**
@@ -136,6 +138,7 @@ public class API
*/
public static void addItemListEntry(ItemStack item) {
ItemInfo.itemOverrides.put(item.getItem(), item);
LayoutManager.markItemsDirty();
}
/**
@@ -145,6 +148,7 @@ public class API
if(items == null)
items = Collections.emptyList();
ItemInfo.itemOverrides.replaceValues(item, items);
LayoutManager.markItemsDirty();
}
/**
@@ -273,5 +277,6 @@ public class API
*/
public static void addItemVariant(Item item, ItemStack variant) {
ItemInfo.itemVariants.put(item, variant);
LayoutManager.markItemsDirty();
}
}
+5
View File
@@ -10,6 +10,7 @@ import codechicken.nei.ItemStackSet;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.PopupInputHandler;
import codechicken.nei.config.ArrayDumper;
import codechicken.nei.config.HandlerDumper;
import codechicken.nei.config.ItemPanelDumper;
import codechicken.nei.config.RegistryDumper;
import codechicken.nei.guihook.GuiContainerManager;
@@ -261,8 +262,10 @@ public class ItemInfo
}
});
API.addOption(new ItemPanelDumper("tools.dump.itempanel"));
API.addOption(new HandlerDumper("tools.dump.handlers"));
}
@SuppressWarnings("unchecked")
private static void parseModItems() {
HashMap<String, ItemStackSet> modSubsets = new HashMap<>();
for (Item item : (Iterable<Item>) Item.itemRegistry) {
@@ -328,6 +331,7 @@ public class ItemInfo
API.addSubset("Blocks.MobSpawners", ItemStackSet.of(Blocks.mob_spawner));
}
@SuppressWarnings("unchecked")
private static void searchItems() {
ItemStackSet tools = new ItemStackSet();
ItemStackSet picks = new ItemStackSet();
@@ -450,6 +454,7 @@ public class ItemInfo
addEntityEgg(EntityIronGolem.class, 0xC5C2C1, 0xffe1cc);
}
@SuppressWarnings("unchecked")
private static void addEntityEgg(Class<?> entity, int i, int j) {
int id = (Integer)EntityList.classToIDMapping.get(entity);
EntityList.entityEggs.put(id, new EntityEggInfo(id, i, j));
+11 -8
View File
@@ -15,6 +15,8 @@ import codechicken.lib.asm.ModularASMTransformer.MethodWriter;
import codechicken.lib.asm.ObfMapping;
import cpw.mods.fml.relauncher.FMLLaunchHandler;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
@@ -31,13 +33,7 @@ import static codechicken.lib.asm.InsnComparator.getControlFlowLabels;
import static codechicken.lib.asm.InsnComparator.matches;
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.IRETURN;
import static org.objectweb.asm.Opcodes.*;
public class NEITransformer implements IClassTransformer
{
@@ -259,8 +255,15 @@ public class NEITransformer implements IClassTransformer
public byte[] transform(String name, String tname, byte[] bytes) {
if (bytes == null) return null;
try {
if (FMLLaunchHandler.side().isClient())
if (FMLLaunchHandler.side().isClient()) {
if (name.equals("net.minecraftforge.oredict.OreDictionary")) {
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cr.accept(new OreDictionaryVisitor(ASM5, cw), ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
bytes = cw.toByteArray();
}
bytes = transformSubclasses(name, bytes);
}
bytes = transformer.transform(name, bytes);
} catch (Exception e) {
@@ -0,0 +1,149 @@
package codechicken.nei.asm;
import static org.objectweb.asm.Opcodes.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
/**
* Code without this patch
* <pre>
public class OreDictionary {
public static int getOreID(String name) {
Integer val = nameToId.get(name);
if (val == null)
{
idToName.add(name);
val = idToName.size() - 1; //0 indexed
nameToId.put(name, val);
idToStack.add(new ArrayList<ItemStack>());
idToStackUn.add(new UnmodifiableArrayList(idToStack.get(val)));
}
return val;
}
}
</pre>
Code with this patch
<pre>
public class OreDictionary {
private static final Object emptyEntryCreationLock = new Object();
public static int getOreID(String name) {
Integer val = nameToId.get(name);
if (val == null)
{
synchronized (emptyEntryCreationLock) {
if ((val = nameToId.get(name)) != null)
return val;
idToName.add(name);
val = idToName.size() - 1; //0 indexed
nameToId.put(name, val);
idToStack.add(new ArrayList<ItemStack>());
idToStackUn.add(new UnmodifiableArrayList(idToStack.get(val)));
}
}
return val;
}
}
* </pre>
*/
public class OreDictionaryVisitor extends ClassVisitor {
private static final Logger logger = LogManager.getLogger("OreDictionaryVisitor");
private static class GetOreIDVisitor extends MethodVisitor {
Label jumpEnd;
Label catchStart = new Label();
Label exitStart = new Label();
public GetOreIDVisitor(int api, MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitJumpInsn(int opcode, Label label) {
super.visitJumpInsn(opcode, label);
logger.trace("Adding getOreID MONITERENTER");
jumpEnd = label;
mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/oredict/OreDictionary", "emptyEntryCreationLock", "Ljava/lang/Object;");
mv.visitInsn(MONITORENTER);
mv.visitLabel(catchStart);
mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/oredict/OreDictionary", "nameToId", "Ljava/util/Map;");
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitVarInsn(ASTORE, 1);
mv.visitVarInsn(ALOAD, 1);
mv.visitJumpInsn(IFNONNULL, exitStart);
}
@Override
public void visitLabel(Label label) {
if (label.equals(jumpEnd)) {
logger.trace("Adding getOreID MONITEREXIT");
// normal exit
mv.visitLabel(exitStart);
mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/oredict/OreDictionary", "emptyEntryCreationLock", "Ljava/lang/Object;");
mv.visitInsn(MONITOREXIT);
// not normal
mv.visitJumpInsn(GOTO, jumpEnd);
Label catchBegin = new Label();
mv.visitLabel(catchBegin);
mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/oredict/OreDictionary", "emptyEntryCreationLock", "Ljava/lang/Object;");
mv.visitInsn(MONITOREXIT);
mv.visitInsn(ATHROW);
// try-catch block metadata
mv.visitTryCatchBlock(catchStart, catchBegin, catchBegin, null);
}
super.visitLabel(label);
}
@Override
public void visitEnd() {
super.visitEnd();
}
}
private static class ClassInitializerVisitor extends MethodVisitor{
public ClassInitializerVisitor(int api, MethodVisitor mv) {
super(api, mv);
}
@Override
public void visitCode() {
super.visitCode();
logger.trace("Adding emptyEntryCreationLock initializer");
mv.visitTypeInsn(NEW, "java/lang/Object");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitFieldInsn(PUTSTATIC, "net/minecraftforge/oredict/OreDictionary","emptyEntryCreationLock", "Ljava/lang/Object;");
}
@Override
public void visitEnd() {
super.visitEnd();
}
}
public OreDictionaryVisitor(int api, ClassVisitor cv) {
super(api, cv);
}
@Override
public void visitEnd() {
logger.debug("Adding emptyEntryCreationLock");
cv.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "emptyEntryCreationLock", "Ljava/lang/Object;", null, null);
super.visitEnd();
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals("getOreID") && desc.equals("(Ljava/lang/String;)I")) {
logger.debug("Patching getOreID");
return new GetOreIDVisitor(api, super.visitMethod(access, name, desc, signature, exceptions));
} else if (name.equals("<clinit>")) {
// some classes don't have clinit. not this one.
logger.debug("Patching clinit");
return new ClassInitializerVisitor(api, super.visitMethod(access, name, desc, signature, exceptions));
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
@@ -0,0 +1,111 @@
package codechicken.nei.config;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.GuiUsageRecipe;
import codechicken.nei.recipe.HandlerInfo;
import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.TemplateRecipeHandler;
import codechicken.nei.util.NBTJson;
import com.google.common.base.Objects;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChatComponentTranslation;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedList;
public class HandlerDumper extends DataDumper
{
public HandlerDumper(String name) {
super(name);
}
@Override
public String[] header() {
return new String[]{"Handler Recipe Name", "Handler Class", "Overlay Identifier", "Mod DisplayName", "ItemStack"};
}
@Override
public Iterable<String[]> dump(int mode) {
LinkedList<String[]> list = new LinkedList<>();
for (IRecipeHandler handler : GuiUsageRecipe.usagehandlers) {
final String handlerName = handler.toString().split("@")[0];
final String handlerId = Objects.firstNonNull(handler instanceof TemplateRecipeHandler ? ((TemplateRecipeHandler)handler).getOverlayIdentifier() : null, "null");
HandlerInfo info = GuiRecipeTab.getHandlerInfo(handlerName, handlerId);
list.add(new String[] {
handler.getRecipeName(),
handlerName,
handlerId,
info != null ? info.getModName() : "Unknown",
info != null && info.getItemStack() != null ? info.getItemStack().toString() : "Unknown"
});
}
return list;
}
@Override
public String renderName() {
return translateN(name);
}
@Override
public String getFileExtension() {
switch(getMode()) {
case 0: return ".csv";
case 1: return ".json";
}
return null;
}
@Override
public ChatComponentTranslation dumpMessage(File file) {
return new ChatComponentTranslation(namespaced(name + ".dumped"), "dumps/" + file.getName());
}
@Override
public String modeButtonText() {
return translateN(name + ".mode." + getMode());
}
@Override
public void dumpTo(File file) throws IOException {
if (getMode() == 0)
super.dumpTo(file);
else
dumpJson(file);
}
public void dumpJson(File file) throws IOException {
final String[] header = header();
final FileWriter writer;
try {
writer = new FileWriter(file);
for (String[] list : dump(getMode())) {
NBTTagCompound tag = new NBTTagCompound();
for (int i = 0; i < header.length; i++) {
tag.setString(header[i], list[i]);
}
IOUtils.write(NBTJson.toJson(tag) + "\n", writer);
}
writer.close();
} catch (IOException e) {
NEIClientConfig.logger.error("Filed to save dump handler list to file {}", file, e);
}
}
@Override
public int modeCount() {
return 2;
}
}
@@ -0,0 +1,87 @@
package codechicken.nei.config;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.HandlerInfo;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.event.FMLInterModComms;
import net.minecraft.nbt.NBTTagCompound;
import java.util.List;
public class IMCHandler {
private IMCHandler() {}
public static void processIMC(List<FMLInterModComms.IMCMessage> messages) {
for (FMLInterModComms.IMCMessage message : messages) {
String type = message.key;
if (type == null || type.isEmpty()) continue;
if(type.equals("registerHandlerInfo")) {
if (!message.isNBTMessage()) {
logInvalidMessage(message, "NBT");
continue;
}
final NBTTagCompound tag = message.getNBTValue();
final String handler = tag.getString("handler");
NEIClientConfig.logger.info("Processing registerHandlerInfo `" + handler + "` from " + message.getSender());
final String modName = tag.getString("modName");
final String modId = tag.getString("modId");
final boolean requiresMod = tag.getBoolean("modRequired");
final String excludedModId = tag.hasKey("excludedModId") ? tag.getString("excludedModId") : null;
if(handler.equals("") || modName.equals("") || modId.equals("")) {
NEIClientConfig.logger.warn("Missing relevant information to registerHandlerInfo!");
continue;
}
if (requiresMod && !Loader.isModLoaded(modId)) continue;
if (excludedModId != null && Loader.isModLoaded(excludedModId)) continue;
HandlerInfo info = new HandlerInfo(handler, modName, modId, requiresMod, excludedModId);
final String imageResource = tag.hasKey("imageResource") ? tag.getString("imageResource") : null;
if(imageResource != null && !imageResource.equals("")) {
info.setImage(imageResource, tag.getInteger("imageX"), tag.getInteger("imageY"), tag.getInteger("imageWidth"), tag.getInteger("imageHeight"));
}
if(!info.hasImageOrItem()) {
final String itemName = tag.getString("itemName");
if (itemName != null && !itemName.equals("")) {
info.setItem(itemName, tag.hasKey("nbtInfo") ? tag.getString("nbtInfo") : null);
}
}
final int yShift = tag.hasKey("yShift") ? tag.getInteger("yShift") : 0;
info.setYShift(yShift);
try {
final int imageHeight = tag.hasKey("handlerHeight") ? tag.getInteger("handlerHeight") : HandlerInfo.DEFAULT_HEIGHT;
final int imageWidth = tag.hasKey("handlerWidth") ? tag.getInteger("handlerWidth") : HandlerInfo.DEFAULT_WIDTH;
final int maxRecipesPerPage = tag.hasKey("maxRecipesPerPage") ? tag.getInteger("maxRecipesPerPage") : HandlerInfo.DEFAULT_MAX_PER_PAGE;
info.setHandlerDimensions(imageHeight, imageWidth, maxRecipesPerPage);
} catch (NumberFormatException ignored) {
NEIClientConfig.logger.info("Error setting handler dimensions for " + handler);
}
GuiRecipeTab.handlerMap.remove(handler);
GuiRecipeTab.handlerMap.put(handler, info);
} else if(type.equals("removeHandlerInfo")) {
if (!message.isNBTMessage()) {
logInvalidMessage(message, "NBT");
continue;
}
final NBTTagCompound tag = message.getNBTValue();
final String handler = tag.getString("handler");
NEIClientConfig.logger.info("Processing removeHandlerInfo `" + handler + "` from " + message.getSender());
GuiRecipeTab.handlerMap.remove(handler);
}
}
}
private static void logInvalidMessage(FMLInterModComms.IMCMessage message, String type) {
FMLLog.bigWarning(String.format("Received invalid IMC '%s' from %s. Not a %s Message.", message.key, message.getSender(), type));
}
}
@@ -0,0 +1,52 @@
package codechicken.nei.config;
import codechicken.nei.Image;
import codechicken.nei.LayoutManager;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import org.lwjgl.opengl.GL11;
import java.awt.Rectangle;
public class OptionToggleButtonBoubs extends OptionButton {
private static final DrawableResource coolBoubs = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 48, 16, 22, 22).build();
private static final DrawableResource angryBoubs = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 70, 16, 22, 22).build();
public final boolean prefixed;
public OptionToggleButtonBoubs(String name, boolean prefixed) {
super(name);
this.prefixed = prefixed;
}
public OptionToggleButtonBoubs(String name) {
this(name, false);
}
public boolean state() {
return renderTag().getBooleanValue();
}
@Override
public void drawButton(int mx, int my) {
Rectangle b = buttonSize();
LayoutManager.drawButtonBackground(b.x, b.y, b.width, b.height, true, getButtonTex(mx, my));
final Image image = state() ? coolBoubs : angryBoubs;
LayoutManager.drawIcon(b.x + (b.width/2) - (coolBoubs.getWidth()/2), b.y, image);
}
public String getButtonText() {
return translateN(name + (state() ? ".true" : ".false"));
}
@Override
public String getPrefix() {
return prefixed ? translateN(name) : null;
}
@Override
public boolean onClick(int button) {
getTag().setBooleanValue(!state());
return true;
}
}
@@ -0,0 +1,52 @@
package codechicken.nei.drawable;
import net.minecraft.util.ResourceLocation;
public class DrawableBuilder {
private final ResourceLocation resourceLocation;
private int u;
private int v;
private int width;
private int height;
private int textureWidth = 256;
private int textureHeight = 256;
private int paddingTop = 0;
private int paddingBottom = 0;
private int paddingLeft = 0;
private int paddingRight = 0;
public DrawableBuilder(String resourceLocation, int u, int v, int width, int height) {
this.u = u;
this.v = v;
this.width = width;
this.height = height;
this.resourceLocation = new ResourceLocation(resourceLocation);
}
public DrawableBuilder setTextureSize(int width, int height) {
this.textureWidth = width;
this.textureHeight = height;
return this;
}
public DrawableBuilder addPadding(int paddingTop, int paddingBottom, int paddingLeft, int paddingRight) {
this.paddingTop = paddingTop;
this.paddingBottom = paddingBottom;
this.paddingLeft = paddingLeft;
this.paddingRight = paddingRight;
return this;
}
public DrawableBuilder trim(int trimTop, int trimBottom, int trimLeft, int trimRight) {
this.u += trimLeft;
this.v += trimTop;
this.width -= trimLeft + trimRight;
this.height -= trimTop + trimBottom;
return this;
}
public DrawableResource build() {
return new DrawableResource(resourceLocation, u, v, width, height, paddingTop, paddingBottom, paddingLeft, paddingRight, textureWidth, textureHeight);
}
}
@@ -0,0 +1,56 @@
package codechicken.nei.drawable;
import codechicken.nei.Image;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.util.ResourceLocation;
public class DrawableResource extends Image {
private final ResourceLocation resourceLocation;
private final int textureWidth;
private final int textureHeight;
private final int paddingTop;
private final int paddingBottom;
private final int paddingLeft;
private final int paddingRight;
public DrawableResource(ResourceLocation resourceLocation, int u, int v, int width, int height, int paddingTop, int paddingBottom, int paddingLeft, int paddingRight, int textureWidth, int textureHeight) {
super(u, v, width, height);
this.resourceLocation = resourceLocation;
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
this.paddingTop = paddingTop;
this.paddingBottom = paddingBottom;
this.paddingLeft = paddingLeft;
this.paddingRight = paddingRight;
}
public int getWidth() {
return width + paddingLeft + paddingRight;
}
public int getHeight() {
return height + paddingTop + paddingBottom;
}
public void draw(int xOffset, int yOffset) {
draw(xOffset, yOffset, 0, 0, 0, 0);
}
public void draw(int xOffset, int yOffset, int maskTop, int maskBottom, int maskLeft, int maskRight) {
Minecraft.getMinecraft().getTextureManager().bindTexture(this.resourceLocation);
final int x = xOffset + this.paddingLeft + maskLeft;
final int y = yOffset + this.paddingTop + maskTop;
final int textureX = this.x + maskLeft;
final int textureY = this.y + maskTop;
final int width = this.width - maskRight - maskLeft;
final int height = this.height - maskBottom - maskTop;
// drawModalRectWithCustomSizedTexture
Gui.func_146110_a(x, y, textureX, textureY, width, height, textureWidth, textureHeight);
}
}
@@ -92,19 +92,23 @@ public class BrewingRecipeHandler extends TemplateRecipeHandler
public void loadCraftingRecipes(ItemStack result) {
if (result.getItem() != potionitem) return;
int damage = result.getItemDamage();
for (BrewingRecipe recipe : apotions)
if (recipe.result.item.getItemDamage() == damage)
arecipes.add(new CachedBrewingRecipe(recipe));
// Note: Not safe as written for parallelStream
apotions.stream()
.filter(recipe -> recipe.result.item.getItemDamage() == damage)
.map(CachedBrewingRecipe::new)
.collect(Collectors.toCollection(() -> arecipes));
}
@Override
public void loadUsageRecipes(ItemStack ingredient) {
if (ingredient.getItem() != potionitem && !ingredients.contains(ingredient)) return;
for (BrewingRecipe recipe : apotions)
if (NEIServerUtils.areStacksSameType(recipe.ingredient.item, ingredient) || NEIServerUtils.areStacksSameType(recipe.precursorPotion.item, ingredient))
arecipes.add(new CachedBrewingRecipe(recipe));
// Note: Not safe as written for parallelStream
apotions.stream()
.filter(recipe -> NEIServerUtils.areStacksSameType(recipe.ingredient.item, ingredient) || NEIServerUtils.areStacksSameType(recipe.precursorPotion.item, ingredient))
.map(CachedBrewingRecipe::new)
.collect(Collectors.toCollection(() -> arecipes));
}
@Override
@@ -16,10 +16,19 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class DefaultOverlayHandler implements IOverlayHandler
{
public static class DistributedIngred
{
@SuppressWarnings("rawtypes, unchecked")
public class DefaultOverlayHandler implements IOverlayHandler {
public static Class gtItem;
static {
try {
gtItem = Class.forName("gregtech.api.items.GT_MetaBase_Item");
} catch (ClassNotFoundException ignored) {
gtItem = null;
}
}
public static class DistributedIngred {
public DistributedIngred(ItemStack item)
{
stack = InventoryUtils.copyStack(item, 1);
@@ -32,10 +41,8 @@ public class DefaultOverlayHandler implements IOverlayHandler
public int recipeAmount;
}
public static class IngredientDistribution
{
public IngredientDistribution(DistributedIngred distrib, ItemStack permutation)
{
public static class IngredientDistribution {
public IngredientDistribution(DistributedIngred distrib, ItemStack permutation) {
this.distrib = distrib;
this.permutation = permutation;
}
@@ -45,8 +52,7 @@ public class DefaultOverlayHandler implements IOverlayHandler
public Slot[] slots;
}
public DefaultOverlayHandler(int x, int y)
{
public DefaultOverlayHandler(int x, int y) {
offsetx = x;
offsety = y;
}
@@ -60,8 +66,7 @@ public class DefaultOverlayHandler implements IOverlayHandler
public int offsety;
@Override
public void overlayRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, boolean shift)
{
public void overlayRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, boolean shift) {
List<PositionedStack> ingredients = recipe.getIngredientStacks(recipeIndex);
List<DistributedIngred> ingredStacks = getPermutationIngredients(ingredients);
@@ -98,10 +103,10 @@ public class DefaultOverlayHandler implements IOverlayHandler
}
@SuppressWarnings("unchecked")
private void moveIngredients(GuiContainer gui, List<IngredientDistribution> assignedIngredients, int quantity)
{
for(IngredientDistribution distrib : assignedIngredients)
{
private void moveIngredients(GuiContainer gui, List<IngredientDistribution> assignedIngredients, int quantity) {
for(IngredientDistribution distrib : assignedIngredients) {
if(distrib.slots.length == 0) continue;
ItemStack pstack = distrib.permutation;
int transferCap = quantity*pstack.stackSize;
int transferred = 0;
@@ -111,8 +116,7 @@ public class DefaultOverlayHandler implements IOverlayHandler
int slotTransferred = 0;
int slotTransferCap = pstack.getMaxStackSize();
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots)
{
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots) {
if(!slot.getHasStack() || !canMoveFrom(slot, gui))
continue;
@@ -122,16 +126,13 @@ public class DefaultOverlayHandler implements IOverlayHandler
FastTransferManager.clickSlot(gui, slot.slotNumber);
int amount = Math.min(transferCap-transferred, stack.stackSize);
for(int c = 0; c < amount; c++)
{
for(int c = 0; c < amount; c++) {
FastTransferManager.clickSlot(gui, dest.slotNumber, 1);
transferred++;
slotTransferred++;
if(slotTransferred >= slotTransferCap)
{
if(slotTransferred >= slotTransferCap) {
destSlotIndex++;
if(destSlotIndex == distrib.slots.length)
{
if(destSlotIndex == distrib.slots.length) {
dest = null;
break;
}
@@ -146,11 +147,9 @@ public class DefaultOverlayHandler implements IOverlayHandler
}
}
private int calculateRecipeQuantity(List<IngredientDistribution> assignedIngredients)
{
private int calculateRecipeQuantity(List<IngredientDistribution> assignedIngredients) {
int quantity = Integer.MAX_VALUE;
for(IngredientDistribution distrib : assignedIngredients)
{
for(IngredientDistribution distrib : assignedIngredients) {
DistributedIngred istack = distrib.distrib;
if(istack.numSlots == 0)
return 0;
@@ -165,8 +164,7 @@ public class DefaultOverlayHandler implements IOverlayHandler
return quantity;
}
private Slot[][] assignIngredSlots(GuiContainer gui, List<PositionedStack> ingredients, List<IngredientDistribution> assignedIngredients)
{
private Slot[][] assignIngredSlots(GuiContainer gui, List<PositionedStack> ingredients, List<IngredientDistribution> assignedIngredients) {
Slot[][] recipeSlots = mapIngredSlots(gui, ingredients);//setup the slot map
HashMap<Slot, Integer> distribution = new HashMap<>();
@@ -178,24 +176,19 @@ public class DefaultOverlayHandler implements IOverlayHandler
HashSet<Slot> avaliableSlots = new HashSet<>(distribution.keySet());
HashSet<Integer> remainingIngreds = new HashSet<>();
ArrayList<LinkedList<Slot>> assignedSlots = new ArrayList<>();
for(int i = 0; i < ingredients.size(); i++)
{
for(int i = 0; i < ingredients.size(); i++) {
remainingIngreds.add(i);
assignedSlots.add(new LinkedList<>());
}
while(avaliableSlots.size() > 0 && remainingIngreds.size() > 0)
{
for(Iterator<Integer> iterator = remainingIngreds.iterator(); iterator.hasNext();)
{
while(avaliableSlots.size() > 0 && remainingIngreds.size() > 0) {
for(Iterator<Integer> iterator = remainingIngreds.iterator(); iterator.hasNext();) {
int i = iterator.next();
boolean assigned = false;
DistributedIngred istack = assignedIngredients.get(i).distrib;
for(Slot slot : recipeSlots[i])
{
if(avaliableSlots.contains(slot))
{
for(Slot slot : recipeSlots[i]) {
if(avaliableSlots.contains(slot)) {
avaliableSlots.remove(slot);
if(slot.getHasStack())
continue;
@@ -225,10 +218,9 @@ public class DefaultOverlayHandler implements IOverlayHandler
DistributedIngred biggestIngred = null;
ItemStack permutation = null;
int biggestSize = 0;
for(ItemStack pstack : posstack.items)
{
for(ItemStack pstack : posstack.items) {
for (DistributedIngred istack : ingredStacks) {
if (!canStack(pstack, istack.stack) || istack.invAmount - istack.distributed < pstack.stackSize)
if (!canStack(pstack, istack.stack) || istack.invAmount - istack.distributed < pstack.stackSize || istack.recipeAmount == 0 || pstack.stackSize == 0)
continue;
int relsize = (istack.invAmount - istack.invAmount / istack.recipeAmount * istack.distributed) / pstack.stackSize;
@@ -252,12 +244,9 @@ public class DefaultOverlayHandler implements IOverlayHandler
}
@SuppressWarnings("unchecked")
private void findInventoryQuantities(GuiContainer gui, List<DistributedIngred> ingredStacks)
{
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots)//work out how much we have to go round
{
if(slot.getHasStack() && canMoveFrom(slot, gui))
{
private void findInventoryQuantities(GuiContainer gui, List<DistributedIngred> ingredStacks) {
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots)/*work out how much we have to go round*/ {
if(slot.getHasStack() && canMoveFrom(slot, gui)) {
ItemStack pstack = slot.getStack();
DistributedIngred istack = findIngred(ingredStacks, pstack);
if(istack != null)
@@ -266,13 +255,10 @@ public class DefaultOverlayHandler implements IOverlayHandler
}
}
private List<DistributedIngred> getPermutationIngredients(List<PositionedStack> ingredients)
{
private List<DistributedIngred> getPermutationIngredients(List<PositionedStack> ingredients) {
ArrayList<DistributedIngred> ingredStacks = new ArrayList<>();
for(PositionedStack posstack : ingredients)//work out what we need
{
for(ItemStack pstack : posstack.items)
{
for(PositionedStack posstack : ingredients)/*work out what we need*/ {
for(ItemStack pstack : posstack.items) {
DistributedIngred istack = findIngred(ingredStacks, pstack);
if(istack == null)
ingredStacks.add(istack = new DistributedIngred(pstack));
@@ -290,14 +276,11 @@ public class DefaultOverlayHandler implements IOverlayHandler
public Slot[][] mapIngredSlots(GuiContainer gui, List<PositionedStack> ingredients)
{
Slot[][] recipeSlotList = new Slot[ingredients.size()][];
for(int i = 0; i < ingredients.size(); i++)//identify slots
{
for(int i = 0; i < ingredients.size(); i++)/*identify slots*/ {
LinkedList<Slot> recipeSlots = new LinkedList<>();
PositionedStack pstack = ingredients.get(i);
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots)
{
if(slot.xDisplayPosition == pstack.relx+offsetx && slot.yDisplayPosition == pstack.rely+offsety)
{
for(Slot slot : (List<Slot>)gui.inventorySlots.inventorySlots) {
if(slot.xDisplayPosition == pstack.relx+offsetx && slot.yDisplayPosition == pstack.rely+offsety) {
recipeSlots.add(slot);
break;
}
@@ -307,8 +290,7 @@ public class DefaultOverlayHandler implements IOverlayHandler
return recipeSlotList;
}
public DistributedIngred findIngred(List<DistributedIngred> ingredStacks, ItemStack pstack)
{
public DistributedIngred findIngred(List<DistributedIngred> ingredStacks, ItemStack pstack) {
for(DistributedIngred istack : ingredStacks)
if(canStack(pstack, istack.stack))
return istack;
@@ -318,6 +300,16 @@ public class DefaultOverlayHandler implements IOverlayHandler
protected boolean canStack(ItemStack stack1, ItemStack stack2) {
if (stack1 == null || stack2 == null)
return true;
return stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage() && ItemStack.areItemStackTagsEqual(stack2, stack1);
if(stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage()) {
if (ItemStack.areItemStackTagsEqual(stack2, stack1)) return true;
// GT Items don't have any NBT set for the recipe, so if either of the stacks has a NULL nbt, and the other doesn't, pretend they stack
if (((gtItem != null && gtItem.isInstance(stack1.getItem())) || (stack1.getMaxStackSize() == 1 && stack2.getMaxStackSize() == 1))
&& (stack1.stackTagCompound == null ^ stack2.stackTagCompound == null)
)
return true;
}
return false;
}
}
@@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import static codechicken.nei.NEIClientUtils.translate;
@@ -49,24 +50,32 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler
return NEIClientUtils.translate("recipe.fuel");
}
@SuppressWarnings("unchecked")
private void loadAllSmelting() {
Map<ItemStack, ItemStack> recipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting().getSmeltingList();
for (Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
mfurnace.add(new SmeltingPair(recipe.getKey(), recipe.getValue()));
// Note: Not safe as written for parallelStream
final Map<ItemStack, ItemStack> smeltingRecipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting().getSmeltingList();
smeltingRecipes.entrySet().stream()
.map(recipe -> new SmeltingPair(recipe.getKey(), recipe.getValue()))
.collect(Collectors.toCollection(() -> mfurnace));
}
@Override
public void loadCraftingRecipes(String outputId, Object... results) {
// Note: Not safe as written for parallelStream
if (outputId.equals("fuel") && getClass() == FuelRecipeHandler.class)
for (FuelPair fuel : afuels)
arecipes.add(new CachedFuelRecipe(fuel));
afuels.stream()
.map(CachedFuelRecipe::new)
.collect(Collectors.toCollection(() -> arecipes));
}
public void loadUsageRecipes(ItemStack ingredient) {
for (FuelPair fuel : afuels)
if (fuel.stack.contains(ingredient))
arecipes.add(new CachedFuelRecipe(fuel));
// Note: Not safe as written for parallelStream
afuels.stream()
.filter(fuel -> fuel != null && fuel.stack != null && fuel.stack.contains(ingredient))
.map(CachedFuelRecipe::new)
.collect(Collectors.toCollection(() -> arecipes));
}
public String getOverlayIdentifier() {
@@ -1,26 +1,19 @@
package codechicken.nei.recipe;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import net.minecraft.block.Block;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiFurnace;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.tileentity.TileEntityFurnace;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class FurnaceRecipeHandler extends TemplateRecipeHandler
{
@@ -47,9 +40,8 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
final PositionedStack ingred;
final PositionedStack result;
}
public static class FuelPair
{
public static class FuelPair {
public FuelPair(ItemStack ingred, int burnTime) {
this.stack = new PositionedStack(ingred, 51, 42, false);
this.burnTime = burnTime;
@@ -60,7 +52,7 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
}
public static ArrayList<FuelPair> afuels;
public static HashSet<Block> efuels;
@Override
public void loadTransferRects() {
@@ -80,8 +72,9 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
@Override
public TemplateRecipeHandler newInstance() {
if (afuels == null || afuels.isEmpty())
findFuels();
// Use the non parallel version since we might already be using the forkJoinPool and might have no threads available
// This will ideally have been pre-cached elsewhere and will be a NOOP
findFuelsOnce();
return super.newInstance();
}
@@ -133,27 +126,6 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
drawProgressBar(74, 23, 176, 14, 24, 16, 48, 0);
}
private static Set<Item> excludedFuels() {
Set<Item> efuels = new HashSet<>();
efuels.add(Item.getItemFromBlock(Blocks.brown_mushroom));
efuels.add(Item.getItemFromBlock(Blocks.red_mushroom));
efuels.add(Item.getItemFromBlock(Blocks.standing_sign));
efuels.add(Item.getItemFromBlock(Blocks.wall_sign));
efuels.add(Item.getItemFromBlock(Blocks.wooden_door));
efuels.add(Item.getItemFromBlock(Blocks.trapped_chest));
return efuels;
}
private static void findFuels() {
afuels = new ArrayList<>();
Set<Item> efuels = excludedFuels();
for (ItemStack item : ItemList.items)
if (!efuels.contains(item.getItem())) {
int burnTime = TileEntityFurnace.getItemBurnTime(item);
if (burnTime > 0)
afuels.add(new FuelPair(item.copy(), burnTime));
}
}
@Override
public String getOverlayIdentifier() {
@@ -1,27 +1,46 @@
package codechicken.nei.recipe;
import codechicken.core.TaskProfiler;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.GuiScreen;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
public class GuiCraftingRecipe extends GuiRecipe
{
public static boolean openRecipeGui(String outputId, Object... results) {
Minecraft mc = NEIClientUtils.mc();
GuiContainer prevscreen = mc.currentScreen instanceof GuiContainer ? (GuiContainer) mc.currentScreen : null;
GuiScreen prevscreen = mc.currentScreen;// instanceof GuiContainer ? (GuiContainer) mc.currentScreen : null;
ArrayList<ICraftingHandler> handlers;
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
ArrayList<ICraftingHandler> handlers = new ArrayList<>();
for (ICraftingHandler craftinghandler : craftinghandlers) {
profiler.start(craftinghandler.getRecipeName());
ICraftingHandler handler = craftinghandler.getRecipeHandler(outputId, results);
if (handler.numRecipes() > 0)
handlers.add(handler);
profiler.start("recipe.concurrent.crafting");
// Pre-find the fuels so we're not fighting over it
FuelRecipeHandler.findFuelsOnceParallel();
try {
handlers = serialCraftingHandlers.stream().map(h -> h.getRecipeHandler(outputId, results))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new));
handlers.addAll(ItemList.forkJoinPool.submit(() -> craftinghandlers.parallelStream()
.map(h -> h.getRecipeHandler(outputId, results))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return false;
} finally {
profiler.end();
}
profiler.end();
if (handlers.isEmpty())
return false;
@@ -29,17 +48,21 @@ public class GuiCraftingRecipe extends GuiRecipe
return true;
}
private GuiCraftingRecipe(GuiContainer prevgui, ArrayList<ICraftingHandler> handlers) {
private GuiCraftingRecipe(GuiScreen prevgui, ArrayList<ICraftingHandler> handlers) {
super(prevgui);
currenthandlers = handlers;
}
public static void registerRecipeHandler(ICraftingHandler handler) {
for (ICraftingHandler handler1 : craftinghandlers)
if (handler1.getClass() == handler.getClass())
return;
final Class<? extends ICraftingHandler> handlerClass = handler.getClass();
if(craftinghandlers.stream().anyMatch(h -> h.getClass() == handlerClass) || serialCraftingHandlers.stream().anyMatch(h -> h.getClass() == handlerClass))
return;
craftinghandlers.add(handler);
final String handlerClassStr = handlerClass.getName();
if(NEIClientConfig.serialHandlers.contains(handlerClassStr))
serialCraftingHandlers.add(handler);
else
craftinghandlers.add(handler);
}
public ArrayList<? extends IRecipeHandler> getCurrentRecipeHandlers() {
@@ -49,4 +72,5 @@ public class GuiCraftingRecipe extends GuiRecipe
public ArrayList<ICraftingHandler> currenthandlers;
public static ArrayList<ICraftingHandler> craftinghandlers = new ArrayList<>();
public static ArrayList<ICraftingHandler> serialCraftingHandlers = new ArrayList<>();
}
+316 -106
View File
@@ -1,21 +1,28 @@
package codechicken.nei.recipe;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.render.CCRenderState;
import codechicken.nei.GuiNEIButton;
import codechicken.nei.LayoutManager;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.VisiblityData;
import codechicken.nei.api.IGuiContainerOverlay;
import codechicken.nei.api.INEIGuiHandler;
import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.api.IRecipeOverlayRenderer;
import codechicken.nei.api.TaggedInventoryArea;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerTooltipHandler;
import codechicken.nei.guihook.IGuiClientSide;
import codechicken.nei.guihook.IGuiHandleMouseWheel;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import org.lwjgl.input.Keyboard;
@@ -24,57 +31,145 @@ import org.lwjgl.opengl.GL11;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOverlay, IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler
{
public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOverlay, IGuiClientSide, IGuiHandleMouseWheel, IContainerTooltipHandler, INEIGuiHandler {
// Background image calculations
private static final int BG_TOP_HEIGHT = 6;
private static final int BG_MIDDLE_HEIGHT = 154;
private static final int BG_BOTTOM_HEIGHT = 6;
private static final int BG_TOP_Y = 0;
private static final int BG_MIDDLE_Y = BG_TOP_Y + BG_TOP_HEIGHT;
private static final int BG_BOTTOM_Y = BG_MIDDLE_Y + BG_MIDDLE_HEIGHT;
// Button sizes
private static final int borderPadding = 6;
private static final int buttonWidth = 13;
private static final int buttonHeight = 12;
// Background image
final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT).build();
final DrawableResource bgMiddle = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_MIDDLE_Y, 176, BG_MIDDLE_HEIGHT).build();
final DrawableResource bgBottom = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_BOTTOM_Y, 176, BG_BOTTOM_HEIGHT).build();
public ArrayList<? extends IRecipeHandler> currenthandlers = new ArrayList<>();
public int page;
public int recipetype;
public ContainerRecipe slotcontainer;
public GuiContainer firstGui;
public GuiContainer prevGui;
public GuiScreen prevGui;
public GuiButton nextpage;
public GuiButton prevpage;
public GuiButton overlay1;
public GuiButton overlay2;
private GuiButton nexttype;
private GuiButton prevtype;
private int OVERLAY_BUTTON_ID_START = 4;
private GuiButton[] overlayButtons;
private final Rectangle area = new Rectangle();
private final GuiRecipeTabs recipeTabs;
private IRecipeHandler handler;
private HandlerInfo handlerInfo;
private int yShift = 0;
protected GuiRecipe(GuiContainer prevgui) {
protected GuiRecipe(GuiScreen prevgui) {
super(new ContainerRecipe());
recipeTabs = new GuiRecipeTabs(this);
slotcontainer = (ContainerRecipe) inventorySlots;
this.prevGui = prevgui;
this.firstGui = prevgui;
if(prevgui instanceof GuiContainer)
this.firstGui = (GuiContainer)prevgui;
if (prevgui instanceof IGuiContainerOverlay)
this.firstGui = ((IGuiContainerOverlay) prevgui).getFirstScreen();
}
@Override
@SuppressWarnings("unchecked")
public void initGui() {
xSize = 176;
ySize = Math.min(Math.max(height - 68, 166), 370);
super.initGui();
guiTop = (height - ySize) / 2 + 10;
currenthandlers = getCurrentRecipeHandlers(); // Probably don't comment me out
if(handler == null)
setRecipePage(recipetype);
else
initOverlayButtons();
checkYShift();
final int rightButtonX = guiLeft + xSize - borderPadding - buttonWidth;
final int leftButtonX = guiLeft + borderPadding;
currenthandlers = getCurrentRecipeHandlers();
GuiButton nexttype = new GuiNEIButton(0, width / 2 - 70, (height - ySize) / 2 + 3, 13, 12, "<");
GuiButton prevtype = new GuiNEIButton(1, width / 2 + 57, (height - ySize) / 2 + 3, 13, 12, ">");
nextpage = new GuiNEIButton(2, width / 2 - 70, (height + ySize) / 2 - 18, 13, 12, "<");
prevpage = new GuiNEIButton(3, width / 2 + 57, (height + ySize) / 2 - 18, 13, 12, ">");
overlay1 = new GuiNEIButton(4, width / 2 + 65, (height - ySize) / 2 + 63, 13, 12, "?");
overlay2 = new GuiNEIButton(5, width / 2 + 65, (height - ySize) / 2 + 128, 13, 12, "?");
buttonList.add(nexttype);
buttonList.add(prevtype);
buttonList.add(nextpage);
buttonList.add(prevpage);
buttonList.add(overlay1);
buttonList.add(overlay2);
nexttype = new GuiNEIButton(0, leftButtonX, guiTop + 3, buttonWidth, buttonHeight, "<");
prevtype = new GuiNEIButton(1, rightButtonX, guiTop + 3, buttonWidth, buttonHeight, ">");
nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<");
prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">");
buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage));
if (currenthandlers.size() == 1) {
nexttype.visible = false;
prevtype.visible = false;
}
recipeTabs.initLayout();
refreshPage();
}
@SuppressWarnings("unchecked")
private void initOverlayButtons() {
if (overlayButtons != null) {
buttonList.removeIf(Arrays.asList(overlayButtons)::contains);
}
final int recipesPerPage = getRecipesPerPage();
overlayButtons = new GuiButton[recipesPerPage];
for (int i = 0 ; i < recipesPerPage ; i++) {
overlayButtons[i] = new GuiNEIButton(
OVERLAY_BUTTON_ID_START + i,
(width / 2) + 65,
guiTop + 16 + (handlerInfo.getHeight() * (i+1)) - 2,
buttonWidth,
buttonHeight,
"?");
}
Collections.addAll(buttonList, overlayButtons);
}
private void checkYShift() {
yShift = handlerInfo == null ? 0 : handlerInfo.getYShift();
}
public void setRecipePage(int idx) {
recipetype = idx;
if (recipetype < 0) recipetype = currenthandlers.size() - 1;
else if (recipetype >= currenthandlers.size()) recipetype = 0;
handler = currenthandlers.get(recipetype);
handlerInfo = getHandlerInfo(handler);
page = 0;
recipeTabs.calcPageNumber();
checkYShift();
initOverlayButtons();
}
@Override
public void keyTyped(char c, int i) {
if (i == Keyboard.KEY_ESCAPE) //esc
@@ -85,9 +180,9 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c))
return;
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int recipe = page * recipehandler.recipiesPerPage(); recipe < recipehandler.numRecipes() && recipe < (page + 1) * recipehandler.recipiesPerPage(); recipe++)
if (recipehandler.keyTyped(this, c, i, recipe))
final int recipesPerPage = getRecipesPerPage();
for (int recipe = page * recipesPerPage; recipe < handler.numRecipes() && recipe < (page + 1) * recipesPerPage; recipe++)
if (handler.keyTyped(this, c, i, recipe))
return;
if (i == mc.gameSettings.keyBindInventory.getKeyCode())
@@ -106,61 +201,74 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
}
@Override
protected void mouseClicked(int par1, int par2, int par3) {
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int recipe = page * recipehandler.recipiesPerPage(); recipe < recipehandler.numRecipes() && recipe < (page + 1) * recipehandler.recipiesPerPage(); recipe++)
if (recipehandler.mouseClicked(this, par3, recipe))
protected void mouseClicked(int x, int y, int button) {
final int recipesPerPage = getRecipesPerPage();
for (int recipe = page * recipesPerPage; recipe < handler.numRecipes() && recipe < (page + 1) * recipesPerPage; recipe++)
if (handler.mouseClicked(this, button, recipe))
return;
super.mouseClicked(par1, par2, par3);
if (recipeTabs.mouseClicked(x, y, button))
return;
super.mouseClicked(x, y, button);
}
@Override
protected void actionPerformed(GuiButton guibutton) {
super.actionPerformed(guibutton);
final int recipesPerPage = getRecipesPerPage();
switch (guibutton.id) {
case 0:
prevType();
break;
return;
case 1:
nextType();
break;
return;
case 2:
prevPage();
break;
return;
case 3:
nextPage();
break;
case 4:
overlayRecipe(page * currenthandlers.get(recipetype).recipiesPerPage());
break;
case 5:
overlayRecipe(page * currenthandlers.get(recipetype).recipiesPerPage() + 1);
break;
return;
}
if (overlayButtons != null && guibutton.id >= OVERLAY_BUTTON_ID_START && guibutton.id < OVERLAY_BUTTON_ID_START + overlayButtons.length) {
overlayRecipe(page * recipesPerPage + guibutton.id - OVERLAY_BUTTON_ID_START);
}
}
@Override
public void updateScreen() {
super.updateScreen();
currenthandlers.get(recipetype).onUpdate();
handler.onUpdate();
refreshPage();
}
@Override
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int i = page * recipehandler.recipiesPerPage(); i < recipehandler.numRecipes() && i < (page + 1) * recipehandler.recipiesPerPage(); i++)
currenttip = recipehandler.handleTooltip(this, currenttip, i);
final int recipesPerPage = getRecipesPerPage();
/*
* Several mods try to figure out the relative mouse position for fluid tooltips. This worked fine
* when it was a static 166.. however now that we're scaling it this no longer works. Rather than
* patching the individual mods (so that we can be as compatible as possible), we'll just fake
* the height for their tooltip rendering.
*/
// Begin Hax
final int oldHeight = this.height;
this.height = 166 + handlerInfo.getHeight() + 18 + (guiTop - 44) * 2;
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
currenttip = handler.handleTooltip(this, currenttip, i);
}
recipeTabs.handleTooltip(mousex, mousey, currenttip);
this.height = oldHeight;
// End Hax
return currenttip;
}
@Override
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey, List<String> currenttip) {
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int i = page * recipehandler.recipiesPerPage(); i < recipehandler.numRecipes() && i < (page + 1) * recipehandler.recipiesPerPage(); i++)
currenttip = recipehandler.handleItemTooltip(this, stack, currenttip, i);
final int recipesPerPage = getRecipesPerPage();
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++)
currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
return currenttip;
}
@@ -172,119 +280,185 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
private void nextPage() {
page++;
if (page > (currenthandlers.get(recipetype).numRecipes() - 1) / currenthandlers.get(recipetype).recipiesPerPage())
page = 0;
if (page > (handler.numRecipes() - 1) / getRecipesPerPage()) page = 0;
}
private void prevPage() {
page--;
if (page < 0)
page = (currenthandlers.get(recipetype).numRecipes() - 1) / currenthandlers.get(recipetype).recipiesPerPage();
if (page < 0) page = (handler.numRecipes() - 1) / getRecipesPerPage();
}
private void nextType() {
recipetype++;
if (recipetype >= currenthandlers.size())
recipetype = 0;
page = 0;
setRecipePage(++recipetype);
}
private void prevType() {
recipetype--;
if (recipetype < 0)
recipetype = currenthandlers.size() - 1;
page = 0;
setRecipePage(--recipetype);
}
public HandlerInfo getHandlerInfo(IRecipeHandler handler) {
final String handlerName = handler.toString().split("@")[0];
final String handlerID;
if(handler instanceof TemplateRecipeHandler) {
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
} else {
handlerID = null;
}
HandlerInfo info = GuiRecipeTab.getHandlerInfo(handlerName, handlerID);
if (info == null)
return GuiRecipeTab.DEFAULT_HANDLER_INFO;
return info;
}
private void overlayRecipe(int recipe) {
IRecipeOverlayRenderer renderer = currenthandlers.get(recipetype).getOverlayRenderer(firstGui, recipe);
IOverlayHandler handler = currenthandlers.get(recipetype).getOverlayHandler(firstGui, recipe);
boolean shift = NEIClientUtils.shiftKey();
final IRecipeOverlayRenderer renderer = handler.getOverlayRenderer(firstGui, recipe);
final IOverlayHandler overlayHandler = handler.getOverlayHandler(firstGui, recipe);
final boolean shift = NEIClientUtils.shiftKey();
if (handler != null && (renderer == null || shift)) {
mc.displayGuiScreen(firstGui);
handler.overlayRecipe(firstGui, currenthandlers.get(recipetype), recipe, shift);
overlayHandler.overlayRecipe(firstGui, currenthandlers.get(recipetype), recipe, shift);
} else if (renderer != null) {
mc.displayGuiScreen(firstGui);
LayoutManager.overlayRenderer = renderer;
}
}
public void refreshPage() {
refreshSlots();
final int recipesPerPage = getRecipesPerPage();
final boolean multiplepages = handler.numRecipes() > recipesPerPage;
IRecipeHandler handler = currenthandlers.get(recipetype);
boolean multiplepages = handler.numRecipes() > handler.recipiesPerPage();
nextpage.visible = multiplepages;
prevpage.visible = multiplepages;
final int numRecipes = Math.min(handler.numRecipes() - (page * recipesPerPage), recipesPerPage);
if(firstGui != null) {
overlay1.yPosition = (height - ySize) / 2 + (handler.recipiesPerPage() == 2 ? 63 : 128);
overlay1.visible = handler.hasOverlay(firstGui, firstGui.inventorySlots, page * handler.recipiesPerPage());
overlay2.visible = handler.recipiesPerPage() == 2 && page * handler.recipiesPerPage() + 1 < handler.numRecipes() &&
handler.hasOverlay(firstGui, firstGui.inventorySlots, page * handler.recipiesPerPage() + 1);
area.width = handlerInfo.getWidth();
area.height = handlerInfo.getHeight() * numRecipes;
area.x = guiLeft - 2;
area.y = guiTop - 4 + yShift;
checkYShift();
nextpage.enabled = prevpage.enabled = multiplepages;
if(firstGui == null) {
for (GuiButton overlay : overlayButtons) {
overlay.visible = false;
}
} else {
overlay1.visible = overlay2.visible = false;
for(int i = 0 ; i < overlayButtons.length ; i ++) {
if (i >= numRecipes) {
overlayButtons[i].visible = false;
} else {
final int curRecipe = page * recipesPerPage + i;
overlayButtons[i].visible = handler.hasOverlay(firstGui, firstGui.inventorySlots, curRecipe);
}
}
}
recipeTabs.refreshPage();
}
private void refreshSlots() {
slotcontainer.inventorySlots.clear();
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int i = page * recipehandler.recipiesPerPage(); i < recipehandler.numRecipes() && i < (page + 1) * recipehandler.recipiesPerPage(); i++) {
final int recipesPerPage = getRecipesPerPage();
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
Point p = getRecipePosition(i);
List<PositionedStack> stacks = recipehandler.getIngredientStacks(i);
List<PositionedStack> stacks = handler.getIngredientStacks(i);
for (PositionedStack stack : stacks)
slotcontainer.addSlot(stack, p.x, p.y);
stacks = recipehandler.getOtherStacks(i);
stacks = handler.getOtherStacks(i);
for (PositionedStack stack : stacks)
slotcontainer.addSlot(stack, p.x, p.y);
PositionedStack result = recipehandler.getResultStack(i);
PositionedStack result = handler.getResultStack(i);
if (result != null)
slotcontainer.addSlot(result, p.x, p.y);
}
}
@Override
protected void drawGuiContainerForegroundLayer(int par1, int par2) {
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
GuiContainerManager.enable2DRender();
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
String s = recipehandler.getRecipeName();
fontRendererObj.drawString(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0x404040);
s = NEIClientUtils.translate("recipe.page", page + 1, (currenthandlers.get(recipetype).numRecipes() - 1) / recipehandler.recipiesPerPage() + 1);
fontRendererObj.drawString(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, ySize - 16, 0x404040);
final int recipesPerPage = getRecipesPerPage();
String s = handler.getRecipeName();
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff);
s = NEIClientUtils.translate("recipe.page", page + 1, (handler.numRecipes() - 1) / recipesPerPage + 1);
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
GL11.glPushMatrix();
GL11.glTranslatef(5, 16, 0);
for (int i = page * recipehandler.recipiesPerPage(); i < recipehandler.numRecipes() && i < (page + 1) * recipehandler.recipiesPerPage(); i++) {
recipehandler.drawForeground(i);
GL11.glTranslatef(0, 65, 0);
GL11.glTranslatef(5, 32 + yShift, 0);
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
handler.drawForeground(i);
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
}
GL11.glPopMatrix();
}
@Override
protected void drawGuiContainerBackgroundLayer(float f, int mx, int my) {
protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
final int recipesPerPage = getRecipesPerPage();
GL11.glColor4f(1, 1, 1, 1);
CCRenderState.changeTexture("nei:textures/gui/recipebg.png");
int j = (width - xSize) / 2;
int k = (height - ySize) / 2;
drawTexturedModalRect(j, k, 0, 0, xSize, ySize);
final int j = (width - xSize) / 2;
final int k = guiTop;
drawBackgroundTiled(j, k);
drawRect(guiLeft + borderPadding + buttonWidth - 1,
nexttype.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nexttype.yPosition + buttonHeight,
0x30000000);
drawRect(guiLeft + borderPadding + buttonWidth - 1,
nextpage.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nextpage.yPosition + buttonHeight,
0x30000000);
if (NEIClientConfig.areJEIStyleTabsVisible()) {
RenderHelper.enableGUIStandardItemLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
recipeTabs.draw(mouseX, mouseY);
RenderHelper.disableStandardItemLighting();
}
GL11.glPushMatrix();
GL11.glTranslatef(j + 5, k + 16, 0);
IRecipeHandler recipehandler = currenthandlers.get(recipetype);
for (int i = page * recipehandler.recipiesPerPage(); i < recipehandler.numRecipes() && i < (page + 1) * recipehandler.recipiesPerPage(); i++) {
recipehandler.drawBackground(i);
GL11.glTranslatef(0, 65, 0);
GL11.glTranslatef(j + 5, k + 32 + yShift, 0);
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
handler.drawBackground(i);
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
}
GL11.glPopMatrix();
}
private void drawBackgroundTiled(int j, int k) {
// Draw the top
bgTop.draw(j, k + BG_TOP_Y);
// Maybe Tile the middle
final int tiledHeight = ySize - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
if (tiledHeight > 0) {
final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT;
final int yRemainder = tiledHeight - (yTileCount * BG_MIDDLE_HEIGHT);
final int yStart = k + BG_TOP_HEIGHT + tiledHeight;
for (int yTile = 0; yTile <= yTileCount; yTile++) {
final int tileHeight = (yTile == yTileCount) ? yRemainder : BG_MIDDLE_HEIGHT;
final int y = yStart - ((yTile + 1) * BG_MIDDLE_HEIGHT);
if (tileHeight > 0) {
bgMiddle.draw(j, y, BG_MIDDLE_HEIGHT - tileHeight, 0, 0, 0);
}
}
}
// Draw the bottom
bgBottom.draw(j, k + ySize - BG_BOTTOM_HEIGHT);
}
@Override
public GuiContainer getFirstScreen() {
return firstGui;
@@ -297,20 +471,56 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
return stackSlot == mouseoverSlot;
}
private int getRecipesPerPage() {
if(handlerInfo != null)
return Math.max(Math.min(((ySize - (buttonHeight*3)) / handlerInfo.getHeight()), handlerInfo.getMaxRecipesPerPage()), 1);
else
return (handler.recipiesPerPage());
}
public Point getRecipePosition(int recipe) {
return new Point(5, 16 + (recipe % currenthandlers.get(recipetype).recipiesPerPage()) * 65);
return new Point(5, 32 + yShift + ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
}
@Override
public void mouseScrolled(int i) {
if (new Rectangle(guiLeft, guiTop, xSize, ySize).contains(GuiDraw.getMousePosition())) {
if (i > 0)
prevPage();
else
nextPage();
if (i > 0) prevPage();
else nextPage();
}
}
public abstract ArrayList<? extends IRecipeHandler> getCurrentRecipeHandlers();
@Override
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility)
{
return currentVisibility;
}
@Override
public Iterable<Integer> getItemSpawnSlots(GuiContainer gui, ItemStack item) {
return Collections.emptyList();
}
@Override
public List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {
return null;
}
@Override
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
return false;
}
@Override
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
// Because some of the handlers *cough avaritia* are oversized
Rectangle rect = new Rectangle(area);
return rect.contains(x, y, w, h);
}
}
@@ -0,0 +1,270 @@
package codechicken.nei.recipe;
import codechicken.lib.gui.GuiDraw;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.Widget;
import codechicken.nei.drawable.DrawableResource;
import codechicken.nei.guihook.GuiContainerManager;
import cpw.mods.fml.common.Loader;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.HashMap;
import java.util.List;
public abstract class GuiRecipeTab extends Widget {
public static HandlerInfo DEFAULT_HANDLER_INFO = getDefaultHandlerInfo();
public static HashMap<String, HandlerInfo> handlerMap = new HashMap<>();
private final GuiRecipe guiRecipe;
private final IRecipeHandler handler;
private final String handlerName;
private final String handlerID;
private boolean selected;
public abstract int getWidth();
public abstract int getHeight();
public abstract DrawableResource getSelectedTabImage();
public abstract DrawableResource getUnselectedTabImage();
protected abstract int getForegroundIconX();
protected abstract int getForegroundIconY();
public GuiRecipeTab(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) {
super();
this.x = x;
this.y = y;
this.w = getWidth();
this.h = getHeight();
this.handler = handler;
this.handlerName = handler.toString().split("@")[0];
this.guiRecipe = guiRecipe;
this.selected = false;
if(handler instanceof TemplateRecipeHandler) {
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
} else {
handlerID = null;
}
}
@Override
public void draw(int mouseX, int mouseY) {
drawBackground(mouseX, mouseY);
drawForeground(mouseX, mouseY);
}
public void drawBackground(int mouseX, int mouseY) {
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glColor4f(1, 1, 1, 1);
final DrawableResource image;
if (selected) image = getSelectedTabImage();
else image = getUnselectedTabImage();
final int iconX = x + (w - image.getWidth()) / 2;
final int iconY = y + (h - image.getHeight()) / 2;
image.draw(iconX, iconY);
}
public void drawForeground(int mouseX, int mouseY) {
final int iconX = getForegroundIconX();
final int iconY = getForegroundIconY();
final FontRenderer fontRenderer = GuiDraw.fontRenderer;
final HandlerInfo handlerInfo = getHandlerInfo(handlerName, handlerID);
final DrawableResource icon = handlerInfo != null ? handlerInfo.getImage() : null;
final ItemStack itemStack = handlerInfo != null ? handlerInfo.getItemStack() : null;
if (icon != null) {
icon.draw(iconX + 1, iconY + 1);
} else if (itemStack != null) {
GuiContainerManager.drawItems.zLevel += 100;
GuiContainerManager.drawItem(iconX, iconY, itemStack);
GuiContainerManager.drawItems.zLevel -= 100;
} else {
// Text fallback
String text = handler.getRecipeName().substring(0, 2);
int textCenterX = x + (int) (getWidth() / 2f);
int textCenterY = y + (int) (getHeight() / 2f) - 3;
int color = selected ? 0xffffa0 : 0xe0e0e0;
fontRenderer.drawStringWithShadow(text, textCenterX - (int) (fontRenderer.getStringWidth(text) / 2f), textCenterY, color);
GL11.glColor4f(1, 1, 1, 1);
}
}
public void addTooltips(List<String> tooltip) {
tooltip.add(handler.getRecipeName().trim());
String handlerMod = getHandlerMod(handlerName, handlerID);
tooltip.add(EnumChatFormatting.BLUE + handlerMod);
boolean shiftHeld = Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT || Keyboard.getEventKey() == Keyboard.KEY_RSHIFT);
if (handlerMod.equals("Unknown") || shiftHeld) {
tooltip.add("");
tooltip.add("HandlerName: " + handlerName);
tooltip.add("HandlerID: " + handlerID);
}
}
public boolean onButtonPress(boolean rightclick) {
int newIdx = guiRecipe.currenthandlers.indexOf(handler);
if (newIdx == -1)
return false;
guiRecipe.setRecipePage(newIdx);
return true;
}
public void setSelected(IRecipeHandler current) {
selected = handler == current;
}
public static HandlerInfo getHandlerInfo(String name, String name2) {
HandlerInfo res = handlerMap.get(name);
if (res == null) res = handlerMap.get(name2);
return res;
}
public static String getHandlerMod(String name, String name2) {
HandlerInfo info = getHandlerInfo(name, name2);
if (info == null)
return "Unknown";
return info.getModName();
}
public static void loadHandlerInfo() {
final boolean fromJar = NEIClientConfig.loadHandlersFromJar();
NEIClientConfig.logger.info("Loading handler info from " + (fromJar ? "JAR" : "Config"));
handlerMap.clear();
URL handlerUrl = Thread.currentThread().getContextClassLoader().getResource("assets/nei/csv/handlers.csv");
URL url;
if (fromJar) {
url = handlerUrl;
if (url == null) {
NEIClientConfig.logger.info("Invalid URL for handlers csv.");
return;
}
} else {
File handlerFile = NEIClientConfig.handlerFile;
if(!handlerFile.exists()) {
NEIClientConfig.logger.info("Config file doesn't exit, creating");
try {
assert handlerUrl != null;
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(handlerFile.getAbsoluteFile());
FileChannel fileChannel = fileOutputStream.getChannel();
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
try {
url = NEIClientConfig.handlerFile.toURI().toURL();
} catch (MalformedURLException e) {
NEIClientConfig.logger.info("Invalid URL for handlers csv (via config).");
e.printStackTrace();
return;
}
}
try {
BufferedReader input = new BufferedReader(new InputStreamReader(url.openStream()));
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(input);
for (CSVRecord record : csvParser) {
final String handler = record.get("handler");
final String modName = record.get("modName");
final String modId = record.get("modId");
final boolean requiresMod = Boolean.parseBoolean(record.get("modRequired"));
final String excludedModId = record.get("excludedModId");
if (requiresMod && !Loader.isModLoaded(modId)) continue;
if (excludedModId != null && Loader.isModLoaded(excludedModId)) continue;
HandlerInfo info = new HandlerInfo(handler, modName, modId, requiresMod, excludedModId);
final String imageResource = record.get("imageResource");
if(imageResource != null && !imageResource.equals("")) {
info.setImage(imageResource,
Integer.parseInt(record.get("imageX")),
Integer.parseInt(record.get("imageY")),
Integer.parseInt(record.get("imageWidth")),
Integer.parseInt(record.get("imageHeight"))
);
}
if(!info.hasImageOrItem()) {
final String itemName = record.get("itemName");
if (itemName != null && !itemName.equals("")) {
info.setItem(itemName, record.get("nbtInfo"));
}
}
final String yShift = record.get("yShift");
if (yShift != null && !yShift.equals(""))
info.setYShift(Integer.parseInt(yShift));
try {
final int imageHeight = intOrDefault(record.get("handlerHeight"), HandlerInfo.DEFAULT_HEIGHT);
final int imageWidth = intOrDefault(record.get("handlerWidth"), HandlerInfo.DEFAULT_WIDTH);
final int maxRecipesPerPage = intOrDefault(record.get("maxRecipesPerPage"), HandlerInfo.DEFAULT_MAX_PER_PAGE);
info.setHandlerDimensions(imageHeight, imageWidth, maxRecipesPerPage);
} catch (NumberFormatException ignored) {
NEIClientConfig.logger.info("Error setting handler dimensions for " + handler);
}
handlerMap.put(handler, info);
NEIClientConfig.logger.info("Loaded " + handler);
}
} catch (IOException e) {
NEIClientConfig.logger.info("Error parsing CSV");
e.printStackTrace();
} catch (Exception e) {
NEIClientConfig.logger.info("Error parsing CSV");
e.printStackTrace();
}
}
private static HandlerInfo getDefaultHandlerInfo() {
final HandlerInfo info = new HandlerInfo("Unknown", "Unknown", "Unknown", false, "");
info.setHandlerDimensions(HandlerInfo.DEFAULT_HEIGHT, HandlerInfo.DEFAULT_WIDTH, HandlerInfo.DEFAULT_MAX_PER_PAGE);
return info;
}
private static int intOrDefault(String str, int defaultValue) {
if (str == null || str.equals("")) return defaultValue;
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return defaultValue;
}
}
}
@@ -0,0 +1,47 @@
package codechicken.nei.recipe;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
public class GuiRecipeTabCreative extends GuiRecipeTab {
public static final int TAB_WIDTH = 28;
public static final int TAB_HEIGHT = 31;
private static final DrawableResource selectedTabImage = new DrawableBuilder("minecraft:textures/gui/container/creative_inventory/tabs.png", 28, 32, 28, 32).build();
private static final DrawableResource unselectedTabImage = new DrawableBuilder("minecraft:textures/gui/container/creative_inventory/tabs.png", 28, 0, 28, 30).build();
public GuiRecipeTabCreative(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) {
super(guiRecipe, handler, x, y);
}
@Override
public int getWidth() {
return TAB_WIDTH;
}
@Override
public int getHeight() {
return TAB_HEIGHT;
}
@Override
protected int getForegroundIconX() {
return x + (w - 16) / 2;
}
@Override
protected int getForegroundIconY() {
return y + h - 22;
}
@Override
public DrawableResource getSelectedTabImage() {
return selectedTabImage;
}
@Override
public DrawableResource getUnselectedTabImage() {
return unselectedTabImage;
}
}
@@ -0,0 +1,47 @@
package codechicken.nei.recipe;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
public class GuiRecipeTabJEI extends GuiRecipeTab {
public static final int TAB_WIDTH = 24;
public static final int TAB_HEIGHT = 24;
private static final DrawableResource selectedTabImage = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 16, 24, 24).build();
private static final DrawableResource unselectedTabImage = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 24, 16, 24, 24).build();
public GuiRecipeTabJEI(GuiRecipe guiRecipe, IRecipeHandler handler, int x, int y) {
super(guiRecipe, handler, x, y);
}
@Override
public int getWidth() {
return TAB_WIDTH;
}
@Override
public int getHeight() {
return TAB_HEIGHT;
}
@Override
protected int getForegroundIconX() {
return x + 4;
}
@Override
protected int getForegroundIconY() {
return y + 4;
}
@Override
public DrawableResource getSelectedTabImage() {
return selectedTabImage;
}
@Override
public DrawableResource getUnselectedTabImage() {
return unselectedTabImage;
}
}
@@ -0,0 +1,196 @@
package codechicken.nei.recipe;
import codechicken.nei.Button;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class GuiRecipeTabs {
private final GuiRecipe guiRecipe;
private final List<GuiRecipeTab> tabs = new ArrayList<>();
private final List<Button> buttons = new ArrayList<>();
private final Rectangle area = new Rectangle();
private boolean creative_tab_style;
private int pageCount = 1;
private int pageNumber = 0;
private int categoriesPerPage = 1;
private int numHandlers = 1;
private int tabWidth;
private int tabHeight;
public GuiRecipeTabs(GuiRecipe guiRecipe) {
this.guiRecipe = guiRecipe;
}
public void initLayout() {
creative_tab_style = NEIClientConfig.useCreativeTabStyle();
if(creative_tab_style) {
tabWidth = GuiRecipeTabCreative.TAB_WIDTH;
tabHeight = GuiRecipeTabCreative.TAB_HEIGHT;
} else {
tabWidth = GuiRecipeTabJEI.TAB_WIDTH;
tabHeight = GuiRecipeTabJEI.TAB_HEIGHT;
}
int totalWidth = 0;
categoriesPerPage = 0;
numHandlers = guiRecipe.currenthandlers.size();
for (IRecipeHandler handler : guiRecipe.currenthandlers) {
if (totalWidth + tabWidth < (guiRecipe.xSize - 4)) {
totalWidth += tabWidth;
categoriesPerPage++;
} else {
break;
}
}
area.width = totalWidth;
area.height = tabHeight;
area.x = guiRecipe.guiLeft + 4;
area.y = guiRecipe.guiTop - tabHeight + 3;
pageCount = (int) Math.ceil((float) numHandlers / categoriesPerPage);
calcPageNumber();
Rectangle navigationArea = new Rectangle(area);
navigationArea.height = 20;
navigationArea.translate(0, -(2 + navigationArea.height));
}
public void calcPageNumber() {
pageNumber = guiRecipe.recipetype / Math.max(categoriesPerPage, 1);
}
public void refreshPage() {
tabs.clear();
buttons.clear();
final int startIndex = pageNumber * categoriesPerPage;
for (int i = 0 ; i < categoriesPerPage ; i++) {
final int index = i + startIndex;
if (index >= numHandlers) break;
IRecipeHandler handler = guiRecipe.currenthandlers.get(index);
int tabX = area.x + (i * tabWidth);
if(NEIClientConfig.useCreativeTabStyle())
tabs.add(new GuiRecipeTabCreative(guiRecipe, handler, tabX, area.y));
else
tabs.add(new GuiRecipeTabJEI(guiRecipe, handler, tabX, area.y));
}
// Maybe add buttons
if (numHandlers > categoriesPerPage) {
Button prevTab = new Button("prevTab") {
@Override
public boolean onButtonPress(boolean rightClick) {
if (!rightClick) {
NEIClientUtils.playClickSound();
return previousPage();
} else
return false;
}
@Override
public String getRenderLabel() {
return "<";
}
};
prevTab.w = 8;
prevTab.h = tabHeight - 4;
prevTab.x = area.x - prevTab.w + 1;
prevTab.y = area.y + 2;
buttons.add(prevTab);
Button nextTab = new Button("nextTab") {
@Override
public boolean onButtonPress(boolean rightclick) {
if (!rightclick) {
NEIClientUtils.playClickSound();
return nextPage();
} else return false;
}
@Override
public String getRenderLabel() {
return ">";
}
};
nextTab.w = prevTab.w;
nextTab.h = prevTab.h;
nextTab.x = area.x + area.width - 1;
nextTab.y = prevTab.y;
buttons.add(nextTab);
}
}
public boolean nextPage() {
if (hasNext()) pageNumber++;
else pageNumber = 0;
refreshPage();
return true;
}
public boolean hasNext() {
return pageNumber + 1 < pageCount;
}
public boolean previousPage() {
if (hasPrevious()) pageNumber--;
else pageNumber = pageCount - 1;
refreshPage();
return true;
}
public boolean hasPrevious() {
return pageNumber > 0;
}
public void draw(int mouseX, int mouseY) {
IRecipeHandler current = guiRecipe.currenthandlers.get(guiRecipe.recipetype);
for (GuiRecipeTab tab : tabs) {
tab.setSelected(current);
tab.draw(mouseX, mouseY);
}
for (Button button : buttons) {
button.draw(mouseX, mouseY);
}
}
public void handleTooltip(int mousex, int mousey, List<String> tooltips) {
if (!NEIClientConfig.areJEIStyleTabsVisible()) return;
for (GuiRecipeTab tab : tabs) {
if (tab.contains(mousex, mousey)) {
tab.addTooltips(tooltips);
}
}
for (Button button : buttons) {
if (button.contains(mousex, mousey)){
button.addTooltips(tooltips);
}
}
}
protected boolean mouseClicked(int x, int y, int mouseButton) {
if (!NEIClientConfig.areJEIStyleTabsVisible()) return false;
for (Button button : buttons) {
if (button.contains(x, y)) {
return button.onButtonPress(mouseButton == 1);
}
}
for (GuiRecipeTab tab : tabs) {
if (tab.contains(x, y)) {
return tab.onButtonPress(mouseButton == 1);
}
}
return false;
}
}
+35 -12
View File
@@ -1,11 +1,16 @@
package codechicken.nei.recipe;
import codechicken.core.TaskProfiler;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
public class GuiUsageRecipe extends GuiRecipe
{
@@ -13,15 +18,29 @@ public class GuiUsageRecipe extends GuiRecipe
Minecraft mc = NEIClientUtils.mc();
GuiContainer prevscreen = mc.currentScreen instanceof GuiContainer ? (GuiContainer) mc.currentScreen : null;
ArrayList<IUsageHandler> handlers;
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
ArrayList<IUsageHandler> handlers = new ArrayList<>();
for (IUsageHandler usagehandler : usagehandlers) {
profiler.start(usagehandler.getRecipeName());
IUsageHandler handler = usagehandler.getUsageHandler(inputId, ingredients);
if (handler.numRecipes() > 0)
handlers.add(handler);
// Pre-find the fuels so we're not fighting over it
FuelRecipeHandler.findFuelsOnceParallel();
profiler.start("recipe.concurrent.usage");
try {
handlers = serialUsageHandlers.stream().map(h -> h.getUsageHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new));
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
.map(h -> h.getUsageHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return false;
} finally {
profiler.end();
}
profiler.end();
if (handlers.isEmpty())
return false;
@@ -35,12 +54,15 @@ public class GuiUsageRecipe extends GuiRecipe
}
public static void registerUsageHandler(IUsageHandler handler) {
for (IUsageHandler handler1 : usagehandlers) {
if (handler1.getClass() == handler.getClass())
return;
}
final Class<? extends IUsageHandler> handlerClass = handler.getClass();
if(usagehandlers.stream().anyMatch(h -> h.getClass() == handlerClass) || serialUsageHandlers.stream().anyMatch(h -> h.getClass() == handlerClass))
return;
usagehandlers.add(handler);
final String handlerClassStr = handlerClass.getName();
if(NEIClientConfig.serialHandlers.contains(handlerClassStr))
serialUsageHandlers.add(handler);
else
usagehandlers.add(handler);
}
public ArrayList<? extends IRecipeHandler> getCurrentRecipeHandlers() {
@@ -50,4 +72,5 @@ public class GuiUsageRecipe extends GuiRecipe
public ArrayList<IUsageHandler> currenthandlers;
public static ArrayList<IUsageHandler> usagehandlers = new ArrayList<>();
public static ArrayList<IUsageHandler> serialUsageHandlers = new ArrayList<>();
}
+156
View File
@@ -0,0 +1,156 @@
package codechicken.nei.recipe;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
import org.apache.logging.log4j.Level;
public class HandlerInfo {
public static int DEFAULT_HEIGHT = 65;
public static int DEFAULT_WIDTH = 166;
public static int DEFAULT_MAX_PER_PAGE = 2;
private String handler;
private String modName;
private String modId;
private boolean requiresMod = true;
private String excludedModId;
private String itemId;
private String nbtString;
private int yShift = 0;
private int height = DEFAULT_HEIGHT;
private int width = DEFAULT_WIDTH;
private int maxRecipesPerPage = DEFAULT_MAX_PER_PAGE;
private ItemStack itemStack = null;
private DrawableResource image = null;
public HandlerInfo(String handler, String modName, String modId, boolean requiresMod, String excludedModId) {
this.handler = handler;
this.modName = modName;
this.modId = modId;
this.requiresMod = requiresMod;
this.excludedModId = excludedModId;
}
public void setHandlerDimensions(int height, int width, int maxRecipesPerPage) {
this.height = height;
this.width = width;
this.maxRecipesPerPage = maxRecipesPerPage;
}
public boolean setItem(String itemId, String nbtString) {
if(hasImageOrItem())
return false;
int meta = -1;
if (!itemId.contains(":")) {
NEIClientConfig.logger.info("Item ID missing colon for handler " + handler + " - " + modName);
return false;
}
final String[] split = itemId.split(":");
// ModID:ItemID
String itemLookupId = split[0] + ":" + split[1];
if(split.length >= 3) {
int mIdx = -1;
if (split[2].matches("\\d+")) {
mIdx = 2;
} else {
itemLookupId += ":" + split[2];
if (split.length >= 4) mIdx = 3;
}
if (mIdx != -1) meta = Integer.parseInt(split[mIdx]);
}
if (meta != -1) {
itemStack = GameRegistry.makeItemStack(itemLookupId, meta, 1, nbtString == null ? "" : nbtString);
} else {
itemStack = GameRegistry.findItemStack(split[0], split[1], 1);
if (nbtString != null && !nbtString.equals("")) {
try {
final NBTBase nbttag = JsonToNBT.func_150315_a(nbtString);
if (!(nbttag instanceof NBTTagCompound)) {
NEIClientConfig.logger.info("Unexpected NBT string - multiple values {}", nbtString);
return false;
}
itemStack.setTagCompound((NBTTagCompound) nbttag);
} catch (NBTException e) {
FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e);
return false;
}
}
}
if (itemStack == null)
NEIClientConfig.logger.info("Couldn't find " + modName + " - " + itemLookupId);
else {
this.itemId = itemId;
this.nbtString = nbtString;
}
return (itemStack != null);
}
public boolean setImage(String resourceLocation, int imageX, int imageY, int imageWidth, int imageHeight) {
if(hasImageOrItem())
return false;
this.image = new DrawableBuilder(resourceLocation, imageX, imageY, imageWidth, imageHeight).build();
return true;
}
public DrawableResource getImage() {
return image;
}
public ItemStack getItemStack() {
return itemStack;
}
public String getModName() {
return modName;
}
public String getModId() {
return modId;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int getMaxRecipesPerPage() {
return Math.max(maxRecipesPerPage, 1);
}
public int getYShift() {
return yShift;
}
public boolean hasImageOrItem() {
if (image != null) return true;
if (itemStack != null) return true;
return false;
}
public void setYShift(int yShift) {
this.yShift = yShift;
}
}
@@ -154,7 +154,7 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler
Object[] items = recipe.getInput();
for (Object item : items)
if (item instanceof List && ((List<?>) item).isEmpty())//ore handler, no ores
if (item instanceof List && ((List<?>) item).isEmpty()) //ore handler, no ores
return null;
return new CachedShapedRecipe(width, height, items, recipe.getRecipeOutput());
@@ -49,7 +49,12 @@ public class ShapelessRecipeHandler extends ShapedRecipeHandler
public void setIngredients(List<?> items) {
ingredients.clear();
for (int ingred = 0; ingred < items.size(); ingred++) {
int itemsSize = items.size();
if (itemsSize > stackorder.length) {
NEIClientConfig.logger.error("RECIPE BUG: Too many items (" + itemsSize + ") for " + this.result.toString());
itemsSize = stackorder.length;
}
for (int ingred = 0; ingred < itemsSize; ingred++) {
PositionedStack stack = new PositionedStack(items.get(ingred), 25 + stackorder[ingred][0] * 18, 6 + stackorder[ingred][1] * 18);
stack.setMaxSize(1);
ingredients.add(stack);
@@ -1,5 +1,6 @@
package codechicken.nei.recipe;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIServerUtils;
@@ -11,11 +12,14 @@ import codechicken.nei.api.IStackPositioner;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerInputHandler;
import codechicken.nei.guihook.IContainerTooltipHandler;
import com.google.common.base.Stopwatch;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.Container;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntityFurnace;
import org.lwjgl.opengl.GL11;
import java.awt.Point;
@@ -26,7 +30,12 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static codechicken.lib.gui.GuiDraw.changeTexture;
import static codechicken.lib.gui.GuiDraw.drawTexturedModalRect;
@@ -41,6 +50,63 @@ import static codechicken.lib.gui.GuiDraw.getMousePosition;
*/
public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageHandler
{
protected static ReentrantLock lock = new ReentrantLock();
public static void findFuelsOnce() {
// Ensure we only find fuels once, even if threaded
lock.lock();
try {
if (FurnaceRecipeHandler.afuels == null || FurnaceRecipeHandler.afuels.isEmpty())
findFuels(false);
} finally {
lock.unlock();
}
}
public static void findFuelsOnceParallel() {
// Ensure we only find fuels once, even if threaded
lock.lock();
try {
if (FurnaceRecipeHandler.afuels == null || FurnaceRecipeHandler.afuels.isEmpty())
findFuels(true);
} finally {
lock.unlock();
}
}
private static Set<Item> efuels;
@SuppressWarnings("UnstableApiUsage")
private static void findFuels(boolean parallel) {
efuels = new HashSet<>();
efuels.add(Item.getItemFromBlock(Blocks.brown_mushroom));
efuels.add(Item.getItemFromBlock(Blocks.red_mushroom));
efuels.add(Item.getItemFromBlock(Blocks.standing_sign));
efuels.add(Item.getItemFromBlock(Blocks.wall_sign));
efuels.add(Item.getItemFromBlock(Blocks.wooden_door));
efuels.add(Item.getItemFromBlock(Blocks.trapped_chest));
Stopwatch stopwatch = Stopwatch.createStarted();
if (parallel) {
try {
FurnaceRecipeHandler.afuels = ItemList.forkJoinPool.submit(() -> ItemList.items.parallelStream().map(TemplateRecipeHandler::identifyFuel).filter(Objects::nonNull).collect(Collectors.toCollection(ArrayList::new))).get();
} catch (InterruptedException | ExecutionException e) {
FurnaceRecipeHandler.afuels = new ArrayList<>();
e.printStackTrace();
}
} else {
FurnaceRecipeHandler.afuels = ItemList.items.stream().map(TemplateRecipeHandler::identifyFuel).filter(Objects::nonNull).collect(Collectors.toCollection(ArrayList::new));
}
NEIClientConfig.logger.info("FindFuels took " + stopwatch.stop() );
}
private static FurnaceRecipeHandler.FuelPair identifyFuel(final ItemStack itemStack) {
if (efuels.contains(itemStack.getItem())) return null;
final int burnTime = TileEntityFurnace.getItemBurnTime(itemStack);
if (burnTime <= 0) return null;
return new FurnaceRecipeHandler.FuelPair(itemStack.copy(), burnTime);
}
/**
* This Recipe Handler runs on this internal class
* Fill the recipe array with subclasses of this to make transforming the different types of recipes out there into a nice format for NEI a much easier job.
@@ -310,7 +376,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
*/
public ArrayList<CachedRecipe> arecipes = new ArrayList<>();
/**
* A list of transferRects that apon when clicked or R is pressed will open a new recipe.
* A list of transferRects that when clicked or R is pressed will open a new recipe.
*/
public LinkedList<RecipeTransferRect> transferRects = new LinkedList<>();
@@ -463,6 +529,9 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
public TemplateRecipeHandler newInstance() {
try {
// Use the non parallel version since we might already be using the forkJoinPool and might have no threads available
// This will ideally have been pre-cached elsewhere and will be a NOOP
findFuelsOnce();
return getClass().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
+158
View File
@@ -0,0 +1,158 @@
package codechicken.nei.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagByte;
import net.minecraft.nbt.NBTTagByteArray;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagDouble;
import net.minecraft.nbt.NBTTagFloat;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagLong;
import net.minecraft.nbt.NBTTagShort;
import net.minecraft.nbt.NBTTagString;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
public class NBTJson {
private static final Pattern numberPattern = Pattern.compile("^([-+]?[\\d]+\\.?[0-9]*)([bBsSlLfFdD]?)$");
private static final JsonParser parser = new JsonParser();
private static final Gson gson = new GsonBuilder().create();
public static String toJson(NBTTagCompound tag) {
final String jsonString = toJsonObject(tag).toString();
return gson.toJson(parser.parse(jsonString));
}
@SuppressWarnings("unchecked")
public static JsonElement toJsonObject(NBTBase nbt) {
if (nbt instanceof NBTTagCompound) {
// NBTTagCompound
final NBTTagCompound nbtTagCompound = (NBTTagCompound) nbt;
final Map<String, NBTBase> tagMap = (Map<String, NBTBase>)nbtTagCompound.tagMap;
JsonObject root = new JsonObject();
for (Map.Entry<String, NBTBase> nbtEntry : tagMap.entrySet() ) {
root.add(nbtEntry.getKey(), toJsonObject(nbtEntry.getValue()));
}
return root;
} else if (nbt instanceof NBTBase.NBTPrimitive) {
// Number
return new JsonPrimitive(((NBTBase.NBTPrimitive) nbt).func_150286_g());
} else if (nbt instanceof NBTTagString) {
// String
return new JsonPrimitive(((NBTTagString) nbt).func_150285_a_());
} else if (nbt instanceof NBTTagList) {
// Tag List
JsonArray arr = new JsonArray();
((NBTTagList) nbt).tagList.forEach(c -> arr.add(toJsonObject((NBTBase) c)));
return arr;
} else if (nbt instanceof NBTTagIntArray) {
// Int Array
JsonArray arr = new JsonArray();
for(int i : ((NBTTagIntArray) nbt).func_150302_c()) {
arr.add(new JsonPrimitive(i));
}
return arr;
} else if (nbt instanceof NBTTagByteArray) {
// Byte Array
JsonArray arr = new JsonArray();
for(int i : ((NBTTagByteArray) nbt).func_150292_c()) {
arr.add(new JsonPrimitive(i));
}
return arr;
} else {
throw new IllegalArgumentException("Unsupported NBT Tag: " + NBTBase.NBTTypes[nbt.getId()] + " - " + nbt);
}
}
public static NBTBase toNbt(JsonElement jsonElement) {
if (jsonElement instanceof JsonPrimitive) {
// Number or String
final JsonPrimitive jsonPrimitive = (JsonPrimitive) jsonElement;
final String jsonString = jsonPrimitive.getAsString();
final Matcher m = numberPattern.matcher(jsonString);
if(m.find()) {
// Number
final String numberString = m.group(1);
if (m.groupCount() == 2 && m.group(2).length() > 0) {
final char numberType = m.group(2).charAt(0);
switch(numberType) {
case 'b':
case 'B':
return new NBTTagByte(Byte.parseByte(numberString));
case 's':
case 'S':
return new NBTTagShort(Short.parseShort(numberString));
case 'l':
case 'L':
return new NBTTagLong(Long.parseLong(numberString));
case 'f':
case 'F':
return new NBTTagFloat(Float.parseFloat(numberString));
case 'd':
case 'D':
return new NBTTagDouble(Double.parseDouble(numberString));
}
} else {
if (numberString.contains("."))
return new NBTTagDouble(Double.parseDouble(numberString));
else
return new NBTTagInt(Integer.parseInt(numberString));
}
} else {
// String
return new NBTTagString(jsonString);
}
} else if (jsonElement instanceof JsonArray) {
// NBTTagIntArray or NBTTagList
final JsonArray jsonArray = (JsonArray) jsonElement;
final List<NBTBase> nbtList = new ArrayList<>();
for (JsonElement element : jsonArray) {
nbtList.add(toNbt(element));
}
if (nbtList.stream().allMatch(n -> n instanceof NBTTagInt)) {
return new NBTTagIntArray(nbtList.stream().mapToInt(i -> ((NBTTagInt)i).func_150287_d() ).toArray());
} else if (nbtList.stream().allMatch(n -> n instanceof NBTTagByte)) {
return new NBTTagByteArray(toByteArray(nbtList.stream().mapToInt(i -> ((NBTTagInt)i).func_150287_d() )));
} else {
NBTTagList nbtTagList = new NBTTagList();
nbtList.forEach(nbtTagList::appendTag);
return nbtTagList;
}
} else if (jsonElement instanceof JsonObject) {
// NBTTagCompound
final JsonObject jsonObject = (JsonObject) jsonElement;
NBTTagCompound nbtTagCompound = new NBTTagCompound();
for (Map.Entry<String, JsonElement> jsonEntry : jsonObject.entrySet()) {
nbtTagCompound.setTag(jsonEntry.getKey(), toNbt(jsonEntry.getValue()));
}
return nbtTagCompound;
}
throw new IllegalArgumentException("Unhandled element " + jsonElement);
}
public static byte[] toByteArray(IntStream stream) {
return stream.collect(ByteArrayOutputStream::new, (baos, i) -> baos.write((byte) i), (baos1, baos2) -> baos1.write(baos2.toByteArray(), 0, baos2.size()))
.toByteArray();
}
}