Compare commits

...
3 Commits
Author SHA1 Message Date
miozune 7834d72ecf RecipeCatalyst Enhancements (#199)
* Fix serial handlers not searching catalysts

* Prevent null stack from being added

* Prevent duplicate stack from being added

* Prevent empty handlerID from being added

* Extract code to get modded items

* Use HANDLER_ID_FUNCTION to determine handler's id
This allows mods that don't implement getOverlayIdentifier to work with

* Implement priority

* Fix typo

* Allow catalysts to be loaded from csv
Add IC2 catalysts

* minor cleanup

* Add Avaritia, BM, Forestry

* Log if TransferRects fail

* Implement removing catalyst

* Add placeholder for version controlling

* Add a BUNCH of catalysts

* Add Schematics

* Add more NASA

* Add way to resolve conflict with handlerID
resolve conflict between IC2 Compressor and Mekanism Osmium Compressor

* Add more catalysts

* Add ALL GT catalysts

* Add more

* temporary "fix" for item rendering
reverts 9bbdd7b174

* enable by default

* forgot this one

* Add ability to skip search for catalysts

* resolve some todos
2022-01-30 17:01:12 +01:00
DrParadox7 3ced04b4d3 Updates Handlers
Adds icons for:
-EtFuturum Requiem
-Modular Powersuits
-Metallurgy 4
-Nuclearcraft

Fixes Nuclearcraft's Workspace recipes not displaying correctly
2022-01-27 08:03:21 -08:00
Jason Mitchell 75c02f0357 Adds a few more methods that weren't implemented and at least one that NEI relied on (addFirst was really the only one I found) 2022-01-26 23:34:29 -08:00
18 changed files with 1639 additions and 117 deletions

No files matched your search

@@ -4,7 +4,6 @@ import codechicken.lib.gui.GuiDraw;
import codechicken.nei.KeyManager.IKeyStateTracker;
import codechicken.nei.api.API;
import codechicken.nei.api.GuiInfo;
import codechicken.nei.api.INEIGuiHandler;
import codechicken.nei.api.IRecipeOverlayRenderer;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.api.LayoutStyle;
@@ -16,7 +15,7 @@ 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 codechicken.nei.recipe.RecipeCatalysts;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
@@ -63,7 +62,6 @@ import static codechicken.nei.NEIClientUtils.getNextGamemode;
import static codechicken.nei.NEIClientUtils.healPlayer;
import static codechicken.nei.NEIClientUtils.isValidGamemode;
import static codechicken.nei.NEIClientUtils.setHourForward;
import static codechicken.nei.NEIClientUtils.setItemQuantity;
import static codechicken.nei.NEIClientUtils.shiftKey;
import static codechicken.nei.NEIClientUtils.toggleMagnetMode;
import static codechicken.nei.NEIClientUtils.toggleRaining;
@@ -360,6 +358,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
} else {
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT || Keyboard.getEventKey() == Keyboard.KEY_RSHIFT)) {
GuiRecipeTab.loadHandlerInfo();
RecipeCatalysts.loadCatalystInfo();
}
getOptionList().openGui(getGuiContainer(), false);
}
@@ -27,8 +27,8 @@ import codechicken.nei.config.OptionUtilities;
import codechicken.nei.event.NEIConfigsLoadedEvent;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.RecipeCatalysts;
import codechicken.nei.recipe.RecipeInfo;
import codechicken.nei.recipe.TemplateRecipeHandler;
import codechicken.obfuscator.ObfuscationRun;
import com.google.common.base.Objects;
import net.minecraft.client.Minecraft;
@@ -62,6 +62,7 @@ public class NEIClientConfig {
new ConfigFile(new File(configDir, "client.cfg")));
public static ConfigSet world;
public static final File handlerFile = new File(configDir, "handlers.csv");
public static final File catalystFile = new File(configDir, "catalysts.csv");
public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg");
public static final File heightHackHandlersFile = new File(configDir, "heighthackhandlers.cfg");
public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv");
@@ -84,11 +85,9 @@ public class NEIClientConfig {
// Function that extracts the handler ID from a handler, with special logic for
// TemplateRecipeHandler: prefer using the overlay ID if it exists.
public static final Function<IRecipeHandler, String> HANDLER_ID_FUNCTION =
handler -> handler instanceof TemplateRecipeHandler
? Objects.firstNonNull(
((TemplateRecipeHandler) handler).getOverlayIdentifier(),
handler.getHandlerId())
: handler.getHandlerId();
handler -> Objects.firstNonNull(
handler.getOverlayIdentifier(),
handler.getHandlerId());
// Comparator that compares handlers using the handlerOrdering map.
public static final Comparator<IRecipeHandler> HANDLER_COMPARATOR =
@@ -202,7 +201,7 @@ public class NEIClientConfig {
API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true));
tag.getTag("inventory.jei_style_item_presence_overlay").setComment("Enable/disable JEI Style item presence overlay on ?-hover").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.jei_style_item_presence_overlay", true));
tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts [experimental]").getBooleanValue(false);
tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true));
@@ -218,6 +217,17 @@ public class NEIClientConfig {
return true;
}
});
tag.getTag("tools.catalyst_load_from_config").setComment("ADVANCED: Load catalysts from config").getBooleanValue(false);
API.addOption(new OptionToggleButton("tools.catalyst_load_from_config", true) {
@Override
public boolean onClick(int button) {
super.onClick(button);
RecipeCatalysts.loadCatalystInfo();
return true;
}
});
setDefaultKeyBindings();
}
@@ -338,6 +348,7 @@ public class NEIClientConfig {
RecipeInfo.load();
LayoutManager.load();
NEIController.load();
RecipeCatalysts.loadCatalystInfo();
configLoaded = true;
@@ -419,6 +430,9 @@ public class NEIClientConfig {
public static boolean loadHandlersFromJar() {
return !getBooleanSetting("tools.handler_load_from_config");
}
public static boolean loadCatalystsFromJar() {
return !getBooleanSetting("tools.catalyst_load_from_config");
}
public static void setEnabled(boolean flag) {
getSetting("inventory.widgetsenabled").setBooleanValue(flag);
@@ -6,13 +6,13 @@ import codechicken.nei.api.IConfigureNEI;
import codechicken.nei.asm.NEICorePlugin;
import codechicken.nei.config.IMCHandler;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.RecipeCatalysts;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.client.FMLFileResourcePack;
import cpw.mods.fml.client.FMLFolderResourcePack;
import cpw.mods.fml.common.DummyModContainer;
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;
@@ -107,6 +107,7 @@ public class NEIModContainer extends DummyModContainer
public void postInit(FMLPostInitializationEvent event) {
if (CommonUtils.isClient()) {
GuiRecipeTab.loadHandlerInfo();
RecipeCatalysts.loadCatalystInfo();
ClientHandler.postInit();
}
}
@@ -5,6 +5,8 @@ import codechicken.core.ServerUtils;
import codechicken.lib.inventory.InventoryRange;
import codechicken.lib.inventory.InventoryUtils;
import codechicken.lib.packet.PacketCustom;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.command.ICommandSender;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.player.EntityPlayer;
@@ -14,6 +16,9 @@ import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTException;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.server.MinecraftServer;
@@ -24,6 +29,7 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraftforge.oredict.OreDictionary;
import org.apache.logging.log4j.Level;
import java.io.File;
import java.io.FileInputStream;
@@ -387,6 +393,50 @@ public class NEIServerUtils
}
}
public static ItemStack getModdedItem(String itemId, String nbtString) {
int meta = -1;
ItemStack itemStack;
if (!itemId.contains(":")) {
NEIClientConfig.logger.info(String.format("Item ID %s is missing colon", itemId));
return null;
}
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.isEmpty()) {
try {
final NBTBase nbttag = JsonToNBT.func_150315_a(nbtString);
if (!(nbttag instanceof NBTTagCompound)) {
NEIClientConfig.logger.info("Unexpected NBT string - multiple values {}", nbtString);
return null;
}
itemStack.setTagCompound((NBTTagCompound) nbttag);
} catch (NBTException e) {
FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e);
return null;
}
}
}
return itemStack;
}
public static NBTTagCompound readNBT(File file) throws IOException {
if(!file.exists()) return null;
FileInputStream in = new FileInputStream(file);
+37 -22
View File
@@ -15,6 +15,7 @@ import codechicken.nei.SubsetWidget.SubsetTag;
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
import codechicken.nei.config.Option;
import codechicken.nei.config.OptionKeyBind;
import codechicken.nei.recipe.CatalystInfo;
import codechicken.nei.recipe.GuiCraftingRecipe;
import codechicken.nei.recipe.GuiUsageRecipe;
import codechicken.nei.recipe.ICraftingHandler;
@@ -299,45 +300,59 @@ public class API
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
* @param handler the recipe category handled by the ingredient
* @param priority higher priority comes first, default to 0
*/
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler) {
addRecipeCatalyst(Collections.singletonList(stack), handler);
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler, int priority) {
String handlerID = RecipeCatalysts.getRecipeID(handler);
addRecipeCatalyst(stack, handlerID, priority);
}
/**
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
* @param stacks the ingredients that can craft recipes (like a furnace or crafting table)
* @param handler the recipe category handled by the ingredient
* See {@link API#addRecipeCatalyst(ItemStack, IRecipeHandler, int)}
*/
public static void addRecipeCatalyst(List<ItemStack> stacks, IRecipeHandler handler) {
String handlerID = handler.getOverlayIdentifier();
if (handlerID != null) {
addRecipeCatalyst(stacks, handler.getOverlayIdentifier());
}
else {
NEIClientConfig.logger.warn(String.format("failed to add recipe catalyst, implement IRecipeHandler#getOverlayIdentifier for your handler %s", handler.getClass().getName()));
}
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler) {
addRecipeCatalyst(stack, handler, 0);
}
/**
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
* @param handlerID recipe category identifier (see {@link IRecipeHandler#getOverlayIdentifier()})
* @param handlerID recipe category identifier (see also {@link RecipeCatalysts#getRecipeID(IRecipeHandler)})
* @param priority higher priority comes first, default to 0
*/
public static void addRecipeCatalyst(ItemStack stack, String handlerID) {
addRecipeCatalyst(Collections.singletonList(stack), handlerID);
public static void addRecipeCatalyst(ItemStack stack, String handlerID, int priority) {
RecipeCatalysts.addRecipeCatalyst(handlerID, new CatalystInfo(stack, priority));
}
/**
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
* @param stacks the ingredients that can craft recipes (like a furnace or crafting table)
* @param handlerID recipe category identifier (see {@link IRecipeHandler#getOverlayIdentifier()})
* See {@link API#addRecipeCatalyst(ItemStack, String, int)}
*/
public static void addRecipeCatalyst(ItemStack stack, String handlerID) {
addRecipeCatalyst(stack, handlerID, 0);
}
public static void removeRecipeCatalyst(ItemStack stack, IRecipeHandler handler) {
String handlerID = RecipeCatalysts.getRecipeID(handler);
removeRecipeCatalyst(stack, handlerID);
}
public static void removeRecipeCatalyst(ItemStack stack, String handlerID) {
RecipeCatalysts.removeRecipeCatalyst(handlerID, stack);
}
@Deprecated
public static void addRecipeCatalyst(List<ItemStack> stacks, IRecipeHandler handler) {
for (ItemStack stack : stacks) {
addRecipeCatalyst(stack, handler);
}
}
@Deprecated
public static void addRecipeCatalyst(List<ItemStack> stacks, String handlerID) {
RecipeCatalysts.addRecipeCatalyst(stacks, handlerID);
for (ItemStack stack : stacks) {
addRecipeCatalyst(stack, handlerID);
}
}
@Deprecated
@@ -194,7 +194,6 @@ public class GuiContainerManager
private static final HashSet<String> stackTraces = new HashSet<>();
public static void drawItem(int i, int j, ItemStack itemstack, FontRenderer fontRenderer, boolean smallAmount) {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
enable3DRender();
float zLevel = drawItems.zLevel += 100F;
try {
@@ -230,7 +229,6 @@ public class GuiContainerManager
enable2DRender();
drawItems.zLevel = zLevel - 100;
GL11.glPopAttrib();
}
//copy from appeng.client.render.AppEngRenderItem
@@ -52,7 +52,98 @@ final class HideousLinkedList<E> extends LinkedList<E> {
public boolean add(E e) {
return backing.add(e);
}
@Override
public void addFirst(E e) {
backing.add(0, e);
}
@Override
public E getFirst() {
if (backing.size() == 0) throw new NoSuchElementException();
return(backing.get(0));
}
@Override
public E removeFirst() {
E item = getFirst();
backing.remove(0);
return item;
}
@Override
public void addLast(E e) {
backing.add(backing.size(), e);
}
@Override
public E getLast() {
if (backing.size() == 0) throw new NoSuchElementException();
return backing.get(backing.size() - 1);
}
@Override
public E removeLast() {
E item = getLast();
backing.remove(backing.size() - 1);
return item;
}
@Override
public E peek() {
return backing.size() > 0 ? backing.get(0) : null;
}
@Override
public E peekFirst() {
return backing.size() > 0 ? getFirst() : null;
}
@Override
public E peekLast() {
return backing.size() > 0 ? getLast() : null;
}
@Override
public E poll() {
return backing.size() > 0 ? removeFirst() : null;
}
@Override
public E pollFirst() {
return poll();
}
@Override
public E pollLast() {
return backing.size() > 0 ? removeLast() : null;
}
@Override
public void push(E e) {
addFirst(e);
}
@Override
public E pop() {
return removeFirst();
}
@Override
public boolean removeFirstOccurrence(Object e) {
return remove(e);
}
@Override
public boolean removeLastOccurrence(Object e) {
int idx = this.backing.lastIndexOf(e);
if (idx != -1) {
this.backing.remove(idx);
return true;
}
return false;
}
@Override
public boolean remove(Object o) {
return backing.remove(o);
@@ -0,0 +1,21 @@
package codechicken.nei.recipe;
import net.minecraft.item.ItemStack;
public class CatalystInfo {
private final ItemStack stack;
private final int priority;
public CatalystInfo(ItemStack stack, int priority) {
this.stack = stack;
this.priority = priority;
}
public ItemStack getStack() {
return stack;
}
public int getPriority() {
return priority;
}
}
@@ -0,0 +1,70 @@
package codechicken.nei.recipe;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import com.google.common.collect.ForwardingList;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// Do not directly extend ArrayList, see Effective Java Item 16
public class CatalystInfoList extends ForwardingList<CatalystInfo> {
private final String handlerID;
private final List<CatalystInfo> catalystInfoList = new ArrayList<>();
public CatalystInfoList(String handlerID) {
this.handlerID = handlerID;
}
public CatalystInfoList(String handlerID, CatalystInfo catalystInfo) {
this(handlerID);
add(catalystInfo);
}
@Override
protected List<CatalystInfo> delegate() {
return catalystInfoList;
}
@Override
public boolean add(@Nonnull CatalystInfo catalystInfo) {
if (contains(catalystInfo)) {
NEIClientConfig.logger.info(String.format("catalyst %s is already registered to handler %s", catalystInfo.getStack().getDisplayName(), handlerID));
return false;
}
super.add(catalystInfo);
return true;
}
@Override
public boolean contains(Object object) {
if (object instanceof CatalystInfo) {
ItemStack stack = ((CatalystInfo) object).getStack();
return contains(stack);
}
return false;
}
public boolean contains(ItemStack stack) {
return catalystInfoList.stream().anyMatch(c -> NEIServerUtils.areStacksSameType(c.getStack(), stack));
}
public boolean remove(ItemStack stack) {
Iterator<CatalystInfo> iter = catalystInfoList.iterator();
while (iter.hasNext()) {
ItemStack next = iter.next().getStack();
if (NEIServerUtils.areStacksSameType(next, stack)) {
iter.remove();
return true;
}
}
return false;
}
public void sort() {
super.sort((c1, c2) -> c2.getPriority() - c1.getPriority());
}
}
@@ -64,7 +64,7 @@ public abstract class GuiRecipeTab extends Widget {
this.handlerName = handler.getHandlerId();
this.guiRecipe = guiRecipe;
this.selected = false;
if(handler instanceof TemplateRecipeHandler) {
handlerID = (((TemplateRecipeHandler)handler).getOverlayIdentifier());
} else {
@@ -207,7 +207,7 @@ public abstract class GuiRecipeTab extends Widget {
} else {
File handlerFile = NEIClientConfig.handlerFile;
if(!handlerFile.exists()) {
NEIClientConfig.logger.info("Config file doesn't exit, creating");
NEIClientConfig.logger.info("Config file doesn't exist, creating");
try {
assert handlerUrl != null;
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
@@ -25,21 +25,14 @@ public class GuiUsageRecipe extends GuiRecipe
profiler.start("recipe.concurrent.usage");
try {
handlers = serialUsageHandlers.stream().map(h -> h.getUsageHandler(inputId, ingredients))
handlers = serialUsageHandlers.stream().map(h -> getUsageOrCatalystHandler(h, inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new));
if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) {
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
.map(h -> h.getUsageAndCatalystHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
} else {
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
.map(h -> h.getUsageHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
}
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
.map(h -> getUsageOrCatalystHandler(h, inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return false;
@@ -76,6 +69,15 @@ public class GuiUsageRecipe extends GuiRecipe
return currenthandlers;
}
private static IUsageHandler getUsageOrCatalystHandler(IUsageHandler handler, String inputId, Object... ingredients) {
boolean skipCatalyst = NEIClientUtils.controlKey();
if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible() && !skipCatalyst) {
return handler.getUsageAndCatalystHandler(inputId, ingredients);
} else {
return handler.getUsageHandler(inputId, ingredients);
}
}
public ArrayList<IUsageHandler> currenthandlers;
public static ArrayList<IUsageHandler> usagehandlers = new ArrayList<>();
@@ -1,6 +1,7 @@
package codechicken.nei.recipe;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.drawable.DrawableBuilder;
import codechicken.nei.drawable.DrawableResource;
import cpw.mods.fml.common.FMLLog;
@@ -53,48 +54,10 @@ public class HandlerInfo {
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 " + handlerName + " - " + 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;
}
}
}
itemStack = NEIServerUtils.getModdedItem(itemId, nbtString);
if (itemStack == null)
NEIClientConfig.logger.info("Couldn't find " + modName + " - " + itemLookupId);
NEIClientConfig.logger.info("Couldn't find " + modName + " - " + itemId);
else {
this.itemId = itemId;
this.nbtString = nbtString;
@@ -3,8 +3,23 @@ package codechicken.nei.recipe;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import com.google.common.base.Objects;
import cpw.mods.fml.common.Loader;
import net.minecraft.item.ItemStack;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.BufferedReader;
import java.io.File;
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.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -12,17 +27,24 @@ import java.util.List;
import java.util.Map;
public class RecipeCatalysts {
private static final Map<String, List<ItemStack>> recipeCatalystMap = new HashMap<>();
private static final Map<String, CatalystInfoList> catalystsAdderFromAPI = new HashMap<>();
private static final Map<String, List<ItemStack>> catalystsRemoverFromAPI = new HashMap<>();
private static final Map<String, CatalystInfoList> recipeCatalystMap = new HashMap<>();
private static Map<String, List<PositionedStack>> positionedRecipeCatalystMap = new HashMap<>();
private static final List<String> forceClassNameList = new ArrayList<>();
private static int heightCache;
public static void addRecipeCatalyst(List<ItemStack> stacks, String handlerID) {
if (handlerID == null) return;
if (recipeCatalystMap.containsKey(handlerID)) {
recipeCatalystMap.get(handlerID).addAll(stacks);
public static void addRecipeCatalyst(String handlerID, CatalystInfo catalystInfo) {
if (handlerID == null || handlerID.isEmpty() || catalystInfo.getStack() == null) return;
addOrPut(catalystsAdderFromAPI, handlerID, catalystInfo);
}
public static void removeRecipeCatalyst(String handlerID, ItemStack stack) {
if (handlerID == null || handlerID.isEmpty() || stack == null) return;
if (catalystsRemoverFromAPI.containsKey(handlerID)) {
catalystsRemoverFromAPI.get(handlerID).add(stack);
} else {
// use ArrayList initializer to prevent UOE
recipeCatalystMap.put(handlerID, new ArrayList<>(stacks));
catalystsRemoverFromAPI.put(handlerID, new ArrayList<>(Collections.singletonList(stack)));
}
}
@@ -31,7 +53,7 @@ public class RecipeCatalysts {
}
public static List<PositionedStack> getRecipeCatalysts(IRecipeHandler handler) {
return getRecipeCatalysts(handler.getOverlayIdentifier());
return getRecipeCatalysts(getRecipeID(handler));
}
public static List<PositionedStack> getRecipeCatalysts(String handlerID) {
@@ -42,25 +64,28 @@ public class RecipeCatalysts {
}
public static boolean containsCatalyst(IRecipeHandler handler, ItemStack candidate) {
return containsCatalyst(handler.getOverlayIdentifier(), candidate);
return containsCatalyst(getRecipeID(handler), candidate);
}
public static boolean containsCatalyst(String handlerID, ItemStack candidate) {
return recipeCatalystMap.getOrDefault(handlerID, Collections.emptyList()).stream()
.anyMatch(s -> NEIServerUtils.areStacksSameType(s, candidate));
if (recipeCatalystMap.containsKey(handlerID)) {
return recipeCatalystMap.get(handlerID).contains(candidate);
}
return false;
}
public static void updatePosition(int availableHeight) {
if (availableHeight == heightCache) return;
public static void updatePosition(int availableHeight, boolean force) {
if (availableHeight == heightCache && !force) return;
Map<String, List<PositionedStack>> newMap = new HashMap<>();
for (Map.Entry<String, List<ItemStack>> entry : recipeCatalystMap.entrySet()) {
List<ItemStack> catalysts = entry.getValue();
for (Map.Entry<String, CatalystInfoList> entry : recipeCatalystMap.entrySet()) {
CatalystInfoList catalysts = entry.getValue();
catalysts.sort();
List<PositionedStack> newStacks = new ArrayList<>();
int rowCount = getRowCount(availableHeight, catalysts.size());
for (int index = 0; index < catalysts.size(); index++) {
ItemStack catalyst = catalysts.get(index);
ItemStack catalyst = catalysts.get(index).getStack();
int column = index / rowCount;
int row = index % rowCount;
newStacks.add(new PositionedStack(catalyst, -column * GuiRecipeCatalyst.ingredientSize, row * GuiRecipeCatalyst.ingredientSize));
@@ -71,6 +96,10 @@ public class RecipeCatalysts {
heightCache = availableHeight;
}
public static void updatePosition(int availableHeight) {
updatePosition(availableHeight, false);
}
public static int getHeight() {
return heightCache;
}
@@ -85,6 +114,143 @@ public class RecipeCatalysts {
return NEIServerUtils.divideCeil(catalystsSize, columnCount);
}
public static void loadCatalystInfo() {
final boolean fromJar = NEIClientConfig.loadCatalystsFromJar();
NEIClientConfig.logger.info("Loading catalyst info from " + (fromJar ? "JAR" : "Config"));
recipeCatalystMap.clear();
URL handlerUrl = Thread.currentThread().getContextClassLoader().getResource("assets/nei/csv/catalysts.csv");
URL url;
if (fromJar) {
url = handlerUrl;
if (url == null) {
NEIClientConfig.logger.warn("Invalid URL for catalysts csv.");
return;
}
} else {
File catalystFile = NEIClientConfig.catalystFile;
if(!catalystFile.exists()) {
NEIClientConfig.logger.info("Config file doesn't exist, creating");
try {
assert handlerUrl != null;
ReadableByteChannel readableByteChannel = Channels.newChannel(handlerUrl.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(catalystFile.getAbsoluteFile());
FileChannel fileChannel = fileOutputStream.getChannel();
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
try {
url = NEIClientConfig.catalystFile.toURI().toURL();
} catch (MalformedURLException e) {
NEIClientConfig.logger.warn("Invalid URL for catalysts csv (via config).");
e.printStackTrace();
return;
}
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(reader);
for (CSVRecord record : csvParser) {
final String handler = record.get("handler");
final String modId = record.get("modId");
final boolean requiresMod = Boolean.parseBoolean(record.get("modRequired"));
final String excludedModId = record.get("excludedModId");
final int priority = intOrDefault(record.get("priority"), 0);
// todo
final String minVersion = record.get("minVersion");
final String maxVersion = record.get("maxVersion");
final boolean forceClassName = Boolean.parseBoolean(record.get("forceClassName"));
if (requiresMod && !Loader.isModLoaded(modId)) continue;
if (excludedModId != null && Loader.isModLoaded(excludedModId)) continue;
String itemName = record.get("itemName");
if (itemName == null || itemName.isEmpty()) continue;
ItemStack stack = NEIServerUtils.getModdedItem(itemName, record.get("nbtInfo"));
if (stack == null) {
NEIClientConfig.logger.warn("Couldn't find ItemStack " + itemName);
continue;
}
CatalystInfo catalystInfo = new CatalystInfo(stack, priority);
String handlerID;
try {
// gently handling copy&paste from handlers.csv
Class<?> clazz = Class.forName(handler);
Object object = clazz.newInstance();
if (object instanceof IRecipeHandler) {
if (forceClassName) {
forceClassNameList.add(handler);
}
handlerID = getRecipeID((IRecipeHandler) object);
} else {
handlerID = handler;
}
} catch (ClassNotFoundException ignored) {
handlerID = handler;
} catch (InstantiationException ignored) {
NEIClientConfig.logger.warn("failed to create instance for " + handler);
handlerID = handler;
}
addOrPut(recipeCatalystMap, handlerID, catalystInfo);
}
} catch (Exception e) {
NEIClientConfig.logger.warn("Error parsing CSV");
e.printStackTrace();
}
for (Map.Entry<String, CatalystInfoList> entry : catalystsAdderFromAPI.entrySet()) {
String handlerID = entry.getKey();
for (CatalystInfo catalyst : entry.getValue()) {
addOrPut(recipeCatalystMap, handlerID, catalyst);
}
}
for (Map.Entry<String, List<ItemStack>> entry : catalystsRemoverFromAPI.entrySet()) {
String handlerID = entry.getKey();
if (recipeCatalystMap.containsKey(handlerID)) {
CatalystInfoList catalysts = recipeCatalystMap.get(handlerID);
entry.getValue().forEach(catalysts::remove);
}
}
updatePosition(getHeight(), true);
}
/**
* Basically {@link NEIClientConfig#HANDLER_ID_FUNCTION}.
* Force using {@link IRecipeHandler#getHandlerId()} if specified in catalysts.csv.
* In other words, refuse to share handlerID defined in {@link TemplateRecipeHandler#getOverlayIdentifier()}.
*/
public static String getRecipeID(IRecipeHandler handler) {
if (forceClassNameList.stream().anyMatch(s -> s.equals(handler.getHandlerId()))) {
return handler.getHandlerId();
}
return Objects.firstNonNull(
handler.getOverlayIdentifier(),
handler.getHandlerId());
}
private static void addOrPut(Map<String, CatalystInfoList> map, String handlerID, CatalystInfo catalyst) {
if (map.containsKey(handlerID)) {
map.get(handlerID).add(catalyst);
} else {
map.put(handlerID, new CatalystInfoList(handlerID, catalyst));
}
}
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;
}
}
@Deprecated
public static void addRecipeCatalyst(List<ItemStack> stacks, Class<? extends IRecipeHandler> handler) {
}
@@ -98,5 +264,4 @@ public class RecipeCatalysts {
public static boolean containsCatalyst(Class<? extends IRecipeHandler> handler, ItemStack candidate) {
return false;
}
}
@@ -10,9 +10,6 @@ import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiCrafting;
import net.minecraft.client.gui.inventory.GuiFurnace;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import java.util.HashMap;
@@ -122,11 +119,6 @@ public class RecipeInfo
API.registerRecipeHandler(new ProfilerRecipeHandler(true));
API.registerUsageHandler(new ProfilerRecipeHandler(false));
API.addRecipeCatalyst(new ItemStack(Blocks.crafting_table), "crafting");
API.addRecipeCatalyst(new ItemStack(Blocks.furnace), new FurnaceRecipeHandler());
API.addRecipeCatalyst(new ItemStack(Items.brewing_stand), new BrewingRecipeHandler());
API.addRecipeCatalyst(new ItemStack(Blocks.furnace), new FuelRecipeHandler());
}
}
@@ -567,6 +567,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
return handler;
}
}
NEIClientConfig.logger.info("failed to load catalyst handler, implement `loadTransferRects` for your handler " + handler.getClass().getName());
}
}
return this.getUsageHandler(inputId, ingredients);
File diff suppressed because it is too large. Load diff
+25 -2
View File
@@ -355,7 +355,7 @@ vazkii.botania.client.integration.nei.recipe.RecipeHandlerRunicAltar,Botania,Bot
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.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,,,,,,
@@ -411,6 +411,7 @@ mekanism.client.nei.ChemicalOxidizerRecipeHandler,Mekanism,Mekanism:MachineBlock
mekanism.client.nei.ChemicalWasherRecipeHandler,Mekanism,Mekanism:MachineBlock2:7,,Mekanism,TRUE,,,70,,5,,,,,,
mekanism.client.nei.CombinerRecipeHandler,Mekanism,Mekanism:MachineBlock:2,,Mekanism,TRUE,,,68,,5,,,,,,
mekanism.client.nei.CrusherRecipeHandler,Mekanism,Mekanism:MachineBlock:3,,Mekanism,TRUE,,,68,,5,,,,,,
mekanism.client.nei.EnrichmentChamberRecipeHandler,Mekanism,Mekanism:MachineBlock:0,,Mekanism,TRUE,,,68,,5,,,,,,
mekanism.client.nei.MetallurgicInfuserRecipeHandler,Mekanism,Mekanism:MachineBlock:8,,Mekanism,TRUE,,,56,,5,,,,,,
mekanism.client.nei.OsmiumCompressorRecipeHandler,Mekanism,Mekanism:MachineBlock:1,,Mekanism,TRUE,,,68,,5,,,,,,
mekanism.client.nei.PRCRecipeHandler,Mekanism,Mekanism:MachineBlock2:10,,Mekanism,TRUE,,,68,,5,,,,,,
@@ -450,4 +451,26 @@ neresources.nei.NEIEnchantmentHandler,Not Enough Resources,minecraft:anvil,,nere
neresources.nei.NEIMobHandler,Not Enough Resources,minecraft:skull:4,,neresources,TRUE,,,130,166,2,,,,,,
neresources.nei.NEIOreHandler,Not Enough Resources,minecraft:diamond_ore,,neresources,TRUE,,,65,166,5,,,,,,
neresources.nei.NEIPlantHandler,Not Enough Resources,minecraft:wheat,,neresources,TRUE,,,130,166,2,,,,,,
wanion.biggercraftingtables.nei.BigShapedRecipeHandler,Bigger Crafting Tables,minecraft:crafting_table,,biggercraftingtables,TRUE,,,130,,2,,,,,,
wanion.biggercraftingtables.nei.BigShapedRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables,,biggercraftingtables,TRUE,,,130,,2,,,,,,
wanion.biggercraftingtables.nei.BigShapelessRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables,,biggercraftingtables,TRUE,,,130,,2,,,,,,
wanion.biggercraftingtables.nei.HugeShapedRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables:1,,biggercraftingtables,TRUE,,,130,,2,,,,,,
wanion.biggercraftingtables.nei.HugeShapelessRecipeHandler,Bigger Crafting Tables,biggercraftingtables:BiggerCraftingTables:1,,biggercraftingtables,TRUE,,,130,,2,,,,,,
net.machinemuse.numina.nei.JSONRecipeHandler,Modular Powersuits,powersuits:tile.tinkerTable,,powersuits,TRUE,,,65,166,5,,,,,,
com.teammetallurgy.metallurgy.nei.CrusherHandler,Metallurgy 4,Metallurgy:crusher,,Metallurgy,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.MetalFurnaceRecipeHandler,NuclearCraft,NuclearCraft:furnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.ElectricFurnaceRecipeHandler,NuclearCraft,NuclearCraft:electricFurnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.NuclearFurnaceRecipeHandler,NuclearCraft,NuclearCraft:nuclearFurnaceIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.FactoryRecipeHandler,NuclearCraft,NuclearCraft:factoryIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.AssemblerRecipeHandler,NuclearCraft,NuclearCraft:assemblerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.SeparatorRecipeHandler,NuclearCraft,NuclearCraft:separatorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.HastenerRecipeHandler,NuclearCraft,NuclearCraft:hastenerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.CollectorRecipeHandler,NuclearCraft,NuclearCraft:collectorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.OxidiserRecipeHandler,NuclearCraft,NuclearCraft:oxidiserIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.IoniserRecipeHandler,NuclearCraft,NuclearCraft:ioniserIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.IrradiatorRecipeHandler,NuclearCraft,NuclearCraft:irradiatorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.CoolerRecipeHandler,NuclearCraft,NuclearCraft:coolerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.HeliumExtractorRecipeHandler,NuclearCraft,NuclearCraft:heliumExtractorIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.RecyclerRecipeHandler,NuclearCraft,NuclearCraft:recyclerIdle,,NuclearCraft,TRUE,,,65,166,5,,,,,,
nc.crafting.nei.NuclearWorkspaceRecipeHandler,NuclearCraft,NuclearCraft:nuclearWorkspace,,NuclearCraft,TRUE,,,130,,2,,,,,,
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker,EtFuturum Requiem,etfuturum:lit_smoker,,etfuturum,TRUE,,,65,166,5,,,,,,
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace,EtFuturum Requiem,etfuturum:lit_blast_furnace,,etfuturum,TRUE,,,65,166,5,,,,,,
1 handler modName itemName nbtInfo modId modRequired excludedModId yShift handlerHeight handlerWidth maxRecipesPerPage imageResource imageX imageY imageWidth imageHeight itemNotes
355 vazkii.botania.client.integration.nei.recipe.RecipeHandlerManaPool Botania Botania:pool Botania TRUE 90 137 4
356 vazkii.botania.client.integration.nei.recipe.RecipeHandlerElvenTrade Botania Botania:alfheimPortal Botania TRUE 90 130 4
357 vazkii.botania.client.integration.nei.recipe.RecipeHandlerBrewery Botania Botania:brewery Botania TRUE 4
358 vazkii.botania.client.integration.nei.recipe.RecipeHandlerPureDaisy Botania Botania:specialFlower {"type": "puredaisy"} {type:puredaisy} Botania TRUE 4
359 vazkii.botania.client.integration.nei.recipe.RecipeHandlerLexicaBotania Botania Botania:lexicon Botania TRUE
360 com.jaquadro.minecraft.storagedrawers.integration.notenoughitems.UpgradeItemRecipeHandler Storage Drawers minecraft:crafting_table StorageDrawers TRUE 65 166 5
361 ieArcFurnace Immersive Engineering ImmersiveEngineering:graphiteElectrode ImmersiveEngineering TRUE 65 166 5
411 mekanism.client.nei.ChemicalWasherRecipeHandler Mekanism Mekanism:MachineBlock2:7 Mekanism TRUE 70 5
412 mekanism.client.nei.CombinerRecipeHandler Mekanism Mekanism:MachineBlock:2 Mekanism TRUE 68 5
413 mekanism.client.nei.CrusherRecipeHandler Mekanism Mekanism:MachineBlock:3 Mekanism TRUE 68 5
414 mekanism.client.nei.EnrichmentChamberRecipeHandler Mekanism Mekanism:MachineBlock:0 Mekanism TRUE 68 5
415 mekanism.client.nei.MetallurgicInfuserRecipeHandler Mekanism Mekanism:MachineBlock:8 Mekanism TRUE 56 5
416 mekanism.client.nei.OsmiumCompressorRecipeHandler Mekanism Mekanism:MachineBlock:1 Mekanism TRUE 68 5
417 mekanism.client.nei.PRCRecipeHandler Mekanism Mekanism:MachineBlock2:10 Mekanism TRUE 68 5
451 neresources.nei.NEIMobHandler Not Enough Resources minecraft:skull:4 neresources TRUE 130 166 2
452 neresources.nei.NEIOreHandler Not Enough Resources minecraft:diamond_ore neresources TRUE 65 166 5
453 neresources.nei.NEIPlantHandler Not Enough Resources minecraft:wheat neresources TRUE 130 166 2
454 wanion.biggercraftingtables.nei.BigShapedRecipeHandler Bigger Crafting Tables minecraft:crafting_table biggercraftingtables:BiggerCraftingTables biggercraftingtables TRUE 130 2
455 wanion.biggercraftingtables.nei.BigShapelessRecipeHandler Bigger Crafting Tables biggercraftingtables:BiggerCraftingTables biggercraftingtables TRUE 130 2
456 wanion.biggercraftingtables.nei.HugeShapedRecipeHandler Bigger Crafting Tables biggercraftingtables:BiggerCraftingTables:1 biggercraftingtables TRUE 130 2
457 wanion.biggercraftingtables.nei.HugeShapelessRecipeHandler Bigger Crafting Tables biggercraftingtables:BiggerCraftingTables:1 biggercraftingtables TRUE 130 2
458 net.machinemuse.numina.nei.JSONRecipeHandler Modular Powersuits powersuits:tile.tinkerTable powersuits TRUE 65 166 5
459 com.teammetallurgy.metallurgy.nei.CrusherHandler Metallurgy 4 Metallurgy:crusher Metallurgy TRUE 65 166 5
460 nc.crafting.nei.MetalFurnaceRecipeHandler NuclearCraft NuclearCraft:furnaceIdle NuclearCraft TRUE 65 166 5
461 nc.crafting.nei.ElectricFurnaceRecipeHandler NuclearCraft NuclearCraft:electricFurnaceIdle NuclearCraft TRUE 65 166 5
462 nc.crafting.nei.NuclearFurnaceRecipeHandler NuclearCraft NuclearCraft:nuclearFurnaceIdle NuclearCraft TRUE 65 166 5
463 nc.crafting.nei.FactoryRecipeHandler NuclearCraft NuclearCraft:factoryIdle NuclearCraft TRUE 65 166 5
464 nc.crafting.nei.AssemblerRecipeHandler NuclearCraft NuclearCraft:assemblerIdle NuclearCraft TRUE 65 166 5
465 nc.crafting.nei.SeparatorRecipeHandler NuclearCraft NuclearCraft:separatorIdle NuclearCraft TRUE 65 166 5
466 nc.crafting.nei.HastenerRecipeHandler NuclearCraft NuclearCraft:hastenerIdle NuclearCraft TRUE 65 166 5
467 nc.crafting.nei.CollectorRecipeHandler NuclearCraft NuclearCraft:collectorIdle NuclearCraft TRUE 65 166 5
468 nc.crafting.nei.OxidiserRecipeHandler NuclearCraft NuclearCraft:oxidiserIdle NuclearCraft TRUE 65 166 5
469 nc.crafting.nei.IoniserRecipeHandler NuclearCraft NuclearCraft:ioniserIdle NuclearCraft TRUE 65 166 5
470 nc.crafting.nei.IrradiatorRecipeHandler NuclearCraft NuclearCraft:irradiatorIdle NuclearCraft TRUE 65 166 5
471 nc.crafting.nei.CoolerRecipeHandler NuclearCraft NuclearCraft:coolerIdle NuclearCraft TRUE 65 166 5
472 nc.crafting.nei.HeliumExtractorRecipeHandler NuclearCraft NuclearCraft:heliumExtractorIdle NuclearCraft TRUE 65 166 5
473 nc.crafting.nei.RecyclerRecipeHandler NuclearCraft NuclearCraft:recyclerIdle NuclearCraft TRUE 65 166 5
474 nc.crafting.nei.NuclearWorkspaceRecipeHandler NuclearCraft NuclearCraft:nuclearWorkspace NuclearCraft TRUE 130 2
475 ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker EtFuturum Requiem etfuturum:lit_smoker etfuturum TRUE 65 166 5
476 ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace EtFuturum Requiem etfuturum:lit_blast_furnace etfuturum TRUE 65 166 5
@@ -120,7 +120,7 @@ nei.options.inventory.jei_style_tabs.false=No [Weirdo]
nei.options.inventory.jei_style_item_presence_overlay=JEI Style Item Overlay on ?-Hover
nei.options.inventory.jei_style_item_presence_overlay.true=Yes
nei.options.inventory.jei_style_item_presence_overlay.false=No
nei.options.inventory.jei_style_recipe_catalyst=JEI Style Recipe Catalysts [experimental]
nei.options.inventory.jei_style_recipe_catalyst=JEI Style Recipe Catalysts
nei.options.inventory.jei_style_recipe_catalyst.true=Yes
nei.options.inventory.jei_style_recipe_catalyst.false=No
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=Save Current Recipe in Bookmarks
@@ -193,6 +193,9 @@ 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.catalyst_load_from_config=Load catalysts from Config
nei.options.tools.catalyst_load_from_config.true=Config
nei.options.tools.catalyst_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