Skip to content

Commit ce7c048

Browse files
committed
Make it easier to create IClickableIngredient
1 parent 5d1ca56 commit ce7c048

File tree

20 files changed

+344
-102
lines changed

20 files changed

+344
-102
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package mezz.jei.common.input;
2+
3+
import mezz.jei.api.gui.builder.IClickableIngredientFactory;
4+
import mezz.jei.api.ingredients.IIngredientType;
5+
import mezz.jei.api.ingredients.ITypedIngredient;
6+
import mezz.jei.api.runtime.IClickableIngredient;
7+
import mezz.jei.api.runtime.IIngredientManager;
8+
import mezz.jei.common.util.ImmutableRect2i;
9+
import net.minecraft.client.renderer.Rect2i;
10+
11+
import java.util.Optional;
12+
13+
public class ClickableIngredientFactory implements IClickableIngredientFactory {
14+
private final IIngredientManager ingredientManager;
15+
16+
public ClickableIngredientFactory(IIngredientManager ingredientManager) {
17+
this.ingredientManager = ingredientManager;
18+
}
19+
20+
@Override
21+
public <T> IBuilder<T> createBuilder(ITypedIngredient<T> value) {
22+
return new WithIngredient<>(value);
23+
}
24+
25+
@Override
26+
public <T> IBuilder<T> createBuilder(IIngredientType<T> ingredientType, T ingredient) {
27+
return ingredientManager.createTypedIngredient(ingredientType, ingredient, false)
28+
.<IBuilder<T>>map(WithIngredient::new)
29+
.orElse(WithoutIngredient.getInstance());
30+
}
31+
32+
private static class WithIngredient<T> implements IBuilder<T> {
33+
private final ITypedIngredient<T> ingredient;
34+
35+
private WithIngredient(ITypedIngredient<T> ingredient) {
36+
this.ingredient = ingredient;
37+
}
38+
39+
@Override
40+
public Optional<IClickableIngredient<T>> buildWithArea(int x, int y, int width, int height) {
41+
ImmutableRect2i area = new ImmutableRect2i(x, y, width, height);
42+
ClickableIngredient<T> result = new ClickableIngredient<>(ingredient, area);
43+
return Optional.of(result);
44+
}
45+
46+
@Override
47+
public Optional<IClickableIngredient<T>> buildWithArea(Rect2i area) {
48+
ImmutableRect2i immutableArea = new ImmutableRect2i(area);
49+
ClickableIngredient<T> result = new ClickableIngredient<>(ingredient, immutableArea);
50+
return Optional.of(result);
51+
}
52+
}
53+
54+
private static class WithoutIngredient<T> implements IBuilder<T> {
55+
public static final WithoutIngredient<?> INSTANCE = new WithoutIngredient<>();
56+
57+
public static <T> IBuilder<T> getInstance() {
58+
@SuppressWarnings("unchecked")
59+
IBuilder<T> cast = (IBuilder<T>) INSTANCE;
60+
return cast;
61+
}
62+
63+
private WithoutIngredient() {}
64+
65+
@Override
66+
public Optional<IClickableIngredient<T>> buildWithArea(int x, int y, int width, int height) {
67+
return Optional.empty();
68+
}
69+
70+
@Override
71+
public Optional<IClickableIngredient<T>> buildWithArea(Rect2i area) {
72+
return Optional.empty();
73+
}
74+
}
75+
}

