Added fluid support in recipes (#1020)

This commit is contained in:
slprime authored and GitHub committed 2026-09-08 13:41:16 +03:00
1 parent 3f38e6f39b
commit fda7688807
31 files changed
+831 -127

No files matched your search

@@ -1053,7 +1053,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
if (NEIClientUtils.altKey()) {
multiplier = NEIClientConfig.showItemQuantityWidget() ? NEIClientConfig.getItemQuantity() : 0;
if (multiplier == 0) {
multiplier = StackInfo.itemStackToNBT(slot.getItemStack()).hasKey("gtFluidName") ? 144
multiplier = StackInfo.isFluidDisplayItem(slot.getItemStack()) ? 144
: slot.getItemStack().getMaxStackSize();
}
}
@@ -39,7 +39,7 @@ public class ItemCraftablesPanel
public CraftablesGridSlot(int slotIndex, int itemIndex, ItemStack itemStack, RecipeId recipeId) {
super(slotIndex, itemIndex, itemStack);
this.realAmount = StackInfo.getAmount(itemStack);
this.isFluidDisplay = StackInfo.itemStackToNBT(itemStack).hasKey("gtFluidName");
this.isFluidDisplay = StackInfo.isFluidDisplayItem(itemStack);
this.recipeId = recipeId;
}
@@ -86,7 +86,7 @@ public class ItemQuantityField extends TextField {
amount = NEIClientConfig.showItemQuantityWidget() ? NEIClientConfig.getItemQuantity() : 0;
if (amount == 0) {
amount = StackInfo.itemStackToNBT(stack).hasKey("gtFluidName") ? 144 : stack.getMaxStackSize();
amount = StackInfo.isFluidDisplayItem(stack) ? 144 : stack.getMaxStackSize();
}
}
@@ -163,9 +163,10 @@ public class ItemsTooltipLineHandler implements ITooltipLineHandler {
for (Map.Entry<NBTTagCompound, Long> entry : ItemStackAmount.of(items).entrySet()) {
final ItemStack stack = StackInfo.loadFromNBT(entry.getKey(), Math.max(0, entry.getValue()));
if (entry.getKey().hasKey("gtFluidName")) {
if (stack != null && StackInfo.isFluidDisplayItem(stack)) {
stack.stackSize = 0;
}
result.add(stack);
}
@@ -119,11 +119,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
*/
public static boolean itemsLoaded = false;
/**
* Not present, Present
*/
public static Image[] itemPresenceOverlays = new Image[2];
public static void load() {
API.addLayoutStyle(0, new LayoutStyleMinecraft());
@@ -939,17 +934,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
tessellator.addVertexWithUV(x, y, z, u, v);
}
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent, boolean slotHighlight) {
if (slotHighlight) {
NEIClientUtils.gl2DRenderContext(() -> drawRect(slotX, slotY, 16, 16, isPresent ? 0x8000AA00 : 0x80AA0000));
} else {
Image icon = itemPresenceOverlays[isPresent ? 1 : 0];
drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon);
}
}
public static LayoutManager instance() {
return instance;
}
@@ -8,7 +8,6 @@ import org.lwjgl.opengl.GL11;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.api.LayoutStyle;
import codechicken.nei.drawable.DrawableBuilder;
public class LayoutStyleMinecraft extends LayoutStyle {
@@ -38,10 +37,6 @@ public class LayoutStyleMinecraft extends LayoutStyle {
LayoutManager.timeButtons[2].icon = new Image(144, 24, 12, 12);
LayoutManager.timeButtons[3].icon = new Image(156, 24, 12, 12);
LayoutManager.heal.icon = new Image(168, 24, 12, 12);
LayoutManager.itemPresenceOverlays[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 40, 8, 8)
.build();
LayoutManager.itemPresenceOverlays[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8)
.build();
}
@Override
@@ -387,6 +387,13 @@ public class NEIClientConfig {
setFavoriteDefaults(tag);
tag.getTag("inventory.tooltip.showFluidTemperature").setComment("Enabled show Fluid Temperature")
.getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.tooltip.showFluidTemperature", true));
tag.getTag("inventory.tooltip.showFluidState").setComment("Enabled show Fluid State").getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.tooltip.showFluidState", true));
tag.getTag("inventory.itemIDs").getIntValue(1);
API.addOption(new OptionCycled("inventory.itemIDs", 3, true));
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
@@ -41,6 +42,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
@@ -56,6 +58,8 @@ import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.api.GuiInfo;
import codechicken.nei.api.IInfiniteItemHandler;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.recipe.GuiOverlayButton.ItemOverlayState;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.util.NEIKeyboardUtils;
public class NEIClientUtils extends NEIServerUtils {
@@ -293,6 +297,83 @@ public class NEIClientUtils extends NEIServerUtils {
return InventoryUtils.getInsertibleQuantity(new InventoryRange(player.inventory, 0, 36), itemstack) > 0;
}
public static List<ItemOverlayState> presenceOverlay(List<PositionedStack> ingredients, List<ItemStack> invStacks) {
final List<ItemOverlayState> states = new ArrayList<>();
final Map<ItemStack, Long> remainingFluid = new IdentityHashMap<>();
for (PositionedStack stack : ingredients) {
boolean found;
if (StackInfo.isFluidDisplayItem(stack.item)) {
final FluidStack requiredFluid = StackInfo.getFluid(stack.item);
found = requiredFluid != null && consumeFluid(invStacks, remainingFluid, requiredFluid);
} else {
found = false;
for (ItemStack is : invStacks) {
if (is.stackSize > 0 && stack.contains(is)) {
is.stackSize--;
found = true;
break;
}
}
}
states.add(new ItemOverlayState(stack, found));
}
return states;
}
private static boolean consumeFluid(List<ItemStack> invStacks, Map<ItemStack, Long> remainingFluid,
FluidStack requiredFluid) {
long need = requiredFluid.amount;
final List<ItemStack> matched = new ArrayList<>();
for (ItemStack is : invStacks) {
if (need <= 0) {
break;
}
if (is.stackSize <= 0) {
continue;
}
final FluidStack invFluid = StackInfo.getFluid(is);
if (invFluid == null || !invFluid.isFluidEqual(requiredFluid)) {
continue;
}
final long available = remainingFluid.computeIfAbsent(is, k -> (long) invFluid.amount * is.stackSize);
if (available <= 0) {
continue;
}
matched.add(is);
need -= available;
}
if (need > 0) {
return false;
}
long remainingNeed = requiredFluid.amount;
for (ItemStack is : matched) {
final long available = remainingFluid.get(is);
final long consumed = Math.min(available, remainingNeed);
remainingFluid.put(is, available - consumed);
remainingNeed -= consumed;
if (remainingNeed <= 0) {
break;
}
}
return true;
}
public static boolean shiftKey() {
return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
}
@@ -35,6 +35,7 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.OreDictionary;
import org.apache.logging.log4j.Level;
@@ -45,6 +46,7 @@ import codechicken.lib.inventory.InventoryRange;
import codechicken.lib.inventory.InventoryUtils;
import codechicken.lib.packet.PacketCustom;
import codechicken.nei.PacketIDs.S2C;
import codechicken.nei.item.ItemFluidDisplay;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.util.NBTHelper;
import cpw.mods.fml.common.FMLLog;
@@ -442,13 +444,49 @@ public class NEIServerUtils {
throw new RuntimeException(msg);
}
@SuppressWarnings("unchecked")
public static ItemStack[] extractRecipeItems(Object obj) {
if (obj instanceof ItemStack) return new ItemStack[] { (ItemStack) obj };
if (obj instanceof ItemStack[]) return (ItemStack[]) obj;
if (obj instanceof List) return ((List<ItemStack>) obj).toArray(new ItemStack[0]);
throw new ClassCastException(obj + " not an ItemStack, ItemStack[] or List<ItemStack?");
if (obj instanceof ItemStack item) {
return new ItemStack[] { item };
}
if (obj instanceof ItemStack[]arr) {
return arr;
}
if (obj instanceof FluidStack fluid) {
return new ItemStack[] { ItemFluidDisplay.createStack(fluid) };
}
if (obj instanceof FluidStack[]arr) {
final ItemStack[] items = new ItemStack[arr.length];
for (int i = 0; i < items.length; i++) {
items[i] = ItemFluidDisplay.createStack(arr[i]);
}
return items;
}
if (obj instanceof List list) {
final ItemStack[] items = new ItemStack[list.size()];
for (int i = 0; i < items.length; i++) {
items[i] = extractRecipeItem(list.get(i));
}
return items;
}
throw new ClassCastException(
obj + " not an ItemStack, ItemStack[], FluidStack, FluidStack[] or a List of them");
}
private static ItemStack extractRecipeItem(Object obj) {
if (obj == null) return null;
if (obj instanceof ItemStack item) return item;
if (obj instanceof FluidStack fluid) return ItemFluidDisplay.createStack(fluid);
throw new ClassCastException(obj + " not an ItemStack or FluidStack");
}
public static List<Integer> getRange(final int start, final int end) {
@@ -6,11 +6,19 @@ import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.OreDictionary;
import org.lwjgl.opengl.GL11;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.guihook.GuiContainerManager;
@@ -230,9 +238,6 @@ public class PositionedStack implements Cloneable {
return "PositionedStack(output='" + item.toString() + "')";
}
/**
* A {@link PositionedStack} that keeps its items but never draws them.
*/
public static class Placeholder extends PositionedStack {
public Placeholder(Object object, int x, int y, boolean genPerms) {
@@ -246,4 +251,124 @@ public class PositionedStack implements Cloneable {
@Override
public void draw(int mousex, int mousey) {}
}
public static class Fluid extends PositionedStack {
/** The tank size the fill level is measured against, in mB. 0 means "always render full". */
public int capacity = 0;
private ItemStack cachedFluidItem;
private FluidStack cachedFluidStack;
public Fluid(Object object, int x, int y, boolean genPerms) {
super(object, x, y, genPerms);
}
public Fluid(Object object, int x, int y) {
this(object, x, y, true);
}
public Fluid(Object object, int x, int y, int width, int height, int capacity) {
super(object, x, y, false);
this.width = width;
this.height = height;
this.capacity = capacity;
}
protected FluidStack getFluidStack() {
if (this.item != this.cachedFluidItem) {
this.cachedFluidItem = this.item;
this.cachedFluidStack = StackInfo.isFluidDisplayItem(this.item) ? StackInfo.getFluid(this.item) : null;
}
return this.cachedFluidStack;
}
@Override
public List<String> getTooltip() {
final List<String> tooltip = new ArrayList<>();
final List<String> customTooltip = super.getTooltip();
final FluidStack fluidStack = getFluidStack();
if (fluidStack != null) {
tooltip.add(
EnumChatFormatting.GRAY + NEIClientUtils
.translate("recipe.fluid.tank.amount", NEIClientUtils.formatFluid(fluidStack.amount)));
}
if (customTooltip != null) {
tooltip.addAll(customTooltip);
}
return tooltip;
}
@Override
public void draw(int mousex, int mousey) {
final FluidStack fluidStack = getFluidStack();
if (fluidStack == null) {
super.draw(mousex, mousey);
return;
}
final int tankCapacity = this.capacity > 0 ? this.capacity : fluidStack.amount;
int fillHeight = tankCapacity > 0
? (int) ((long) this.height * Math.min(fluidStack.amount, tankCapacity) / tankCapacity)
: 0;
if (fluidStack.amount > 0 && fillHeight <= 0) {
fillHeight = 1;
}
if (fillHeight > 0) {
drawFluid(this.relx, this.rely, this.width, this.height, fillHeight, fluidStack);
}
}
private static void drawFluid(int x, int y, int width, int height, int fillHeight, FluidStack fluidStack) {
final IIcon icon = fluidStack.getFluid().getIcon(fluidStack);
if (icon == null) {
return;
}
final int color = fluidStack.getFluid().getColor(fluidStack);
final float red = (color >> 16 & 0xFF) / 255F;
final float green = (color >> 8 & 0xFF) / 255F;
final float blue = (color & 0xFF) / 255F;
Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
GL11.glColor4f(red, green, blue, 1F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_LIGHTING);
final Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
for (int tx = 0; tx < width; tx += 16) {
final int tileWidth = Math.min(16, width - tx);
final double u2 = icon.getMinU() + (icon.getMaxU() - icon.getMinU()) * tileWidth / 16D;
for (int ty = 0; ty < fillHeight; ty += 16) {
final int tileHeight = Math.min(16, fillHeight - ty);
final double v2 = icon.getMinV() + (icon.getMaxV() - icon.getMinV()) * tileHeight / 16D;
final int bottomY = y + height - ty;
final int topY = bottomY - tileHeight;
tessellator.addVertexWithUV(x + tx, bottomY, 0, icon.getMinU(), v2);
tessellator.addVertexWithUV(x + tx + tileWidth, bottomY, 0, u2, v2);
tessellator.addVertexWithUV(x + tx + tileWidth, topY, 0, u2, icon.getMinV());
tessellator.addVertexWithUV(x + tx, topY, 0, icon.getMinU(), icon.getMinV());
}
}
tessellator.draw();
GL11.glDisable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glColor4f(1F, 1F, 1F, 1F);
}
}
}
@@ -1,15 +1,12 @@
package codechicken.nei.api;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.PositionedStack;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.recipe.GuiOverlayButton.ItemOverlayState;
import codechicken.nei.recipe.IRecipeHandler;
@@ -38,28 +35,14 @@ public interface IOverlayHandler {
}
default List<ItemOverlayState> presenceOverlay(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex) {
final List<ItemOverlayState> itemPresenceSlots = new ArrayList<>();
final List<PositionedStack> ingredients = recipe.getIngredientStacks(recipeIndex);
final List<ItemStack> invStacks = firstGui.inventorySlots.inventorySlots.stream()
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(firstGui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toList());
for (PositionedStack stack : ingredients) {
Optional<ItemStack> used = invStacks.stream().filter(is -> is.stackSize > 0 && stack.contains(is))
.findAny();
itemPresenceSlots.add(new ItemOverlayState(stack, used.isPresent()));
if (used.isPresent()) {
ItemStack is = used.get();
is.stackSize -= 1;
}
}
return itemPresenceSlots;
return NEIClientUtils.presenceOverlay(
recipe.getIngredientStacks(recipeIndex),
firstGui.inventorySlots.inventorySlots.stream()
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(firstGui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toList()));
}
}
@@ -24,4 +24,8 @@ public interface IStackStringifyHandler {
default void pauseItemDamageSound(boolean pause) {}
default boolean isFluidDisplayItem(ItemStack stack) {
return false;
}
}
@@ -60,6 +60,7 @@ import codechicken.nei.config.HandlerDumper;
import codechicken.nei.config.ItemPanelDumper;
import codechicken.nei.config.RegistryDumper;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.item.ItemFluidDisplay;
import codechicken.nei.recipe.BrewingRecipeHandler;
import codechicken.nei.recipe.RecipeItemInputHandler;
import codechicken.nei.search.IdentifierFilter;
@@ -133,6 +134,7 @@ public class ItemInfo {
public static void preInit() {
addMobSpawnerItem();
addFluidDisplayItem();
}
public static void load() {
@@ -318,6 +320,10 @@ public class ItemInfo {
GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.mob_spawner), new ItemMobSpawner());
}
private static void addFluidDisplayItem() {
GameRegistry.registerItem(new ItemFluidDisplay(), "neiFluidDisplay");
}
private static void addInfiniteHandlers() {
API.addInfiniteItemHandler(new InfiniteStackSizeHandler());
API.addInfiniteItemHandler(new InfiniteToolHandler());
@@ -402,6 +408,7 @@ public class ItemInfo {
item -> item.getItem() instanceof ItemArmor armor && armor.armorType == 2);
API.addSubset("Items.Armor.Boots", item -> item.getItem() instanceof ItemArmor armor && armor.armorType == 3);
API.addSubset("Items.Food", item -> item.getItem() instanceof ItemFood);
API.addSubset("Items.Fluids", item -> item.getItem() instanceof ItemFluidDisplay);
API.addSubset("Items.Potions.Ingredients", BrewingRecipeHandler.ingredients);
for (CreativeTabs tab : CreativeTabs.creativeTabArray) {
@@ -24,7 +24,7 @@ import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
import codechicken.nei.ItemPanels;
import codechicken.nei.ItemStackSet;
import codechicken.nei.ItemStackAmount;
import codechicken.nei.ItemsGrid;
import codechicken.nei.ItemsGrid.MouseContext;
import codechicken.nei.LayoutManager;
@@ -913,8 +913,8 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
}
public void addRecipe(Recipe recipe, int multiplier, int groupId) {
final ItemStackSet seenResults = new ItemStackSet();
final ItemStackSet seenIngredients = new ItemStackSet();
final ItemStackAmount seenResults = new ItemStackAmount();
final ItemStackAmount seenIngredients = new ItemStackAmount();
final List<ItemStack> results = new ArrayList<>();
final List<ItemStack> ingredients = new ArrayList<>();
@@ -42,7 +42,7 @@ public class BookmarkItem {
this.groupId = groupId;
this.stack = stack;
this.factor = nbTag.hasKey("gtFluidName") ? Math.min(144, nbTag.getInteger("Count")) : 1;
this.factor = StackInfo.isFluidDisplayItem(stack) ? Math.min(144, nbTag.getInteger("Count")) : 1;
}
public Builder factor(long factor) {
@@ -82,7 +82,7 @@ public class BookmarksGridSlot extends ItemsGridSlot {
this.bookmarkItem = bookmarkItem;
this.isOutputRecipe = group.crafting != null && group.crafting.outputRecipes.contains(bookmarkItem.recipeId);
this.isFluidDisplay = StackInfo.itemStackToNBT(bookmarkItem.itemStack).hasKey("gtFluidName");
this.isFluidDisplay = StackInfo.isFluidDisplayItem(bookmarkItem.itemStack);
this.realMultiplier = realMultiplier;
this.calculatedMultiplier = calculatedMultiplier;
@@ -0,0 +1,92 @@
package codechicken.nei.item;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.fluids.FluidStack;
import org.lwjgl.opengl.GL11;
import codechicken.nei.util.ReadableNumberConverter;
public class FluidDisplayRenderer implements IItemRenderer {
@Override
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
return type == ItemRenderType.INVENTORY;
}
@Override
public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {
return false;
}
@Override
public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
if (type != ItemRenderType.INVENTORY || !(item.getItem() instanceof ItemFluidDisplay fluidDisplay)) {
return;
}
renderIcon(item, fluidDisplay);
renderAmountOverlay(item, fluidDisplay);
}
private void renderIcon(ItemStack item, ItemFluidDisplay fluidDisplay) {
final IIcon icon = fluidDisplay.getIconIndex(item);
if (icon == null) {
return;
}
final int color = fluidDisplay.getColorFromItemStack(item, 0);
final float red = (color >> 16 & 0xFF) / 255F;
final float green = (color >> 8 & 0xFF) / 255F;
final float blue = (color & 0xFF) / 255F;
Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
GL11.glColor4f(red, green, blue, 1F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
final Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV(0, 16, 0, icon.getMinU(), icon.getMaxV());
tessellator.addVertexWithUV(16, 16, 0, icon.getMaxU(), icon.getMaxV());
tessellator.addVertexWithUV(16, 0, 0, icon.getMaxU(), icon.getMinV());
tessellator.addVertexWithUV(0, 0, 0, icon.getMinU(), icon.getMinV());
tessellator.draw();
GL11.glColor4f(1F, 1F, 1F, 1F);
GL11.glDisable(GL11.GL_BLEND);
}
private void renderAmountOverlay(ItemStack item, ItemFluidDisplay fluidDisplay) {
final FluidStack fluidStack = fluidDisplay.getFluid(item);
if (fluidStack == null || fluidStack.amount <= 0) {
return;
}
String amountString = "";
if (fluidStack.amount < 10_000) {
amountString = String.valueOf(fluidStack.amount) + "L";
} else {
amountString = ReadableNumberConverter.INSTANCE.toWideReadableForm(fluidStack.amount) + "L";
}
final FontRenderer fontRender = Minecraft.getMinecraft().fontRenderer;
float smallTextScale = fontRender.getUnicodeFlag() ? 3F / 4F : 1F / 2F;
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPushMatrix();
GL11.glScalef(smallTextScale, smallTextScale, 1.0f);
fontRender
.drawString(amountString, 0, (int) (16 / smallTextScale) - fontRender.FONT_HEIGHT + 1, 0xFFFFFF, true);
GL11.glPopMatrix();
GL11.glPopAttrib();
}
}
@@ -0,0 +1,196 @@
package codechicken.nei.item;
import java.util.List;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidContainerItem;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class ItemFluidDisplay extends Item implements IFluidContainerItem {
public static ItemFluidDisplay INSTANCE;
public final static CreativeTabs tabFluids = new CreativeTabs("neiFluids") {
@Override
public Item getTabIconItem() {
return INSTANCE;
}
@Override
@SideOnly(Side.CLIENT)
public ItemStack getIconItemStack() {
return createStack(new FluidStack(FluidRegistry.WATER, 0));
}
};
public ItemFluidDisplay() {
setMaxStackSize(1);
setUnlocalizedName("nei.fluidDisplay");
INSTANCE = this;
setCreativeTab(tabFluids);
MinecraftForgeClient.registerItemRenderer(this, new FluidDisplayRenderer());
}
public static ItemStack createStack(FluidStack fluidStack) {
if (fluidStack == null || fluidStack.getFluid() == null) {
return null;
}
int fluidId;
try {
fluidId = FluidRegistry.getFluidID(fluidStack.getFluid());
} catch (Exception e) {
NEIClientConfig.logger.error("Failed to get fluid id for: " + fluidStack.getFluid().getName(), e);
return null;
}
final ItemStack stack = new ItemStack(INSTANCE, 1, fluidId);
final NBTTagCompound nbtTag = new NBTTagCompound();
if (fluidStack.tag != null) {
nbtTag.setTag("FluidTag", fluidStack.tag.copy());
}
nbtTag.setInteger("neiFluidDisplayAmount", fluidStack.amount);
stack.setTagCompound(nbtTag);
return stack;
}
@Override
public FluidStack getFluid(ItemStack stack) {
if (stack == null || !(stack.getItem() instanceof ItemFluidDisplay) || !stack.hasTagCompound()) {
return null;
}
final Fluid fluid = FluidRegistry.getFluid(stack.getItemDamage());
if (fluid == null) {
return null;
}
final NBTTagCompound nbTag = stack.getTagCompound();
final FluidStack fluidStack = new FluidStack(fluid, nbTag.getInteger("neiFluidDisplayAmount"));
if (nbTag.hasKey("FluidTag")) {
fluidStack.tag = nbTag.getCompoundTag("FluidTag");
}
return fluidStack;
}
@Override
public int getCapacity(ItemStack stack) {
if (stack == null || !(stack.getItem() instanceof ItemFluidDisplay) || !stack.hasTagCompound()) {
return 0;
}
return stack.getTagCompound().getInteger("neiFluidDisplayAmount");
}
@Override
public int fill(ItemStack container, FluidStack resource, boolean doFill) {
return 0;
}
@Override
public FluidStack drain(ItemStack container, int maxDrain, boolean doDrain) {
return null;
}
@Override
public IIcon getIconFromDamage(int metadata) {
final Fluid fluid = FluidRegistry.getFluid(metadata);
final IIcon icon = fluid != null ? fluid.getStillIcon() : null;
return icon != null ? icon : FluidRegistry.WATER.getStillIcon();
}
@Override
public int getSpriteNumber() {
return 0;
}
@Override
public int getColorFromItemStack(ItemStack stack, int renderPass) {
final Fluid fluid = stack != null ? FluidRegistry.getFluid(stack.getItemDamage()) : null;
return fluid != null ? fluid.getColor() : 0xFFFFFF;
}
@Override
public String getItemStackDisplayName(ItemStack stack) {
final Fluid fluid = stack != null ? FluidRegistry.getFluid(stack.getItemDamage()) : null;
return fluid != null ? fluid.getLocalizedName() : super.getItemStackDisplayName(stack);
}
@Override
public String getUnlocalizedName(ItemStack stack) {
final Fluid fluid = stack != null ? FluidRegistry.getFluid(stack.getItemDamage()) : null;
return fluid != null ? fluid.getUnlocalizedName() : super.getUnlocalizedName(stack);
}
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, EntityPlayer player, List<String> tooltip, boolean advanced) {
final Fluid fluid = FluidRegistry.getFluid(stack.getItemDamage());
if (fluid == null) {
return;
}
if (NEIClientConfig.getBooleanSetting("inventory.tooltip.showFluidTemperature")) {
tooltip.add(
EnumChatFormatting.RED + NEIClientUtils.translate(
"inventory.tooltip.temperature.fluid",
NEIClientUtils.formatNumber(fluid.getTemperature())));
}
if (NEIClientConfig.getBooleanSetting("inventory.tooltip.showFluidState")) {
tooltip.add(
EnumChatFormatting.GREEN + NEIClientUtils.translate(
"inventory.tooltip.state.fluid",
NEIClientUtils.translate(
fluid.isGaseous() ? "inventory.tooltip.state.fluid.gas"
: "inventory.tooltip.state.fluid.liquid")));
}
}
@Override
public void registerIcons(IIconRegister register) {}
@Override
@SideOnly(Side.CLIENT)
public void getSubItems(Item aItem, CreativeTabs aTab, List<ItemStack> aList) {
for (int i = 0, j = FluidRegistry.getMaxID(); i < j; i++) {
final Fluid fluid = FluidRegistry.getFluid(i);
if (fluid == null) {
continue;
}
final ItemStack stack = ItemFluidDisplay.createStack(new FluidStack(fluid, 0));
if (stack != null) {
aList.add(stack);
}
}
}
}
@@ -29,6 +29,15 @@ import codechicken.nei.util.NEIMouseUtils;
public class GuiOverlayButton extends GuiRecipeButton {
protected static DrawableResource notPresent = new DrawableBuilder(
"nei:textures/nei_tabbed_sprites.png",
0,
40,
8,
8).build();
protected static DrawableResource present = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8)
.build();
public enum ItemOverlayFormat {
BACKGROUND,
@@ -58,11 +67,23 @@ public class GuiOverlayButton extends GuiRecipeButton {
}
public void draw(ItemOverlayFormat format) {
LayoutManager.drawItemPresenceOverlay(
this.slot.relx,
this.slot.rely,
this.isPresent,
format == ItemOverlayFormat.BACKGROUND);
if (format == ItemOverlayFormat.BACKGROUND) {
NEIClientUtils.gl2DRenderContext(
() -> drawRect(
this.slot.relx,
this.slot.rely,
this.slot.width,
this.slot.height,
isPresent ? 0x8000AA00 : 0x80AA0000));
} else {
final DrawableResource icon = isPresent ? present : notPresent;
LayoutManager.drawIcon(
this.slot.relx + this.slot.width - icon.width,
this.slot.rely + this.slot.height - icon.height,
icon);
}
}
}
@@ -256,6 +277,11 @@ public class GuiOverlayButton extends GuiRecipeButton {
return this.itemPresenceCache;
}
@Override
public void onPermutationsChanged() {
this.itemPresenceCache.clear();
}
public void setRequireShiftForOverlayRecipe(boolean require) {
this.requireShiftForOverlayRecipe = require;
updateEnabled();
@@ -291,30 +317,15 @@ public class GuiOverlayButton extends GuiRecipeButton {
}
protected List<ItemOverlayState> presenceOverlay(List<PositionedStack> ingredients) {
final List<ItemOverlayState> states = new ArrayList<>();
final List<ItemStack> invStacks = this.firstGui.inventorySlots.inventorySlots.stream()
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(this.firstGui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toCollection(ArrayList::new));
for (PositionedStack stack : ingredients) {
boolean found = false;
for (ItemStack is : invStacks) {
if (is.stackSize > 0 && stack.contains(is)) {
is.stackSize--;
found = true;
break;
}
}
states.add(new ItemOverlayState(stack, found));
}
return states;
return NEIClientUtils.presenceOverlay(
ingredients,
this.firstGui.inventorySlots.inventorySlots.stream()
.filter(
s -> s != null && s.getStack() != null
&& s.getStack().stackSize > 0
&& s.isItemValid(s.getStack())
&& s.canTakeStack(this.firstGui.mc.thePlayer))
.map(s -> s.getStack().copy()).collect(Collectors.toList()));
}
public void overlayRecipe(boolean shift) {
@@ -65,6 +65,10 @@ public abstract class GuiRecipeButton extends GuiNEIButton {
}
public void onPermutationsChanged() {
}
public boolean mouseScrolled(int scroll) {
return false;
}
@@ -175,6 +175,10 @@ public class NEIRecipeWidget extends Widget {
if (!NEIClientUtils.shiftKey() && ((this.cycleticks++) / 20) != this.lastcycle || this.lastcycle == -1) {
this.lastcycle = this.cycleticks / 20;
updatePermutations();
for (GuiRecipeButton button : getRecipeButtonsIfInit()) {
button.onPermutationsChanged();
}
}
for (GuiRecipeButton button : getRecipeButtons()) {
@@ -21,6 +21,7 @@ import codechicken.nei.LRUCache;
import codechicken.nei.api.IStackStringifyHandler;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler;
import codechicken.nei.recipe.stackinfo.FluidDisplayStackStringifyHandler;
import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler;
import codechicken.nei.util.ItemStackKey;
import codechicken.nei.util.NBTHelper;
@@ -36,6 +37,7 @@ public class StackInfo {
static {
stackStringifyHandlers.add(new DefaultStackStringifyHandler());
stackStringifyHandlers.add(new FluidDisplayStackStringifyHandler());
stackStringifyHandlers.add(new GTFluidStackStringifyHandler());
}
@@ -86,6 +88,19 @@ public class StackInfo {
return result == null ? stack : result;
}
public static boolean isFluidDisplayItem(ItemStack stack) {
if (stack == null) {
return false;
}
for (int i = stackStringifyHandlers.size() - 1; i >= 0; i--) {
if (stackStringifyHandlers.get(i).isFluidDisplayItem(stack)) {
return true;
}
}
return false;
}
public static void pauseItemDamageSound(boolean pause) {
if (isPausedItemDamageSound != (isPausedItemDamageSound = pause)) {
for (IStackStringifyHandler handler : stackStringifyHandlers) {
@@ -40,7 +40,7 @@ public class LabelWidget extends Widget implements IUpdatableWidget {
@Override
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
if (contains(mx, my)) {
if (contains(mx, my) && this.value != null) {
tooltip.add(this.value);
}
@@ -1,9 +1,14 @@
package codechicken.nei.recipe.stackinfo;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidContainerItem;
@@ -49,8 +54,24 @@ public class DefaultStackStringifyHandler implements IStackStringifyHandler {
public FluidStack getFluid(ItemStack stack) {
FluidStack fluidStack = FluidContainerRegistry.getFluidForFilledItem(stack);
if (fluidStack == null && stack.getItem() instanceof IFluidContainerItem) {
fluidStack = ((IFluidContainerItem) stack.getItem()).getFluid(stack);
if (fluidStack == null && stack.getItem() instanceof IFluidContainerItem container) {
fluidStack = container.getFluid(stack);
}
if (fluidStack == null && Block.getBlockFromItem(stack.getItem()) instanceof BlockLiquid liquidBlock) {
Fluid fluid = FluidRegistry.lookupFluidForBlock(liquidBlock);
if (fluid == null) {
if (liquidBlock.getMaterial() == Material.water) {
fluid = FluidRegistry.WATER;
} else if (liquidBlock.getMaterial() == Material.lava) {
fluid = FluidRegistry.LAVA;
}
}
if (fluid != null) {
fluidStack = new FluidStack(fluid, FluidContainerRegistry.BUCKET_VOLUME);
}
}
return fluidStack;
@@ -0,0 +1,77 @@
package codechicken.nei.recipe.stackinfo;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import codechicken.nei.api.IStackStringifyHandler;
import codechicken.nei.item.ItemFluidDisplay;
public class FluidDisplayStackStringifyHandler implements IStackStringifyHandler {
public static final String NBT_FLUID_NAME = "neiFluidName";
@Override
public boolean isFluidDisplayItem(ItemStack stack) {
return stack.getItem() instanceof ItemFluidDisplay;
}
@Override
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize) {
if (!(stack.getItem() instanceof ItemFluidDisplay)) {
return null;
}
final FluidStack fluidStack = ((ItemFluidDisplay) stack.getItem()).getFluid(stack);
if (fluidStack == null) {
return null;
}
final NBTTagCompound nbTag = new NBTTagCompound();
nbTag.setString(NBT_FLUID_NAME, fluidStack.getFluid().getName());
nbTag.setInteger("Count", saveStackSize ? fluidStack.amount : 1);
if (fluidStack.tag != null) {
nbTag.setTag("FluidTag", fluidStack.tag.copy());
}
return nbTag;
}
@Override
public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag) {
if (!nbtTag.hasKey(NBT_FLUID_NAME)) {
return null;
}
final Fluid fluid = FluidRegistry.getFluid(nbtTag.getString(NBT_FLUID_NAME));
if (fluid == null) {
return null;
}
final FluidStack fluidStack = new FluidStack(fluid, nbtTag.getInteger("Count"));
if (nbtTag.hasKey("FluidTag")) {
fluidStack.tag = nbtTag.getCompoundTag("FluidTag");
}
return ItemFluidDisplay.createStack(fluidStack);
}
@Override
public FluidStack getFluid(ItemStack stack) {
if (stack.getItem() instanceof ItemFluidDisplay fluidDisplay) {
return fluidDisplay.getFluid(stack);
}
return null;
}
}
@@ -11,13 +11,13 @@ import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import codechicken.nei.api.IStackStringifyHandler;
import codechicken.nei.item.ItemFluidDisplay;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.relauncher.ReflectionHelper;
public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
protected static Class<?> itemFluidDisplay = null;
protected static Method getFluidDisplayStack = null;
protected static Method getFluidFromDisplayStack = null;
protected static Class<?> gtMetaGeneratedTool = null;
protected static Field playSound = null;
@@ -33,7 +33,6 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
"gregtech.common.items.ItemFluidDisplay",
"gregtech.common.items.GT_FluidDisplayItem");
getFluidFromDisplayStack = gtUtility.getMethod("getFluidFromDisplayStack", ItemStack.class);
getFluidDisplayStack = gtUtility.getMethod("getFluidDisplayStack", FluidStack.class, boolean.class);
gtMetaGeneratedTool = ReflectionHelper.getClass(
loader,
@@ -45,14 +44,15 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
}
}
@Override
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize) {
if (stack.getItem() != GameRegistry.findItem("ae2fc", "fluid_drop")) {
if (stack != null && isFluidDisplayItem(stack)) {
final FluidStack fluidStack = getFluid(stack);
if (fluidStack != null) {
final NBTTagCompound nbTag = new NBTTagCompound();
nbTag.setString("gtFluidName", fluidStack.getFluid().getName());
nbTag.setString(FluidDisplayStackStringifyHandler.NBT_FLUID_NAME, fluidStack.getFluid().getName());
nbTag.setInteger("Count", saveStackSize ? fluidStack.amount : 144);
return nbTag;
}
@@ -61,23 +61,23 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
return null;
}
@Override
public ItemStack convertNBTToItemStack(NBTTagCompound nbtTag) {
if (getFluidDisplayStack != null && nbtTag.hasKey("gtFluidName")) {
if (nbtTag.hasKey("gtFluidName")) {
final String fluidName = nbtTag.getString("gtFluidName");
final Fluid fluid = FluidRegistry.getFluid(fluidName);
final int amount = nbtTag.getInteger("Count");
if (fluid != null) {
try {
return (ItemStack) getFluidDisplayStack.invoke(null, new FluidStack(fluid, amount), true);
} catch (Exception e) {}
return ItemFluidDisplay.createStack(new FluidStack(fluid, amount));
}
}
return null;
}
@Override
public FluidStack getFluid(ItemStack stack) {
final Item item = stack.getItem();
@@ -110,6 +110,7 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
return null;
}
@Override
public ItemStack normalizeRecipeQueryStack(ItemStack stack) {
if (stack.getItem() == GameRegistry.findItem("ae2fc", "fluid_drop")
@@ -117,9 +118,7 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
final FluidStack fluidStack = getFluid(stack);
if (fluidStack != null) {
try {
return (ItemStack) getFluidDisplayStack.invoke(null, fluidStack, true);
} catch (Exception e) {}
return ItemFluidDisplay.createStack(fluidStack);
}
}
@@ -136,4 +135,11 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
}
@Override
public boolean isFluidDisplayItem(ItemStack stack) {
final Item item = stack.getItem();
return (itemFluidDisplay != null && itemFluidDisplay.isInstance(item))
|| item == GameRegistry.findItem("ae2fc", "fluid_packet");
}
}
@@ -1,13 +1,17 @@
package codechicken.nei.search;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.item.ItemFluidDisplay;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.registry.GameRegistry;
@@ -15,6 +19,7 @@ import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
public class ModNameFilter implements ItemFilter {
private static final Map<String, String> fluidOwners = new HashMap<>();
private final Pattern pattern;
public ModNameFilter(Pattern pattern) {
@@ -23,31 +28,52 @@ public class ModNameFilter implements ItemFilter {
@Override
public boolean matches(ItemStack itemStack) {
return this.pattern.matcher(nameFromStack(itemStack.getItem())).find();
return this.pattern.matcher(nameFromStack(itemStack)).find();
}
protected static String nameFromStack(Item item) {
protected static String nameFromStack(ItemStack itemStack) {
try {
ModContainer mod = Loader.instance().getIndexedModList().get(getModId(item));
ModContainer mod = Loader.instance().getIndexedModList().get(getModId(itemStack));
return mod == null ? "Minecraft" : mod.getName();
} catch (NullPointerException e) {
} catch (Throwable e) {
return "";
}
}
protected static String getModId(Item item) {
protected static String getModId(ItemStack itemStack) {
if (!ItemInfo.itemOwners.containsKey(item)) {
if (itemStack.getItem() instanceof ItemFluidDisplay fluidDisplay) {
return getFluidModId(fluidDisplay, itemStack);
}
if (!ItemInfo.itemOwners.containsKey(itemStack.getItem())) {
try {
UniqueIdentifier ident = GameRegistry.findUniqueIdentifierFor(item);
ItemInfo.itemOwners.put(item, ident.modId);
final UniqueIdentifier identifier = GameRegistry.findUniqueIdentifierFor(itemStack.getItem());
ItemInfo.itemOwners.put(itemStack.getItem(), identifier.modId);
} catch (Exception ignored) {
NEIClientConfig.logger.error("Failed to find identifier for: " + item);
ItemInfo.itemOwners.put(item, "Unknown");
NEIClientConfig.logger.error("Failed to find identifier for: " + itemStack.getItem());
ItemInfo.itemOwners.put(itemStack.getItem(), "Unknown");
}
}
return ItemInfo.itemOwners.get(item);
return ItemInfo.itemOwners.get(itemStack.getItem());
}
private static String getFluidModId(ItemFluidDisplay fluidDisplay, ItemStack itemStack) {
final Fluid fluid = FluidRegistry.getFluid(itemStack.getItemDamage());
final String fluidName = FluidRegistry.getDefaultFluidName(fluid);
if (!fluidOwners.containsKey(fluidName)) {
try {
final UniqueIdentifier identifier = new UniqueIdentifier(fluidName);
fluidOwners.put(fluidName, identifier.modId);
} catch (Exception ignored) {
NEIClientConfig.logger.error("Failed to find identifier for fluid: " + fluidName);
fluidOwners.put(fluidName, "Unknown");
}
}
return fluidOwners.get(fluidName);
}
}
@@ -25,4 +25,6 @@ minecraft:record_
#splash potion
minecraft:potion 16000-17000
#lingering potion
minecraft:potion 8000-9000
minecraft:potion 8000-9000
#fluid display
neifluiddisplay
@@ -44,14 +44,14 @@ com.rwtema.extrautils.nei.InfoHandler,Extra Utilities,ExtraUtilities:chandelier,
com.rwtema.extrautils.nei.MicroBlocksHandler,Extra Utilities,ExtraUtilities:microblocks:1,,ExtraUtilities,TRUE,,,,,,,,,,,,
com.rwtema.extrautils.nei.SoulHandler,Extra Utilities,ExtraUtilities:mini-soul,,ExtraUtilities,TRUE,,,,,,,,,,,,
hellfirepvp.beebetteratbees.client.gui.BBABGuiRecipeTreeHandler,Bees,Forestry:beeQueenGE,,Forestry,TRUE,,,140,,2,,,,,,,
forestry.factory.recipes.nei.NEIHandlerBottler,Forestry for Minecraft,Forestry:factory,,Forestry,TRUE,,,84,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerCarpenter,Forestry for Minecraft,Forestry:factory:1,,Forestry,TRUE,,,81,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerBottler,Forestry for Minecraft,Forestry:factory,,Forestry,TRUE,,,71,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerCarpenter,Forestry for Minecraft,Forestry:factory:1,,Forestry,TRUE,,,95,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerCentrifuge,Forestry for Minecraft,Forestry:factory:2,,Forestry,TRUE,,,81,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerFabricator,Forestry for Minecraft,Forestry:factory2,,Forestry,TRUE,,,,,,,,,,,,
forestry.factory.recipes.nei.NEIHandlerFermenter,Forestry for Minecraft,Forestry:factory:3,,Forestry,TRUE,,,81,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerMoistener,Forestry for Minecraft,Forestry:factory:4,,Forestry,TRUE,,,84,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerSqueezer,Forestry for Minecraft,Forestry:factory:5,,Forestry,TRUE,,,84,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerStill,Forestry for Minecraft,Forestry:factory:6,,Forestry,TRUE,,,81,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerFermenter,Forestry for Minecraft,Forestry:factory:3,,Forestry,TRUE,,2,69,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerMoistener,Forestry for Minecraft,Forestry:factory:4,,Forestry,TRUE,,1,70,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerSqueezer,Forestry for Minecraft,Forestry:factory:5,,Forestry,TRUE,,,98,,5,,,,,,,
forestry.factory.recipes.nei.NEIHandlerStill,Forestry for Minecraft,Forestry:factory:6,,Forestry,TRUE,,2,69,,5,,,,,,,
net.bdew.neiaddons.forestry.bees.BeeBreedingHandler,Forestry for Minecraft,Forestry:beeQueenGE,,Forestry,TRUE,,,65,,5,,,,,,,
net.bdew.neiaddons.forestry.bees.BeeProduceHandler,Forestry for Minecraft,Forestry:beeQueenGE,,Forestry,TRUE,,,65,,5,,,,,,,
net.bdew.neiaddons.forestry.butterflies.ButterflyBreedingHandler,Forestry for Minecraft,Forestry:butterflyGE,,Forestry,TRUE,,,,,,,,,,,,
1 handler modName itemName nbtInfo modId modRequired excludedModId yShift handlerHeight handlerWidth maxRecipesPerPage imageResource imageX imageY imageWidth imageHeight itemNotes useCustomScroll
44 com.rwtema.extrautils.nei.MicroBlocksHandler Extra Utilities ExtraUtilities:microblocks:1 ExtraUtilities TRUE
45 com.rwtema.extrautils.nei.SoulHandler Extra Utilities ExtraUtilities:mini-soul ExtraUtilities TRUE
46 hellfirepvp.beebetteratbees.client.gui.BBABGuiRecipeTreeHandler Bees Forestry:beeQueenGE Forestry TRUE 140 2
47 forestry.factory.recipes.nei.NEIHandlerBottler Forestry for Minecraft Forestry:factory Forestry TRUE 84 71 5
48 forestry.factory.recipes.nei.NEIHandlerCarpenter Forestry for Minecraft Forestry:factory:1 Forestry TRUE 81 95 5
49 forestry.factory.recipes.nei.NEIHandlerCentrifuge Forestry for Minecraft Forestry:factory:2 Forestry TRUE 81 5
50 forestry.factory.recipes.nei.NEIHandlerFabricator Forestry for Minecraft Forestry:factory2 Forestry TRUE
51 forestry.factory.recipes.nei.NEIHandlerFermenter Forestry for Minecraft Forestry:factory:3 Forestry TRUE 2 81 69 5
52 forestry.factory.recipes.nei.NEIHandlerMoistener Forestry for Minecraft Forestry:factory:4 Forestry TRUE 1 84 70 5
53 forestry.factory.recipes.nei.NEIHandlerSqueezer Forestry for Minecraft Forestry:factory:5 Forestry TRUE 84 98 5
54 forestry.factory.recipes.nei.NEIHandlerStill Forestry for Minecraft Forestry:factory:6 Forestry TRUE 2 81 69 5
55 net.bdew.neiaddons.forestry.bees.BeeBreedingHandler Forestry for Minecraft Forestry:beeQueenGE Forestry TRUE 65 5
56 net.bdew.neiaddons.forestry.bees.BeeProduceHandler Forestry for Minecraft Forestry:beeQueenGE Forestry TRUE 65 5
57 net.bdew.neiaddons.forestry.butterflies.ButterflyBreedingHandler Forestry for Minecraft Forestry:butterflyGE Forestry TRUE
@@ -123,7 +123,14 @@ nei.inventory.current.gamemode.2=Current gamemode: creative+
nei.inventory.current.gamemode.3=Current gamemode: adventure
nei.inventory.tooltip.page=Page: %s / %s [Press %s to see next page]
nei.inventory.tooltip.count.item=Count: %s
itemGroup.neiFluids=Fluids
nei.inventory.tooltip.count.fluid=Amount: %s
nei.inventory.tooltip.temperature.fluid=Temperature: %sK
nei.inventory.tooltip.state.fluid=State: %s
nei.inventory.tooltip.state.fluid.gas=Gas
nei.inventory.tooltip.state.fluid.liquid=Liquid
nei.inventory.gamemode.0=Click: Set gamemode to survival
nei.inventory.gamemode.1=Click: Set gamemode to creative
@@ -486,6 +493,14 @@ nei.options.inventory.itemUntranslator=Item Untranslator
nei.options.inventory.itemUntranslator.true=Enabled
nei.options.inventory.itemUntranslator.false=Disabled
nei.options.inventory.tooltip=Tooltips
nei.options.inventory.tooltip.showFluidTemperature=Show Fluid Temperature
nei.options.inventory.tooltip.showFluidTemperature.true=Yes
nei.options.inventory.tooltip.showFluidTemperature.false=No
nei.options.inventory.tooltip.showFluidState=Show Fluid State
nei.options.inventory.tooltip.showFluidState.true=Yes
nei.options.inventory.tooltip.showFluidState.false=No
nei.options.command=Commands
nei.options.command.creative=Gamemode
nei.options.command.creative.tip={0} = 1 for creative, 0 for survival, {1} = player
@@ -576,6 +591,7 @@ nei.debug.RecipeHandler.reset=Reset
nei.recipe.page=Page %s/%s
nei.recipe.tooltip=Recipes
nei.recipe.fluid.tank.amount=Amount: %s
nei.recipe.tab.view_all.tooltip=View all categories
nei.recipe.search.tooltip.name=Filter Syntax
nei.recipe.search.tooltip.shift=§7Hold §6Shift§7 for more info
@@ -674,6 +690,7 @@ nei.subsets.Items.Armor.Boots=Boots
nei.subsets.Items.Armor.Chestplates=Chestplates
nei.subsets.Items.Armor.Helmets=Helmets
nei.subsets.Items.Armor.Leggings=Leggings
nei.subsets.Items.Fluids=Fluids
nei.subsets.Items.Food=Food
nei.subsets.Items.Potions=Potions
nei.subsets.Items.Potions.Ingredients=Ingredients
@@ -84,6 +84,13 @@ nei.inventory.current.gamemode.2=Текущий режим игры: творч
nei.inventory.current.gamemode.3=Текущий режим игры: приключение
nei.inventory.tooltip.page=Страница: %s / %s [Нажмите %s для перехода на следующую страницу]
itemGroup.neiFluids=Жидкости
nei.inventory.tooltip.temperature.fluid=Температура: %sK
nei.inventory.tooltip.state.fluid=Состояние: %s
nei.inventory.tooltip.state.fluid.gas=Газ
nei.inventory.tooltip.state.fluid.liquid=Жидкость
nei.inventory.gamemode.0=Клик: Установить режим игры на выживание
nei.inventory.gamemode.1=Клик: Установить режим игры на творческий
nei.inventory.gamemode.2=Клик: Установить режим игры на творческий+
@@ -444,6 +451,7 @@ nei.subsets.Items.Armor.Boots=Ботинки
nei.subsets.Items.Armor.Chestplates=Нагрудники
nei.subsets.Items.Armor.Helmets=Шлемы
nei.subsets.Items.Armor.Leggings=Поножи
nei.subsets.Items.Fluids=Жидкости
nei.subsets.Items.Food=Еда
nei.subsets.Items.Potions=Зелья
nei.subsets.Items.Potions.Ingredients=Ингредиенты