### IModPlugin Interface Implementation Source: https://context7.com/mezz/justenoughitems/llms.txt Example of implementing the IModPlugin interface for JEI integration. This includes registering recipe categories, recipes, ingredient information, recipe catalysts, and recipe transfer handlers. ```APIDOC ## `IModPlugin` — Plugin Entry Point The central interface every JEI integration must implement. Annotate with `@JeiPlugin` on Forge/NeoForge; register as a `jei_mod_plugin` entrypoint on Fabric. All registration methods are optional `default` methods—implement only what your mod needs. ```java // Forge / NeoForge @JeiPlugin public class MyModJeiPlugin implements IModPlugin { private static final ResourceLocation PLUGIN_UID = ResourceLocation.fromNamespaceAndPath("mymod", "jei_plugin"); @Override public ResourceLocation getPluginUid() { return PLUGIN_UID; } // Called to register custom recipe categories @Override public void registerCategories(IRecipeCategoryRegistration registration) { IJeiHelpers helpers = registration.getJeiHelpers(); IGuiHelper guiHelper = helpers.getGuiHelper(); registration.addRecipeCategories(new MyMachineRecipeCategory(guiHelper)); } // Called to register recipes into JEI @Override public void registerRecipes(IRecipeRegistration registration) { List recipes = MyMachineRecipes.getAll(); registration.addRecipes(MyMachineRecipeCategory.RECIPE_TYPE, recipes); // Add an info description page for an item registration.addIngredientInfo( Items.ENDER_PEARL, Component.translatable("mymod.jei.ender_pearl_info") ); } // Called to associate crafting stations with recipe categories @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { registration.addCraftingStation( MyMachineRecipeCategory.RECIPE_TYPE, MyMod.MY_MACHINE_BLOCK.get() ); } // Called to register recipe transfer handlers (the "+" button) @Override public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { registration.addRecipeTransferHandler( MyMachineContainer.class, MyMod.MY_MACHINE_MENU_TYPE.get(), MyMachineRecipeCategory.RECIPE_TYPE, 0, // recipe slot start 9, // recipe slot count 9, // inventory slot start 36 // inventory slot count ); } // Called once JEI runtime is fully available @Override public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { IRecipeManager recipeManager = jeiRuntime.getRecipeManager(); // Hide a specific recipe category at runtime // recipeManager.hideRecipeCategory(RecipeTypes.CRAFTING); } // Called when the player logs out / JEI shuts down @Override public void onRuntimeUnavailable() { // Clean up any runtime state } } ``` ``` -------------------------------- ### Get Ingredient Blacklist - Java Source: https://github.com/mezz/justenoughitems/wiki/Hiding-Ingredients Retrieve the ingredient blacklist from the mod registry to add items that should be hidden from JEI. ```java IIngredientBlacklist blacklist = modRegistry.getJeiHelpers().getIngredientBlacklist() ``` -------------------------------- ### Query and Modify Ingredients at Runtime with JEI Source: https://context7.com/mezz/justenoughitems/llms.txt Access the `IIngredientManager` to get all registered ingredients of a specific type, add new ingredients, remove existing ones, or listen for changes. This manager is available both during registration and at runtime. ```java // At registration time (inside registerRecipes): IIngredientManager ingredientManager = registration.getIngredientManager(); Collection allItems = ingredientManager.getAllItemStacks(); // At runtime (inside onRuntimeAvailable): IIngredientManager ingredientManager = jeiRuntime.getIngredientManager(); // Get all ingredients of a custom type Collection energies = ingredientManager.getAllIngredients(MyModJei.ENERGY_TYPE); // Add server-defined items at runtime ingredientManager.addIngredientsAtRuntime( VanillaTypes.ITEM_STACK, List.of(new ItemStack(MyMod.SERVER_DEFINED_ITEM.get())) ); // Remove items that should be hidden at runtime ingredientManager.removeIngredientsAtRuntime( VanillaTypes.ITEM_STACK, List.of(new ItemStack(MyMod.HIDDEN_ITEM.get())) ); // Listen for ingredient changes ingredientManager.registerIngredientListener(new IIngredientManager.IIngredientListener() { @Override public void onIngredientsAdded(IIngredientHelper helper, Collection> added) { added.forEach(i -> MyMod.LOGGER.info("Added: {}", helper.getDisplayName(i.getIngredient()))); } @Override public void onIngredientsRemoved(IIngredientHelper helper, Collection> removed) { removed.forEach(i -> MyMod.LOGGER.info("Removed: {}", helper.getDisplayName(i.getIngredient()))); } }); // Create a typed ingredient safely (handles empty/invalid stacks) Optional> typed = ingredientManager.createTypedIngredient(VanillaTypes.ITEM_STACK, new ItemStack(Items.DIAMOND), true); ``` -------------------------------- ### Implement IModPlugin for JEI Integration (Forge/NeoForge) Source: https://context7.com/mezz/justenoughitems/llms.txt Implement this interface to integrate your mod's recipes and items with JEI. Annotate with `@JeiPlugin` for Forge/NeoForge. All registration methods are optional. ```java import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.gui.handlers.IGuiHandler; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.recipe.IRecipeManager; import mezz.jei.api.recipe.IRecipeType; import mezz.jei.api.registration.*; import mezz.jei.api.runtime.IJeiRuntime; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Items; import net.minecraft.network.chat.Component; import java.util.List; // Forge / NeoForge @JeiPlugin public class MyModJeiPlugin implements IModPlugin { private static final ResourceLocation PLUGIN_UID = ResourceLocation.fromNamespaceAndPath("mymod", "jei_plugin"); @Override public ResourceLocation getPluginUid() { return PLUGIN_UID; } // Called to register custom recipe categories @Override public void registerCategories(IRecipeCategoryRegistration registration) { IJeiHelpers helpers = registration.getJeiHelpers(); IGuiHelper guiHelper = helpers.getGuiHelper(); registration.addRecipeCategories(new MyMachineRecipeCategory(guiHelper)); } // Called to register recipes into JEI @Override public void registerRecipes(IRecipeRegistration registration) { List recipes = MyMachineRecipes.getAll(); registration.addRecipes(MyMachineRecipeCategory.RECIPE_TYPE, recipes); // Add an info description page for an item registration.addIngredientInfo( Items.ENDER_PEARL, Component.translatable("mymod.jei.ender_pearl_info") ); } // Called to associate crafting stations with recipe categories @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { registration.addCraftingStation( MyMachineRecipeCategory.RECIPE_TYPE, MyMod.MY_MACHINE_BLOCK.get() ); } // Called to register recipe transfer handlers (the "+" button) @Override public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { registration.addRecipeTransferHandler( MyMachineContainer.class, MyMod.MY_MACHINE_MENU_TYPE.get(), MyMachineRecipeCategory.RECIPE_TYPE, 0, // recipe slot start 9, // recipe slot count 9, // inventory slot start 36 // inventory slot count ); } // Called once JEI runtime is fully available @Override public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { IRecipeManager recipeManager = jeiRuntime.getRecipeManager(); // Hide a specific recipe category at runtime // recipeManager.hideRecipeCategory(RecipeTypes.CRAFTING); } // Called when the player logs out / JEI shuts down @Override public void onRuntimeUnavailable() { // Clean up any runtime state } } ``` -------------------------------- ### Get Ingredient Groups in IRecipeLayout Source: https://github.com/mezz/justenoughitems/wiki/Non-Item-Ingredients Access specific ingredient groups for ItemStacks and FluidStacks, or a generic group for custom ingredient types. ```java IGuiItemStackGroup getItemStacks(); IGuiFluidStackGroup getFluidStacks(); IGuiIngredientGroup getIngredientsGroup(Class ingredientClass); ``` -------------------------------- ### Get Recipe Transfer Registry Source: https://github.com/mezz/justenoughitems/wiki/Recipe-Transfer-Handlers Retrieve the IRecipeTransferRegistry from the IModRegistry within your plugin's register method. This registry is essential for managing recipe transfer functionalities. ```java IRecipeTransferRegistry recipeTransferRegistry = modRegistry.getRecipeTransferRegistry() ``` -------------------------------- ### Create Drawables with IGuiHelper Source: https://context7.com/mezz/justenoughitems/llms.txt Utilize IGuiHelper to create drawable elements like animated textures and standard widgets for recipe category backgrounds. Obtained from IJeiHelpers. ```java IDrawableStatic arrowStatic = guiHelper.createDrawable( ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/machine.png"), 0, 0, 24, 16 ); this.progressArrow = guiHelper.createAnimatedDrawable( arrowStatic, 40, IDrawableAnimated.StartDirection.LEFT, false ); ``` ```java this.flameBackground = guiHelper.getRecipeFlameEmpty(); ``` ```java this.flameForeground = guiHelper.createAnimatedRecipeFlame(20); ``` ```java flameBackground.draw(graphics, 57, 37); ``` ```java flameForeground.draw(graphics, 57, 37); ``` ```java progressArrow.draw(graphics, 60, 20); ``` -------------------------------- ### GUI Integration Source: https://context7.com/mezz/justenoughitems/llms.txt This section explains how to integrate JEI's overlay with custom GUIs by registering click areas, excluded zones, and ghost ingredient drop targets. ```APIDOC ## `IGuiHandlerRegistration` — GUI Integration Registers click areas, excluded zones, and ghost ingredient drop targets so JEI's overlay works correctly next to custom GUIs. ```java @Override public void registerGuiHandlers(IGuiHandlerRegistration registration) { // Add a clickable zone on MyMachineScreen that opens the machine's recipe category registration.addRecipeClickArea( MyMachineScreen.class, 52, 18, // x, y (relative to GUI left/top) 20, 20, // width, height MyMachineRecipeCategory.RECIPE_TYPE ); // Tell JEI to avoid drawing its item list over a specific area of the GUI registration.addGuiContainerHandler(MyMachineScreen.class, new IGuiContainerHandler() { @Override public List getGuiExtraAreas(MyMachineScreen screen) { return List.of(new Rect2i(screen.getGuiLeft() - 80, screen.getGuiTop(), 76, 120)); } } ); // Allow ghost ingredients to be dropped onto the filter slot registration.addGhostIngredientHandler(MyMachineScreen.class, new IGhostIngredientHandler() { @Override public List> getTargets(MyMachineScreen screen, ITypedIngredient ingredient, boolean doStart) { return List.of(/* define drop targets */); } @Override public void onComplete() {} } ); } ``` ``` -------------------------------- ### Open Recipe Viewer with IRecipesGui Source: https://context7.com/mezz/justenoughitems/llms.txt Use IRecipesGui to programmatically open the JEI recipe viewer to show specific items or recipe types. Obtain from IJeiRuntime. ```java IFocus focus = focusFactory.createFocus( RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.DIAMOND) ); recipesGui.show(focus); ``` ```java recipesGui.show(List.of( focusFactory.createFocus(RecipeIngredientRole.INPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.COAL)), focusFactory.createFocus(RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.IRON_INGOT)) )); ``` ```java recipesGui.showTypes(List.of(RecipeTypes.CRAFTING, RecipeTypes.SMELTING)); ``` -------------------------------- ### IGuiHelper — Drawable and GUI Utilities Source: https://context7.com/mezz/justenoughitems/llms.txt Provides utilities for creating drawables from textures, animated elements, and standard GUI widgets for recipe category backgrounds. ```APIDOC ## `IGuiHelper` — Drawable and GUI Utilities Obtained from `IJeiHelpers.getGuiHelper()`. ### Methods - **`createDrawable(ResourceLocation, int, int, int, int)`**: Creates a static drawable from a texture. - **`createAnimatedDrawable(IDrawableStatic, int, IDrawableAnimated.StartDirection, boolean)`**: Creates an animated drawable from a static drawable. - **`getRecipeFlameEmpty()`**: Gets a drawable for an empty recipe flame. - **`createAnimatedRecipeFlame(int)`**: Creates an animated drawable for a recipe flame. ### Example Usage ```java // Draw a portion of a custom texture IDrawableStatic arrowStatic = guiHelper.createDrawable( ResourceLocation.fromNamespaceAndPath("mymod", "textures/gui/machine.png"), 0, 0, 24, 16 ); // Animate it filling left-to-right over 40 ticks this.progressArrow = guiHelper.createAnimatedDrawable( arrowStatic, 40, IDrawableAnimated.StartDirection.LEFT, false ); // Vanilla-style slot and flame drawables this.flameBackground = guiHelper.getRecipeFlameEmpty(); this.flameForeground = guiHelper.createAnimatedRecipeFlame(20); // In the draw method: flameBackground.draw(graphics, 57, 37); flameForeground.draw(graphics, 57, 37); progressArrow.draw(graphics, 60, 20); ``` ``` -------------------------------- ### Configure Minecraft and JEI Versions Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.21-for-NeoForge,-Forge,-or-Fabric] Set the Minecraft and JEI versions in your `gradle.properties` file. `${mc_version}` and `${jei_version}` are placeholders that will be replaced. ```properties mc_version=1.21 jei_version=19.5.0.59 ``` -------------------------------- ### IRecipesGui — Programmatically Open Recipe Viewer Source: https://context7.com/mezz/justenoughitems/llms.txt Open the JEI recipe viewer to display specific items or recipe types from your own GUI code. ```APIDOC ## `IRecipesGui` — Programmatically Open Recipe Viewer Available via `IJeiRuntime.getRecipesGui()`. ### Methods - **`show(IFocus)`**: Displays recipes related to a single focus. - **`show(List)`**: Displays recipes related to multiple focuses. - **`showTypes(List)`**: Displays all recipes of specified types. ### Example Usage ```java // Show all recipes that output a Diamond IFocus focus = focusFactory.createFocus( RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.DIAMOND) ); recipesGui.show(focus); // Show recipes for multiple focuses simultaneously recipesGui.show(List.of( focusFactory.createFocus(RecipeIngredientRole.INPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.COAL)), focusFactory.createFocus(RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.IRON_INGOT)) )); // Show all recipes of a specific category recipesGui.showTypes(List.of(RecipeTypes.CRAFTING, RecipeTypes.SMELTING)); ``` ``` -------------------------------- ### NeoForge Dependencies for JEI Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.20.4--for-NeoForge,-Forge,-or-Fabric] Configure your build.gradle for NeoForge to compile against the JEI API and include the full JEI jar at runtime. Ensure `${mc_version}` and `${jei_version}` are defined. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime compileOnly("mezz.jei:jei-${mc_version}-common-api:${jei_version}") compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}") // at runtime, use the full JEI jar for NeoForge runtimeOnly("mezz.jei:jei-${mc_version}-neoforge:${jei_version}") } ``` -------------------------------- ### Forge Dependencies for JEI Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.20.4--for-NeoForge,-Forge,-or-Fabric] Set up your build.gradle for Forge to compile against the JEI API and include the full JEI jar at runtime. Use `fg.deobf` for ForgeGradle compatibility. Ensure `${mc_version}` and `${jei_version}` are defined. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")) compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")) // at runtime, use the full JEI jar for Forge runtimeOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")) } ``` -------------------------------- ### Registering Recipes and Info Pages with JEI Source: https://context7.com/mezz/justenoughitems/llms.txt Implement IModPlugin.registerRecipes to submit custom recipes and add ingredient information pages. This method receives an IRecipeRegistration instance for these operations. ```java @Override public void registerRecipes(IRecipeRegistration registration) { // Register custom machine recipes List machineRecipes = MyMachineRecipes.getAll(); registration.addRecipes(MyMachineRecipeCategory.RECIPE_TYPE, machineRecipes); // Register additional brewing recipes beyond vanilla auto-detection IVanillaRecipeFactory factory = registration.getVanillaRecipeFactory(); IJeiBrewingRecipe myBrewingRecipe = factory.createBrewingRecipe( List.of(new ItemStack(Items.BLAZE_POWDER)), // ingredient new ItemStack(Items.POTION), // input new ItemStack(MyMod.MY_CUSTOM_POTION.get()) // output ); registration.addRecipes(RecipeTypes.BREWING, List.of(myBrewingRecipe)); // Add a description page visible when looking up an item registration.addIngredientInfo( List.of( new ItemStack(MyMod.MY_ORE.get()), new ItemStack(MyMod.MY_DEEPSLATE_ORE.get()) ), VanillaTypes.ITEM_STACK, Component.translatable("mymod.jei.my_ore.description_line1"), Component.translatable("mymod.jei.my_ore.description_line2") ); } ``` -------------------------------- ### Register JEI Plugin Entrypoint (Fabric) Source: https://context7.com/mezz/justenoughitems/llms.txt Register your JEI plugin class as a `jei_mod_plugin` entrypoint in your Fabric mod's `fabric.mod.json` file. ```json { "entrypoints": { "jei_mod_plugin": [ "com.example.mymod.jei.MyModJeiPlugin" ] } } ``` -------------------------------- ### Accessing Vanilla Ingredient Types and Recipe Categories in JEI Source: https://context7.com/mezz/justenoughitems/llms.txt Demonstrates how to access the ITEM_STACK ingredient type and lists various built-in recipe types provided by JEI. Use these constants to interact with JEI's recipe and ingredient systems. ```java import mezz.jei.api.constants.RecipeTypes; import mezz.jei.api.constants.VanillaTypes; // Vanilla ingredient types IIngredientType itemType = VanillaTypes.ITEM_STACK; // uid: "item_stack" // All built-in recipe types (auto-populated from the recipe manager): // RecipeTypes.CRAFTING — CraftingRecipe // RecipeTypes.SMELTING — SmeltingRecipe // RecipeTypes.BLASTING — BlastingRecipe // RecipeTypes.SMOKING — SmokingRecipe // RecipeTypes.CAMPFIRE_COOKING — CampfireCookingRecipe // RecipeTypes.STONECUTTING — StonecutterRecipe // RecipeTypes.SMITHING — SmithingRecipe // RecipeTypes.BREWING — IJeiBrewingRecipe // RecipeTypes.ANVIL — IJeiAnvilRecipe // RecipeTypes.GRINDSTONE — IJeiGrindstoneRecipe // RecipeTypes.COMPOSTING — IJeiCompostingRecipe // RecipeTypes.SMELTING_FUEL — IJeiFuelingRecipe (auto-created for burnable items) // RecipeTypes.INFORMATION — IJeiIngredientInfoRecipe (from addIngredientInfo) // Example: look up crafting recipes at runtime recipeManager.createRecipeLookup(RecipeTypes.CRAFTING) .get() .forEach(recipe -> { /* process */ }); // Example: add catalyst for smelting catalystRegistration.addCraftingStation( RecipeTypes.SMELTING, Items.FURNACE ); ``` -------------------------------- ### Add JEI Maven Repositories Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-10-or-higher-for-Forge-or-Fabric] Configure your build script to include the necessary Maven repositories for JEI. These repositories host JEI files, with different URLs for versions before and after January 2023, and a fallback mirror. ```gradle repositories { maven { // location of the maven that hosts JEI files before January 2023 name = "Progwml6's maven" url = "https://dvs1.progwml6.com/files/maven/" } maven { // location of the maven that hosts JEI files since January 2023 name = "Jared's maven" url = "https://maven.blamejared.com/" } maven { // location of a maven mirror for JEI files, as a fallback name = "ModMaven" url = "https://modmaven.dev" } } ``` -------------------------------- ### Add JEI Dependencies for NeoForge Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.21-for-NeoForge,-Forge,-or-Fabric] Configure your build.gradle to compile against the JEI API and include the full JEI jar at runtime for NeoForge mods. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}") // at runtime, use the full JEI jar for NeoForge runtimeOnly("mezz.jei:jei-${mc_version}-neoforge:${jei_version}") } ``` -------------------------------- ### Configure Minecraft and JEI Versions Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[1.13-to-1.18.2] Define the Minecraft and JEI versions for your project in `gradle.properties`. These properties are used by the `build.gradle` script to fetch the correct JEI artifacts. ```properties mc_version=1.16.5 jei_version=7.6.1.75 ``` -------------------------------- ### Set Minecraft and JEI Versions Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started Define the Minecraft and JEI versions in your `gradle.properties` file. These properties are used to substitute placeholders in your `build.gradle` dependencies. ```properties mc_version=1.10.2 jei_version=3.13.0.330 ``` -------------------------------- ### Fabric Entrypoint Registration Source: https://context7.com/mezz/justenoughitems/llms.txt Configuration for registering the JEI plugin as an entrypoint in Fabric's mod.json file. ```APIDOC ```json // fabric.mod.json — Fabric entrypoint registration { "entrypoints": { "jei_mod_plugin": [ "com.example.mymod.jei.MyModJeiPlugin" ] } } ``` ``` -------------------------------- ### Register Recipe Click Area for JEI Overlay Source: https://context7.com/mezz/justenoughitems/llms.txt Add a clickable area to your screen class that, when clicked, will open the associated JEI recipe category. Specify the screen class, the relative coordinates and dimensions of the clickable area, and the recipe type. ```java registration.addRecipeClickArea( MyMachineScreen.class, 52, 18, // x, y (relative to GUI left/top) 20, 20, // width, height MyMachineRecipeCategory.RECIPE_TYPE ); ``` -------------------------------- ### IRecipeManager - Runtime Recipe Queries and Control Source: https://context7.com/mezz/justenoughitems/llms.txt Manage recipes at runtime: look up, hide, unhide, and add recipes. Also allows programmatic opening of recipe GUIs. ```APIDOC ## `IRecipeManager` — Runtime Recipe Queries and Control Available via `IJeiRuntime.getRecipeManager()`. ### Methods - **`createRecipeLookup(RecipeType)`**: Creates a lookup for recipes of a specific type. - **`hideRecipeCategory(RecipeType)`**: Hides an entire recipe category. - **`unhideRecipeCategory(RecipeType)`**: Unhides a previously hidden recipe category. - **`hideRecipes(RecipeType, List)`**: Hides a list of specific recipes. - **`addRecipes(RecipeType, List)`**: Adds new recipes at runtime. - **`createCraftingStationLookup(RecipeType)`**: Creates a lookup for crafting stations associated with a recipe type. ### Example Usage ```java // Look up all smelting recipes that output Iron Ingot List smeltingRecipes = recipeManager .createRecipeLookup(RecipeTypes.SMELTING) .limitFocus(List.of( jeiRuntime.getJeiHelpers().getFocusFactory() .createFocus(RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.IRON_INGOT)) )) .get() .toList(); // Hide a specific recipe category recipeManager.hideRecipeCategory(RecipeTypes.CRAFTING); // Hide specific recipes List toHide = List.of(/* some recipe instances */); recipeManager.hideRecipes(RecipeTypes.SMELTING, toHide); // Add new recipes at runtime MyMachineRecipe dynamicRecipe = new MyMachineRecipe(/* ... */); recipeManager.addRecipes(MyMachineRecipeCategory.RECIPE_TYPE, List.of(dynamicRecipe)); // Get crafting stations for a recipe type recipeManager.createCraftingStationLookup(RecipeTypes.SMELTING) .get() .forEach(station -> MyMod.LOGGER.info("Furnace station: {}", station)); ``` ``` -------------------------------- ### Query and Control Recipes with IRecipeManager Source: https://context7.com/mezz/justenoughitems/llms.txt Use IRecipeManager to look up, hide, unhide, and add recipes at runtime. Requires access to IJeiRuntime. ```java recipeManager.createRecipeLookup(RecipeTypes.SMELTING) .limitFocus(List.of( jeiRuntime.getJeiHelpers().getFocusFactory() .createFocus(RecipeIngredientRole.OUTPUT, VanillaTypes.ITEM_STACK, new ItemStack(Items.IRON_INGOT)) )) .get() .toList(); ``` ```java recipeManager.hideRecipeCategory(RecipeTypes.CRAFTING); ``` ```java recipeManager.unhideRecipeCategory(RecipeTypes.CRAFTING); ``` ```java List toHide = List.of(/* some recipe instances */); recipeManager.hideRecipes(RecipeTypes.SMELTING, toHide); ``` ```java MyMachineRecipe dynamicRecipe = new MyMachineRecipe(/* ... */); recipeManager.addRecipes(MyMachineRecipeCategory.RECIPE_TYPE, List.of(dynamicRecipe)); ``` ```java recipeManager.createCraftingStationLookup(RecipeTypes.SMELTING) .get() .forEach(station -> MyMod.LOGGER.info("Furnace station: {}", station)); ``` -------------------------------- ### Registering Recipe Catalysts with JEI Source: https://context7.com/mezz/justenoughitems/llms.txt Implement IModPlugin.registerRecipeCatalysts to associate crafting station items with recipe categories. This allows players to click on the catalyst item to view associated recipes. ```java @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { // Associate a single block with one recipe type registration.addCraftingStation( MyMachineRecipeCategory.RECIPE_TYPE, MyMod.MY_MACHINE_BLOCK.get() ); // Associate multiple items with one recipe type registration.addCraftingStation( RecipeTypes.SMELTING, Items.FURNACE, Items.BLAST_FURNACE ); // Associate a custom fluid ingredient type with a recipe type registration.addCraftingStation( MyRecipeTypes.FLUID_CRAFTING, VanillaTypes.ITEM_STACK, new ItemStack(MyMod.FLUID_CRAFTER.get()) ); } ``` -------------------------------- ### Add JEI Maven Repositories Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.21-for-NeoForge,-Forge,-or-Fabric] Include these repositories in your build.gradle file to allow Gradle to download JEI. ```gradle repositories { maven { // location of the maven that hosts JEI files since January 2023 name = "Jared's maven" url = "https://maven.blamejared.com/" } maven { // location of a maven mirror for JEI files, as a fallback name = "ModMaven" url = "https://modmaven.dev" } } ``` -------------------------------- ### Add JEI Repositories to build.gradle Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[1.13-to-1.18.2] Configure your build script to include the Maven repositories where JEI files are hosted. This ensures Gradle can find and download JEI dependencies. ```gradle repositories { maven { // location of the maven that hosts JEI files name = "Progwml6 maven" url = "https://dvs1.progwml6.com/files/maven/" } maven { // location of a maven mirror for JEI files, as a fallback name = "ModMaven" url = "https://modmaven.dev" } } ``` -------------------------------- ### Register Ghost Ingredient Handler for Drop Targets Source: https://context7.com/mezz/justenoughitems/llms.txt Implement `IGhostIngredientHandler` to define where ghost ingredients can be dropped within your GUI. The `getTargets` method should return a list of `Target` objects, specifying the locations and conditions for valid drops. ```java registration.addGhostIngredientHandler(MyMachineScreen.class, new IGhostIngredientHandler() { @Override public List> getTargets(MyMachineScreen screen, ITypedIngredient ingredient, boolean doStart) { return List.of(/* define drop targets */); } @Override public void onComplete() {} } ); ``` -------------------------------- ### Add JEI Gradle Dependencies Source: https://context7.com/mezz/justenoughitems/llms.txt Configure your Gradle build file to include JEI dependencies. Use compileOnly for the API artifact and runtimeOnly for the full implementation. Ensure your repositories are set up correctly. ```gradle // build.gradle (gradle.properties: mc_version=1.21, jei_version=19.5.0.59) repositories { maven { name = "Jared's maven" url = "https://maven.blamejared.com/" } maven { name = "ModMaven" url = "https://modmaven.dev" } } dependencies { // NeoForge (NeoGradle) compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}") runtimeOnly("mezz.jei:jei-${mc_version}-neoforge:${jei_version}") // Forge (ForgeGradle) // compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")) // runtimeOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")) // Fabric (Loom) // modCompileOnly("mezz.jei:jei-${mc_version}-fabric-api:${jei_version}") // modRuntimeOnly("mezz.jei:jei-${mc_version}-fabric:${jei_version}") } ``` -------------------------------- ### Add JEI Dependencies using FG3 Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[1.13-to-1.18.2] Specify JEI as a dependency in your `build.gradle` file using ForgeGradle 3. This includes compiling against the JEI API for stable development and including the full JEI jar at runtime. ```gradle dependencies { /* minecraft dependency is here */ // compile against the JEI API but do not include it at runtime compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // at runtime, use the full JEI jar runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") } ``` -------------------------------- ### Configure Minecraft and JEI Versions Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-10-or-higher-for-Forge-or-Fabric] Set the Minecraft and JEI versions in your `gradle.properties` file. These properties are used to resolve the correct JEI artifacts for your project. ```properties mc_version=1.19 jei_version=11.0.0.206 ``` -------------------------------- ### Add JEI Dependencies for Forge Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.21-for-NeoForge,-Forge,-or-Fabric] Configure your build.gradle to compile against the JEI API and include the full JEI jar at runtime for Forge mods. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime compileOnly("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") // at runtime, use the full JEI jar for Forge runtimeOnly("mezz.jei:jei-${mc_version}-forge:${jei_version}") } ``` -------------------------------- ### Add JEI Dependencies for Fabric Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.21-for-NeoForge,-Forge,-or-Fabric] Configure your build.gradle to compile against the JEI API and include the full JEI jar at runtime for Fabric mods. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime modCompileOnly("mezz.jei:jei-${mc_version}-fabric-api:${jei_version}") // at runtime, use the full JEI jar for Fabric modRuntimeOnly("mezz.jei:jei-${mc_version}-fabric:${jei_version}") } ``` -------------------------------- ### Register Simple Slot-Based Recipe Transfer Handler Source: https://context7.com/mezz/justenoughitems/llms.txt Use this to register a basic recipe transfer handler for containers with simple slot layouts. Specify the container class, menu type, recipe type, and the indices for recipe slots and player inventory slots. ```java registration.addRecipeTransferHandler( MyMachineContainer.class, MyMod.MY_MACHINE_MENU_TYPE.get(), MyMachineRecipeCategory.RECIPE_TYPE, 0, // recipeSlotStart: first input slot index in container 9, // recipeSlotCount: 9 input slots 9, // inventorySlotStart: player inventory starts at slot 9 36 // inventorySlotCount: 36 player inventory slots ); ``` -------------------------------- ### Gradle Properties for Minecraft and JEI Versions Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.20.4--for-NeoForge,-Forge,-or-Fabric] Define the Minecraft and JEI versions in your `gradle.properties` file. This allows for easy management and updates of these versions across your build script. ```properties mc_version=1.20.4 jei_version=17.0.0.30 ``` -------------------------------- ### Declare JEI Dependencies in Gradle Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started Specify JEI dependencies in your `build.gradle` file. Use `deobfProvided` to compile against the JEI API and `runtime` to include the full JEI JAR at runtime. ```gradle dependencies { // compile against the JEI API but do not include it at runtime deobfProvided "mezz.jei:jei_${mc_version}:${jei_version}:api" // at runtime, use the full JEI jar runtime "mezz.jei:jei_${mc_version}:${jei_version}" } ``` -------------------------------- ### Register Custom Ingredient Type with JEI Source: https://context7.com/mezz/justenoughitems/llms.txt Implement `IModIngredientRegistration` to register a new ingredient type. Requires defining the type token, providing a list of all possible ingredients, and implementing helper, renderer, and codec interfaces. ```java public static final IIngredientType ENERGY_TYPE = () -> MyEnergy.class; @Override public void registerIngredients(IModIngredientRegistration registration) { List allEnergies = List.of( new MyEnergy(100), new MyEnergy(1000), new MyEnergy(10000) ); registration.register( ENERGY_TYPE, allEnergies, new MyEnergyIngredientHelper(), // implements IIngredientHelper new MyEnergyIngredientRenderer(), // implements IIngredientRenderer MyEnergy.CODEC // Codec ); } ``` ```java // Minimal IIngredientHelper implementation public class MyEnergyIngredientHelper implements IIngredientHelper { @Override public IIngredientType getIngredientType() { return ENERGY_TYPE; } @Override public String getDisplayName(MyEnergy ingredient) { return ingredient.getAmount() + " FE"; } @Override public Object getUid(MyEnergy ingredient, UidContext context) { return ingredient.getAmount(); } @Override public Identifier getIdentifier(MyEnergy ingredient) { return ResourceLocation.fromNamespaceAndPath("mymod", "energy_" + ingredient.getAmount()); } @Override public MyEnergy copyIngredient(MyEnergy ingredient) { return new MyEnergy(ingredient.getAmount()); } @Override public String getErrorInfo(@Nullable MyEnergy ingredient) { return ingredient == null ? "null" : ingredient.toString(); } } ``` -------------------------------- ### Registering Recipe Transfer Handlers Source: https://context7.com/mezz/justenoughitems/llms.txt This section details how to register recipe transfer handlers for custom containers. It shows both a simple slot-based registration and a full custom handler implementation. ```APIDOC ## `IRecipeTransferRegistration` — Recipe Transfer Handler Enables the "+" button to fill a crafting GUI from a JEI recipe. For simple slot-based containers, provide slot indices. For complex containers, implement `IRecipeTransferHandler`. ```java // Simple slot-based transfer @Override public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { registration.addRecipeTransferHandler( MyMachineContainer.class, MyMod.MY_MACHINE_MENU_TYPE.get(), MyMachineRecipeCategory.RECIPE_TYPE, 0, // recipeSlotStart: first input slot index in container 9, // recipeSlotCount: 9 input slots 9, // inventorySlotStart: player inventory starts at slot 9 36 // inventorySlotCount: 36 player inventory slots ); } // Full custom transfer handler public class MyMachineTransferHandler implements IRecipeTransferHandler { @Override public Class getContainerClass() { return MyMachineContainer.class; } @Override public Optional> getMenuType() { return Optional.of(MyMod.MY_MACHINE_MENU_TYPE.get()); } @Override public IRecipeType getRecipeType() { return MyMachineRecipeCategory.RECIPE_TYPE; } @Override @Nullable public IRecipeTransferError transferRecipe( MyMachineContainer container, MyMachineRecipe recipe, IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer ) { if (!doTransfer) { return null; // no error, transfer is possible } // Perform custom slot-filling logic here MyMachineTransferPacket.send(player, recipe.getId(), maxTransfer); return null; // null = success } } ``` ``` -------------------------------- ### Add Recipe Click Area - Java Source: https://github.com/mezz/justenoughitems/wiki/Recipe-Click-Areas Use `modRegistry.addRecipeClickArea` to link a GUI element to a JEI recipe category. Specify the GUI class, coordinates, dimensions, and the recipe category UID. ```java registry.addRecipeClickArea(GuiCrafting.class, 88, 32, 28, 23, VanillaRecipeCategoryUid.CRAFTING); ``` -------------------------------- ### Custom Machine Recipe Category Source: https://context7.com/mezz/justenoughitems/llms.txt Extend AbstractRecipeCategory to define a new recipe category for custom machines. Implement setRecipe to define ingredient and output slots, and optionally override draw and getTooltip for custom rendering and information. ```java public class MyMachineRecipeCategory extends AbstractRecipeCategory { public static final IRecipeType RECIPE_TYPE = IRecipeType.create("mymod", "my_machine", MyMachineRecipe.class); private static final int WIDTH = 120; private static final int HEIGHT = 60; public MyMachineRecipeCategory(IGuiHelper guiHelper) { super( RECIPE_TYPE, Component.translatable("mymod.jei.category.my_machine"), guiHelper.createDrawableItemLike(MyMod.MY_MACHINE_BLOCK.get()), // tab icon WIDTH, HEIGHT ); } @Override public void setRecipe(IRecipeLayoutBuilder builder, MyMachineRecipe recipe, IFocusGroup focuses) { // Add a single input slot at position (10, 20) builder.addInputSlot(10, 20) .addItemStacks(recipe.getInputs()); // Add the output slot at position (90, 20) builder.addOutputSlot(90, 20) .addItemStack(recipe.getOutput()); // Link input and output so focusing one filters the other // builder.createFocusLink(inputSlot, outputSlot); } @Override public void draw(MyMachineRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) { // Draw a static arrow between slots // arrowDrawable.draw(graphics, 52, 18); } @Override public void getTooltip(ITooltipBuilder tooltip, MyMachineRecipe recipe, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { if (mouseX > 50 && mouseX < 70 && mouseY > 15 && mouseY < 35) { tooltip.add(Component.translatable("mymod.jei.processing_time", recipe.getProcessingTime())); } } } ``` -------------------------------- ### Fabric Dependencies for JEI Source: https://github.com/mezz/justenoughitems/wiki/Getting-Started-[JEI-for-Minecraft-1.20.4--for-NeoForge,-Forge,-or-Fabric] Configure your build.gradle for Fabric using Loom to compile against the JEI API and include the full JEI jar at runtime. Ensure `${mc_version}` and `${jei_version}` are defined. ```gradle dependencies { /* other minecraft dependencies are here */ // compile against the JEI API but do not include it at runtime modCompileOnlyApi("mezz.jei:jei-${mc_version}-common-api:${jei_version}") modCompileOnlyApi("mezz.jei:jei-${mc_version}-fabric-api:${jei_version}") // at runtime, use the full JEI jar for Fabric modRuntimeOnly("mezz.jei:jei-${mc_version}-fabric:${jei_version}") } ```