Skip to content

Commit 44877fc

Browse files
authored
Add JEI Categories and related improvements (#201)
* extra IWC part of JEI * move JEI removal to mixin to ensure it happens after mods * fix builders being commented in documentation * implement adding JEI Categories * add class and custom reloading example * move custom script files to their own folder * use event to reload
1 parent 8911f99 commit 44877fc

File tree

21 files changed

+488
-55
lines changed

21 files changed

+488
-55
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package classes
2+
3+
import classes.SimpleConversionRecipe
4+
import mezz.jei.api.gui.IDrawable
5+
import mezz.jei.api.gui.IGuiIngredient
6+
import mezz.jei.api.gui.IGuiIngredientGroup
7+
import mezz.jei.api.gui.IRecipeLayout
8+
import mezz.jei.api.ingredients.IIngredients
9+
import mezz.jei.api.ingredients.VanillaTypes
10+
import mezz.jei.api.recipe.IRecipeCategory
11+
import mezz.jei.api.recipe.IRecipeWrapper
12+
import mezz.jei.gui.ingredients.GuiIngredient
13+
import net.minecraft.client.Minecraft
14+
import net.minecraft.client.renderer.GlStateManager
15+
import net.minecraft.client.resources.I18n
16+
17+
import java.util.stream.Collectors
18+
19+
/**
20+
* An example of a IRecipeCategory from JEI, used in {@code /postInit/jei.groovy}.
21+
* Will only appear if {@code SimpleConversionRecipe.recipes} contains recipes.
22+
*/
23+
class GenericRecipeCategory implements IRecipeCategory<RecipeWrapper> {
24+
25+
static final String UID = "${getPackId()}:generic"
26+
27+
private final def icon
28+
29+
private final def uid
30+
private final def background
31+
32+
static def rightArrow
33+
static def slot
34+
35+
GenericRecipeCategory(guiHelper) {
36+
this(guiHelper, UID, 176, 67)
37+
}
38+
39+
GenericRecipeCategory(guiHelper, uid, width, height) {
40+
this.uid = uid
41+
this.background = guiHelper.createBlankDrawable(width, height)
42+
if (slot == null) {
43+
rightArrow = guiHelper.drawableBuilder(resource('groovyscript:textures/jei/arrow_right.png'), 0, 0, 24, 15)
44+
.setTextureSize(24, 15)
45+
.build()
46+
slot = guiHelper.getSlotDrawable()
47+
}
48+
this.icon = guiHelper.createDrawableIngredient(item('minecraft:clay'))
49+
}
50+
51+
static def getRecipeWrappers() {
52+
SimpleConversionRecipe.recipes.collect RecipeWrapper.&new
53+
}
54+
55+
void setRecipe(IRecipeLayout recipeLayout, IRecipeWrapper recipeWrapper, IIngredients ingredients) {
56+
addItemSlot(recipeLayout, 0, true, 53, 25)
57+
addItemSlot(recipeLayout, 1, false, 105, 25)
58+
59+
recipeLayout.getItemStacks().set(ingredients)
60+
setBackgrounds(recipeLayout.getItemStacks(), slot)
61+
}
62+
63+
void drawExtras(Minecraft minecraft) {
64+
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)
65+
rightArrow.draw(minecraft, 76, 26)
66+
}
67+
68+
IDrawable getIcon() {
69+
icon
70+
}
71+
72+
String getUid() {
73+
this.uid
74+
}
75+
76+
String getTitle() {
77+
I18n.format("jei.category.${this.uid}.name")
78+
}
79+
80+
String getModName() {
81+
getPackName()
82+
}
83+
84+
IDrawable getBackground() {
85+
this.background
86+
}
87+
88+
private static void addItemSlot(IRecipeLayout recipeLayout, int index, boolean input, int x, int y) {
89+
recipeLayout.getItemStacks().init(index, input, x, y)
90+
}
91+
92+
private static void setBackgrounds(IGuiIngredientGroup<?> ingredientGroup, IDrawable drawable) {
93+
for (IGuiIngredient<?> ingredient : ingredientGroup.getGuiIngredients().values()) {
94+
((GuiIngredient<?>) ingredient).setBackground(drawable)
95+
}
96+
}
97+
98+
static class RecipeWrapper implements IRecipeWrapper {
99+
100+
private final SimpleConversionRecipe recipe
101+
102+
RecipeWrapper(SimpleConversionRecipe recipe) {
103+
this.recipe = recipe
104+
}
105+
106+
void getIngredients(IIngredients ingredients) {
107+
ingredients.setInput(VanillaTypes.ITEM, this.recipe.getInput())
108+
ingredients.setOutput(VanillaTypes.ITEM, this.recipe.getOutput())
109+
}
110+
}
111+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package classes
2+
3+
/**
4+
* A simple example of reloadable compat for a single registry, in this case {@code SimpleConversionRecipe}.<br>
5+
*
6+
* To use, call {@link GenericRecipeReloading#onReload()} in an event listener listening to {@code GroovyReloadEvent},
7+
* and manipulate recipes by calling {@link GenericRecipeReloading#add()} or {@link GenericRecipeReloading#remove()}.<br>
8+
*
9+
* Note that {@link GenericRecipeReloading#onReload()} should only be called when GroovyScript is reloading,
10+
* so you will want to have it called by listening to {@code GroovyReloadEvent} in something like this:<br>
11+
* <pre>
12+
* eventManager.listen(com.cleanroommc.groovyscript.event.GroovyReloadEvent) {
13+
* GenericRecipeReloading.instance.onReload()
14+
* }
15+
* </pre>
16+
*/
17+
class GenericRecipeReloading {
18+
19+
static def instance = new GenericRecipeReloading()
20+
21+
def scripted = []
22+
def backup = []
23+
24+
void onReload() {
25+
scripted.each { SimpleConversionRecipe.recipes.remove(it) }
26+
scripted.clear()
27+
backup.each { SimpleConversionRecipe.recipes.add(it) }
28+
backup.clear()
29+
}
30+
31+
void add(recipe) {
32+
scripted << recipe
33+
SimpleConversionRecipe.recipes.add(recipe)
34+
}
35+
36+
void remove(recipe) {
37+
backup << recipe
38+
SimpleConversionRecipe.recipes.remove(recipe)
39+
}
40+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package classes
2+
3+
/**
4+
* A simple recipe and recipe holder to demonstrate both classes in GroovyScript and custom reloading compat.
5+
*/
6+
class SimpleConversionRecipe {
7+
static final List<SimpleConversionRecipe> recipes = []
8+
9+
ItemStack input
10+
ItemStack output
11+
12+
SimpleConversionRecipe(input, output) {
13+
this.input = input
14+
this.output = output
15+
}
16+
17+
}
File renamed without changes.
File renamed without changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
// this file demonstrates custom reloading compat
3+
// also demonstrating some event manager interactions
4+
5+
import classes.GenericRecipeReloading
6+
import classes.SimpleConversionRecipe
7+
import net.minecraft.util.text.TextComponentString
8+
import net.minecraftforge.event.world.BlockEvent
9+
import com.cleanroommc.groovyscript.event.GroovyReloadEvent
10+
11+
// add the example recipe
12+
GenericRecipeReloading.instance.add(new SimpleConversionRecipe(item('minecraft:clay'), item('minecraft:gold_ingot')))
13+
14+
// reload via an event
15+
eventManager.listen(GroovyReloadEvent) {
16+
GenericRecipeReloading.instance.onReload()
17+
}
18+
19+
// use an event to demonstrate the recipe in-game
20+
eventManager.listen(BlockEvent.BreakEvent) {
21+
// get the block drop if it was silk touched
22+
def drop = it.getState().getBlock().getSilkTouchDrop(it.getState())
23+
// find if any of the recipes have an input that match the drop
24+
def found = SimpleConversionRecipe.recipes.find { it.input in drop }
25+
if (found != null) {
26+
// send the player a pair of messages to demonstrate the recipe
27+
it.player.sendMessage(new TextComponentString("You broke a ${it.getState().getBlock().getLocalizedName()} Block!"))
28+
it.player.sendMessage(new TextComponentString("A custom recipe marks a ${found.output.getDisplayName()} as its output."))
29+
}
30+
}

0 commit comments

Comments
 (0)