Common/src/main/java/mezz/jei/common/transfer/RecipeTransferUtil.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import it.unimi.dsi.fastutil.Hash;
44
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
55
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
6-
import mezz.jei.api.constants.VanillaTypes;
76
import mezz.jei.api.gui.IRecipeLayoutDrawable;
87
import mezz.jei.api.gui.ingredient.IRecipeSlotView;
98
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
@@ -296,7 +295,7 @@ private static Set<Object> calculateUids(IRecipeSlotView recipeSlotView, IStackH
296295
if (typedIngredient == null) {
297296
continue;
298297
}
299-
ITypedIngredient<ItemStack> typedItemStack = typedIngredient.cast(VanillaTypes.ITEM_STACK);
298+
ITypedIngredient<ItemStack> typedItemStack = typedIngredient.castToItemStackType();
300299
if (typedItemStack != null) {
301300
Object uid = stackhelper.getUidForStack(typedItemStack, UidContext.Ingredient);
302301
uids.add(uid);

Common/src/main/java/mezz/jei/common/util/StackHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public String getUniqueIdentifierForStack(ItemStack stack, UidContext context) {
7373
}
7474

7575
public boolean hasSubtypes(ItemStack stack) {
76-
return subtypeManager.hasSubtypes(VanillaTypes.ITEM_STACK, stack);
76+
return subtypeManager.hasSubtypes(stack);
7777
}
7878

7979
public static String getRegistryNameForStack(ItemStack stack) {
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package mezz.jei.api.gui.builder;
2+
3+
import mezz.jei.api.constants.VanillaTypes;
4+
import mezz.jei.api.gui.handlers.IGuiContainerHandler;
5+
import mezz.jei.api.ingredients.IIngredientType;
6+
import mezz.jei.api.ingredients.ITypedIngredient;
7+
import mezz.jei.api.runtime.IClickableIngredient;
8+
import mezz.jei.api.runtime.IIngredientManager;
9+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
10+
import net.minecraft.client.renderer.Rect2i;
11+
import net.minecraft.world.item.ItemStack;
12+
13+
import java.util.Optional;
14+
15+
/**
16+
* Helper factory for creating {@link IClickableIngredient}.
17+
*
18+
* Passed to mods in methods that need to create clickable ingredients, like
19+
* {@link IGuiContainerHandler#getClickableIngredientUnderMouse(IClickableIngredientFactory, AbstractContainerScreen, double, double)}
20+
*
21+
* An instance is also available from {@link IIngredientManager#getClickableIngredientFactory()}.
22+
*
23+
* @since 19.23.0
24+
*/
25+
public interface IClickableIngredientFactory {
26+
/**
27+
* Create a clickable ingredient builder with the given ItemStack.
28+
*
29+
* @since 19.23.0
30+
*/
31+
default IBuilder<ItemStack> createBuilder(ItemStack itemStack) {
32+
return createBuilder(VanillaTypes.ITEM_STACK, itemStack);
33+
}
34+
35+
/**
36+
* Create a clickable ingredient builder with the given typed ingredient.
37+
*
38+
* @since 19.23.0
39+
*/
40+
<T> IBuilder<T> createBuilder(ITypedIngredient<T> value);
41+
42+
/**
43+
* Create a clickable ingredient builder with the given typed ingredient.
44+
*
45+
* @since 19.23.0
46+
*/
47+
<T> IBuilder<T> createBuilder(IIngredientType<T> ingredientType, T ingredient);
48+
49+
/**
50+
* An intermediate builder for clickable ingredients.
51+
* It has an ingredient and needs an area in order to build the clickable ingredient.
52+
*
53+
* @since 19.23.0
54+
*/
55+
interface IBuilder<T> {
56+
/**
57+
* Create a clickable ingredient with the given area
58+
*
59+
* @since 19.23.0
60+
*/
61+
Optional<IClickableIngredient<T>> buildWithArea(int x, int y, int width, int height);
62+
63+
/**
64+
* Create a clickable ingredient with the given area
65+
*
66+
* @since 19.23.0
67+
*/
68+
Optional<IClickableIngredient<T>> buildWithArea(Rect2i area);
69+
}
70+
}

CommonApi/src/main/java/mezz/jei/api/gui/handlers/IGlobalGuiHandler.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package mezz.jei.api.gui.handlers;
22

3+
import mezz.jei.api.gui.builder.IClickableIngredientFactory;
34
import mezz.jei.api.registration.IGuiHandlerRegistration;
45
import mezz.jei.api.registration.IModIngredientRegistration;
56
import mezz.jei.api.runtime.IClickableIngredient;
@@ -30,6 +31,24 @@ default Collection<Rect2i> getGuiExtraAreas() {
3031
return Collections.emptyList();
3132
}
3233

34+
/**
35+
* Return a clickable ingredient under the mouse that JEI could not normally detect, used for JEI recipe lookups.
36+
* <p>
37+
* This is useful for guis that don't have normal slots (which is how JEI normally detects items under the mouse).
38+
* <p>
39+
* This can also be used to let JEI look up liquids in tanks directly, by returning a FluidStack.
40+
* Works with any ingredient type that has been registered with {@link IModIngredientRegistration}.
41+
*
42+
* @param builder a builder to help with the creation of clickable ingredients.
43+
* @param mouseX the current X position of the mouse in screen coordinates.
44+
* @param mouseY the current Y position of the mouse in screen coordinates.
45+
*
46+
* @since 19.23.0
47+
*/
48+
default Optional<IClickableIngredient<?>> getClickableIngredientUnderMouse(IClickableIngredientFactory builder, double mouseX, double mouseY) {
49+
return getClickableIngredientUnderMouse(mouseX, mouseY);
50+
}
51+
3352
/**
3453
* Return a clickable ingredient under the mouse that JEI could not normally detect, used for JEI recipe lookups.
3554
* <p>
@@ -42,7 +61,10 @@ default Collection<Rect2i> getGuiExtraAreas() {
4261
* @param mouseY the current Y position of the mouse in screen coordinates.
4362
*
4463
* @since 11.5.0
64+
* @deprecated use {@link #getClickableIngredientUnderMouse(IClickableIngredientFactory, double, double)}
4565
*/
66+
@SuppressWarnings("DeprecatedIsStillUsed")
67+
@Deprecated(forRemoval = true, since = "19.23.0")
4668
default Optional<IClickableIngredient<?>> getClickableIngredientUnderMouse(double mouseX, double mouseY) {
4769
return Optional.empty();
4870
}

CommonApi/src/main/java/mezz/jei/api/gui/handlers/IGuiContainerHandler.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package mezz.jei.api.gui.handlers;
22

3+
import mezz.jei.api.gui.builder.IClickableIngredientFactory;
34
import mezz.jei.api.registration.IGuiHandlerRegistration;
45
import mezz.jei.api.registration.IModIngredientRegistration;
56
import mezz.jei.api.runtime.IClickableIngredient;
@@ -26,6 +27,28 @@ default List<Rect2i> getGuiExtraAreas(T containerScreen) {
2627
return Collections.emptyList();
2728
}
2829

30+
/**
31+
* Return a clickable ingredient under the mouse that JEI could not normally detect, used for JEI recipe lookups.
32+
*
33+
* This is useful for guis that don't have normal slots (which is how JEI normally detects items under the mouse).
34+
*
35+
* This can also be used to let JEI look up liquids in tanks directly, by returning a FluidStack.
36+
* Works with any ingredient type that has been registered with {@link IModIngredientRegistration}.
37+
*
38+
* @param mouseX the current X position of the mouse in screen coordinates.
39+
* @param mouseY the current Y position of the mouse in screen coordinates.
40+
*
41+
* @since 19.23.0
42+
*/
43+
default Optional<? extends IClickableIngredient<?>> getClickableIngredientUnderMouse(
44+
IClickableIngredientFactory builder,
45+
T containerScreen,
46+
double mouseX,
47+
double mouseY
48+
) {
49+
return getClickableIngredientUnderMouse(containerScreen, mouseX, mouseY);
50+
}
51+
2952
/**
3053
* Return a clickable ingredient under the mouse that JEI could not normally detect, used for JEI recipe lookups.
3154
*
@@ -38,7 +61,10 @@ default List<Rect2i> getGuiExtraAreas(T containerScreen) {
3861
* @param mouseY the current Y position of the mouse in screen coordinates.
3962
*
4063
* @since 11.5.0
64+
* @deprecated use {@link #getClickableIngredientUnderMouse(IClickableIngredientFactory, AbstractContainerScreen, double, double)}
4165
*/
66+
@SuppressWarnings("DeprecatedIsStillUsed")
67+
@Deprecated(forRemoval = true, since = "19.23.0")
4268
default Optional<IClickableIngredient<?>> getClickableIngredientUnderMouse(T containerScreen, double mouseX, double mouseY) {
4369
return Optional.empty();
4470
}

CommonApi/src/main/java/mezz/jei/api/ingredients/ITypedIngredient.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ default <V> ITypedIngredient<V> cast(IIngredientType<V> ingredientType) {
7070
return null;
7171
}
7272

73+
/**
74+
* @return this instance, only if it contains an ItemStack.
75+
* This is useful when handling a wildcard generic instance of `ITypedIngredient<?>`.
76+
*
77+
* @since 19.23.0
78+
*/
79+
@Nullable
80+
default ITypedIngredient<ItemStack> castToItemStackType() {
81+
return cast(VanillaTypes.ITEM_STACK);
82+
}
83+
7384
/**
7485
* @return the ingredient's base ingredient. (For example, an ItemStack's base ingredient is the Item)
7586
*

CommonApi/src/main/java/mezz/jei/api/ingredients/subtypes/ISubtypeManager.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ default String getSubtypeInfo(ItemStack ingredient, UidContext context) {
6868
@Deprecated(since = "19.9.0", forRemoval = true)
6969
<T> String getSubtypeInfo(IIngredientTypeWithSubtypes<?, T> ingredientType, T ingredient, UidContext context);
7070

71+
/**
72+
* Return true if the given ItemStack can have subtypes.
73+
* For example in the vanilla game an enchanted book may have subtypes, but an apple does not.
74+
*
75+
* @see ISubtypeRegistration#registerSubtypeInterpreter
76+
* @see ISubtypeManager#getSubtypeData
77+
*
78+
* @since 19.23.0
79+
*/
80+
default boolean hasSubtypes(ItemStack ingredient) {
81+
return hasSubtypes(VanillaTypes.ITEM_STACK, ingredient);
82+
}
83+
7184
/**
7285
* Return true if the given ingredient can have subtypes.
7386
* For example in the vanilla game an enchanted book may have subtypes, but an apple does not.

CommonApi/src/main/java/mezz/jei/api/registration/IIngredientAliasRegistration.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package mezz.jei.api.registration;
22

3+
import mezz.jei.api.constants.VanillaTypes;
34
import mezz.jei.api.ingredients.IIngredientType;
45
import mezz.jei.api.ingredients.ITypedIngredient;
6+
import net.minecraft.world.item.ItemStack;
57

68
import java.util.Collection;
79

@@ -12,6 +14,16 @@
1214
* @since 19.10.0
1315
*/
1416
public interface IIngredientAliasRegistration {
17+
/**
18+
* Register a search alias for an ingredient.
19+
* An alias may be a translation key.
20+
*
21+
* @since 19.23.0
22+
*/
23+
default void addAlias(ItemStack itemStack, String alias) {
24+
addAlias(VanillaTypes.ITEM_STACK, itemStack, alias);
25+
}
26+
1527
/**
1628
* Register a search alias for an ingredient.
1729
* An alias may be a translation key.

CommonApi/src/main/java/mezz/jei/api/runtime/IClickableIngredient.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package mezz.jei.api.runtime;
22

3+
import mezz.jei.api.gui.builder.IClickableIngredientFactory;
34
import mezz.jei.api.ingredients.IIngredientType;
45
import mezz.jei.api.ingredients.ITypedIngredient;
56
import net.minecraft.client.renderer.Rect2i;
@@ -10,7 +11,8 @@
1011
* This can be an ingredient drawn in a GUI container slot, a fluid tank,
1112
* or anything else that holds ingredients.
1213
*
13-
* Create one with {@link IIngredientManager#createClickableIngredient}.
14+
* Create one with {@link IIngredientManager#getClickableIngredientFactory()}
15+
* @see IClickableIngredientFactory
1416
*
1517
* @since 11.5.0
1618
*/
@@ -19,21 +21,25 @@ public interface IClickableIngredient<T> {
1921
* Get the typed ingredient that can be looked up by JEI for recipes.
2022
*
2123
* @since 11.5.0
22-
* @deprecated use {@link #getIngredient()} and {@link #getIngredientType()} instead.
2324
*/
24-
@Deprecated(since = "19.12.0", forRemoval = true)
2525
ITypedIngredient<T> getTypedIngredient();
2626

2727
/**
2828
* @since 19.12.0
29+
*
30+
* @deprecated use {@link #getTypedIngredient()}
2931
*/
32+
@Deprecated(since = "19.23.0", forRemoval = true)
3033
default IIngredientType<T> getIngredientType() {
3134
return getTypedIngredient().getType();
3235
}
3336

3437
/**
3538
* @since 19.12.0
39+
*
40+
* @deprecated use {@link #getTypedIngredient()}
3641
*/
42+
@Deprecated(since = "19.23.0", forRemoval = true)
3743
default T getIngredient() {
3844
ITypedIngredient<T> typedIngredient = getTypedIngredient();
3945
return typedIngredient.getIngredient();

0 commit comments

Comments
 (0)