Skip to content

Commit 8cb8f0c

Browse files
committed
Add JEI support on 1.19.2
1 parent 2efe2e4 commit 8cb8f0c

File tree

9 files changed

+370
-5
lines changed

9 files changed

+370
-5
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package net.darkhax.botanypots.addons.jei;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
import mezz.jei.api.constants.VanillaTypes;
5+
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
6+
import mezz.jei.api.gui.drawable.IDrawable;
7+
import mezz.jei.api.gui.drawable.IDrawableStatic;
8+
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
9+
import mezz.jei.api.helpers.IGuiHelper;
10+
import mezz.jei.api.recipe.IFocusGroup;
11+
import mezz.jei.api.recipe.RecipeType;
12+
import mezz.jei.api.recipe.category.IRecipeCategory;
13+
import net.darkhax.bookshelf.api.Services;
14+
import net.darkhax.botanypots.Constants;
15+
import net.darkhax.botanypots.addons.jei.ui.CropDisplayInfo;
16+
import net.minecraft.network.chat.Component;
17+
import net.minecraft.resources.ResourceLocation;
18+
import net.minecraft.world.item.ItemStack;
19+
20+
public class CropDisplayCategory implements IRecipeCategory<CropDisplayInfo> {
21+
22+
private final RecipeType<CropDisplayInfo> type;
23+
private final IGuiHelper guiHelper;
24+
private final IDrawable icon;
25+
private final IDrawableStatic background;
26+
private final Component localizedName;
27+
28+
public CropDisplayCategory(IGuiHelper gui, RecipeType<CropDisplayInfo> type) {
29+
30+
this.guiHelper = gui;
31+
this.type = type;
32+
this.icon = gui.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(Services.REGISTRIES.items().get(new ResourceLocation(Constants.MOD_ID, "terracotta_botany_pot"))));
33+
this.background = gui.createBlankDrawable(155, 57);
34+
this.localizedName = Component.translatable("gui.jei.category.botanypots.crop");
35+
}
36+
37+
@Override
38+
public void setRecipe(IRecipeLayoutBuilder builder, CropDisplayInfo recipe, IFocusGroup focuses) {
39+
40+
recipe.setRecipe(builder, focuses);
41+
}
42+
43+
@Override
44+
public void draw(CropDisplayInfo recipe, IRecipeSlotsView view, PoseStack stack, double mouseX, double mouseY) {
45+
46+
recipe.draw(view, stack, mouseX, mouseY, this.guiHelper);
47+
}
48+
49+
@Override
50+
public RecipeType<CropDisplayInfo> getRecipeType() {
51+
52+
return this.type;
53+
}
54+
55+
@Override
56+
public Component getTitle() {
57+
58+
return this.localizedName;
59+
}
60+
61+
@Override
62+
public IDrawable getBackground() {
63+
64+
return this.background;
65+
}
66+
67+
@Override
68+
public IDrawable getIcon() {
69+
70+
return this.icon;
71+
}
72+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package net.darkhax.botanypots.addons.jei;
2+
3+
import mezz.jei.api.IModPlugin;
4+
import mezz.jei.api.JeiPlugin;
5+
import mezz.jei.api.helpers.IGuiHelper;
6+
import mezz.jei.api.recipe.RecipeType;
7+
import mezz.jei.api.registration.IRecipeCatalystRegistration;
8+
import mezz.jei.api.registration.IRecipeCategoryRegistration;
9+
import mezz.jei.api.registration.IRecipeRegistration;
10+
import net.darkhax.botanypots.BotanyPotHelper;
11+
import net.darkhax.botanypots.Constants;
12+
import net.darkhax.botanypots.addons.jei.ui.BasicCropDisplayInfo;
13+
import net.darkhax.botanypots.addons.jei.ui.CropDisplayInfo;
14+
import net.darkhax.botanypots.data.recipes.crop.BasicCrop;
15+
import net.darkhax.botanypots.data.recipes.crop.Crop;
16+
import net.darkhax.botanypots.data.recipes.fertilizer.Fertilizer;
17+
import net.darkhax.botanypots.data.recipes.potinteraction.PotInteraction;
18+
import net.darkhax.botanypots.data.recipes.soil.Soil;
19+
import net.minecraft.client.Minecraft;
20+
import net.minecraft.resources.ResourceLocation;
21+
import net.minecraft.world.item.crafting.RecipeManager;
22+
23+
import java.util.List;
24+
25+
@JeiPlugin
26+
public class JEIPlugin implements IModPlugin {
27+
28+
private static final ResourceLocation PLUGIN_ID = new ResourceLocation(Constants.MOD_ID, "jei_support");
29+
30+
public static final RecipeType<CropDisplayInfo> SOIL = RecipeType.create(Constants.MOD_ID, "soil", CropDisplayInfo.class);
31+
public static final RecipeType<CropDisplayInfo> CROP = RecipeType.create(Constants.MOD_ID, "crop", CropDisplayInfo.class);
32+
public static final RecipeType<PotInteraction> POT_INTERACTION = RecipeType.create(Constants.MOD_ID, "pot_interaction", PotInteraction.class);
33+
public static final RecipeType<Fertilizer> FERTILIZER = RecipeType.create(Constants.MOD_ID, "fertilizer", Fertilizer.class);
34+
35+
@Override
36+
public ResourceLocation getPluginUid() {
37+
38+
return PLUGIN_ID;
39+
}
40+
41+
@Override
42+
public void registerCategories(IRecipeCategoryRegistration registration) {
43+
44+
final IGuiHelper gui = registration.getJeiHelpers().getGuiHelper();
45+
registration.addRecipeCategories(new CropDisplayCategory(gui, SOIL));
46+
registration.addRecipeCategories(new CropDisplayCategory(gui, CROP));
47+
}
48+
49+
@Override
50+
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
51+
52+
}
53+
54+
@Override
55+
public void registerRecipes(IRecipeRegistration registration) {
56+
57+
final RecipeManager recipeManager = Minecraft.getInstance().level.getRecipeManager();
58+
final List<Soil> soils = recipeManager.getAllRecipesFor(BotanyPotHelper.SOIL_TYPE.get());
59+
final List<Crop> crops = recipeManager.getAllRecipesFor(BotanyPotHelper.CROP_TYPE.get());
60+
61+
crops.forEach(crop -> {
62+
63+
if (crop instanceof BasicCrop basic) {
64+
registration.addRecipes(CROP, BasicCropDisplayInfo.getCropRecipes(basic, soils));
65+
}
66+
});
67+
}
68+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package net.darkhax.botanypots.addons.jei.ui;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
5+
import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
6+
import mezz.jei.api.gui.drawable.IDrawableStatic;
7+
import mezz.jei.api.gui.ingredient.IRecipeSlotTooltipCallback;
8+
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
9+
import mezz.jei.api.helpers.IGuiHelper;
10+
import mezz.jei.api.recipe.IFocusGroup;
11+
import mezz.jei.api.recipe.RecipeIngredientRole;
12+
import net.darkhax.botanypots.BotanyPotHelper;
13+
import net.darkhax.botanypots.data.recipes.crop.BasicCrop;
14+
import net.darkhax.botanypots.data.recipes.crop.HarvestEntry;
15+
import net.darkhax.botanypots.data.recipes.soil.BasicSoil;
16+
import net.darkhax.botanypots.data.recipes.soil.Soil;
17+
import net.minecraft.ChatFormatting;
18+
import net.minecraft.network.chat.Component;
19+
import net.minecraft.world.item.crafting.Ingredient;
20+
21+
import java.text.DecimalFormat;
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
25+
public class BasicCropDisplayInfo extends CropDisplayInfo {
26+
27+
public static List<CropDisplayInfo> getCropRecipes(BasicCrop crop, List<Soil> soils) {
28+
29+
final List<CropDisplayInfo> info = new ArrayList<>();
30+
31+
for (Soil soil : soils) {
32+
33+
if (soil instanceof BasicSoil basicSoil && crop.canGrowInSoil(null, null, null, soil)) {
34+
35+
final int ticks = BotanyPotHelper.getRequiredGrowthTicks(null, null, null, crop, soil);
36+
info.add(new BasicCropDisplayInfo(crop.getSeed(), basicSoil.getIngredient(), crop.getResults(), ticks, basicSoil.getGrowthModifier()));
37+
}
38+
}
39+
40+
return info;
41+
}
42+
43+
private static final DecimalFormat FORMAT = new DecimalFormat("#.##");
44+
45+
private final List<Ingredient> seeds;
46+
private final List<Ingredient> soils;
47+
private final List<HarvestEntry> drops;
48+
private final int growthTime;
49+
private final float modifier;
50+
51+
public BasicCropDisplayInfo(Ingredient seeds, Ingredient soils, List<HarvestEntry> drops, int growthTime, float modifier) {
52+
53+
this(List.of(seeds), List.of(soils), drops, growthTime, modifier);
54+
}
55+
56+
public BasicCropDisplayInfo(List<Ingredient> seeds, List<Ingredient> soils, List<HarvestEntry> drops, int growthTime, float modifier) {
57+
58+
this.seeds = seeds;
59+
this.soils = soils;
60+
this.drops = drops;
61+
this.growthTime = growthTime;
62+
this.modifier = modifier;
63+
}
64+
65+
@Override
66+
public void setRecipe(IRecipeLayoutBuilder builder, IFocusGroup focuses) {
67+
68+
// Seeds
69+
final IRecipeSlotBuilder seedSlot = builder.addSlot(RecipeIngredientRole.INPUT, 31, 11);
70+
this.seeds.forEach(seedSlot::addIngredients);
71+
seedSlot.addTooltipCallback(getSeedTooltip());
72+
73+
// Soils
74+
final IRecipeSlotBuilder soilSlot = builder.addSlot(RecipeIngredientRole.INPUT, 31, 29);
75+
this.soils.forEach(soilSlot::addIngredients);
76+
soilSlot.addTooltipCallback(getSoilTooltip());
77+
78+
// Drops
79+
80+
int dropCount = 0;
81+
82+
for (final HarvestEntry entry : drops) {
83+
84+
final IRecipeSlotBuilder dropSlot = builder.addSlot(RecipeIngredientRole.OUTPUT, 81 + 18 * (dropCount % 4), 1 + (18 * (dropCount / 4)));
85+
dropSlot.addItemStack(entry.getItem());
86+
dropSlot.addTooltipCallback(getDropTooltip(entry));
87+
88+
dropCount++;
89+
}
90+
}
91+
92+
private IRecipeSlotTooltipCallback getSeedTooltip() {
93+
94+
return (view, tooltip) -> {
95+
96+
tooltip.add(Component.translatable("tooltip.botanypots.grow_time", ticksToTime(this.growthTime)).withStyle(ChatFormatting.GRAY));
97+
};
98+
}
99+
100+
private IRecipeSlotTooltipCallback getSoilTooltip() {
101+
102+
return (view, tooltip) -> {
103+
104+
tooltip.add(Component.translatable("tooltip.botanypots.modifier", FORMAT.format(this.modifier)).withStyle(ChatFormatting.GRAY));
105+
};
106+
}
107+
108+
private IRecipeSlotTooltipCallback getDropTooltip(HarvestEntry drops) {
109+
110+
return (view, tooltip) -> {
111+
112+
tooltip.add(Component.translatable("tooltip.botanypots.chance", FORMAT.format(drops.getChance() * 100f)).withStyle(ChatFormatting.GRAY));
113+
114+
final int rollMin = drops.getMinRolls();
115+
final int rollMax = drops.getMaxRolls();
116+
117+
if (rollMin == rollMax) {
118+
119+
tooltip.add(Component.translatable("tooltip.botanypots.rolls", rollMin).withStyle(ChatFormatting.GRAY));
120+
}
121+
122+
else {
123+
124+
tooltip.add(Component.translatable("tooltip.botanypots.rollrange", rollMin, rollMax).withStyle(ChatFormatting.GRAY));
125+
}
126+
};
127+
}
128+
129+
@Override
130+
public void draw(IRecipeSlotsView view, PoseStack stack, double mouseX, double mouseY, IGuiHelper guiHelper) {
131+
132+
final IDrawableStatic slot = guiHelper.getSlotDrawable();
133+
134+
slot.draw(stack, 30, 10); // Seed
135+
slot.draw(stack, 30, 28); // Soil
136+
137+
// Drops
138+
for (int nextSlotId = 0; nextSlotId < 12; nextSlotId++) {
139+
140+
slot.draw(stack, 80 + 18 * (nextSlotId % 4), 18 * (nextSlotId / 4));
141+
}
142+
}
143+
144+
private static String ticksToTime (int ticks) {
145+
146+
ticks = Math.abs(ticks);
147+
int i = ticks / 20;
148+
final int j = i / 60;
149+
i = i % 60;
150+
151+
return i < 10 ? j + ":0" + i : j + ":" + i;
152+
}
153+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package net.darkhax.botanypots.addons.jei.ui;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
5+
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
6+
import mezz.jei.api.helpers.IGuiHelper;
7+
import mezz.jei.api.recipe.IFocusGroup;
8+
9+
public abstract class CropDisplayInfo {
10+
11+
public abstract void setRecipe (IRecipeLayoutBuilder builder, IFocusGroup focuses);
12+
13+
public abstract void draw(IRecipeSlotsView view, PoseStack stack, double mouseX, double mouseY, IGuiHelper guiHelper);
14+
}

Common/src/main/java/net/darkhax/botanypots/data/recipes/crop/BasicCrop.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import net.minecraft.world.level.Level;
1515

1616
import javax.annotation.Nullable;
17+
import java.util.Collections;
1718
import java.util.List;
1819
import java.util.Random;
1920
import java.util.Set;
@@ -138,4 +139,32 @@ public RecipeSerializer<?> getSerializer() {
138139

139140
return BotanyPotHelper.CROP_SERIALIZER.get();
140141
}
142+
143+
public Ingredient getSeed() {
144+
return seed;
145+
}
146+
147+
public Set<String> getSoilCategories() {
148+
149+
return Collections.unmodifiableSet(soilCategories);
150+
}
151+
152+
public int getGrowthTicks() {
153+
154+
return growthTicks;
155+
}
156+
157+
public List<HarvestEntry> getResults() {
158+
159+
return Collections.unmodifiableList(results);
160+
}
161+
162+
public List<DisplayState> getDisplayStates() {
163+
164+
return Collections.unmodifiableList(displayStates);
165+
}
166+
167+
public int getLightLevel() {
168+
return lightLevel;
169+
}
141170
}

Common/src/main/java/net/darkhax/botanypots/data/recipes/soil/BasicSoil.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,25 @@ public RecipeSerializer<?> getSerializer() {
110110

111111
return BotanyPotHelper.SOIL_SERIALIZER.get();
112112
}
113+
114+
115+
public Ingredient getIngredient() {
116+
return ingredient;
117+
}
118+
119+
public DisplayState getDisplayState() {
120+
return displayState;
121+
}
122+
123+
public float getGrowthModifier() {
124+
return growthModifier;
125+
}
126+
127+
public Set<String> getCategories() {
128+
return categories;
129+
}
130+
131+
public int getLightLevel() {
132+
return lightLevel;
133+
}
113134
}

0 commit comments

Comments
 (0)