Added JEI integration (way too painful)

This commit is contained in:
IM23a-cernik
2025-05-30 01:24:00 +02:00
parent b8a66c2875
commit ff91d3a371
6 changed files with 181 additions and 8 deletions
+15
View File
@@ -19,6 +19,16 @@ group = mod_group_id
repositories { repositories {
mavenLocal() mavenLocal()
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"
}
} }
base { base {
@@ -123,6 +133,11 @@ dependencies {
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it // We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}" // localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}"
// compile against the JEI API but do not include it at runtime
compileOnly("mezz.jei:jei-${minecraft_version}-neoforge-api:${jei_version}")
// at runtime, use the full JEI jar for NeoForge
runtimeOnly("mezz.jei:jei-${minecraft_version}-neoforge:${jei_version}")
// Example mod dependency using a mod jar from ./libs with a flat dir repository // Example mod dependency using a mod jar from ./libs with a flat dir repository
// This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
// The group id is ignored when searching -- in this case, it is "blank" // The group id is ignored when searching -- in this case, it is "blank"
+3 -1
View File
@@ -24,6 +24,8 @@ neo_version_range=[21.1.148,)
# The loader version range can only use the major version of FML as bounds # The loader version range can only use the major version of FML as bounds
loader_version_range=[1,) loader_version_range=[1,)
jei_version=19.21.1.305
## Mod Properties ## Mod Properties
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
@@ -34,7 +36,7 @@ mod_name=Stalinium
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT mod_license=MIT
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
mod_version=0.0.18 mod_version=0.0.19
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html
@@ -171,8 +171,8 @@ public class StaliniumPressBlockEntity extends BlockEntity implements MenuProvid
private Optional<RecipeHolder<StaliniumPressRecipe>> getCurrentRecipe() { private Optional<RecipeHolder<StaliniumPressRecipe>> getCurrentRecipe() {
return this.level.getRecipeManager() return this.level.getRecipeManager()
.getRecipeFor(ModRecipes.STALINIUM_PRESS_TYPE.get(), new StaliniumPressRecipeInput( .getRecipeFor(ModRecipes.STALINIUM_PRESS_TYPE.get(), new StaliniumPressRecipeInput(
itemHandler.getStackInSlot(INPUT_SLOT),
itemHandler.getStackInSlot(REDSTONE_FUEL_SLOT), itemHandler.getStackInSlot(REDSTONE_FUEL_SLOT),
itemHandler.getStackInSlot(INPUT_SLOT),
itemHandler.getStackInSlot(LAVA_FUEL_SLOT) itemHandler.getStackInSlot(LAVA_FUEL_SLOT)
), level); ), level);
} }
@@ -0,0 +1,55 @@
package net.krituximon.stalinium.compat;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import net.krituximon.stalinium.Stalinium;
import net.krituximon.stalinium.block.ModBlocks;
import net.krituximon.stalinium.recipe.ModRecipes;
import net.krituximon.stalinium.recipe.StaliniumPressRecipe;
import net.krituximon.stalinium.screen.custom.StaliniumPressScreen;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager;
import java.util.List;
@JeiPlugin
public class JEIStaliniumPlugin implements IModPlugin {
@Override
public ResourceLocation getPluginUid() {
return ResourceLocation.fromNamespaceAndPath(Stalinium.MODID, "jei_plugin");
}
@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(new StaliniumPressRecipeCategory(
registration.getJeiHelpers().getGuiHelper()));
}
@Override
public void registerRecipes(IRecipeRegistration registration) {
RecipeManager recipeManager = Minecraft.getInstance().level.getRecipeManager();
List<StaliniumPressRecipe> staliniumPressRecipes = recipeManager
.getAllRecipesFor(ModRecipes.STALINIUM_PRESS_TYPE.get()).stream().map(RecipeHolder::value).toList();
registration.addRecipes(StaliniumPressRecipeCategory.STALINIUM_PRESS_RECIPE_RECIPE_TYPE, staliniumPressRecipes);
}
@Override
public void registerGuiHandlers(IGuiHandlerRegistration registration) {
registration.addRecipeClickArea(StaliniumPressScreen.class, 74, 30, 22, 20,
StaliniumPressRecipeCategory.STALINIUM_PRESS_RECIPE_RECIPE_TYPE);
}
@Override
public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
registration.addRecipeCatalyst(new ItemStack(ModBlocks.STALINIUM_PRESS.get().asItem()),
StaliniumPressRecipeCategory.STALINIUM_PRESS_RECIPE_RECIPE_TYPE);
}
}
@@ -0,0 +1,93 @@
package net.krituximon.stalinium.compat;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.krituximon.stalinium.Stalinium;
import net.krituximon.stalinium.block.ModBlocks;
import net.krituximon.stalinium.recipe.StaliniumPressRecipe;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
public class StaliniumPressRecipeCategory implements IRecipeCategory<StaliniumPressRecipe> {
public static final ResourceLocation UID = ResourceLocation.fromNamespaceAndPath(Stalinium.MODID, "stalinium_chamber");
public static final ResourceLocation TEXTURE =
ResourceLocation.fromNamespaceAndPath(Stalinium.MODID, "textures/gui/stalinium_press_gui.png");
public static final RecipeType<StaliniumPressRecipe> STALINIUM_PRESS_RECIPE_RECIPE_TYPE =
new RecipeType<>(UID, StaliniumPressRecipe.class);
private final IDrawable background;
private final IDrawable icon;
/* --------------------------------------------------------------------- */
/* GUI layout constants */
/* --------------------------------------------------------------------- */
private static final int[][] INPUT_SLOT_POSITIONS = {
{54, 34},
{54, 14},
{54, 54}
};
private static final int OUTPUT_X = 104;
private static final int OUTPUT_Y = 34;
public StaliniumPressRecipeCategory(IGuiHelper helper) {
this.background = helper.createDrawable(TEXTURE, 0, 0, 176, 85);
this.icon = helper.createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(ModBlocks.STALINIUM_PRESS));
}
@Override
public RecipeType<StaliniumPressRecipe> getRecipeType() {
return STALINIUM_PRESS_RECIPE_RECIPE_TYPE;
}
@Override
public Component getTitle() {
return Component.translatable("block.stalinium.stalinium_press");
}
@Override
public @Nullable IDrawable getIcon() {
return icon;
}
@Override
public IDrawable getBackground() {
return background;
}
@Override
public void setRecipe(IRecipeLayoutBuilder builder,
StaliniumPressRecipe recipe,
IFocusGroup focuses) {
// -------------------- INPUT SLOTS --------------------
var ingredients = recipe.getIngredients();
int slotCount = Math.min(ingredients.size(), INPUT_SLOT_POSITIONS.length);
for (int i = 0; i < slotCount; i++) {
int x = INPUT_SLOT_POSITIONS[i][0];
int y = INPUT_SLOT_POSITIONS[i][1];
builder.addSlot(RecipeIngredientRole.INPUT, x, y)
.addIngredients(ingredients.get(i));
}
// -------------------- OUTPUT SLOT --------------------
var output = recipe.getResultItem(
net.minecraft.client.Minecraft.getInstance()
.level
.registryAccess()); // <- real registry
builder.addSlot(RecipeIngredientRole.OUTPUT, OUTPUT_X, OUTPUT_Y)
.addItemStack(output);
}
}
@@ -36,6 +36,12 @@ public record StaliniumPressRecipe(NonNullList<Ingredient> ingredients,
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
/* Recipe implementation */ /* Recipe implementation */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@Override
public NonNullList<Ingredient> getIngredients() { // <-- add this
return ingredients;
}
@Override @Override
public boolean matches(StaliniumPressRecipeInput input, Level level) { public boolean matches(StaliniumPressRecipeInput input, Level level) {
if (level.isClientSide()) return false; if (level.isClientSide()) return false;
@@ -80,15 +86,17 @@ public record StaliniumPressRecipe(NonNullList<Ingredient> ingredients,
/* ---------- Codec used for JSON files ---------- */ /* ---------- Codec used for JSON files ---------- */
public static final MapCodec<StaliniumPressRecipe> CODEC = public static final MapCodec<StaliniumPressRecipe> CODEC =
RecordCodecBuilder.mapCodec(inst -> inst.group( RecordCodecBuilder.mapCodec(inst -> inst.group(
Ingredient.CODEC_NONEMPTY.fieldOf("nugget").forGetter(StaliniumPressRecipe::nugget), Ingredient.CODEC_NONEMPTY.fieldOf("nugget").forGetter(r -> r.nugget()),
Ingredient.CODEC_NONEMPTY.fieldOf("power").forGetter(StaliniumPressRecipe::power), Ingredient.CODEC_NONEMPTY.fieldOf("power").forGetter(r -> r.power()),
Ingredient.CODEC_NONEMPTY.fieldOf("fuel").forGetter(StaliniumPressRecipe::fuel), Ingredient.CODEC_NONEMPTY.fieldOf("fuel").forGetter(r -> r.fuel()),
ItemStack.CODEC.fieldOf("result").forGetter(StaliniumPressRecipe::output) ItemStack.CODEC.fieldOf("result").forGetter(StaliniumPressRecipe::output)
).apply(inst, (p, n, f, res) -> { ).apply(inst, (nugget, power, fuel, result) -> {
NonNullList<Ingredient> list = NonNullList.of(Ingredient.EMPTY, p, n, f); NonNullList<Ingredient> list = NonNullList.of(Ingredient.EMPTY,
return new StaliniumPressRecipe(list, res); power, nugget, fuel); // keep the slot order you want in JEI
return new StaliniumPressRecipe(list, result);
})); }));
/* ---------- Codec used for network sync ---------- */ /* ---------- Codec used for network sync ---------- */
private static final StreamCodec<RegistryFriendlyByteBuf, StaliniumPressRecipe> STREAM_CODEC = private static final StreamCodec<RegistryFriendlyByteBuf, StaliniumPressRecipe> STREAM_CODEC =
StreamCodec.composite( StreamCodec.composite(