Compare commits

...
Author SHA1 Message Date
Martin Robertz 195b984493 Merge remote-tracking branch 'origin/legacy-handler-compatibility-improvements' into dev 2023-07-04 18:42:23 +02:00
Wilhelm Schuster 8d3a0056ab Fix Thermal Expansion recipe handlers
These handlers expect only two recipes to be displayed at a time. This can only be fixed through asm AFAICT.
2023-07-03 21:15:39 +02:00
Wilhelm Schuster a34df30231 Fix Ex Nihilo recipe handlers 2023-07-03 21:15:39 +02:00
Wilhelm Schuster 61f427f0d6 Add support for modId, modRequired, and excludedModId to registerCatalyst IMC message 2023-07-02 19:59:28 +02:00
Wilhelm Schuster 82e58c4eb5 Fix Immersive Engineering recipe handlers 2023-07-02 13:13:58 +02:00
Wilhelm Schuster 13e9f3c547 Extend the height hack to also cover guiTop and getRecipePosition
Certain legacy recipe handlers hardcode even more of the NEI recipe
screen layout, requiring only the singular recipe handler switcher
widget at the top, whereas this improved NEI moves the recipe pager to
the top as well expecting recipe handler to move down another 16px. One
such mod that breaks is Immersive Engineering. To fix it we move the top
edge of the gui (guiTop) down by 16px so that the old gap calculation
works correctly. This required special handling in getRecipePosition()
and refreshSlots().
2023-07-02 13:13:58 +02:00
Wilhelm Schuster 405bb35495 Store serialhandlers.cfg as an internal asset instead of an array of strings
Is copied into the config directory upon first launch. Also, comments
are now allowed (only from the beginning of the file).

Removes GTNH-specific code to be replaced with a configuration file.
2023-07-01 21:38:16 +02:00
Wilhelm Schuster 368018c2b1 Store heighthackhandlers.cfg as an internal asset instead of an array of strings
Is copied into the config directory upon first launch. Also, comments
are now allowed (only from the beginning of the file).
2023-07-01 21:38:16 +02:00
6 changed files with 90 additions and 43 deletions

No files matched your search

