Compare commits

...
Author SHA1 Message Date
Martin Robertz 2fa641c2aa Merge remote-tracking branch 'origin/recipe-catalyst' into test 2022-01-15 14:00:03 +01:00
miozune 255dac4db0 oops 2022-01-11 15:44:35 +09:00
miozune 9bbdd7b174 fix rendering items 2022-01-11 15:32:57 +09:00
Martin Robertz af0f71e7ca Merge remote-tracking branch 'origin/recipe-catalyst' into test 2022-01-10 16:34:32 +01:00
miozune de4e2c1632 fix offset 2022-01-10 19:23:54 +09:00
miozune f1518102bc rework rendering 2022-01-10 19:20:07 +09:00
miozune 29fe442671 add config 2022-01-10 04:06:24 +09:00
miozune c75420b31d use explicit import 2022-01-10 03:51:36 +09:00
miozune 98b6e552c4 Add RecipeCatalyst system 2022-01-09 18:48:33 +09:00
19 changed files with 490 additions and 9 deletions

No files matched your search

@@ -200,6 +200,8 @@ 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);
API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true));
tag.getTag("inventory.creative_tab_style").setComment("Creative or JEI style tabs").getBooleanValue(false);
@@ -403,6 +405,9 @@ public class NEIClientConfig {
public static boolean isJEIStyleItemPresenceOverlayVisible() {
return getBooleanSetting("inventory.jei_style_item_presence_overlay");
}
public static boolean areJEIStyleRecipeCatalystsVisible() {
return getBooleanSetting("inventory.jei_style_recipe_catalyst");
}
public static boolean useCreativeTabStyle() {
return getBooleanSetting("inventory.creative_tab_style");
}
@@ -408,4 +408,8 @@ public class NEIServerUtils
CompressedStreamTools.writeCompressed(tag, out);
out.close();
}
public static int divideCeil(int numerator, int denominator) {
return (int) Math.ceil((float) numerator / denominator);
}
}
@@ -18,7 +18,9 @@ import codechicken.nei.config.OptionKeyBind;
import codechicken.nei.recipe.GuiCraftingRecipe;
import codechicken.nei.recipe.GuiUsageRecipe;
import codechicken.nei.recipe.ICraftingHandler;
import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.IUsageHandler;
import codechicken.nei.recipe.RecipeCatalysts;
import codechicken.nei.recipe.RecipeInfo;
import codechicken.nei.recipe.StackInfo;
import net.minecraft.block.Block;
@@ -30,6 +32,7 @@ import org.lwjgl.input.Keyboard;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* This is the main class that handles item property configuration.
@@ -291,4 +294,24 @@ public class API
StackInfo.stackStringifyHandlers.add(handler);
}
/**
* 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 handler the recipe category handled by the ingredient
*/
public static void addRecipeCatalyst(ItemStack stack, Class<? extends IRecipeHandler> handler) {
addRecipeCatalyst(Collections.singletonList(stack), handler);
}
/**
* 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
*/
public static void addRecipeCatalyst(List<ItemStack> stacks, Class<? extends IRecipeHandler> handler) {
RecipeCatalysts.addRecipeCatalyst(stacks, handler);
}
}
@@ -3,11 +3,11 @@ package codechicken.nei.api;
import codechicken.nei.NEIChestGuiHandler;
import codechicken.nei.NEICreativeGuiHandler;
import codechicken.nei.NEIDummySlotHandler;
import codechicken.nei.recipe.GuiRecipeCatalyst;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiContainerCreative;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -24,6 +24,7 @@ public class GuiInfo {
API.registerNEIGuiHandler(new NEICreativeGuiHandler());
API.registerNEIGuiHandler(new NEIChestGuiHandler());
API.registerNEIGuiHandler(new NEIDummySlotHandler());
API.registerNEIGuiHandler(new GuiRecipeCatalyst(null));
customSlotGuis.add(GuiContainerCreative.class);
}
@@ -0,0 +1,91 @@
package codechicken.nei.drawable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.gui.GuiScreen;
/*
* Taken from Mantle 1.12-1.3.3.49 under the MIT License
*
* The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@SideOnly(Side.CLIENT)
public class GuiElementDuex {
// this is totally completely ugly but it's a simple solution that doesn't clutter everything too much >_>
public static int defaultTexW = 256;
public static int defaultTexH = 256;
public final int x;
public final int y;
public final int w;
public final int h;
public int texW;
public int texH;
public GuiElementDuex(int x, int y, int w, int h, int texW, int texH) {
this(x, y, w, h);
setTextureSize(texW, texH);
defaultTexW = texW;
defaultTexH = texH;
}
public GuiElementDuex(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
setTextureSize(defaultTexW, defaultTexH);
}
public GuiElementDuex setTextureSize(int w, int h) {
texW = w;
texH = h;
return this;
}
public GuiElementDuex shift(int xd, int yd) {
return new GuiElementDuex(this.x + xd, this.y + yd, this.w, this.h, this.texW, this.texH);
}
/**
* Draws the element at the given x/y coordinates
*
* @param xPos X-Coordinate on the screen
* @param yPos Y-Coordinate on the screen
*/
public int draw(int xPos, int yPos) {
// drawModalRectWithCustomSizedTexture
GuiScreen.func_146110_a(xPos, yPos, x, y, w, h, texW, texH);
return w;
}
public static class Builder {
public int w;
public int h;
public Builder(int w, int h) {
this.w = w;
this.h = h;
}
public GuiElementDuex get(int x, int y, int w, int h) {
return new GuiElementDuex(x, y, w, h, this.w, this.h);
}
}
}
@@ -0,0 +1,92 @@
package codechicken.nei.drawable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.gui.GuiScreen;
/*
* Taken from Mantle 1.12-1.3.3.49 under the MIT License
*
* The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
@SideOnly(Side.CLIENT)
public class GuiElementScalable extends GuiElementDuex {
public GuiElementScalable(int x, int y, int w, int h, int texW, int texH) {
super(x, y, w, h, texW, texH);
}
public GuiElementScalable(int x, int y, int w, int h) {
super(x, y, w, h);
}
public int drawScaledX(int xPos, int yPos, int width) {
for(int i = 0; i < width / w; i++) {
draw(xPos + i * w, yPos);
}
// remainder that doesn't fit total width
int remainder = width % w;
if(remainder > 0) {
GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, h, texW, texH);
}
return width;
}
public int drawScaledY(int xPos, int yPos, int height) {
for(int i = 0; i < height / h; i++) {
draw(xPos, yPos + i * h);
}
// remainder that doesn't fit total width
int remainder = height % h;
if(remainder > 0) {
// drawModalRectWithCustomSizedTexture
GuiScreen.func_146110_a(xPos, yPos + height - remainder, x, y, w, remainder, texW, texH);
}
return w;
}
public int drawScaled(int xPos, int yPos, int width, int height) {
// we draw full height row-wise
int full = height / this.h;
for(int i = 0; i < full; i++) {
drawScaledX(xPos, yPos + i * this.h, width);
}
yPos += full * this.h;
// and the remainder is drawn manually
int yRest = height % this.h;
// the same as drawScaledX but with the remaining height
for(int i = 0; i < width / w; i++) {
drawScaledY(xPos + i * w, yPos, yRest);
}
// remainder that doesn't fit total width
int remainder = width % w;
if(remainder > 0) {
// drawModalRectWithCustomSizedTexture
GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, yRest, texW, texH);
}
return width;
}
@Override
public GuiElementScalable shift(int xd, int yd) {
GuiElementScalable element = new GuiElementScalable(this.x + xd, this.y + yd, this.w, this.h);
element.setTextureSize(texW, texH);
return element;
}
}
@@ -193,6 +193,7 @@ 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 {
@@ -228,6 +229,7 @@ public class GuiContainerManager
enable2DRender();
drawItems.zLevel = zLevel - 100;
GL11.glPopAttrib();
}
//copy from appeng.client.render.AppEngRenderItem
@@ -8,7 +8,6 @@ import net.minecraft.item.crafting.FurnaceRecipes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import static codechicken.nei.NEIClientUtils.translate;
@@ -78,6 +77,11 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler
}
@Override
public String specifyTransferRect() {
return "fuel";
}
public String getOverlayIdentifier() {
return "fuel";
}
@@ -115,6 +115,11 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler
}
}
@Override
public String specifyTransferRect() {
return "smelting";
}
@Override
public String getGuiTexture() {
return "textures/gui/container/furnace.png";
@@ -76,6 +76,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
private final Rectangle area = new Rectangle();
private final GuiRecipeTabs recipeTabs;
private final GuiRecipeCatalyst guiRecipeCatalyst;
private IRecipeHandler handler;
private HandlerInfo handlerInfo;
@@ -84,6 +85,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
protected GuiRecipe(GuiScreen prevgui) {
super(new ContainerRecipe());
recipeTabs = new GuiRecipeTabs(this);
guiRecipeCatalyst = new GuiRecipeCatalyst(this);
slotcontainer = (ContainerRecipe) inventorySlots;
this.prevGui = prevgui;
@@ -267,7 +269,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
return handler.getIngredientStacks(idx);
}
}
return null;
}
@@ -454,6 +456,7 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
}
public void refreshPage() {
RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2));
refreshSlots();
final int recipesPerPage = getRecipesPerPage();
final boolean multiplepages = handler.numRecipes() > recipesPerPage;
@@ -503,6 +506,13 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
PositionedStack result = handler.getResultStack(i);
if (result != null)
slotcontainer.addSlot(result, p.x, p.y);
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler.getClass());
for (PositionedStack catalyst : catalysts) {
int xOffset = -GuiRecipeCatalyst.ingredientSize + 1;
int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder;
slotcontainer.addSlot(catalyst, xOffset, yOffset);
}
}
}
@@ -587,6 +597,9 @@ public abstract class GuiRecipe extends GuiContainer implements IGuiContainerOve
RenderHelper.enableGUIStandardItemLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
recipeTabs.draw(mouseX, mouseY);
if (NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) {
guiRecipeCatalyst.draw();
}
RenderHelper.disableStandardItemLighting();
}
@@ -0,0 +1,107 @@
package codechicken.nei.recipe;
import codechicken.nei.api.INEIGuiAdapter;
import codechicken.nei.drawable.GuiElementDuex;
import codechicken.nei.drawable.GuiElementScalable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Rectangle;
public class GuiRecipeCatalyst extends INEIGuiAdapter {
private GuiRecipe guiRecipe;
public static final int ingredientSize = 16;
public static final int ingredientBorder = 1;
public static final int tabBorder = 5;
public static final int fullBorder = ingredientBorder + tabBorder;
private static final Rectangle catalystRect = new Rectangle();
private static final Rectangle targetRect = new Rectangle();
public GuiRecipeCatalyst(GuiRecipe guiRecipe) {
this.guiRecipe = guiRecipe;
}
public void draw() {
if (guiRecipe == null) return;
int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler().getClass()).size();
if (catalystsSize == 0) return;
int availableHeight = RecipeCatalysts.getHeight();
int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize);
int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize);
int width, height, xPos, yPos;
width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize);
height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize);
xPos = guiRecipe.guiLeft - width + tabBorder + 1;
yPos = guiRecipe.guiTop;
drawBordered("nei:textures/catalyst_tab.png", xPos, yPos, width, height, 28, 28, 6, 6, 6, 6);
width = (ingredientBorder * 2) + (columnCount * ingredientSize);
height = (ingredientBorder * 2) + (rowCount * ingredientSize);
xPos = guiRecipe.guiLeft - width + ingredientBorder + 1;
yPos = guiRecipe.guiTop + fullBorder - ingredientBorder;
drawBordered("nei:textures/slot.png", xPos, yPos, width, height, 18, 18, 1, 1, 1, 1);
}
@Override
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
if (!(gui instanceof GuiRecipe)) return false;
guiRecipe = (GuiRecipe) gui;
int catalystsSize = RecipeCatalysts.getRecipeCatalysts(guiRecipe.getHandler().getClass()).size();
if (catalystsSize == 0) return false;
int availableHeight = RecipeCatalysts.getHeight();
int columnCount = RecipeCatalysts.getColumnCount(availableHeight, catalystsSize);
int rowCount = RecipeCatalysts.getRowCount(availableHeight, catalystsSize);
int margin = 4;
int width = (ingredientBorder * 2) + (tabBorder * 2) + (columnCount * ingredientSize) + margin;
int height = (ingredientBorder * 2) + (tabBorder * 2) + (rowCount * ingredientSize) + margin;
int xOffset = guiRecipe.guiLeft - width + tabBorder;
int yOffset = guiRecipe.guiTop;
catalystRect.setBounds(xOffset, yOffset, width, height);
targetRect.setBounds(x, y, w, h);
return targetRect.intersects(catalystRect);
}
private void drawBordered(String location, int xPos, int yPos, int width, int height, int texWidth, int texHeight, int sliceLeft, int sliceRight, int sliceTop, int sliceBottom) {
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation(location));
GuiElementDuex cornerTopLeft = new GuiElementDuex(0, 0, sliceLeft, sliceTop, texWidth, texHeight);
GuiElementDuex cornerTopRight = new GuiElementDuex(texWidth - sliceRight, 0, sliceRight, sliceTop, texWidth, texHeight);
GuiElementDuex cornerBottomLeft = new GuiElementDuex(0, texHeight - sliceBottom, sliceLeft, sliceBottom, texWidth, texHeight);
GuiElementDuex cornerBottomRight = new GuiElementDuex(texWidth - sliceRight, texHeight - sliceBottom, sliceRight, sliceBottom, texWidth, texHeight);
GuiElementScalable borderTop = new GuiElementScalable(sliceLeft, 0, texWidth - sliceLeft - sliceRight, sliceTop, texWidth, texHeight);
GuiElementScalable borderBottom = new GuiElementScalable(sliceLeft, texHeight - sliceBottom, texWidth - sliceLeft - sliceRight, sliceBottom, texWidth, texHeight);
GuiElementScalable borderLeft = new GuiElementScalable(0, sliceTop, sliceLeft, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
GuiElementScalable borderRight = new GuiElementScalable(texWidth - sliceRight, sliceTop, sliceRight, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
GuiElementScalable center = new GuiElementScalable(sliceLeft, sliceTop, texWidth - sliceLeft - sliceRight, texHeight - sliceTop - sliceBottom, texWidth, texHeight);
int midW = width - borderLeft.w - borderRight.w;
int midH = height - borderTop.h - borderBottom.h;
// top row
int x = xPos;
int y = yPos;
x += cornerTopLeft.draw(x, y);
x += borderTop.drawScaledX(x, y, midW);
cornerTopRight.draw(x, y);
// center row
x = xPos;
y += borderTop.h;
x += borderLeft.drawScaledY(x, y, midH);
x += center.drawScaled(x, y, midW, midH);
borderRight.drawScaledY(x, y, midH);
// bottom row
x = xPos;
y += midH;
x += cornerBottomLeft.draw(x, y);
x += borderBottom.drawScaledX(x, y, midW);
cornerBottomRight.draw(x, y);
}
}
@@ -28,11 +28,18 @@ public class GuiUsageRecipe extends GuiRecipe
handlers = serialUsageHandlers.stream().map(h -> h.getUsageHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new));
handlers.addAll(ItemList.forkJoinPool.submit(() -> usagehandlers.parallelStream()
.map(h -> h.getUsageHandler(inputId, ingredients))
.filter(h -> h.numRecipes() > 0)
.collect(Collectors.toCollection(ArrayList::new))).get());
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());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return false;
@@ -15,5 +15,12 @@ public interface IUsageHandler extends IRecipeHandler
* @param ingredients Objects representing the ingredients that matching recipes must contain.
* @return An instance of {@link IUsageHandler} configured with a list of recipes that contain matching input
*/
public IUsageHandler getUsageHandler(String inputId, Object... ingredients);
IUsageHandler getUsageHandler(String inputId, Object... ingredients);
/**
* See {@link TemplateRecipeHandler#getUsageAndCatalystHandler} for implementation
*/
default IUsageHandler getUsageAndCatalystHandler(String inputId, Object... ingredients) {
return getUsageHandler(inputId, ingredients);
}
}
@@ -0,0 +1,78 @@
package codechicken.nei.recipe;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import net.minecraft.item.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RecipeCatalysts {
private static final Map<Class<? extends IRecipeHandler>, List<ItemStack>> recipeCatalystMap = new HashMap<>();
private static Map<Class<? extends IRecipeHandler>, List<PositionedStack>> positionedRecipeCatalystMap = new HashMap<>();
private static int heightCache;
public static void addRecipeCatalyst(List<ItemStack> stacks, Class<? extends IRecipeHandler> handler) {
if (recipeCatalystMap.containsKey(handler)) {
recipeCatalystMap.get(handler).addAll(stacks);
} else {
recipeCatalystMap.put(handler, new ArrayList<>(stacks));
}
}
public static Map<Class<? extends IRecipeHandler>, List<PositionedStack>> getPositionedRecipeCatalystMap() {
return positionedRecipeCatalystMap;
}
public static List<PositionedStack> getRecipeCatalysts(Class<? extends IRecipeHandler> handler) {
if (!NEIClientConfig.areJEIStyleTabsVisible() || !NEIClientConfig.areJEIStyleRecipeCatalystsVisible()) {
return Collections.emptyList();
}
return positionedRecipeCatalystMap.getOrDefault(handler, Collections.emptyList());
}
public static boolean containsCatalyst(Class<? extends IRecipeHandler> handler, ItemStack candidate) {
return recipeCatalystMap.getOrDefault(handler, Collections.emptyList()).stream()
.anyMatch(s -> NEIServerUtils.areStacksSameType(s, candidate));
}
public static void updatePosition(int availableHeight) {
if (availableHeight == heightCache) return;
Map<Class<? extends IRecipeHandler>, List<PositionedStack>> newMap = new HashMap<>();
for (Map.Entry<Class<? extends IRecipeHandler>, List<ItemStack>> entry : recipeCatalystMap.entrySet()) {
List<ItemStack> catalysts = entry.getValue();
List<PositionedStack> newStacks = new ArrayList<>();
int rowCount = getRowCount(availableHeight, catalysts.size());
for (int index = 0; index < catalysts.size(); index++) {
ItemStack catalyst = catalysts.get(index);
int column = index / rowCount;
int row = index % rowCount;
newStacks.add(new PositionedStack(catalyst, -column * GuiRecipeCatalyst.ingredientSize, row * GuiRecipeCatalyst.ingredientSize));
}
newMap.put(entry.getKey(), newStacks);
}
positionedRecipeCatalystMap = newMap;
heightCache = availableHeight;
}
public static int getHeight() {
return heightCache;
}
public static int getColumnCount(int availableHeight, int catalystsSize) {
int maxItemsPerColumn = availableHeight / GuiRecipeCatalyst.ingredientSize;
return NEIServerUtils.divideCeil(catalystsSize, maxItemsPerColumn);
}
public static int getRowCount(int availableHeight, int catalystsSize) {
int columnCount = getColumnCount(availableHeight, catalystsSize);
return NEIServerUtils.divideCeil(catalystsSize, columnCount);
}
}
@@ -10,6 +10,9 @@ 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;
@@ -119,6 +122,13 @@ public class RecipeInfo
API.registerRecipeHandler(new ProfilerRecipeHandler(true));
API.registerUsageHandler(new ProfilerRecipeHandler(false));
API.addRecipeCatalyst(new ItemStack(Blocks.crafting_table), ShapedRecipeHandler.class);
API.addRecipeCatalyst(new ItemStack(Blocks.crafting_table), ShapelessRecipeHandler.class);
API.addRecipeCatalyst(new ItemStack(Blocks.crafting_table), FireworkRecipeHandler.class);
API.addRecipeCatalyst(new ItemStack(Blocks.furnace), FurnaceRecipeHandler.class);
API.addRecipeCatalyst(new ItemStack(Items.brewing_stand), BrewingRecipeHandler.class);
API.addRecipeCatalyst(new ItemStack(Blocks.furnace), FuelRecipeHandler.class);
}
}
@@ -550,6 +550,35 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
return handler;
}
/**
* First look up {@link RecipeCatalysts} whether target ingredient is registered for it.
* If so, load all recipes for this handler.
* Fallback to {@link TemplateRecipeHandler#getUsageHandler}.
*/
public IUsageHandler getUsageAndCatalystHandler(String inputId, Object... ingredients) {
TemplateRecipeHandler handler = newInstance();
if (inputId.equals("item")) {
ItemStack candidate = (ItemStack) ingredients[0];
if (RecipeCatalysts.containsCatalyst(handler.getClass(), candidate)) {
for (RecipeTransferRect rect : transferRects) {
if (specifyTransferRect() == null || Objects.equals(rect.outputId, specifyTransferRect())) {
handler.loadCraftingRecipes(rect.outputId, rect.results);
return handler;
}
}
}
}
return this.getUsageHandler(inputId, ingredients);
}
/**
* Override this if you have multiple {@link RecipeTransferRect}s.
* Used for {@link TemplateRecipeHandler#getUsageAndCatalystHandler}.
*/
public String specifyTransferRect() {
return null;
}
public int numRecipes() {
return arecipes.size();
}
@@ -120,6 +120,9 @@ 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.true=Yes
nei.options.inventory.jei_style_recipe_catalyst.false=No
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=Save Current Recipe in Bookmarks
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=Enabled
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=Disabled
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B