1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-18 15:37:38 +00:00

Re-enable JEI integration

This commit is contained in:
Jonathan Coates
2025-07-12 21:41:50 +01:00
parent 4868c4aa32
commit 01de6110c6
4 changed files with 80 additions and 58 deletions

View File

@@ -9,7 +9,7 @@
# Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml # Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml
fabric-api = "0.128.0+1.21.7" fabric-api = "0.128.0+1.21.7"
fabric-loader = "0.16.14" fabric-loader = "0.16.14"
neoForge = "21.7.1-beta" neoForge = "21.7.19-beta"
neoMergeTool = "2.0.0" neoMergeTool = "2.0.0"
mixin = "0.8.5" mixin = "0.8.5"
parchment = "2025.06.29" parchment = "2025.06.29"
@@ -40,7 +40,7 @@ emi = "1.1.7+1.21"
fabricPermissions = "0.3.3" fabricPermissions = "0.3.3"
iris-fabric = "1.9.1+1.21.7-fabric" iris-fabric = "1.9.1+1.21.7-fabric"
iris-forge = "1.9.1+1.21.7-neoforge" iris-forge = "1.9.1+1.21.7-neoforge"
jei = "19.8.2.99" jei = "23.1.0.4"
modmenu = "13.0.2" modmenu = "13.0.2"
moreRed = "6.0.0.3" moreRed = "6.0.0.3"
rei = "18.0.800" rei = "18.0.800"
@@ -69,7 +69,7 @@ ideaExt = "1.1.7"
illuaminate = "0.1.0-83-g1131f68" illuaminate = "0.1.0-83-g1131f68"
lwjgl = "3.3.3" lwjgl = "3.3.3"
minotaur = "2.8.7" minotaur = "2.8.7"
modDevGradle = "2.0.95" modDevGradle = "2.0.99"
nullAway = "0.12.7" nullAway = "0.12.7"
shadow = "8.3.1" shadow = "8.3.1"
spotless = "7.0.2" spotless = "7.0.2"
@@ -113,9 +113,9 @@ fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-l
fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" } fabricPermissions = { module = "me.lucko:fabric-permissions-api", version.ref = "fabricPermissions" }
iris-fabric = { module = "maven.modrinth:iris", version.ref = "iris-fabric" } iris-fabric = { module = "maven.modrinth:iris", version.ref = "iris-fabric" }
iris-forge = { module = "maven.modrinth:iris", version.ref = "iris-forge" } iris-forge = { module = "maven.modrinth:iris", version.ref = "iris-forge" }
jei-api = { module = "mezz.jei:jei-1.21-common-api", version.ref = "jei" } jei-api = { module = "mezz.jei:jei-1.21.7-common-api", version.ref = "jei" }
jei-fabric = { module = "mezz.jei:jei-1.21-fabric", version.ref = "jei" } jei-fabric = { module = "mezz.jei:jei-1.21.7-fabric", version.ref = "jei" }
jei-forge = { module = "mezz.jei:jei-1.21-neoforge", version.ref = "jei" } jei-forge = { module = "mezz.jei:jei-1.21.7-neoforge", version.ref = "jei" }
mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" } mixin = { module = "org.spongepowered:mixin", version.ref = "mixin" }
mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" } mixinExtra = { module = "io.github.llamalad7:mixinextras-common", version.ref = "mixinExtra" }
modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" }
@@ -186,7 +186,7 @@ kotlin = ["kotlin-stdlib", "kotlin-coroutines"]
# Minecraft # Minecraft
externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"] externalMods-common = ["iris-forge", "jei-api", "nightConfig-core", "nightConfig-toml"]
externalMods-forge-compile = ["moreRed", "iris-forge", "jei-api"] externalMods-forge-compile = ["moreRed", "iris-forge", "jei-api"]
externalMods-forge-runtime = [] externalMods-forge-runtime = ["jei-forge"]
externalMods-fabric-compile = ["fabricPermissions", "iris-fabric", "jei-api", "rei-api", "rei-builtin"] externalMods-fabric-compile = ["fabricPermissions", "iris-fabric", "jei-api", "rei-api", "rei-builtin"]
externalMods-fabric-runtime = [] externalMods-fabric-runtime = []

View File