@@ -9,9 +9,6 @@ import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
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;
@@ -48,20 +45,12 @@ import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.StackInfo;
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;
public class ClientHandler {
private static String[] defaultSerialHandlers = {
"WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler" };
private static String[] defaultHeightHackHandlerRegex = { "buildcraft.compat.nei.*",
"cofh.thermalexpansion.plugins.nei.handlers.*", "crazypants.enderio.nei.*",
"forestry.factory.recipes.nei.*", "ic2.neiIntegration.core.recipehandler.*", "mariculture.plugins.nei.*",
"redgear.brewcraft.plugins.nei.*", "tconstruct.plugins.nei.*",
"WayofTime.alchemicalWizardry.client.nei.*", };
private static String[] defaultHandlerOrdering = {
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
"# Ordering lines are <handler ID>,<ordering number>.",
@@ -165,16 +154,19 @@ public class ClientHandler {
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);
URL defaultSerialHandlersResource = ClientHandler.class
.getResource("/assets/nei/cfg/serialhandlers.cfg");
if (defaultSerialHandlersResource != null) {
IOUtils.copy(defaultSerialHandlersResource.openStream(), 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));
NEIClientConfig.serialHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#"))
.collect(Collectors.toCollection(HashSet::new));
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e);
}
@@ -185,8 +177,11 @@ public class ClientHandler {
if (!file.exists()) {
try (FileWriter writer = new FileWriter(file)) {
NEIClientConfig.logger.info("Creating default height hack handlers list {}", file);
Collection<String> toSave = Arrays.asList(defaultHeightHackHandlerRegex);
IOUtils.writeLines(toSave, "\n", writer);
URL defaultHeightHackHandlersResource = ClientHandler.class
.getResource("/assets/nei/cfg/heighthackhandlers.cfg");
if (defaultHeightHackHandlersResource != null) {
IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer);
}
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e);
}
@@ -194,7 +189,8 @@ public class ClientHandler {
try (FileReader reader = new FileReader(file)) {
NEIClientConfig.logger.info("Loading height hack handlers from file {}", file);
NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream().map(Pattern::compile)
NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream()
.filter((line) -> !line.startsWith("#")).map(Pattern::compile)
.collect(Collectors.toCollection(HashSet::new));
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e);
@@ -135,6 +135,13 @@ public class IMCHandler {
NEIClientConfig.logger.warn("Missing handlerID for registerCatalystInfo!");
return;
}
final String modId = tag.hasKey("modId") ? tag.getString("modId") : null;
final boolean requiresMod = tag.getBoolean("modRequired");
final String excludedModId = tag.hasKey("excludedModId") ? tag.getString("excludedModId") : null;
if (requiresMod && modId != null && !Loader.isModLoaded(modId)) return;
if (excludedModId != null && Loader.isModLoaded(excludedModId)) return;
final String itemName = tag.getString("itemName");
final String nbtInfo = tag.hasKey("nbtInfo") ? tag.getString("nbtInfo") : null;
if (itemName.isEmpty()) {
@@ -170,7 +177,7 @@ public class IMCHandler {
final String itemName = tag.getString("itemName");
final String nbtInfo = tag.hasKey("nbtInfo") ? tag.getString("nbtInfo") : null;
if (itemName.isEmpty()) {
NEIClientConfig.logger.warn(String.format("Missing itemName for registerCatalystInfo in `%s`!", handlerID));
NEIClientConfig.logger.warn(String.format("Missing itemName for removeCatalystInfo in `%s`!", handlerID));
return;
}
final ItemStack itemStack = NEIServerUtils.getModdedItem(itemName, nbtInfo);
@@ -100,6 +100,8 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
private int yShift = 0;
private boolean isHeightHackApplied = false;
protected GuiRecipe(GuiScreen prevgui) {
super(new ContainerRecipe());
recipeTabs = new GuiRecipeTabs(this);
@@ -118,7 +120,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
/**
* Many old mods assumed a fixed NEI window height of {@code 166} pixels. Now that this is no longer the case, their
* fluid mouseover handling is broken. This helper class fixes these old mods by hacking the {@link #height}
* tooltip and click zone handling is broken. This helper class fixes these old mods by hacking the {@link #height}
* property's value so that these old mods' calculations return the correct value for the new height.
*
* <p>
@@ -128,31 +130,43 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
private class HeightHack implements AutoCloseable {
private final int trueHeight;
private final int trueGuiTop;
private HeightHack() {
trueHeight = height;
trueGuiTop = guiTop;
boolean applyHeightHack = NEIClientConfig.heightHackHandlerRegex.stream()
isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
if (applyHeightHack) {
// The old mods use the calculation ((height - 166) / 2) to compute the y-value of
// the top edge of the NEI window.
// guiTop is exactly that: the y-value of the top edge of the NEI window.
// So we set height to be equal to the inverse of this calculation, applied to
// guiTop, so that old mods get the right result back when they use this calculation.
if (isHeightHackApplied) {
// guiTop is the top edge of the recipe screen on the y-axis. Old recipe handlers expect a single paging
// widget at the top and at the bottom of the recipe screen with a height of 16px, but GTNH NEI move the
// bottom paging widget to the top following JEI's UI increasing the forbidden zone at the top to 32px.
// To fix these old recipe handlers we move guiTop down 16px so that they can keep working with the old
// 16px gap.
guiTop += 16;
// The old NEI recipe screen had a fixed width and height and was always centered on the screen. Legacy
// recipe handlers use the calculation ((height - 166) / 2) to compute the y-value of the top edge of
// the NEI recipe screen. GTNH NEI now has a flexible recipe screen length and is no longer centered
// vertically, so in order for the top-of-screen calculation to return the correct result, we have to
// hack the height field with an inverse of the calculation using the actual top of the recipe screen
// stored in guiTop.
height = (2 * guiTop) + 166;
// For reference, in case we ever need to modify width as well:
// the legacy calculation used for width is ((width - 176) / 2), which should
// evaluate to be equal to guiWidth (the x-value of the left edge of the NEI window).
// So if we wanted to override width as well, we'd do this:
// the legacy calculation used for width is ((width - 176) / 2), which should evaluate to be equal to
// guiWidth (the x-value of the left edge of the NEI recipe screen). So if we wanted to override width
// as well, we'd do this:
// width = (2 * guiWidth) + 176;
}
}
@Override
public void close() {
guiTop = trueGuiTop;
height = trueHeight;
isHeightHackApplied = false;
}
}
@@ -454,9 +468,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
@Override
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey,
List<String> currenttip) {
// Height hacking is probably not needed as it doesn't look like any mods check mouse
// position for this method.
for (int i : getRecipeIndices()) currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
try (HeightHack heightHack = new HeightHack()) {
for (int i : getRecipeIndices()) currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
}
return currenttip;
}
@@ -542,6 +556,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
final int recipesPerPage = getRecipesPerPage();
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
Point p = getRecipePosition(i);
// Legacy recipe handlers only expect a single paging widget at the top of the recipe screen, in contrast,
// GTNH NEI moves the recipe paging widget from the bottom to the top, which means said legacy handlers will
// position item slots 16px too high in the screen.
if (isHeightHackApplied) {
p.translate(0, 16);
}
List<PositionedStack> stacks = handler.getIngredientStacks(i);
for (PositionedStack stack : stacks) slotcontainer.addSlot(stack, p.x, p.y);
@@ -735,7 +755,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
public Point getRecipePosition(int recipe) {
return new Point(5, 32 + yShift + ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
// Legacy recipe handlers using the height hack might use getRecipePosition in combination with guiTop/height to
// position certain elements like tooltips. Since guiTop is moved down by 16px during height hacking, we need to
// reduce the vertical shift here to 16px instead of 32px.
return new Point(
5,
(isHeightHackApplied ? 16 : 32) + yShift + ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
}
public abstract ArrayList<H> getCurrentRecipeHandlers();
@@ -0,0 +1,13 @@
# Each line in this file should either be a comment (starts with '#') or a fully qualified class name (that includes the
# package name) for a recipe handler. Wildcard patterns ('*') can be used to catch multiple classes with a single entry.
# If you delete this file, it will be regenerated with the default height hacked handlers list.
buildcraft.compat.nei.*
cofh.thermalexpansion.plugins.nei.handlers.*
crazypants.enderio.nei.*
forestry.factory.recipes.nei.*
ic2.neiIntegration.core.recipehandler.*
mariculture.plugins.nei.*
redgear.brewcraft.plugins.nei.*
tconstruct.plugins.nei.*
WayofTime.alchemicalWizardry.client.nei.*
exnihilo.compatibility.nei.*
@@ -0,0 +1,6 @@
# This version of NEI loads recipes in parallel. Some recipe handlers have not been designed with that in mind and might
# crash. List these handlers in this file to force them to be loaded a single thread. Each line in this file should
# either be a comment (starts with '#') or a fully qualified class name (that includes the package name) for a recipe
# handler.
# If you delete this file, it will be regenerated with the default height hacked handlers list.
WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler
@@ -373,11 +373,11 @@ NEIArcFurnaceHandlerCarrot Ingot,Immersive Engineering,minecraft:carrot,,Immersi
NEIArcFurnaceHandlerExtraction,Immersive Engineering,minecraft:glowstone_dust,,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:woodenDevice:5,,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:metalMultiblock:4,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:1,,ImmersiveEngineering,TRUE,,,71,166,2,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:2,,ImmersiveEngineering,TRUE,,,71,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEISqueezerHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:2,,ImmersiveEngineering,TRUE,,1,64,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIFermenterHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:3,,ImmersiveEngineering,TRUE,,,71,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIRefineryHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:4,,ImmersiveEngineering,TRUE,,,65,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler,Immersive Engineering,minecraft:glass_bottle,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:13,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICrusherHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:5,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
@@ -410,13 +410,13 @@ cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCharger,Thermal Expansio
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingMachine,Thermal Expansion,ThermalExpansion:Frame,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingSecure,Thermal Expansion,ThermalExpansion:material:16,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingUpgrade,Thermal Expansion,ThermalExpansion:Frame:3,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible,Thermal Expansion,ThermalExpansion:Machine:4,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible,Thermal Expansion,ThermalExpansion:Machine:4,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerFurnace,Thermal Expansion,ThermalExpansion:Machine:0,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator,Thermal Expansion,ThermalExpansion:Machine:11,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator,Thermal Expansion,ThermalExpansion:Machine:11,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerPulverizer,Thermal Expansion,ThermalExpansion:Machine:1,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSawmill,Thermal Expansion,ThermalExpansion:Machine:2,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSmelter,Thermal Expansion,ThermalExpansion:Machine:3,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer,Thermal Expansion,ThermalExpansion:Machine:5,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer,Thermal Expansion,ThermalExpansion:Machine:5,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
mekanism.client.nei.ChemicalCrystallizerRecipeHandler,Mekanism,Mekanism:MachineBlock2:8,,Mekanism,TRUE,,,79,,4,,,,,,
mekanism.client.nei.ChemicalDissolutionChamberRecipeHandler,Mekanism,Mekanism:MachineBlock2:6,,Mekanism,TRUE,,,79,,4,,,,,,
mekanism.client.nei.ChemicalInfuserRecipeHandler,Mekanism,Mekanism:MachineBlock2:2,,Mekanism,TRUE,,,80,,4,,,,,,
@@ -437,7 +437,7 @@ mekanism.client.nei.ShapelessMekanismRecipeHandler,Mekanism,minecraft:crafting_t
mekanism.client.nei.SolarNeutronRecipeHandler,Mekanism,Mekanism:MachineBlock3:1,,Mekanism,TRUE,,,70,,5,,,,,,
mekanism.client.nei.ThermalEvaporationRecipeHandler,Mekanism,Mekanism:BasicBlock:14,,Mekanism,TRUE,,,62,,5,,,,,,
exnihilo.compatibility.nei.RecipeHandlerHammer,Ex Nihilo,exnihilo:hammer_iron,,exnihilo,TRUE,,,58,,5,,,,,,
exnihilo.compatibility.nei.RecipeHandlerSieve,Ex Nihilo,exnihilo:sifting_table,,exnihilo,TRUE,,,130,,2,,,,,,
exnihilo.compatibility.nei.RecipeHandlerSieve,Ex Nihilo,exnihilo:sifting_table,,exnihilo,TRUE,,,130,,1,,,,,,
gregtech.Alloy,GregTech-Addon,gregtech_addon:machine:56,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
gregtech.Assembler,GregTech-Addon,gregtech_addon:machine:60,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
gregtech.Bender,GregTech-Addon,gregtech_addon:machine:59,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
1 handler modName itemName nbtInfo modId modRequired excludedModId yShift handlerHeight handlerWidth maxRecipesPerPage imageResource imageX imageY imageWidth imageHeight itemNotes
373 NEIArcFurnaceHandlerExtraction Immersive Engineering minecraft:glowstone_dust ImmersiveEngineering TRUE 65 166 5
374 blusunrize.immersiveengineering.client.nei.NEIShaderBagHandler Immersive Engineering ImmersiveEngineering:shaderBag ImmersiveEngineering TRUE 65 166 5
375 blusunrize.immersiveengineering.client.nei.NEIBlueprintHandler Immersive Engineering ImmersiveEngineering:woodenDevice:5 ImmersiveEngineering TRUE 65 166 5
376 blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:1 ImmersiveEngineering TRUE 71 166 5 2
377 blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:2 ImmersiveEngineering TRUE 71 166 5 2
378 blusunrize.immersiveengineering.client.nei.NEISqueezerHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:2 ImmersiveEngineering TRUE 1 71 64 166 5 2
379 blusunrize.immersiveengineering.client.nei.NEIFermenterHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:3 ImmersiveEngineering TRUE 71 166 5 2
380 blusunrize.immersiveengineering.client.nei.NEIRefineryHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:4 ImmersiveEngineering TRUE 65 166 5 2
381 blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler Immersive Engineering minecraft:glass_bottle ImmersiveEngineering TRUE 65 166 5
382 blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:13 ImmersiveEngineering TRUE 65 166 5
383 blusunrize.immersiveengineering.client.nei.NEICrusherHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:5 ImmersiveEngineering TRUE 71 166 5
410 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingMachine Thermal Expansion ThermalExpansion:Frame ThermalExpansion TRUE 65 166 5
411 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingSecure Thermal Expansion ThermalExpansion:material:16 ThermalExpansion TRUE 65 166 5
412 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingUpgrade Thermal Expansion ThermalExpansion:Frame:3 ThermalExpansion TRUE 65 166 5
413 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible Thermal Expansion ThermalExpansion:Machine:4 ThermalExpansion TRUE 65 166 5 2
414 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerFurnace Thermal Expansion ThermalExpansion:Machine:0 ThermalExpansion TRUE 65 166 5
415 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator Thermal Expansion ThermalExpansion:Machine:11 ThermalExpansion TRUE 65 166 5 2
416 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerPulverizer Thermal Expansion ThermalExpansion:Machine:1 ThermalExpansion TRUE 65 166 5
417 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSawmill Thermal Expansion ThermalExpansion:Machine:2 ThermalExpansion TRUE 65 166 5
418 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSmelter Thermal Expansion ThermalExpansion:Machine:3 ThermalExpansion TRUE 65 166 5
419 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer Thermal Expansion ThermalExpansion:Machine:5 ThermalExpansion TRUE 65 166 5 2
420 mekanism.client.nei.ChemicalCrystallizerRecipeHandler Mekanism Mekanism:MachineBlock2:8 Mekanism TRUE 79 4
421 mekanism.client.nei.ChemicalDissolutionChamberRecipeHandler Mekanism Mekanism:MachineBlock2:6 Mekanism TRUE 79 4
422 mekanism.client.nei.ChemicalInfuserRecipeHandler Mekanism Mekanism:MachineBlock2:2 Mekanism TRUE 80 4
437 mekanism.client.nei.SolarNeutronRecipeHandler Mekanism Mekanism:MachineBlock3:1 Mekanism TRUE 70 5
438 mekanism.client.nei.ThermalEvaporationRecipeHandler Mekanism Mekanism:BasicBlock:14 Mekanism TRUE 62 5
439 exnihilo.compatibility.nei.RecipeHandlerHammer Ex Nihilo exnihilo:hammer_iron exnihilo TRUE 58 5
440 exnihilo.compatibility.nei.RecipeHandlerSieve Ex Nihilo exnihilo:sifting_table exnihilo TRUE 130 2 1
441 gregtech.Alloy GregTech-Addon gregtech_addon:machine:56 gregtech_addon TRUE 15 145 166 2
442 gregtech.Assembler GregTech-Addon gregtech_addon:machine:60 gregtech_addon TRUE 15 145 166 2
443 gregtech.Bender GregTech-Addon gregtech_addon:machine:59 gregtech_addon TRUE 15 145 166 2