@@ -14,7 +14,6 @@ plugins {
sourceSets.client { sourceSets.client {
java { java {
exclude("dan200/computercraft/client/integration/emi") exclude("dan200/computercraft/client/integration/emi")
exclude("dan200/computercraft/client/integration/jei")
} }
} }

View File

@@ -8,13 +8,14 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.ModRegistry; import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.integration.RecipeModHelpers; import dan200.computercraft.shared.integration.RecipeModHelpers;
import dan200.computercraft.shared.pocket.core.PocketSide;
import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.pocket.items.PocketComputerItem;
import dan200.computercraft.shared.turtle.items.TurtleItem; import dan200.computercraft.shared.turtle.items.TurtleItem;
import mezz.jei.api.IModPlugin; import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin; import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.RecipeTypes; import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter; import mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter;
import mezz.jei.api.registration.IAdvancedRegistration; import mezz.jei.api.registration.IAdvancedRegistration;
import mezz.jei.api.registration.ISubtypeRegistration; import mezz.jei.api.registration.ISubtypeRegistration;
import mezz.jei.api.runtime.IJeiRuntime; import mezz.jei.api.runtime.IJeiRuntime;
@@ -46,7 +47,7 @@ public class JEIComputerCraft implements IModPlugin {
@Override @Override
public void registerAdvanced(IAdvancedRegistration registry) { public void registerAdvanced(IAdvancedRegistration registry) {
registry.addRecipeManagerPlugin(new RecipeResolver(getRegistryAccess())); registry.addSimpleRecipeManagerPlugin(RecipeTypes.CRAFTING, new RecipeResolver(getRegistryAccess()));
} }
@Override @Override
@@ -62,7 +63,7 @@ public class JEIComputerCraft implements IModPlugin {
// Hide all upgrade recipes // Hide all upgrade recipes
var category = registry.createRecipeLookup(RecipeTypes.CRAFTING); var category = registry.createRecipeLookup(RecipeTypes.CRAFTING);
category.get().forEach(wrapper -> { category.get().forEach(wrapper -> {
if (RecipeModHelpers.shouldRemoveRecipe(wrapper.id())) { if (RecipeModHelpers.shouldRemoveRecipe(wrapper.id().location())) {
registry.hideRecipes(RecipeTypes.CRAFTING, List.of(wrapper)); registry.hideRecipes(RecipeTypes.CRAFTING, List.of(wrapper));
} }
}); });
@@ -71,7 +72,7 @@ public class JEIComputerCraft implements IModPlugin {
/** /**
* Distinguishes turtles by upgrades and family. * Distinguishes turtles by upgrades and family.
*/ */
private static final IIngredientSubtypeInterpreter<ItemStack> turtleSubtype = (stack, ctx) -> { private static final ISubtypeInterpreter<ItemStack> turtleSubtype = (stack, ctx) -> {
var name = new StringBuilder("turtle:"); var name = new StringBuilder("turtle:");
// Add left and right upgrades to the identifier // Add left and right upgrades to the identifier
@@ -87,12 +88,15 @@ public class JEIComputerCraft implements IModPlugin {
/** /**
* Distinguishes pocket computers by upgrade and family. * Distinguishes pocket computers by upgrade and family.
*/ */
private static final IIngredientSubtypeInterpreter<ItemStack> pocketSubtype = (stack, ctx) -> { private static final ISubtypeInterpreter<ItemStack> pocketSubtype = (stack, ctx) -> {
var name = new StringBuilder("pocket:"); var name = new StringBuilder("pocket:");
// Add the upgrade to the identifier // Add the upgrade to the identifier
var upgrade = PocketComputerItem.getUpgradeWithData(stack); var back = PocketComputerItem.getUpgradeWithData(stack, PocketSide.BACK);
if (upgrade != null) name.append(upgrade.holder().key().location()); var bottom = PocketComputerItem.getUpgradeWithData(stack, PocketSide.BOTTOM);
if (back != null) name.append(back.holder().key().location());
if (back != null && bottom != null) name.append('|');
if (bottom != null) name.append(bottom.holder().key().location());
return name.toString(); return name.toString();
}; };
@@ -100,7 +104,7 @@ public class JEIComputerCraft implements IModPlugin {
/** /**
* Distinguishes disks by colour. * Distinguishes disks by colour.
*/ */
private static final IIngredientSubtypeInterpreter<ItemStack> diskSubtype = (stack, ctx) -> Integer.toString(DyedItemColor.getOrDefault(stack, -1)); private static final ISubtypeInterpreter<ItemStack> diskSubtype = (stack, ctx) -> Integer.toString(DyedItemColor.getOrDefault(stack, -1));
private static RegistryAccess getRegistryAccess() { private static RegistryAccess getRegistryAccess() {
return Minecraft.getInstance().level.registryAccess(); return Minecraft.getInstance().level.registryAccess();

View File

@@ -8,71 +8,90 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.shared.integration.UpgradeRecipeGenerator; import dan200.computercraft.shared.integration.UpgradeRecipeGenerator;
import dan200.computercraft.shared.pocket.items.PocketComputerItem; import dan200.computercraft.shared.pocket.items.PocketComputerItem;
import dan200.computercraft.shared.turtle.items.TurtleItem; import dan200.computercraft.shared.turtle.items.TurtleItem;
import mezz.jei.api.constants.RecipeTypes; import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.recipe.IFocus; import mezz.jei.api.recipe.advanced.ISimpleRecipeManagerPlugin;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.*;
import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.display.RecipeDisplay;
import net.minecraft.world.level.Level;
import java.util.List; import java.util.List;
class RecipeResolver implements IRecipeManagerPlugin { class RecipeResolver implements ISimpleRecipeManagerPlugin<RecipeHolder<CraftingRecipe>> {
private final UpgradeRecipeGenerator<RecipeHolder<CraftingRecipe>> resolver;
/** /**
* We need to generate unique ids for each recipe, as JEI will attempt to deduplicate them otherwise. * We need to generate unique ids for each recipe, as JEI will attempt to deduplicate them otherwise.
*/ */
private int nextId = 0; private int nextId = 0;
private final UpgradeRecipeGenerator<RecipeHolder<CraftingRecipe>> resolver;
RecipeResolver(HolderLookup.Provider registries) { RecipeResolver(HolderLookup.Provider registries) {
resolver = new UpgradeRecipeGenerator<>( resolver = new UpgradeRecipeGenerator<>(x -> new RecipeHolder<>(
x -> new RecipeHolder<>(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "upgrade_" + nextId++), x), ResourceKey.create(Registries.RECIPE, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "upgrade_" + nextId++)),
registries new CraftingWrapper(x)
); ), registries);
} }
@Override @Override
public <V> List<RecipeType<?>> getRecipeTypes(IFocus<V> focus) { public boolean isHandledInput(ITypedIngredient<?> input) {
var value = focus.getTypedValue().getIngredient(); return input.getIngredient() instanceof ItemStack stack
if (!(value instanceof ItemStack stack)) return List.of(); && (stack.getItem() instanceof TurtleItem || stack.getItem() instanceof PocketComputerItem || resolver.isUpgrade(stack));
return switch (focus.getRole()) {
case INPUT ->
stack.getItem() instanceof TurtleItem || stack.getItem() instanceof PocketComputerItem || resolver.isUpgrade(stack)
? List.of(RecipeTypes.CRAFTING)
: List.of();
case OUTPUT -> stack.getItem() instanceof TurtleItem || stack.getItem() instanceof PocketComputerItem
? List.of(RecipeTypes.CRAFTING)
: List.of();
default -> List.of();
};
} }
@Override @Override
public <T, V> List<T> getRecipes(IRecipeCategory<T> recipeCategory, IFocus<V> focus) { public boolean isHandledOutput(ITypedIngredient<?> output) {
if (!(focus.getTypedValue().getIngredient() instanceof ItemStack stack) || recipeCategory.getRecipeType() != RecipeTypes.CRAFTING) { return output.getIngredient() instanceof ItemStack stack
return List.of(); && (stack.getItem() instanceof TurtleItem || stack.getItem() instanceof PocketComputerItem);
}
return switch (focus.getRole()) {
case INPUT -> cast(RecipeTypes.CRAFTING, resolver.findRecipesWithInput(stack));
case OUTPUT -> cast(RecipeTypes.CRAFTING, resolver.findRecipesWithOutput(stack));
default -> List.of();
};
} }
@Override @Override
public <T> List<T> getRecipes(IRecipeCategory<T> recipeCategory) { public List<RecipeHolder<CraftingRecipe>> getRecipesForInput(ITypedIngredient<?> input) {
return input.getIngredient() instanceof ItemStack stack ? resolver.findRecipesWithInput(stack) : List.of();
}
@Override
public List<RecipeHolder<CraftingRecipe>> getRecipesForOutput(ITypedIngredient<?> output) {
return output.getIngredient() instanceof ItemStack stack ? resolver.findRecipesWithOutput(stack) : List.of();
}
@Override
public List<RecipeHolder<CraftingRecipe>> getAllRecipes() {
return List.of(); return List.of();
} }
@SuppressWarnings({ "unchecked", "rawtypes", "UnusedVariable" }) private record CraftingWrapper(RecipeDisplay recipes) implements CraftingRecipe {
private static <T, U> List<T> cast(RecipeType<U> ignoredType, List<U> from) { @Override
return (List) from; public RecipeSerializer<? extends CraftingRecipe> getSerializer() {
throw new IllegalStateException("Should not serialise CraftingWrapper");
}
@Override
public CraftingBookCategory category() {
return CraftingBookCategory.MISC;
}
@Override
public boolean matches(CraftingInput input, Level level) {
return false;
}
@Override
public ItemStack assemble(CraftingInput input, HolderLookup.Provider registries) {
return ItemStack.EMPTY;
}
@Override
public PlacementInfo placementInfo() {
return PlacementInfo.NOT_PLACEABLE;
}
@Override
public List<RecipeDisplay> display() {
return List.of(recipes);
}
} }
} }